diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 1403ab331..c7d7b12e3 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -254,6 +254,8 @@ #define TLS_EXT_MAX_FRAGMENT_LENGTH 1 +#define TLS_EXT_TRUNCATED_HMAC 4 + #define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 #define TLS_EXT_SUPPORTED_POINT_FORMATS 11 @@ -336,6 +338,7 @@ struct _ssl_session #endif /* POLARSSL_X509_PARSE_C */ unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ + int trunc_hmac; /*!< flag for truncated hmac activation */ }; /* diff --git a/library/ssl_cli.c b/library/ssl_cli.c index c89bf0cb0..877d6cddd 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -293,6 +293,28 @@ static void ssl_write_max_fragment_length_ext( ssl_context *ssl, *olen = 5; } +static void ssl_write_truncated_hmac_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->trunc_hmac == SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} + static int ssl_write_client_hello( ssl_context *ssl ) { int ret; @@ -463,6 +485,9 @@ static int ssl_write_client_hello( ssl_context *ssl ) ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", ext_len ) ); @@ -526,6 +551,7 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl, return( 0 ); } + static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -544,6 +570,23 @@ static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, return( 0 ); } +static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->trunc_hmac == SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} + static int ssl_parse_server_hello( ssl_context *ssl ) { uint32_t t; @@ -771,6 +814,17 @@ static int ssl_parse_server_hello( ssl_context *ssl ) break; + case TLS_EXT_TRUNCATED_HMAC: + SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); + + if( ( ret = ssl_parse_truncated_hmac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; + default: SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", ext_id ) ); diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 3e1838667..6cbc5f406 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -306,6 +306,23 @@ static int ssl_parse_max_fragment_length_ext( ssl_context *ssl, return( 0 ); } +static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} + #if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) static int ssl_parse_client_hello_v2( ssl_context *ssl ) { @@ -848,6 +865,14 @@ static int ssl_parse_client_hello( ssl_context *ssl ) return( ret ); break; + case TLS_EXT_TRUNCATED_HMAC: + SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + default: SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", ext_id ) ); @@ -957,6 +982,29 @@ have_ciphersuite: return( 0 ); } +static void ssl_write_truncated_hmac_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} + static void ssl_write_renegotiation_ext( ssl_context *ssl, unsigned char *buf, size_t *olen ) @@ -1128,6 +1176,9 @@ static int ssl_write_server_hello( ssl_context *ssl ) ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );