From e18dc7eb9ac8d4d4161dace796c436cb6a2ef225 Mon Sep 17 00:00:00 2001 From: Jerry Yu Date: Thu, 4 Aug 2022 16:29:22 +0800 Subject: [PATCH] Add forbidden extensions check for ClientHello Signed-off-by: Jerry Yu --- library/ssl_misc.h | 173 ++++++++++++++++++++++++++++++++++++- library/ssl_tls13_server.c | 57 +++++++++--- 2 files changed, 216 insertions(+), 14 deletions(-) diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 41bb9c514d..cf3010a8fa 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -103,6 +103,93 @@ #define MBEDTLS_SSL_EXT_SIG_ALG_CERT ( 1 << 20 ) #define MBEDTLS_SSL_EXT_KEY_SHARE ( 1 << 21 ) +/* Except ServerHello, other message should ignore unrecognized extension. + * + * RFC 8446 page 31 + * + * The ServerHello MUST only include extensions which are required to establish + * the cryptographic context and negotiate the protocol version. + * + * RFC 8446 page 35 + * + * If an implementation receives an extension which it recognizes and which is + * not specified for the message in which it appears, it MUST abort the handshake + * with an "illegal_parameter" alert. + */ +#define MBEDTLS_SSL_EXT_UNRECOGNIZED ( 1U << 31 ) + +/* RFC 8446 page 36. Allowed extensions for ClienHello */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH \ + ( MBEDTLS_SSL_EXT_SERVERNAME | \ + MBEDTLS_SSL_EXT_MAX_FRAGMENT_LENGTH | \ + MBEDTLS_SSL_EXT_STATUS_REQUEST | \ + MBEDTLS_SSL_EXT_SUPPORTED_GROUPS | \ + MBEDTLS_SSL_EXT_SIG_ALG | \ + MBEDTLS_SSL_EXT_USE_SRTP | \ + MBEDTLS_SSL_EXT_HEARTBEAT | \ + MBEDTLS_SSL_EXT_ALPN | \ + MBEDTLS_SSL_EXT_SCT | \ + MBEDTLS_SSL_EXT_CLI_CERT_TYPE | \ + MBEDTLS_SSL_EXT_SERV_CERT_TYPE | \ + MBEDTLS_SSL_EXT_PADDING | \ + MBEDTLS_SSL_EXT_KEY_SHARE | \ + MBEDTLS_SSL_EXT_PRE_SHARED_KEY | \ + MBEDTLS_SSL_EXT_PSK_KEY_EXCHANGE_MODES | \ + MBEDTLS_SSL_EXT_EARLY_DATA | \ + MBEDTLS_SSL_EXT_COOKIE | \ + MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS | \ + MBEDTLS_SSL_EXT_CERT_AUTH | \ + MBEDTLS_SSL_EXT_POST_HANDSHAKE_AUTH | \ + MBEDTLS_SSL_EXT_SIG_ALG_CERT | \ + MBEDTLS_SSL_EXT_UNRECOGNIZED ) + +/* RFC 8446 page 36. Allowed extensions for EncryptedExtensions */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE \ + ( MBEDTLS_SSL_EXT_SERVERNAME | \ + MBEDTLS_SSL_EXT_MAX_FRAGMENT_LENGTH | \ + MBEDTLS_SSL_EXT_SUPPORTED_GROUPS | \ + MBEDTLS_SSL_EXT_USE_SRTP | \ + MBEDTLS_SSL_EXT_HEARTBEAT | \ + MBEDTLS_SSL_EXT_ALPN | \ + MBEDTLS_SSL_EXT_CLI_CERT_TYPE | \ + MBEDTLS_SSL_EXT_SERV_CERT_TYPE | \ + MBEDTLS_SSL_EXT_EARLY_DATA | \ + MBEDTLS_SSL_EXT_UNRECOGNIZED ) + +/* RFC 8446 page 36. Allowed extensions for CertificateRequest */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR \ + ( MBEDTLS_SSL_EXT_STATUS_REQUEST | \ + MBEDTLS_SSL_EXT_SIG_ALG | \ + MBEDTLS_SSL_EXT_SCT | \ + MBEDTLS_SSL_EXT_CERT_AUTH | \ + MBEDTLS_SSL_EXT_OID_FILTERS | \ + MBEDTLS_SSL_EXT_SIG_ALG_CERT | \ + MBEDTLS_SSL_EXT_UNRECOGNIZED ) + +/* RFC 8446 page 36. Allowed extensions for Certificate */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT \ + ( MBEDTLS_SSL_EXT_STATUS_REQUEST | \ + MBEDTLS_SSL_EXT_SCT | \ + MBEDTLS_SSL_EXT_UNRECOGNIZED ) + +/* RFC 8446 page 36. Allowed extensions for ServerHello */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH \ + ( MBEDTLS_SSL_EXT_KEY_SHARE | \ + MBEDTLS_SSL_EXT_PRE_SHARED_KEY | \ + MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS ) + +/* RFC 8446 page 36. Allowed extensions for HelloRetryRequest */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR \ + ( MBEDTLS_SSL_EXT_KEY_SHARE | \ + MBEDTLS_SSL_EXT_COOKIE | \ + MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS | \ + MBEDTLS_SSL_EXT_UNRECOGNIZED ) + +/* RFC 8446 page 36. Allowed extensions for NewSessionTicket */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST \ + ( MBEDTLS_SSL_EXT_EARLY_DATA | \ + MBEDTLS_SSL_EXT_UNRECOGNIZED ) + /* * Helper macros for function call with return check. */ @@ -858,7 +945,7 @@ struct mbedtls_ssl_handshake_params #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) - int extensions_present; /*!< extension presence; Each bitfield + uint32_t extensions_present; /*!< extension presence; Each bitfield represents an extension and defined as \c MBEDTLS_SSL_EXT_XXX */ @@ -1838,6 +1925,90 @@ static inline int mbedtls_ssl_tls13_some_psk_enabled( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ +/* + * Helper functions to check if the extension is allowed or forbiden + */ +static inline int mbedtls_ssl_tls13_has_extensions( mbedtls_ssl_context *ssl, + int extensions_mask ) +{ + int masked = ssl->handshake->extensions_present & extensions_mask; + return( masked != 0 ); +} + +static inline int mbedtls_tls13_get_extension_mask( uint16_t extension_type ) +{ + switch( extension_type ) + { + case MBEDTLS_TLS_EXT_SERVERNAME: + return( MBEDTLS_SSL_EXT_SERVERNAME ); + + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + return( MBEDTLS_SSL_EXT_MAX_FRAGMENT_LENGTH ); + + case MBEDTLS_TLS_EXT_STATUS_REQUEST: + return( MBEDTLS_SSL_EXT_STATUS_REQUEST ); + + case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: + return( MBEDTLS_SSL_EXT_SUPPORTED_GROUPS ); + + case MBEDTLS_TLS_EXT_SIG_ALG: + return( MBEDTLS_SSL_EXT_SIG_ALG ); + + case MBEDTLS_TLS_EXT_USE_SRTP: + return( MBEDTLS_SSL_EXT_USE_SRTP ); + + case MBEDTLS_TLS_EXT_HEARTBEAT: + return( MBEDTLS_SSL_EXT_HEARTBEAT ); + + case MBEDTLS_TLS_EXT_ALPN: + return( MBEDTLS_SSL_EXT_ALPN ); + + case MBEDTLS_TLS_EXT_SCT: + return( MBEDTLS_SSL_EXT_SCT ); + + case MBEDTLS_TLS_EXT_CLI_CERT_TYPE: + return( MBEDTLS_SSL_EXT_CLI_CERT_TYPE ); + + case MBEDTLS_TLS_EXT_SERV_CERT_TYPE: + return( MBEDTLS_SSL_EXT_SERV_CERT_TYPE ); + + case MBEDTLS_TLS_EXT_PADDING: + return( MBEDTLS_SSL_EXT_PADDING ); + + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + return( MBEDTLS_SSL_EXT_PRE_SHARED_KEY ); + + case MBEDTLS_TLS_EXT_EARLY_DATA: + return( MBEDTLS_SSL_EXT_EARLY_DATA ); + + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + return( MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS ); + + case MBEDTLS_TLS_EXT_COOKIE: + return( MBEDTLS_SSL_EXT_COOKIE ); + + case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: + return( MBEDTLS_SSL_EXT_PSK_KEY_EXCHANGE_MODES ); + + case MBEDTLS_TLS_EXT_CERT_AUTH: + return( MBEDTLS_SSL_EXT_CERT_AUTH ); + + case MBEDTLS_TLS_EXT_OID_FILTERS: + return( MBEDTLS_SSL_EXT_OID_FILTERS ); + + case MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH: + return( MBEDTLS_SSL_EXT_POST_HANDSHAKE_AUTH ); + + case MBEDTLS_TLS_EXT_SIG_ALG_CERT: + return( MBEDTLS_SSL_EXT_SIG_ALG_CERT ); + + case MBEDTLS_TLS_EXT_KEY_SHARE: + return( MBEDTLS_SSL_EXT_KEY_SHARE ); + }; + + return( MBEDTLS_SSL_EXT_UNRECOGNIZED ); +} + /* * Helper functions to check the selected key exchange mode. */ diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index b24aa4a8c5..32f64d73c9 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -1239,6 +1239,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, const unsigned char *cipher_suites_end; size_t extensions_len; const unsigned char *extensions_end; + uint32_t extensions_present; int hrr_required = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) @@ -1247,7 +1248,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, const unsigned char *pre_shared_key_ext_end = NULL; #endif - ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE; + extensions_present = MBEDTLS_SSL_EXT_NONE; /* * ClientHello layout: @@ -1431,7 +1432,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, * Servers MUST check that it is the last extension and otherwise fail * the handshake with an "illegal_parameter" alert. */ - if( ssl->handshake->extensions_present & MBEDTLS_SSL_EXT_PRE_SHARED_KEY ) + if( extensions_present & MBEDTLS_SSL_EXT_PRE_SHARED_KEY ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "pre_shared_key is not last extension." ) ); @@ -1449,6 +1450,27 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, extension_data_len ); extension_data_end = p + extension_data_len; + /* RFC 8446 page 35 + * + * If an implementation receives an extension which it recognizes and which + * is not specified for the message in which it appears, it MUST abort the + * handshake with an "illegal_parameter" alert. + */ + extensions_present |= mbedtls_tls13_get_extension_mask( extension_type ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello : received %s(%u) extension", + mbedtls_tls13_get_extension_name( extension_type ), + extension_type ) ); + if( ( extensions_present & MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( + 3, ( "forbidden extension received." ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + switch( extension_type ) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -1462,7 +1484,6 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, 1, "mbedtls_ssl_parse_servername_ext", ret ); return( ret ); } - ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SERVERNAME; break; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ @@ -1485,7 +1506,6 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, return( ret ); } - ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SUPPORTED_GROUPS; break; #endif /* MBEDTLS_ECDH_C */ @@ -1515,7 +1535,6 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, return( ret ); } - ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_KEY_SHARE; break; #endif /* MBEDTLS_ECDH_C */ @@ -1530,7 +1549,6 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, ( "ssl_tls13_parse_supported_versions_ext" ), ret ); return( ret ); } - ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS; break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) @@ -1546,13 +1564,12 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, return( ret ); } - ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_PSK_KEY_EXCHANGE_MODES; break; #endif case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: MBEDTLS_SSL_DEBUG_MSG( 3, ( "found pre_shared_key extension" ) ); - if( ( ssl->handshake->extensions_present & + if( ( extensions_present & MBEDTLS_SSL_EXT_PSK_KEY_EXCHANGE_MODES ) == 0 ) { MBEDTLS_SSL_PEND_FATAL_ALERT( @@ -1567,8 +1584,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, */ pre_shared_key_ext = p; pre_shared_key_ext_end = extension_data_end; -#endif - ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_PRE_SHARED_KEY; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ break; #if defined(MBEDTLS_SSL_ALPN) @@ -1582,7 +1598,6 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, 1, ( "mbedtls_ssl_parse_alpn_ext" ), ret ); return( ret ); } - ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_ALPN; break; #endif /* MBEDTLS_SSL_ALPN */ @@ -1599,7 +1614,6 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, ret ) ); return( ret ); } - ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SIG_ALG; break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ @@ -1613,6 +1627,22 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, p += extension_data_len; } + MBEDTLS_SSL_TLS1_3_PRINT_EXTS( 3, "ClientHello", extensions_present ); + + /* RFC 8446 page 102 + * - "supported_versions" is REQUIRED for all ClientHello, ServerHello, and + * HelloRetryRequest messages. + */ + if( ( extensions_present & MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "client hello: supported_versions not found" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + mbedtls_ssl_add_hs_hdr_to_checksum( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, p - buf ); @@ -1636,7 +1666,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, cipher_suites_end ); if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) { - ssl->handshake->extensions_present &= ~MBEDTLS_SSL_EXT_PRE_SHARED_KEY; + extensions_present &= ~MBEDTLS_SSL_EXT_PRE_SHARED_KEY; } else if( ret != 0 ) { @@ -1651,6 +1681,7 @@ static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl, ssl->handshake->update_checksum( ssl, buf, p - buf ); } + ssl->handshake->extensions_present = extensions_present; ret = ssl_tls13_determine_key_exchange_mode( ssl ); if( ret < 0 ) return( ret );