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 * *****************************************************************/
21 #include "pkix_interface.h"
22 #include "credresource.h"
23 #include "crlresource.h"
24 #include "srmresourcestrings.h"
25 #include "casecurityinterface.h"
28 #include "oic_malloc.h"
31 #define TAG "OIC_SRM_PKIX_INTERFACE"
33 static HWPkixContext_t gHwPkixCtx = {
34 .getHwKeyContext = NULL,
35 .freeHwKeyContext = NULL,
37 .setupPkContextCb = NULL,
42 * returns the number of removed zeros
44 static size_t remove_useless_leading_zeros(uint8_t *asn_integer_buf, uint32_t size)
49 uint8_t tag = asn_integer_buf[0];
50 uint8_t len = asn_integer_buf[1];
51 uint8_t *p = asn_integer_buf + 2;
59 if (tag != MBEDTLS_ASN1_INTEGER)
64 if ((uint32_t)len + 2 != size || sizeof(buf) < size)
69 for (idx = 0; idx < (uint32_t)len - 1; idx++)
75 if (p[idx] == 0 && ((p[idx + 1] & 0x80) != 0)) // 00000000 1XXXXXXXX (bit)
87 asn_integer_buf[1] = len;
89 memcpy(buf, p + idx, len);
95 void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
97 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
100 OIC_LOG(ERROR, TAG, "Param buf is NULL");
103 if (NULL == crtBufLen)
105 OIC_LOG(ERROR, TAG, "Param bufLen is NULL");
109 OIC_LOG_V(INFO, TAG, "Cert Buf Length: %lu", *crtBufLen);
110 OIC_LOG(INFO, TAG, "[Cert Buf] : ");
111 OIC_LOG_BUFFER(INFO, TAG, crtBuf, *crtBufLen);
113 mbedtls_x509_crt deviceCert;
116 // check only first(i.e., device) certificate
117 if (crtBuf[0] == 0x30 && crtBuf[1] == 0x82)
119 uint8_t *sign_ptr = NULL;
121 * structure of r_buf & s_buf
122 * +---------------+-------------+----------------------------+
123 * | tag (INTEGER) | length (1B) | value (r or s in integer) |
124 * +---------------+-------------+----------------------------+
126 uint8_t r_buf[32 + 4]; // for ECC 256 sign
127 uint8_t s_buf[32 + 4];
131 uint32_t removed = 0;
132 uint32_t removed_total = 0;
135 mbedtls_x509_crt_init(&deviceCert);
137 unsigned char * tmp = (unsigned char *)crtBuf + 1;
138 if ( 0 != mbedtls_asn1_get_len(&tmp, crtBuf + *crtBufLen, &org_len))
140 OIC_LOG(ERROR, TAG, "Invalid parsed length");
144 if (org_len < *crtBufLen)
146 ret = mbedtls_x509_crt_parse_der(&deviceCert, crtBuf, org_len + 4);
149 OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse_der returned -0x%04x", -(ret));
153 if (NULL == deviceCert.sig.p)
155 OIC_LOG(ERROR, TAG, "Cert's signature is NULL");
158 sign_ptr = (uint8_t*)deviceCert.sig.p;
159 ret = mbedtls_asn1_get_tag(&sign_ptr, deviceCert.sig.p + deviceCert.sig.len, &sign_len,
160 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
163 OIC_LOG_V(ERROR, TAG, "mbedtls_asn1_get_tag error : %d", ret);
168 r_len = sign_ptr[1] + 2; // including header itself
170 if (r_len > deviceCert.sig.len)
172 OIC_LOG_V(ERROR, TAG, "signature length check error #1 : %d", ret);
175 OIC_LOG_V(DEBUG, TAG, "r_len = %d", r_len);
176 memcpy(r_buf, sign_ptr, r_len);
177 removed = remove_useless_leading_zeros(r_buf, r_len);
179 /* Do not change order */
182 removed_total += removed;
185 s_len = sign_ptr[1] + 2; // including header itself
187 if (s_len + r_len > deviceCert.sig.len)
189 OIC_LOG_V(ERROR, TAG, "signature length check error #2 : %d", ret);
192 OIC_LOG_V(DEBUG, TAG, "s_len = %d", s_len);
193 memcpy(s_buf, sign_ptr, s_len);
194 removed = remove_useless_leading_zeros(s_buf, s_len);
196 removed_total += removed;
198 if (removed_total > 0)
200 // if length of signature is incorrect.
201 OIC_LOG_V(INFO, TAG, "Cert Length (Before) : %lu", *crtBufLen);
202 OIC_LOG(INFO, TAG, "Invalid length of signature is dectected.");
203 OIC_LOG(INFO, TAG, "Update signature...");
205 uint16_t crt_len = 0;
206 /* change bitstring length */
208 uint8_t *sign_len_ptr = deviceCert.sig.p + 1;
209 *sign_len_ptr -= removed_total;
211 /* change signature length */
213 uint8_t *sign_len_ptr = deviceCert.sig.p - 1;
214 if (*sign_len_ptr == 0)
218 *sign_len_ptr -= removed_total;
220 /* change signature */
222 memcpy(deviceCert.sig.p + 2, r_buf, r_len);
223 memcpy(deviceCert.sig.p + 2 + r_len, s_buf, s_len);
225 /* change certificate length */
227 uint8_t *crt_len_ptr = deviceCert.raw.p + 2;
228 crt_len = (crt_len_ptr[0] << 8) & 0x0000FF00;
229 crt_len |= (crt_len_ptr[1] & 0x000000FF);
230 crt_len -= removed_total;
231 crt_len_ptr[0] = (uint8_t)(crt_len >> 8);
232 crt_len_ptr[1] = (uint8_t)(crt_len);
234 crt_len += 4; // include header and length field
235 /* change raw data and crt parse cert again */
237 mbedtls_x509_crt crt_cpy;
238 mbedtls_x509_crt_init( &crt_cpy );
239 if ((ret = mbedtls_x509_crt_parse_der(&crt_cpy, deviceCert.raw.p, (size_t)crt_len)) != 0)
241 OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse error : %d", ret);
242 mbedtls_x509_crt_free(&crt_cpy);
246 org_len += 4; // include header and length field
247 size_t remained_len = (*crtBufLen - org_len);
248 memcpy(crtBuf, deviceCert.raw.p, crt_len);
249 memcpy(crtBuf + crt_len, crtBuf + org_len, remained_len);
250 *crtBufLen = (size_t)crt_len + remained_len;
252 mbedtls_x509_crt_free(&crt_cpy);
253 OIC_LOG_V(INFO, TAG, "Dev cert : %lu -> %lu", org_len, crt_len);
254 OIC_LOG_V(INFO, TAG, "Remained chain : %lu", remained_len);
255 OIC_LOG_V(INFO, TAG, "Cert Length (After) : %lu", *crtBufLen);
260 // if length of signature is correct.
261 OIC_LOG(INFO, TAG, "Don't need to update signature...");
268 OIC_LOG(ERROR, TAG, "PEM or invalid cert format detected. finish to check");
272 mbedtls_x509_crt_free(&deviceCert);
273 OIC_LOG_V(DEBUG, TAG, "Cert chain length = %d", *crtBufLen);
274 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
278 * Internal API to load the key/cert from HW PKI
280 * @return true on HW PKI is available
282 static bool GetPkixInfoFromHw(PkiInfo_t * inf)
284 OIC_LOG_V(INFO, TAG, "In %s", __func__);
286 if (!gHwPkixCtx.hwKeyCtx && gHwPkixCtx.getHwKeyContext)
288 gHwPkixCtx.hwKeyCtx = gHwPkixCtx.getHwKeyContext(
290 HWKEY_USAGE_PRIMARY, NULL);
291 if (!gHwPkixCtx.hwKeyCtx)
293 OIC_LOG(WARNING, TAG, "gHwPkixCtx.getHwKeyContext return null");
297 if (gHwPkixCtx.hwKeyCtx && gHwPkixCtx.getOwnCertCb)
299 int ret = gHwPkixCtx.getOwnCertCb(gHwPkixCtx.hwKeyCtx, &inf->crt.data, &inf->crt.len);
302 OIC_LOG_V(ERROR, TAG, "gHwPkixCtx.getOwnCertCb error : %d", ret);
303 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
307 // check and fix invalid cert signature
308 CheckInvalidDERSignature(inf->crt.data, &inf->crt.len);
310 OIC_LOG_V(INFO, TAG, "Cert chain length = %d", inf->crt.len);
311 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
314 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
318 void GetPkixInfo(PkiInfo_t * inf)
320 OIC_LOG_V(INFO, TAG, "In %s", __func__);
323 OIC_LOG(ERROR, TAG, "NULL passed");
324 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
328 if (GetPkixInfoFromHw(inf))
330 OIC_LOG(INFO, TAG, "H/W based PKI will be used.");
334 GetDerOwnCert(&inf->crt, PRIMARY_CERT);
335 GetDerKey(&inf->key, PRIMARY_CERT);
337 GetDerCaCert(&inf->ca, TRUST_CA);
338 GetDerCrl(&inf->crl);
340 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
343 void GetManufacturerPkixInfo(PkiInfo_t * inf)
345 OIC_LOG_V(INFO, TAG, "In %s", __func__);
348 OIC_LOG(ERROR, TAG, "NULL passed");
349 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
353 if (GetPkixInfoFromHw(inf))
355 OIC_LOG(INFO, TAG, "H/W based PKI will be used.");
359 GetDerOwnCert(&inf->crt, MF_PRIMARY_CERT);
360 GetDerKey(&inf->key, MF_PRIMARY_CERT);
362 GetDerCaCert(&inf->ca, MF_TRUST_CA);
365 OICFree(inf->crl.data);
367 inf->crl.data = NULL;
369 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
372 void InitCipherSuiteList(bool * list)
374 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
377 OIC_LOG(ERROR, TAG, "NULL passed");
378 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
381 InitCipherSuiteListInternal(list, TRUST_CA);
382 if (gHwPkixCtx.getOwnCertCb)
386 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
389 void InitManufacturerCipherSuiteList(bool * list)
391 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
394 OIC_LOG(ERROR, TAG, "NULL passed");
395 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
398 InitCipherSuiteListInternal(list, MF_TRUST_CA);
399 if (gHwPkixCtx.getOwnCertCb)
403 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
406 int SetupHwPkContext(mbedtls_pk_context* pkCtx)
408 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
411 OIC_LOG(ERROR, TAG, "NULL passed");
412 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
416 if (gHwPkixCtx.setupPkContextCb)
418 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
419 return gHwPkixCtx.setupPkContextCb(pkCtx, gHwPkixCtx.hwKeyCtx);
423 OIC_LOG(ERROR, TAG, "gHwPkixCallbacks.setupPkContextCb is NULL");
426 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
431 int SetHwPkixCallbacks(GetHwKeyContext getHwKeyContext,
432 FreeHwKeyContext freeHwKeyContext,
433 GetOwnCertFromHwCallback getOwnCertCb,
434 SetupPkContextFromHwCallback setupPkContextCb)
436 OIC_LOG_V(INFO, TAG, "In %s", __func__);
438 if (NULL == getHwKeyContext && NULL == freeHwKeyContext
439 && NULL == getOwnCertCb && NULL == setupPkContextCb)
441 OIC_LOG(INFO, TAG, "Unregistering callbacks");
443 else if (NULL == getHwKeyContext || NULL == freeHwKeyContext
444 || NULL == getOwnCertCb || NULL == setupPkContextCb)
446 OIC_LOG(ERROR, TAG, "NULL Passed");
447 OIC_LOG(ERROR, TAG, "Callback function parameters can not be null");
451 gHwPkixCtx.getHwKeyContext = getHwKeyContext;
452 gHwPkixCtx.freeHwKeyContext = freeHwKeyContext;
453 gHwPkixCtx.getOwnCertCb = getOwnCertCb;
454 gHwPkixCtx.setupPkContextCb = setupPkContextCb;
456 if (gHwPkixCtx.hwKeyCtx && NULL != freeHwKeyContext)
458 gHwPkixCtx.freeHwKeyContext(gHwPkixCtx.hwKeyCtx);
460 gHwPkixCtx.hwKeyCtx = NULL;
462 // setup pkcontext handler
463 CAregisterSetupPkContextHandler(SetupHwPkContext);
465 OIC_LOG_V(INFO, TAG, "Out %s", __func__);