diff --git a/ChangeLog b/ChangeLog index 6fdbc0b4b..9e77f2c86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,12 +6,15 @@ Features SSL_EDH_RSA_CAMELLIA_128_SHA ciphersuites * Added compile-time and run-time version information * Expanded ssl_client2 arguments for more flexibility + * Added support for TLS v1.1 Changes * Made Makefile cleaner * Removed dependency on rand() in rsa_pkcs1_encrypt(). Now using random fuction provided to context. Requires initialization with rsa_init() before use! + * Some SSL defines were renamed in order to avoid + future confusion Bug fixes * Fixed CMake out of source build for tests (found by diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 0eb46cc2f..254c8ef14 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -92,14 +92,14 @@ /* * Supported ciphersuites */ -#define SSL_RSA_RC4_128_MD5 4 -#define SSL_RSA_RC4_128_SHA 5 -#define SSL_RSA_DES_168_SHA 10 -#define SSL_EDH_RSA_DES_168_SHA 22 -#define SSL_RSA_AES_128_SHA 47 -#define SSL_EDH_RSA_AES_128_SHA 51 -#define SSL_RSA_AES_256_SHA 53 -#define SSL_EDH_RSA_AES_256_SHA 57 +#define SSL_RSA_RC4_128_MD5 0x04 +#define SSL_RSA_RC4_128_SHA 0x05 +#define SSL_RSA_DES_168_SHA 0x0A +#define SSL_EDH_RSA_DES_168_SHA 0x16 +#define SSL_RSA_AES_128_SHA 0x2F +#define SSL_EDH_RSA_AES_128_SHA 0x33 +#define SSL_RSA_AES_256_SHA 0x35 +#define SSL_EDH_RSA_AES_256_SHA 0x39 #define SSL_RSA_CAMELLIA_128_SHA 0x41 #define SSL_EDH_RSA_CAMELLIA_128_SHA 0x45 @@ -114,10 +114,33 @@ #define SSL_MSG_HANDSHAKE 22 #define SSL_MSG_APPLICATION_DATA 23 -#define SSL_ALERT_CLOSE_NOTIFY 0 -#define SSL_ALERT_WARNING 1 -#define SSL_ALERT_FATAL 2 -#define SSL_ALERT_NO_CERTIFICATE 41 +#define SSL_ALERT_LEVEL_WARNING 1 +#define SSL_ALERT_LEVEL_FATAL 2 + +#define SSL_ALERT_MSG_CLOSE_NOTIFY 0 +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 +#define SSL_ALERT_MSG_BAD_RECORD_MAD 20 +#define SSL_ALERT_MSG_DECRYPTION_FAILED 21 +#define SSL_ALERT_MSG_RECORD_OVERFLOW 22 +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 +#define SSL_ALERT_MSG_NO_CERT 41 +#define SSL_ALERT_MSG_BAD_CERT 42 +#define SSL_ALERT_MSG_UNSUPPORTED_CERT 43 +#define SSL_ALERT_MSG_CERT_REVOKED 44 +#define SSL_ALERT_MSG_CERT_EXPIRED 45 +#define SSL_ALERT_MSG_CERT_UNKNOWN 46 +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 +#define SSL_ALERT_MSG_UNKNOWN_CA 48 +#define SSL_ALERT_MSG_ACCESS_DENIED 49 +#define SSL_ALERT_MSG_DECODE_ERROR 50 +#define SSL_ALERT_MSG_DECRYPT_ERROR 51 +#define SSL_ALERT_MSG_EXPORT_RESTRICTION 60 +#define SSL_ALERT_MSG_PROTOCOL_VERSION 70 +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 +#define SSL_ALERT_MSG_INTERNAL_ERROR 80 +#define SSL_ALERT_MSG_USER_CANCELED 90 +#define SSL_ALERT_MSG_NO_RENEGOTIATION 100 #define SSL_HS_HELLO_REQUEST 0 #define SSL_HS_CLIENT_HELLO 1 diff --git a/library/ssl_cli.c b/library/ssl_cli.c index b4828a1f6..ba1d287ab 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -48,7 +48,7 @@ static int ssl_write_client_hello( ssl_context *ssl ) ssl->minor_ver = SSL_MINOR_VERSION_0; ssl->max_major_ver = SSL_MAJOR_VERSION_3; - ssl->max_minor_ver = SSL_MINOR_VERSION_1; + ssl->max_minor_ver = SSL_MINOR_VERSION_2; /* * 0 . 0 handshake type @@ -208,8 +208,7 @@ static int ssl_parse_server_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); } - if( buf[5] != SSL_MINOR_VERSION_0 && - buf[5] != SSL_MINOR_VERSION_1 ) + if( buf[5] > ssl->max_minor_ver ) { SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index fa172c295..67eff4728 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -294,6 +294,9 @@ int ssl_derive_keys( ssl_context *ssl ) 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 @@ int ssl_derive_keys( ssl_context *ssl ) 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 @@ static int ssl_encrypt_buf( ssl_context *ssl ) } 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 @@ static int ssl_encrypt_buf( ssl_context *ssl ) 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 @@ static int ssl_encrypt_buf( ssl_context *ssl ) 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 @@ static int ssl_encrypt_buf( ssl_context *ssl ) 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 @@ static int ssl_encrypt_buf( ssl_context *ssl ) 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 @@ static int ssl_decrypt_buf( ssl_context *ssl ) } else { + unsigned char *dec_msg; + unsigned char *dec_msg_result; + int dec_msglen; + /* * Decrypt and check the padding */ @@ -645,13 +687,30 @@ static int ssl_decrypt_buf( ssl_context *ssl ) 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 @@ static int ssl_decrypt_buf( ssl_context *ssl ) 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 @@ static int ssl_decrypt_buf( ssl_context *ssl ) 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 @@ int ssl_read_record( ssl_context *ssl ) 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 @@ int ssl_read_record( ssl_context *ssl ) /* * 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 @@ int ssl_write_certificate( ssl_context *ssl ) { 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 @@ int ssl_parse_certificate( ssl_context *ssl ) 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 @@ int ssl_close_notify( ssl_context *ssl ) { 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 ) {