From 5f70b25c9bbe01cd9d7c074eeafc0b7653dc5e77 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Thu, 13 Sep 2012 14:23:06 +0000 Subject: [PATCH] - Correctly handle SHA256 ciphersuites in SSLv3 - Moved ssl3_prf to separate function (no exceptions) --- library/ssl_tls.c | 161 ++++++++++++++++++++++++++++------------------ 1 file changed, 97 insertions(+), 64 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 2d86fda6f..905f7cf03 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -68,6 +68,50 @@ int (*ssl_hw_record_finish)(ssl_context *ssl) = NULL; /* * 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, unsigned char *random, size_t rlen, 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 i; - md5_context md5; - sha1_context sha1; unsigned char tmp[64]; - unsigned char padding[16]; - unsigned char sha1sum[20]; unsigned char keyblk[256]; unsigned char *key1; unsigned char *key2; @@ -241,7 +280,7 @@ int ssl_derive_keys( ssl_context *ssl ) */ 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_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( 'BB' + premaster + randbytes ) ) + * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) - * + * * TLSv1: * master = PRF( premaster, "master secret", randbytes )[0..47] */ 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 ); - - 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 ); + ssl->tls_prf( ssl->premaster, ssl->pmslen, "master secret", + ssl->randbytes, 64, ssl->session->master, 48 ); memset( ssl->premaster, 0, sizeof( ssl->premaster ) ); } @@ -328,33 +346,8 @@ int ssl_derive_keys( ssl_context *ssl ) * TLSv1: * key block = PRF( master, "key expansion", randbytes ) */ - if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) - { - 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->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_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 ); } +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 */ @@ -834,11 +856,19 @@ static int ssl_encrypt_buf( ssl_context *ssl ) ssl_mac_md5( ssl->mac_enc, ssl->out_msg, ssl->out_msglen, ssl->out_ctr, ssl->out_msgtype ); - - if( ssl->maclen == 20 ) + else if( ssl->maclen == 20 ) ssl_mac_sha1( ssl->mac_enc, ssl->out_msg, ssl->out_msglen, 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 { @@ -851,8 +881,7 @@ static int ssl_encrypt_buf( ssl_context *ssl ) md5_hmac_finish( &ctx, ssl->out_msg + ssl->out_msglen ); memset( &ctx, 0, sizeof(md5_context)); } - - if( ssl->maclen == 20 ) + else if( ssl->maclen == 20 ) { sha1_context ctx; 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 ); memset( &ctx, 0, sizeof(sha1_context)); } - - if( ssl->maclen == 32 ) + else if( ssl->maclen == 32 ) { sha2_context ctx; 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 ); 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",