From 28f2fcd08dd1b6172af0b6b6fcc14382e067508a Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 7 Feb 2019 10:11:07 +0000 Subject: [PATCH] Add helper function to check whether a CRT msg is expected This commit adds a helper function `ssl_parse_certificate_coordinate()` which checks whether a `Certificate` message is expected from the peer. The logic is the following: - For ciphersuites which don't use server-side CRTs, no Certificate message is expected (neither for the server, nor the client). - On the server, no client certificate is expected in the following cases: * The server server didn't request a Certificate, which is controlled by the `authmode` setting. * A RSA-PSK suite is used; this is the only suite using server CRTs but not allowing client-side authentication. --- library/ssl_tls.c | 62 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 16f836df9..ef3ec2333 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5944,11 +5944,49 @@ static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_SRV_C */ +/* Check if a certificate message is expected. + * Return either + * - SSL_CERTIFICATE_EXPECTED, or + * - SSL_CERTIFICATE_SKIP + * indicating whether a Certificate message is expected or not. + */ +#define SSL_CERTIFICATE_EXPECTED 0 +#define SSL_CERTIFICATE_SKIP 1 +static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl, + int authmode ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + return( SSL_CERTIFICATE_SKIP ); + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + return( SSL_CERTIFICATE_SKIP ); + + if( authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + /* NOTE: Is it intentional that we set verify_result + * to SKIP_VERIFY on server-side only? */ + ssl->session_negotiate->verify_result = + MBEDTLS_X509_BADCERT_SKIP_VERIFY; + return( SSL_CERTIFICATE_SKIP ); + } + } +#endif /* MBEDTLS_SSL_SRV_C */ + + return( SSL_CERTIFICATE_EXPECTED ); +} + int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { int ret = 0; - const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + int crt_expected; #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ? ssl->handshake->sni_authmode @@ -5960,29 +5998,13 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + crt_expected = ssl_parse_certificate_coordinate( ssl, authmode ); + if( crt_expected == SSL_CERTIFICATE_SKIP ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); goto exit; } -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - goto exit; - } - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - authmode == MBEDTLS_SSL_VERIFY_NONE ) - { - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - goto exit; - } -#endif - #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )