Merge tizen_5.0 codes into tizen_4.0
[platform/upstream/iotivity.git] / resource / csdk / security / src / pkix_interface.c
index 5b1dc61..6a487a9 100644 (file)
 #include "srmresourcestrings.h"
 #include "casecurityinterface.h"
 #include "logger.h"
-#ifdef __TIZENRT__
+#include "base64.h"
 #include "oic_malloc.h"
-#endif
+
+#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----"
+#define PEM_END_CRT "-----END CERTIFICATE-----"
 
 #define TAG "OIC_SRM_PKIX_INTERFACE"
 
+#define ECC256_SIG_LEN 32+4
+
 static HWPkixContext_t gHwPkixCtx = {
     .getHwKeyContext = NULL,
     .freeHwKeyContext = NULL,
@@ -106,16 +110,87 @@ void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
         return;
     }
 
-    OIC_LOG_V(INFO, TAG, "Cert Buf Length: %lu", *crtBufLen);
+    OIC_LOG_V(INFO, TAG, "Cert Buf Length: %zu", *crtBufLen);
     OIC_LOG(INFO, TAG, "[Cert Buf] : ");
     OIC_LOG_BUFFER(INFO, TAG, crtBuf, *crtBufLen);
 
     mbedtls_x509_crt deviceCert;
+    mbedtls_x509_crt_init(&deviceCert);
     int ret = 0;
 
+    uint8_t *derCrtBuf = NULL;
+    size_t *derCrtBufLen = NULL;
+
+    uint8_t *derCrtBufTmp = NULL;
+    size_t derCrtBufLenTmp = 0;
+
     // check only first(i.e., device) certificate
     if (crtBuf[0] == 0x30 && crtBuf[1] == 0x82)
     {
+        derCrtBuf = crtBuf;
+        derCrtBufLen = crtBufLen;
+    }
+    else
+    {
+        uint8_t * begin = (uint8_t *)memmem(crtBuf, *crtBufLen,
+                                            PEM_BEGIN_CRT, sizeof(PEM_BEGIN_CRT) - 1);
+        if (NULL != begin)
+        {
+            uint8_t * end = (uint8_t *)memmem(crtBuf, *crtBufLen,
+                                              PEM_END_CRT, sizeof(PEM_END_CRT) - 1);
+            if (NULL != end)
+            {
+                uint32_t idx = 0;
+                uint32_t count = 0;
+                uint32_t decodedLen = 0;
+                begin += sizeof(PEM_BEGIN_CRT) - 1;
+                size_t certLen = (size_t)(end - begin);
+                size_t outBufSize = B64DECODE_OUT_SAFESIZE(certLen + 1);
+
+                uint8_t * certCopy = (uint8_t *)OICCalloc(certLen, 1);
+                if(NULL == certCopy)
+                {
+                    OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
+                    goto exit;
+                }
+                for (idx = 0; idx < certLen; idx++)
+                {
+                    if (begin[idx] != '\r' && begin[idx] != '\n')
+                    {
+                        certCopy[count] = begin[idx];
+                        count++;
+                    }
+                }
+                certLen = count;
+
+                derCrtBufTmp = (uint8_t *)OICCalloc(outBufSize, 1);
+                if(NULL == derCrtBufTmp)
+                {
+                    OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
+                    OICFree(certCopy);
+                    goto exit;
+                }
+
+                if (B64_OK != b64Decode((char *)certCopy, certLen, derCrtBufTmp, outBufSize, &decodedLen))
+                {
+                    OICFree(certCopy);
+                    goto exit;
+                }
+                OICFree(certCopy);
+
+                derCrtBuf = derCrtBufTmp;
+                derCrtBufLenTmp = decodedLen;
+                derCrtBufLen = &derCrtBufLenTmp;
+            }
+        }
+        else
+        {
+            goto exit;
+        }
+    }
+
+    if (NULL != derCrtBuf && NULL != derCrtBufLen && 0 != *derCrtBufLen)
+    {
         uint8_t *sign_ptr = NULL;
         /**
         * structure of r_buf & s_buf
@@ -123,8 +198,8 @@ void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
         * | 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];
+        uint8_t r_buf[ECC256_SIG_LEN]; // for ECC 256 sign
+        uint8_t s_buf[ECC256_SIG_LEN];
         uint32_t r_len = 0;
         uint32_t s_len = 0;
         size_t sign_len = 0;
@@ -132,18 +207,16 @@ void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
         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))
+        unsigned char * tmp = (unsigned char *)derCrtBuf + 1;
+        if ( 0 != mbedtls_asn1_get_len(&tmp, derCrtBuf + *derCrtBufLen, &org_len))
         {
             OIC_LOG(ERROR, TAG, "Invalid parsed length");
             goto exit;
         }
 
-        if (org_len < *crtBufLen)
+        if (org_len < *derCrtBufLen)
         {
-            ret = mbedtls_x509_crt_parse_der(&deviceCert, crtBuf, org_len + 4);
+            ret = mbedtls_x509_crt_parse_der(&deviceCert, derCrtBuf, org_len + 4);
             if (0 != ret)
             {
                 OIC_LOG_V(ERROR, TAG, "mbedtls_x509_crt_parse_der returned -0x%04x", -(ret));
@@ -167,7 +240,7 @@ void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
             {
                 r_len = sign_ptr[1] + 2; // including header itself
             }
-            if (r_len > deviceCert.sig.len)
+            if (r_len > deviceCert.sig.len || r_len > ECC256_SIG_LEN)
             {
                 OIC_LOG_V(ERROR, TAG, "signature length check error #1 : %d", ret);
                 goto exit;
@@ -184,7 +257,7 @@ void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
             {
                 s_len = sign_ptr[1] + 2; // including header itself
             }
-            if (s_len + r_len > deviceCert.sig.len)
+            if (s_len + r_len > deviceCert.sig.len || s_len > ECC256_SIG_LEN)
             {
                 OIC_LOG_V(ERROR, TAG, "signature length check error #2 : %d", ret);
                 goto exit;
@@ -198,7 +271,7 @@ void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
             if (removed_total > 0)
             {
                 // if length of signature is incorrect.
-                OIC_LOG_V(INFO, TAG, "Cert Length (Before) : %lu", *crtBufLen);
+                OIC_LOG_V(INFO, TAG, "Cert Length (Before) : %zu", *derCrtBufLen);
                 OIC_LOG(INFO, TAG, "Invalid length of signature is dectected.");
                 OIC_LOG(INFO, TAG, "Update signature...");
 
@@ -244,15 +317,15 @@ void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
                     }
 
                     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;
+                    size_t remained_len = (*derCrtBufLen - org_len);
+                    memcpy(derCrtBuf, deviceCert.raw.p, crt_len);
+                    memcpy(derCrtBuf + crt_len, derCrtBuf + org_len, remained_len);
+                    *derCrtBufLen = (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);
+                    OIC_LOG_V(INFO, TAG, "Dev cert : %zu -> %u", org_len, crt_len);
+                    OIC_LOG_V(INFO, TAG, "Remained chain : %zu", remained_len);
+                    OIC_LOG_V(INFO, TAG, "Cert Length (After) : %zu", *crtBufLen);
                 }
             }
             else
@@ -270,7 +343,8 @@ void CheckInvalidDERSignature(uint8_t *crtBuf, size_t *crtBufLen)
 
 exit:
     mbedtls_x509_crt_free(&deviceCert);
-    OIC_LOG_V(DEBUG, TAG, "Cert chain length = %d", *crtBufLen);
+    OICFree(derCrtBufTmp);
+    OIC_LOG_V(DEBUG, TAG, "Cert chain length = %u", *crtBufLen);
     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
 }
 
@@ -307,7 +381,7 @@ static bool GetPkixInfoFromHw(PkiInfo_t * inf)
         // 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, "Cert chain length = %u", inf->crt.len);
         OIC_LOG_V(INFO, TAG, "Out %s", __func__);
         return true;
     }