diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index ce5bb376b0ff..a889ead699b4 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1221,6 +1221,10 @@ struct mbedtls_ssl_config /** Callback to customize X.509 certificate chain verification */ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); void *p_vrfy; /*!< context for X.509 verify calllback */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + int (*f_verify_callback)(void *, const mbedtls_x509_crt *, const char *); + void *p_verify_callback; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) @@ -1953,6 +1957,25 @@ void mbedtls_ssl_conf_early_data(mbedtls_ssl_config* conf, int early_data, char* void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ); +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) +/** + * \brief Set the verification callback (Optional). + * + * If the application does not explicitly specify a + * verification callback function, the built-in verification + * function is used. If a verification callback is specified via + * mbedtls_ssl_conf_set_verify_callback(), the supplied callback + * function is called instead. By setting callback to NULL, the + * default behaviour is restored. + * + * \param conf SSL configuration + * \param f_verify_callback verification function + * \param p_verify_callback verification parameter + */ +void mbedtls_ssl_conf_set_verify_callback( mbedtls_ssl_config *conf, + int (*f_verify_callback)(void *, const mbedtls_x509_crt *, const char *), + void *p_verify_callback ); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) && defined(MBEDTLS_X509_CRT_PARSE_C) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b43cd79eda07..30c571fde550 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4514,6 +4514,16 @@ void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, conf->f_vrfy = f_vrfy; conf->p_vrfy = p_vrfy; } + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) +void mbedtls_ssl_conf_set_verify_callback( mbedtls_ssl_config *conf, + int (*f_verify_callback)(void *, const mbedtls_x509_crt *, const char *), + void *p_verify_callback ) { + conf->f_verify_callback = f_verify_callback; + conf->p_verify_callback = p_verify_callback; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + #endif /* MBEDTLS_X509_CRT_PARSE_C */ void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 6bcb3d604a09..320103678637 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -2912,8 +2912,9 @@ static int ssl_read_certificate_validate( mbedtls_ssl_context* ssl ) { int ret = 0; int authmode = ssl->conf->authmode; - mbedtls_x509_crt* ca_chain; - mbedtls_x509_crl* ca_crl; + int have_ca_chain = 0; + mbedtls_x509_crt* ca_chain = NULL; + mbedtls_x509_crl* ca_crl = NULL; /* If SNI was used, overwrite authentication mode * from the configuration. */ @@ -2961,6 +2962,21 @@ static int ssl_read_certificate_validate( mbedtls_ssl_context* ssl ) return( 0 ); } +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->conf->f_verify_callback) { + if (ssl->conf->f_verify_callback( + ssl->conf->p_verify_callback, + ssl->session_negotiate->peer_cert, + ssl->hostname) != 0) + { + ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_OTHER; + ret = MBEDTLS_ERR_X509_CERT_VERIFY_FAILED; + } + have_ca_chain = 1; + } + else +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if( ssl->handshake->sni_ca_chain != NULL ) { @@ -2974,6 +2990,8 @@ static int ssl_read_certificate_validate( mbedtls_ssl_context* ssl ) ca_crl = ssl->conf->ca_crl; } + if( ca_chain != NULL ) + have_ca_chain = 1; /* * Main check: verify certificate */ @@ -2984,10 +3002,13 @@ static int ssl_read_certificate_validate( mbedtls_ssl_context* ssl ) ssl->hostname, &ssl->session_negotiate->verify_result, ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + } if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN); } /* @@ -3034,7 +3055,7 @@ static int ssl_read_certificate_validate( mbedtls_ssl_context* ssl ) ret = 0; } - if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + if( have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;