From ca4ab491585b432d7db0266aa6fbcbc6813eda00 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Wed, 18 Apr 2012 14:23:57 +0000 Subject: [PATCH] - Added GCM ciphersuites to TLS implementation --- ChangeLog | 1 + include/polarssl/gcm.h | 10 + include/polarssl/ssl.h | 14 +- library/ssl_cli.c | 45 ++++- library/ssl_srv.c | 12 +- library/ssl_tls.c | 381 ++++++++++++++++++++++++++++++++++---- programs/ssl/ssl_server.c | 12 ++ tests/compat.sh | 10 +- 8 files changed, 433 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8333b5a99..3bde699c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ Features * Added cert_req example application * Added base Galois Counter Mode (GCM) for AES * Added TLS 1.2 support + * Added GCM suites to TLS 1.2 (RFC 5288) Changes * Removed redundant POLARSSL_DEBUG_MSG define diff --git a/include/polarssl/gcm.h b/include/polarssl/gcm.h index 14b04d2e3..2f88c7015 100644 --- a/include/polarssl/gcm.h +++ b/include/polarssl/gcm.h @@ -35,6 +35,7 @@ #define GCM_DECRYPT 0 #define POLARSSL_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ +#define POLARSSL_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ /** * \brief GCM context structure @@ -64,6 +65,11 @@ int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize ) /** * \brief GCM buffer encryption/decryption using AES * + * \note On encryption, the output buffer can be the same as the input buffer. + * On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * * \param ctx GCM context * \param mode GCM_ENCRYPT or GCM_DECRYPT * \param length length of the input data @@ -93,6 +99,10 @@ int gcm_crypt_and_tag( gcm_context *ctx, /** * \brief GCM buffer authenticated decryption using AES * + * \note On decryption, the output buffer cannot be the same as input buffer. + * If buffers overlap, the output buffer must trail at least 8 bytes + * behind the input buffer. + * * \param ctx GCM context * \param length length of the input data * \param iv initialization vector diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 90de64932..8110fbce6 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -35,6 +35,7 @@ #include "md5.h" #include "sha1.h" #include "sha2.h" +#include "sha4.h" #include "x509.h" #include "config.h" @@ -142,6 +143,11 @@ #define SSL_RSA_CAMELLIA_256_SHA256 0xC0 /**< TLS 1.2 */ #define SSL_EDH_RSA_CAMELLIA_256_SHA256 0xC4 /**< TLS 1.2 */ +#define SSL_RSA_AES_128_GCM_SHA256 0x9C +#define SSL_RSA_AES_256_GCM_SHA384 0x9D +#define SSL_EDH_RSA_AES_128_GCM_SHA256 0x9E +#define SSL_EDH_RSA_AES_256_GCM_SHA384 0x9F + /* * Supported Signature and Hash algorithms (For TLS 1.2) */ @@ -172,7 +178,7 @@ #define SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ #define SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ #define SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ -#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 41 /* 0x29 */ +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ #define SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ #define SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ #define SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ @@ -339,6 +345,7 @@ struct _ssl_context md5_context fin_md5; /*!< Finished MD5 checksum */ sha1_context fin_sha1; /*!< Finished SHA-1 checksum */ sha2_context fin_sha2; /*!< Finished SHA-256 checksum */ + sha4_context fin_sha4; /*!< Finished SHA-384 checksum */ void (*calc_finished)(ssl_context *, unsigned char *, int); int (*tls_prf)(unsigned char *, size_t, char *, @@ -351,6 +358,7 @@ struct _ssl_context unsigned int keylen; /*!< symmetric key length */ size_t minlen; /*!< min. ciphertext length */ size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ size_t maclen; /*!< MAC length */ unsigned char randbytes[64]; /*!< random bytes */ @@ -362,8 +370,8 @@ struct _ssl_context unsigned char mac_enc[32]; /*!< MAC (encryption) */ unsigned char mac_dec[32]; /*!< MAC (decryption) */ - unsigned long ctx_enc[128]; /*!< encryption context */ - unsigned long ctx_dec[128]; /*!< decryption context */ + unsigned long ctx_enc[134]; /*!< encryption context */ + unsigned long ctx_dec[134]; /*!< decryption context */ /* * TLS extensions diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 6f9206f9d..df4dbb0f9 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -453,7 +453,9 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl ) ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA && ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA && ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 ) + ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 && + ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 && + ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 ) { SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); ssl->state++; @@ -786,7 +788,9 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ) + ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { #if !defined(POLARSSL_DHM_C) SSL_DEBUG_MSG( 1, ( "support for dhm in not available" ) ); @@ -888,7 +892,7 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) { int ret = 0; size_t n = 0, offset = 0; - unsigned char hash[36]; + unsigned char hash[48]; int hash_id = SIG_RSA_RAW; unsigned int hashlen = 36; @@ -903,8 +907,21 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) { - hash_id = SIG_RSA_SHA256; - hashlen = 32; + // TODO TLS1.2 Should be based on allowed signature algorithm received in + // Certificate Request according to RFC 5246. But OpenSSL only allows + // SHA256 and SHA384. Find out why OpenSSL does this. + // + if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + { + hash_id = SIG_RSA_SHA384; + hashlen = 48; + } + else + { + hash_id = SIG_RSA_SHA256; + hashlen = 32; + } } if( ssl->rsa_key == NULL ) @@ -934,9 +951,21 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) { - // TODO TLS1.2 Base on signature algorithm received in Certificate Request - ssl->out_msg[4] = SSL_HASH_SHA256; - ssl->out_msg[5] = SSL_SIG_RSA; + // TODO TLS1.2 Should be based on allowed signature algorithm received in + // Certificate Request according to RFC 5246. But OpenSSL only allows + // SHA256 and SHA384. Find out why OpenSSL does this. + // + if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + { + ssl->out_msg[4] = SSL_HASH_SHA384; + ssl->out_msg[5] = SSL_SIG_RSA; + } + else + { + ssl->out_msg[4] = SSL_HASH_SHA256; + ssl->out_msg[5] = SSL_SIG_RSA; + } offset = 2; } diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 2d8b0b8d7..790b8a7c6 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -109,6 +109,7 @@ static int ssl_parse_client_hello( ssl_context *ssl ) md5_update( &ssl->fin_md5 , buf + 2, n ); sha1_update( &ssl->fin_sha1, buf + 2, n ); sha2_update( &ssl->fin_sha2, buf + 2, n ); + sha4_update( &ssl->fin_sha4, buf + 2, n ); buf = ssl->in_msg; n = ssl->in_left - 5; @@ -230,6 +231,7 @@ static int ssl_parse_client_hello( ssl_context *ssl ) md5_update( &ssl->fin_md5 , buf, n ); sha1_update( &ssl->fin_sha1, buf, n ); sha2_update( &ssl->fin_sha2, buf, n ); + sha4_update( &ssl->fin_sha4, buf, n ); /* * SSL layer: @@ -539,7 +541,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) #if defined(POLARSSL_DHM_C) int ret; size_t n, rsa_key_len = 0; - unsigned char hash[36]; + unsigned char hash[48]; md5_context md5; sha1_context sha1; int hash_id; @@ -557,7 +559,9 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA && ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA && ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_128_SHA256 && - ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 ) + ssl->session->ciphersuite != SSL_EDH_RSA_CAMELLIA_256_SHA256 && + ssl->session->ciphersuite != SSL_EDH_RSA_AES_128_GCM_SHA256 && + ssl->session->ciphersuite != SSL_EDH_RSA_AES_256_GCM_SHA384 ) { SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); ssl->state++; @@ -770,7 +774,9 @@ static int ssl_parse_client_key_exchange( ssl_context *ssl ) ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA || ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA || ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_128_SHA256 || - ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 ) + ssl->session->ciphersuite == SSL_EDH_RSA_CAMELLIA_256_SHA256 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) { #if !defined(POLARSSL_DHM_C) SSL_DEBUG_MSG( 1, ( "support for dhm is not available" ) ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 98a2187a9..9a962b2d1 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -43,6 +43,10 @@ #include "polarssl/ssl.h" #include "polarssl/sha2.h" +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + #include #include @@ -152,9 +156,49 @@ static int tls_prf_sha256( unsigned char *secret, size_t slen, char *label, return( 0 ); } -static void ssl_calc_finished_ssl (ssl_context *,unsigned char *,int); -static void ssl_calc_finished_tls (ssl_context *,unsigned char *,int); -static void ssl_calc_finished_tls1_2(ssl_context *,unsigned char *,int); +static int tls_prf_sha384( unsigned char *secret, size_t slen, char *label, + unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k; + unsigned char tmp[128]; + unsigned char h_i[48]; + + if( sizeof( tmp ) < 48 + strlen( label ) + rlen ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + nb = strlen( label ); + memcpy( tmp + 48, label, nb ); + memcpy( tmp + 48 + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + sha4_hmac( secret, slen, tmp + 48, nb, tmp, 1 ); + + for( i = 0; i < dlen; i += 48 ) + { + sha4_hmac( secret, slen, tmp, 48 + nb, h_i, 1 ); + sha4_hmac( secret, slen, tmp, 48, tmp, 1 ); + + k = ( i + 48 > dlen ) ? dlen % 48 : 48; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + memset( tmp, 0, sizeof( tmp ) ); + memset( h_i, 0, sizeof( h_i ) ); + + return( 0 ); +} + +static void ssl_calc_finished_ssl(ssl_context *,unsigned char *,int); +static void ssl_calc_finished_tls(ssl_context *,unsigned char *,int); +static void ssl_calc_finished_tls_sha256(ssl_context *,unsigned char *,int); +static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int); int ssl_derive_keys( ssl_context *ssl ) { @@ -167,26 +211,34 @@ int ssl_derive_keys( ssl_context *ssl ) unsigned char keyblk[256]; unsigned char *key1; unsigned char *key2; + unsigned int iv_copy_len; SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); /* - * Set appropriate PRF function. - */ - if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) - ssl->tls_prf = tls1_prf; - else - ssl->tls_prf = tls_prf_sha256; - - /* - * Set appropriate SSL / TLS / TLS1.2 functions + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions */ if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + ssl->tls_prf = tls1_prf; ssl->calc_finished = ssl_calc_finished_ssl; + } else if( ssl->minor_ver < SSL_MINOR_VERSION_3 ) + { + ssl->tls_prf = tls1_prf; ssl->calc_finished = ssl_calc_finished_tls; + } + else if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + { + ssl->tls_prf = tls_prf_sha384; + ssl->calc_finished = ssl_calc_finished_tls_sha384; + } else - ssl->calc_finished = ssl_calc_finished_tls1_2; + { + ssl->tls_prf = tls_prf_sha256; + ssl->calc_finished = ssl_calc_finished_tls_sha256; + } /* * SSLv3: @@ -337,6 +389,21 @@ int ssl_derive_keys( ssl_context *ssl ) ssl->ivlen = 16; ssl->maclen = 32; break; #endif +#if defined(POLARSSL_GCM_C) + case SSL_RSA_AES_128_GCM_SHA256: + case SSL_EDH_RSA_AES_128_GCM_SHA256: + ssl->keylen = 16; ssl->minlen = 1; + ssl->ivlen = 12; ssl->maclen = 0; + ssl->fixed_ivlen = 4; + break; + + case SSL_RSA_AES_256_GCM_SHA384: + case SSL_EDH_RSA_AES_256_GCM_SHA384: + ssl->keylen = 32; ssl->minlen = 1; + ssl->ivlen = 12; ssl->maclen = 0; + ssl->fixed_ivlen = 4; + break; +#endif #endif #if defined(POLARSSL_CAMELLIA_C) @@ -417,9 +484,10 @@ int ssl_derive_keys( ssl_context *ssl ) /* * 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 ); + iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen; + memcpy( ssl->iv_enc, key2 + ssl->keylen, iv_copy_len ); + memcpy( ssl->iv_dec, key2 + ssl->keylen + iv_copy_len, + iv_copy_len ); } else { @@ -432,9 +500,10 @@ int ssl_derive_keys( ssl_context *ssl ) /* * 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 ); + iv_copy_len = ( ssl->fixed_ivlen ) ? ssl->fixed_ivlen : ssl->ivlen; + memcpy( ssl->iv_dec, key1 + ssl->keylen, iv_copy_len ); + memcpy( ssl->iv_enc, key1 + ssl->keylen + iv_copy_len, + iv_copy_len ); } switch( ssl->session->ciphersuite ) @@ -458,42 +527,48 @@ int ssl_derive_keys( ssl_context *ssl ) #if defined(POLARSSL_AES_C) case SSL_RSA_AES_128_SHA: case SSL_EDH_RSA_AES_128_SHA: -#if defined(POLARSSL_SHA2_C) case SSL_RSA_AES_128_SHA256: case SSL_EDH_RSA_AES_128_SHA256: -#endif aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 128 ); aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 128 ); break; case SSL_RSA_AES_256_SHA: case SSL_EDH_RSA_AES_256_SHA: -#if defined(POLARSSL_SHA2_C) case SSL_RSA_AES_256_SHA256: case SSL_EDH_RSA_AES_256_SHA256: -#endif aes_setkey_enc( (aes_context *) ssl->ctx_enc, key1, 256 ); aes_setkey_dec( (aes_context *) ssl->ctx_dec, key2, 256 ); break; + +#if defined(POLARSSL_GCM_C) + case SSL_RSA_AES_128_GCM_SHA256: + case SSL_EDH_RSA_AES_128_GCM_SHA256: + gcm_init( (gcm_context *) ssl->ctx_enc, key1, 128 ); + gcm_init( (gcm_context *) ssl->ctx_dec, key2, 128 ); + break; + + case SSL_RSA_AES_256_GCM_SHA384: + case SSL_EDH_RSA_AES_256_GCM_SHA384: + gcm_init( (gcm_context *) ssl->ctx_enc, key1, 256 ); + gcm_init( (gcm_context *) ssl->ctx_dec, key2, 256 ); + break; +#endif #endif #if defined(POLARSSL_CAMELLIA_C) case SSL_RSA_CAMELLIA_128_SHA: case SSL_EDH_RSA_CAMELLIA_128_SHA: -#if defined(POLARSSL_SHA2_C) case SSL_RSA_CAMELLIA_128_SHA256: case SSL_EDH_RSA_CAMELLIA_128_SHA256: -#endif camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 128 ); camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 128 ); break; case SSL_RSA_CAMELLIA_256_SHA: case SSL_EDH_RSA_CAMELLIA_256_SHA: -#if defined(POLARSSL_SHA2_C) case SSL_RSA_CAMELLIA_256_SHA256: case SSL_EDH_RSA_CAMELLIA_256_SHA256: -#endif camellia_setkey_enc( (camellia_context *) ssl->ctx_enc, key1, 256 ); camellia_setkey_dec( (camellia_context *) ssl->ctx_dec, key2, 256 ); break; @@ -527,11 +602,12 @@ int ssl_derive_keys( ssl_context *ssl ) return( 0 ); } -void ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] ) +void ssl_calc_verify( ssl_context *ssl, unsigned char hash[48] ) { md5_context md5; sha1_context sha1; sha2_context sha2; + sha4_context sha4; unsigned char pad_1[48]; unsigned char pad_2[48]; @@ -540,6 +616,7 @@ void ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] ) memcpy( &md5 , &ssl->fin_md5 , sizeof( md5_context ) ); memcpy( &sha1, &ssl->fin_sha1, sizeof( sha1_context ) ); memcpy( &sha2, &ssl->fin_sha2, sizeof( sha2_context ) ); + memcpy( &sha4, &ssl->fin_sha4, sizeof( sha4_context ) ); if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) { @@ -571,12 +648,17 @@ void ssl_calc_verify( ssl_context *ssl, unsigned char hash[36] ) md5_finish( &md5, hash ); sha1_finish( &sha1, hash + 16 ); } + else if( ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + { + sha4_finish( &sha4, hash ); + } else { sha2_finish( &sha2, hash ); } - SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); return; @@ -690,10 +772,6 @@ static int ssl_encrypt_buf( ssl_context *ssl ) ssl->out_msglen += ssl->maclen; - for( i = 8; i > 0; i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - if( ssl->ivlen == 0 ) { padlen = 0; @@ -723,6 +801,82 @@ static int ssl_encrypt_buf( ssl_context *ssl ) #endif return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } + else if( ssl->ivlen == 12 ) + { + size_t enc_msglen; + unsigned char *enc_msg; + unsigned char add_data[13]; + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + + padlen = 0; + enc_msglen = ssl->out_msglen; + + memcpy( add_data, ssl->out_ctr, 8 ); + add_data[8] = ssl->out_msgtype; + add_data[9] = ssl->major_ver; + add_data[10] = ssl->minor_ver; + add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->out_msglen & 0xFF; + + SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + +#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C) + + if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || + ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + { + /* + * Generate IV + */ + ret = ssl->f_rng( ssl->p_rng, ssl->iv_enc + ssl->fixed_ivlen, + ssl->ivlen - ssl->fixed_ivlen ); + if( ret != 0 ) + return( ret ); + + /* + * Shift message for ivlen bytes and prepend IV + */ + memmove( ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen, + ssl->out_msg, ssl->out_msglen ); + memcpy( ssl->out_msg, ssl->iv_enc + ssl->fixed_ivlen, + ssl->ivlen - ssl->fixed_ivlen ); + + /* + * Fix pointer positions and message length with added IV + */ + enc_msg = ssl->out_msg + ssl->ivlen - ssl->fixed_ivlen; + enc_msglen = ssl->out_msglen; + ssl->out_msglen += ssl->ivlen - ssl->fixed_ivlen; + + SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + ssl->out_msglen, 0 ) ); + + SSL_DEBUG_BUF( 4, "before encrypt: output payload", + ssl->out_msg, ssl->out_msglen ); + + /* + * Adjust for tag + */ + ssl->out_msglen += 16; + + gcm_crypt_and_tag( (gcm_context *) ssl->ctx_enc, + GCM_ENCRYPT, enc_msglen, + ssl->iv_enc, ssl->ivlen, + add_data, 13, + enc_msg, enc_msg, + 16, enc_msg + enc_msglen ); + + SSL_DEBUG_BUF( 4, "after encrypt: tag", + enc_msg + enc_msglen, 16 ); + + } else +#endif + return( ret ); + } else { unsigned char *enc_msg; @@ -834,6 +988,10 @@ static int ssl_encrypt_buf( ssl_context *ssl ) } } + for( i = 8; i > 0; i-- ) + if( ++ssl->out_ctr[i - 1] != 0 ) + break; + SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); return( 0 ); @@ -879,6 +1037,65 @@ static int ssl_decrypt_buf( ssl_context *ssl ) #endif return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); } + else if( ssl->ivlen == 12 ) + { + unsigned char *dec_msg; + unsigned char *dec_msg_result; + size_t dec_msglen; + unsigned char add_data[13]; + int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; + + padlen = 0; + +#if defined(POLARSSL_AES_C) && defined(POLARSSL_GCM_C) + if( ssl->session->ciphersuite == SSL_RSA_AES_128_GCM_SHA256 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_128_GCM_SHA256 || + ssl->session->ciphersuite == SSL_RSA_AES_256_GCM_SHA384 || + ssl->session->ciphersuite == SSL_EDH_RSA_AES_256_GCM_SHA384 ) + { + dec_msglen = ssl->in_msglen - ( ssl->ivlen - ssl->fixed_ivlen ); + dec_msglen -= 16; + dec_msg = ssl->in_msg + ( ssl->ivlen - ssl->fixed_ivlen ); + dec_msg_result = ssl->in_msg; + ssl->in_msglen = dec_msglen; + + memcpy( add_data, ssl->in_ctr, 8 ); + add_data[8] = ssl->in_msgtype; + add_data[9] = ssl->major_ver; + add_data[10] = ssl->minor_ver; + add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; + add_data[12] = ssl->in_msglen & 0xFF; + + SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, 13 ); + + memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg, + ssl->ivlen - ssl->fixed_ivlen ); + + SSL_DEBUG_BUF( 4, "IV used", ssl->iv_dec, ssl->ivlen ); + SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 ); + + memcpy( ssl->iv_dec + ssl->fixed_ivlen, ssl->in_msg, + ssl->ivlen - ssl->fixed_ivlen ); + + ret = gcm_auth_decrypt( (gcm_context *) ssl->ctx_dec, + dec_msglen, + ssl->iv_dec, ssl->ivlen, + add_data, 13, + dec_msg + dec_msglen, 16, + dec_msg, dec_msg_result ); + + if( ret != 0 ) + { + SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)", + -ret ) ); + + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } + } else +#endif + return( ret ); + } else { unsigned char *dec_msg; @@ -1063,7 +1280,7 @@ static int ssl_decrypt_buf( ssl_context *ssl ) * Finally check the padding length; bad padding * will produce the same error as an invalid MAC. */ - if( ssl->ivlen != 0 && padlen == 0 ) + if( ssl->ivlen != 0 && ssl->ivlen != 12 && padlen == 0 ) return( POLARSSL_ERR_SSL_INVALID_MAC ); if( ssl->in_msglen == 0 ) @@ -1181,6 +1398,7 @@ int ssl_write_record( ssl_context *ssl ) md5_update( &ssl->fin_md5 , ssl->out_msg, len ); sha1_update( &ssl->fin_sha1, ssl->out_msg, len ); sha2_update( &ssl->fin_sha2, ssl->out_msg, len ); + sha4_update( &ssl->fin_sha4, ssl->out_msg, len ); } if( ssl->do_crypt != 0 ) @@ -1256,6 +1474,7 @@ int ssl_read_record( ssl_context *ssl ) md5_update( &ssl->fin_md5 , ssl->in_msg, ssl->in_hslen ); sha1_update( &ssl->fin_sha1, ssl->in_msg, ssl->in_hslen ); sha2_update( &ssl->fin_sha2, ssl->in_msg, ssl->in_hslen ); + sha4_update( &ssl->fin_sha4, ssl->in_msg, ssl->in_hslen ); return( 0 ); } @@ -1402,6 +1621,7 @@ int ssl_read_record( ssl_context *ssl ) md5_update( &ssl->fin_md5 , ssl->in_msg, ssl->in_hslen ); sha1_update( &ssl->fin_sha1, ssl->in_msg, ssl->in_hslen ); sha2_update( &ssl->fin_sha2, ssl->in_msg, ssl->in_hslen ); + sha4_update( &ssl->fin_sha4, ssl->in_msg, ssl->in_hslen ); } if( ssl->in_msgtype == SSL_MSG_ALERT ) @@ -1888,7 +2108,7 @@ static void ssl_calc_finished_tls( SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } -static void ssl_calc_finished_tls1_2( +static void ssl_calc_finished_tls_sha256( ssl_context *ssl, unsigned char *buf, int from ) { int len = 12; @@ -1927,6 +2147,45 @@ static void ssl_calc_finished_tls1_2( SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } +static void ssl_calc_finished_tls_sha384( + ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + char *sender; + sha4_context sha4; + unsigned char padbuf[48]; + + SSL_DEBUG_MSG( 2, ( "=> calc finished tls 1.2" ) ); + + memcpy( &sha4, &ssl->fin_sha4, sizeof( sha4_context ) ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + + SSL_DEBUG_BUF( 4, "finished sha4 state", (unsigned char *) + sha4.state, sizeof( sha4.state ) ); + + sender = ( from == SSL_IS_CLIENT ) + ? (char *) "client finished" + : (char *) "server finished"; + + sha4_finish( &sha4, padbuf ); + + ssl->tls_prf( ssl->session->master, 48, sender, + padbuf, 48, buf, len ); + + SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + memset( &sha4, 0, sizeof( sha4_context ) ); + + memset( padbuf, 0, sizeof( padbuf ) ); + + SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} + int ssl_write_finished( ssl_context *ssl ) { int ret, hash_len; @@ -2064,6 +2323,7 @@ int ssl_init( ssl_context *ssl ) md5_starts( &ssl->fin_md5 ); sha1_starts( &ssl->fin_sha1 ); sha2_starts( &ssl->fin_sha2, 0 ); + sha4_starts( &ssl->fin_sha4, 1 ); return( 0 ); } @@ -2110,6 +2370,7 @@ void ssl_session_reset( ssl_context *ssl ) md5_starts( &ssl->fin_md5 ); sha1_starts( &ssl->fin_sha1 ); sha2_starts( &ssl->fin_sha2, 0 ); + sha4_starts( &ssl->fin_sha4, 1 ); } /* @@ -2326,8 +2587,24 @@ const char *ssl_get_ciphersuite_name( const int ciphersuite_id ) case SSL_EDH_RSA_AES_256_SHA256: return( "SSL-EDH-RSA-AES-256-SHA256" ); #endif + +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) + case SSL_RSA_AES_128_GCM_SHA256: + return( "SSL-RSA-AES-128-GCM-SHA256" ); + + case SSL_EDH_RSA_AES_128_GCM_SHA256: + return( "SSL-EDH-RSA-AES-128-GCM-SHA256" ); #endif +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) + case SSL_RSA_AES_256_GCM_SHA384: + return( "SSL-RSA-AES-256-GCM-SHA384" ); + + case SSL_EDH_RSA_AES_256_GCM_SHA384: + return( "SSL-EDH-RSA-AES-256-GCM-SHA384" ); +#endif +#endif /* POLARSSL_AES_C */ + #if defined(POLARSSL_CAMELLIA_C) case SSL_RSA_CAMELLIA_128_SHA: return( "SSL-RSA-CAMELLIA-128-SHA" ); @@ -2417,6 +2694,20 @@ int ssl_get_ciphersuite_id( const char *ciphersuite_name ) if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-SHA256")) return( SSL_EDH_RSA_AES_256_SHA256 ); #endif + +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) + if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-128-GCM-SHA256")) + return( SSL_RSA_AES_128_GCM_SHA256 ); + if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-128-GCM-SHA256")) + return( SSL_EDH_RSA_AES_128_GCM_SHA256 ); +#endif + +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) + if (0 == strcasecmp(ciphersuite_name, "SSL-RSA-AES-256-GCM-SHA384")) + return( SSL_RSA_AES_256_GCM_SHA384 ); + if (0 == strcasecmp(ciphersuite_name, "SSL-EDH-RSA-AES-256-GCM-SHA384")) + return( SSL_EDH_RSA_AES_256_GCM_SHA384 ); +#endif #endif #if defined(POLARSSL_CAMELLIA_C) @@ -2495,17 +2786,27 @@ int ssl_default_ciphersuites[] = #if defined(POLARSSL_AES_C) #if defined(POLARSSL_SHA2_C) SSL_EDH_RSA_AES_256_SHA256, - SSL_EDH_RSA_AES_128_SHA256, #endif /* POLARSSL_SHA2_C */ +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) + SSL_EDH_RSA_AES_256_GCM_SHA384, +#endif SSL_EDH_RSA_AES_256_SHA, +#if defined(POLARSSL_SHA2_C) + SSL_EDH_RSA_AES_128_SHA256, +#endif +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) + SSL_EDH_RSA_AES_128_GCM_SHA256, +#endif SSL_EDH_RSA_AES_128_SHA, #endif #if defined(POLARSSL_CAMELLIA_C) #if defined(POLARSSL_SHA2_C) SSL_EDH_RSA_CAMELLIA_256_SHA256, - SSL_EDH_RSA_CAMELLIA_128_SHA256, #endif /* POLARSSL_SHA2_C */ SSL_EDH_RSA_CAMELLIA_256_SHA, +#if defined(POLARSSL_SHA2_C) + SSL_EDH_RSA_CAMELLIA_128_SHA256, +#endif /* POLARSSL_SHA2_C */ SSL_EDH_RSA_CAMELLIA_128_SHA, #endif #if defined(POLARSSL_DES_C) @@ -2516,6 +2817,9 @@ int ssl_default_ciphersuites[] = #if defined(POLARSSL_AES_C) #if defined(POLARSSL_SHA2_C) SSL_RSA_AES_256_SHA256, +#endif /* POLARSSL_SHA2_C */ +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) + SSL_RSA_AES_256_GCM_SHA384, #endif /* POLARSSL_SHA2_C */ SSL_RSA_AES_256_SHA, #endif @@ -2528,6 +2832,9 @@ int ssl_default_ciphersuites[] = #if defined(POLARSSL_AES_C) #if defined(POLARSSL_SHA2_C) SSL_RSA_AES_128_SHA256, +#endif /* POLARSSL_SHA2_C */ +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) + SSL_RSA_AES_128_GCM_SHA256, #endif /* POLARSSL_SHA2_C */ SSL_RSA_AES_128_SHA, #endif diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c index d4798ecbd..0d2478718 100644 --- a/programs/ssl/ssl_server.c +++ b/programs/ssl/ssl_server.c @@ -80,6 +80,12 @@ int my_ciphersuites[] = #endif /* POLARSSL_SHA2_C */ SSL_EDH_RSA_AES_256_SHA, SSL_EDH_RSA_AES_128_SHA, +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) + SSL_EDH_RSA_AES_256_GCM_SHA384, +#endif +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) + SSL_EDH_RSA_AES_128_GCM_SHA256, +#endif #endif #if defined(POLARSSL_CAMELLIA_C) #if defined(POLARSSL_SHA2_C) @@ -111,6 +117,12 @@ int my_ciphersuites[] = SSL_RSA_AES_128_SHA256, #endif /* POLARSSL_SHA2_C */ SSL_RSA_AES_128_SHA, +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA4_C) + SSL_RSA_AES_256_GCM_SHA384, +#endif +#if defined(POLARSSL_GCM_C) && defined(POLARSSL_SHA2_C) + SSL_RSA_AES_128_GCM_SHA256, +#endif #endif #if defined(POLARSSL_CAMELLIA_C) #if defined(POLARSSL_SHA2_C) diff --git a/tests/compat.sh b/tests/compat.sh index ac41ec3b5..473a21ad3 100644 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -7,7 +7,7 @@ VERIFY="" if [ "X$VERIFY" = "XYES" ]; then P_CLIENT_ARGS="crt_file=data_files/server2.crt key_file=data_files/server2.key" - O_SERVER_ARGS="-verify 10" + O_SERVER_ARGS="-verify 10 -CAfile data_files/test-ca.crt" fi for MODE in $MODES; @@ -61,6 +61,10 @@ then SSL-EDH-RSA-AES-128-SHA256 \ SSL-RSA-AES-256-SHA256 \ SSL-EDH-RSA-AES-256-SHA256 \ + SSL-RSA-AES-128-GCM-SHA256 \ + SSL-EDH-RSA-AES-128-GCM-SHA256 \ + SSL-RSA-AES-256-GCM-SHA384 \ + SSL-EDH-RSA-AES-256-GCM-SHA384 \ " O_CIPHERS="$O_CIPHERS \ @@ -69,6 +73,10 @@ then DHE-RSA-AES128-SHA256 \ AES256-SHA256 \ DHE-RSA-AES256-SHA256 \ + AES128-GCM-SHA256 \ + DHE-RSA-AES128-GCM-SHA256 \ + AES256-GCM-SHA384 \ + DHE-RSA-AES256-GCM-SHA384 \ " fi