diff --git a/ChangeLog b/ChangeLog index 4be7ec4c5..98da62639 100644 --- a/ChangeLog +++ b/ChangeLog @@ -39,6 +39,8 @@ Bugfix * Fix buffer length assertions in the ssl_parse_certificate_request() function which leads to a potential one byte overread of the message buffer. + * Fix cipher suite validation in ssl_parse_server_hello() by performing same + checks as performed in ssl_write_client_hello(). Changes * Support cmake build where Mbed TLS is a subproject. Fix diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 0d8836406..d34946eae 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -717,6 +717,45 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) return( 0 ); } +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param suite_info cipher suite to validate + * \param ssl SSL context + * + * \return 0 if valid, else 1 + */ +static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl ) +{ + if( suite_info == NULL ) + return( 1 ); + + if( suite_info->min_minor_ver > ssl->conf->max_minor_ver || + suite_info->max_minor_ver < ssl->conf->min_minor_ver ) + return( 1 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 1 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 1 ); +#endif + + return( 0 ); +} + static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { int ret; @@ -869,31 +908,9 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); - if( ciphersuite_info == NULL ) + if( ssl_validate_ciphersuite( ciphersuite_info, ssl ) != 0 ) continue; - if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver || - ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver ) - continue; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) - continue; -#endif - -#if defined(MBEDTLS_ARC4_C) - if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) - continue; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && - mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - continue; -#endif - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", ciphersuites[i] ) ); @@ -1690,22 +1707,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); - suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); - if( suite_info == NULL -#if defined(MBEDTLS_ARC4_C) - || ( ssl->conf->arc4_disabled && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); - + /* Perform cipher suite validation in same way as in ssl_write_client_hello. + */ i = 0; while( 1 ) { @@ -1724,6 +1727,17 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } } + suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + if( comp != MBEDTLS_SSL_COMPRESS_NULL #if defined(MBEDTLS_ZLIB_SUPPORT) && comp != MBEDTLS_SSL_COMPRESS_DEFLATE