diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index fa2429d07c..6bdb7acd18 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -486,6 +486,7 @@ #define MBEDTLS_SSL_HS_SERVER_HELLO 2 #define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 #define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSION 8 // NEW IN TLS 1.3 #define MBEDTLS_SSL_HS_CERTIFICATE 11 #define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 #define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 979db31449..686edfe3b9 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -1395,11 +1395,125 @@ cleanup: } /* - * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS + * + * EncryptedExtensions message + * + * The EncryptedExtensions message contains any extensions which + * should be protected, i.e., any which are not needed to establish + * the cryptographic context. */ -static int ssl_tls1_3_process_encrypted_extensions( mbedtls_ssl_context *ssl ) + +/* + * Overview + */ +static int ssl_tls1_3_read_encrypted_extensions( mbedtls_ssl_context *ssl ); + +/* Main entry point; orchestrates the other functions */ +static int ssl_tls13_encrypted_extensions_process( mbedtls_ssl_context *ssl ); + +static int ssl_tls13_encrypted_extensions_parse( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t buf_len ); +static int ssl_tls13_encrypted_extensions_postprocess( mbedtls_ssl_context *ssl ); + +/* + * Handler for MBEDTLS_SSL_ENCRYPTED_ENTENSIONS + */ +static int ssl_tls13_encrypted_extensions_process( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse encrypted extensions" ) ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl, + MBEDTLS_SSL_HS_ENCRYPTED_EXTENSION, + &buf, &buf_len ) ); + + /* Process the message contents */ + MBEDTLS_SSL_PROC_CHK( ssl_tls13_encrypted_extensions_parse( ssl, buf, buf_len ) ); + + mbedtls_ssl_tls13_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSION, buf, buf_len ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_encrypted_extensions_postprocess( ssl ) ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse encrypted extensions" ) ); + return( ret ); + +} + +static int ssl_tls13_encrypted_extensions_parse( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t buf_len ) +{ + int ret = 0; + size_t ext_len; + const unsigned char *ext; + + if( buf_len < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "EncryptedExtension message too short" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + ext_len = MBEDTLS_GET_UINT16_BE(buf, 0); + + buf += 2; /* skip extension length */ + ext = buf; + + /* Checking for an extension length that is too short */ + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "EncryptedExtension message too short" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Checking for an extension length that isn't aligned with the rest + * of the message */ + if( buf_len != 2 + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "EncryptedExtension lengths misaligned" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "encrypted extensions extensions", ext, ext_len ); + + while( ext_len ) + { + unsigned int ext_id = MBEDTLS_GET_UINT16_BE(ext, 0); + size_t ext_size = MBEDTLS_GET_UINT16_BE(ext, 2); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad encrypted extensions message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* TBD: The client MUST check EncryptedExtensions for the + * presence of any forbidden extensions and if any are found MUST abort + * the handshake with an "illegal_parameter" alert. + */ + ((void) ext_id); + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad encrypted extensions message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + } + + return( ret ); +} + +static int ssl_tls13_encrypted_extensions_postprocess( mbedtls_ssl_context *ssl ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) ); mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST ); return( 0 ); } @@ -1555,6 +1669,10 @@ int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl ) ret = ssl_tls1_3_handshake_wrapup( ssl ); break; + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + ret = ssl_tls13_encrypted_extensions_process( ssl ); + break; + default: MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index b3a4a09ddc..949fa74741 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -27,6 +27,39 @@ #include "mbedtls/debug.h" #include "ssl_misc.h" +#include + +int mbedtls_ssl_tls13_fetch_handshake_msg( mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buflen ) +{ + int ret; + + if( ( ret = mbedtls_ssl_read_record( ssl, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + goto cleanup; + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != hs_type ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto cleanup; + } + + *buf = ssl->in_msg + 4; + *buflen = ssl->in_hslen - 4; + + +cleanup: + + return( ret ); +} int mbedtls_ssl_tls1_3_fetch_handshake_msg( mbedtls_ssl_context *ssl, unsigned hs_type,