- Added support for TLS v1.1 - Renamed some SSL defines to prevent future naming confusion
diff --git a/library/ssl_tls.c b/library/ssl_tls.c index fa172c2..67eff47 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c
@@ -294,6 +294,9 @@ memcpy( ssl->mac_enc, keyblk, ssl->maclen ); memcpy( ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen ); + /* + * This is not used in TLS v1.1. + */ memcpy( ssl->iv_enc, key2 + ssl->keylen, ssl->ivlen ); memcpy( ssl->iv_dec, key2 + ssl->keylen + ssl->ivlen, ssl->ivlen ); @@ -306,6 +309,9 @@ memcpy( ssl->mac_dec, keyblk, ssl->maclen ); memcpy( ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen ); + /* + * This is not used in TLS v1.1. + */ memcpy( ssl->iv_dec, key1 + ssl->keylen, ssl->ivlen ); memcpy( ssl->iv_enc, key1 + ssl->keylen + ssl->ivlen, ssl->ivlen ); @@ -545,6 +551,9 @@ } else { + unsigned char *enc_msg; + int enc_msglen; + padlen = ssl->ivlen - ( ssl->out_msglen + 1 ) % ssl->ivlen; if( padlen == ssl->ivlen ) padlen = 0; @@ -554,9 +563,38 @@ ssl->out_msglen += padlen + 1; + enc_msglen = ssl->out_msglen; + enc_msg = ssl->out_msg; + + /* + * Prepend per-record IV for block cipher in TLS v1.1 as per + * Method 1 (6.2.3.2. in RFC4346) + */ + if( ssl->minor_ver == SSL_MINOR_VERSION_2 ) + { + /* + * Generate IV + */ + for( i = 0; i < ssl->ivlen; i++ ) + ssl->iv_enc[i] = ssl->f_rng( ssl->p_rng ); + + /* + * Shift message for ivlen bytes and prepend IV + */ + memmove( ssl->out_msg + ssl->ivlen, ssl->out_msg, ssl->out_msglen ); + memcpy( ssl->out_msg, ssl->iv_enc, ssl->ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg + ssl->ivlen; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->ivlen; + } + SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, padlen + 1 ) ); + "including %d bytes of IV and %d bytes of padding", + ssl->out_msglen, ssl->ivlen, padlen + 1 ) ); SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_msg, ssl->out_msglen ); @@ -566,8 +604,8 @@ case 8: #if defined(POLARSSL_DES_C) des3_crypt_cbc( (des3_context *) ssl->ctx_enc, - DES_ENCRYPT, ssl->out_msglen, - ssl->iv_enc, ssl->out_msg, ssl->out_msg ); + DES_ENCRYPT, enc_msglen, + ssl->iv_enc, enc_msg, enc_msg ); break; #endif @@ -579,8 +617,8 @@ ssl->session->cipher == SSL_EDH_RSA_AES_256_SHA) { aes_crypt_cbc( (aes_context *) ssl->ctx_enc, - AES_ENCRYPT, ssl->out_msglen, - ssl->iv_enc, ssl->out_msg, ssl->out_msg ); + AES_ENCRYPT, enc_msglen, + ssl->iv_enc, enc_msg, enc_msg); break; } #endif @@ -592,8 +630,8 @@ ssl->session->cipher == SSL_EDH_RSA_CAMELLIA_256_SHA) { camellia_crypt_cbc( (camellia_context *) ssl->ctx_enc, - CAMELLIA_ENCRYPT, ssl->out_msglen, - ssl->iv_enc, ssl->out_msg, ssl->out_msg ); + CAMELLIA_ENCRYPT, enc_msglen, + ssl->iv_enc, enc_msg, enc_msg ); break; } #endif @@ -635,6 +673,10 @@ } else { + unsigned char *dec_msg; + unsigned char *dec_msg_result; + int dec_msglen; + /* * Decrypt and check the padding */ @@ -645,13 +687,30 @@ return( POLARSSL_ERR_SSL_INVALID_MAC ); } + dec_msglen = ssl->in_msglen; + dec_msg = ssl->in_msg; + dec_msg_result = ssl->in_msg; + + /* + * Initialize for prepended IV for block cipher in TLS v1.1 + */ + if( ssl->minor_ver == SSL_MINOR_VERSION_2 ) + { + dec_msg += ssl->ivlen; + dec_msglen -= ssl->ivlen; + ssl->in_msglen -= ssl->ivlen; + + for( i = 0; i < ssl->ivlen; i++ ) + ssl->iv_dec[i] = ssl->in_msg[i]; + } + switch( ssl->ivlen ) { #if defined(POLARSSL_DES_C) case 8: des3_crypt_cbc( (des3_context *) ssl->ctx_dec, - DES_DECRYPT, ssl->in_msglen, - ssl->iv_dec, ssl->in_msg, ssl->in_msg ); + DES_DECRYPT, dec_msglen, + ssl->iv_dec, dec_msg, dec_msg_result ); break; #endif @@ -663,8 +722,8 @@ ssl->session->cipher == SSL_EDH_RSA_AES_256_SHA) { aes_crypt_cbc( (aes_context *) ssl->ctx_dec, - AES_DECRYPT, ssl->in_msglen, - ssl->iv_dec, ssl->in_msg, ssl->in_msg ); + AES_DECRYPT, dec_msglen, + ssl->iv_dec, dec_msg, dec_msg_result ); break; } #endif @@ -676,8 +735,8 @@ ssl->session->cipher == SSL_EDH_RSA_CAMELLIA_256_SHA) { camellia_crypt_cbc( (camellia_context *) ssl->ctx_dec, - CAMELLIA_DECRYPT, ssl->in_msglen, - ssl->iv_dec, ssl->in_msg, ssl->in_msg ); + CAMELLIA_DECRYPT, dec_msglen, + ssl->iv_dec, dec_msg, dec_msg_result ); break; } #endif @@ -982,8 +1041,7 @@ return( POLARSSL_ERR_SSL_INVALID_RECORD ); } - if( ssl->in_hdr[2] != SSL_MINOR_VERSION_0 && - ssl->in_hdr[2] != SSL_MINOR_VERSION_1 ) + if( ssl->in_hdr[2] > ssl->max_minor_ver ) { SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); return( POLARSSL_ERR_SSL_INVALID_RECORD ); @@ -1093,14 +1151,14 @@ /* * Ignore non-fatal alerts, except close_notify */ - if( ssl->in_msg[0] == SSL_ALERT_FATAL ) + if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL ) { SSL_DEBUG_MSG( 1, ( "is a fatal alert message" ) ); return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE | ssl->in_msg[1] ); } - if( ssl->in_msg[0] == SSL_ALERT_WARNING && - ssl->in_msg[1] == SSL_ALERT_CLOSE_NOTIFY ) + if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY ) { SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY ); @@ -1142,8 +1200,8 @@ { ssl->out_msglen = 2; ssl->out_msgtype = SSL_MSG_ALERT; - ssl->out_msg[0] = SSL_ALERT_WARNING; - ssl->out_msg[1] = SSL_ALERT_NO_CERTIFICATE; + ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = SSL_ALERT_MSG_NO_CERT; SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); goto write_msg; @@ -1241,10 +1299,10 @@ if( ssl->endpoint == SSL_IS_SERVER && ssl->minor_ver == SSL_MINOR_VERSION_0 ) { - if( ssl->in_msglen == 2 && - ssl->in_msgtype == SSL_MSG_ALERT && - ssl->in_msg[0] == SSL_ALERT_WARNING && - ssl->in_msg[1] == SSL_ALERT_NO_CERTIFICATE ) + if( ssl->in_msglen == 2 && + ssl->in_msgtype == SSL_MSG_ALERT && + ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == SSL_ALERT_MSG_NO_CERT ) { SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); @@ -2026,8 +2084,8 @@ { ssl->out_msgtype = SSL_MSG_ALERT; ssl->out_msglen = 2; - ssl->out_msg[0] = SSL_ALERT_WARNING; - ssl->out_msg[1] = SSL_ALERT_CLOSE_NOTIFY; + ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = SSL_ALERT_MSG_CLOSE_NOTIFY; if( ( ret = ssl_write_record( ssl ) ) != 0 ) {