From 4ba48dde56db93e6e0f93fa342f866773cf28b6c Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Fri, 23 Feb 2018 17:12:49 +0200 Subject: [PATCH] Enable allowing unsupported critical extensions in runtime When compile time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION is not set, certificate parsing fails if certificate contains unsupported critical extension. This patch allows to modify this behavior in runtime. Signed-off-by: Lev Stipakov --- include/mbedtls/ssl.h | 22 ++++++++++++++++++++++ include/mbedtls/x509_crt.h | 2 ++ library/ssl_tls.c | 11 +++++++++++ library/x509_crt.c | 10 ++++++++-- tests/data_files/test-ca-nc.crt | 20 ++++++++++++++++++++ tests/suites/test_suite_x509parse.data | 6 ++++++ tests/suites/test_suite_x509parse.function | 15 +++++++++++++++ 7 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 tests/data_files/test-ca-nc.crt diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 655f59d328c..5f454cb2694 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1063,6 +1063,10 @@ struct mbedtls_ssl_config retransmission timeout (ms) */ #endif + uint32_t allowed_unsupported_critical_exts; /*!< Bit flags which represent runtime-enabled + unsupported critical extensions, e.g. + MBEDTLS_X509_EXT_NAME_CONSTRAINTS */ + #if defined(MBEDTLS_SSL_RENEGOTIATION) int renego_max_records; /*!< grace period for renegotiation */ unsigned char renego_period[8]; /*!< value of the record counters @@ -3392,6 +3396,24 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, const unsigned char period[8] ); #endif /* MBEDTLS_SSL_RENEGOTIATION */ +/** + * \brief Allows unsupported critical extensions + * + * Without compile-time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * mbedTLS fails certificate verification if certificate contains + * unsupported critical extensions. + * + * This method allows to modify behavior in runtime by providing + * bit flags which represent unsupported extensions (for example MBEDTLS_X509_EXT_NAME_CONSTRAINTS) + * which should be allowed despite missing above mentioned compile-time flag. + * + * \param conf SSL configuration + * \param exts Bit flags which represent runtime-enabled unsupported critical extensions, + * e.g. MBEDTLS_X509_EXT_NAME_CONSTRAINTS + * + */ +void mbedtls_ssl_conf_allow_unsupported_critical_exts( mbedtls_ssl_config *conf, uint32_t exts ); + /** * \brief Check if there is data already read from the * underlying transport but not yet processed. diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index e4fb1354329..7380a3dae7b 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -96,6 +96,8 @@ typedef struct mbedtls_x509_crt mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + uint32_t allowed_unsupported_critical_exts; /**< Optional Bit flags which represent runtime-enabled unsupported critical extensions, e.g. MBEDTLS_X509_EXT_NAME_CONSTRAINTS */ + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ } mbedtls_x509_crt; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 63bc5c850c5..76d01dfb8ec 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2250,6 +2250,12 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } + if (ssl->session_negotiate->peer_cert != NULL) + { + ssl->session_negotiate->peer_cert->allowed_unsupported_critical_exts = + ssl->conf->allowed_unsupported_critical_exts; + } + /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */ i += 3; @@ -4670,6 +4676,11 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, } #endif /* MBEDTLS_SSL_RENEGOTIATION */ +void mbedtls_ssl_conf_allow_unsupported_critical_exts( mbedtls_ssl_config *conf, uint32_t exts ) +{ + conf->allowed_unsupported_critical_exts = exts; +} + #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_CLI_C) void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) diff --git a/library/x509_crt.c b/library/x509_crt.c index 1e472303b16..3f75c49378d 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -891,6 +891,7 @@ static int x509_get_crt_ext( unsigned char **p, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *end_ext_data, *end_ext_octet; + int is_supported; if( *p == end ) return( 0 ); @@ -945,9 +946,9 @@ static int x509_get_crt_ext( unsigned char **p, /* * Detect supported extensions */ - ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + ret = mbedtls_oid_get_x509_ext_type_supported( &extn_oid, &ext_type, &is_supported ); - if( ret != 0 ) + if( ( ret != 0 ) || ( is_supported == 0 ) ) { /* No parser found, skip extension */ *p = end_ext_octet; @@ -955,6 +956,10 @@ static int x509_get_crt_ext( unsigned char **p, #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) if( is_critical ) { + /* Do not fail if extension is found, but unsupported and allowed in runtime */ + if( ( ret == 0 ) && ( ext_type & crt->allowed_unsupported_critical_exts ) ) + continue; + /* Data is marked as critical: fail */ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); @@ -1346,6 +1351,7 @@ static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain, prev = crt; mbedtls_x509_crt_init( crt->next ); + crt->next->allowed_unsupported_critical_exts = crt->allowed_unsupported_critical_exts; crt = crt->next; } diff --git a/tests/data_files/test-ca-nc.crt b/tests/data_files/test-ca-nc.crt new file mode 100644 index 00000000000..7e0c561340d --- /dev/null +++ b/tests/data_files/test-ca-nc.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDSzCCAjOgAwIBAgIJAJx/NjT4C4viMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV +BAMMCExlZXZpQ0E0MB4XDTE4MDEyNzE1MDczMloXDTI4MDEyNTE1MDczMlowEzER +MA8GA1UEAwwITGVldmlDQTQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDWN79RTlyFm5o0LVMSVjc68W0+gtl95xpaaD7IS6gDYjcbGnCwSefiq7y9rtck +OM1A5Bzhj5+iWbmZStUmeJUhSGgxP/FxuUaAV0fsBGJ5jDrzmbhzDkHsNxDMB2ks +XFyy4LfODcBs9TXxY43KUKuq/0meiT3WAaZWHMYle9vkQJM2l0RyH4IXHCHiIRwd +2wntin6T9QOFJOc2ietNb7KsXVne81wb7h9BVMsjCIAsbPpHa+PZQs1xFuxmRxCs +kpavnMy+SqevHhvqtvbHppcXYtZspTnkVoXWUdx3HHXgZMQKlAWlwyx57xpZBU2g +qksO+KCLVYOQMN9usmuMOpHHAgMBAAGjgaEwgZ4wHQYDVR0eAQH/BBMwEaAPMA2C +C2V4YW1wbGUuY29tMB0GA1UdDgQWBBR3T9IilPeRAFfLO8ocg216OBo+6DBDBgNV +HSMEPDA6gBR3T9IilPeRAFfLO8ocg216OBo+6KEXpBUwEzERMA8GA1UEAwwITGVl +dmlDQTSCCQCcfzY0+AuL4jAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkq +hkiG9w0BAQsFAAOCAQEAR086ciNM3ujSQNhhguqFHYGfDRRuAgOk4l7GXIfFa9te +B2KMLSwP367QaMwFxRrOoDvixIjzbpiiKB3cv+IXqGyfsRJw47XLwGK4FtSsXjst +m2M8W5iXBQ94XoLj9OKb4ZJWKI930S/PF7uuxICtWttYSoylfyMkiR45+1SLj2eF +X4EnXK3Q0H42v8LCDFqj9iNQ2WMLwA7kFPB+oOZxkFi2G0F3VuW+JZeBPQCpYdRO +0kQQ/gIZE6KEdscKHi9y6OfGSeRlDBMADky9NiZy7I3AcspLcmMQh/191/DnooNe +OwQ6w1HweApjB46bGyILpGUi9MZhvCnoLWg+cN3/wQ== +-----END CERTIFICATE----- diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index b3e36130076..6f1e7b3bc9a 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -2518,6 +2518,12 @@ X509 File parse (trailing spaces, OK) depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C x509parse_crt_file:"data_files/server7_trailing_space.crt":0 +X509 File parse (unsupported critical ext Name Constraints, fail) +x509parse_crt_file:"data_files/test-ca-nc.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG + +X509 File parse (allowed unsupported critical ext Name Constraints, ok) +x509parse_crt_file_allow_exts:"data_files/test-ca-nc.crt":MBEDTLS_X509_EXT_NAME_CONSTRAINTS:0 + X509 Get time (UTC no issues) depends_on:MBEDTLS_X509_USE_C x509_get_time:MBEDTLS_ASN1_UTC_TIME:"500101000000Z":0:1950:1:1:0:0:0 diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index 85ff41df27a..2d4e2e4dcb1 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -735,6 +735,21 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_FS_IO */ +void x509parse_crt_file_allow_exts( char *crt_file, int exts, int result ) +{ + mbedtls_x509_crt crt; + + mbedtls_x509_crt_init( &crt ); + crt.allowed_unsupported_critical_exts = exts; + + TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == result ); + +exit: + mbedtls_x509_crt_free( &crt ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */ void x509parse_crt( data_t * buf, char * result_str, int result ) {