add optional cert extensions 85/27285/7
authorSteven Saunders <s.saunders-contractor@cablelabs.com>
Tue, 2 Oct 2018 17:52:33 +0000 (11:52 -0600)
committerNathan Heldt-Sheller <nathan.heldt-sheller@intel.com>
Wed, 31 Oct 2018 00:21:22 +0000 (00:21 +0000)
Change-Id: I11ee97610c01f464dba896e600c71831629650bc
Signed-off-by: Steven Saunders <s.saunders-contractor@cablelabs.com>
resource/csdk/connectivity/test/cacertprofiletest.cpp
resource/csdk/security/provisioning/sample/config-templates/oic_svr_db_client.json [new file with mode: 0644]
resource/csdk/security/provisioning/sample/config-templates/oic_svr_db_server_mfg.json [new file with mode: 0644]
resource/csdk/security/provisioning/sample/makecerts [new file with mode: 0755]
resource/csdk/security/src/occertutility.c
resource/csdk/security/src/spresource.c

index 3b99633..e3a83ac 100644 (file)
@@ -30,6 +30,7 @@
 #include <mbedtls/ctr_drbg.h>
 #include <mbedtls/oid.h>
 #include <mbedtls/pem.h>
+#include <mbedtls/asn1write.h>
 
 #include "oic_platform.h"
 #include "oic_malloc.h"
@@ -55,6 +56,7 @@ static void FreeTestCert(mbedtls_x509_crt *cert);
 static void removeCertChaining(mbedtls_x509_crt* rootCert, mbedtls_x509_crt* intCert, mbedtls_x509_crt* eeCert);
 static CertProfileResult SetNotBefore(ValidityTime notBefore, bool invalid);
 static CertProfileResult SetNotAfter(ValidityTime notAfter, bool invalid);
+static int OCWriteBasicConstraints( mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen, int critical);
 
 class CACertProfileTests : public testing::Test {
     protected:
@@ -102,6 +104,63 @@ static const OCByteString s_ekuOcfIdentityOid = { s_ekuOcfIdentityOidBytes, size
 static const OCByteString s_ekuAnyOid = { s_ekuAnyOidBytes, sizeof(s_ekuAnyOidBytes) };
 
 
+static const char s_ComplianceExtOid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x04\x01\x83\x91\x56\x01\x00"; // 1.3.6.1.4.1.51414.1.0
+static const uint8_t s_ComplianceExtBytes[] = {
+
+  0x30, 0x81, 0x8C, // compliance extension sequence
+
+  0x30, 0x09, // version sequence (9 bytes)
+  0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, // [2, 0, 0]
+
+  0x30, 0x64, // security profile sequence (100 bytes)
+
+    0x0C, 0x17, // utf8_string, 23 bytes long, '1.3.6.1.4.1.51414.0.1.0' (baseline)
+    0x31, 0x2E, 0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E,
+    0x31, 0x2E, 0x35, 0x31, 0x34, 0x31, 0x34, 0x2E, 0x30, 0x2E, 0x31, 0x2E, 0x30,
+
+    0x0C, 0x17, // utf8_string, 23 bytes long, '1.3.6.1.4.1.51414.0.2.0' (black)
+    0x31, 0x2E, 0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E,
+    0x31, 0x2E, 0x35, 0x31, 0x34, 0x31, 0x34, 0x2E, 0x30, 0x2E, 0x32, 0x2E, 0x30,
+
+    0x0C, 0x17, // utf8_string, 23 bytes long, '1.3.6.1.4.1.51414.0.3.0' (blue)
+    0x31, 0x2E, 0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E,
+    0x31, 0x2E, 0x35, 0x31, 0x34, 0x31, 0x34, 0x2E, 0x30, 0x2E, 0x33, 0x2E, 0x30,
+
+    0x0C, 0x17, // utf8_string, 23 bytes long, '1.3.6.1.4.1.51414.0.4.0' (purple)
+    0x31, 0x2E, 0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E,
+    0x31, 0x2E, 0x35, 0x31, 0x34, 0x31, 0x34, 0x2E, 0x30, 0x2E, 0x34, 0x2E, 0x30,
+
+    0x0C, 0x0F, // urf8_string 15 bytes long (device name)
+    0x49, 0x6F, 0x54, 0x69, 0x76, 0x69, 0x74, 0x79, 0x20, 0x53, // 'IoTivity Server'
+    0x65, 0x72, 0x76, 0x65, 0x72,
+
+    0x0C, 0x08, // urf8_string 8 bytes long (device manufacturer)
+    0x49, 0x6F, 0x54, 0x69, 0x76, 0x69, 0x74, 0x79 // 'IoTivity'
+};
+
+
+static const char s_cplSecurityClaimsExtOid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x04\x01\x83\x91\x56\x01\x01"; // 1.3.6.1.4.1.51414.1.1
+static const uint8_t s_cplSecurityClaimsExtBytes[] = {
+    0x30, 0x1A, // sequence of length 26
+    0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x91, 0x56, 0x01, 0x01, 0x00, // OID 1.3.6.1.4.1.51414.1.1.0 (claim secure boot)
+    0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x91, 0x56, 0x01, 0x01, 0x01  // OID 1.3.6.1.4.1.51414.1.1.1 (claim hw backed credential)
+};
+
+static const char s_cplAttributesExtOid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x04\x01\x83\x91\x56\x01\x02"; // 1.3.6.1.4.1.51414.1.2
+static const uint8_t s_cplAttributesExtBytes[] = {
+    0x30, 0x20, // sequence of length 32
+
+    0x0C, 0x0E, // utf8_string, 14 bytes long
+    0X31, 0X2E, 0X33, 0X2E, 0X36, 0X2E, 0X31, 0X2E, 0X34, 0X2E, 0X31, 0X2E, 0X37, 0X31,  // '1.3.6.1.4.1.71'
+
+    0x0C, 0x09, // utf8_string, 9 bytes long
+    0X44, 0X69, 0X73, 0X63, 0X6F, 0X76, 0X65, 0X72, 0X79, // 'Discovery'
+
+    0x0C, 0x03, // utf8_string, 3 bytes long
+    0X31, 0X2E, 0X30 // '1.0'
+};
+
+
 // The key pairs below are OCF compliant ellliptic curve key pairs
 // (RFC 5480 secp256r1 keys) generated by the IoTivity`certgenerator` utility.
 // They are used as the public and signing keys for certificates
@@ -744,6 +803,7 @@ static CertProfileResult GenerateTestCert(CertType certType, CertProfileViolatio
 
     int isCa = 0;
     int maxPathLen = 0;
+    int critical = 0;
     unsigned int usage = 0;
     bool makeDateInvalid = false;
 
@@ -893,18 +953,21 @@ static CertProfileResult GenerateTestCert(CertType certType, CertProfileViolatio
     case CERT_CA_ROOT:
         isCa = (violations & CP_INVALID_BASIC_CONSTRAINTS_CA) ? 0 : 1;
         maxPathLen = (violations & CP_INVALID_BASIC_CONSTRAINTS_PATH_LEN) ? 2 :-1;
+        critical = 1;
         break;
     case CERT_CA_INT:
         isCa = (violations & CP_INVALID_BASIC_CONSTRAINTS_CA) ? 0 : 1;
         maxPathLen = (violations & CP_INVALID_BASIC_CONSTRAINTS_PATH_LEN) ? -1 : 0;
+        critical = 1;
         break;
     case CERT_EE:
         isCa = (violations & CP_INVALID_BASIC_CONSTRAINTS_CA) ? 1 : 0;
         maxPathLen = (violations & CP_INVALID_BASIC_CONSTRAINTS_PATH_LEN) ? 10 : -1;
+        critical = 0;
         break;
     };
 
-    mbedRet = mbedtls_x509write_crt_set_basic_constraints(&outCertCtx, isCa, maxPathLen);
+    mbedRet = OCWriteBasicConstraints(&outCertCtx, isCa, maxPathLen, critical  );
     CP_LOG_MBED_ERROR(TAG, mbedRet, mbedErrBuf, sizeof(mbedErrBuf), ERROR);
     cpResult = (0 == mbedRet) ? CP_STATUS_OK : CP_STATUS_FAILED;
     VERIFY_SUCCESS_OR_EXIT(TAG, 0 == mbedRet, "Problem writing basic constraints", ERROR);
@@ -996,6 +1059,51 @@ static CertProfileResult GenerateTestCert(CertType certType, CertProfileViolatio
         }
     }
 
+    // Optional extensions
+
+    if (CERT_EE == certType)
+    {
+
+        // FILE *fp = fopen("./cpl.der", "wb");
+        // fwrite(s_cplAttributesExtBytes, sizeof(s_cplAttributesExtBytes), 1, fp );
+        // fclose(fp);
+
+        mbedRet = mbedtls_x509write_crt_set_extension(
+                    &outCertCtx,
+                    s_cplAttributesExtOid,
+                    MBEDTLS_OID_SIZE(s_cplAttributesExtOid), 0,
+                    (const unsigned char*)s_cplAttributesExtBytes, sizeof(s_cplAttributesExtBytes));
+        CP_LOG_MBED_ERROR(TAG, mbedRet, mbedErrBuf, sizeof(mbedErrBuf), ERROR);
+        cpResult = (0 == mbedRet) ? CP_STATUS_OK : CP_STATUS_FAILED;
+        VERIFY_SUCCESS_OR_EXIT(TAG, (0 == mbedRet), "Problem writing certified product list extension", ERROR);
+
+        // fp = fopen("./claims.der", "wb");
+        // fwrite(s_cplSecurityClaimsExtBytes, sizeof(s_cplSecurityClaimsExtBytes), 1, fp );
+        // fclose(fp);
+
+        mbedRet = mbedtls_x509write_crt_set_extension(
+                    &outCertCtx,
+                    s_cplSecurityClaimsExtOid,
+                    MBEDTLS_OID_SIZE(s_cplSecurityClaimsExtOid), 0,
+                    (const unsigned char*)s_cplSecurityClaimsExtBytes, sizeof(s_cplSecurityClaimsExtBytes));
+        CP_LOG_MBED_ERROR(TAG, mbedRet, mbedErrBuf, sizeof(mbedErrBuf), ERROR);
+        cpResult = (0 == mbedRet) ? CP_STATUS_OK : CP_STATUS_FAILED;
+        VERIFY_SUCCESS_OR_EXIT(TAG, (0 == mbedRet), "Problem writing certified product list extension", ERROR);
+
+        // fp = fopen("./compliance.der", "wb");
+        // fwrite(s_ComplianceExtBytes, sizeof(s_ComplianceExtBytes), 1, fp );
+        // fclose(fp);
+
+        mbedRet = mbedtls_x509write_crt_set_extension(
+                    &outCertCtx,
+                    s_ComplianceExtOid,
+                    MBEDTLS_OID_SIZE(s_ComplianceExtOid), 0,
+                    (const unsigned char*)s_ComplianceExtBytes, sizeof(s_ComplianceExtBytes));
+        CP_LOG_MBED_ERROR(TAG, mbedRet, mbedErrBuf, sizeof(mbedErrBuf), ERROR);
+        cpResult = (0 == mbedRet) ? CP_STATUS_OK : CP_STATUS_FAILED;
+        VERIFY_SUCCESS_OR_EXIT(TAG, (0 == mbedRet), "Problem writing certified product list extension", ERROR);
+    }
+
     // Create the cert
 
     mbedRet = mbedtls_x509write_crt_pem(&outCertCtx, (uint8_t *)buf, sizeof(buf), mbedtls_ctr_drbg_random, &ctr_drbg);
@@ -1147,6 +1255,42 @@ static void InitTestCert(mbedtls_x509_crt *cert)
 }
 
 
+// write basic constraints to a cert
+// Same as mbedtls_x509write_crt_set_basic_constraints, with the added ability to set `critical` flag
+// returns mbedtls error
+static int OCWriteBasicConstraints( mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen, int critical)
+{
+
+    int ret;
+    unsigned char buf[9];
+    unsigned char *c = buf + sizeof(buf);
+    size_t len = 0;
+
+    memset( buf, 0, sizeof(buf) );
+
+    if( is_ca && max_pathlen > 127 )
+        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+
+    if( is_ca )
+    {
+        if( max_pathlen >= 0 )
+        {
+            MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
+        }
+        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
+    }
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
+                                                       MBEDTLS_ASN1_SEQUENCE ) );
+
+    return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
+                                                 MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
+                                                   critical, buf + sizeof(buf) - len, len );
+}
+
+
+
 static void FreeTestCert(mbedtls_x509_crt *cert)
 {
     mbedtls_x509_crt_free(cert);
diff --git a/resource/csdk/security/provisioning/sample/config-templates/oic_svr_db_client.json b/resource/csdk/security/provisioning/sample/config-templates/oic_svr_db_client.json
new file mode 100644 (file)
index 0000000..41451a9
--- /dev/null
@@ -0,0 +1,114 @@
+{\r
+    "cred": {\r
+        "creds": [\r
+            {\r
+                "credid": 1,\r
+                "subjectuuid": "12121212-1212-1212-1212-121212121212",\r
+                "credtype": 8,\r
+                "publicdata": {\r
+                   "encoding": "oic.sec.encoding.der",\r
+                   "data": "$PUBLIC_EE_KEY"\r
+                },\r
+                "credusage": "oic.sec.cred.mfgcert",\r
+                "privatedata": {\r
+                   "encoding": "oic.sec.encoding.raw",\r
+                   "data": "$PRIVATE_EE_KEY"\r
+                }\r
+             },\r
+             {\r
+                "credid": 2,\r
+                "subjectuuid": "12121212-1212-1212-1212-121212121212",\r
+                "credtype": 8,\r
+                "publicdata": {\r
+                   "encoding": "oic.sec.encoding.der",\r
+                   "data": "$PUBLIC_SUBCA_KEY"\r
+                },\r
+                "credusage": "oic.sec.cred.mfgcert"\r
+             },\r
+            {\r
+                "credid": 3,\r
+                "subjectuuid": "*",\r
+                "credtype": 8,\r
+                "publicdata": {\r
+                   "encoding": "oic.sec.encoding.der",\r
+                   "data": "$PUBLIC_PEER_ROOT_KEY",\r
+                   "revstat": false\r
+                },\r
+                "credusage": "oic.sec.cred.mfgtrustca"\r
+             }\r
+        ],\r
+        "rowneruuid": "12121212-1212-1212-1212-121212121212",\r
+        "rt": ["oic.r.cred"],\r
+        "if": ["oic.if.baseline"]\r
+     },\r
+    "acl": {\r
+      "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p"}\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p"}\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 3,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 14\r
+            },\r
+            {\r
+                "aceid": 4,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/sec/doxm" },\r
+                    { "href": "/oic/sec/roles" }\r
+                ],\r
+                "permission": 14\r
+            }\r
+        ],\r
+      "rowneruuid": "12121212-1212-1212-1212-121212121212",\r
+      "rt": ["oic.r.acl"],\r
+      "if": ["oic.if.baseline"]\r
+   },\r
+   "pstat": {\r
+      "dos": {\r
+         "s": 1,\r
+         "p": false\r
+      },\r
+      "isop": false,\r
+      "cm": 2,\r
+      "tm": 0,\r
+      "om": 4,\r
+      "sm": 4,\r
+      "rowneruuid": "12121212-1212-1212-1212-121212121212",\r
+      "rt": ["oic.r.pstat"],\r
+      "if": ["oic.if.baseline"]\r
+   },\r
+   "doxm": {\r
+      "oxms": [2],\r
+      "oxmsel": 2,\r
+      "sct": 9,\r
+      "owned": false,\r
+      "deviceuuid": "12121212-1212-1212-1212-121212121212",\r
+      "devowneruuid": "12121212-1212-1212-1212-121212121212",\r
+      "rowneruuid": "12121212-1212-1212-1212-121212121212",\r
+      "x.org.iotivity.dpc": true,\r
+      "rt": ["oic.r.doxm"],\r
+      "if": ["oic.if.baseline"]\r
+   }\r
+}\r
diff --git a/resource/csdk/security/provisioning/sample/config-templates/oic_svr_db_server_mfg.json b/resource/csdk/security/provisioning/sample/config-templates/oic_svr_db_server_mfg.json
new file mode 100644 (file)
index 0000000..3c054a4
--- /dev/null
@@ -0,0 +1,134 @@
+{
+    "sp": {
+        "supportedprofiles": [ "1.3.6.1.4.1.51414.0.2.0", "1.3.6.1.4.1.51414.0.3.0", "1.3.6.1.4.1.51414.0.4.0", "1.3.6.1.4.1.51414.0.1.0" ],
+        "currentprofile": "1.3.6.1.4.1.51414.0.1.0",
+        "rowneruuid": "00000000-0000-0000-0000-000000000000",
+        "rt": ["oic.r.sp"],
+        "if": ["oic.if.baseline"]
+    },
+    "cred": {
+        "creds": [
+            {
+                "credid": 1,
+                "subjectuuid": "89898989-8989-8989-8989-898989898989",
+                "credtype": 8,
+                "publicdata": {
+                   "encoding": "oic.sec.encoding.der",
+                   "data": "$PUBLIC_EE_KEY"
+                },
+                "credusage": "oic.sec.cred.mfgcert",
+                "privatedata": {
+                   "encoding": "oic.sec.encoding.raw",
+                   "data": "$PRIVATE_EE_KEY"
+                }
+             },
+             {
+                "credid": 2,
+                "subjectuuid": "89898989-8989-8989-8989-898989898989",
+                "credtype": 8,
+                "publicdata": {
+                   "encoding": "oic.sec.encoding.der",
+                   "data": "$PUBLIC_SUBCA_KEY"
+                },
+                "credusage": "oic.sec.cred.mfgcert"
+             },
+            {
+                "credid": 3,
+                "subjectuuid": "*",
+                "credtype": 8,
+                "publicdata": {
+                   "encoding": "oic.sec.encoding.der",
+                   "data": "$PUBLIC_PEER_ROOT_KEY",
+                   "revstat": false
+                },
+                "credusage": "oic.sec.cred.mfgtrustca"
+             }
+        ],
+        "rowneruuid": "00000000-0000-0000-0000-000000000000",
+        "rt": ["oic.r.cred"],
+        "if": ["oic.if.baseline"]
+     },
+    "acl": {
+      "aclist2": [
+            {
+                "aceid": 1,
+                "subject": { "conntype": "anon-clear" },
+                "resources": [
+                    { "href": "/oic/res" },
+                    { "href": "/oic/d" },
+                    { "href": "/oic/p"}
+                ],
+                "permission": 2
+            },
+            {
+                "aceid": 2,
+                "subject": { "conntype": "auth-crypt" },
+                "resources": [
+                    { "href": "/oic/res" },
+                    { "href": "/oic/d" },
+                    { "href": "/oic/p"}
+                ],
+                "permission": 2
+            },
+            {
+                "aceid": 3,
+                "subject": { "conntype": "anon-clear" },
+                "resources": [
+                    { "href": "/oic/sec/doxm" }
+                ],
+                "permission": 14
+            },
+            {
+                "aceid": 4,
+                "subject": { "conntype": "auth-crypt" },
+                "resources": [
+                    { "href": "/oic/sec/doxm" },
+                    { "href": "/oic/sec/roles" }
+                ],
+                "permission": 14
+            },
+            {
+                "aceid": 5,
+                "subject": { "uuid": "11111111-1111-1111-1111-111111111111" },
+                "resources": [
+                    { "href": "/oic/sec/acl2" },
+                    { "href": "/oic/sec/cred" },
+                    { "href": "/oic/sec/doxm" },
+                    { "href": "/oic/sec/pstat" },
+                    { "href": "/oic/sec/csr" },
+                    { "href": "/oic/sec/sp" }
+                ],
+                "permission": 15
+            }
+
+        ],
+      "rowneruuid": "00000000-0000-0000-0000-000000000000",
+      "rt": ["oic.r.acl"],
+      "if": ["oic.if.baseline"]
+   },
+   "pstat": {
+      "dos": {
+         "s": 1,
+         "p": false
+      },
+      "isop": false,
+      "cm": 2,
+      "tm": 0,
+      "om": 4,
+      "sm": 4,
+      "rowneruuid": "00000000-0000-0000-0000-000000000000",
+      "rt": ["oic.r.pstat"],
+      "if": ["oic.if.baseline"]
+   },
+   "doxm": {
+      "oxms": [2],
+      "oxmsel": 2,
+      "sct": 9,
+      "owned": false,
+      "deviceuuid": "89898989-8989-8989-8989-898989898989",
+      "devowneruuid": "00000000-0000-0000-0000-000000000000",
+      "rowneruuid": "00000000-0000-0000-0000-000000000000",
+      "rt": ["oic.r.doxm"],
+      "if": ["oic.if.baseline"]
+   }
+}
diff --git a/resource/csdk/security/provisioning/sample/makecerts b/resource/csdk/security/provisioning/sample/makecerts
new file mode 100755 (executable)
index 0000000..f2ec4a0
--- /dev/null
@@ -0,0 +1,114 @@
+#! /bin/bash
+
+if [ $# -ne 1 ]
+then
+    echo "makecerts output_dir"
+    exit
+fi
+
+#----------------------------------------------------------------------------
+function GEN_SEED_CERTS () {
+#----------------------------------------------------------------------------
+../certgenerator <<EOD
+1
+root
+1
+subca
+1
+$CLIENT
+1
+$SERVER
+2
+root
+C=US, O=Open Connectivity Foundation, CN=Root CA
+3
+subca
+root
+C=US, O=Open Connectivity Foundation, CN=Sub CA
+4
+$CLIENT
+subca
+12121212-1212-1212-1212-121212121212
+4
+$SERVER
+subca
+89898989-8989-8989-8989-898989898989
+0
+EOD
+}
+
+#----------------------------------------------------------------------------
+function PEM_2_DER () {
+#----------------------------------------------------------------------------
+  IN_PEM=$1
+  OUT_DER=$(basename $IN_PEM .pem).der
+  OUT_HEX=$OUT_DER.hex
+  openssl x509 -in $IN_PEM -out $OUT_DER -outform der
+  xxd  -ps $OUT_DER | tr -d \\n > $OUT_HEX
+}
+
+#----------------------------------------------------------------------------
+function ECKEY_PEM_2_DER () {
+#----------------------------------------------------------------------------
+  IN_PEM=$1
+  OUT=`basename $1`.der
+  OUT_DER=$(basename $IN_PEM .pem).der
+  OUT_HEX=$OUT_DER.hex
+  openssl ec -inform PEM -in $IN_PEM -outform DER -out $OUT_DER
+  cat $OUT_DER | xxd  -ps | tr -d \\n >> $OUT_HEX
+}
+
+#----------------------------------------------------------------------------
+function BUILD_CERT_PKG () {
+#----------------------------------------------------------------------------
+  CERT_NAME=$1
+  mkdir -p $CERT_NAME
+  cp "originals/${CERT_NAME}.crt" "${CERT_NAME}/${CERT_NAME}_cert.pem"
+  cp "originals/${CERT_NAME}.prv" "${CERT_NAME}/${CERT_NAME}_key.pem"
+  cd ./$CERT_NAME
+  PEM_2_DER "${CERT_NAME}_cert.pem"
+  ECKEY_PEM_2_DER "${CERT_NAME}_key.pem"
+  mkdir -p chain
+  cp ../originals/root.crt chain/0-root-cert.pem
+  cp ../originals/subca.crt chain/1-subca-cert.pem
+  cd chain
+  PEM_2_DER 0-root-cert.pem
+  PEM_2_DER 1-subca-cert.pem
+  cd ../..
+}
+
+#----------------------------------------------------------------------------
+function BUILD_CONFIG () {
+#----------------------------------------------------------------------------
+  MY_CERT_NAME=$1
+  PEER_CERT_NAME=$2
+  CONFIG_TEMPLATE=${3}.json
+  J2C=../../../tool/json2cbor
+  J2C_OUT=${3}.dat
+
+  sed -e "s/\$PUBLIC_EE_KEY/$(sed 's:/:\\/:g' ./${MY_CERT_NAME}/${MY_CERT_NAME}_cert.der.hex)/" ../config-templates/${CONFIG_TEMPLATE} > ${CONFIG_TEMPLATE}
+  sed -i "s/\$PRIVATE_EE_KEY/$(sed 's:/:\\/:g' ./${MY_CERT_NAME}/${MY_CERT_NAME}_key.der.hex)/" ${CONFIG_TEMPLATE}
+  sed -i "s/\$PUBLIC_SUBCA_KEY/$(sed 's:/:\\/:g' ./${MY_CERT_NAME}/chain/1-subca-cert.der.hex)/" ${CONFIG_TEMPLATE}
+  sed -i "s/\$PUBLIC_PEER_ROOT_KEY/$(sed 's:/:\\/:g' ./${PEER_CERT_NAME}/chain/0-root-cert.der.hex)/" ${CONFIG_TEMPLATE}
+
+  $J2C $CONFIG_TEMPLATE $J2C_OUT
+}
+
+#--------------------------------------------------------------------------------------
+
+OUT_DIR=$1
+CLIENT=client
+SERVER=server
+
+mkdir -p $OUT_DIR
+cd $OUT_DIR
+
+GEN_SEED_CERTS
+mkdir -p originals
+mv *.pub *.prv *.crt originals/.
+
+BUILD_CERT_PKG $CLIENT
+BUILD_CERT_PKG $SERVER
+BUILD_CONFIG $CLIENT $SERVER oic_svr_db_client
+BUILD_CONFIG $SERVER $CLIENT oic_svr_db_server_mfg
+
index d76d2cd..821d8f5 100644 (file)
@@ -51,6 +51,7 @@
 #include "mbedtls/oid.h"
 #include "mbedtls/pem.h"
 #include "mbedtls/base64.h"
+#include "mbedtls/asn1write.h"
 
 #ifndef NDEBUG
 #include "mbedtls/debug.h"
@@ -91,6 +92,63 @@ static const unsigned char s_ekuRole[] = { 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0
 /* ASN.1 DER encoding of the EKU for both identity and roles (for use by CAs) */
 static const unsigned char s_ekuCA[] = { 0x30, 0x18, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xDE, 0x7C, 0x01, 0x06, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xDE, 0x7C, 0x01, 0x07 };
 
+static const char s_ComplianceExtOid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x04\x01\x83\x91\x56\x01\x00"; // 1.3.6.1.4.1.51414.1.0
+static const uint8_t s_ComplianceExtBytes[] = {
+
+  0x30, 0x81, 0x8C, // compliance extension sequence
+
+  0x30, 0x09, // version sequence (9 bytes)
+  0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, // [2, 0, 0]
+
+  0x30, 0x64, // security profile sequence (100 bytes)
+
+    0x0C, 0x17, // utf8_string, 23 bytes long, '1.3.6.1.4.1.51414.0.1.0' (baseline)
+    0x31, 0x2E, 0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E,
+    0x31, 0x2E, 0x35, 0x31, 0x34, 0x31, 0x34, 0x2E, 0x30, 0x2E, 0x31, 0x2E, 0x30,
+
+    0x0C, 0x17, // utf8_string, 23 bytes long, '1.3.6.1.4.1.51414.0.2.0' (black)
+    0x31, 0x2E, 0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E,
+    0x31, 0x2E, 0x35, 0x31, 0x34, 0x31, 0x34, 0x2E, 0x30, 0x2E, 0x32, 0x2E, 0x30,
+
+    0x0C, 0x17, // utf8_string, 23 bytes long, '1.3.6.1.4.1.51414.0.3.0' (blue)
+    0x31, 0x2E, 0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E,
+    0x31, 0x2E, 0x35, 0x31, 0x34, 0x31, 0x34, 0x2E, 0x30, 0x2E, 0x33, 0x2E, 0x30,
+
+    0x0C, 0x17, // utf8_string, 23 bytes long, '1.3.6.1.4.1.51414.0.4.0' (purple)
+    0x31, 0x2E, 0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E,
+    0x31, 0x2E, 0x35, 0x31, 0x34, 0x31, 0x34, 0x2E, 0x30, 0x2E, 0x34, 0x2E, 0x30,
+
+    0x0C, 0x0F, // urf8_string 15 bytes long (device name)
+    0x49, 0x6F, 0x54, 0x69, 0x76, 0x69, 0x74, 0x79, 0x20, 0x53, // 'IoTivity Server'
+    0x65, 0x72, 0x76, 0x65, 0x72,
+
+    0x0C, 0x08, // urf8_string 8 bytes long (device manufacturer)
+    0x49, 0x6F, 0x54, 0x69, 0x76, 0x69, 0x74, 0x79 // 'IoTivity'
+};
+
+
+static const char s_cplSecurityClaimsExtOid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x04\x01\x83\x91\x56\x01\x01"; // 1.3.6.1.4.1.51414.1.1
+static const uint8_t s_cplSecurityClaimsExtBytes[] = {
+    0x30, 0x1A, // sequence of length 26
+    0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x91, 0x56, 0x01, 0x01, 0x00, // OID 1.3.6.1.4.1.51414.1.1.0 (claim secure boot)
+    0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x91, 0x56, 0x01, 0x01, 0x01  // OID 1.3.6.1.4.1.51414.1.1.1 (claim hw backed credential)
+};
+
+static const char s_cplAttributesExtOid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x04\x01\x83\x91\x56\x01\x02"; // 1.3.6.1.4.1.51414.1.2
+static const uint8_t s_cplAttributesExtBytes[] = {
+    0x30, 0x20, // sequence of length 32
+
+    0x0C, 0x0E, // utf8_string, 14 bytes long
+    0X31, 0X2E, 0X33, 0X2E, 0X36, 0X2E, 0X31, 0X2E, 0X34, 0X2E, 0X31, 0X2E, 0X37, 0X31,  // '1.3.6.1.4.1.71'
+
+    0x0C, 0x09, // utf8_string, 9 bytes long
+    0X44, 0X69, 0X73, 0X63, 0X6F, 0X76, 0X65, 0X72, 0X79, // 'Discovery'
+
+    0x0C, 0x03, // utf8_string, 3 bytes long
+    0X31, 0X2E, 0X30 // '1.0'
+};
+
+
 OCStackResult OC_CALL OCGenerateRandomSerialNumber(char **serial, size_t *serialLen)
 {
     int ret = 0;
@@ -233,6 +291,44 @@ typedef enum {
     CERT_TYPE_ROLE
 } CertificateType_t;
 
+
+// write basic constraints to a cert
+// Same as mbedtls_x509write_crt_set_basic_constraints, with the added ability to set `critical` flag
+static OCStackResult OCWriteBasicConstraints( mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen, int critical)
+{
+
+    int ret;
+    char mbedErrorBuf[256];
+    unsigned char buf[9];
+    unsigned char *c = buf + sizeof(buf);
+    size_t len = 0;
+
+    memset( buf, 0, sizeof(buf) );
+
+    if( is_ca && max_pathlen > 127 )
+        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+
+    if( is_ca )
+    {
+        if( max_pathlen >= 0 )
+        {
+            MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
+        }
+        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
+    }
+
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
+    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
+                                                       MBEDTLS_ASN1_SEQUENCE ) );
+
+    ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
+                                                   MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
+                                                   critical, buf + sizeof(buf) - len, len );
+    LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(ret), ERROR);
+    return (0 == ret) ? OC_STACK_OK : OC_STACK_ERROR;
+}
+
+
 static OCStackResult GenerateCertificate(
     CertificateType_t certType,
     const char *subject,
@@ -349,9 +445,8 @@ static OCStackResult GenerateCertificate(
 
     if (CERT_TYPE_ROOT_CA == certType)
     {
-        ret = mbedtls_x509write_crt_set_basic_constraints(&outCertCtx, 1, -1);
-        LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
-        VERIFY_OR_LOG_AND_EXIT(TAG, 0 == ret, "Could not write basic constraints for internal root ca cert generation",  ERROR);
+        res = OCWriteBasicConstraints(&outCertCtx, 1, -1, 1);
+        VERIFY_OR_LOG_AND_EXIT(TAG, OC_STACK_OK == res, "Could not write basic constraints for internal root ca cert generation",  ERROR);
         ret = mbedtls_x509write_crt_set_key_usage(&outCertCtx,
             MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_CRL_SIGN);
         LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
@@ -359,9 +454,8 @@ static OCStackResult GenerateCertificate(
     }
     else if (CERT_TYPE_INTERMEDIATE_CA == certType)
     {
-        ret = mbedtls_x509write_crt_set_basic_constraints(&outCertCtx, 1, 0);
-        LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
-        VERIFY_OR_LOG_AND_EXIT(TAG, 0 == ret, "Could not write basic constraints for internal intermediate ca cert generation",  ERROR);
+        res = OCWriteBasicConstraints(&outCertCtx, 1, 0, 1);
+        VERIFY_OR_LOG_AND_EXIT(TAG, OC_STACK_OK == res, "Could not write basic constraints for internal intermediate ca cert generation",  ERROR);
         ret = mbedtls_x509write_crt_set_key_usage(&outCertCtx,
             MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_CRL_SIGN);
         LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
@@ -369,9 +463,8 @@ static OCStackResult GenerateCertificate(
     }
     else
     {
-        ret = mbedtls_x509write_crt_set_basic_constraints(&outCertCtx, 0, -1);
-        LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
-        VERIFY_OR_LOG_AND_EXIT(TAG, 0 == ret, "Could not write basic constraints for internal root ee cert generation",  ERROR);
+        res = OCWriteBasicConstraints(&outCertCtx, 0, -1, 0);
+        VERIFY_OR_LOG_AND_EXIT(TAG, OC_STACK_OK == res, "Could not write basic constraints for internal root ee cert generation",  ERROR);
         ret = mbedtls_x509write_crt_set_key_usage(&outCertCtx,
             MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_AGREEMENT);
         LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
@@ -409,8 +502,47 @@ static OCStackResult GenerateCertificate(
             s_ekuIdentity, sizeof(s_ekuIdentity));
         LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
         VERIFY_OR_LOG_AND_EXIT(TAG, 0 == ret,  "Could not write eku for internal ee cert generation", ERROR);
+
+        // optional extensions
+
+        // FILE *fp = fopen("./cpl-ext.der", "wb");
+        // fwrite(s_cplAttributesExtBytes, sizeof(s_cplAttributesExtBytes), 1, fp );
+        // fclose(fp);
+
+        ret = mbedtls_x509write_crt_set_extension(
+                    &outCertCtx,
+                    s_cplAttributesExtOid,
+                    MBEDTLS_OID_SIZE(s_cplAttributesExtOid), 0,
+                    (const unsigned char*)s_cplAttributesExtBytes, sizeof(s_cplAttributesExtBytes));
+        LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
+        VERIFY_OR_LOG_AND_EXIT(TAG, 0 == ret, "Problem writing certified product list extension", ERROR);
+
+        // fp = fopen("./claims-ext.der", "wb");
+        // fwrite(s_cplSecurityClaimsExtBytes, sizeof(s_cplSecurityClaimsExtBytes), 1, fp );
+        // fclose(fp);
+
+        ret = mbedtls_x509write_crt_set_extension(
+                    &outCertCtx,
+                    s_cplSecurityClaimsExtOid,
+                    MBEDTLS_OID_SIZE(s_cplSecurityClaimsExtOid), 0,
+                    (const unsigned char*)s_cplSecurityClaimsExtBytes, sizeof(s_cplSecurityClaimsExtBytes));
+        LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
+        VERIFY_OR_LOG_AND_EXIT(TAG, 0 == ret, "Problem writing certified product list extension", ERROR);
+
+        // fp = fopen("./compliance-ext.der", "wb");
+        // fwrite(s_ComplianceExtBytes, sizeof(s_ComplianceExtBytes), 1, fp );
+        // fclose(fp);
+
+        ret = mbedtls_x509write_crt_set_extension(
+                    &outCertCtx,
+                    s_ComplianceExtOid,
+                    MBEDTLS_OID_SIZE(s_ComplianceExtOid), 0,
+                    (const unsigned char*)s_ComplianceExtBytes, sizeof(s_ComplianceExtBytes));
+        LOG_MBED_ERROR(TAG, ret, mbedErrorBuf, sizeof(mbedErrorBuf), ERROR);
+        VERIFY_OR_LOG_AND_EXIT(TAG, 0 == ret, "Problem writing certified product list extension", ERROR);
         break;
 
+
     case CERT_TYPE_ROOT_CA:
     case CERT_TYPE_INTERMEDIATE_CA:
         ret = mbedtls_x509write_crt_set_extension(&outCertCtx,
index 1d13cb5..230e745 100644 (file)
@@ -44,11 +44,13 @@ static OCResourceHandle    gSpHandle  = NULL;
 static OicSecSp_t         *gSp        = NULL;
 
 // Default sp values
+// char * gSupportedProfiles[] = { "1.3.6.1.4.1.51414.0.1.0", "1.3.6.1.4.1.51414.0.2.0", "1.3.6.1.4.1.51414.0.3.0", "1.3.6.1.4.1.51414.0.4.0" };
 char * gSupportedProfiles[] = { "1.3.6.1.4.1.51414.0.1.0" };
 OicSecSp_t gDefaultSp =
 {
-    1,                     // supportedLen
-    gSupportedProfiles,    // supportedProfiles[0]
+    // 4,                      // supportedLen
+    1,
+    gSupportedProfiles,        // supportedProfiles
     "1.3.6.1.4.1.51414.0.1.0", // currentProfile
 };