diff --git a/library/ssl_client.c b/library/ssl_client.c index 345e608938..0bd00cd91a 100644 --- a/library/ssl_client.c +++ b/library/ssl_client.c @@ -29,19 +29,20 @@ static int ssl_write_hostname_ext(mbedtls_ssl_context *ssl, size_t *olen) { unsigned char *p = buf; + const char *hostname = mbedtls_ssl_get_hostname_pointer(ssl); size_t hostname_len; *olen = 0; - if (ssl->hostname == NULL) { + if (hostname == NULL) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding server name extension: %s", - ssl->hostname)); + hostname)); - hostname_len = strlen(ssl->hostname); + hostname_len = strlen(hostname); MBEDTLS_SSL_CHK_BUF_PTR(p, end, hostname_len + 9); @@ -85,7 +86,7 @@ static int ssl_write_hostname_ext(mbedtls_ssl_context *ssl, MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); p += 2; - memcpy(p, ssl->hostname, hostname_len); + memcpy(p, hostname, hostname_len); *olen = hostname_len + 9; @@ -881,13 +882,14 @@ static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const char *context_hostname = mbedtls_ssl_get_hostname_pointer(ssl); if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && ssl->handshake->resume) { - int hostname_mismatch = ssl->hostname != NULL || + int hostname_mismatch = context_hostname != NULL || session_negotiate->hostname != NULL; - if (ssl->hostname != NULL && session_negotiate->hostname != NULL) { + if (context_hostname != NULL && session_negotiate->hostname != NULL) { hostname_mismatch = strcmp( - ssl->hostname, session_negotiate->hostname) != 0; + context_hostname, session_negotiate->hostname) != 0; } if (hostname_mismatch) { @@ -898,7 +900,7 @@ static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl) } } else { return mbedtls_ssl_session_set_hostname(session_negotiate, - ssl->hostname); + context_hostname); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 7495ae3bec..37d26b414a 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -2899,6 +2899,18 @@ int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( unsigned char *buf, unsigned char *end); #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** Get the host name from the SSL context. + * + * \param[in] ssl SSL context + * + * \return The \p hostname pointer from the SSL context. + * \c NULL if mbedtls_ssl_set_hostname() has never been called on + * \p ssl or if it was last called with \p NULL. + */ +const char *mbedtls_ssl_get_hostname_pointer(const mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index c773365bf6..c3b7497946 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2757,6 +2757,46 @@ void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, } #if defined(MBEDTLS_X509_CRT_PARSE_C) + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/** Whether mbedtls_ssl_set_hostname() has been called. + * + * \param[in] ssl SSL context + * + * \return \c 1 if mbedtls_ssl_set_hostname() has been called on \p ssl + * (including `mbedtls_ssl_set_hostname(ssl, NULL)`), + * otherwise \c 0. + */ +static int mbedtls_ssl_has_set_hostname_been_called( + const mbedtls_ssl_context *ssl) +{ + /* We can't tell the difference between the case where + * mbedtls_ssl_set_hostname() has not been called at all, and + * the case where it was last called with NULL. For the time + * being, we assume the latter, i.e. we behave as if there had + * been an implicit call to mbedtls_ssl_set_hostname(ssl, NULL). */ + return ssl->hostname != NULL; +} +#endif + +/* Micro-optimization: don't export this function if it isn't needed outside + * of this source file. */ +#if !defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static +#endif +const char *mbedtls_ssl_get_hostname_pointer(const mbedtls_ssl_context *ssl) +{ + return ssl->hostname; +} + +static void mbedtls_ssl_free_hostname(mbedtls_ssl_context *ssl) +{ + if (ssl->hostname != NULL) { + mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); + } + ssl->hostname = NULL; +} + int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname) { /* Initialize to suppress unnecessary compiler warning */ @@ -2774,10 +2814,7 @@ int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname) /* Now it's clear that we will overwrite the old hostname, * so we can free it safely */ - - if (ssl->hostname != NULL) { - mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); - } + mbedtls_ssl_free_hostname(ssl); /* Passing NULL as hostname shall clear the old one */ @@ -5571,9 +5608,7 @@ void mbedtls_ssl_free(mbedtls_ssl_context *ssl) } #if defined(MBEDTLS_X509_CRT_PARSE_C) - if (ssl->hostname != NULL) { - mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); - } + mbedtls_ssl_free_hostname(ssl); #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) @@ -9784,6 +9819,21 @@ int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, return ret; } +static int get_hostname_for_verification(mbedtls_ssl_context *ssl, + const char **hostname) +{ + if (!mbedtls_ssl_has_set_hostname_been_called(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Certificate verification without having set hostname")); + } + + *hostname = mbedtls_ssl_get_hostname_pointer(ssl); + if (*hostname == NULL) { + MBEDTLS_SSL_DEBUG_MSG(2, ("Certificate verification without CN verification")); + } + + return 0; +} + int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl, int authmode, mbedtls_x509_crt *chain, @@ -9809,7 +9859,13 @@ int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl, p_vrfy = ssl->conf->p_vrfy; } - int ret = 0; + const char *hostname = ""; + int ret = get_hostname_for_verification(ssl, &hostname); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "get_hostname_for_verification", ret); + return ret; + } + int have_ca_chain_or_callback = 0; #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) if (ssl->conf->f_ca_cb != NULL) { @@ -9822,7 +9878,7 @@ int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl, ssl->conf->f_ca_cb, ssl->conf->p_ca_cb, ssl->conf->cert_profile, - ssl->hostname, + hostname, &ssl->session_negotiate->verify_result, f_vrfy, p_vrfy); } else @@ -9849,7 +9905,7 @@ int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl, chain, ca_chain, ca_crl, ssl->conf->cert_profile, - ssl->hostname, + hostname, &ssl->session_negotiate->verify_result, f_vrfy, p_vrfy, rs_ctx); }