From 698940726195eb543059a9701afc8cd18f075d50 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Mon, 24 Jan 2022 12:58:00 -0500 Subject: [PATCH] Add accessor to retrieve SNI during handshake Signed-off-by: Glenn Strauss --- ChangeLog.d/mbedtls_ssl_cert_cb.txt | 2 ++ include/mbedtls/ssl.h | 21 +++++++++++++++++++++ library/ssl_misc.h | 5 +++++ library/ssl_srv.c | 12 +++++++++--- library/ssl_tls.c | 7 +++++++ tests/ssl-opt.sh | 2 -- 6 files changed, 44 insertions(+), 5 deletions(-) diff --git a/ChangeLog.d/mbedtls_ssl_cert_cb.txt b/ChangeLog.d/mbedtls_ssl_cert_cb.txt index 9a00c547d2..fcdc23cf0c 100644 --- a/ChangeLog.d/mbedtls_ssl_cert_cb.txt +++ b/ChangeLog.d/mbedtls_ssl_cert_cb.txt @@ -3,3 +3,5 @@ Features Register callback with mbedtls_ssl_conf_cert_cb(). * Provide mechanism to reset handshake cert list by calling mbedtls_ssl_set_hs_own_cert() with NULL value for own_cert param. + * Add accessor mbedtls_ssl_get_hs_sni() to retrieve SNI from within + cert callback (mbedtls_ssl_conf_cert_cb()) during handshake. diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index d1fec95116..738f07bf54 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3540,6 +3540,27 @@ int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Retrieve SNI extension value for the current handshake. + * Available in \p f_cert_cb of \c mbedtls_ssl_conf_cert_cb(), + * this is the same value passed to \p f_sni callback of + * \c mbedtls_ssl_conf_sni() and may be used instead of + * \c mbedtls_ssl_conf_sni(). + * + * \param ssl SSL context + * \param name_len pointer into which to store length of returned value. + * 0 if SNI extension is not present or not yet processed. + * + * \return const pointer to SNI extension value. + * - value is valid only when called in \p f_cert_cb + * registered with \c mbedtls_ssl_conf_cert_cb(). + * - value is NULL if SNI extension is not present. + * - value is not '\0'-terminated. Use \c name_len for len. + * - value must not be freed. + */ +const unsigned char *mbedtls_ssl_get_hs_sni( mbedtls_ssl_context *ssl, + size_t *name_len ); + /** * \brief Set own certificate and key for the current handshake * diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 0656439678..4ecf9155b2 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -849,6 +849,11 @@ struct mbedtls_ssl_handshake_params * The library does not use it internally. */ void *user_async_ctx; #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const unsigned char *sni_name; /*!< raw SNI */ + size_t sni_name_len; /*!< raw SNI len */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ }; typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; diff --git a/library/ssl_srv.c b/library/ssl_srv.c index bd0982c3c9..c757ac803d 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -118,6 +118,11 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) { + ssl->handshake->sni_name = p + 3; + ssl->handshake->sni_name_len = hostname_len; + if( ssl->conf->f_sni == NULL ) + return( 0 ); + ret = ssl->conf->f_sni( ssl->conf->p_sni, ssl, p + 3, hostname_len ); if( ret != 0 ) @@ -1643,9 +1648,6 @@ read_record_header: #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) case MBEDTLS_TLS_EXT_SERVERNAME: MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); - if( ssl->conf->f_sni == NULL ) - break; - ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); if( ret != 0 ) return( ret ); @@ -1878,6 +1880,10 @@ read_record_header: MBEDTLS_SSL_DEBUG_RET( 1, "f_cert_cb", ret ); return( ret ); } +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + ssl->handshake->sni_name = NULL; + ssl->handshake->sni_name_len = 0; +#endif /* * Search for a matching ciphersuite diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 089f239123..2220721f1e 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1389,6 +1389,13 @@ void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +const unsigned char *mbedtls_ssl_get_hs_sni( mbedtls_ssl_context *ssl, + size_t *name_len ) +{ + *name_len = ssl->handshake->sni_name_len; + return( ssl->handshake->sni_name ); +} + int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key ) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 2fe7a4016f..a0d007f3f5 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -5025,7 +5025,6 @@ run_test "SNI: no SNI callback" \ crt_file=data_files/server5.crt key_file=data_files/server5.key" \ "$P_CLI server_name=localhost" \ 0 \ - -S "parse ServerName extension" \ -c "issuer name *: C=NL, O=PolarSSL, CN=Polarssl Test EC CA" \ -c "subject name *: C=NL, O=PolarSSL, CN=localhost" @@ -5175,7 +5174,6 @@ run_test "SNI: DTLS, no SNI callback" \ crt_file=data_files/server5.crt key_file=data_files/server5.key" \ "$P_CLI server_name=localhost dtls=1" \ 0 \ - -S "parse ServerName extension" \ -c "issuer name *: C=NL, O=PolarSSL, CN=Polarssl Test EC CA" \ -c "subject name *: C=NL, O=PolarSSL, CN=localhost"