diff --git a/ChangeLog.d/fix-critical-extension-handling.txt b/ChangeLog.d/fix-critical-extension-handling.txt new file mode 100644 index 0000000000..a0f8fcd2bb --- /dev/null +++ b/ChangeLog.d/fix-critical-extension-handling.txt @@ -0,0 +1,3 @@ +Bugfix + * Add critical extension handling support for TLS peer x509 certificates. + Fixes issue #7182. diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 00e28442d6..86250a47db 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1432,6 +1432,10 @@ struct mbedtls_ssl_config { /** Callback to customize X.509 certificate chain verification */ int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify calllback */ + + /** Callback to skip unsupported extentions */ + mbedtls_x509_crt_ext_cb_t MBEDTLS_PRIVATE(f_ext); + void *MBEDTLS_PRIVATE(p_ext); /*!< context for X.509 extention calllback */ #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) @@ -1649,6 +1653,10 @@ struct mbedtls_ssl_context { /** Callback to customize X.509 certificate chain verification */ int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify callback */ + + /** Callback to skip unsupported extentions */ + mbedtls_x509_crt_ext_cb_t MBEDTLS_PRIVATE(f_ext); + void *MBEDTLS_PRIVATE(p_ext); /*!< context for X.509 extention calllback */ #endif mbedtls_ssl_send_t *MBEDTLS_PRIVATE(f_send); /*!< Callback for network send */ @@ -2102,6 +2110,21 @@ void mbedtls_ssl_conf_max_early_data_size( void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); + +/** + * \brief Set the unsupported extention callback (Optional). + * + * If set, the provided extention callback is called whenever + * a certificate is parsed. For more information, please see + * the documentation of + * \c mbedtls_x509_crt_parse_der_with_ext_cb(). + * + * \param conf The SSL configuration to use. + * \param f_ext The extentions callback to use during CRT parsing. + * \param p_ext The opaque context to be passed to the callback. + */ +void mbedtls_ssl_conf_ext_cb(mbedtls_ssl_config *conf, mbedtls_x509_crt_ext_cb_t f_ext, + void *p_ext); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** @@ -2410,6 +2433,20 @@ void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu); void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); + +/** + * \brief Set a connection-specific extention callback (optional). + * + * If set, the provided extention callback is called whenever + * a certificate is parsed. For more information, please see + * the documentation of + * \c mbedtls_x509_crt_parse_der_with_ext_cb(). + * + * \param ssl The SSL context to use. + * \param f_ext The extentions callback to use during CRT parsing. + * \param p_ext The opaque context to be passed to the callback. + */ +void mbedtls_ssl_set_ext_cb(mbedtls_ssl_context *ssl, mbedtls_x509_crt_ext_cb_t f_ext, void *p_ext); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 0195576213..5651b8ed3c 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1472,6 +1472,12 @@ void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, conf->f_vrfy = f_vrfy; conf->p_vrfy = p_vrfy; } + +void mbedtls_ssl_conf_ext_cb(mbedtls_ssl_config *conf, mbedtls_x509_crt_ext_cb_t f_ext, void *p_ext) +{ + conf->f_ext = f_ext; + conf->p_ext = p_ext; +} #endif /* MBEDTLS_X509_CRT_PARSE_C */ void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, @@ -1754,6 +1760,12 @@ void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, ssl->f_vrfy = f_vrfy; ssl->p_vrfy = p_vrfy; } + +void mbedtls_ssl_set_ext_cb(mbedtls_ssl_context *ssl, mbedtls_x509_crt_ext_cb_t f_ext, void *p_ext) +{ + ssl->f_ext = f_ext; + ssl->p_ext = p_ext; +} #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -6946,12 +6958,30 @@ static int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl, /* Parse the next certificate in the chain. */ #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n); + enum { COPY_CRT = 1 }; #else - /* If we don't need to store the CRT chain permanently, parse - * it in-place from the input buffer instead of making a copy. */ - ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n); + enum { COPY_CRT = 0 }; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + mbedtls_x509_crt_ext_cb_t f_ext; + void *p_ext; + + if (ssl->f_ext != NULL) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific extension callback")); + f_ext = ssl->f_ext; + p_ext = ssl->p_ext; + } else { + MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific extension callback")); + f_ext = ssl->conf->f_ext; + p_ext = ssl->conf->p_ext; + } + + ret = mbedtls_x509_crt_parse_der_with_ext_cb(chain, + ssl->in_msg + i, + n, + COPY_CRT, + f_ext, + p_ext); switch (ret) { case 0: /*ok*/ case MBEDTLS_ERR_X509_UNKNOWN_OID: