Merge branch 'etm' into dtls

* etm:
  Fix warning in reduced config
  Update Changelog for EtM
  Keep EtM state across renegotiations
  Adjust minimum length for EtM
  Don't send back EtM extension if not using CBC
  Fix for the RFC erratum
  Implement EtM
  Preparation for EtM
  Implement initial negotiation of EtM

Conflicts:
	include/polarssl/check_config.h
This commit is contained in:
Manuel Pégourié-Gonnard 2014-11-06 01:36:32 +01:00
commit f9d778d635
10 changed files with 531 additions and 23 deletions

View file

@ -12,11 +12,12 @@ API Changes
= 1.3 branch
Reminder: bump SONAME for ABI change (FALLBACK_SCSV, session-hash)
Reminder: bump SONAME for ABI change (FALLBACK_SCSV, session-hash, EtM)
Features
* Add support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv)
* Add support for Extended Master Secret (draft-ietf-tls-session-hash)
* Add support for Encrypt-then-MAC (RFC 7366)
= PolarSSL 1.3.9 released 2014-10-20
Security

View file

@ -283,6 +283,13 @@
#error "POLARSSL_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites"
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) && \
!defined(POLARSSL_SSL_PROTO_TLS1) && \
!defined(POLARSSL_SSL_PROTO_TLS1_1) && \
!defined(POLARSSL_SSL_PROTO_TLS1_2)
#error "POLARSSL_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites"
#endif
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) && \
!defined(POLARSSL_SSL_PROTO_TLS1) && \
!defined(POLARSSL_SSL_PROTO_TLS1_1) && \

View file

@ -811,6 +811,24 @@
*/
//#define POLARSSL_SSL_DEBUG_ALL
/** \def POLARSSL_SSL_ENCRYPT_THEN_MAC
*
* Enable support for Encrypt-then-MAC, RFC 7366.
*
* This allows peers that both support it to use a more robust protection for
* ciphersuites using CBC, providing deep resistance against timing attacks
* on the padding or underlying cipher.
*
* This only affects CBC ciphersuites, and is useless if none is defined.
*
* Requires: POLARSSL_SSL_PROTO_TLS1 or
* POLARSSL_SSL_PROTO_TLS1_1 or
* POLARSSL_SSL_PROTO_TLS1_2
*
* Comment this macro to disable support for Encrypt-then-MAC
*/
#define POLARSSL_SSL_ENCRYPT_THEN_MAC
/** \def POLARSSL_SSL_EXTENDED_MASTER_SECRET
*
* Enable support for Extended Master Secret, aka Session Hash

View file

@ -221,6 +221,9 @@
#define SSL_EXTENDED_MS_DISABLED 0
#define SSL_EXTENDED_MS_ENABLED 1
#define SSL_ETM_DISABLED 0
#define SSL_ETM_ENABLED 1
#define SSL_COMPRESS_NULL 0
#define SSL_COMPRESS_DEFLATE 1
@ -442,6 +445,7 @@
#define TLS_EXT_ALPN 16
#define TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */
#define TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */
#define TLS_EXT_SESSION_TICKET 35
@ -585,6 +589,10 @@ struct _ssl_session
#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
int trunc_hmac; /*!< flag for truncated hmac activation */
#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
int encrypt_then_mac; /*!< flag for EtM activation */
#endif
};
/*
@ -795,6 +803,9 @@ struct _ssl_context
#if defined(POLARSSL_SSL_FALLBACK_SCSV) && defined(POLARSSL_SSL_CLI_C)
char fallback; /*!< flag for fallback connections */
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
char encrypt_then_mac; /*!< flag for encrypt-then-mac */
#endif
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
char extended_ms; /*!< flag for extended master secret */
#endif
@ -1754,6 +1765,21 @@ int ssl_set_min_version( ssl_context *ssl, int major, int minor );
void ssl_set_fallback( ssl_context *ssl, char fallback );
#endif /* POLARSSL_SSL_FALLBACK_SCSV && POLARSSL_SSL_CLI_C */
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
/**
* \brief Enable or disable Encrypt-then-MAC
* (Default: SSL_ETM_ENABLED)
*
* \note This should always be enabled, it is a security
* improvement, and should not cause any interoperability
* issue (used only if the peer supports it too).
*
* \param ssl SSL context
* \param etm SSL_ETM_ENABLED or SSL_ETM_DISABLED
*/
void ssl_set_encrypt_then_mac( ssl_context *ssl, char etm );
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
/**
* \brief Enable or disable Extended Master Secret negotiation.

View file

@ -359,6 +359,32 @@ static void ssl_write_truncated_hmac_ext( ssl_context *ssl,
}
#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
static void ssl_write_encrypt_then_mac_ext( ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
if( ssl->encrypt_then_mac == SSL_ETM_DISABLED ||
ssl->max_minor_ver == SSL_MINOR_VERSION_0 )
{
*olen = 0;
return;
}
SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac "
"extension" ) );
*p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF );
*p++ = 0x00;
*p++ = 0x00;
*olen = 4;
}
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
static void ssl_write_extended_ms_ext( ssl_context *ssl,
unsigned char *buf, size_t *olen )
@ -770,6 +796,11 @@ static int ssl_write_client_hello( ssl_context *ssl )
ext_len += olen;
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
#endif
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
@ -898,6 +929,26 @@ static int ssl_parse_truncated_hmac_ext( ssl_context *ssl,
}
#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
static int ssl_parse_encrypt_then_mac_ext( ssl_context *ssl,
const unsigned char *buf,
size_t len )
{
if( ssl->encrypt_then_mac == SSL_ETM_DISABLED ||
ssl->minor_ver == SSL_MINOR_VERSION_0 ||
len != 0 )
{
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
}
((void) buf);
ssl->session_negotiate->encrypt_then_mac = SSL_ETM_ENABLED;
return( 0 );
}
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
static int ssl_parse_extended_ms_ext( ssl_context *ssl,
const unsigned char *buf,
@ -1395,6 +1446,19 @@ static int ssl_parse_server_hello( ssl_context *ssl )
break;
#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
case TLS_EXT_ENCRYPT_THEN_MAC:
SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) );
if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl,
ext + 4, ext_size ) ) != 0 )
{
return( ret );
}
break;
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
case TLS_EXT_EXTENDED_MASTER_SECRET:
SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) );

View file

@ -665,6 +665,29 @@ static int ssl_parse_truncated_hmac_ext( ssl_context *ssl,
}
#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
static int ssl_parse_encrypt_then_mac_ext( ssl_context *ssl,
const unsigned char *buf,
size_t len )
{
if( len != 0 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
((void) buf);
if( ssl->encrypt_then_mac == SSL_ETM_ENABLED &&
ssl->minor_ver != SSL_MINOR_VERSION_0 )
{
ssl->session_negotiate->encrypt_then_mac = SSL_ETM_ENABLED;
}
return( 0 );
}
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
static int ssl_parse_extended_ms_ext( ssl_context *ssl,
const unsigned char *buf,
@ -1731,6 +1754,16 @@ read_record_header:
break;
#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
case TLS_EXT_ENCRYPT_THEN_MAC:
SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) );
ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size );
if( ret != 0 )
return( ret );
break;
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
case TLS_EXT_EXTENDED_MASTER_SECRET:
SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) );
@ -1939,6 +1972,49 @@ static void ssl_write_truncated_hmac_ext( ssl_context *ssl,
}
#endif /* POLARSSL_SSL_TRUNCATED_HMAC */
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
static void ssl_write_encrypt_then_mac_ext( ssl_context *ssl,
unsigned char *buf,
size_t *olen )
{
unsigned char *p = buf;
const ssl_ciphersuite_t *suite = NULL;
const cipher_info_t *cipher = NULL;
if( ssl->session_negotiate->encrypt_then_mac == SSL_EXTENDED_MS_DISABLED ||
ssl->minor_ver == SSL_MINOR_VERSION_0 )
{
*olen = 0;
return;
}
/*
* RFC 7366: "If a server receives an encrypt-then-MAC request extension
* from a client and then selects a stream or Authenticated Encryption
* with Associated Data (AEAD) ciphersuite, it MUST NOT send an
* encrypt-then-MAC response extension back to the client."
*/
if( ( suite = ssl_ciphersuite_from_id(
ssl->session_negotiate->ciphersuite ) ) == NULL ||
( cipher = cipher_info_from_type( suite->cipher ) ) == NULL ||
cipher->mode != POLARSSL_MODE_CBC )
{
*olen = 0;
return;
}
SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) );
*p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
*p++ = (unsigned char)( ( TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF );
*p++ = 0x00;
*p++ = 0x00;
*olen = 4;
}
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
static void ssl_write_extended_ms_ext( ssl_context *ssl,
unsigned char *buf,
@ -2344,6 +2420,11 @@ static int ssl_write_server_hello( ssl_context *ssl )
ext_len += olen;
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
#endif
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;

View file

@ -675,12 +675,23 @@ int ssl_derive_keys( ssl_context *ssl )
{
/*
* GenericBlockCipher:
* first multiple of blocklen greater than maclen
* + IV except for SSL3 and TLS 1.0
* 1. if EtM is in use: one block plus MAC
* otherwise: * first multiple of blocklen greater than maclen
* 2. IV except for SSL3 and TLS 1.0
*/
transform->minlen = transform->maclen
+ cipher_info->block_size
- transform->maclen % cipher_info->block_size;
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
if( session->encrypt_then_mac == SSL_ETM_ENABLED )
{
transform->minlen = transform->maclen
+ cipher_info->block_size;
}
else
#endif
{
transform->minlen = transform->maclen
+ cipher_info->block_size
- transform->maclen % cipher_info->block_size;
}
#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1)
if( ssl->minor_ver == SSL_MINOR_VERSION_0 ||
@ -1134,6 +1145,46 @@ static void ssl_mac( md_context_t *md_ctx, unsigned char *secret,
}
#endif /* POLARSSL_SSL_PROTO_SSL3 */
#define MAC_NONE 0
#define MAC_PLAINTEXT 1
#define MAC_CIPHERTEXT 2
/*
* Is MAC applied on ciphertext, cleartext or not at all?
*/
static char ssl_get_mac_order( ssl_context *ssl,
const ssl_session *session,
cipher_mode_t mode )
{
#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
if( mode == POLARSSL_MODE_STREAM )
return( MAC_PLAINTEXT );
#endif
#if defined(POLARSSL_CIPHER_MODE_CBC) && \
( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) )
if( mode == POLARSSL_MODE_CBC )
{
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
if( session != NULL && session->encrypt_then_mac == SSL_ETM_ENABLED )
{
SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
return( MAC_CIPHERTEXT );
}
#endif
return( MAC_PLAINTEXT );
}
#endif
/* Unused if AEAD is the only option */
((void) ssl);
((void) session);
((void) mode);
return( MAC_NONE );
}
/*
* Encryption/decryption functions
*/
@ -1141,17 +1192,19 @@ static int ssl_encrypt_buf( ssl_context *ssl )
{
const cipher_mode_t mode = cipher_get_cipher_mode(
&ssl->transform_out->cipher_ctx_enc );
char mac_order;
SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
mac_order = ssl_get_mac_order( ssl, ssl->session_out, mode );
/*
* Add MAC before encrypt, except for AEAD modes
* Add MAC before if needed
*/
#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \
( defined(POLARSSL_CIPHER_MODE_CBC) && \
( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
if( mode != POLARSSL_MODE_GCM &&
mode != POLARSSL_MODE_CCM )
if( mac_order == MAC_PLAINTEXT )
{
#if defined(POLARSSL_SSL_PROTO_SSL3)
if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
@ -1387,6 +1440,37 @@ static int ssl_encrypt_buf( ssl_context *ssl )
ssl->transform_out->ivlen );
}
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
if( mac_order == MAC_CIPHERTEXT )
{
/*
* MAC(MAC_write_key, seq_num +
* TLSCipherText.type +
* TLSCipherText.version +
* length_of( (IV +) ENC(...) ) +
* IV + // except for TLS 1.0
* ENC(content + padding + padding_length));
*/
unsigned char pseudo_hdr[13];
memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 );
memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 );
pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF );
pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF );
SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 );
md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 );
md_hmac_update( &ssl->transform_out->md_ctx_enc,
ssl->out_iv, ssl->out_msglen );
md_hmac_finish( &ssl->transform_out->md_ctx_enc,
ssl->out_iv + ssl->out_msglen );
md_hmac_reset( &ssl->transform_out->md_ctx_enc );
ssl->out_msglen += ssl->transform_out->maclen;
}
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
}
else
#endif /* POLARSSL_CIPHER_MODE_CBC &&
@ -1413,6 +1497,7 @@ static int ssl_decrypt_buf( ssl_context *ssl )
( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
size_t padlen = 0, correct = 1;
#endif
char mac_order;
SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
@ -1423,6 +1508,8 @@ static int ssl_decrypt_buf( ssl_context *ssl )
return( POLARSSL_ERR_SSL_INVALID_MAC );
}
mac_order = ssl_get_mac_order( ssl, ssl->session_in, mode );
#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
if( mode == POLARSSL_MODE_STREAM )
{
@ -1538,13 +1625,6 @@ static int ssl_decrypt_buf( ssl_context *ssl )
/*
* Check immediate ciphertext sanity
*/
if( ssl->in_msglen % ssl->transform_in->ivlen != 0 )
{
SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
ssl->in_msglen, ssl->transform_in->ivlen ) );
return( POLARSSL_ERR_SSL_INVALID_MAC );
}
#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
if( ssl->minor_ver >= SSL_MINOR_VERSION_2 )
minlen += ssl->transform_in->ivlen;
@ -1564,6 +1644,56 @@ static int ssl_decrypt_buf( ssl_context *ssl )
dec_msg = ssl->in_msg;
dec_msg_result = ssl->in_msg;
/*
* Authenticate before decrypt if enabled
*/
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
if( mac_order == MAC_CIPHERTEXT )
{
unsigned char computed_mac[POLARSSL_SSL_MAX_MAC_SIZE];
unsigned char pseudo_hdr[13];
dec_msglen -= ssl->transform_in->maclen;
ssl->in_msglen -= ssl->transform_in->maclen;
memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 );
memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 );
pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF );
pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF );
SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 );
md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 );
md_hmac_update( &ssl->transform_in->md_ctx_dec,
ssl->in_iv, ssl->in_msglen );
md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac );
md_hmac_reset( &ssl->transform_in->md_ctx_dec );
SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen,
ssl->transform_in->maclen );
SSL_DEBUG_BUF( 4, "computed mac", computed_mac,
ssl->transform_in->maclen );
if( safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac,
ssl->transform_in->maclen ) != 0 )
{
SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
return( POLARSSL_ERR_SSL_INVALID_MAC );
}
}
#endif /* POLARSSL_SSL_ENCRYPT_THEN_MAC */
/*
* Check length sanity
*/
if( ssl->in_msglen % ssl->transform_in->ivlen != 0 )
{
SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
ssl->in_msglen, ssl->transform_in->ivlen ) );
return( POLARSSL_ERR_SSL_INVALID_MAC );
}
#if defined(POLARSSL_SSL_PROTO_TLS1_1) || defined(POLARSSL_SSL_PROTO_TLS1_2)
/*
* Initialize for prepended IV for block cipher in TLS v1.1 and up
@ -1608,7 +1738,8 @@ static int ssl_decrypt_buf( ssl_context *ssl )
padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];
if( ssl->in_msglen < ssl->transform_in->maclen + padlen )
if( ssl->in_msglen < ssl->transform_in->maclen + padlen &&
mac_order == MAC_PLAINTEXT )
{
#if defined(POLARSSL_SSL_DEBUG_ALL)
SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
@ -1682,6 +1813,8 @@ static int ssl_decrypt_buf( ssl_context *ssl )
SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
}
ssl->in_msglen -= padlen;
}
else
#endif /* POLARSSL_CIPHER_MODE_CBC &&
@ -1695,17 +1828,17 @@ static int ssl_decrypt_buf( ssl_context *ssl )
ssl->in_msg, ssl->in_msglen );
/*
* Always compute the MAC (RFC4346, CBCTIME), except for AEAD of course
* Authenticate if not done yet.
* Compute the MAC regardless of the padding result (RFC4346, CBCTIME).
*/
#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \
( defined(POLARSSL_CIPHER_MODE_CBC) && \
( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) )
if( mode != POLARSSL_MODE_GCM &&
mode != POLARSSL_MODE_CCM )
if( mac_order == MAC_PLAINTEXT )
{
unsigned char tmp[POLARSSL_SSL_MAX_MAC_SIZE];
ssl->in_msglen -= ( ssl->transform_in->maclen + padlen );
ssl->in_msglen -= ssl->transform_in->maclen;
ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 );
ssl->in_len[1] = (unsigned char)( ssl->in_msglen );
@ -1829,6 +1962,10 @@ static int ssl_decrypt_buf( ssl_context *ssl )
return( 0 );
}
#undef MAC_NONE
#undef MAC_PLAINTEXT
#undef MAC_CIPHERTEXT
#if defined(POLARSSL_ZLIB_SUPPORT)
/*
* Compression/decompression functions
@ -4336,6 +4473,12 @@ void ssl_handshake_wrapup( ssl_context *ssl )
*/
if( ssl->session )
{
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
/* RFC 7366 3.1: keep the EtM state */
ssl->session_negotiate->encrypt_then_mac =
ssl->session->encrypt_then_mac;
#endif
ssl_session_free( ssl->session );
polarssl_free( ssl->session );
}
@ -4763,6 +4906,10 @@ int ssl_init( ssl_context *ssl )
/* No error is possible, SSL_TRANSPORT_STREAM always valid */
(void) ssl_set_transport( ssl, SSL_TRANSPORT_STREAM );
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
ssl->encrypt_then_mac = SSL_ETM_ENABLED;
#endif
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
ssl->extended_ms = SSL_EXTENDED_MS_ENABLED;
#endif
@ -5459,6 +5606,13 @@ void ssl_set_fallback( ssl_context *ssl, char fallback )
}
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
void ssl_set_encrypt_then_mac( ssl_context *ssl, char etm )
{
ssl->encrypt_then_mac = etm;
}
#endif
#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET)
void ssl_set_extended_master_secret( ssl_context *ssl, char ems )
{

View file

@ -102,6 +102,7 @@ int main( int argc, char *argv[] )
#define DFL_HS_TO_MAX 0
#define DFL_FALLBACK -1
#define DFL_EXTENDED_MS -1
#define DFL_ETM -1
#define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: "
#define GET_REQUEST_END "\r\n\r\n"
@ -146,6 +147,7 @@ struct options
uint32_t hs_to_max; /* Max value of DTLS handshake timer */
int fallback; /* is this a fallback connection? */
char extended_ms; /* negotiate extended master secret? */
char etm; ; /* negotiate encrypt then mac? ? */
} opt;
static void my_debug( void *ctx, int level, const char *str )
@ -321,6 +323,13 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags )
#define USAGE_EMS ""
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
#define USAGE_ETM \
" etm=0/1 default: (library default: on)\n"
#else
#define USAGE_ETM ""
#endif
#define USAGE \
"\n usage: ssl_client2 param=<>...\n" \
"\n acceptable parameters:\n" \
@ -356,6 +365,7 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags )
USAGE_ALPN \
USAGE_FALLBACK \
USAGE_EMS \
USAGE_ETM \
"\n" \
" min_version=%%s default: \"\" (ssl3)\n" \
" max_version=%%s default: \"\" (tls1_2)\n" \
@ -463,6 +473,7 @@ int main( int argc, char *argv[] )
opt.hs_to_max = DFL_HS_TO_MAX;
opt.fallback = DFL_FALLBACK;
opt.extended_ms = DFL_EXTENDED_MS;
opt.etm = DFL_ETM;
for( i = 1; i < argc; i++ )
{
@ -605,6 +616,15 @@ int main( int argc, char *argv[] )
default: goto usage;
}
}
else if( strcmp( p, "etm" ) == 0 )
{
switch( atoi( q ) )
{
case 0: opt.etm = SSL_ETM_DISABLED; break;
case 1: opt.etm = SSL_ETM_ENABLED; break;
default: goto usage;
}
}
else if( strcmp( p, "min_version" ) == 0 )
{
if( strcmp( q, "ssl3" ) == 0 )
@ -1022,6 +1042,11 @@ int main( int argc, char *argv[] )
ssl_set_extended_master_secret( &ssl, opt.extended_ms );
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
if( opt.etm != DFL_ETM )
ssl_set_encrypt_then_mac( &ssl, opt.etm );
#endif
#if defined(POLARSSL_SSL_ALPN)
if( opt.alpn_string != NULL )
if( ( ret = ssl_set_alpn_protocols( &ssl, alpn_list ) ) != 0 )

View file

@ -128,6 +128,7 @@ int main( int argc, char *argv[] )
#define DFL_HS_TO_MAX 0
#define DFL_BADMAC_LIMIT -1
#define DFL_EXTENDED_MS -1
#define DFL_ETM -1
#define LONG_RESPONSE "<p>01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
"02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
@ -196,6 +197,7 @@ struct options
uint32_t hs_to_max; /* Max value of DTLS handshake timer */
int badmac_limit; /* Limit of records with bad MAC */
char extended_ms; /* allow negotiation of extended MS? */
char etm; /* allow negotiation of encrypt-then-MAC? */
} opt;
static void my_debug( void *ctx, int level, const char *str )
@ -357,6 +359,13 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len )
#define USAGE_EMS ""
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
#define USAGE_ETM \
" etm=0/1 default: (library default: on)\n"
#else
#define USAGE_ETM ""
#endif
#define USAGE \
"\n usage: ssl_server2 param=<>...\n" \
"\n acceptable parameters:\n" \
@ -390,6 +399,7 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len )
USAGE_MAX_FRAG_LEN \
USAGE_ALPN \
USAGE_EMS \
USAGE_ETM \
"\n" \
" min_version=%%s default: \"ssl3\"\n" \
" max_version=%%s default: \"tls1_2\"\n" \
@ -794,6 +804,7 @@ int main( int argc, char *argv[] )
opt.hs_to_max = DFL_HS_TO_MAX;
opt.badmac_limit = DFL_BADMAC_LIMIT;
opt.extended_ms = DFL_EXTENDED_MS;
opt.etm = DFL_ETM;
for( i = 1; i < argc; i++ )
{
@ -998,6 +1009,15 @@ int main( int argc, char *argv[] )
default: goto usage;
}
}
else if( strcmp( p, "etm" ) == 0 )
{
switch( atoi( q ) )
{
case 0: opt.etm = SSL_ETM_DISABLED; break;
case 1: opt.etm = SSL_ETM_ENABLED; break;
default: goto usage;
}
}
else if( strcmp( p, "tickets" ) == 0 )
{
opt.tickets = atoi( q );
@ -1435,6 +1455,11 @@ int main( int argc, char *argv[] )
ssl_set_extended_master_secret( &ssl, opt.extended_ms );
#endif
#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC)
if( opt.etm != DFL_ETM )
ssl_set_encrypt_then_mac( &ssl, opt.etm );
#endif
#if defined(POLARSSL_SSL_ALPN)
if( opt.alpn_string != NULL )
if( ( ret = ssl_set_alpn_protocols( &ssl, alpn_list ) ) != 0 )

View file

@ -362,14 +362,14 @@ run_test() {
if is_polar "$SRV_CMD"; then
if grep "Performing the SSL/TLS handshake" $SRV_OUT >/dev/null; then :;
else
fail "server failed to start"
fail "server or client failed to reach handshake stage"
return
fi
fi
if is_polar "$CLI_CMD"; then
if grep "Performing the SSL/TLS handshake" $CLI_OUT >/dev/null; then :;
else
fail "client failed to start"
fail "server or client failed to reach handshake stage"
return
fi
fi
@ -567,6 +567,92 @@ run_test "Truncated HMAC: actual test" \
0 \
-s "dumping 'computed mac' (10 bytes)"
# Tests for Encrypt-then-MAC extension
run_test "Encrypt then MAC: default" \
"$P_SRV debug_level=3 \
force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
"$P_CLI debug_level=3" \
0 \
-c "client hello, adding encrypt_then_mac extension" \
-s "found encrypt then mac extension" \
-s "server hello, adding encrypt then mac extension" \
-c "found encrypt_then_mac extension" \
-c "using encrypt then mac" \
-s "using encrypt then mac"
run_test "Encrypt then MAC: client enabled, server disabled" \
"$P_SRV debug_level=3 etm=0 \
force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
"$P_CLI debug_level=3 etm=1" \
0 \
-c "client hello, adding encrypt_then_mac extension" \
-s "found encrypt then mac extension" \
-S "server hello, adding encrypt then mac extension" \
-C "found encrypt_then_mac extension" \
-C "using encrypt then mac" \
-S "using encrypt then mac"
run_test "Encrypt then MAC: client enabled, aead cipher" \
"$P_SRV debug_level=3 etm=1 \
force_ciphersuite=TLS-RSA-WITH-AES-128-GCM-SHA256" \
"$P_CLI debug_level=3 etm=1" \
0 \
-c "client hello, adding encrypt_then_mac extension" \
-s "found encrypt then mac extension" \
-S "server hello, adding encrypt then mac extension" \
-C "found encrypt_then_mac extension" \
-C "using encrypt then mac" \
-S "using encrypt then mac"
run_test "Encrypt then MAC: client enabled, stream cipher" \
"$P_SRV debug_level=3 etm=1 \
force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
"$P_CLI debug_level=3 etm=1" \
0 \
-c "client hello, adding encrypt_then_mac extension" \
-s "found encrypt then mac extension" \
-S "server hello, adding encrypt then mac extension" \
-C "found encrypt_then_mac extension" \
-C "using encrypt then mac" \
-S "using encrypt then mac"
run_test "Encrypt then MAC: client disabled, server enabled" \
"$P_SRV debug_level=3 etm=1 \
force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
"$P_CLI debug_level=3 etm=0" \
0 \
-C "client hello, adding encrypt_then_mac extension" \
-S "found encrypt then mac extension" \
-S "server hello, adding encrypt then mac extension" \
-C "found encrypt_then_mac extension" \
-C "using encrypt then mac" \
-S "using encrypt then mac"
run_test "Encrypt then MAC: client SSLv3, server enabled" \
"$P_SRV debug_level=3 \
force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
"$P_CLI debug_level=3 force_version=ssl3" \
0 \
-C "client hello, adding encrypt_then_mac extension" \
-S "found encrypt then mac extension" \
-S "server hello, adding encrypt then mac extension" \
-C "found encrypt_then_mac extension" \
-C "using encrypt then mac" \
-S "using encrypt then mac"
run_test "Encrypt then MAC: client enabled, server SSLv3" \
"$P_SRV debug_level=3 force_version=ssl3 \
force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
"$P_CLI debug_level=3" \
0 \
-c "client hello, adding encrypt_then_mac extension" \
-s "found encrypt then mac extension" \
-S "server hello, adding encrypt then mac extension" \
-C "found encrypt_then_mac extension" \
-C "using encrypt then mac" \
-S "using encrypt then mac"
# Tests for Extended Master Secret extension
run_test "Extended Master Secret: default" \
@ -1972,6 +2058,13 @@ run_test "Small packet TLS 1.0 BlockCipher" \
0 \
-s "Read from client: 1 bytes read"
run_test "Small packet TLS 1.0 BlockCipher without EtM" \
"$P_SRV" \
"$P_CLI request_size=1 force_version=tls1 etm=0 \
force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
0 \
-s "Read from client: 1 bytes read"
run_test "Small packet TLS 1.0 BlockCipher truncated MAC" \
"$P_SRV" \
"$P_CLI request_size=1 force_version=tls1 \
@ -1995,6 +2088,13 @@ run_test "Small packet TLS 1.1 BlockCipher" \
0 \
-s "Read from client: 1 bytes read"
run_test "Small packet TLS 1.1 BlockCipher without EtM" \
"$P_SRV" \
"$P_CLI request_size=1 force_version=tls1_1 etm=0 \
force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
0 \
-s "Read from client: 1 bytes read"
run_test "Small packet TLS 1.1 StreamCipher" \
"$P_SRV" \
"$P_CLI request_size=1 force_version=tls1_1 \
@ -2025,6 +2125,13 @@ run_test "Small packet TLS 1.2 BlockCipher" \
0 \
-s "Read from client: 1 bytes read"
run_test "Small packet TLS 1.2 BlockCipher without EtM" \
"$P_SRV" \
"$P_CLI request_size=1 force_version=tls1_2 etm=0 \
force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
0 \
-s "Read from client: 1 bytes read"
run_test "Small packet TLS 1.2 BlockCipher larger MAC" \
"$P_SRV" \
"$P_CLI request_size=1 force_version=tls1_2 force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \