From 42740e7b34e921308375eebd0491566aa8c4d8cb Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Tue, 9 Jan 2024 10:24:48 +0100 Subject: [PATCH] fixup! Serialize selected certificates to PEM string --- port/esp32/adapter/include/debug_print.h | 24 +- port/esp32/adapter/include/oc_certificates.h | 107 --------- port/esp32/adapter/src/debug_print.c | 45 ---- port/esp32/main/main.c | 2 - security/oc_certs.c | 6 + security/oc_cred.c | 1 + security/oc_pki.c | 170 +++++++------- security/oc_tls.c | 1 + security/unittest/credtest.cpp | 126 +--------- security/unittest/pkitest.cpp | 235 ++++++++++++++++++- tests/gtest/PKI.cpp | 104 +++++++- tests/gtest/PKI.h | 23 ++ 12 files changed, 475 insertions(+), 369 deletions(-) delete mode 100644 port/esp32/adapter/include/oc_certificates.h diff --git a/port/esp32/adapter/include/debug_print.h b/port/esp32/adapter/include/debug_print.h index 0925cf7946..54ff881be3 100644 --- a/port/esp32/adapter/include/debug_print.h +++ b/port/esp32/adapter/include/debug_print.h @@ -18,8 +18,6 @@ extern "C" { #endif -#define APP_PRINT(...) printf(__VA_ARGS__) - /** * @brief print current all macro information * @@ -40,22 +38,6 @@ void print_macro_info(); */ void print_message_info(const oc_message_t *message); -/** - * @brief print the data detail information - * - * print input data, print from data[0] to data[len-1], addtionally add notes - * string - * - * @param[in] data: input data pointer to print - * @param[in] len: data length - * @param[in] note: notes for read easily - * @param[in] mode: 0x00, 0x01, 0x10, 0x11 to decide the BINARY_SHOW && - * BYTES_SHOW - * - */ -void print_debug(const char *data, const unsigned int len, const char *note, - int mode); - /** * @brief print the fatal error information and cycle it * @@ -73,9 +55,9 @@ void print_debug(const char *data, const unsigned int len, const char *note, #define APP_LOG(level, ...) \ do { \ - APP_PRINT("%s: %s <%s:%d>: ", level, __FILE__, __FUNCTION__, __LINE__); \ - APP_PRINT(__VA_ARGS__); \ - APP_PRINT("\n"); \ + printf("%s: %s <%s:%d>: ", level, __FILE__, __FUNCTION__, __LINE__); \ + printf(__VA_ARGS__); \ + printf("\n"); \ } while (0) #define APP_DBG(...) APP_LOG("DEBUG", __VA_ARGS__) #define APP_WRN(...) APP_LOG("WARNING", __VA_ARGS__) diff --git a/port/esp32/adapter/include/oc_certificates.h b/port/esp32/adapter/include/oc_certificates.h deleted file mode 100644 index 35ba3a13dd..0000000000 --- a/port/esp32/adapter/include/oc_certificates.h +++ /dev/null @@ -1,107 +0,0 @@ -/****************************************************************** - * - * Copyright (c) 2016 Intel Corporation - * - * 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 OC_CERTIFICATES_H -#define OC_CERTIFICATES_H - -#include "oc_config.h" - -#if defined(OC_SECURITY) && defined(OC_PKI) - -#ifdef __cplusplus -extern "C" { -#endif - -const char oc_root_ca[] = - "-----BEGIN CERTIFICATE-----\n" - "MIIB3zCCAYWgAwIBAgIJAPObjMBXKhGyMAoGCCqGSM49BAMCMFMxDDAKBgNVBAoM\n" - "A09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJbmZyYXN0cnVjdHVyZTEfMB0GA1UE\n" - "AwwWS3lyaW8gVEVTVCBST09UIENBMDAwMjAeFw0xODExMzAxNzMxMDVaFw0yODEx\n" - "MjcxNzMxMDVaMFMxDDAKBgNVBAoMA09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJ\n" - "bmZyYXN0cnVjdHVyZTEfMB0GA1UEAwwWS3lyaW8gVEVTVCBST09UIENBMDAwMjBZ\n" - "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABGt1sU2QhQcK/kflKSF9TCrvKaDckLWd\n" - "ZoyvP6z0OrqNdtBscZgVYsSHMQZ1R19wWxsflvNr8bMVW1K3HWMkpsijQjBAMA8G\n" - "A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBQoSOTlJ1jZ\n" - "CO4JNOSxuz1ZZh/I9TAKBggqhkjOPQQDAgNIADBFAiAlMUwgVeL8d5W4jZdFJ5Zg\n" - "clk7XT66LNMfGkExSjU1ngIhANOvTmd32A0kEtIpHbiKA8+RFDCPJWjN4loxrBC7\n" - "v0JE\n" - "-----END CERTIFICATE-----\n"; - -const char oc_inter_ca[] = - "-----BEGIN CERTIFICATE-----\n" - "MIIC+jCCAqGgAwIBAgIJAPObjMBXKhG1MAoGCCqGSM49BAMCMFMxDDAKBgNVBAoM\n" - "A09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJbmZyYXN0cnVjdHVyZTEfMB0GA1UE\n" - "AwwWS3lyaW8gVEVTVCBST09UIENBMDAwMjAeFw0xODExMzAxODEyMTVaFw0yODEx\n" - "MjYxODEyMTVaMFsxDDAKBgNVBAoMA09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJ\n" - "bmZyYXN0cnVjdHVyZTEnMCUGA1UEAwweS3lyaW8gVEVTVCBJbnRlcm1lZGlhdGUg\n" - "Q0EwMDAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvA+Gn3ofRpH40XuVppBR\n" - "f78mDtfclOkBd7/32yQcmK2LQ0wm/uyl2cyeABPuN6NFcR9+LYkXZ5P4Ovy9R43Q\n" - "vqOCAVQwggFQMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMB0G\n" - "A1UdDgQWBBQZc2oEGgsHcE9TeVM2h/wMunyuCzAfBgNVHSMEGDAWgBQoSOTlJ1jZ\n" - "CO4JNOSxuz1ZZh/I9TCBjQYIKwYBBQUHAQEEgYAwfjBVBggrBgEFBQcwAoZJaHR0\n" - "cDovL3Rlc3Rwa2kua3lyaW8uY29tL29jZi80RTY4RTNGQ0YwRjJFNEY4MEE4RDE0\n" - "MzhGNkExQkE1Njk1NzEzRDYzLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL3Rlc3Rv\n" - "Y3NwLmt5cmlvLmNvbTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vdGVzdHBraS5r\n" - "eXJpby5jb20vb2NmLzRFNjhFM0ZDRjBGMkU0RjgwQThEMTQzOEY2QTFCQTU2OTU3\n" - "MTNENjMuY3JsMAoGCCqGSM49BAMCA0cAMEQCHwXkRYd+u5pOPH544wBmBRJz/b0j\n" - "ppvUIHx8IUH0CioCIQDC8CnMVTOC5aIoo5Yg4k7BDDNxbRQoPujYes0OTVGgPA==\n" - "-----END CERTIFICATE-----\n"; - -const char oc_certificate[] = - "-----BEGIN CERTIFICATE-----\n" - "MIIEFDCCA7qgAwIBAgIJAI0K+3tTsk4eMAoGCCqGSM49BAMCMFsxDDAKBgNVBAoM\n" - "A09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJbmZyYXN0cnVjdHVyZTEnMCUGA1UE\n" - "AwweS3lyaW8gVEVTVCBJbnRlcm1lZGlhdGUgQ0EwMDAyMB4XDTIwMDQxNDE3MzMy\n" - "NloXDTIwMDUxNDE3MzMyNlowYTEMMAoGA1UECgwDT0NGMSIwIAYDVQQLDBlLeXJp\n" - "byBUZXN0IEluZnJhc3RydWN0dXJlMS0wKwYDVQQDDCQyYjI1ODQ4Mi04ZDZhLTQ5\n" - "OTEtOGQ2OS0zMTAxNDE5ODE2NDYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARZ\n" - "H0LnMEg5BR41xctwQMPoNwa0ERVB1J9WWUvdrKq4GVkX/HwPUGvViISpmIS0GM8z\n" - "Ky2IjHm+rMrc4oSTfyX0o4ICXzCCAlswCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMC\n" - "A4gwKQYDVR0lBCIwIAYIKwYBBQUHAwIGCCsGAQUFBwMBBgorBgEEAYLefAEGMB0G\n" - "A1UdDgQWBBTS5/x0htLNUYt8JoL82HU2rkjuWDAfBgNVHSMEGDAWgBQZc2oEGgsH\n" - "cE9TeVM2h/wMunyuCzCBlgYIKwYBBQUHAQEEgYkwgYYwXQYIKwYBBQUHMAKGUWh0\n" - "dHA6Ly90ZXN0cGtpLmt5cmlvLmNvbS9vY2YvY2FjZXJ0cy9CQkU2NEY5QTdFRTM3\n" - "RDI5QTA1RTRCQjc3NTk1RjMwOEJFNDFFQjA3LmNydDAlBggrBgEFBQcwAYYZaHR0\n" - "cDovL3Rlc3RvY3NwLmt5cmlvLmNvbTBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8v\n" - "dGVzdHBraS5reXJpby5jb20vb2NmL2NybHMvQkJFNjRGOUE3RUUzN0QyOUEwNUU0\n" - "QkI3NzU5NUYzMDhCRTQxRUIwNy5jcmwwGAYDVR0gBBEwDzANBgsrBgEEAYORVgAB\n" - "AjBhBgorBgEEAYORVgEABFMwUTAJAgECAgEAAgEAMDYMGTEuMy42LjEuNC4xLjUx\n" - "NDE0LjAuMC4xLjAMGTEuMy42LjEuNC4xLjUxNDE0LjAuMC4yLjAMBUxpdGUxDAVM\n" - "aXRlMTAqBgorBgEEAYORVgEBBBwwGgYLKwYBBAGDkVYBAQAGCysGAQQBg5FWAQEB\n" - "MDAGCisGAQQBg5FWAQIEIjAgDA4xLjMuNi4xLjQuMS43MQwJRGlzY292ZXJ5DAMx\n" - "LjAwCgYIKoZIzj0EAwIDSAAwRQIgedG7zHeLh9YzM0bU3DQBnKDRIFnJHiDayyuE\n" - "8pVfJOQCIQCo/llZOZD87IHzsyxEfXm/QhkTNA5WJOa7sjF2ngQ1/g==\n" - "-----END CERTIFICATE-----\n"; - -const char oc_certificate_key[] = - "-----BEGIN EC PARAMETERS-----\n" - "BggqhkjOPQMBBw==\n" - "-----END EC PARAMETERS-----\n" - "-----BEGIN EC PRIVATE KEY-----\n" - "MHcCAQEEIBF8S8rq+h8EnykDcCpAyvMam+u3D9i/5oYF5owt/+SnoAoGCCqGSM49\n" - "AwEHoUQDQgAEWR9C5zBIOQUeNcXLcEDD6DcGtBEVQdSfVllL3ayquBlZF/x8D1Br\n" - "1YiEqZiEtBjPMystiIx5vqzK3OKEk38l9A==\n" - "-----END EC PRIVATE KEY-----\n"; - -#ifdef __cplusplus -} -#endif - -#endif /* OC_SECURITY && OC_PKI */ - -#endif /* OC_CERTIFICATES_H */ diff --git a/port/esp32/adapter/src/debug_print.c b/port/esp32/adapter/src/debug_print.c index d69e981344..1dc7fd4132 100644 --- a/port/esp32/adapter/src/debug_print.c +++ b/port/esp32/adapter/src/debug_print.c @@ -127,48 +127,3 @@ print_message_info(const oc_message_t *message) printf("\n****************************************\n"); #endif } - -/** - * @brief print the data detail information - * - * print input data, print from data[0] to data[len-1], addtionally add notes - * string - * - * @param[in] data: input data pointer to print - * @param[in] len: data length - * @param[in] note: notes for read easily - * @param[in] mode: 0x00, 0x01, 0x10, 0x11 to decide the BINARY_SHOW && - * BYTES_SHOW - * - * @return noreturn - * - */ -void -print_debug(const char *data, const unsigned int len, const char *note, - int mode) -{ -#define BINARY_SHOW 0x10 -#define BYTES_SHOW 0x01 - printf("\n********** %s [len:%u] start addr:%p **********\n", note, len, - data); - int i = 0; - for (i = 0; i < len; ++i) { - if (BINARY_SHOW & mode) { - printf("%02x ", data[i]); - } else { - if (data[i] < 32 || data[i] > 126) { // control || invisible charset - if (i > 0 && (data[i - 1] >= 33 && data[i - 1] <= 126)) - printf(" "); - printf("%02x ", data[i]); - } else { - printf("%c", data[i]); - } - } - - if ((BYTES_SHOW & mode) && ((i + 1) % 32 == 0)) { - printf(" | %d Bytes\n", i + 1); - } - } // end for - - printf("\n---------- %s End ----------\n", note); -} diff --git a/port/esp32/main/main.c b/port/esp32/main/main.c index ae374de28d..6ad6f76fe9 100644 --- a/port/esp32/main/main.c +++ b/port/esp32/main/main.c @@ -31,8 +31,6 @@ #ifdef OC_HAS_FEATURE_PLGD_HAWKBIT #include "hawkbit.h" -#else /* !OC_HAS_FEATURE_PLGD_HAWKBIT */ -#include "oc_certificates.h" #endif /* OC_HAS_FEATURE_PLGD_HAWKBIT */ #include "driver/gpio.h" diff --git a/security/oc_certs.c b/security/oc_certs.c index e8b6b35f1a..c927bdf0dd 100644 --- a/security/oc_certs.c +++ b/security/oc_certs.c @@ -163,6 +163,7 @@ oc_certs_parse_serial_number(const unsigned char *cert, size_t cert_size, int ret = mbedtls_x509_crt_parse(&crt, cert, cert_size); if (ret != 0) { OC_ERR("could not parse the provided cert %d", ret); + mbedtls_x509_crt_free(&crt); return ret; } @@ -197,6 +198,7 @@ oc_certs_parse_private_key(size_t device, const unsigned char *cert, int ret = mbedtls_x509_crt_parse(&crt, cert, cert_size); if (ret != 0) { OC_ERR("could not parse the provided cert %d", ret); + mbedtls_x509_crt_free(&crt); return ret; } @@ -255,6 +257,7 @@ oc_certs_parse_public_key(const unsigned char *cert, size_t cert_size, int ret = mbedtls_x509_crt_parse(&crt, cert, cert_size); if (ret != 0) { OC_ERR("could not parse the provided cert %d", ret); + mbedtls_x509_crt_free(&crt); return -1; } @@ -273,6 +276,7 @@ oc_certs_parse_public_key_to_oc_string(const unsigned char *cert, int ret = mbedtls_x509_crt_parse(&crt, cert, cert_size); if (ret != 0) { OC_ERR("could not parse the provided cert %d", ret); + mbedtls_x509_crt_free(&crt); return -1; } @@ -372,6 +376,7 @@ oc_certs_parse_CN_for_UUID(const unsigned char *cert, size_t cert_size, int ret = mbedtls_x509_crt_parse(&crt, cert, cert_size); if (ret != 0) { OC_ERR("could not parse the provided cert %d", ret); + mbedtls_x509_crt_free(&crt); return false; } @@ -544,6 +549,7 @@ oc_certs_parse_first_role(const unsigned char *cert, size_t cert_size, int ret = mbedtls_x509_crt_parse(&crt, cert, cert_size); if (ret != 0) { OC_ERR("could not parse the provided cert %d", ret); + mbedtls_x509_crt_free(&crt); return false; } diff --git a/security/oc_cred.c b/security/oc_cred.c index 71c182c777..fcb8514537 100644 --- a/security/oc_cred.c +++ b/security/oc_cred.c @@ -1101,6 +1101,7 @@ oc_cred_parse_certificate(const oc_sec_cred_t *cred, mbedtls_x509_crt *crt) int ret = mbedtls_x509_crt_parse(crt, cert, cert_size); if (ret < 0) { OC_ERR("failed to parse certificate: %d", ret); + mbedtls_x509_crt_free(crt); return false; } return true; diff --git a/security/oc_pki.c b/security/oc_pki.c index a54cb03d70..fba546ce6e 100644 --- a/security/oc_pki.c +++ b/security/oc_pki.c @@ -20,6 +20,7 @@ #if defined(OC_SECURITY) && defined(OC_PKI) +#include "api/oc_core_res_internal.h" #include "oc_pki.h" #include "oc_certs_internal.h" #include "oc_cred_internal.h" @@ -139,11 +140,68 @@ pki_add_intermediate_cert(size_t device, int credid, const unsigned char *cert, return credid; } +static bool +pki_is_equal_certificate(const mbedtls_x509_crt *cert1, + const mbedtls_x509_crt *cert2) +{ + return cert1->raw.len == cert2->raw.len && + memcmp(cert1->raw.p, cert2->raw.p, cert2->raw.len) == 0; +} + +static int +pki_find_certificate(size_t device, const mbedtls_x509_crt *cert, + oc_sec_credusage_t credusage) +{ + oc_sec_creds_t *creds = oc_sec_get_creds(device); + assert(creds != NULL); + oc_sec_cred_t *c = oc_list_head(creds->creds); + for (; c != NULL; c = c->next) { + if (c->credusage != credusage) { + continue; + } + mbedtls_x509_crt cert2; + mbedtls_x509_crt_init(&cert2); + int ret = + mbedtls_x509_crt_parse(&cert2, oc_cast(c->publicdata.data, unsigned char), + oc_string_len(c->publicdata.data) + 1); + if (ret < 0) { + OC_ERR("could not parse stored certificate: %d", ret); + mbedtls_x509_crt_free(&cert2); + continue; + } + + if (credusage == OC_CREDUSAGE_TRUSTCA || + credusage == OC_CREDUSAGE_MFG_TRUSTCA) { + mbedtls_x509_crt *trustca = &cert2; + for (; trustca != NULL; trustca = trustca->next) { + if (pki_is_equal_certificate(cert, trustca)) { + mbedtls_x509_crt_free(&cert2); + return c->credid; + } + } + } else if (credusage == OC_CREDUSAGE_IDENTITY_CERT || + credusage == OC_CREDUSAGE_MFG_CERT) { + if (pki_is_equal_certificate(cert, &cert2)) { + mbedtls_x509_crt_free(&cert2); + OC_DBG("found identity cert in cred with credid %d", c->credid); + return c->credid; + } + } + + mbedtls_x509_crt_free(&cert2); + } + return -1; +} + static int pki_add_identity_cert(size_t device, const unsigned char *cert, size_t cert_size, const unsigned char *key, size_t key_size, oc_sec_credusage_t credusage) { + if (!oc_core_device_is_valid(device)) { + OC_ERR("invalid device index"); + return -1; + } OC_DBG("attempting to add an identity certificate chain"); if (!oc_certs_is_PEM(cert, cert_size)) { @@ -171,6 +229,7 @@ pki_add_identity_cert(size_t device, const unsigned char *cert, mbedtls_ctr_drbg_random, oc_tls_ctr_drbg_context()); if (ret != 0) { OC_ERR("could not parse identity cert's private key %d", ret); + mbedtls_pk_free(&pkey); return -1; } OC_DBG("parsed the provided identity cert's private key"); @@ -195,6 +254,7 @@ pki_add_identity_cert(size_t device, const unsigned char *cert, ret = mbedtls_x509_crt_parse(&cert1, cert, c_size); if (ret < 0) { OC_ERR("could not parse the provided identity cert"); + mbedtls_x509_crt_free(&cert1); return -1; } OC_DBG("parsed the provided identity cert"); @@ -207,57 +267,31 @@ pki_add_identity_cert(size_t device, const unsigned char *cert, subjectuuid[0] = '*'; subjectuuid[1] = '\0'; } - oc_sec_creds_t *creds = oc_sec_get_creds(device); - oc_sec_cred_t *c = oc_list_head(creds->creds); - for (; c != NULL; c = c->next) { - /* Iterate over all identity certs provisioned to this logical - * device. - */ - if (c->credusage != credusage) { - continue; - } - mbedtls_x509_crt cert2; - mbedtls_x509_crt_init(&cert2); - - ret = - mbedtls_x509_crt_parse(&cert2, oc_cast(c->publicdata.data, unsigned char), - oc_string_len(c->publicdata.data) + 1); - if (ret < 0) { - mbedtls_x509_crt_free(&cert2); - continue; - } - - if (cert1.raw.len == cert2.raw.len && - memcmp(cert1.raw.p, cert2.raw.p, cert2.raw.len) == 0) { - mbedtls_x509_crt_free(&cert1); - mbedtls_x509_crt_free(&cert2); - OC_DBG("found identity cert in cred with credid %d", c->credid); - return c->credid; - } - mbedtls_x509_crt_free(&cert2); + int credid = pki_find_certificate(device, &cert1, credusage); + mbedtls_x509_crt_free(&cert1); + if (credid != -1) { + OC_DBG("found identity cert in cred with credid %d", credid); + return credid; } OC_DBG("adding a new identity cert chain to /oic/sec/cred"); - mbedtls_x509_crt_free(&cert1); - oc_sec_encoded_data_t privatedata = { privkbuf + (sizeof(privkbuf) - private_key_size), private_key_size, OC_ENCODING_RAW }; oc_sec_encoded_data_t publicdata = { cert, c_size - 1, OC_ENCODING_PEM }; - int credid = oc_sec_add_new_cred( - device, false, NULL, -1, OC_CREDTYPE_CERT, credusage, subjectuuid, - privatedata, publicdata, oc_string_view2(NULL), oc_string_view2(NULL), - oc_string_view2(NULL), NULL); - - if (credid != -1) { - OC_DBG("added new identity cert(credid=%d) chain to /oic/sec/cred", credid); - oc_sec_dump_cred(device); - } else { + ret = oc_sec_add_new_cred(device, false, NULL, -1, OC_CREDTYPE_CERT, + credusage, subjectuuid, privatedata, publicdata, + OC_STRING_VIEW_NULL, OC_STRING_VIEW_NULL, + oc_string_view2(NULL), NULL); + if (ret == -1) { OC_ERR("could not add identity cert chain to /oic/sec/cred"); + return -1; } - return credid; + OC_DBG("added new identity cert(credid=%d) chain to /oic/sec/cred", ret); + oc_sec_dump_cred(device); + return ret; } int @@ -288,7 +322,12 @@ static int pki_add_trust_anchor(size_t device, const unsigned char *cert, size_t cert_size, oc_sec_credusage_t credusage) { + if (!oc_core_device_is_valid(device)) { + OC_ERR("invalid device index"); + return -1; + } OC_DBG("attempting to add a trust anchor"); + /* Parse root cert */ if (!oc_certs_is_PEM(cert, cert_size)) { OC_ERR("provided cert is not in PEM format"); @@ -303,43 +342,17 @@ pki_add_trust_anchor(size_t device, const unsigned char *cert, size_t cert_size, int ret = mbedtls_x509_crt_parse(&cert1, cert, c_size); if (ret < 0) { OC_ERR("could not parse the provided trust anchor: %d", ret); + mbedtls_x509_crt_free(&cert1); return -1; } OC_DBG("parsed the provided trust anchor"); /* Pass through all known trust anchors looking for a match */ - oc_sec_creds_t *creds = oc_sec_get_creds(device); - oc_sec_cred_t *c = oc_list_head(creds->creds); - for (; c != NULL; c = c->next) { - if (c->credusage != credusage) { - continue; - } - mbedtls_x509_crt cert2; - mbedtls_x509_crt_init(&cert2); - ret = - mbedtls_x509_crt_parse(&cert2, oc_cast(c->publicdata.data, unsigned char), - oc_string_len(c->publicdata.data) + 1); - if (ret < 0) { - OC_ERR("could not parse stored certificate: %d", ret); - mbedtls_x509_crt_free(&cert2); - continue; - } - - mbedtls_x509_crt *trustca = &cert2; - for (; trustca != NULL; trustca = trustca->next) { - if (trustca->raw.len == cert1.raw.len && - memcmp(trustca->raw.p, cert1.raw.p, cert1.raw.len) == 0) { - break; - } - } - - mbedtls_x509_crt_free(&cert2); - - if (trustca) { - mbedtls_x509_crt_free(&cert1); - OC_DBG("found trust anchor in cred with credid %d", c->credid); - return c->credid; - } + int credid = pki_find_certificate(device, &cert1, credusage); + mbedtls_x509_crt_free(&cert1); + if (credid != -1) { + OC_DBG("found trust anchor in cred with credid %d", credid); + return credid; } OC_DBG("adding a new trust anchor entry to /oic/sec/cred"); @@ -348,16 +361,15 @@ pki_add_trust_anchor(size_t device, const unsigned char *cert, size_t cert_size, oc_sec_encoded_data_t publicdata = { cert, c_size - 1, OC_ENCODING_PEM }; ret = oc_sec_add_new_cred(device, false, NULL, -1, OC_CREDTYPE_CERT, credusage, - "*", privatedata, publicdata, oc_string_view2(NULL), - oc_string_view2(NULL), oc_string_view2(NULL), NULL); - if (ret != -1) { - OC_DBG("added new trust anchor entry to /oic/sec/cred"); - oc_sec_dump_cred(device); - } else { + "*", privatedata, publicdata, OC_STRING_VIEW_NULL, + OC_STRING_VIEW_NULL, OC_STRING_VIEW_NULL, NULL); + if (ret == -1) { OC_ERR("could not add trust anchor entry to /oic/sec/cred"); + return -1; } - mbedtls_x509_crt_free(&cert1); + OC_DBG("added new trust anchor entry to /oic/sec/cred"); + oc_sec_dump_cred(device); return ret; } diff --git a/security/oc_tls.c b/security/oc_tls.c index 2f667d371b..b556632d2a 100644 --- a/security/oc_tls.c +++ b/security/oc_tls.c @@ -955,6 +955,7 @@ is_known_identity_cert(const oc_sec_cred_t *cred) cert, (const unsigned char *)oc_string(cred->publicdata.data), cert_len); if (ret < 0) { OC_ERR("could not parse identity cert from cred"); + mbedtls_x509_crt_free(cert); return true; } diff --git a/security/unittest/credtest.cpp b/security/unittest/credtest.cpp index dce492ed93..0bf8d226c3 100644 --- a/security/unittest/credtest.cpp +++ b/security/unittest/credtest.cpp @@ -28,13 +28,13 @@ #include "security/oc_certs_internal.h" #include "security/oc_cred_internal.h" #include "security/oc_cred_util_internal.h" -#include "security/oc_entropy_internal.h" #include "security/oc_obt_internal.h" #include "security/oc_security_internal.h" #include "security/oc_svr_internal.h" #include "security/oc_tls_internal.h" #include "tests/gtest/Device.h" #include "tests/gtest/KeyPair.h" +#include "tests/gtest/PKI.h" #ifdef OC_HAS_FEATURE_PUSH #include "api/oc_push_internal.h" @@ -44,24 +44,11 @@ #include #include #include -#include -#include #include #include static constexpr size_t kDeviceID{ 0 }; -#if defined(OC_PKI) && (defined(OC_DYNAMIC_ALLOCATION) || defined(OC_TEST)) -static constexpr std::string_view kRootSubjectName{ "IoTivity-Lite Test" }; -static const std::string kRootSubject{ "C=US, O=OCF, CN=" + - std::string(kRootSubjectName) }; -static const std::vector kPersonalizationString{ 'I', 'o', 'T' }; -// 12/31/2029 23:59:59 to seconds since epoch -static constexpr int64_t kNotAfter{ 1893455999 }; -static mbedtls_ctr_drbg_context g_oc_ctr_drbg_ctx{}; -static mbedtls_entropy_context g_entropy_ctx{}; -#endif /* OC_PKI && (OC_DYNAMIC_ALLOCATION || OC_TEST) */ - class TestCreds : public testing::Test { public: static void SetUpTestCase() @@ -80,22 +67,14 @@ class TestCreds : public testing::Test { oc_mbedtls_init(); #if defined(OC_PKI) && (defined(OC_DYNAMIC_ALLOCATION) || defined(OC_TEST)) - mbedtls_entropy_init(&g_entropy_ctx); - oc_entropy_add_source(&g_entropy_ctx); - mbedtls_ctr_drbg_init(&g_oc_ctr_drbg_ctx); - std::string pers = "test"; - ASSERT_EQ(0, mbedtls_ctr_drbg_seed( - &g_oc_ctr_drbg_ctx, mbedtls_entropy_func, &g_entropy_ctx, - reinterpret_cast(pers.c_str()), - pers.length())); + #endif /* OC_PKI && (OC_DYNAMIC_ALLOCATION || OC_TEST) */ } static void TearDownTestCase() { #if defined(OC_PKI) && (defined(OC_DYNAMIC_ALLOCATION) || defined(OC_TEST)) - mbedtls_ctr_drbg_free(&g_oc_ctr_drbg_ctx); - mbedtls_entropy_free(&g_entropy_ctx); + #endif /* OC_PKI && (OC_DYNAMIC_ALLOCATION || OC_TEST) */ oc_sec_svr_free(); @@ -109,11 +88,8 @@ class TestCreds : public testing::Test { oc_network_event_handler_mutex_destroy(); } - void SetUp() override { oc_log_set_level(OC_LOG_LEVEL_DEBUG); } - void TearDown() override { - oc_log_set_level(OC_LOG_LEVEL_INFO); oc_sec_cred_clear(kDeviceID, nullptr, nullptr); } @@ -139,105 +115,29 @@ class TestCreds : public testing::Test { static int addRootCertificate(size_t device, const oc::keypair_t &kp, bool isMfg = false) { - oc_certs_generate_t root_cert{}; - root_cert.personalization_string = { kPersonalizationString.data(), - kPersonalizationString.size() }; - root_cert.serial_number_size = 20; - root_cert.validity.not_before = oc_certs_timestamp_now(); - root_cert.validity.not_after = { kNotAfter, 0, 0 }; - root_cert.subject.name = kRootSubject.c_str(); - root_cert.subject.public_key = { kp.public_key.data(), kp.public_key_size }; - root_cert.subject.private_key = { kp.private_key.data(), - kp.private_key_size }; - root_cert.signature_md = MBEDTLS_MD_SHA256; - root_cert.is_CA = true; - - std::array pem{}; - if (oc_certs_generate(&root_cert, &pem[0], pem.size()) < 0) { - return -1; - } - auto it = - std::find(pem.begin(), pem.end(), static_cast('\0')); - if (pem.end() == it) { - return -1; - } - size_t data_len = std::distance(pem.begin(), it); - return isMfg ? oc_pki_add_mfg_trust_anchor(device, pem.data(), data_len) - : oc_pki_add_trust_anchor(device, pem.data(), data_len); - } - - static std::vector getPrivateKey(const unsigned char *key, - size_t keylen) - { - mbedtls_pk_context pk; - mbedtls_pk_init(&pk); - if (mbedtls_pk_parse_key(&pk, key, keylen, nullptr, 0, - mbedtls_ctr_drbg_random, - &g_oc_ctr_drbg_ctx) != 0) { - mbedtls_pk_free(&pk); - return {}; - } - - std::vector pem{}; - pem.resize(1024); - mbedtls_pk_write_key_pem(&pk, &pem[0], pem.size()); - mbedtls_pk_free(&pk); - - auto it = - std::find(pem.begin(), pem.end(), static_cast('\0')); - if (pem.end() == it) { - return {}; - } - size_t dataSize = - std::distance(pem.begin(), it) + 1; // include null terminator - pem.resize(dataSize); - return pem; + auto pem = oc::pki::GenerateRootCertificate(kp); + return isMfg ? oc_pki_add_mfg_trust_anchor(device, pem.data(), pem.size()) + : oc_pki_add_trust_anchor(device, pem.data(), pem.size()); } static int addIdentityCertificate(size_t device, const oc::keypair_t &kp, const oc::keypair_t &issuer_kp, bool isMfg = false) { - oc_uuid_t uuid{}; - oc_gen_uuid(&uuid); - std::array subject{}; - if (!oc_certs_encode_CN_with_UUID(&uuid, subject.data(), subject.size())) { + auto pem = oc::pki::GeneratIdentityCertificate(kp, issuer_kp); + if (pem.empty()) { return -1; } - - oc_certs_generate_t identity_cert{}; - identity_cert.personalization_string = { kPersonalizationString.data(), - kPersonalizationString.size() }; - identity_cert.serial_number_size = 20; - identity_cert.validity.not_before = oc_certs_timestamp_now(); - identity_cert.validity.not_after = { kNotAfter, 0, 0 }; - identity_cert.subject.name = subject.data(); - identity_cert.subject.public_key = { kp.public_key.data(), - kp.public_key_size }; - identity_cert.issuer.name = kRootSubject.c_str(); - identity_cert.issuer.private_key = { issuer_kp.private_key.data(), - issuer_kp.private_key_size }; - identity_cert.signature_md = MBEDTLS_MD_SHA256; - - std::array pem{}; - if (oc_certs_generate(&identity_cert, &pem[0], pem.size()) < 0) { - return -1; - } - auto it = - std::find(pem.begin(), pem.end(), static_cast('\0')); - if (pem.end() == it) { - return -1; - } - size_t dataLen = std::distance(pem.begin(), it); - - auto keyPem = getPrivateKey(kp.private_key.data(), kp.private_key_size); + oc::pki::KeyParser parser{}; + auto keyPem = + parser.GetPrivateKey(kp.private_key.data(), kp.private_key_size); if (keyPem.empty()) { return -1; } - return isMfg ? oc_pki_add_mfg_cert(device, pem.data(), dataLen, + return isMfg ? oc_pki_add_mfg_cert(device, pem.data(), pem.size(), keyPem.data(), keyPem.size()) - : oc_pki_add_identity_cert(device, pem.data(), dataLen, + : oc_pki_add_identity_cert(device, pem.data(), pem.size(), keyPem.data(), keyPem.size()); } #endif /* OC_PKI && (OC_DYNAMIC_ALLOCATION || OC_TEST) */ diff --git a/security/unittest/pkitest.cpp b/security/unittest/pkitest.cpp index 934ace6d6a..2b404578fe 100644 --- a/security/unittest/pkitest.cpp +++ b/security/unittest/pkitest.cpp @@ -18,13 +18,246 @@ #if defined(OC_SECURITY) && defined(OC_PKI) +#include "api/oc_core_res_internal.h" +#include "api/oc_ri_internal.h" +#include "api/oc_runtime_internal.h" +#include "oc_api.h" +#include "oc_cred.h" #include "oc_pki.h" #include "oc_config.h" +#include "port/oc_network_event_handler_internal.h" +#include "security/oc_certs_internal.h" +#include "security/oc_cred_util_internal.h" #include "security/oc_pki_internal.h" +#include "security/oc_security_internal.h" +#include "security/oc_svr_internal.h" +#include "tests/gtest/Device.h" #include "tests/gtest/PKI.h" -#include +#ifdef OC_HAS_FEATURE_PUSH +#include "api/oc_push_internal.h" +#endif /* OC_HAS_FEATURE_PUSH */ + +#include + #include +#include +#include + +static constexpr size_t kDeviceID{ 0 }; + +class TestPKI : public testing::Test { +public: + static void SetUpTestCase() + { + oc_network_event_handler_mutex_init(); + oc_runtime_init(); + oc_ri_init(); + oc_core_init(); + ASSERT_EQ(0, oc_add_device(oc::DefaultDevice.uri.c_str(), + oc::DefaultDevice.rt.c_str(), + oc::DefaultDevice.name.c_str(), + oc::DefaultDevice.spec_version.c_str(), + oc::DefaultDevice.data_model_version.c_str(), + nullptr, nullptr)); + oc_sec_svr_create(); + oc_mbedtls_init(); + } + + static void TearDownTestCase() + { + oc_sec_svr_free(); +#ifdef OC_HAS_FEATURE_PUSH + oc_push_free(); +#endif /* OC_HAS_FEATURE_PUSH */ + oc_connectivity_shutdown(kDeviceID); + oc_core_shutdown(); + oc_ri_shutdown(); + oc_runtime_shutdown(); + oc_network_event_handler_mutex_destroy(); + } + + void TearDown() override + { + oc_sec_cred_clear(kDeviceID, nullptr, nullptr); + } + +#ifdef OC_DYNAMIC_ALLOCATION + size_t countCreds(size_t device) + { + const oc_sec_creds_t *device_creds = oc_sec_get_creds(device); + if (device_creds == nullptr) { + return 0; + } + + size_t count = 0; + oc_cred_iterate( + device_creds->creds, + [](const oc_sec_cred_t *, void *data) { + ++(*static_cast(data)); + return true; + }, + &count); + return count; + } +#endif /* OC_DYNAMIC_ALLOCATION */ +}; + +TEST_F(TestPKI, AddIdentityCertificate_FailInvalidInput) +{ + EXPECT_EQ(-1, oc_pki_add_identity_cert(kDeviceID, nullptr, 0, nullptr, 0)); +} + +TEST_F(TestPKI, AddTrustAnchor_FailInvalidInput) +{ + EXPECT_EQ(-1, oc_pki_add_trust_anchor(kDeviceID, nullptr, 0)); +} + +#ifdef OC_DYNAMIC_ALLOCATION + +TEST_F(TestPKI, AddIdentityCertificate) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + oc::keypair_t identKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + + auto pem = oc::pki::GeneratIdentityCertificate(rootKey, identKey); + ASSERT_FALSE(pem.empty()); + oc::pki::KeyParser parser{}; + auto keyPem = + parser.GetPrivateKey(rootKey.private_key.data(), rootKey.private_key_size); + ASSERT_FALSE(keyPem.empty()); + EXPECT_NE(-1, oc_pki_add_identity_cert(kDeviceID, pem.data(), pem.size(), + keyPem.data(), keyPem.size())); + + auto pem2 = oc::pki::GeneratIdentityCertificate(rootKey, identKey); + ASSERT_FALSE(pem2.empty()); + // send size without nul-terminator for pem2 and keyPem + EXPECT_NE(-1, + oc_pki_add_identity_cert(kDeviceID, pem2.data(), pem2.size() - 1, + keyPem.data(), keyPem.size() - 1)); + + auto pem3 = oc::pki::GeneratIdentityCertificate(rootKey, identKey); + ASSERT_FALSE(pem3.empty()); + // use DER format for key + EXPECT_NE(-1, oc_pki_add_identity_cert( + kDeviceID, pem3.data(), pem3.size() - 1, + rootKey.private_key.data(), rootKey.private_key_size)); +} + +TEST_F(TestPKI, AddIdentityCertificate_FailInvalidDevice) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + oc::keypair_t identKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + + auto pem = oc::pki::GeneratIdentityCertificate(rootKey, identKey); + EXPECT_EQ(-1, oc_pki_add_identity_cert(/*device*/ 42, pem.data(), pem.size(), + rootKey.private_key.data(), + rootKey.private_key_size)); +} + +TEST_F(TestPKI, AddIdentityCertificate_Duplicate) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + oc::keypair_t identKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + + auto pem = oc::pki::GeneratIdentityCertificate(rootKey, identKey); + int credid = oc_pki_add_identity_cert(kDeviceID, pem.data(), pem.size(), + rootKey.private_key.data(), + rootKey.private_key_size); + EXPECT_NE(-1, credid); + ASSERT_EQ(1, TestPKI::countCreds(kDeviceID)); + + EXPECT_EQ(credid, oc_pki_add_identity_cert(kDeviceID, pem.data(), pem.size(), + rootKey.private_key.data(), + rootKey.private_key_size)); + EXPECT_EQ(1, TestPKI::countCreds(kDeviceID)); +} + +TEST_F(TestPKI, AddIdentityCertificate_FailCorruptedKey) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + oc::keypair_t identKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + + auto pem = oc::pki::GeneratIdentityCertificate(rootKey, identKey); + ASSERT_FALSE(pem.empty()); + oc::pki::KeyParser parser{}; + auto keyPem = + parser.GetPrivateKey(rootKey.private_key.data(), rootKey.private_key_size); + ASSERT_FALSE(keyPem.empty()); + constexpr std::string_view label{ "-----BEGIN EC PRIVATE KEY-----" }; + pem.insert(keyPem.begin() + label.length(), { 'l', 'e', 'e', 't', '4', '2' }); + ASSERT_TRUE(oc_certs_is_PEM(keyPem.data(), keyPem.size())); + + EXPECT_EQ(-1, oc_pki_add_identity_cert(kDeviceID, pem.data(), pem.size(), + keyPem.data(), keyPem.size())); +} + +TEST_F(TestPKI, AddIdentityCertificate_FailCorruptedCertifiate) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + oc::keypair_t identKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + + auto pem = oc::pki::GeneratIdentityCertificate(rootKey, identKey); + ASSERT_FALSE(pem.empty()); + constexpr std::string_view label{ "-----BEGIN CERTIFICATE-----" }; + pem.insert(pem.begin() + label.length(), { 'l', 'e', 'e', 't', '4', '2' }); + ASSERT_TRUE(oc_certs_is_PEM(pem.data(), pem.size())); + + EXPECT_EQ(-1, oc_pki_add_identity_cert(kDeviceID, pem.data(), pem.size(), + rootKey.private_key.data(), + rootKey.private_key_size)); +} + +TEST_F(TestPKI, AddTrustAnchor) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + auto pem = oc::pki::GenerateRootCertificate(rootKey); + ASSERT_FALSE(pem.empty()); + EXPECT_NE(-1, oc_pki_add_trust_anchor(kDeviceID, pem.data(), pem.size())); + + auto pem2 = oc::pki::GenerateRootCertificate(rootKey); + ASSERT_FALSE(pem2.empty()); + // send size without nul-terminator for pem2 + EXPECT_NE(-1, + oc_pki_add_trust_anchor(kDeviceID, pem2.data(), pem2.size() - 1)); +} + +TEST_F(TestPKI, AddTrustAnchor_FailInvalidDevice) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + auto pem = oc::pki::GenerateRootCertificate(rootKey); + ASSERT_FALSE(pem.empty()); + + EXPECT_EQ(-1, oc_pki_add_trust_anchor(/*device*/ 42, pem.data(), pem.size())); +} + +// the same certificate should not be added to the same device twice +TEST_F(TestPKI, AddTrustAnchor_Duplicate) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + auto pem = oc::pki::GenerateRootCertificate(rootKey); + ASSERT_FALSE(pem.empty()); + int credid = oc_pki_add_trust_anchor(kDeviceID, pem.data(), pem.size()); + EXPECT_NE(-1, credid); + ASSERT_EQ(1, TestPKI::countCreds(kDeviceID)); + + EXPECT_EQ(credid, oc_pki_add_trust_anchor(kDeviceID, pem.data(), pem.size())); + EXPECT_EQ(1, TestPKI::countCreds(kDeviceID)); +} + +TEST_F(TestPKI, AddTrustAnchor_FailCorruptedCertifiate) +{ + oc::keypair_t rootKey{ oc::GetECPKeyPair(MBEDTLS_ECP_DP_SECP256R1) }; + auto pem = oc::pki::GenerateRootCertificate(rootKey); + ASSERT_FALSE(pem.empty()); + constexpr std::string_view label{ "-----BEGIN CERTIFICATE-----" }; + pem.insert(pem.begin() + label.length(), { 'l', 'e', 'e', 't', '4', '2' }); + ASSERT_TRUE(oc_certs_is_PEM(pem.data(), pem.size())); + + EXPECT_EQ(-1, oc_pki_add_trust_anchor(kDeviceID, pem.data(), pem.size())); +} + +#endif /* OC_DYNAMIC_ALLOCATION */ class TestPKIPK : public testing::Test { public: diff --git a/tests/gtest/PKI.cpp b/tests/gtest/PKI.cpp index fa3d96ac60..d1e910ef5a 100644 --- a/tests/gtest/PKI.cpp +++ b/tests/gtest/PKI.cpp @@ -18,10 +18,11 @@ #ifdef OC_PKI -#include "PKI.h" #include "oc_pki.h" +#include "PKI.h" #include "port/oc_log_internal.h" #include "security/oc_certs_internal.h" +#include "security/oc_entropy_internal.h" #include #include @@ -55,6 +56,13 @@ ReadPem(const std::string &path) #if defined(OC_DYNAMIC_ALLOCATION) || defined(OC_TEST) +static constexpr std::string_view kRootSubjectName{ "IoTivity-Lite Test" }; +static const std::string kRootSubject{ "C=US, O=OCF, CN=" + + std::string(kRootSubjectName) }; +static const std::vector kPersonalizationString{ 'I', 'o', 'T' }; +// 12/31/2029 23:59:59 to seconds since epoch +static constexpr int64_t kNotAfter{ 1893455999 }; + std::vector GenerateCertificate(const oc_certs_generate_t &generate) { @@ -77,8 +85,102 @@ GenerateCertificate(const oc_certs_generate_t &generate) return cert_buf; } +std::vector +GenerateRootCertificate(const oc::keypair_t &kp) +{ + oc_certs_generate_t root_cert{}; + root_cert.personalization_string = { kPersonalizationString.data(), + kPersonalizationString.size() }; + root_cert.serial_number_size = 20; + root_cert.validity.not_before = oc_certs_timestamp_now(); + root_cert.validity.not_after = { kNotAfter, 0, 0 }; + root_cert.subject.name = kRootSubject.c_str(); + root_cert.subject.public_key = { kp.public_key.data(), kp.public_key_size }; + root_cert.subject.private_key = { kp.private_key.data(), + kp.private_key_size }; + root_cert.signature_md = MBEDTLS_MD_SHA256; + root_cert.is_CA = true; + return GenerateCertificate(root_cert); +} + +std::vector +GeneratIdentityCertificate(const oc::keypair_t &kp, + const oc::keypair_t &issuer_kp) +{ + oc_uuid_t uuid{}; + oc_gen_uuid(&uuid); + std::array subject{}; + if (!oc_certs_encode_CN_with_UUID(&uuid, subject.data(), subject.size())) { + return {}; + } + + oc_certs_generate_t identity_cert{}; + identity_cert.personalization_string = { kPersonalizationString.data(), + kPersonalizationString.size() }; + identity_cert.serial_number_size = 20; + identity_cert.validity.not_before = oc_certs_timestamp_now(); + identity_cert.validity.not_after = { kNotAfter, 0, 0 }; + identity_cert.subject.name = subject.data(); + identity_cert.subject.public_key = { kp.public_key.data(), + kp.public_key_size }; + identity_cert.issuer.name = kRootSubject.c_str(); + identity_cert.issuer.private_key = { issuer_kp.private_key.data(), + issuer_kp.private_key_size }; + identity_cert.signature_md = MBEDTLS_MD_SHA256; + return GenerateCertificate(identity_cert); +} + #endif /* OC_DYNAMIC_ALLOCATION || OC_TEST */ +KeyParser::KeyParser() +{ + mbedtls_entropy_init(&entropy_ctx_); + oc_entropy_add_source(&entropy_ctx_); + mbedtls_ctr_drbg_init(&ctr_drbg_ctx_); + std::string pers = "test"; + if (mbedtls_ctr_drbg_seed( + &ctr_drbg_ctx_, mbedtls_entropy_func, &entropy_ctx_, + reinterpret_cast(pers.c_str()), + pers.length()) != 0) { + throw std::string("failed to initialize entropy function"); + } +} + +KeyParser::~KeyParser() +{ + mbedtls_entropy_free(&entropy_ctx_); + mbedtls_ctr_drbg_free(&ctr_drbg_ctx_); +} + +std::vector +KeyParser::GetPrivateKey(const unsigned char *key, size_t keylen) +{ + mbedtls_pk_context pk; + mbedtls_pk_init(&pk); + if (mbedtls_pk_parse_key(&pk, key, keylen, nullptr, 0, + mbedtls_ctr_drbg_random, &ctr_drbg_ctx_) != 0) { + mbedtls_pk_free(&pk); + return {}; + } + + std::vector pem{}; + pem.resize(1024); + if (mbedtls_pk_write_key_pem(&pk, &pem[0], pem.size()) != 0) { + mbedtls_pk_free(&pk); + return {}; + } + mbedtls_pk_free(&pk); + + auto it = std::find(pem.begin(), pem.end(), static_cast('\0')); + if (pem.end() == it) { + return {}; + } + size_t dataSize = + std::distance(pem.begin(), it) + 1; // include null terminator + pem.resize(dataSize); + return pem; +} + PemData::PemData(const std::string &path) : path_{ path } { diff --git a/tests/gtest/PKI.h b/tests/gtest/PKI.h index 794a3b33d2..9a43dd2b57 100644 --- a/tests/gtest/PKI.h +++ b/tests/gtest/PKI.h @@ -22,6 +22,11 @@ #include "oc_pki.h" #include "security/oc_certs_generate_internal.h" +#include "tests/gtest/KeyPair.h" + +#include +#include +#include #include #include @@ -33,8 +38,26 @@ std::vector ReadPem(const std::string &path); #if defined(OC_DYNAMIC_ALLOCATION) || defined(OC_TEST) std::vector GenerateCertificate( const oc_certs_generate_t &generate); + +std::vector GenerateRootCertificate(const oc::keypair_t &kp); + +std::vector GeneratIdentityCertificate( + const oc::keypair_t &kp, const oc::keypair_t &issuer_kp); #endif /* OC_DYNAMIC_ALLOCATION || OC_TEST */ +class KeyParser { +public: + KeyParser(); + ~KeyParser(); + + std::vector GetPrivateKey(const unsigned char *key, + size_t keylen); + +private: + mbedtls_ctr_drbg_context ctr_drbg_ctx_{}; + mbedtls_entropy_context entropy_ctx_{}; +}; + class PemData { public: PemData(const std::string &path);