- Correctly handle SHA256 ciphersuites in SSLv3

- Moved ssl3_prf to separate function (no exceptions)
This commit is contained in:
Paul Bakker 2012-09-13 14:23:06 +00:00
parent ec636f3bdd
commit 5f70b25c9b

View file

@ -68,6 +68,50 @@ int (*ssl_hw_record_finish)(ssl_context *ssl) = NULL;
/* /*
* Key material generation * Key material generation
*/ */
static int ssl3_prf( unsigned char *secret, size_t slen, char *label,
unsigned char *random, size_t rlen,
unsigned char *dstbuf, size_t dlen )
{
size_t i;
md5_context md5;
sha1_context sha1;
unsigned char padding[16];
unsigned char sha1sum[20];
((void)label);
/*
* SSLv3:
* block =
* MD5( secret + SHA1( 'A' + secret + random ) ) +
* MD5( secret + SHA1( 'BB' + secret + random ) ) +
* MD5( secret + SHA1( 'CCC' + secret + random ) ) +
* ...
*/
for( i = 0; i < dlen / 16; i++ )
{
memset( padding, 'A' + i, 1 + i );
sha1_starts( &sha1 );
sha1_update( &sha1, padding, 1 + i );
sha1_update( &sha1, secret, slen );
sha1_update( &sha1, random, rlen );
sha1_finish( &sha1, sha1sum );
md5_starts( &md5 );
md5_update( &md5, secret, slen );
md5_update( &md5, sha1sum, 20 );
md5_finish( &md5, dstbuf + i * 16 );
}
memset( &md5, 0, sizeof( md5 ) );
memset( &sha1, 0, sizeof( sha1 ) );
memset( padding, 0, sizeof( padding ) );
memset( sha1sum, 0, sizeof( sha1sum ) );
return( 0 );
}
static int tls1_prf( unsigned char *secret, size_t slen, char *label, static int tls1_prf( unsigned char *secret, size_t slen, char *label,
unsigned char *random, size_t rlen, unsigned char *random, size_t rlen,
unsigned char *dstbuf, size_t dlen ) unsigned char *dstbuf, size_t dlen )
@ -223,12 +267,7 @@ static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int);
int ssl_derive_keys( ssl_context *ssl ) int ssl_derive_keys( ssl_context *ssl )
{ {
int i;
md5_context md5;
sha1_context sha1;
unsigned char tmp[64]; unsigned char tmp[64];
unsigned char padding[16];
unsigned char sha1sum[20];
unsigned char keyblk[256]; unsigned char keyblk[256];
unsigned char *key1; unsigned char *key1;
unsigned char *key2; unsigned char *key2;
@ -241,7 +280,7 @@ int ssl_derive_keys( ssl_context *ssl )
*/ */
if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
{ {
ssl->tls_prf = tls1_prf; ssl->tls_prf = ssl3_prf;
ssl->calc_verify = ssl_calc_verify_ssl; ssl->calc_verify = ssl_calc_verify_ssl;
ssl->calc_finished = ssl_calc_finished_ssl; ssl->calc_finished = ssl_calc_finished_ssl;
} }
@ -271,37 +310,16 @@ int ssl_derive_keys( ssl_context *ssl )
* MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) +
* MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) +
* MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
* *
* TLSv1: * TLSv1:
* master = PRF( premaster, "master secret", randbytes )[0..47] * master = PRF( premaster, "master secret", randbytes )[0..47]
*/ */
if( ssl->resume == 0 ) if( ssl->resume == 0 )
{ {
size_t len = ssl->pmslen; SSL_DEBUG_BUF( 3, "premaster secret", ssl->premaster, ssl->pmslen );
SSL_DEBUG_BUF( 3, "premaster secret", ssl->premaster, len ); ssl->tls_prf( ssl->premaster, ssl->pmslen, "master secret",
ssl->randbytes, 64, ssl->session->master, 48 );
if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
{
for( i = 0; i < 3; i++ )
{
memset( padding, 'A' + i, 1 + i );
sha1_starts( &sha1 );
sha1_update( &sha1, padding, 1 + i );
sha1_update( &sha1, ssl->premaster, len );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_finish( &sha1, sha1sum );
md5_starts( &md5 );
md5_update( &md5, ssl->premaster, len );
md5_update( &md5, sha1sum, 20 );
md5_finish( &md5, ssl->session->master + i * 16 );
}
}
else
ssl->tls_prf( ssl->premaster, len, "master secret",
ssl->randbytes, 64, ssl->session->master, 48 );
memset( ssl->premaster, 0, sizeof( ssl->premaster ) ); memset( ssl->premaster, 0, sizeof( ssl->premaster ) );
} }
@ -328,33 +346,8 @@ int ssl_derive_keys( ssl_context *ssl )
* TLSv1: * TLSv1:
* key block = PRF( master, "key expansion", randbytes ) * key block = PRF( master, "key expansion", randbytes )
*/ */
if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) ssl->tls_prf( ssl->session->master, 48, "key expansion",
{ ssl->randbytes, 64, keyblk, 256 );
for( i = 0; i < 16; i++ )
{
memset( padding, 'A' + i, 1 + i );
sha1_starts( &sha1 );
sha1_update( &sha1, padding, 1 + i );
sha1_update( &sha1, ssl->session->master, 48 );
sha1_update( &sha1, ssl->randbytes, 64 );
sha1_finish( &sha1, sha1sum );
md5_starts( &md5 );
md5_update( &md5, ssl->session->master, 48 );
md5_update( &md5, sha1sum, 20 );
md5_finish( &md5, keyblk + i * 16 );
}
memset( &md5, 0, sizeof( md5 ) );
memset( &sha1, 0, sizeof( sha1 ) );
memset( padding, 0, sizeof( padding ) );
memset( sha1sum, 0, sizeof( sha1sum ) );
}
else
ssl->tls_prf( ssl->session->master, 48, "key expansion",
ssl->randbytes, 64, keyblk, 256 );
SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", ssl_get_ciphersuite( ssl ) ) ); SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", ssl_get_ciphersuite( ssl ) ) );
SSL_DEBUG_BUF( 3, "master secret", ssl->session->master, 48 ); SSL_DEBUG_BUF( 3, "master secret", ssl->session->master, 48 );
@ -816,6 +809,35 @@ static void ssl_mac_sha1( unsigned char *secret,
sha1_finish( &sha1, buf + len ); sha1_finish( &sha1, buf + len );
} }
static void ssl_mac_sha2( unsigned char *secret,
unsigned char *buf, size_t len,
unsigned char *ctr, int type )
{
unsigned char header[11];
unsigned char padding[32];
sha2_context sha2;
memcpy( header, ctr, 8 );
header[ 8] = (unsigned char) type;
header[ 9] = (unsigned char)( len >> 8 );
header[10] = (unsigned char)( len );
memset( padding, 0x36, 32 );
sha2_starts( &sha2, 0 );
sha2_update( &sha2, secret, 32 );
sha2_update( &sha2, padding, 32 );
sha2_update( &sha2, header, 11 );
sha2_update( &sha2, buf, len );
sha2_finish( &sha2, buf + len );
memset( padding, 0x5C, 32 );
sha2_starts( &sha2, 0 );
sha2_update( &sha2, secret, 32 );
sha2_update( &sha2, padding, 32 );
sha2_update( &sha2, buf + len, 32 );
sha2_finish( &sha2, buf + len );
}
/* /*
* Encryption/decryption functions * Encryption/decryption functions
*/ */
@ -834,11 +856,19 @@ static int ssl_encrypt_buf( ssl_context *ssl )
ssl_mac_md5( ssl->mac_enc, ssl_mac_md5( ssl->mac_enc,
ssl->out_msg, ssl->out_msglen, ssl->out_msg, ssl->out_msglen,
ssl->out_ctr, ssl->out_msgtype ); ssl->out_ctr, ssl->out_msgtype );
else if( ssl->maclen == 20 )
if( ssl->maclen == 20 )
ssl_mac_sha1( ssl->mac_enc, ssl_mac_sha1( ssl->mac_enc,
ssl->out_msg, ssl->out_msglen, ssl->out_msg, ssl->out_msglen,
ssl->out_ctr, ssl->out_msgtype ); ssl->out_ctr, ssl->out_msgtype );
else if( ssl->maclen == 32 )
ssl_mac_sha2( ssl->mac_enc,
ssl->out_msg, ssl->out_msglen,
ssl->out_ctr, ssl->out_msgtype );
else if( ssl->maclen != 0 )
{
SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d", ssl->maclen ) );
return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
}
} }
else else
{ {
@ -851,8 +881,7 @@ static int ssl_encrypt_buf( ssl_context *ssl )
md5_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen ); md5_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen );
memset( &ctx, 0, sizeof(md5_context)); memset( &ctx, 0, sizeof(md5_context));
} }
else if( ssl->maclen == 20 )
if( ssl->maclen == 20 )
{ {
sha1_context ctx; sha1_context ctx;
sha1_hmac_starts( &ctx, ssl->mac_enc, 20 ); sha1_hmac_starts( &ctx, ssl->mac_enc, 20 );
@ -861,8 +890,7 @@ static int ssl_encrypt_buf( ssl_context *ssl )
sha1_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen ); sha1_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen );
memset( &ctx, 0, sizeof(sha1_context)); memset( &ctx, 0, sizeof(sha1_context));
} }
else if( ssl->maclen == 32 )
if( ssl->maclen == 32 )
{ {
sha2_context ctx; sha2_context ctx;
sha2_hmac_starts( &ctx, ssl->mac_enc, 32, 0 ); sha2_hmac_starts( &ctx, ssl->mac_enc, 32, 0 );
@ -871,6 +899,11 @@ static int ssl_encrypt_buf( ssl_context *ssl )
sha2_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen ); sha2_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen );
memset( &ctx, 0, sizeof(sha2_context)); memset( &ctx, 0, sizeof(sha2_context));
} }
else if( ssl->maclen != 0 )
{
SSL_DEBUG_MSG( 1, ( "invalid MAC len: %d", ssl->maclen ) );
return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
}
} }
SSL_DEBUG_BUF( 4, "computed mac", SSL_DEBUG_BUF( 4, "computed mac",