From 699cafaea27c72ea68aa85bd8a4e18afb879e272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 27 Oct 2014 13:57:03 +0100 Subject: [PATCH 1/9] Implement initial negotiation of EtM Not implemented yet: - actually using EtM - conditions on renegotiation --- include/polarssl/check_config.h | 7 ++++ include/polarssl/config.h | 18 ++++++++++ include/polarssl/ssl.h | 26 ++++++++++++++ library/ssl_cli.c | 64 +++++++++++++++++++++++++++++++++ library/ssl_srv.c | 64 +++++++++++++++++++++++++++++++++ library/ssl_tls.c | 20 +++++++++++ programs/ssl/ssl_client2.c | 25 +++++++++++++ programs/ssl/ssl_server2.c | 25 +++++++++++++ tests/ssl-opt.sh | 61 +++++++++++++++++++++++++++++-- 9 files changed, 308 insertions(+), 2 deletions(-) diff --git a/include/polarssl/check_config.h b/include/polarssl/check_config.h index b4ae54144..80b037eb2 100644 --- a/include/polarssl/check_config.h +++ b/include/polarssl/check_config.h @@ -257,6 +257,13 @@ #error "Illegal protocol selection" #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) && \ diff --git a/include/polarssl/config.h b/include/polarssl/config.h index dfe2764e5..6e736e2b7 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -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 diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 7b5ec8e6e..82ed04e11 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -212,6 +212,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 @@ -409,6 +412,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 @@ -548,6 +552,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 }; /* @@ -713,6 +721,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 @@ -1425,6 +1436,21 @@ void 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. diff --git a/library/ssl_cli.c b/library/ssl_cli.c index c40d62ec0..fd0a81165 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -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 ) @@ -688,6 +714,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; @@ -811,6 +842,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, @@ -1203,6 +1254,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" ) ); diff --git a/library/ssl_srv.c b/library/ssl_srv.c index ad67c2215..c884e7cc4 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -635,6 +635,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, @@ -1523,6 +1546,16 @@ static int ssl_parse_client_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" ) ); + + 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" ) ); @@ -1682,6 +1715,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->session_negotiate->encrypt_then_mac == SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == SSL_MINOR_VERSION_0 ) + { + *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, @@ -2012,6 +2071,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; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index c8b7fa2a9..e8f2b7fd4 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1071,6 +1071,15 @@ static int ssl_encrypt_buf( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); +#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) + if( ssl->session_out != NULL && + ssl->session_out->encrypt_then_mac == SSL_ETM_ENABLED ) + { + // WIP + SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + } +#endif + /* * Add MAC before encrypt, except for AEAD modes */ @@ -3474,6 +3483,10 @@ int ssl_init( ssl_context *ssl ) memset( ssl-> in_ctr, 0, SSL_BUFFER_LEN ); memset( ssl->out_ctr, 0, SSL_BUFFER_LEN ); +#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 @@ -4025,6 +4038,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 ) { diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index d4cde0f14..444322bf4 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -97,6 +97,7 @@ int main( int argc, char *argv[] ) #define DFL_ALPN_STRING NULL #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" @@ -136,6 +137,7 @@ struct options const char *alpn_string; /* ALPN supported protocols */ 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 ) @@ -302,6 +304,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" \ @@ -333,6 +342,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" \ @@ -435,6 +445,7 @@ int main( int argc, char *argv[] ) opt.alpn_string = DFL_ALPN_STRING; opt.fallback = DFL_FALLBACK; opt.extended_ms = DFL_EXTENDED_MS; + opt.etm = DFL_ETM; for( i = 1; i < argc; i++ ) { @@ -559,6 +570,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 ) @@ -927,6 +947,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 ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 35a156bdf..08f2ff864 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -117,6 +117,7 @@ int main( int argc, char *argv[] ) #define DFL_ALPN_STRING NULL #define DFL_DHM_FILE NULL #define DFL_EXTENDED_MS -1 +#define DFL_ETM -1 #define LONG_RESPONSE "

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" \ @@ -178,6 +179,7 @@ struct options const char *alpn_string; /* ALPN supported protocols */ const char *dhm_file; /* the file with the DH parameters */ 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 ) @@ -308,6 +310,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" \ @@ -334,6 +343,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" \ @@ -724,6 +734,7 @@ int main( int argc, char *argv[] ) opt.alpn_string = DFL_ALPN_STRING; opt.dhm_file = DFL_DHM_FILE; opt.extended_ms = DFL_EXTENDED_MS; + opt.etm = DFL_ETM; for( i = 1; i < argc; i++ ) { @@ -900,6 +911,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 ); @@ -1282,6 +1302,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 ) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 38bc89b7a..6db8571ff 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -247,14 +247,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 @@ -440,6 +440,63 @@ 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" \ + "$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" \ + "$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" \ + "$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" \ + "$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" \ + "$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" \ From 0098e7dc70f9009570b3318209caef94ff31bff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 28 Oct 2014 13:08:59 +0100 Subject: [PATCH 2/9] Preparation for EtM --- library/ssl_tls.c | 59 ++++++++++++++++++++++++++++++++++++++--------- tests/ssl-opt.sh | 15 ++++++++---- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index e8f2b7fd4..5ffb35ef7 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1060,6 +1060,41 @@ 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 + + return( MAC_NONE ); +} + /* * Encryption/decryption functions */ @@ -1068,26 +1103,20 @@ static int ssl_encrypt_buf( ssl_context *ssl ) size_t i; const cipher_mode_t mode = cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); + char mac_order; SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); -#if defined(POLARSSL_SSL_ENCRYPT_THEN_MAC) - if( ssl->session_out != NULL && - ssl->session_out->encrypt_then_mac == SSL_ETM_ENABLED ) - { - // WIP - SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); - } -#endif + 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 + || mac_order == MAC_CIPHERTEXT ) // WIP! { #if defined(POLARSSL_SSL_PROTO_SSL3) if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) @@ -1358,6 +1387,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" ) ); @@ -1368,6 +1398,9 @@ 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 ); + (void) mac_order; // WIP + #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) if( mode == POLARSSL_MODE_STREAM ) { @@ -1763,6 +1796,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 diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 6db8571ff..100c24459 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -443,7 +443,8 @@ run_test "Truncated HMAC: actual test" \ # Tests for Encrypt-then-MAC extension run_test "Encrypt then MAC: default" \ - "$P_SRV debug_level=3" \ + "$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" \ @@ -454,7 +455,8 @@ run_test "Encrypt then MAC: default" \ -s "using encrypt then mac" run_test "Encrypt then MAC: client enabled, server disabled" \ - "$P_SRV debug_level=3 etm=0" \ + "$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" \ @@ -465,7 +467,8 @@ run_test "Encrypt then MAC: client enabled, server disabled" \ -S "using encrypt then mac" run_test "Encrypt then MAC: client disabled, server enabled" \ - "$P_SRV debug_level=3 etm=1" \ + "$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" \ @@ -476,7 +479,8 @@ run_test "Encrypt then MAC: client disabled, server enabled" \ -S "using encrypt then mac" run_test "Encrypt then MAC: client SSLv3, server enabled" \ - "$P_SRV debug_level=3" \ + "$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" \ @@ -487,7 +491,8 @@ run_test "Encrypt then MAC: client SSLv3, server enabled" \ -S "using encrypt then mac" run_test "Encrypt then MAC: client enabled, server SSLv3" \ - "$P_SRV debug_level=3 force_version=ssl3" \ + "$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" \ From 313d796e80d034869d66b19057b327a57b3075e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 29 Oct 2014 12:07:57 +0100 Subject: [PATCH 3/9] Implement EtM --- library/ssl_tls.c | 98 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5ffb35ef7..f63550555 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1115,8 +1115,7 @@ static int ssl_encrypt_buf( ssl_context *ssl ) #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) || \ ( defined(POLARSSL_CIPHER_MODE_CBC) && \ ( defined(POLARSSL_AES_C) || defined(POLARSSL_CAMELLIA_C) ) ) - if( mac_order == MAC_PLAINTEXT - || mac_order == MAC_CIPHERTEXT ) // WIP! + if( mac_order == MAC_PLAINTEXT ) { #if defined(POLARSSL_SSL_PROTO_SSL3) if( ssl->minor_ver == SSL_MINOR_VERSION_0 ) @@ -1350,6 +1349,36 @@ 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 + + * TLSCipherText.length + + * IV + // except for TLS 1.0 + * ENC(content + padding + padding_length)); + */ + size_t final_len = ssl->out_msglen + ssl->transform_out->maclen; + 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)( ( final_len >> 8 ) & 0xFF ); + pseudo_hdr[12] = (unsigned char)( ( final_len ) & 0xFF ); + + 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 && @@ -1399,7 +1428,6 @@ static int ssl_decrypt_buf( ssl_context *ssl ) } mac_order = ssl_get_mac_order( ssl, ssl->session_in, mode ); - (void) mac_order; // WIP #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) if( mode == POLARSSL_MODE_STREAM ) @@ -1516,13 +1544,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; @@ -1542,6 +1563,50 @@ 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]; + + dec_msglen -= ssl->transform_in->maclen; + ssl->in_msglen -= ssl->transform_in->maclen; + + // TODO: adjust for DTLS + md_hmac_update( &ssl->transform_in->md_ctx_dec, + ssl->in_ctr, 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 @@ -1586,7 +1651,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)", @@ -1660,6 +1726,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 && @@ -1673,17 +1741,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_hdr[3] = (unsigned char)( ssl->in_msglen >> 8 ); ssl->in_hdr[4] = (unsigned char)( ssl->in_msglen ); From 08558e5b46c4f7f642fb82c4f50e2ee32f9f0d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 4 Nov 2014 14:40:21 +0100 Subject: [PATCH 4/9] Fix for the RFC erratum --- library/ssl_tls.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index f63550555..4132e47aa 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1357,17 +1357,18 @@ static int ssl_encrypt_buf( ssl_context *ssl ) * MAC(MAC_write_key, seq_num + * TLSCipherText.type + * TLSCipherText.version + - * TLSCipherText.length + + * length_of( (IV +) ENC(...) ) + * IV + // except for TLS 1.0 * ENC(content + padding + padding_length)); */ - size_t final_len = ssl->out_msglen + ssl->transform_out->maclen; 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)( ( final_len >> 8 ) & 0xFF ); - pseudo_hdr[12] = (unsigned char)( ( final_len ) & 0xFF ); + 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, @@ -1570,13 +1571,19 @@ static int ssl_decrypt_buf( ssl_context *ssl ) 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; - // TODO: adjust for DTLS - md_hmac_update( &ssl->transform_in->md_ctx_dec, - ssl->in_ctr, 13 ); + 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 ); From 78e745fc0a5ab2895946f9b5ba5e268558908541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 4 Nov 2014 15:44:06 +0100 Subject: [PATCH 5/9] Don't send back EtM extension if not using CBC --- library/ssl_srv.c | 17 +++++++++++++++++ tests/ssl-opt.sh | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index c884e7cc4..6d8626cc2 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -1721,6 +1721,8 @@ static void ssl_write_encrypt_then_mac_ext( ssl_context *ssl, 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 ) @@ -1729,6 +1731,21 @@ static void ssl_write_encrypt_then_mac_ext( ssl_context *ssl, 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 ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 100c24459..26b2f897c 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -466,6 +466,30 @@ run_test "Encrypt then MAC: client enabled, server disabled" \ -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" \ From 169dd6a514142902665f5f9890f338bb251d2a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 4 Nov 2014 16:15:39 +0100 Subject: [PATCH 6/9] Adjust minimum length for EtM --- library/ssl_tls.c | 21 ++++++++++++++++----- tests/ssl-opt.sh | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 4132e47aa..8c981cf36 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -601,12 +601,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 || diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 26b2f897c..1349737f9 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1864,6 +1864,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 \ @@ -1887,6 +1894,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 \ @@ -1917,6 +1931,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" \ From 1a03473576f150468c6b2e4ff206db5bb14b1c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 4 Nov 2014 17:36:18 +0100 Subject: [PATCH 7/9] Keep EtM state across renegotiations --- library/ssl_tls.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 8c981cf36..b608e5c98 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3248,6 +3248,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 ); } From c122ae76122f9817770115159de8f48fc3949fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 4 Nov 2014 18:27:16 +0100 Subject: [PATCH 8/9] Update Changelog for EtM --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e3774d413..89c87e057 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,11 +2,12 @@ PolarSSL ChangeLog (Sorted per branch, date) = 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 From 9d7821d774ebeb4256463f08abfb93910a376ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 6 Nov 2014 01:19:52 +0100 Subject: [PATCH 9/9] Fix warning in reduced config --- library/ssl_tls.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b608e5c98..6462ad0bd 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1103,6 +1103,11 @@ static char ssl_get_mac_order( ssl_context *ssl, } #endif + /* Unused if AEAD is the only option */ + ((void) ssl); + ((void) session); + ((void) mode); + return( MAC_NONE ); }