From 18bebeb1ee7bfc90a397fd24fa09cb9f7bc3991d Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Thu, 17 Aug 2023 06:53:00 +0000 Subject: [PATCH] tls: print error log messages --- port/linux/tcpsession.c | 2 +- security/oc_certs.c | 8 +- security/oc_tls.c | 214 ++++++++++++++++------------ security/oc_tls_internal.h | 67 +++++++++ security/unittest/tls_cert_test.cpp | 91 +++++++++--- 5 files changed, 268 insertions(+), 114 deletions(-) diff --git a/port/linux/tcpsession.c b/port/linux/tcpsession.c index ed8f347382..6f6226d3e1 100644 --- a/port/linux/tcpsession.c +++ b/port/linux/tcpsession.c @@ -529,7 +529,7 @@ try_connect_nonblocking(int sockfd, const struct sockaddr *r, socklen_t r_len) int n = connect(sockfd, r, r_len); if (n < 0 && errno != EINPROGRESS) { - OC_DBG("connect to socked(%d) failed with error: %d", sockfd, (int)errno); + OC_ERR("connect to socked(%d) failed with error: %d", sockfd, (int)errno); return -1; } return n == 0 ? OC_TCP_SOCKET_STATE_CONNECTED diff --git a/security/oc_certs.c b/security/oc_certs.c index 6d99e5b33d..2ada18eaf0 100644 --- a/security/oc_certs.c +++ b/security/oc_certs.c @@ -396,12 +396,14 @@ oc_certs_parse_CN_buffer_for_UUID(mbedtls_asn1_buf val, char *buffer, if (uuid_prefix_len == 0 || val.len - uuid_prefix_len < OC_UUID_LEN - 1) { // -1 because val is not nul-terminated -#if OC_ERR_IS_ENABLED +#if OC_DBG_IS_ENABLED oc_string_t cn; oc_new_string(&cn, uuid_CN, val.len); - OC_ERR("invalid Common Name field (tag:%d val:%s)", val.tag, oc_string(cn)); + OC_DBG("Common Name field (tag:%d val:%s) is not in format " UUID_PREFIX + ":", + val.tag, oc_string(cn)); oc_free_string(&cn); -#endif /* OC_ERR_IS_ENABLED */ +#endif /* OC_DBG_IS_ENABLED */ return false; } diff --git a/security/oc_tls.c b/security/oc_tls.c index 3c68c3590c..24e1193502 100644 --- a/security/oc_tls.c +++ b/security/oc_tls.c @@ -64,17 +64,57 @@ #include #include #include + +#include +#include +#include +#include + /// TODO update mbedtls_config.h to use LOG_LEVEL instead of OC_DEBUG #if defined(OC_DEBUG) #include #include #include -#endif /* OC_DEBUG */ +#elif OC_DBG_IS_ENABLED || OC_ERR_IS_ENABLED || OC_WRN_IS_ENABLED +static void +mbedtls_strerror(int ret, char *buf, size_t buflen) +{ + snprintf(buf, buflen, "MBEDTLS_ERR(%d)", ret); + return buf; +} +#endif /* OC_DBG_IS_ENABLED || OC_ERR_IS_ENABLED || OC_WRN_IS_ENABLED */ -#include -#include -#include -#include +#define OC_TLS_SELECTED_ANY_CRED_ID (-1) + +#if OC_DBG_IS_ENABLED || OC_ERR_IS_ENABLED +#if OC_ERR_IS_ENABLED +#define MBEDTLS_ERR(mbedtls_func_name, mbedtls_err) \ + do { \ + char buf_mbedtls_strerror[128]; \ + mbedtls_strerror(mbedtls_err, buf_mbedtls_strerror, \ + OC_ARRAY_SIZE(buf_mbedtls_strerror)); \ + OC_ERR("oc_tls: %s ends with error: %s", mbedtls_func_name, \ + buf_mbedtls_strerror); \ + } while (0) +#else /* OC_ERR_IS_ENABLED */ +#define MBEDTLS_ERR(mbedtls_func_name, mbedtls_err) +#endif /* !OC_ERR_IS_ENABLED */ + +#define TLS_LOG_MBEDTLS_ERROR(mbedtls_func_name, mbedtls_err) \ + do { \ + if (mbedtls_err == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { \ + OC_DBG("oc_tls: %s Close-Notify received", mbedtls_func_name); \ + break; \ + } \ + if (mbedtls_err == MBEDTLS_ERR_SSL_CLIENT_RECONNECT) { \ + OC_DBG("oc_tls: %s Client wants to reconnect", mbedtls_func_name); \ + break; \ + } \ + MBEDTLS_ERR(mbedtls_func_name, mbedtls_err); \ + } while (0) +#else /* !OC_DBG_IS_ENABLED && !OC_ERR_IS_ENABLED */ +#define TLS_LOG_MBEDTLS_ERROR(mbedtls_func_name, mbedtls_err) +#endif /* !OC_DBG_IS_ENABLED && !OC_ERR_IS_ENABLED */ typedef struct oc_random_pin_t { @@ -193,8 +233,8 @@ OC_LIST(g_identity_certs); static const int *g_ciphers = NULL; #ifdef OC_PKI -static int g_selected_mfg_cred = -1; -static int g_selected_id_cred = -1; +static int g_selected_mfg_cred = OC_TLS_SELECTED_ANY_CRED_ID; +static int g_selected_id_cred = OC_TLS_SELECTED_ANY_CRED_ID; #ifdef OC_CLOUD static const int default_priority[12] = { #else /* OC_CLOUD */ @@ -653,6 +693,7 @@ check_retry_timers(void) mbedtls_ssl_set_client_transport_id( &peer->ssl_ctx, (const unsigned char *)&peer->endpoint.addr, sizeof(peer->endpoint.addr)) != 0) { + TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_set_client_transport_id", ret); oc_tls_free_peer(peer, false); peer = next; continue; @@ -660,11 +701,7 @@ check_retry_timers(void) } if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { -#if defined(OC_DEBUG) && OC_ERR_IS_ENABLED - char buf[256]; // NOLINT(readability-magic-numbers) - mbedtls_strerror(ret, buf, sizeof(buf)); - OC_ERR("oc_tls: mbedtls_error: %s", buf); -#endif /* OC_DEBUG && OC_ERR_IS_ENABLED */ + TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_handshake", ret); oc_tls_free_peer(peer, false); } } @@ -1342,21 +1379,51 @@ oc_tls_configure_end_entity_cert_chain(mbedtls_ssl_config *conf, size_t device, oc_x509_crt_t *cert = (oc_x509_crt_t *)oc_list_head(g_identity_certs); while (cert != NULL) { if (cert->device == device && cert->cred->credusage == credusage && - (credid == -1 || cert->cred->credid == credid)) { + (credid == OC_TLS_SELECTED_ANY_CRED_ID || + cert->cred->credid == credid)) { break; } cert = cert->next; } - - if (!cert || mbedtls_ssl_conf_own_cert(conf, &cert->cert, &cert->pk) != 0) { - OC_WRN("error configuring identity cert"); + if (!cert) { +#if OC_WRN_IS_ENABLED + char credid_str[16]; + memset(credid_str, 0, sizeof(credid_str)); + if (credid == OC_TLS_SELECTED_ANY_CRED_ID) { + strncpy(credid_str, "any", sizeof(credid_str)); + } else { + snprintf(credid_str, sizeof(credid_str), "%d", credid); + } + OC_WRN( + "cannot set client %s certificate(selected %s): certificate not found", + credusage == OC_CREDUSAGE_MFG_CERT ? "manufacturer" : "identity", + credid_str); +#endif /* OC_WRN_IS_ENABLED */ + return -1; + } + int err = mbedtls_ssl_conf_own_cert(conf, &cert->cert, &cert->pk); + if (err != 0) { +#if OC_WRN_IS_ENABLED + char credid_str[16]; + memset(credid_str, 0, sizeof(credid_str)); + if (credid == OC_TLS_SELECTED_ANY_CRED_ID) { + strncpy(credid_str, "any", sizeof(credid_str)); + } else { + snprintf(credid_str, sizeof(credid_str), "%d", credid); + } + char buf[128]; + mbedtls_strerror(err, buf, sizeof(buf)); + OC_WRN("cannot set client %s certificate(selected %s): %s", + credusage == OC_CREDUSAGE_MFG_CERT ? "manufacturer" : "identity", + credid_str, buf); +#endif /* OC_WRN_IS_ENABLED */ return -1; } return 0; } -static int +int oc_tls_load_mfg_cert_chain(mbedtls_ssl_config *conf, size_t device, int credid) { OC_DBG("loading manufacturer cert chain"); @@ -1364,10 +1431,15 @@ oc_tls_load_mfg_cert_chain(mbedtls_ssl_config *conf, size_t device, int credid) OC_CREDUSAGE_MFG_CERT, credid); } -static int +int oc_tls_load_identity_cert_chain(mbedtls_ssl_config *conf, size_t device, int credid) { + if (credid < OC_TLS_SELECTED_ANY_CRED_ID) { + // could be set when the application wants to use manufacturer certificate + // instead of identity certificate + return -1; + } OC_DBG("loading identity cert chain"); return oc_tls_configure_end_entity_cert_chain( conf, device, OC_CREDUSAGE_IDENTITY_CERT, credid); @@ -1504,6 +1576,18 @@ get_identity_cert_for_session(const mbedtls_ssl_config *conf) } return NULL; } + +bool +oc_tls_load_cert_chain(mbedtls_ssl_config *conf, size_t device, bool owned) +{ + /* Decide between configuring the identity cert chain vs manufacturer cert + * chain for this device based on device ownership status. + */ + return (owned && oc_tls_load_identity_cert_chain(conf, device, + g_selected_id_cred) == 0) || + (oc_tls_load_mfg_cert_chain(conf, device, g_selected_mfg_cred) == 0); +} + #endif /* OC_PKI */ static void @@ -1514,20 +1598,14 @@ oc_tls_set_ciphersuites(mbedtls_ssl_config *conf, const oc_endpoint_t *endpoint) #ifdef OC_CLIENT bool loaded_chain = false; #endif /* OC_CLIENT */ - size_t device = endpoint->device; - const oc_sec_doxm_t *doxm = oc_sec_get_doxm(device); - /* Decide between configuring the identity cert chain vs manufacturer cert - * chain for this device based on device ownership status. - */ - if ((doxm->owned && oc_tls_load_identity_cert_chain( - conf, device, g_selected_id_cred) == 0) || - (oc_tls_load_mfg_cert_chain(conf, device, g_selected_mfg_cred) == 0)) { + const oc_sec_doxm_t *doxm = oc_sec_get_doxm(endpoint->device); + if (oc_tls_load_cert_chain(conf, endpoint->device, doxm->owned)) { #ifdef OC_CLIENT loaded_chain = true; #endif /* OC_CLIENT */ } - g_selected_mfg_cred = -1; - g_selected_id_cred = -1; + g_selected_mfg_cred = OC_TLS_SELECTED_ANY_CRED_ID; + g_selected_id_cred = OC_TLS_SELECTED_ANY_CRED_ID; #endif /* OC_PKI */ const oc_sec_pstat_t *ps = oc_sec_get_pstat(endpoint->device); if (conf->endpoint == MBEDTLS_SSL_IS_SERVER && ps->s == OC_DOS_RFOTM) { @@ -2403,11 +2481,10 @@ oc_tls_send_message_internal(oc_message_t *message) } if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { -#if defined(OC_DEBUG) && OC_ERR_IS_ENABLED - char buf[256]; // NOLINT(readability-magic-numbers) - mbedtls_strerror(ret, buf, OC_ARRAY_SIZE(buf)); - OC_ERR("oc_tls: mbedtls_error: %s", buf); -#endif /* OC_DEBUG && OC_ERR_IS_ENABLED */ + TLS_LOG_MBEDTLS_ERROR((peer->endpoint.flags & TCP) != 0 + ? "ssl_write_tcp" + : "mbedtls_ssl_write", + ret); oc_tls_free_peer(peer, false); } else { length = message->length; @@ -2457,11 +2534,10 @@ write_application_data(oc_tls_peer_t *peer) oc_message_unref(message); if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { -#if defined(OC_DEBUG) && OC_ERR_IS_ENABLED - char buf[256]; // NOLINT(readability-magic-numbers) - mbedtls_strerror(ret, buf, OC_ARRAY_SIZE(buf)); - OC_ERR("oc_tls: mbedtls_error: %s", buf); -#endif /* OC_DEBUG && OC_ERR_IS_ENABLED */ + TLS_LOG_MBEDTLS_ERROR((peer->endpoint.flags & TCP) != 0 + ? "ssl_write_tcp" + : "mbedtls_ssl_write", + ret); oc_tls_free_peer(peer, false); break; } @@ -2475,11 +2551,7 @@ oc_tls_handshake(oc_tls_peer_t *peer) int ret = mbedtls_ssl_handshake(&peer->ssl_ctx); if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { -#if defined(OC_DEBUG) && OC_ERR_IS_ENABLED - char buf[256]; // NOLINT(readability-magic-numbers) - mbedtls_strerror(ret, buf, OC_ARRAY_SIZE(buf)); - OC_ERR("oc_tls: mbedtls_error: %s", buf); -#endif /* OC_DEBUG && OC_ERR_IS_ENABLED */ + TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_handshake", ret); oc_tls_free_peer(peer, false); return; } @@ -2504,6 +2576,7 @@ oc_tls_on_tcp_connect(const oc_endpoint_t *endpoint, int state, void *data) oc_tls_handshake(peer); return; } + OC_ERR("oc_tls_on_tcp_connect: ends with error state: %d", state); oc_tls_free_peer(peer, false); } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ @@ -2569,7 +2642,9 @@ oc_tls_init_connection(oc_message_t *message) oc_message_unref(message); return; } - + OC_ERR( + "oc_tls_init_connection: oc_tcp_connect returns unexpected state: %d", + state); oc_tls_free_peer(peer, false); oc_message_unref(message); return; @@ -2631,25 +2706,6 @@ assert_all_roles_internal(oc_client_response_t *data) #define DEFAULT_RECEIVE_SIZE \ (COAP_TCP_DEFAULT_HEADER_LEN + COAP_TCP_MAX_EXTENDED_LENGTH_LEN) -static void -tls_read_application_data_tcp_error(int err) -{ - if (err == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - OC_DBG("oc_tls_tcp: Close-Notify received"); - return; - } - if (err == MBEDTLS_ERR_SSL_CLIENT_RECONNECT) { - OC_DBG("oc_tls_tcp: Client wants to reconnect"); - return; - } - -#if defined(OC_DEBUG) && OC_ERR_IS_ENABLED - char buf[256]; // NOLINT(readability-magic-numbers) - mbedtls_strerror(err, buf, OC_ARRAY_SIZE(buf)); - OC_ERR("oc_tls_tcp: mbedtls_error: %s", buf); -#endif /* OC_DEBUG && OC_ERR_IS_ENABLED */ -} - static void tls_read_application_data_tcp(oc_tls_peer_t *peer) { @@ -2691,8 +2747,6 @@ tls_read_application_data_tcp(oc_tls_peer_t *peer) OC_DBG("oc_tls_tcp: Received WantRead/WantWrite"); return; } - tls_read_application_data_tcp_error(ret); - oc_message_unref(peer->processed_recv_message); peer->processed_recv_message = NULL; if (peer->role == MBEDTLS_SSL_IS_SERVER && @@ -2700,6 +2754,7 @@ tls_read_application_data_tcp(oc_tls_peer_t *peer) mbedtls_ssl_close_notify(&peer->ssl_ctx); mbedtls_ssl_close_notify(&peer->ssl_ctx); } + TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_read", ret); oc_tls_free_peer(peer, false); return; } @@ -2725,25 +2780,6 @@ tls_read_application_data_tcp(oc_tls_peer_t *peer) } #endif /* OC_TCP */ -static void -tls_read_application_data_error(int err) -{ - if (err == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - OC_DBG("oc_tls: Close-Notify received"); - return; - } - if (err == MBEDTLS_ERR_SSL_CLIENT_RECONNECT) { - OC_DBG("oc_tls: Client wants to reconnect"); - return; - } - -#if defined(OC_DEBUG) && OC_ERR_IS_ENABLED - char buf[256]; - mbedtls_strerror(err, buf, OC_ARRAY_SIZE(buf)); - OC_ERR("oc_tls: mbedtls_error: %s", buf); -#endif /* OC_DEBUG && OC_ERR_IS_ENABLED */ -} - static void tls_handshake_step(oc_tls_peer_t *peer) { @@ -2756,7 +2792,7 @@ tls_handshake_step(oc_tls_peer_t *peer) mbedtls_ssl_set_client_transport_id( &peer->ssl_ctx, (const unsigned char *)&peer->endpoint.addr, sizeof(peer->endpoint.addr)) != 0) { - OC_ERR("oc_tls: mbedtls_ssl_set_client_transport_id failed"); + TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_set_client_transport_id", ret); oc_tls_free_peer(peer, false); return; } @@ -2767,11 +2803,7 @@ tls_handshake_step(oc_tls_peer_t *peer) ret == MBEDTLS_ERR_SSL_WANT_WRITE) { break; } -#if defined(OC_DEBUG) && OC_ERR_IS_ENABLED - char buf[256]; // NOLINT(readability-magic-numbers) - mbedtls_strerror(ret, buf, OC_ARRAY_SIZE(buf)); - OC_ERR("oc_tls: mbedtls_error: %s", buf); -#endif /* OC_DEBUG && OC_ERR_IS_ENABLED */ + TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_handshake_step", ret); oc_tls_free_peer(peer, false); return; } @@ -2821,7 +2853,7 @@ tls_read_application_data_udp(oc_tls_peer_t *peer) OC_DBG("oc_tls: Received WantRead/WantWrite"); return; } - tls_read_application_data_error(ret); + TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_read", ret); if (peer->role == MBEDTLS_SSL_IS_SERVER && (peer->endpoint.flags & TCP) == 0) { mbedtls_ssl_close_notify(&peer->ssl_ctx); diff --git a/security/oc_tls_internal.h b/security/oc_tls_internal.h index bc6cb07dee..ff4c2b25b3 100644 --- a/security/oc_tls_internal.h +++ b/security/oc_tls_internal.h @@ -224,8 +224,39 @@ bool oc_tls_uses_psk_cred(const oc_tls_peer_t *peer); /* Public APIs for selecting certificate credentials */ void oc_tls_select_cert_ciphersuite(void); + +/** + * This function establishes an interface with the aim of selecting manufacturer + * credentials within the client role, which are consequently applied during the + * TLS handshake procedure. + * + * Internally employed by the stack, these interface methods serve to pinpoint + * the suitable manufacturer certificate credentials for a specific peer.It's + * crucial to note that these methods are not designed to be thread-safe. + * + * @param credid The designated credential ID: opt for -1 to allow the selection + * from any credential, or choose a value less than -1 to deactivate credential + * selection entirely. + */ void oc_tls_select_mfg_cert_chain(int credid); + +/** + * This function defines an interface aimed at the task of choosing identity + * credentials within the client role, which are subsequently applied during + * the TLS handshake procedure. + * + * These interface methods are utilized internally by the stack to determine + * the suitable identity certificate credentials for a given peer. It's crucial + * to note that these methods are not designed to be thread-safe. + * + * @param credid The chosen credential ID; use -1 to allow selection from any + * credential, and use a value less than -1 to deactivate credential selection. + * + * @note If the intention is to enforce the use of the manufacturer's + * certificate rather than the identity certificate, simply set credid to -2. + */ void oc_tls_select_identity_cert_chain(int credid); + void oc_tls_select_psk_ciphersuite(void); void oc_tls_select_anon_ciphersuite(void); void oc_tls_select_cloud_ciphersuite(void); @@ -325,6 +356,41 @@ mbedtls_x509_crt *oc_tls_get_trust_anchor_for_cred(const oc_sec_cred_t *cred); */ mbedtls_x509_crt *oc_tls_get_trust_anchors(void); +/** + * @brief Check global lists of credentials and trust anchors that they + * contain the same items. + * + * @return true if the lists of trust anchors are consistent with each + * other + * @return false otherwise + */ +int oc_tls_load_mfg_cert_chain(mbedtls_ssl_config *conf, size_t device, + int credid); + +/** + * @brief Check global lists of credentials and trust anchors that they + * contain the same items. + * + * @return true if the lists of trust anchors are consistent with each + * other + * @return false otherwise + */ +int oc_tls_load_identity_cert_chain(mbedtls_ssl_config *conf, size_t device, + int credid); + +/** + * @brief Set up trust anchor and certificate chain for device to mbedtls ssl + * config. + * + * @param conf mbedtls ssl config + * @param device device index + * @param owned true if device is owned + * @return true success + * @return false failure + */ +bool oc_tls_load_cert_chain(mbedtls_ssl_config *conf, size_t device, + bool owned); + #ifdef OC_TEST /** * @brief Check global lists of credentials and identity certificates that they @@ -345,6 +411,7 @@ bool oc_tls_validate_identity_certs_consistency(void); * @return false otherwise */ bool oc_tls_validate_trust_anchors_consistency(void); + #endif /* OC_TEST */ #endif /* OC_PKI */ diff --git a/security/unittest/tls_cert_test.cpp b/security/unittest/tls_cert_test.cpp index fa36641056..2ba669c13a 100644 --- a/security/unittest/tls_cert_test.cpp +++ b/security/unittest/tls_cert_test.cpp @@ -71,9 +71,9 @@ class TestTlsCertificates : public testing::Test { device_ = oc_core_get_num_devices() - 1; EXPECT_GE(device_, 0); - ASSERT_TRUE(idcert1_.Add(device_)); - ASSERT_TRUE(subca1_.Add(device_, idcert1_.CredentialID())); - ASSERT_TRUE(idcert2_.Add(device_)); + ASSERT_TRUE(mfgcert_.Add(device_)); + ASSERT_TRUE(subca1_.Add(device_, mfgcert_.CredentialID())); + ASSERT_TRUE(idcert_.Add(device_)); ASSERT_TRUE(rootca1_.Add(device_)); ASSERT_TRUE(rootca2_.Add(device_)); } @@ -93,12 +93,11 @@ class TestTlsCertificates : public testing::Test { } int device_{ -1 }; - oc::pki::IdentityCertificate idcert1_{ "pki_certs/ee.pem", + oc::pki::IdentityCertificate mfgcert_{ "pki_certs/ee.pem", "pki_certs/key.pem", true }; - oc::pki::IdentityCertificate idcert2_{ - "pki_certs/certification_tests_ee.pem", - "pki_certs/certification_tests_key.pem", true - }; + oc::pki::IdentityCertificate idcert_{ "pki_certs/certification_tests_ee.pem", + "pki_certs/certification_tests_key.pem", + false }; oc::pki::IntermediateCertificate subca1_{ "pki_certs/subca1.pem" }; oc::pki::TrustAnchor rootca1_{ "pki_certs/rootca1.pem", true }; oc::pki::TrustAnchor rootca2_{ "pki_certs/rootca2.pem", true }; @@ -123,7 +122,7 @@ oc_sec_cred_count(size_t device) TEST_F(TestTlsCertificates, ClearCertificates) { - // 4 = 2 root certificates + 2 mfg certs + // 4 = 2 root certificates + 1 mfg certs + 1 identity certificate EXPECT_EQ(4, oc_sec_cred_count(device_)); oc_sec_cred_clear( @@ -131,28 +130,28 @@ TEST_F(TestTlsCertificates, ClearCertificates) EXPECT_EQ(4, oc_sec_cred_count(device_)); EXPECT_NE(nullptr, - oc_sec_get_cred_by_credid(idcert1_.CredentialID(), device_)); + oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), device_)); oc_sec_cred_clear( device_, [](const oc_sec_cred_t *cred, void *data) { const auto *cert = static_cast(data); return cred->credid == cert->CredentialID(); }, - &idcert1_); + &mfgcert_); EXPECT_EQ(3, oc_sec_cred_count(device_)); EXPECT_EQ(nullptr, - oc_sec_get_cred_by_credid(idcert1_.CredentialID(), device_)); + oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), device_)); EXPECT_NE(nullptr, - oc_sec_get_cred_by_credid(idcert2_.CredentialID(), device_)); + oc_sec_get_cred_by_credid(idcert_.CredentialID(), device_)); auto removeMfgCert = [](const oc_sec_cred_t *cred, void *) { return cred->credtype == OC_CREDTYPE_CERT && cred->credusage == OC_CREDUSAGE_MFG_CERT; }; oc_sec_cred_clear(device_, removeMfgCert, nullptr); - EXPECT_EQ(2, oc_sec_cred_count(device_)); + EXPECT_EQ(3, oc_sec_cred_count(device_)); EXPECT_EQ(nullptr, - oc_sec_get_cred_by_credid(idcert2_.CredentialID(), device_)); + oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), device_)); oc_sec_cred_clear(device_, nullptr, nullptr); EXPECT_EQ(0, oc_sec_cred_count(device_)); @@ -163,9 +162,9 @@ TEST_F(TestTlsCertificates, ClearCertificates) TEST_F(TestTlsCertificates, RemoveIdentityCertificates) { EXPECT_TRUE(oc_tls_validate_identity_certs_consistency()); - EXPECT_TRUE(oc_sec_remove_cred_by_credid(idcert1_.CredentialID(), device_)); + EXPECT_TRUE(oc_sec_remove_cred_by_credid(mfgcert_.CredentialID(), device_)); EXPECT_TRUE(oc_tls_validate_identity_certs_consistency()); - EXPECT_TRUE(oc_sec_remove_cred_by_credid(idcert2_.CredentialID(), device_)); + EXPECT_TRUE(oc_sec_remove_cred_by_credid(idcert_.CredentialID(), device_)); EXPECT_TRUE(oc_tls_validate_identity_certs_consistency()); } @@ -178,6 +177,60 @@ TEST_F(TestTlsCertificates, RemoveTrustAnchors) EXPECT_TRUE(oc_tls_validate_trust_anchors_consistency()); } +static void +test_oc_tls_load_cert_chain_selected(exp int, device size_t, credid int, + int (*fn)(mbedtls_x509_crt *crt, + device size_t, credid int)) +{ + mbedtls_ssl_config conf = {}; + mbedtls_ssl_config_init(&conf); + EXPECT_EQ(exp, fn(&conf, device, credid)); + mbedtls_ssl_config_free(&conf); +} + +static void +test_oc_tls_load_cert_chain(exp bool, device size_t, owned bool) +{ + mbedtls_ssl_config conf = {}; + mbedtls_ssl_config_init(&conf); + EXPECT_EQ(exp, oc_tls_load_cert_chain(&conf, device, owned)); + mbedtls_ssl_config_free(&conf); +} + +TEST_F(TestTlsCertificates, LoadClientCertificateToMbedtls) +{ + EXPECT_EQ(4, oc_sec_cred_count(device_)); + test_oc_tls_load_cert_chain_selected(0, device_, mfgcert_.CredentialID(), + oc_tls_load_mfg_cert_chain); + test_oc_tls_load_cert_chain_selected(0, device_, -1, + oc_tls_load_mfg_cert_chain); + test_oc_tls_load_cert_chain_selected(-1, device_, -2, + oc_tls_load_mfg_cert_chain); + + test_oc_tls_load_cert_chain_selected(0, device_, idcert_.CredentialID(), + oc_tls_load_identity_cert_chain); + test_oc_tls_load_cert_chain_selected(0, device_, -1, + oc_tls_load_identity_cert_chain); + test_oc_tls_load_cert_chain_selected(-1, device_, -2, + oc_tls_load_identity_cert_chain); + + oc_tls_select_mfg_cert_chain(-2); + oc_tls_select_identity_cert_chain(-1); + test_oc_tls_load_cert_chain(true, device_, true); + oc_tls_select_identity_cert_chain(idcert_.CredentialID()); + test_oc_tls_load_cert_chain(true, device_, true); + + oc_tls_select_identity_cert_chain(-2); + oc_tls_select_mfg_cert_chain(-1); + .test_oc_tls_load_cert_chain(true, device_, true); + oc_tls_select_mfg_cert_chain(mfgcert_.CredentialID()); + test_oc_tls_load_cert_chain(true, device_, true); + + oc_tls_select_identity_cert_chain(-2); + oc_tls_select_mfg_cert_chain(-2); + test_oc_tls_load_cert_chain(false, device_, true); +} + #endif /* OC_TEST */ TEST_F(TestTlsCertificates, VerifyCredCerts) @@ -198,8 +251,8 @@ TEST_F(TestTlsCertificates, VerifyCredCerts) EXPECT_EQ( 0, oc_cred_verify_certificate_chain(cred, verify_cert_validity, nullptr)); - // expired - idcert1_ valid_from: 14.4.2020, valid_to: 14.5.2020 - cred = oc_sec_get_cred_by_credid(idcert1_.CredentialID(), device_); + // expired - mfgcert_ valid_from: 14.4.2020, valid_to: 14.5.2020 + cred = oc_sec_get_cred_by_credid(mfgcert_.CredentialID(), device_); EXPECT_NE(nullptr, cred); EXPECT_EQ( 1, oc_cred_verify_certificate_chain(cred, verify_cert_validity, nullptr));