mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-23 03:45:39 +01:00
Fix heap corruption in ssl_decrypt_buf
Previously, MAC validation for an incoming record proceeded as follows: 1) Make a copy of the MAC contained in the record; 2) Compute the expected MAC in place, overwriting the presented one; 3) Compare both. This resulted in a record buffer overflow if truncated MAC was used, as in this case the record buffer only reserved 10 bytes for the MAC, but the MAC computation routine in 2) always wrote a full digest. For specially crafted records, this could be used to perform a controlled write of up to 6 bytes past the boundary of the heap buffer holding the record, thereby corrupting the heap structures and potentially leading to a crash or remote code execution. This commit fixes this by making the following change: 1) Compute the expected MAC in a temporary buffer that has the size of the underlying message digest. 2) Compare to this to the MAC contained in the record, potentially restricting to the first 10 bytes if truncated HMAC is used. A similar fix is applied to the encryption routine `ssl_encrypt_buf`.
This commit is contained in:
parent
75ea35eac8
commit
251bab5ceb
@ -1141,12 +1141,16 @@ static int ssl_encrypt_buf( ssl_context *ssl )
|
||||
defined(POLARSSL_SSL_PROTO_TLS1_2)
|
||||
if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
|
||||
{
|
||||
unsigned char mac[SSL_MAC_ADD];
|
||||
|
||||
md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 13 );
|
||||
md_hmac_update( &ssl->transform_out->md_ctx_enc,
|
||||
ssl->out_msg, ssl->out_msglen );
|
||||
md_hmac_finish( &ssl->transform_out->md_ctx_enc,
|
||||
ssl->out_msg + ssl->out_msglen );
|
||||
md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac );
|
||||
md_hmac_reset( &ssl->transform_out->md_ctx_enc );
|
||||
|
||||
memcpy( ssl->out_msg + ssl->out_msglen, mac,
|
||||
ssl->transform_out->maclen );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -1419,8 +1423,6 @@ static int ssl_encrypt_buf( ssl_context *ssl )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#define POLARSSL_SSL_MAX_MAC_SIZE 48
|
||||
|
||||
static int ssl_decrypt_buf( ssl_context *ssl )
|
||||
{
|
||||
size_t i;
|
||||
@ -1588,7 +1590,7 @@ static int ssl_decrypt_buf( ssl_context *ssl )
|
||||
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
|
||||
if( ssl->session_in->encrypt_then_mac == SSL_ETM_ENABLED )
|
||||
{
|
||||
unsigned char computed_mac[POLARSSL_SSL_MAX_MAC_SIZE];
|
||||
unsigned char mac_expect[SSL_MAC_ADD];
|
||||
unsigned char pseudo_hdr[13];
|
||||
|
||||
SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
|
||||
@ -1606,15 +1608,15 @@ static int ssl_decrypt_buf( ssl_context *ssl )
|
||||
md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 );
|
||||
md_hmac_update( &ssl->transform_in->md_ctx_dec,
|
||||
ssl->in_iv, ssl->in_msglen );
|
||||
md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac );
|
||||
md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect );
|
||||
md_hmac_reset( &ssl->transform_in->md_ctx_dec );
|
||||
|
||||
SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen,
|
||||
ssl->transform_in->maclen );
|
||||
SSL_DEBUG_BUF( 4, "computed mac", computed_mac,
|
||||
SSL_DEBUG_BUF( 4, "computed mac", mac_expect,
|
||||
ssl->transform_in->maclen );
|
||||
|
||||
if( safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac,
|
||||
if( safer_memcmp( ssl->in_iv + ssl->in_msglen, mac_expect,
|
||||
ssl->transform_in->maclen ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
|
||||
@ -1775,15 +1777,13 @@ static int ssl_decrypt_buf( ssl_context *ssl )
|
||||
#if defined(POLARSSL_SOME_MODES_USE_MAC)
|
||||
if( auth_done == 0 )
|
||||
{
|
||||
unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
|
||||
unsigned char mac_expect[SSL_MAC_ADD];
|
||||
|
||||
ssl->in_msglen -= ssl->transform_in->maclen;
|
||||
|
||||
ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
|
||||
ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen );
|
||||
|
||||
memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen );
|
||||
|
||||
#if defined(POLARSSL_SSL_PROTO_SSL3)
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
|
||||
{
|
||||
@ -1820,8 +1820,8 @@ static int ssl_decrypt_buf( ssl_context *ssl )
|
||||
md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 13 );
|
||||
md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg,
|
||||
ssl->in_msglen );
|
||||
md_hmac_finish( &ssl->transform_in->md_ctx_dec,
|
||||
ssl->in_msg + ssl->in_msglen );
|
||||
md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect );
|
||||
|
||||
/* Call md_process at least once due to cache attacks */
|
||||
for( j = 0; j < extra_run + 1; j++ )
|
||||
md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
|
||||
@ -1836,11 +1836,11 @@ static int ssl_decrypt_buf( ssl_context *ssl )
|
||||
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen );
|
||||
SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen,
|
||||
SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen );
|
||||
SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen,
|
||||
ssl->transform_in->maclen );
|
||||
|
||||
if( safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen,
|
||||
if( safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect,
|
||||
ssl->transform_in->maclen ) != 0 )
|
||||
{
|
||||
#if defined(POLARSSL_SSL_DEBUG_ALL)
|
||||
|
@ -504,40 +504,40 @@ run_test "Truncated HMAC: client default, server default" \
|
||||
"$P_SRV debug_level=4" \
|
||||
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
|
||||
0 \
|
||||
-s "dumping 'computed mac' (20 bytes)" \
|
||||
-S "dumping 'computed mac' (10 bytes)"
|
||||
-s "dumping 'expected mac' (20 bytes)" \
|
||||
-S "dumping 'expected mac' (10 bytes)"
|
||||
|
||||
run_test "Truncated HMAC: client disabled, server default" \
|
||||
"$P_SRV debug_level=4" \
|
||||
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
|
||||
trunc_hmac=0" \
|
||||
0 \
|
||||
-s "dumping 'computed mac' (20 bytes)" \
|
||||
-S "dumping 'computed mac' (10 bytes)"
|
||||
-s "dumping 'expected mac' (20 bytes)" \
|
||||
-S "dumping 'expected mac' (10 bytes)"
|
||||
|
||||
run_test "Truncated HMAC: client enabled, server default" \
|
||||
"$P_SRV debug_level=4" \
|
||||
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
|
||||
trunc_hmac=1" \
|
||||
0 \
|
||||
-S "dumping 'computed mac' (20 bytes)" \
|
||||
-s "dumping 'computed mac' (10 bytes)"
|
||||
-S "dumping 'expected mac' (20 bytes)" \
|
||||
-s "dumping 'expected mac' (10 bytes)"
|
||||
|
||||
run_test "Truncated HMAC: client enabled, server disabled" \
|
||||
"$P_SRV debug_level=4 trunc_hmac=0" \
|
||||
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
|
||||
trunc_hmac=1" \
|
||||
0 \
|
||||
-s "dumping 'computed mac' (20 bytes)" \
|
||||
-S "dumping 'computed mac' (10 bytes)"
|
||||
-s "dumping 'expected mac' (20 bytes)" \
|
||||
-S "dumping 'expected mac' (10 bytes)"
|
||||
|
||||
run_test "Truncated HMAC: client enabled, server enabled" \
|
||||
"$P_SRV debug_level=4 trunc_hmac=1" \
|
||||
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
|
||||
trunc_hmac=1" \
|
||||
0 \
|
||||
-S "dumping 'computed mac' (20 bytes)" \
|
||||
-s "dumping 'computed mac' (10 bytes)"
|
||||
-S "dumping 'expected mac' (20 bytes)" \
|
||||
-s "dumping 'expected mac' (10 bytes)"
|
||||
|
||||
# Tests for Encrypt-then-MAC extension
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user