Skip to content

Commit ff531d3

Browse files
author
Mika Leppänen
committed
Added IDevID and LDevID certificate validation
Border Router (authenticator) now forces nodes i.e. clients to use IDevID/LDevID (top) certificates defined by Wi-SUN. Client certificate must contain SubjectAlternativeName extension (SANE) with OtherName of type id-on-hardwareModuleName containing hwType and hwSerialNum. HW type and serial are traced by TLS library interface module. Certificate must also contain ExtendedKeyUsage with id-kp-wisun-fan-device object identifier. Clients verify now that if either id-on-hardwareModuleName or ExtendedKeyUsage is present with Wi-SUN fields in Server certificate, both of them shall be present and valid. Added also check for all certificates that certificates are signed with SHA256withECDSA to certification validation callback.
1 parent b30635f commit ff531d3

File tree

1 file changed

+146
-8
lines changed

1 file changed

+146
-8
lines changed

source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c

Lines changed: 146 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "mbedtls/ctr_drbg.h"
5050
#include "mbedtls/ssl_ciphersuites.h"
5151
#include "mbedtls/debug.h"
52+
#include "mbedtls/oid.h"
5253

5354
#include "mbedtls/ssl_internal.h"
5455

@@ -57,7 +58,10 @@
5758
#define TLS_HANDSHAKE_TIMEOUT_MIN 25000
5859
#define TLS_HANDSHAKE_TIMEOUT_MAX 201000
5960

60-
//#define TLS_SEC_PROT_LIB_TLS_DEBUG // Enable mbed TLS debug traces
61+
//#define TLS_SEC_PROT_LIB_TLS_DEBUG // Enable mbed TLS debug traces
62+
#define TLS_SEC_PROT_LIB_CERT_VALID_SKIP // Skip certificate validation
63+
64+
typedef int tls_sec_prot_lib_crt_verify_cb(mbedtls_x509_crt *crt, uint32_t *flags);
6165

6266
struct tls_security_s {
6367
mbedtls_ssl_config conf; /**< mbed TLS SSL configuration */
@@ -71,6 +75,7 @@ struct tls_security_s {
7175
mbedtls_x509_crt owncert; /**< Own certificate(s) */
7276
mbedtls_pk_context pkey; /**< Private key for own certificate */
7377
void *handle; /**< Handle provided in callbacks (defined by library user) */
78+
tls_sec_prot_lib_crt_verify_cb *crt_verify; /**< Verify function for top certificate */
7479
tls_sec_prot_lib_send *send; /**< Send callback */
7580
tls_sec_prot_lib_receive *receive; /**< Receive callback */
7681
tls_sec_prot_lib_export_keys *export_keys; /**< Export keys callback */
@@ -88,15 +93,23 @@ static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char
8893
size_t ivlen, const unsigned char client_random[32],
8994
const unsigned char server_random[32],
9095
mbedtls_tls_prf_types tls_prf_type);
96+
97+
static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags);
98+
static int8_t tls_sec_prot_lib_subject_alternative_name_validate(mbedtls_x509_crt *crt);
99+
static int8_t tls_sec_prot_lib_extended_key_usage_validate(mbedtls_x509_crt *crt);
100+
#ifdef HAVE_PAE_AUTH
101+
static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(mbedtls_x509_crt *crt, uint32_t *flags);
102+
#endif
103+
#ifdef HAVE_PAE_SUPP
104+
static int tls_sec_prot_lib_x509_crt_server_verify(mbedtls_x509_crt *crt, uint32_t *flags);
105+
#endif
91106
#ifdef TLS_SEC_PROT_LIB_TLS_DEBUG
92107
static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int line, const char *string);
93108
#endif
94-
95109
#ifdef MBEDTLS_PLATFORM_MEMORY
96110
// Disable for now
97111
//#define TLS_SEC_PROT_LIB_USE_MBEDTLS_PLATFORM_MEMORY
98112
#endif
99-
100113
#ifdef TLS_SEC_PROT_LIB_USE_MBEDTLS_PLATFORM_MEMORY
101114
static void *tls_sec_prot_lib_mem_calloc(size_t count, size_t size);
102115
static void tls_sec_prot_lib_mem_free(void *ptr);
@@ -272,18 +285,37 @@ static int tls_sec_prot_lib_configure_certificates(tls_security_t *sec, const se
272285
return 0;
273286
}
274287

288+
#if defined(HAVE_PAE_AUTH) && defined(HAVE_PAE_SUPP)
289+
#define is_server_is_set (is_server == true)
290+
#define is_server_is_not_set (is_server == false)
291+
#elif defined(HAVE_PAE_AUTH)
292+
#define is_server_is_set true
293+
#define is_server_is_not_set false
294+
#elif defined(HAVE_PAE_SUPP)
295+
#define is_server_is_set false
296+
#define is_server_is_not_set true
297+
#endif
298+
275299
int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_prot_certs_t *certs)
276300
{
277301
if (!sec) {
278302
return -1;
279303
}
280304

281-
int endpoint = MBEDTLS_SSL_IS_CLIENT;
282-
if (is_server) {
283-
endpoint = MBEDTLS_SSL_IS_SERVER;
305+
#ifdef HAVE_PAE_SUPP
306+
if (is_server_is_not_set) {
307+
sec->crt_verify = tls_sec_prot_lib_x509_crt_server_verify;
308+
}
309+
#endif
310+
#ifdef HAVE_PAE_AUTH
311+
if (is_server_is_set) {
312+
sec->crt_verify = tls_sec_prot_lib_x509_crt_idevid_ldevid_verify;
284313
}
314+
#endif
285315

286-
if ((mbedtls_ssl_config_defaults(&sec->conf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM, 0)) != 0) {
316+
if ((mbedtls_ssl_config_defaults(&sec->conf,
317+
is_server_is_set ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
318+
MBEDTLS_SSL_TRANSPORT_STREAM, 0)) != 0) {
287319
tr_error("config defaults fail");
288320
return -1;
289321
}
@@ -331,8 +363,11 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p
331363
mbedtls_ssl_conf_min_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3);
332364
mbedtls_ssl_conf_max_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3);
333365

366+
// Set certificate verify callback
367+
mbedtls_ssl_set_verify(&sec->ssl, tls_sec_prot_lib_x509_crt_verify, sec);
368+
334369
#ifdef MBEDTLS_ECP_RESTARTABLE
335-
if (endpoint == MBEDTLS_SSL_IS_SERVER) {
370+
if (is_server_is_set) {
336371
// Temporary to enable non blocking ECC */
337372
sec->ssl.handshake->ecrs_enabled = 1;
338373
}
@@ -433,6 +468,109 @@ static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char
433468
return 0;
434469
}
435470

471+
static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags)
472+
{
473+
/* MD/PK forced also by configuration flags and dynamic settings but still verified
474+
here to prevent invalid configurations/certificates */
475+
if (crt->sig_md != MBEDTLS_MD_SHA256) {
476+
tr_error("Invalid signature md algorithm");
477+
*flags |= MBEDTLS_X509_BADCRL_BAD_MD;
478+
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
479+
}
480+
if (crt->sig_pk != MBEDTLS_PK_ECDSA) {
481+
tr_error("Invalid signature pk algorithm");
482+
*flags |= MBEDTLS_X509_BADCRL_BAD_PK;
483+
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
484+
}
485+
486+
// Verify top certificate of the chain
487+
if (certificate_depth == 0) {
488+
tls_security_t *sec = (tls_security_t *)ctx;
489+
return sec->crt_verify(crt, flags);
490+
}
491+
492+
// No further checks for intermediate and root certificates at the moment
493+
return 0;
494+
}
495+
496+
static int8_t tls_sec_prot_lib_subject_alternative_name_validate(mbedtls_x509_crt *crt)
497+
{
498+
mbedtls_asn1_sequence *seq = &crt->subject_alt_names;
499+
int8_t result = -1;
500+
while (seq) {
501+
mbedtls_x509_subject_alternative_name san;
502+
int ret_value = mbedtls_x509_parse_subject_alt_name((mbedtls_x509_buf *)&seq->buf, &san);
503+
if (ret_value == 0 && san.type == MBEDTLS_X509_SAN_OTHER_NAME) {
504+
// id-on-hardwareModuleName must be present (1.3.6.1.5.5.7.8.4)
505+
if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &san.san.other_name.value.hardware_module_name.oid)) {
506+
// Traces hardwareModuleName (1.3.6.1.4.1.<enteprise number>.<model,version,etc.>)
507+
char buffer[30];
508+
ret_value = mbedtls_oid_get_numeric_string(buffer, sizeof(buffer), &san.san.other_name.value.hardware_module_name.oid);
509+
if (ret_value != MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
510+
tr_info("id-on-hardwareModuleName %s", buffer);
511+
}
512+
// Traces serial number as hex string
513+
mbedtls_x509_buf *val = &san.san.other_name.value.hardware_module_name.val;
514+
if (val->p) {
515+
tr_info("id-on-hardwareModuleName hwSerialNum %s", trace_array(val->p, val->len));
516+
}
517+
result = 0;
518+
}
519+
} else {
520+
tr_debug("Ignored subject alt name: %i", san.type);
521+
}
522+
seq = seq->next;
523+
}
524+
return result;
525+
}
526+
527+
static int8_t tls_sec_prot_lib_extended_key_usage_validate(mbedtls_x509_crt *crt)
528+
{
529+
// Extended key usage must be present
530+
if (mbedtls_x509_crt_check_extended_key_usage(crt, MBEDTLS_OID_WISUN_FAN, sizeof(MBEDTLS_OID_WISUN_FAN) - 1) != 0) {
531+
return -1; // FAIL
532+
}
533+
return 0;
534+
}
535+
536+
#ifdef HAVE_PAE_AUTH
537+
static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(mbedtls_x509_crt *crt, uint32_t *flags)
538+
{
539+
// For both IDevID and LDevId both subject alternative name or extended key usage must be valid
540+
if (tls_sec_prot_lib_subject_alternative_name_validate(crt) < 0 ||
541+
tls_sec_prot_lib_extended_key_usage_validate(crt) < 0) {
542+
tr_error("invalid cert");
543+
#ifndef TLS_SEC_PROT_LIB_CERT_VALID_SKIP
544+
*flags |= MBEDTLS_X509_BADCERT_OTHER;
545+
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
546+
#endif
547+
}
548+
return 0;
549+
}
550+
#endif
551+
552+
#ifdef HAVE_PAE_SUPP
553+
static int tls_sec_prot_lib_x509_crt_server_verify(mbedtls_x509_crt *crt, uint32_t *flags)
554+
{
555+
int8_t sane_res = tls_sec_prot_lib_subject_alternative_name_validate(crt);
556+
int8_t ext_key_res = tls_sec_prot_lib_extended_key_usage_validate(crt);
557+
558+
// If either subject alternative name or extended key usage is present
559+
if (sane_res >= 0 || ext_key_res >= 0) {
560+
// Then both subject alternative name and extended key usage must be valid
561+
if (sane_res < 0 || ext_key_res < 0) {
562+
tr_error("invalid cert");
563+
#ifndef TLS_SEC_PROT_LIB_CERT_VALID_SKIP
564+
*flags |= MBEDTLS_X509_BADCERT_OTHER;
565+
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
566+
#endif
567+
}
568+
}
569+
570+
return 0;
571+
}
572+
#endif
573+
436574
static int tls_sec_lib_entropy_poll(void *ctx, unsigned char *output, size_t len, size_t *olen)
437575
{
438576
(void)ctx;

0 commit comments

Comments
 (0)