Skip MAC computation/check when GCM is used

This commit is contained in:
Manuel Pégourié-Gonnard 2013-10-25 19:31:25 +02:00
parent 65ea372f9b
commit 7109624aef

View file

@ -973,41 +973,53 @@ static int ssl_encrypt_buf( ssl_context *ssl )
SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
/* /*
* Add MAC then encrypt * Add MAC before encrypt, except for GCM
*/ */
#if defined(POLARSSL_SSL_PROTO_SSL3) #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \
if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ( defined(POLARSSL_CIPHER_MODE_CBC) && \
( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode !=
POLARSSL_MODE_GCM )
{ {
ssl_mac( &ssl->transform_out->md_ctx_enc, #if defined(POLARSSL_SSL_PROTO_SSL3)
ssl->transform_out->mac_enc, if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
ssl->out_msg, ssl->out_msglen, {
ssl->out_ctr, ssl->out_msgtype ); ssl_mac( &ssl->transform_out->md_ctx_enc,
} ssl->transform_out->mac_enc,
else ssl->out_msg, ssl->out_msglen,
ssl->out_ctr, ssl->out_msgtype );
}
else
#endif #endif
#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ #if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
defined(POLARSSL_SSL_PROTO_TLS1_2) defined(POLARSSL_SSL_PROTO_TLS1_2)
if( ssl->minor_ver >= SSL_MINOR_VERSION_1 ) if( ssl->minor_ver >= SSL_MINOR_VERSION_1 )
{ {
md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 13 ); md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 13 );
md_hmac_update( &ssl->transform_out->md_ctx_enc, md_hmac_update( &ssl->transform_out->md_ctx_enc,
ssl->out_msg, ssl->out_msglen ); ssl->out_msg, ssl->out_msglen );
md_hmac_finish( &ssl->transform_out->md_ctx_enc, md_hmac_finish( &ssl->transform_out->md_ctx_enc,
ssl->out_msg + ssl->out_msglen ); ssl->out_msg + ssl->out_msglen );
md_hmac_reset( &ssl->transform_out->md_ctx_enc ); md_hmac_reset( &ssl->transform_out->md_ctx_enc );
} }
else else
#endif #endif
{ {
SSL_DEBUG_MSG( 1, ( "should never happen" ) ); SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
}
SSL_DEBUG_BUF( 4, "computed mac",
ssl->out_msg + ssl->out_msglen,
ssl->transform_out->maclen );
ssl->out_msglen += ssl->transform_out->maclen;
} }
#endif /* GCM not the only option */
SSL_DEBUG_BUF( 4, "computed mac", /*
ssl->out_msg + ssl->out_msglen, ssl->transform_out->maclen ); * Encrypt
*/
ssl->out_msglen += ssl->transform_out->maclen;
#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode == if( ssl->transform_out->cipher_ctx_enc.cipher_info->mode ==
POLARSSL_MODE_STREAM ) POLARSSL_MODE_STREAM )
@ -1634,84 +1646,92 @@ static int ssl_decrypt_buf( ssl_context *ssl )
ssl->in_msg, ssl->in_msglen ); ssl->in_msg, ssl->in_msglen );
/* /*
* Always compute the MAC (RFC4346, CBCTIME). * Always compute the MAC (RFC4346, CBCTIME), except for GCM of course
*/ */
ssl->in_msglen -= ( ssl->transform_in->maclen + padlen ); #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \
( defined(POLARSSL_CIPHER_MODE_CBC) && \
( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
if( ssl->transform_in->cipher_ctx_dec.cipher_info->mode !=
POLARSSL_MODE_GCM )
{
ssl->in_msglen -= ( ssl->transform_in->maclen + padlen );
ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 ); ssl->in_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 );
ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen ); ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen );
memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen );
#if defined(POLARSSL_SSL_PROTO_SSL3) #if defined(POLARSSL_SSL_PROTO_SSL3)
if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
{ {
ssl_mac( &ssl->transform_in->md_ctx_dec, ssl_mac( &ssl->transform_in->md_ctx_dec,
ssl->transform_in->mac_dec, ssl->transform_in->mac_dec,
ssl->in_msg, ssl->in_msglen, ssl->in_msg, ssl->in_msglen,
ssl->in_ctr, ssl->in_msgtype ); ssl->in_ctr, ssl->in_msgtype );
} }
else else
#endif /* POLARSSL_SSL_PROTO_SSL3 */ #endif /* POLARSSL_SSL_PROTO_SSL3 */
#if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \ #if defined(POLARSSL_SSL_PROTO_TLS1) || defined(POLARSSL_SSL_PROTO_TLS1_1) || \
defined(POLARSSL_SSL_PROTO_TLS1_2) defined(POLARSSL_SSL_PROTO_TLS1_2)
if( ssl->minor_ver > SSL_MINOR_VERSION_0 ) if( ssl->minor_ver > SSL_MINOR_VERSION_0 )
{ {
/* /*
* Process MAC and always update for padlen afterwards to make * Process MAC and always update for padlen afterwards to make
* total time independent of padlen * total time independent of padlen
* *
* extra_run compensates MAC check for padlen * extra_run compensates MAC check for padlen
* *
* Known timing attacks: * Known timing attacks:
* - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
* *
* We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values
* correctly. (We round down instead of up, so -56 is the correct * correctly. (We round down instead of up, so -56 is the correct
* value for our calculations instead of -55) * value for our calculations instead of -55)
*/ */
size_t j, extra_run = 0; size_t j, extra_run = 0;
extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
( 13 + ssl->in_msglen + 8 ) / 64; ( 13 + ssl->in_msglen + 8 ) / 64;
extra_run &= correct * 0xFF; extra_run &= correct * 0xFF;
md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 13 ); 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, md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg,
ssl->in_msglen ); ssl->in_msglen );
md_hmac_finish( &ssl->transform_in->md_ctx_dec, md_hmac_finish( &ssl->transform_in->md_ctx_dec,
ssl->in_msg + ssl->in_msglen ); ssl->in_msg + ssl->in_msglen );
for( j = 0; j < extra_run; j++ ) for( j = 0; j < extra_run; j++ )
md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
md_hmac_reset( &ssl->transform_in->md_ctx_dec ); md_hmac_reset( &ssl->transform_in->md_ctx_dec );
} }
else else
#endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \ #endif /* POLARSSL_SSL_PROTO_TLS1 || POLARSSL_SSL_PROTO_TLS1_1 || \
POLARSSL_SSL_PROTO_TLS1_2 */ POLARSSL_SSL_PROTO_TLS1_2 */
{ {
SSL_DEBUG_MSG( 1, ( "should never happen" ) ); SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
} }
SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); 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, "computed mac", ssl->in_msg + ssl->in_msglen,
ssl->transform_in->maclen ); ssl->transform_in->maclen );
if( memcmp( tmp, ssl->in_msg + ssl->in_msglen, if( memcmp( tmp, ssl->in_msg + ssl->in_msglen,
ssl->transform_in->maclen ) != 0 ) ssl->transform_in->maclen ) != 0 )
{ {
#if defined(POLARSSL_SSL_DEBUG_ALL) #if defined(POLARSSL_SSL_DEBUG_ALL)
SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
#endif #endif
correct = 0; correct = 0;
} }
/* /*
* Finally check the correct flag * Finally check the correct flag
*/ */
if( correct == 0 ) if( correct == 0 )
return( POLARSSL_ERR_SSL_INVALID_MAC ); return( POLARSSL_ERR_SSL_INVALID_MAC );
}
#endif /* GCM not the only option */
if( ssl->in_msglen == 0 ) if( ssl->in_msglen == 0 )
{ {