[IOT-1947][IOT-2761][IOT-3228] Rm PEM/DER convert 83/22983/19 master
authorOleksii Beketov <ol.beketov@samsung.com>
Mon, 5 Nov 2018 13:21:23 +0000 (15:21 +0200)
committerNathan Heldt-Sheller <nathan.heldt-sheller@intel.com>
Tue, 6 Nov 2018 17:36:36 +0000 (17:36 +0000)
PEM/DER casting removed, allowing  mbedtls to manage
certificate conversion by itself. Credresource loads
certificates that could be either PEM or DER encoded
to a linked list instead of pushing them to a buffer.

Change-Id: I200f9ef8798b20bf894b8ef2cf85e42e13749f38
Signed-off-by: Oleksii Beketov <ol.beketov@samsung.com>
16 files changed:
resource/c_common/experimental/byte_array.h
resource/csdk/connectivity/api/casecurityinterface.h
resource/csdk/connectivity/common/SConscript
resource/csdk/connectivity/common/inc/parsechain.h [new file with mode: 0644]
resource/csdk/connectivity/common/src/parsechain.c [new file with mode: 0644]
resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c
resource/csdk/connectivity/test/ca_api_unittest.cpp
resource/csdk/connectivity/test/ssladapter_test.cpp
resource/csdk/security/include/internal/certhelpers.h
resource/csdk/security/include/internal/credresource.h
resource/csdk/security/src/certhelpers.c
resource/csdk/security/src/credresource.c
resource/csdk/security/src/pkix_interface.c
resource/csdk/security/src/rolesresource.c
resource/csdk/security/tool/svrdbeditor_src/svrdbeditorcommon.h
resource/csdk/security/tool/svrdbeditor_src/svrdbeditorcred.c

index 2810112..9e36176 100644 (file)
@@ -45,6 +45,13 @@ typedef struct ByteArray
     size_t len;      /**< Data size */
 } ByteArray_t;
 
+typedef struct ByteArrayLL ByteArrayLL_t;
+
+struct ByteArrayLL
+{
+    ByteArray_t *cert;
+    ByteArrayLL_t *next;
+};
 
 /**@def BYTE_ARRAY_INITIALIZER
  *
@@ -53,6 +60,13 @@ typedef struct ByteArray
 #undef BYTE_ARRAY_INITIALIZER
 #define BYTE_ARRAY_INITIALIZER {NULL, 0}
 
+/**@def CERT_CHAIN_INITIALIZER
+ *
+ * Initializes of existing certificate chain pointer to \a NULL.
+ */
+#undef CERT_CHAIN_INITIALIZER
+#define CERT_CHAIN_INITIALIZER {NULL, NULL}
+
 /**@def INIT_BYTE_ARRAY(array)
  *
  * Initializes of existing byte array \a array.
index 6bce2c4..faf597c 100644 (file)
@@ -109,6 +109,7 @@ bool CAGetSecureEndpointAttributes(const CAEndpoint_t* peer, uint32_t* allAttrib
  *
  */
 typedef void (*CAgetCredentialTypesHandler)(bool * list, const char* deviceId);
+
 /**
  * Binary structure containing PKIX related info
  * own certificate chain, public key, CA's and CRL's
@@ -119,9 +120,9 @@ typedef void (*CAgetCredentialTypesHandler)(bool * list, const char* deviceId);
  */
 typedef struct
 {
-    ByteArray_t crt;    /**< own certificate chain as a null-terminated PEM string of certificates */
+    ByteArrayLL_t crt;  /**< own certificate chain as a null-terminated PEM string of certificates */
     ByteArray_t key;    /**< own private key as binary-encoded DER */
-    ByteArray_t ca;     /**< trusted CAs as a null-terminated PEM string of certificates */
+    ByteArrayLL_t ca;   /**< trusted CAs as a null-terminated PEM string of certificates */
     ByteArray_t crl;    /**< trusted CRLs as binary-encoded DER */
 } PkiInfo_t;
 
@@ -333,4 +334,3 @@ void CAcloseSslConnectionAll(CATransportAdapter_t transportType);
 
 
 #endif /* CA_SECURITY_INTERFACE_H_ */
-
index c6cb0d8..49d21e2 100644 (file)
@@ -27,4 +27,7 @@ ca_common_src = [File(src) for src in (
 if connectivity_env['POSIX_SUPPORTED'] or target_os in ('windows'):
     ca_common_src.append(File('src/cathreadpool_pthreads.c'))
 
+if connectivity_env.get('SECURED') == '1':
+    ca_common_src.append(File('src/parsechain.c'))
+
 connectivity_env.AppendUnique(CA_SRC=ca_common_src)
diff --git a/resource/csdk/connectivity/common/inc/parsechain.h b/resource/csdk/connectivity/common/inc/parsechain.h
new file mode 100644 (file)
index 0000000..8e9ac29
--- /dev/null
@@ -0,0 +1,54 @@
+/* ****************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#ifndef U_PARSECHAIN_H_
+#define U_PARSECHAIN_H_
+
+#include <mbedtls/ssl.h>
+#include "casecurityinterface.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Parse chain of X.509 certificates.
+ *
+ * @param[out] crt     container for X.509 certificates
+ * @param[in]  certs   array of X.509 certificates
+ * @param[in]  errNum  number of certificates that failed to parse
+ *
+ * @return  number of successfully parsed certificates or -1 on error
+ */
+int ParseChain(mbedtls_x509_crt *crt, const ByteArrayLL_t *certs, int *errNum);
+
+/**
+ * Free chain of X.509 certificates.
+ *
+ * @param[in]  certs   array of X.509 certificates
+ */
+void FreeCertChain(ByteArrayLL_t *certs);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_ARRAYLIST_H_ */
diff --git a/resource/csdk/connectivity/common/src/parsechain.c b/resource/csdk/connectivity/common/src/parsechain.c
new file mode 100644 (file)
index 0000000..6b5a2a3
--- /dev/null
@@ -0,0 +1,75 @@
+/******************************************************************
+ *
+ * Copyright 2014 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#include "parsechain.h"
+#include "utlist.h"
+#include "caadapterutils.h"
+#include "oic_malloc.h"
+
+#define PARSE_CHAIN_TAG "OIC_PARSE_CHAIN"
+
+int ParseChain(mbedtls_x509_crt *crt, const ByteArrayLL_t *certs, int *errNum)
+{
+    OIC_LOG_V(DEBUG, PARSE_CHAIN_TAG, "In %s", __func__);
+    VERIFY_NON_NULL_RET(crt, PARSE_CHAIN_TAG, "Param crt is NULL", -1);
+    VERIFY_NON_NULL_RET(certs, PARSE_CHAIN_TAG, "Param certs is NULL", -1);
+    VERIFY_NON_NULL_RET(errNum, PARSE_CHAIN_TAG, "Param errNum is NULL", -1);
+    VERIFY_NON_NULL_RET(certs->cert, PARSE_CHAIN_TAG, "certs->cert is NULL", -1);
+
+    int count = 0;
+    int ret = 0;
+    *errNum = 0;
+
+    const ByteArrayLL_t *temp = certs;
+    LL_FOREACH(certs, temp)
+    {
+        ret = mbedtls_x509_crt_parse(crt, temp->cert->data, temp->cert->len);
+        if (0 == ret)
+        {
+            count++;
+        }
+        else
+        {
+            (*errNum)++;
+            OIC_LOG_V(ERROR, PARSE_CHAIN_TAG, "mbedtls_x509_crt_parse returned -0x%04x\n", -(ret));
+            return -1;
+        }
+    }
+    OIC_LOG_V(DEBUG, PARSE_CHAIN_TAG, "%s successfully parsed %d certificates", __func__, count);
+    OIC_LOG_V(DEBUG, PARSE_CHAIN_TAG, "Out %s", __func__);
+    return count;
+}
+
+void FreeCertChain(ByteArrayLL_t *certs)
+{
+    ByteArrayLL_t *tmp0 = certs, *tmp1 = NULL, *tmp2 = NULL;
+    LL_FOREACH_SAFE(tmp0, tmp1, tmp2)
+    {
+        LL_DELETE(tmp0, tmp1);
+        if (NULL != tmp1->cert) {
+            if (NULL != tmp1->cert->data)
+            {
+                OICFree(tmp1->cert->data);
+            }
+            OICFree(tmp1->cert);
+        }
+        tmp1 = NULL;
+    }
+}
index c9df6cd..af3bf6e 100644 (file)
@@ -39,6 +39,8 @@
 #include "experimental/byte_array.h"
 #include "octhread.h"
 #include "octimer.h"
+#include "utlist.h"
+#include "parsechain.h"
 
 // headers required for mbed TLS
 #include "mbedtls/platform.h"
@@ -650,57 +652,6 @@ static int RecvCallBack(void * tep, unsigned char * data, size_t dataLen)
     return (int)retLen;
 }
 
-/**
- * Parse chain of X.509 certificates.
- *
- * @param[out] crt     container for X.509 certificates
- * @param[in]  buf     buffer with X.509 certificates. Certificates must be in a single null-terminated
- *                     string, with each certificate in PEM encoding with headers.
- * @param[in]  bufLen  buffer length
- * @param[in]  errNum  number certificates that failed to parse
- *
- * @return  number of successfully parsed certificates or -1 on error
- */
-static int ParseChain(mbedtls_x509_crt * crt, unsigned char * buf, size_t bufLen, int * errNum)
-{
-    int ret;
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
-    VERIFY_NON_NULL_RET(crt, NET_SSL_TAG, "Param crt is NULL", -1);
-    VERIFY_NON_NULL_RET(buf, NET_SSL_TAG, "Param buf is NULL", -1);
-
-    if (NULL != errNum)
-    {
-        *errNum = 0;
-    }
-
-    if ((bufLen >= 2) && (buf[0] == 0x30) && (buf[1] == 0x82))
-    {
-        OIC_LOG_V(ERROR, NET_SSL_TAG, "DER-encoded certificate passed to ParseChain");
-        return -1;
-    }
-
-    ret = mbedtls_x509_crt_parse(crt, buf, bufLen);
-    if (0 > ret)
-    {
-        OIC_LOG_V(ERROR, NET_SSL_TAG, "mbedtls_x509_crt_parse failed: -0x%04x", -(ret));
-        return -1;
-    }
-
-    if (NULL != errNum)
-    {
-        *errNum = ret;
-    }
-
-    ret = 0;
-    for (const mbedtls_x509_crt *cur = crt; cur != NULL; cur = cur->next)
-    {
-        ret++;
-    }
-
-    OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
-    return ret;
-}
-
 /**
  * Deinit Pki Info
  *
@@ -717,9 +668,9 @@ static void DeInitPkixInfo(PkiInfo_t * inf)
         return;
     }
 
-    DEINIT_BYTE_ARRAY(inf->crt);
+    FreeCertChain(&(inf->crt));
     DEINIT_BYTE_ARRAY(inf->key);
-    DEINIT_BYTE_ARRAY(inf->ca);
+    FreeCertChain(&(inf->ca));
     DEINIT_BYTE_ARRAY(inf->crl);
 
     OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
@@ -732,9 +683,9 @@ static int InitPKIX(CATransportAdapter_t adapter)
     VERIFY_NON_NULL_RET(g_getPkixInfoCallback, NET_SSL_TAG, "PKIX info callback is NULL", -1);
     // load pk key, cert, trust chain and crl
     PkiInfo_t pkiInfo = {
+        CERT_CHAIN_INITIALIZER,
         BYTE_ARRAY_INITIALIZER,
-        BYTE_ARRAY_INITIALIZER,
-        BYTE_ARRAY_INITIALIZER,
+        CERT_CHAIN_INITIALIZER,
         BYTE_ARRAY_INITIALIZER
     };
 
@@ -742,7 +693,6 @@ static int InitPKIX(CATransportAdapter_t adapter)
     {
         g_getPkixInfoCallback(&pkiInfo);
     }
-
     VERIFY_NON_NULL_RET(g_caSslContext, NET_SSL_TAG, "SSL Context is NULL", -1);
 
     mbedtls_x509_crt_free(&g_caSslContext->ca);
@@ -754,7 +704,6 @@ static int InitPKIX(CATransportAdapter_t adapter)
     mbedtls_x509_crt_init(&g_caSslContext->crt);
     mbedtls_pk_init(&g_caSslContext->pkey);
     mbedtls_x509_crl_init(&g_caSslContext->crl);
-
     mbedtls_ssl_config * serverConf = (adapter == CA_ADAPTER_IP ||
                                    adapter == CA_ADAPTER_GATT_BTLE ?
                                    &g_caSslContext->serverDtlsConf : &g_caSslContext->serverTlsConf);
@@ -764,7 +713,7 @@ static int InitPKIX(CATransportAdapter_t adapter)
     // optional
     int ret;
     int errNum;
-    int count = ParseChain(&g_caSslContext->crt, pkiInfo.crt.data, pkiInfo.crt.len, &errNum);
+    int count = ParseChain(&g_caSslContext->crt, &(pkiInfo.crt), &errNum);
     if (0 >= count)
     {
         OIC_LOG(WARNING, NET_SSL_TAG, "Own certificate chain parsing error");
@@ -826,7 +775,7 @@ static int InitPKIX(CATransportAdapter_t adapter)
     }
 
     required:
-    count = ParseChain(&g_caSslContext->ca, pkiInfo.ca.data, pkiInfo.ca.len, &errNum);
+    count = ParseChain(&g_caSslContext->ca, &(pkiInfo.ca), &errNum);
     if(0 >= count)
     {
         OIC_LOG(ERROR, NET_SSL_TAG, "CA chain parsing error");
index 1f741f0..afc6195 100644 (file)
@@ -81,7 +81,7 @@ void adapter_handler(CATransportAdapter_t /*adapter*/,
 {
 }
 
-void connection_handler(const CAEndpoint_t * /*endpoint*/, 
+void connection_handler(const CAEndpoint_t * /*endpoint*/,
                         bool /*connected*/)
 {
 }
@@ -199,12 +199,14 @@ void provide_x509_cert_and_key(PkiInfo_t* inf)
 {
     /* PEM data must end in newline and be null terminated for IoTivity */
 
-    inf->crt.data = (uint8_t*) our_cert;
-    inf->crt.len = strlen(our_cert) + 1;
+    inf->crt.cert->data = (uint8_t*) our_cert;
+    inf->crt.cert->len = strlen(our_cert) + 1;
+    inf->crt.next = NULL;
     inf->key.data = (uint8_t*) our_key;
     inf->key.len = strlen(our_key) + 1;
-    inf->ca.data = (uint8_t*) our_ca;
-    inf->ca.len = strlen(our_ca) + 1;
+    inf->ca.cert->data = (uint8_t*) our_ca;
+    inf->ca.cert->len = strlen(our_ca) + 1;
+    inf->ca.next = NULL;
 
     // CRL not provided
     inf->crl.data = NULL;
@@ -222,11 +224,11 @@ void provide_supported_credential_types(bool* list, const char* /*deviceId*/)
 {
     list[1] = true;
     /*
-     * Note: there is a default implementation of this in credresource.c, exposed by 
-     * pkix_interface.h, called InitManufacturerCipherSuiteList.  If the cred resource 
-     * has a credential of the required type, it updates list accordingly. 
+     * Note: there is a default implementation of this in credresource.c, exposed by
+     * pkix_interface.h, called InitManufacturerCipherSuiteList.  If the cred resource
+     * has a credential of the required type, it updates list accordingly.
      *
-     * In a separate test, we could use the cred resource and APIs (credresource.h). 
+     * In a separate test, we could use the cred resource and APIs (credresource.h).
      */
     return;
 }
@@ -365,9 +367,9 @@ TEST_F(CATests, DISABLED_PkiTest)
 {
     // @todo: this test is disabled for now, it crashes with an invalid write. Cert data
     // provided by the provide_x509_cert_and_key is stored as const char, but ParseChain()
-    // (in ca_adapter_net_ssl.c) writes to it while reading.  We could change the test to 
+    // (in ca_adapter_net_ssl.c) writes to it while reading.  We could change the test to
     // provide data on the heap, but the CA stack should not be changing data provided to it
-    // by callbacks. 
+    // by callbacks.
 
     const char* local_addr = "127.0.0.1";
     uint16_t local_port = 5503;
@@ -391,7 +393,7 @@ TEST_F(CATests, DISABLED_PkiTest)
 
     // Register a working callback to provide the keys, expect success.
     EXPECT_EQ(CA_STATUS_OK, CAregisterPkixInfoHandler(provide_x509_cert_and_key));
-    EXPECT_EQ(CA_STATUS_OK, CAInitiateHandshake(serverAddr)); 
+    EXPECT_EQ(CA_STATUS_OK, CAInitiateHandshake(serverAddr));
 
     CADestroyEndpoint(serverAddr);
 }
index bbf252e..2c09541 100644 (file)
  *
  * *************************/
 
-// Data blob contains 7 certificates in PEM and DER encoding
-unsigned char certChain[] = {
-    // PEM encoded certificate
+// 10 certificates in PEM and DER encoding
+unsigned char cert0[] = {
     0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
     0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43,
     0x6e, 0x44, 0x43, 0x43, 0x41, 0x6a, 0x2b, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55,
@@ -169,8 +168,9 @@ unsigned char certChain[] = {
     0x61, 0x6b, 0x76, 0x72, 0x4e, 0x4b, 0x66, 0x44, 0x79, 0x2b, 0x4f, 0x4e, 0x43, 0x6e, 0x4e, 0x6e,
     0x43, 0x59, 0x57, 0x4a, 0x37, 0x39, 0x35, 0x4b, 0x49, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45,
     0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
-    0x2d, 0x2d, 0x2d,
-    // PEM encoded certificate
+    0x2d, 0x2d, 0x2d, 0x00
+};
+unsigned char cert1[] = {
     0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
     0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43,
     0x6e, 0x44, 0x43, 0x43, 0x41, 0x6a, 0x2b, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55,
@@ -231,8 +231,9 @@ unsigned char certChain[] = {
     0x61, 0x6b, 0x76, 0x72, 0x4e, 0x4b, 0x66, 0x44, 0x79, 0x2b, 0x4f, 0x4e, 0x43, 0x6e, 0x4e, 0x6e,
     0x43, 0x59, 0x57, 0x4a, 0x37, 0x39, 0x35, 0x4b, 0x49, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45,
     0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
-    0x2d, 0x2d, 0x2d,
-    // PEM encoded certificate
+    0x2d, 0x2d, 0x2d, 0x00
+};
+unsigned char cert2[] = {
     0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
     0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x4d, 0x49, 0x49,
     0x45, 0x67, 0x44, 0x43, 0x43, 0x41, 0x32, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49,
@@ -336,7 +337,9 @@ unsigned char certChain[] = {
     0x56, 0x6e, 0x79, 0x63, 0x6e, 0x4a, 0x73, 0x43, 0x68, 0x65, 0x73, 0x0d, 0x0a, 0x46, 0x4c, 0x78,
     0x6f, 0x6c, 0x77, 0x3d, 0x3d, 0x0d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20,
     0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
-    // PEM encoded certificate
+    0x00
+};
+unsigned char cert3[] = {
     0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
     0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44,
     0x38, 0x44, 0x43, 0x43, 0x41, 0x74, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x44,
@@ -426,8 +429,9 @@ unsigned char certChain[] = {
     0x6c, 0x6d, 0x77, 0x75, 0x39, 0x52, 0x59, 0x32, 0x33, 0x6e, 0x48, 0x4d, 0x41, 0x63, 0x49, 0x53,
     0x0a, 0x77, 0x53, 0x48, 0x47, 0x46, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45,
     0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
-    0x2d, 0x2d, 0x2d,
-    // PEM encoded certificate
+    0x2d, 0x2d, 0x2d, 0x00
+  };
+  unsigned char cert4[] = {
     0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
     0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43,
     0x6e, 0x44, 0x43, 0x43, 0x41, 0x6a, 0x2b, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55,
@@ -488,8 +492,9 @@ unsigned char certChain[] = {
     0x61, 0x6b, 0x76, 0x72, 0x4e, 0x4b, 0x66, 0x44, 0x79, 0x2b, 0x4f, 0x4e, 0x43, 0x6e, 0x4e, 0x6e,
     0x43, 0x59, 0x57, 0x4a, 0x37, 0x39, 0x35, 0x4b, 0x49, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45,
     0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
-    0x2d, 0x2d, 0x2d,
-    // PEM encoded certificate
+    0x2d, 0x2d, 0x2d, 0x00
+  };
+  unsigned char cert5[] = {
     0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
     0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44,
     0x38, 0x44, 0x43, 0x43, 0x41, 0x74, 0x69, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x44,
@@ -579,8 +584,9 @@ unsigned char certChain[] = {
     0x6c, 0x6d, 0x77, 0x75, 0x39, 0x52, 0x59, 0x32, 0x33, 0x6e, 0x48, 0x4d, 0x41, 0x63, 0x49, 0x53,
     0x0a, 0x77, 0x53, 0x48, 0x47, 0x46, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45,
     0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
-    0x2d, 0x2d, 0x2d,
-    // PEM encoded certificate
+    0x2d, 0x2d, 0x2d, 0x00
+  };
+  unsigned char cert6[] = {
     0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
     0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x43,
     0x6e, 0x44, 0x43, 0x43, 0x41, 0x6a, 0x2b, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55,
@@ -641,11 +647,122 @@ unsigned char certChain[] = {
     0x61, 0x6b, 0x76, 0x72, 0x4e, 0x4b, 0x66, 0x44, 0x79, 0x2b, 0x4f, 0x4e, 0x43, 0x6e, 0x4e, 0x6e,
     0x43, 0x59, 0x57, 0x4a, 0x37, 0x39, 0x35, 0x4b, 0x49, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45,
     0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
-    0x2d, 0x2d, 0x2d,
-    // NULL terminator
-    0x00
+    0x2d, 0x2d, 0x2d, 0x00
+};
+unsigned char cert7[] = {
+    0x30, 0x82, 0x02, 0x39, 0x30, 0x82, 0x01, 0xdf, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a,
+    0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x7c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+    0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+    0x09, 0x53, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x74, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+    0x55, 0x04, 0x07, 0x0c, 0x08, 0x53, 0x6f, 0x6d, 0x65, 0x63, 0x69, 0x74, 0x79, 0x31, 0x0b, 0x30,
+    0x09, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x02, 0x42, 0x42, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03,
+    0x55, 0x04, 0x0b, 0x0c, 0x0d, 0x53, 0x65, 0x71, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x50, 0x61,
+    0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x02, 0x6f, 0x62, 0x31,
+    0x14, 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x05,
+    0x6f, 0x62, 0x40, 0x62, 0x62, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x31, 0x35, 0x31,
+    0x33, 0x31, 0x31, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x35, 0x31, 0x32, 0x31, 0x33,
+    0x31, 0x31, 0x31, 0x37, 0x5a, 0x30, 0x81, 0xd4, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+    0x06, 0x13, 0x02, 0x55, 0x41, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x03,
+    0x41, 0x73, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x06, 0x47, 0x6f,
+    0x74, 0x68, 0x61, 0x6d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x02, 0x5a,
+    0x5a, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x42, 0x65, 0x61, 0x6d,
+    0x54, 0x65, 0x61, 0x6d, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+    0x01, 0x09, 0x01, 0x16, 0x0d, 0x72, 0x61, 0x69, 0x6c, 0x40, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63,
+    0x6f, 0x6d, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x29, 0x75, 0x75, 0x69,
+    0x64, 0x3a, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x2d,
+    0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32,
+    0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x0c,
+    0x2b, 0x75, 0x73, 0x65, 0x72, 0x69, 0x64, 0x3a, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37,
+    0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d,
+    0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x30, 0x59, 0x30, 0x13,
+    0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xf7, 0x13, 0x5c, 0x73, 0x72, 0xce, 0x10, 0xe5, 0x09,
+    0x97, 0x9a, 0xf8, 0xf2, 0x70, 0xa6, 0x3d, 0x89, 0xf5, 0xc5, 0xe4, 0x44, 0xe2, 0x4a, 0xb6, 0x61,
+    0xa8, 0x12, 0x8d, 0xb4, 0xdc, 0x2b, 0x47, 0x84, 0x60, 0x0c, 0x25, 0x66, 0xe9, 0xe0, 0xe5, 0xac,
+    0x22, 0xbf, 0x15, 0xdc, 0x71, 0xb1, 0x88, 0x4f, 0x16, 0xbf, 0xc2, 0x77, 0x37, 0x76, 0x3f, 0xe0,
+    0x67, 0xc6, 0x1d, 0x23, 0xfe, 0x7c, 0x8b, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x47, 0xcc, 0x41, 0x8a, 0x27, 0xc7,
+    0xd0, 0xaa, 0xb4, 0xab, 0x85, 0xbf, 0x09, 0x4d, 0x06, 0xd7, 0x7e, 0x0d, 0x39, 0xf9, 0x36, 0xa1,
+    0x3d, 0x96, 0x23, 0xe2, 0x24, 0x64, 0x98, 0x63, 0x21, 0xba, 0x02, 0x21, 0x00, 0xe5, 0x8f, 0x7f,
+    0xf1, 0xa6, 0x82, 0x03, 0x6a, 0x18, 0x7a, 0x54, 0xe7, 0x0e, 0x25, 0x77, 0xd8, 0x46, 0xfa, 0x96,
+    0x8a, 0x7e, 0x14, 0xc4, 0xcb, 0x21, 0x32, 0x3e, 0x89, 0xd9, 0xba, 0x8c, 0x3f
+};
+unsigned char cert8[] = {
+    0x30, 0x82, 0x02, 0x39, 0x30, 0x82, 0x01, 0xdf, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a,
+    0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x7c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+    0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+    0x09, 0x53, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x74, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+    0x55, 0x04, 0x07, 0x0c, 0x08, 0x53, 0x6f, 0x6d, 0x65, 0x63, 0x69, 0x74, 0x79, 0x31, 0x0b, 0x30,
+    0x09, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x02, 0x42, 0x42, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03,
+    0x55, 0x04, 0x0b, 0x0c, 0x0d, 0x53, 0x65, 0x71, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x50, 0x61,
+    0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x02, 0x6f, 0x62, 0x31,
+    0x14, 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x05,
+    0x6f, 0x62, 0x40, 0x62, 0x62, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x31, 0x35, 0x31,
+    0x33, 0x31, 0x31, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x35, 0x31, 0x32, 0x31, 0x33,
+    0x31, 0x31, 0x31, 0x37, 0x5a, 0x30, 0x81, 0xd4, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+    0x06, 0x13, 0x02, 0x55, 0x41, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x03,
+    0x41, 0x73, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x06, 0x47, 0x6f,
+    0x74, 0x68, 0x61, 0x6d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x02, 0x5a,
+    0x5a, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x42, 0x65, 0x61, 0x6d,
+    0x54, 0x65, 0x61, 0x6d, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+    0x01, 0x09, 0x01, 0x16, 0x0d, 0x72, 0x61, 0x69, 0x6c, 0x40, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63,
+    0x6f, 0x6d, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x29, 0x75, 0x75, 0x69,
+    0x64, 0x3a, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x2d,
+    0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32,
+    0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x0c,
+    0x2b, 0x75, 0x73, 0x65, 0x72, 0x69, 0x64, 0x3a, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37,
+    0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d,
+    0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x30, 0x59, 0x30, 0x13,
+    0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xf7, 0x13, 0x5c, 0x73, 0x72, 0xce, 0x10, 0xe5, 0x09,
+    0x97, 0x9a, 0xf8, 0xf2, 0x70, 0xa6, 0x3d, 0x89, 0xf5, 0xc5, 0xe4, 0x44, 0xe2, 0x4a, 0xb6, 0x61,
+    0xa8, 0x12, 0x8d, 0xb4, 0xdc, 0x2b, 0x47, 0x84, 0x60, 0x0c, 0x25, 0x66, 0xe9, 0xe0, 0xe5, 0xac,
+    0x22, 0xbf, 0x15, 0xdc, 0x71, 0xb1, 0x88, 0x4f, 0x16, 0xbf, 0xc2, 0x77, 0x37, 0x76, 0x3f, 0xe0,
+    0x67, 0xc6, 0x1d, 0x23, 0xfe, 0x7c, 0x8b, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x47, 0xcc, 0x41, 0x8a, 0x27, 0xc7,
+    0xd0, 0xaa, 0xb4, 0xab, 0x85, 0xbf, 0x09, 0x4d, 0x06, 0xd7, 0x7e, 0x0d, 0x39, 0xf9, 0x36, 0xa1,
+    0x3d, 0x96, 0x23, 0xe2, 0x24, 0x64, 0x98, 0x63, 0x21, 0xba, 0x02, 0x21, 0x00, 0xe5, 0x8f, 0x7f,
+    0xf1, 0xa6, 0x82, 0x03, 0x6a, 0x18, 0x7a, 0x54, 0xe7, 0x0e, 0x25, 0x77, 0xd8, 0x46, 0xfa, 0x96,
+    0x8a, 0x7e, 0x14, 0xc4, 0xcb, 0x21, 0x32, 0x3e, 0x89, 0xd9, 0xba, 0x8c, 0x3f
+};
+unsigned char cert9[] = {
+    0x30, 0x82, 0x02, 0x39, 0x30, 0x82, 0x01, 0xdf, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a,
+    0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x7c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+    0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+    0x09, 0x53, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x74, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+    0x55, 0x04, 0x07, 0x0c, 0x08, 0x53, 0x6f, 0x6d, 0x65, 0x63, 0x69, 0x74, 0x79, 0x31, 0x0b, 0x30,
+    0x09, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x02, 0x42, 0x42, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03,
+    0x55, 0x04, 0x0b, 0x0c, 0x0d, 0x53, 0x65, 0x71, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x50, 0x61,
+    0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x02, 0x6f, 0x62, 0x31,
+    0x14, 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x05,
+    0x6f, 0x62, 0x40, 0x62, 0x62, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x38, 0x31, 0x35, 0x31,
+    0x33, 0x31, 0x31, 0x31, 0x37, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x30, 0x35, 0x31, 0x32, 0x31, 0x33,
+    0x31, 0x31, 0x31, 0x37, 0x5a, 0x30, 0x81, 0xd4, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+    0x06, 0x13, 0x02, 0x55, 0x41, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x03,
+    0x41, 0x73, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x06, 0x47, 0x6f,
+    0x74, 0x68, 0x61, 0x6d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x02, 0x5a,
+    0x5a, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x42, 0x65, 0x61, 0x6d,
+    0x54, 0x65, 0x61, 0x6d, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+    0x01, 0x09, 0x01, 0x16, 0x0d, 0x72, 0x61, 0x69, 0x6c, 0x40, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63,
+    0x6f, 0x6d, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x29, 0x75, 0x75, 0x69,
+    0x64, 0x3a, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x2d,
+    0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x2d, 0x33, 0x32, 0x33, 0x32, 0x33, 0x32,
+    0x33, 0x32, 0x33, 0x32, 0x33, 0x32, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x0c,
+    0x2b, 0x75, 0x73, 0x65, 0x72, 0x69, 0x64, 0x3a, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37,
+    0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d, 0x36, 0x37, 0x36, 0x37, 0x2d,
+    0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x30, 0x59, 0x30, 0x13,
+    0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xf7, 0x13, 0x5c, 0x73, 0x72, 0xce, 0x10, 0xe5, 0x09,
+    0x97, 0x9a, 0xf8, 0xf2, 0x70, 0xa6, 0x3d, 0x89, 0xf5, 0xc5, 0xe4, 0x44, 0xe2, 0x4a, 0xb6, 0x61,
+    0xa8, 0x12, 0x8d, 0xb4, 0xdc, 0x2b, 0x47, 0x84, 0x60, 0x0c, 0x25, 0x66, 0xe9, 0xe0, 0xe5, 0xac,
+    0x22, 0xbf, 0x15, 0xdc, 0x71, 0xb1, 0x88, 0x4f, 0x16, 0xbf, 0xc2, 0x77, 0x37, 0x76, 0x3f, 0xe0,
+    0x67, 0xc6, 0x1d, 0x23, 0xfe, 0x7c, 0x8b, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x47, 0xcc, 0x41, 0x8a, 0x27, 0xc7,
+    0xd0, 0xaa, 0xb4, 0xab, 0x85, 0xbf, 0x09, 0x4d, 0x06, 0xd7, 0x7e, 0x0d, 0x39, 0xf9, 0x36, 0xa1,
+    0x3d, 0x96, 0x23, 0xe2, 0x24, 0x64, 0x98, 0x63, 0x21, 0xba, 0x02, 0x21, 0x00, 0xe5, 0x8f, 0x7f,
+    0xf1, 0xa6, 0x82, 0x03, 0x6a, 0x18, 0x7a, 0x54, 0xe7, 0x0e, 0x25, 0x77, 0xd8, 0x46, 0xfa, 0x96,
+    0x8a, 0x7e, 0x14, 0xc4, 0xcb, 0x21, 0x32, 0x3e, 0x89, 0xd9, 0xba, 0x8c, 0x3f
 };
-int certChainLen = sizeof(certChain);
 
 unsigned char serverCert[] =
     "-----BEGIN CERTIFICATE-----\n"
@@ -677,7 +794,7 @@ unsigned char serverPrivateKey[] = {
 
 int serverPrivateKeyLen = sizeof(serverPrivateKey);
 
-unsigned char caCert[] = 
+unsigned char caCert[] =
     "-----BEGIN CERTIFICATE-----\n"
     "MIICPjCCAeWgAwIBAgIJAIenaAF86fjwMAoGCCqGSM49BAMCMHwxCzAJBgNVBAYT\n"
     "AlVTMRIwEAYDVQQIDAlTb21lc3RhdGUxETAPBgNVBAcMCFNvbWVjaXR5MQswCQYD\n"
@@ -918,22 +1035,26 @@ static void PacketReceive(unsigned char *data, int * datalen)
 
 static void infoCallback_that_loads_x509(PkiInfo_t * inf)
 {
-    inf->crt.len = sizeof(serverCert);
-    inf->crt.data = (uint8_t*)OICMalloc(inf->crt.len);
-    ASSERT_TRUE(inf->crt.data != NULL);
-    memcpy(inf->crt.data, serverCert, inf->crt.len);
+    ByteArray_t * ca = (ByteArray_t *)OICMalloc(sizeof(ByteArray_t));
+    ca->data = (uint8_t *)OICMalloc(sizeof(serverCert));
+    ASSERT_TRUE(ca->data != NULL);
+    memcpy(ca->data, serverCert, sizeof(serverCert));
+    ca->len = sizeof(serverCert);
 
-    inf->key.len = sizeof(serverPrivateKey);
-    inf->key.data = (uint8_t*)OICMalloc(inf->key.len);
-    ASSERT_TRUE(inf->key.data != NULL);
-    memcpy(inf->key.data, serverPrivateKey, inf->key.len);
+    ByteArray_t * own = (ByteArray_t *)OICMalloc(sizeof(ByteArray_t));
+    own->data = (uint8_t *)OICMalloc(sizeof(caCert));
+    ASSERT_TRUE(own->data != NULL);
+    memcpy(own->data, caCert, sizeof(caCert));
+    own->len = sizeof(caCert);
 
+    inf->crt.cert = ca;
+    inf->crt.next = NULL;
 
-    inf->ca.len = sizeof(caCert);
-    inf->ca.data = (uint8_t*)OICMalloc(inf->ca.len);
-    ASSERT_TRUE(inf->ca.data != NULL);
-    memcpy(inf->ca.data, caCert, inf->ca.len);
+    inf->ca.cert = own;
+    inf->ca.next = NULL;
 
+    inf->key.data = (uint8_t*)serverPrivateKey;
+    inf->key.len = sizeof(serverPrivateKey);
 
     inf->crl.data = NULL;
     inf->crl.len = 0;
@@ -1393,7 +1514,7 @@ exit:
     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_SSL_TLS_C) || \
     !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_NET_C) ||     \
     !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_CTR_DRBG_C) ||    \
-    !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) 
+    !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO)
 
 /* int */void * server( void )
 {
@@ -3031,14 +3152,56 @@ TEST(TLSAdapter, Test_11)
 
 TEST(TLSAdapter, Test_ParseChain)
 {
-    int errNum;
     mbedtls_x509_crt crt;
     mbedtls_x509_crt_init(&crt);
-    size_t ret = ParseChain(&crt, certChain, certChainLen, &errNum);
+
+    ByteArray_t certs[10];
+    certs[0].data = cert0;
+    certs[0].len = sizeof(cert0);
+    certs[1].data = cert1;
+    certs[1].len = sizeof(cert1);
+    certs[2].data = cert2;
+    certs[2].len = sizeof(cert2);
+    certs[3].data = cert3;
+    certs[3].len = sizeof(cert3);
+    certs[4].data = cert4;
+    certs[4].len = sizeof(cert4);
+    certs[5].data = cert5;
+    certs[5].len = sizeof(cert5);
+    certs[6].data = cert6;
+    certs[6].len = sizeof(cert6);
+    certs[7].data = cert7;
+    certs[7].len = sizeof(cert7);
+    certs[8].data = cert8;
+    certs[8].len = sizeof(cert8);
+    certs[9].data = cert9;
+    certs[9].len = sizeof(cert9);
+
+    ByteArrayLL_t * certChain = (ByteArrayLL_t *) OICMalloc (sizeof(ByteArrayLL_t));
+    certChain->cert = (ByteArray_t*) OICMalloc (sizeof(ByteArray_t));
+    certChain->cert->data = (unsigned char *) OICMalloc (certs[0].len);
+    memcpy(certChain->cert->data, certs[0].data, certs[0].len);
+    certChain->cert->len = certs[0].len;
+    certChain->next = NULL;
+
+    ByteArrayLL_t * tmp = NULL;
+    for (int i = 1; i < 10; i++)
+    {
+        tmp = (ByteArrayLL_t *) OICMalloc (sizeof(ByteArrayLL_t));
+        tmp->cert = (ByteArray_t*) OICMalloc (sizeof(ByteArray_t));
+        tmp->cert->data = (unsigned char *) OICMalloc (certs[i].len);
+        memcpy(tmp->cert->data, certs[i].data, certs[i].len);
+        tmp->cert->len = certs[i].len;
+        LL_APPEND(certChain, tmp);
+    }
+
+    int errNum;
+    int ret = ParseChain(&crt, certChain, &errNum);
+
+    FreeCertChain(certChain);
     mbedtls_x509_crt_free(&crt);
 
-    EXPECT_EQ(7u, ret);
-    EXPECT_EQ(0, errNum);
+    EXPECT_EQ(10, ret + errNum);
 }
 
 TEST(TLSAdapter, TestCertsValid)
index 0313024..f2a4cea 100644 (file)
@@ -23,8 +23,9 @@
 
 #if defined(__WITH_TLS__) || defined(__WITH_DTLS__)
 
-#include "mbedtls/pk.h"
+#include <mbedtls/pk.h>
 #include <time.h>
+#include "casecurityinterface.h"
 
 /**
  * Internal certificate request function; used by CSR resource handler
@@ -40,7 +41,7 @@
  *
  * @return 0 on success, <0 on failure
  */
-int OCInternalCSRRequest(const char *subject, mbedtls_pk_context *keyPair, 
+int OCInternalCSRRequest(const char *subject, mbedtls_pk_context *keyPair,
                          OicEncodingType_t encoding, OCByteString *csr);
 
 /**
@@ -65,7 +66,7 @@ int OCInternalGenerateKeyPair(mbedtls_pk_context *keyPair);
  * 3. It contains at least one Subject Alternative Name extension that validly encodes a role.
  *
  * It does NOT validate the cryptographic signature nor check its time validity.
- * These checks should be done when the certificate is being used as part of an access control check, 
+ * These checks should be done when the certificate is being used as part of an access control check,
  * as that is when the time validity check should be made, and when trusted CAs are known.
  *
  * @param[in] buf           Buffer containing certificate as a PEM string
@@ -86,7 +87,7 @@ OCStackResult OCInternalIsValidRoleCertificate(const uint8_t *buf, size_t bufLen
 /**
  * Determine if a buffer contains a valid chain of certificates. This is intended to verify
  * one or more intermediate CA certificates are valid.
- * 
+ *
  * This only checks that they are valid X.509 structures; no verification of the cryptographic
  * signature of time-validity is performed. These should be done at point of use.
  *
@@ -110,8 +111,7 @@ OCStackResult OCInternalIsValidCertChain(const uint8_t *buf, size_t bufLen);
  * parameters.
  *
  * @param[in] certificateChain      OicSecKey_t containing one or more certificates
- * @param[in] trustedCaCerts        PEM string containing the trusted CAs certificates
- * @param[in] trustedCaCertsLength  Length of trustedCaCerts (including terminating NULL)
+ * @param[in] trustedCaCerts        Trusted CAs certificates chain container
  * @param[out] roles                Pointer to receive array of OicSecRole_t objects listing roles
  *                                  Caller must call OICFree to release this memory when finished
  * @param[out] rolesLength          Length of returned roles array
@@ -121,7 +121,8 @@ OCStackResult OCInternalIsValidCertChain(const uint8_t *buf, size_t bufLen);
  *         OC_STACK_INVALID_PARAM if the certificate is not valid.
  *         OC_STACK_NO_MEMORY or OC_STACK_ERROR if some other error arose during validation.
  */
-OCStackResult OCInternalVerifyRoleCertificate(const OicSecKey_t *certificateChain, const uint8_t *trustedCaCerts,
-                                              size_t trustedCaCertsLength, OicSecRole_t **roles,
-                                              size_t *rolesLength, struct tm *notValidAfter);
+OCStackResult OCInternalVerifyRoleCertificate(const OicSecKey_t *certificateChain,
+                                              const ByteArrayLL_t *trustedCaCerts,
+                                              OicSecRole_t **roles, size_t *rolesLength,
+                                              struct tm *notValidAfter);
 #endif
index a862588..9d78bea 100644 (file)
@@ -278,7 +278,7 @@ OCStackResult GetCredRownerId(OicUuid_t *rowneruuid);
  * @param[out] crt certificates to be filled.
  * @param[in] usage credential usage string.
  */
-OCStackResult GetPemCaCert(ByteArray_t * crt, const char * usage);
+void GetCaCert(ByteArrayLL_t * crt, const char * usage);
 
 /**
  * Get a list of all role certificates. Used when asserting roles.
@@ -297,7 +297,7 @@ OCStackResult GetAllRoleCerts(RoleCertChain_t** roleCerts);
  * @param[out] crt certificate chain to be filled.
  * @param[in] usage credential usage string.
  */
-void GetPemOwnCert(ByteArray_t * crt, const char * usage);
+void GetOwnCert(ByteArrayLL_t * crt, const char * usage);
 /**
  * Used by mbedTLS to retrieve own private key
  *
index 8b18e29..916d5df 100644 (file)
@@ -29,6 +29,7 @@
 #include "cacommon.h"
 #include "experimental/ocrandom.h"
 #include "cacommonutil.h"
+#include "parsechain.h"
 
 #include "ocpayload.h"
 #include "experimental/payload_logging.h"
@@ -440,9 +441,10 @@ static const mbedtls_x509_crt_profile s_certProfile = {
     0                                                   /* RSA minimum key length - not used because we only use EC key pairs */
 };
 
-OCStackResult OCInternalVerifyRoleCertificate(const OicSecKey_t *certificateChain, const uint8_t *trustedCaCerts,
-                                              size_t trustedCaCertsLength, OicSecRole_t **roles,
-                                              size_t *rolesLength, struct tm *notValidAfter)
+OCStackResult OCInternalVerifyRoleCertificate(const OicSecKey_t *certificateChain,
+                                              const ByteArrayLL_t *trustedCaCerts,
+                                              OicSecRole_t **roles, size_t *rolesLength,
+                                              struct tm *notValidAfter)
 {
     bool freeData = false;
     uint8_t *data = certificateChain->data;
@@ -502,10 +504,17 @@ OCStackResult OCInternalVerifyRoleCertificate(const OicSecKey_t *certificateChai
         goto exit;
     }
 
-    mbedRet = mbedtls_x509_crt_parse(&trustedCas, trustedCaCerts, trustedCaCertsLength);
-    if (0 > mbedRet)
+    int errNum;
+    int count = ParseChain(&trustedCas, trustedCaCerts, &errNum);
+    if (0 >= count)
+    {
+        OIC_LOG(WARNING, TAG, "Could not parse trusted CA certs");
+        res = OC_STACK_ERROR;
+        goto exit;
+    }
+    if (0 != errNum)
     {
-        OIC_LOG_V(ERROR, TAG, "Could not parse trusted CA certs: %d", mbedRet);
+        OIC_LOG_V(WARNING, TAG, "Trusted CA certs parsing error: %d certs failed to parse", errNum);
         res = OC_STACK_ERROR;
         goto exit;
     }
@@ -640,4 +649,4 @@ exit:
     OIC_LOG_V(DEBUG, TAG, "OCInternalVerifyRoleCertificate out: %d", res);
 
     return res;
-}
\ No newline at end of file
+}
index b30ddc3..8cadda2 100644 (file)
@@ -73,6 +73,9 @@
 #include <mbedtls/base64.h>
 #include <mbedtls/x509_crt.h>
 #include <mbedtls/pem.h>
+#include "parsechain.h"
+static const char PEM_BEGIN_CRT[] = "-----BEGIN CERTIFICATE-----";
+static const char PEM_END_CRT[] = "-----END CERTIFICATE-----";
 #endif
 
 #define TAG  "OIC_SRM_CREDL"
@@ -3263,6 +3266,8 @@ exit:
     return ret;
 }
 
+#ifndef NDEBUG
+
 /* Caller must call OICFree on *pem when finished. */
 static int ConvertDerCertToPem(const uint8_t* der, size_t derLen, uint8_t** pem)
 {
@@ -3309,6 +3314,118 @@ static int ConvertDerCertToPem(const uint8_t* der, size_t derLen, uint8_t** pem)
     return 0;
 }
 
+#endif // NDEBUG
+
+OCStackResult FillCertChain(ByteArrayLL_t * chain, OicSecCred_t * temp)
+{
+    int pemCertNum = 0;
+    uint8_t *tempPubData = temp->publicData.data;
+    while (tempPubData)
+    {
+        tempPubData = (uint8_t *) strstr((const char *) tempPubData, PEM_BEGIN_CRT);
+        if (NULL != tempPubData)
+        {
+            if ((size_t)(tempPubData - temp->publicData.data + sizeof(PEM_BEGIN_CRT) - 1) > temp->publicData.len)
+            {
+                break;
+            }
+            pemCertNum++;
+            tempPubData += sizeof(PEM_BEGIN_CRT) - 1;
+        }
+    }
+
+    if (pemCertNum > 0)  // PEM or BASE64 certificates processing
+    {
+        uint8_t * begin = (uint8_t *) strstr((const char *)temp->publicData.data, PEM_BEGIN_CRT);
+        uint8_t * end = (uint8_t *) strstr((const char *)begin, PEM_END_CRT);
+        for (int i = 0; i < pemCertNum; i++)
+        {
+            if (NULL != begin && NULL != end)
+            {
+                ByteArray_t * item = (ByteArray_t *) OICMalloc (sizeof(ByteArray_t));
+                if (NULL == item)
+                {
+                    OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+                    return OC_STACK_ERROR;
+                }
+                item->len = end - begin + sizeof(PEM_END_CRT);
+                item->data = (uint8_t *) OICMalloc (item->len);
+                if (NULL == item->data)
+                {
+                    OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+                    OICFree(item);
+                    return OC_STACK_ERROR;
+                }
+                memcpy(item->data, begin, item->len - 1);
+                item->data[item->len - 1] = '\0'; // adding null terminator at the end of the cert (required by mbedtls_x509_crt_parse)
+                if (chain->cert == NULL)
+                {
+                    chain->cert = item;
+                }
+                else
+                {
+                    ByteArrayLL_t * tmp = (ByteArrayLL_t *) OICMalloc (sizeof(ByteArrayLL_t));
+                    if (NULL == tmp)
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+                        OICFree(item->data);
+                        OICFree(item);
+                        return OC_STACK_ERROR;
+                    }
+                    tmp->cert = item;
+                    LL_APPEND(chain, tmp);
+                }
+            }
+            begin = (uint8_t *) strstr((const char *)end, PEM_BEGIN_CRT);
+            if (NULL == begin)
+            {
+                break;
+            }
+            end = (uint8_t *) strstr((const char *)begin, PEM_END_CRT);
+            if (NULL == end)
+            {
+                break;
+            }
+        }
+    }
+    else // DER certificates processing
+    {
+        ByteArray_t * item = (ByteArray_t *) OICMalloc (sizeof(ByteArray_t));
+        if (NULL == item)
+        {
+            OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+            return OC_STACK_ERROR;
+        }
+        item->data = (uint8_t *) OICMalloc (temp->publicData.len);
+        if (NULL == item->data)
+        {
+            OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+            OICFree(item);
+            return OC_STACK_ERROR;
+        }
+        memcpy(item->data, temp->publicData.data, temp->publicData.len);
+        item->len = temp->publicData.len;
+        if (chain->cert == NULL)
+        {
+            chain->cert = item;
+        }
+        else
+        {
+            ByteArrayLL_t * tmp = (ByteArrayLL_t *) OICMalloc (sizeof(ByteArrayLL_t));
+            if (NULL == tmp)
+            {
+                OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+                OICFree(item->data);
+                OICFree(item);
+                return OC_STACK_ERROR;
+            }
+            tmp->cert = item;
+            LL_APPEND(chain, tmp);
+        }
+    }
+    return OC_STACK_OK;
+}
+
 
 void GetIdentityHandler(UuidContext_t* ctx, unsigned char* crt, size_t crtLen)
 {
@@ -3584,27 +3701,14 @@ void LogCurrrentCredResource(void) {
 #endif
 }
 
-static OCStackResult GetCaCert(ByteArray_t * crt, const char * usage, OicEncodingType_t desiredEncoding)
+void GetCaCert(ByteArrayLL_t * chain, const char * usage)
 {
     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
-    if (NULL == crt || NULL == usage)
+    if (NULL == chain || NULL == usage)
     {
         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    switch (desiredEncoding)
-    {
-    case OIC_ENCODING_PEM:
-    case OIC_ENCODING_DER:
-    case OIC_ENCODING_BASE64:
-        break;
-    default:
-        OIC_LOG_V(ERROR, TAG, "%s: Unsupported encoding %d", __func__, desiredEncoding);
-        return OC_STACK_INVALID_PARAM;
+        return;
     }
-
-    crt->len = 0;
     OicSecCred_t* temp = NULL;
 
     LL_FOREACH(gCred, temp)
@@ -3613,7 +3717,6 @@ static OCStackResult GetCaCert(ByteArray_t * crt, const char * usage, OicEncodin
             (temp->credUsage != NULL) &&
             (0 == strcmp(temp->credUsage, usage)) && (false == temp->optionalData.revstat))
         {
-
             if ((OIC_ENCODING_BASE64 != temp->publicData.encoding) &&
                 (OIC_ENCODING_PEM != temp->publicData.encoding) &&
                 (OIC_ENCODING_DER != temp->publicData.encoding))
@@ -3621,124 +3724,26 @@ static OCStackResult GetCaCert(ByteArray_t * crt, const char * usage, OicEncodin
                 OIC_LOG_V(WARNING, TAG, "%s: Unknown encoding type", __func__);
                 continue;
             }
-
-            if (OIC_ENCODING_DER == desiredEncoding)
-            {
-                if ((OIC_ENCODING_BASE64 == temp->publicData.encoding) ||
-                    (OIC_ENCODING_PEM == temp->publicData.encoding))
-                {
-                    uint8_t* buf = NULL;
-                    size_t outSize = 0;
-                    int ret = ConvertPemCertToDer((const char*)temp->publicData.data, temp->publicData.len, &buf, &outSize);
-                    if (0 > ret)
-                    {
-                        OIC_LOG(ERROR, TAG, "Could not convert PEM cert to DER");
-                        return OC_STACK_ERROR;
-                    }
-
-                    uint8_t *savePtr = crt->data;
-                    crt->data = OICRealloc(crt->data, crt->len + outSize);
-                    if (NULL == crt->data)
-                    {
-                        OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
-                        OICFree(savePtr);
-                        OICFree(buf);
-                        return OC_STACK_NO_MEMORY;
-                    }
-                    memcpy(crt->data + crt->len, buf, outSize);
-                    crt->len += outSize;
-                    OICFree(buf);
-                }
-                else
-                {
-                    uint8_t *savePtr = crt->data;
-                    crt->data = OICRealloc(crt->data, crt->len + temp->publicData.len);
-                    if (NULL == crt->data)
-                    {
-                        OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
-                        OICFree(savePtr);
-                        return OC_STACK_NO_MEMORY;
-                    }
-                    memcpy(crt->data + crt->len, temp->publicData.data, temp->publicData.len);
-                    crt->len += temp->publicData.len;
-                }
-                OIC_LOG_V(DEBUG, TAG, "%s found", usage);
-            }
-            else
+            OIC_LOG_V(DEBUG, TAG, "%s found", usage);
+            if (OC_STACK_OK != FillCertChain(chain, temp))
             {
-                /* PEM/Base64 */
-                uint8_t *pem = NULL;
-                size_t pemLen = 0;
-                if ((OIC_ENCODING_BASE64 == temp->publicData.encoding) ||
-                    (OIC_ENCODING_PEM == temp->publicData.encoding))
-                {
-                    pem = temp->publicData.data;
-                    pemLen = temp->publicData.len;
-                }
-                else
-                {
-                    int ret = ConvertDerCertToPem(temp->publicData.data, temp->publicData.len, &pem);
-                    if (0 > ret)
-                    {
-                        OIC_LOG_V(ERROR, TAG, "Failed converting DER cert to PEM: %d", ret);
-                        return OC_STACK_ERROR;
-                    }
-                    pemLen = strlen((char *)pem) + 1;
-                }
-
-                uint8_t *oldData = crt->data;
-                crt->data = OICRealloc(crt->data, crt->len + pemLen);
-                if (NULL == crt->data)
-                {
-                    OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
-                    OICFree(oldData);
-                    return OC_STACK_NO_MEMORY;
-                }
-                memcpy(crt->data + crt->len, pem, pemLen);
-                crt->len += pemLen;
+                FreeCertChain(chain);
+                OIC_LOG_V(ERROR, TAG, "%s: Failed to parse certificate chain", __func__);
             }
         }
     }
-    if(0 == crt->len)
+    if(NULL == chain->cert)
     {
         OIC_LOG_V(WARNING, TAG, "%s not found", usage);
-        return OC_STACK_NO_RESOURCE;
-    }
-
-    if (OIC_ENCODING_PEM == desiredEncoding)
-    {
-        /* mbedtls_x509_crt_parse requires a null terminator to determine that the format is PEM */
-        size_t crtLength = crt->len;
-        bool addNull = (crt->data[crtLength - 1] != 0);
-
-        if (addNull)
-        {
-            OIC_LOG_V(DEBUG, TAG, "%s: adding null terminator at the end of the cert", __func__);
-            uint8_t *oldData = crt->data;
-            crt->data = OICRealloc(crt->data, crtLength + 1);
-            if (NULL == crt->data)
-            {
-                OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
-                OICFree(oldData);
-                return OC_STACK_NO_MEMORY;
-            }
-            crt->data[crtLength] = 0;
-            crt->len = crtLength + 1;
-        }
     }
 
 #ifndef NDEBUG
     OIC_LOG(DEBUG, TAG_LOG, "==== Cert being returned ===================================");
-    LogCert ( crt->data, crt->len, desiredEncoding, TAG_LOG );
+    LogCert ( chain->cert->data, chain->cert->len, OIC_ENCODING_PEM, TAG_LOG );
     OIC_LOG(DEBUG, TAG_LOG, "============================================================");
 #endif
     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
-    return OC_STACK_OK;
-}
-
-OCStackResult GetPemCaCert(ByteArray_t * crt, const char * usage)
-{
-    return GetCaCert(crt, usage, OIC_ENCODING_PEM);
+    return;
 }
 
 static int cloneSecKey(OicSecKey_t * dst, OicSecKey_t * src)
@@ -3815,118 +3820,37 @@ error:
     return OC_STACK_ERROR;
 }
 
-void GetPemOwnCert(ByteArray_t * crt, const char * usage)
+void GetOwnCert(ByteArrayLL_t * chain, const char * usage)
 {
     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
-    if (NULL == crt || NULL == usage)
+    if (NULL == chain || NULL == usage)
     {
         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
         return;
     }
-    crt->len = 0;
     OicSecCred_t * temp = NULL;
     LL_FOREACH(gCred, temp)
     {
         if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
-            temp->credUsage != NULL &&
             0 == strcmp(temp->credUsage, usage))
         {
-            uint8_t *p = NULL;
-            int mbedRet = 0;
-            uint8_t *pem = NULL;
-            size_t pemLen = 0;
-            bool mustFreePem = false;
-            bool mustAddNull = true;
-
-            switch (temp->publicData.encoding)
-            {
-            case OIC_ENCODING_DER:
-            case OIC_ENCODING_RAW:
-                mbedRet = ConvertDerCertToPem(temp->publicData.data, temp->publicData.len, &pem);
-                if (0 > mbedRet)
-                {
-                    OIC_LOG_V(ERROR, TAG, "Failed to ConvertDerCertToPem: %d", mbedRet);
-                    return;
-                }
-                mustFreePem = true;
-                mustAddNull = false; /* mbedTLS always NULL-terminates. */
-                pemLen = strlen((char *)pem) + 1;
-                break;
-
-            case OIC_ENCODING_PEM:
-            case OIC_ENCODING_BASE64:
-                pem = temp->publicData.data;
-                pemLen = temp->publicData.len;
-
-                /* Make sure the buffer has a terminating NULL. If not, make sure we add one later. */
-                for (size_t i = pemLen - 1; i > 0; i--)
-                {
-                    if ('\0' == (char)pem[i])
-                    {
-                        mustAddNull = false;
-                        break;
-                    }
-                }
-                break;
-
-            default:
-                OIC_LOG_V(ERROR, TAG, "Unsupported encoding %d", temp->publicData.encoding);
-                return;
-            }
-
-            p = crt->data;
-            crt->data = OICRealloc(crt->data, crt->len + pemLen + (mustAddNull ? 1 : 0));
-            if (NULL == crt->data)
-            {
-                OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
-                OICFree(p);
-                if (mustFreePem)
-                {
-                    OICFree(pem);
-                }
-                return;
-            }
-
-            /* If we're appending, subtract one from crt->len below so we overwrite the current terminating
-             * NULL with the beginning of the new data.
-             */
-            if (0 < crt->len)
-            {
-                assert(crt->data[crt->len - 1] == '\0');
-                memcpy(crt->data + crt->len - 1, pem, pemLen);
-                crt->len += pemLen - 1;
-            }
-            else
-            {
-                memcpy(crt->data, pem, pemLen);
-                crt->len = pemLen;
-            }
-
-            /* If pem doesn't contain a terminating NULL, add one. */
-            if (mustAddNull)
-            {
-                assert(crt->data[crt->len - 1] != '\0');
-                crt->data[crt->len] = '\0';
-                crt->len += 1;
-            }
-
-            if (mustFreePem)
+            OIC_LOG_V(DEBUG, TAG, "%s found", usage);
+            if (OC_STACK_OK != FillCertChain(chain, temp))
             {
-                OICFree(pem);
+                FreeCertChain(chain);
+                OIC_LOG_V(ERROR, TAG, "%s: Failed to parse certificate chain", __func__);
             }
-
-            OIC_LOG_V(DEBUG, TAG, "%s found", usage);
         }
     }
-    if(0 == crt->len)
+    if(NULL == chain->cert)
     {
         OIC_LOG_V(WARNING, TAG, "%s not found", usage);
     }
 #ifndef NDEBUG
-    if(0 < crt->len)
+    if(0 < chain->cert->len)
     {
         OIC_LOG(DEBUG, TAG_LOG, "==== Cert being returned ===================================");
-        LogCert ( crt->data, crt->len, OIC_ENCODING_PEM, TAG_LOG );
+        LogCert ( chain->cert->data, chain->cert->len, OIC_ENCODING_PEM, TAG_LOG );
         OIC_LOG(DEBUG, TAG_LOG, "============================================================");
     }
 #endif
index 874d105..3ae09f4 100644 (file)
@@ -36,8 +36,8 @@ void GetPkixInfo(PkiInfo_t * inf)
         return;
     }
 
-    GetPemOwnCert(&inf->crt, PRIMARY_CERT);
-    if (inf->crt.len == 0)
+    GetOwnCert(&inf->crt, PRIMARY_CERT);
+    if (NULL == inf->crt.cert || 0 == inf->crt.cert->len)
     {
         OIC_LOG_V(WARNING, TAG, "%s: empty certificate", __func__);
     }
@@ -48,8 +48,8 @@ void GetPkixInfo(PkiInfo_t * inf)
         OIC_LOG_V(WARNING, TAG, "%s: empty key", __func__);
     }
 
-    (void)GetPemCaCert(&inf->ca, TRUST_CA);
-    if (inf->ca.len == 0)
+    GetCaCert(&inf->ca, TRUST_CA);
+    if (NULL == inf->ca.cert || 0 == inf->ca.cert->len)
     {
         OIC_LOG_V(WARNING, TAG, "%s: empty CA cert", __func__);
     }
@@ -67,9 +67,17 @@ void GetManufacturerPkixInfo(PkiInfo_t * inf)
         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
         return;
     }
-    GetPemOwnCert(&inf->crt, MF_PRIMARY_CERT);
+    GetOwnCert(&inf->crt, MF_PRIMARY_CERT);
+    if (NULL == inf->crt.cert || 0 == inf->crt.cert->len)
+    {
+        OIC_LOG_V(WARNING, TAG, "%s: empty certificate", __func__);
+    }
     GetDerKey(&inf->key, MF_PRIMARY_CERT);
-    (void)GetPemCaCert(&inf->ca, MF_TRUST_CA);
+    GetCaCert(&inf->ca, MF_TRUST_CA);
+    if (NULL == inf->ca.cert || 0 == inf->ca.cert->len)
+    {
+        OIC_LOG_V(WARNING, TAG, "%s: empty CA cert", __func__);
+    }
     // CRL not provided
     inf->crl.data = NULL;
     inf->crl.len = 0;
index 40554eb..e8d546c 100644 (file)
@@ -49,6 +49,7 @@
 #include "ocstackinternal.h"
 #include "rolesresource.h"
 #include "secureresourcemanager.h"
+#include "parsechain.h"
 
 #define TAG  "OIC_SRM_ROLES"
 
@@ -1159,7 +1160,7 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role
     RolesEntry_t *targetEntry = NULL;
     OicSecRole_t *rolesToReturn = NULL;
     size_t rolesToReturnCount = 0;
-    ByteArray_t trustedCaCerts;
+    ByteArrayLL_t trustedCaCerts;
     memset(&trustedCaCerts, 0, sizeof(trustedCaCerts));
 
     OCStackResult res = GetPeerPublicKeyFromEndpoint(endpoint, &publicKey, &publicKeyLength);
@@ -1272,8 +1273,8 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role
     InvalidateRoleCache(targetEntry);
 
     /* Retrieve the current set of trusted CAs from the cred resource. */
-    res = GetPemCaCert(&trustedCaCerts, TRUST_CA);
-    if (OC_STACK_OK != res)
+    GetCaCert(&trustedCaCerts, TRUST_CA);
+    if (NULL == trustedCaCerts.cert || 0 == trustedCaCerts.cert->len)
     {
         OIC_LOG_V(ERROR, TAG, "Could not get CA certs: %d", res);
         OICFree(publicKey);
@@ -1289,8 +1290,7 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role
         struct tm notValidAfter;
         memset(&notValidAfter, 0, sizeof(notValidAfter));
 
-        res = OCInternalVerifyRoleCertificate(&chain->certificate, trustedCaCerts.data,
-                                              trustedCaCerts.len, &currCertRoles,
+        res = OCInternalVerifyRoleCertificate(&chain->certificate, &trustedCaCerts, &currCertRoles,
                                               &currCertRolesCount, &notValidAfter);
 
         if (OC_STACK_OK != res)
@@ -1310,7 +1310,7 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role
             {
                 OIC_LOG(ERROR, TAG, "No memory reallocating rolesToReturn");
                 memset(&targetEntry->cacheValidUntil, 0, sizeof(targetEntry->cacheValidUntil));
-                OICFree(trustedCaCerts.data);
+                FreeCertChain(&trustedCaCerts);
                 OICFree(savePtr);
                 OICFree(currCertRoles);
                 OICFree(publicKey);
@@ -1353,14 +1353,14 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role
     if (NULL == *roles)
     {
         OICFree(publicKey);
-        OICFree(trustedCaCerts.data);
+        FreeCertChain(&trustedCaCerts);
         return OC_STACK_NO_MEMORY;
     }
     memcpy(*roles, targetEntry->cachedRoles, (targetEntry->cachedRolesLength * sizeof(OicSecRole_t)));
     *roleCount = targetEntry->cachedRolesLength;
 
     OICFree(publicKey);
-    OICFree(trustedCaCerts.data);
+    FreeCertChain(&trustedCaCerts);
     return OC_STACK_OK;
 }
 
index af2965b..6df1408 100644 (file)
@@ -61,6 +61,14 @@ typedef enum SubOperationType
     BACK = 99
 } SubOperationType_t;
 
+typedef struct
+{
+    ByteArray_t crt;    /**< own certificate chain as a null-terminated PEM string of certificates */
+    ByteArray_t key;    /**< own private key as binary-encoded DER */
+    ByteArray_t ca;     /**< trusted CAs as a null-terminated PEM string of certificates */
+    ByteArray_t crl;    /**< trusted CRLs as binary-encoded DER */
+} PkiInfoCrt_t;
+
 void PrintUuid(const OicUuid_t *uuid);
 void PrintIntArray(const int *array, size_t length);
 void PrintStringArray(const char **array, size_t length);
index f0cf6cf..d10a554 100644 (file)
@@ -533,10 +533,10 @@ void PrintCredList(const OicSecCred_t *creds)
                         char buf[2048];
                         mbedtls_x509_crt crt;
                         mbedtls_x509_crt *tmpCrt = NULL;
-                        PkiInfo_t inf;
+                        PkiInfoCrt_t inf;
                         int i = 0;
 
-                        memset(&inf, 0x00, sizeof(PkiInfo_t));
+                        memset(&inf, 0x00, sizeof(PkiInfoCrt_t));
                         mbedtls_x509_crt_init(&crt);
 
                         ParseDerOwnCert(&inf.crt, cred->credUsage, cred->credId);
@@ -558,7 +558,7 @@ void PrintCredList(const OicSecCred_t *creds)
                         char buf[2048];
                         mbedtls_x509_crt ca;
                         mbedtls_x509_crt *tmpCa = NULL;
-                        PkiInfo_t inf;
+                        PkiInfoCrt_t inf;
                         int i = 0;
 
                         memset(&inf, 0x00, sizeof(PkiInfo_t));
@@ -601,10 +601,10 @@ void PrintCredList(const OicSecCred_t *creds)
                         char buf[2048];
                         mbedtls_x509_crt ca;
                         mbedtls_x509_crt *tmpCa = NULL;
-                        PkiInfo_t inf;
+                        PkiInfoCrt_t inf;
                         int i = 0;
 
-                        memset(&inf, 0x00, sizeof(PkiInfo_t));
+                        memset(&inf, 0x00, sizeof(PkiInfoCrt_t));
                         mbedtls_x509_crt_init(&ca);
 
                         ParseDerCaCert(&inf.ca, cred->credUsage, cred->credId);