6 #include "oic_malloc.h"
7 #include "oic_string.h"
8 #include "cacommonutil.h"
10 #include "ocpayload.h"
11 #include "payload_logging.h"
12 #include "doxmresource.h"
13 #include "pmutility.h"
14 #include "secureresourceprovider.h"
16 // headers required for mbed TLS
17 #include "mbedtls/platform.h"
18 #include "mbedtls/ssl.h"
19 #include "mbedtls/entropy.h"
20 #include "mbedtls/ctr_drbg.h"
21 #include "mbedtls/pkcs12.h"
22 #include "mbedtls/ssl_internal.h"
23 #include "mbedtls/x509_csr.h"
26 #include "mbedtls/debug.h"
27 #include "mbedtls/version.h"
33 #define TAG "CLOUD-CSR"
35 //TODO: is it required in CSR response?
36 static OCByteString privateKey = {0, 0};
38 #define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
40 #define MAX_STRING_LEN 254
44 * @brief Seed for initialization RNG
47 #define SEED "IOTIVITY_RND"
59 * Make CSR subject like:
60 * Subject: C=KR, O=Samsung, OU=OCF Device, CN=uuid:1234567890
61 * @param[in] subj the subject
63 static void CSRMakeSubject(char *subject, const char *countryCode, const char *organisation,
64 const char *organizationalUnitName, const char *deviceId)
66 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
70 OIC_LOG_V(ERROR, TAG, "%s: The device id is NULL",__func__);
73 snprintf(subject, MAX_STRING_LEN, "C=%s, O=%s, OU=%s, CN=uuid:%s", countryCode, organisation, organizationalUnitName, deviceId);
75 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
78 * Generates elliptic keypair.
80 * @param[out] pk mbedtls public key container
82 * @return 0 on success or -1 on error
84 static int ecdsaGenKeypair(mbedtls_pk_context * pk)
86 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
87 mbedtls_entropy_context entropy;
88 mbedtls_ctr_drbg_context ctr_drbg;
90 VERIFY_NON_NULL_RET(pk, TAG, "Param pk is NULL", -1);
94 unsigned char seed[sizeof(SEED)] = {0};
96 urandomFd = open("/dev/urandom", O_RDONLY);
99 OIC_LOG(ERROR, TAG, "Fails open /dev/urandom!");
100 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
103 if(0 > read(urandomFd, seed, sizeof(seed)))
105 OIC_LOG(ERROR, TAG, "Fails read from /dev/urandom!");
107 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
113 unsigned char * seed = (unsigned char*) SEED;
115 // Initialize and seed DRBG context
116 mbedtls_ctr_drbg_init(&ctr_drbg);
117 mbedtls_entropy_init(&entropy);
118 if (0 != mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
119 &entropy, seed, sizeof(SEED)))
121 OIC_LOG(ERROR, TAG, "Seed initialization failed!");
122 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
125 mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF);
126 // Initialize l context
128 if (0 > mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)))
130 OIC_LOG(ERROR, TAG, "mbedtls_pk_info_from_type error");
131 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
134 if (0 > mbedtls_ecp_group_load(&mbedtls_pk_ec(*pk)->grp, MBEDTLS_ECP_DP_SECP256R1))
136 OIC_LOG(ERROR, TAG, "mbedtls_ecp_group_load error");
137 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
140 if (0 > mbedtls_ecp_gen_keypair(&mbedtls_pk_ec(*pk)->grp,
141 &mbedtls_pk_ec(*pk)->d,
142 &mbedtls_pk_ec(*pk)->Q,
143 mbedtls_ctr_drbg_random, &ctr_drbg))
145 OIC_LOG(ERROR, TAG, "mbedtls_ecp_gen_keypair error");
146 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
150 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
157 * Generates keypair and certificate signing request.
159 * @param[in] subjectName CSR Subject names should contain
160 * a comma-separated list of OID types and values:
161 * e.g. "C=UA,O=ABC,CN=uuid:32323232-3232-3232-3232-323232323232"
162 * @param[out] prKey private key in DER
163 * @param[out] prKeyLen private key buffer length
164 * @param[out] pubKey public key in DER
165 * @param[out] pubKeyLen public key buffer length
166 * @param[out] CSR certificate signing request in DER
167 * @param[out] CSRLen certificate signing request buffer length
169 * @return 0 on success or -1 on error
171 static int GenerateCSR(char *subject, OCByteString *csr)
173 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
174 VERIFY_NON_NULL_RET(subject, TAG, "Param subject is NULL", -1);
175 VERIFY_NON_NULL_RET(csr, TAG, "Param csr is NULL", -1);
179 unsigned char * buf = NULL;
180 mbedtls_entropy_context entropy;
181 mbedtls_ctr_drbg_context ctr_drbg;
182 mbedtls_pk_context * key = NULL;
183 mbedtls_x509write_csr req;
185 // Initialize keypair context
186 key = (mbedtls_pk_context *)OICMalloc(sizeof(mbedtls_pk_context));
189 OIC_LOG_V(ERROR, TAG, "OICMalloc returned NULL on key allocation");
190 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
194 if (0 > ecdsaGenKeypair(key))
196 OIC_LOG(ERROR, TAG, "ecdsaGenKeypair error");
197 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
201 // Initialize CSR context
202 mbedtls_x509write_csr_init(&req);
203 // Set up MD algorithm, key and subject to CSR
204 mbedtls_x509write_csr_set_md_alg(&req, MBEDTLS_MD_SHA256);
205 mbedtls_x509write_csr_set_key(&req, key);
206 if (0 > mbedtls_x509write_csr_set_subject_name(&req, subject))
208 OIC_LOG(ERROR, TAG, "mbedtls_x509write_csr_set_subject_name error");
209 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
215 unsigned char seed[sizeof(SEED)] = {0};
217 urandomFd = open("/dev/urandom", O_RDONLY);
220 OIC_LOG(ERROR, TAG, "Fails open /dev/urandom!");
221 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
224 if(0 > read(urandomFd, seed, sizeof(seed)))
226 OIC_LOG(ERROR, TAG, "Fails read from /dev/urandom!");
228 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
234 unsigned char * seed = (unsigned char *) SEED;
236 // Initialize and seed DRBG context
237 mbedtls_ctr_drbg_init(&ctr_drbg);
238 mbedtls_entropy_init(&entropy);
239 if (0 != mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
240 &entropy, seed, sizeof(SEED)))
242 OIC_LOG(ERROR, TAG, "Seed initialization failed!");
243 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
246 mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF);
249 buf = (unsigned char *)OICMalloc(bufsize * sizeof(unsigned char));
252 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on buf allocation");
253 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
256 ret = mbedtls_x509write_csr_der(&req, buf, bufsize,
257 mbedtls_ctr_drbg_random, &ctr_drbg);
260 OIC_LOG(ERROR, TAG, "mbedtls_x509write_csr_der error");
261 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
266 csr->bytes = (uint8_t *)OICMalloc(ret * sizeof(uint8_t));
267 if (NULL == csr->bytes)
269 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on csr allocation");
270 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
273 memcpy(csr->bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
275 // Private key to output
276 ret = mbedtls_pk_write_key_der(key, buf, bufsize);
279 OIC_LOG(ERROR, TAG, "mbedtls_pk_write_key_der error");
280 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
283 privateKey.bytes = (uint8_t *)OICMalloc(ret * sizeof(char));
284 if (NULL == privateKey.bytes)
286 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on privateKey.bytes allocation");
287 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
290 memcpy(privateKey.bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
291 privateKey.len = ret;
292 // Public key to output
293 ret = mbedtls_pk_write_pubkey_der(key, buf, bufsize);
296 OIC_LOG(ERROR, TAG, "mbedtls_pk_write_pubkey_der error");
297 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
300 //leave this, may be public key will be required in future
301 OCByteString publicKey;
302 publicKey.bytes = (uint8_t *)OICMalloc(ret * sizeof(char));
303 if (NULL == publicKey.bytes)
305 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on pubKey allocation");
306 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
309 memcpy(publicKey.bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
311 OICFree(publicKey.bytes);
313 mbedtls_entropy_free(&entropy);
314 mbedtls_ctr_drbg_free(&ctr_drbg);
315 mbedtls_x509write_csr_free(&req);
318 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
323 * Cloud CSR Sign response handler
325 * @param[in] ctx context
326 * @param[out] data data required to external application
327 * @param[in] response peer response
328 * @return OCStackResult application result
330 static OCStackResult HandleCertificateIssueRequest(void *ctx, void **data, OCClientResponse *response)
332 OCStackResult result = OC_STACK_OK;
333 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
340 OIC_LOG_V(ERROR, TAG, "%s: Client response is null",__func__);
341 return OC_STACK_INVALID_PARAM;
344 if (response->result < 4 && response->payload)
346 OIC_LOG_V(ERROR, TAG, "CSR sign error: result: %d, payload null: %s",
347 response->result, response->payload ? "no" : "yes");
348 OIC_LOG_PAYLOAD(DEBUG, response->payload);
349 return OC_STACK_ERROR;
354 if (!OCRepPayloadGetPropString((OCRepPayload *)response->payload,
355 OC_RSRVD_DEVICE_ID, &deviceId))
357 OIC_LOG(ERROR, TAG, "Can't get: Device Id");
358 result = OC_STACK_ERROR;
362 if (!OCRepPayloadGetPropPubDataType((OCRepPayload *)response->payload,
363 OC_RSRVD_CERT, &cert))
365 OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_CERT);
366 result = OC_STACK_ERROR;
384 result = SRPSaveOwnCertChain(&cert1, &key, &credId);
385 if (result != OC_STACK_OK)
387 OIC_LOG(ERROR, TAG, "Cann't add cert");
393 if (!OCRepPayloadGetPropPubDataType((OCRepPayload *)response->payload,
394 OC_RSRVD_CACERT, &caCert))
396 OIC_LOG_V(ERROR, TAG, "Cann't get: %s", OC_RSRVD_CACERT);
397 result = OC_STACK_ERROR;
402 result = SRPSaveTrustCertChain(caCert.data, caCert.len, caCert.encoding, &credId);
403 if (result != OC_STACK_OK)
405 OIC_LOG(ERROR, TAG, "Can't insert CA cert");
409 OICFree(privateKey.bytes);
410 privateKey.bytes = NULL;
413 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
419 * Certificate-Issue request function
421 * @param[in] endPoint cloud host and port
422 * @return OCStackResult application result
424 OCStackResult OCCloudCertificateIssueRequest(void* ctx,
425 const OCDevAddr *endPoint,
426 OCCloudResponseCB callback)
428 OCStackResult ret = OC_STACK_OK;
430 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
432 if (NULL == endPoint)
434 OIC_LOG(ERROR, TAG, "Input parameter endpoint is NULL");
435 return OC_STACK_INVALID_PARAM;
438 char *deviceId = getDeviceId();
440 char subject[MAX_STRING_LEN] = { 0 };
441 CSRMakeSubject(subject, "KR", "Samsung", "OCF Device", deviceId);
443 OIC_LOG_V(DEBUG, TAG, "Certificate Request subject: %s", subject);
445 OCByteString request;
446 if (0 != GenerateCSR(subject, &request))
448 OIC_LOG(ERROR, TAG, "Cann't get the sertificate request");
449 ret = OC_STACK_ERROR;
452 OIC_LOG(DEBUG, TAG, "Certificate Request:");
453 OIC_LOG_BUFFER(DEBUG, TAG, request.bytes, request.len);
455 OIC_LOG(DEBUG, TAG, "Private Key:");
456 OIC_LOG_BUFFER(DEBUG, TAG, privateKey.bytes, privateKey.len);
458 OCRepPayload* payload = OCRepPayloadCreate();
461 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
462 ret = OC_STACK_ERROR;
466 OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
468 OicSecKey_t csr = {.data = request.bytes, .len = request.len, .encoding = OIC_ENCODING_DER};
470 OCRepPayloadSetPropPubDataType(payload, OC_RSRVD_CSR, &csr);
472 OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)payload);
474 char uri[MAX_URI_QUERY] = { 0 };
475 snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
476 endPoint->addr, endPoint->port,
477 OC_RSRVD_PROV_CERT_URI);
479 OCCallbackData cbData;
480 fillCallbackData(&cbData, ctx, callback, HandleCertificateIssueRequest, NULL);
482 ret = OCDoResource(NULL, OC_REST_POST, uri, NULL,
483 (OCPayload *)payload,
485 OC_LOW_QOS, &cbData, NULL, 0);
487 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
489 OICFree(request.bytes);