+ if (NULL == crtBuf)
+ {
+ OIC_LOG(ERROR, TAG, "Param buf is NULL");
+ return;
+ }
+ if (NULL == crtBufLen)
+ {
+ OIC_LOG(ERROR, TAG, "Param bufLen is NULL");
+ return;
+ }
+
+ mbedtls_x509_crt deviceCert;
+ int ret = 0;
+
+ // check only first(i.e., device) certificate
+ if (crtBuf[0] == 0x30 && crtBuf[1] == 0x82)
+ {
+ uint8_t *sign_ptr = NULL;
+ /**
+ * structure of r_buf & s_buf
+ * +---------------+-------------+----------------------------+
+ * | tag (INTEGER) | length (1B) | value (r or s in integer) |
+ * +---------------+-------------+----------------------------+
+ */
+ uint8_t r_buf[32 + 4]; // for ECC 256 sign
+ uint8_t s_buf[32 + 4];
+ uint32_t r_len = 0;
+ uint32_t s_len = 0;
+ size_t sign_len = 0;
+ uint32_t removed = 0;
+ uint32_t removed_total = 0;
+ size_t org_len = 0;
+
+ mbedtls_x509_crt_init(&deviceCert);
+
+ unsigned char * tmp = (unsigned char *)crtBuf + 1;
+ if ( 0 != mbedtls_asn1_get_len(&tmp, crtBuf + *crtBufLen, &org_len))
+ {
+ OIC_LOG(ERROR, TAG, "Invalid parsed length");
+ goto exit;
+ }
+
+ if (org_len < *crtBufLen)
+ {
+ ret = mbedtls_x509_crt_parse_der(&deviceCert, crtBuf, org_len + 4);
+ if (0 != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse_der returned -0x%04x", -(ret));
+ goto exit;
+ }
+
+ if (NULL == deviceCert.sig.p)
+ {
+ OIC_LOG(ERROR, TAG, "Cert's signature is NULL");
+ goto exit;
+ }
+ sign_ptr = (uint8_t*)deviceCert.sig.p;
+ ret = mbedtls_asn1_get_tag(&sign_ptr, deviceCert.sig.p + deviceCert.sig.len, &sign_len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (0 != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "mbedtls_asn1_get_tag error : %d", ret);
+ goto exit;
+ }
+ if (sign_ptr)
+ {
+ r_len = sign_ptr[1] + 2; // including header itself
+ }
+ if (r_len > deviceCert.sig.len)
+ {
+ OIC_LOG_V(ERROR, TAG, "signature length check error #1 : %d", ret);
+ goto exit;
+ }
+ OIC_LOG_V(DEBUG, TAG, "r_len = %d", r_len);
+ memcpy(r_buf, sign_ptr, r_len);
+ removed = remove_useless_leading_zeros(r_buf, r_len);
+
+ /* Do not change order */
+ sign_ptr += r_len;
+ r_len -= removed;
+ removed_total += removed;
+ if (sign_ptr)
+ {
+ s_len = sign_ptr[1] + 2; // including header itself
+ }
+ if (s_len + r_len > deviceCert.sig.len)
+ {
+ OIC_LOG_V(ERROR, TAG, "signature length check error #2 : %d", ret);
+ goto exit;
+ }
+ OIC_LOG_V(DEBUG, TAG, "s_len = %d", s_len);
+ memcpy(s_buf, sign_ptr, s_len);
+ removed = remove_useless_leading_zeros(s_buf, s_len);
+ s_len -= removed;
+ removed_total += removed;
+
+ if (removed_total > 0)
+ {
+ // if length of signature is incorrect.
+ OIC_LOG_V(INFO, TAG, "Cert Length (Before) : %lu", *crtBufLen);
+ OIC_LOG(INFO, TAG, "Invalid length of signature is dectected.");
+ OIC_LOG(INFO, TAG, "Update signature...");
+
+ uint16_t crt_len = 0;
+ /* change bitstring length */
+ {
+ uint8_t *sign_len_ptr = deviceCert.sig.p + 1;
+ *sign_len_ptr -= removed_total;
+ }
+ /* change signature length */
+ {
+ uint8_t *sign_len_ptr = deviceCert.sig.p - 1;
+ if (*sign_len_ptr == 0)
+ {
+ sign_len_ptr--;
+ }
+ *sign_len_ptr -= removed_total;
+ }
+ /* change signature */
+ {
+ memcpy(deviceCert.sig.p + 2, r_buf, r_len);
+ memcpy(deviceCert.sig.p + 2 + r_len, s_buf, s_len);
+ }
+ /* change certificate length */
+ {
+ uint8_t *crt_len_ptr = deviceCert.raw.p + 2;
+ crt_len = (crt_len_ptr[0] << 8) & 0x0000FF00;
+ crt_len |= (crt_len_ptr[1] & 0x000000FF);
+ crt_len -= removed_total;
+ crt_len_ptr[0] = (uint8_t)(crt_len >> 8);
+ crt_len_ptr[1] = (uint8_t)(crt_len);
+ }
+ crt_len += 4; // include header and length field
+ /* change raw data and crt parse cert again */
+ {
+ mbedtls_x509_crt crt_cpy;
+ mbedtls_x509_crt_init( &crt_cpy );
+ if ((ret = mbedtls_x509_crt_parse_der(&crt_cpy, deviceCert.raw.p, (size_t)crt_len)) != 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse error : %d", ret);
+ mbedtls_x509_crt_free(&crt_cpy);
+ goto exit;
+ }
+
+ org_len += 4; // include header and length field
+ size_t remained_len = (*crtBufLen - org_len);
+ memcpy(crtBuf, deviceCert.raw.p, crt_len);
+ memcpy(crtBuf + crt_len, crtBuf + org_len, remained_len);
+ *crtBufLen = (size_t)crt_len + remained_len;
+
+ mbedtls_x509_crt_free(&crt_cpy);
+ OIC_LOG_V(INFO, TAG, "Dev cert : %lu -> %lu", org_len, crt_len);
+ OIC_LOG_V(INFO, TAG, "Remained chain : %lu", remained_len);
+ OIC_LOG_V(INFO, TAG, "Cert Length (After) : %lu", *crtBufLen);
+ }
+ }
+ else
+ {
+ // if length of signature is correct.
+ OIC_LOG(INFO, TAG, "Don't need to update signature...");
+ }
+
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "PEM or invalid cert format detected. finish to check");
+ }
+
+exit:
+ mbedtls_x509_crt_free(&deviceCert);
+ OIC_LOG_V(DEBUG, TAG, "Cert chain length = %d", *crtBufLen);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
+
+/**
+ * Internal API to load the key/cert from HW PKI
+ *
+ * @return true on HW PKI is available
+ */
+static bool GetPkixInfoFromHw(PkiInfo_t * inf)
+{
+ OIC_LOG_V(INFO, TAG, "In %s", __func__);
+
+ if (!gHwPkixCtx.hwKeyCtx && gHwPkixCtx.getHwKeyContext)
+ {
+ gHwPkixCtx.hwKeyCtx = gHwPkixCtx.getHwKeyContext(
+ HWKEY_SVC_IOTIVITY,
+ HWKEY_USAGE_PRIMARY, NULL);
+ if (!gHwPkixCtx.hwKeyCtx)
+ {
+ OIC_LOG(WARNING, TAG, "gHwPkixCtx.getHwKeyContext return null");
+ }
+ }
+
+ if (gHwPkixCtx.hwKeyCtx && gHwPkixCtx.getOwnCertCb)
+ {
+ int ret = gHwPkixCtx.getOwnCertCb(gHwPkixCtx.hwKeyCtx, &inf->crt.data, &inf->crt.len);
+ if (0 != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "gHwPkixCtx.getOwnCertCb error : %d", ret);
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return false;
+ }
+
+ // check and fix invalid cert signature
+ CheckInvalidDERSignature(inf->crt.data, &inf->crt.len);
+
+ OIC_LOG_V(INFO, TAG, "Cert chain length = %d", inf->crt.len);
+ OIC_LOG_V(INFO, TAG, "Out %s", __func__);
+ return true;
+ }
+ OIC_LOG_V(INFO, TAG, "Out %s", __func__);
+ return false;
+}
+
+void GetPkixInfo(PkiInfo_t * inf)
+{
+ OIC_LOG_V(INFO, TAG, "In %s", __func__);