1 /* *****************************************************************
3 * Copyright 2016 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * *****************************************************************/
20 #include "iotivity_config.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "cacommonutil.h"
30 #include "ocpayload.h"
31 #include "payload_logging.h"
32 #include "doxmresource.h"
33 #include "pmutility.h"
34 #include "secureresourceprovider.h"
36 // headers required for mbed TLS
37 #include "mbedtls/platform.h"
38 #include "mbedtls/ssl.h"
39 #include "mbedtls/entropy.h"
40 #include "mbedtls/ctr_drbg.h"
41 #include "mbedtls/pkcs12.h"
42 #include "mbedtls/ssl_internal.h"
43 #include "mbedtls/x509_csr.h"
46 #include "mbedtls/debug.h"
47 #include "mbedtls/version.h"
55 #define TAG "OIC_CLOUD_CSR"
57 //TODO: is it required in CSR response?
58 static OCByteString g_privateKey = {0, 0};
60 #define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
62 #define MAX_STRING_LEN 254
65 * @def PERSONALIZATION_STRING
66 * @brief Personalization string for the mbedtls RNG
68 #define PERSONALIZATION_STRING "IOTIVITY_RND"
80 * Make CSR subject like:
81 * Subject: C=KR, O=Samsung, OU=OCF Device, CN=uuid:1234567890
82 * @param[in] subj the subject
84 static void CSRMakeSubject(char *subject, const char *countryCode, const char *organisation,
85 const char *organizationalUnitName, const char *deviceId)
87 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
91 OIC_LOG_V(ERROR, TAG, "%s: The device id is NULL",__func__);
94 snprintf(subject, MAX_STRING_LEN, "C=%s, O=%s, OU=%s, CN=uuid:%s", countryCode, organisation, organizationalUnitName, deviceId);
96 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
99 * Generates elliptic keypair.
101 * @param[out] pk mbedtls public key container
103 * @return 0 on success or -1 on error
105 static int ecdsaGenKeypair(mbedtls_pk_context * pk)
107 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
108 mbedtls_entropy_context entropy;
109 mbedtls_ctr_drbg_context ctr_drbg;
111 VERIFY_NON_NULL_RET(pk, TAG, "Param pk is NULL", -1);
113 // Initialize the DRBG context
114 mbedtls_ctr_drbg_init(&ctr_drbg);
115 mbedtls_entropy_init(&entropy);
116 if (0 != mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
117 &entropy, PERSONALIZATION_STRING, sizeof(PERSONALIZATION_STRING)))
119 OIC_LOG(ERROR, TAG, "Seed initialization failed!");
120 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
123 mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON);
124 // Initialize l context
126 if (0 > mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)))
128 OIC_LOG(ERROR, TAG, "mbedtls_pk_info_from_type error");
129 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
132 if (0 > mbedtls_ecp_group_load(&mbedtls_pk_ec(*pk)->grp, MBEDTLS_ECP_DP_SECP256R1))
134 OIC_LOG(ERROR, TAG, "mbedtls_ecp_group_load error");
135 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
138 if (0 > mbedtls_ecp_gen_keypair(&mbedtls_pk_ec(*pk)->grp,
139 &mbedtls_pk_ec(*pk)->d,
140 &mbedtls_pk_ec(*pk)->Q,
141 mbedtls_ctr_drbg_random, &ctr_drbg))
143 OIC_LOG(ERROR, TAG, "mbedtls_ecp_gen_keypair error");
144 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
148 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
155 * Generates keypair and certificate signing request.
157 * @param[in] subjectName CSR Subject names should contain
158 * a comma-separated list of OID types and values:
159 * e.g. "C=UA,O=ABC,CN=uuid:32323232-3232-3232-3232-323232323232"
160 * @param[out] prKey private key in DER
161 * @param[out] prKeyLen private key buffer length
162 * @param[out] pubKey public key in DER
163 * @param[out] pubKeyLen public key buffer length
164 * @param[out] CSR certificate signing request in DER
165 * @param[out] CSRLen certificate signing request buffer length
167 * @return 0 on success or -1 on error
169 static int GenerateCSR(char *subject, OCByteString *csr)
171 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
172 VERIFY_NON_NULL_RET(subject, TAG, "Param subject is NULL", -1);
173 VERIFY_NON_NULL_RET(csr, TAG, "Param csr is NULL", -1);
177 unsigned char * buf = NULL;
178 mbedtls_entropy_context entropy;
179 mbedtls_ctr_drbg_context ctr_drbg;
180 mbedtls_pk_context * key = NULL;
181 mbedtls_x509write_csr req;
183 // Initialize keypair context
184 key = (mbedtls_pk_context *)OICMalloc(sizeof(mbedtls_pk_context));
187 OIC_LOG_V(ERROR, TAG, "OICMalloc returned NULL on key allocation");
188 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
192 if (0 > ecdsaGenKeypair(key))
194 OIC_LOG(ERROR, TAG, "ecdsaGenKeypair error");
195 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
199 // Initialize CSR context
200 mbedtls_x509write_csr_init(&req);
201 // Set up MD algorithm, key and subject to CSR
202 mbedtls_x509write_csr_set_md_alg(&req, MBEDTLS_MD_SHA256);
203 mbedtls_x509write_csr_set_key(&req, key);
204 if (0 > mbedtls_x509write_csr_set_subject_name(&req, subject))
206 OIC_LOG(ERROR, TAG, "mbedtls_x509write_csr_set_subject_name error");
207 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
211 // Initialize the DRBG context
212 mbedtls_ctr_drbg_init(&ctr_drbg);
213 mbedtls_entropy_init(&entropy);
214 if (0 != mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
215 &entropy, PERSONALIZATION_STRING, sizeof(PERSONALIZATION_STRING)))
217 OIC_LOG(ERROR, TAG, "Seed initialization failed!");
218 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
221 mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON);
224 buf = (unsigned char *)OICMalloc(bufsize * sizeof(unsigned char));
227 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on buf allocation");
228 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
231 ret = mbedtls_x509write_csr_der(&req, buf, bufsize,
232 mbedtls_ctr_drbg_random, &ctr_drbg);
235 OIC_LOG(ERROR, TAG, "mbedtls_x509write_csr_der error");
236 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
241 csr->bytes = (uint8_t *)OICMalloc(ret * sizeof(uint8_t));
242 if (NULL == csr->bytes)
244 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on csr allocation");
245 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
248 memcpy(csr->bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
250 // Private key to output
251 ret = mbedtls_pk_write_key_der(key, buf, bufsize);
254 OIC_LOG(ERROR, TAG, "mbedtls_pk_write_key_der error");
255 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
258 g_privateKey.bytes = (uint8_t *)OICMalloc(ret * sizeof(char));
259 if (NULL == g_privateKey.bytes)
261 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on g_privateKey.bytes allocation");
262 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
265 memcpy(g_privateKey.bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
266 g_privateKey.len = ret;
267 // Public key to output
268 ret = mbedtls_pk_write_pubkey_der(key, buf, bufsize);
271 OIC_LOG(ERROR, TAG, "mbedtls_pk_write_pubkey_der error");
272 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
275 //leave this, may be public key will be required in future
276 OCByteString publicKey;
277 publicKey.bytes = (uint8_t *)OICMalloc(ret * sizeof(char));
278 if (NULL == publicKey.bytes)
280 OIC_LOG(ERROR, TAG, "OICMalloc returned NULL on pubKey allocation");
281 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
284 memcpy(publicKey.bytes, buf + bufsize - ret, ret * sizeof(uint8_t));
286 OICFree(publicKey.bytes);
288 mbedtls_entropy_free(&entropy);
289 mbedtls_ctr_drbg_free(&ctr_drbg);
290 mbedtls_x509write_csr_free(&req);
293 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
298 * Cloud CSR Sign response handler
300 * @param[in] ctx context
301 * @param[out] data data required to external application
302 * @param[in] response peer response
303 * @return OCStackResult application result
305 static OCStackResult HandleCertificateIssueRequest(void *ctx, void **data, OCClientResponse *response)
307 OCStackResult result = OC_STACK_OK;
308 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
315 OIC_LOG_V(ERROR, TAG, "%s: Client response is null",__func__);
316 return OC_STACK_INVALID_PARAM;
319 if (response->result < 4 && response->payload)
321 OIC_LOG_V(ERROR, TAG, "CSR sign error: result: %d, payload null: %s",
322 response->result, response->payload ? "no" : "yes");
323 OIC_LOG_PAYLOAD(DEBUG, response->payload);
324 return OC_STACK_ERROR;
329 if (!OCRepPayloadGetPropString((OCRepPayload *)response->payload,
330 OC_RSRVD_DEVICE_ID, &deviceId))
332 OIC_LOG(ERROR, TAG, "Can't get: Device Id");
333 result = OC_STACK_ERROR;
337 if (!OCRepPayloadGetPropPubDataType((OCRepPayload *)response->payload,
338 OC_RSRVD_CERT, &cert))
340 OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_CERT);
341 result = OC_STACK_ERROR;
353 result = SRPSaveOwnCertChain(&cert, &key, &credId);
354 if (result != OC_STACK_OK)
356 OIC_LOG(ERROR, TAG, "Can't add cert");
362 if (!OCRepPayloadGetPropPubDataType((OCRepPayload *)response->payload,
363 OC_RSRVD_CACERT, &caCert))
365 OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_CACERT);
366 result = OC_STACK_ERROR;
371 result = SRPSaveTrustCertChain(caCert.data, caCert.len, caCert.encoding, &credId);
372 if (result != OC_STACK_OK)
374 OIC_LOG(ERROR, TAG, "Can't insert CA cert");
378 OICClearMemory(g_privateKey.bytes, g_privateKey.len);
379 OICFree(g_privateKey.bytes);
380 g_privateKey.bytes = NULL;
381 g_privateKey.len = 0;
383 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
389 * Certificate-Issue request function
391 * @param[in] endPoint cloud host and port
392 * @return OCStackResult application result
394 OCStackResult OCCloudCertificateIssueRequest(void* ctx,
395 const OCDevAddr *endPoint,
396 OCCloudResponseCB callback)
398 OCStackResult ret = OC_STACK_OK;
400 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
402 if (NULL == endPoint)
404 OIC_LOG(ERROR, TAG, "Input parameter endpoint is NULL");
405 return OC_STACK_INVALID_PARAM;
408 char *deviceId = getDeviceId();
410 char subject[MAX_STRING_LEN] = { 0 };
411 CSRMakeSubject(subject, "KR", "Samsung", "OCF Device", deviceId);
413 OIC_LOG_V(DEBUG, TAG, "Certificate Request subject: %s", subject);
415 OCByteString request;
416 if (0 != GenerateCSR(subject, &request))
418 OIC_LOG(ERROR, TAG, "Cann't get the sertificate request");
419 ret = OC_STACK_ERROR;
422 OIC_LOG(DEBUG, TAG, "Certificate Request:");
423 OIC_LOG_BUFFER(DEBUG, TAG, request.bytes, request.len);
425 OIC_LOG(DEBUG, TAG, "Private Key:");
426 OIC_LOG_BUFFER(DEBUG, TAG, g_privateKey.bytes, g_privateKey.len);
428 OCRepPayload* payload = OCRepPayloadCreate();
431 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
432 ret = OC_STACK_ERROR;
436 OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
438 OicSecKey_t csr = {.data = request.bytes, .len = request.len, .encoding = OIC_ENCODING_DER};
440 OCRepPayloadSetPropPubDataType(payload, OC_RSRVD_CSR, &csr);
442 OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)payload);
444 char uri[MAX_URI_QUERY] = { 0 };
445 snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
446 endPoint->addr, endPoint->port,
447 OC_RSRVD_PROV_CERT_URI);
448 OIC_LOG_V(DEBUG, TAG, "Certificate Request Query: %s", uri);
450 OCCallbackData cbData;
451 fillCallbackData(&cbData, ctx, callback, HandleCertificateIssueRequest, NULL);
453 ret = OCDoResource(NULL, OC_REST_POST, uri, NULL,
454 (OCPayload *)payload,
456 OC_LOW_QOS, &cbData, NULL, 0);
458 OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
460 OICFree(request.bytes);