From 367381fdddb68e72c408fed763b955f620abf451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Oct 2014 18:40:56 +0200 Subject: [PATCH 1/7] Add negotiation of Extended Master Secret (But not the actual thing yet.) --- include/polarssl/config.h | 14 +++++++++ include/polarssl/ssl.h | 26 ++++++++++++++++ library/ssl_cli.c | 62 ++++++++++++++++++++++++++++++++++++++ library/ssl_srv.c | 61 +++++++++++++++++++++++++++++++++++++ library/ssl_tls.c | 16 ++++++++++ programs/ssl/ssl_client2.c | 25 +++++++++++++++ programs/ssl/ssl_server2.c | 25 +++++++++++++++ tests/ssl-opt.sh | 35 +++++++++++++++++++++ 8 files changed, 264 insertions(+) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index ff0ccecbd..9ca39e71d 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -811,6 +811,20 @@ */ //#define POLARSSL_SSL_DEBUG_ALL +/** \def POLARSSL_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define POLARSSL_SSL_EXTENDED_MASTER_SECRET + /** * \def POLARSSL_SSL_FALLBACK_SCSV * diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 875709c7b..7b5ec8e6e 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -209,6 +209,9 @@ #define SSL_IS_NOT_FALLBACK 0 #define SSL_IS_FALLBACK 1 +#define SSL_EXTENDED_MS_DISABLED 0 +#define SSL_EXTENDED_MS_ENABLED 1 + #define SSL_COMPRESS_NULL 0 #define SSL_COMPRESS_DEFLATE 1 @@ -406,6 +409,8 @@ #define TLS_EXT_ALPN 16 +#define TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + #define TLS_EXT_SESSION_TICKET 35 #define TLS_EXT_RENEGOTIATION_INFO 0xFF01 @@ -657,6 +662,9 @@ struct _ssl_handshake_params #if defined(POLARSSL_SSL_SESSION_TICKETS) int new_session_ticket; /*!< use NewSessionTicket? */ #endif /* POLARSSL_SSL_SESSION_TICKETS */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + int extended_ms; /*!< use Extended Master Secret? */ +#endif }; #if defined(POLARSSL_SSL_SESSION_TICKETS) @@ -705,6 +713,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_EXTENDED_MASTER_SECRET) + char extended_ms; /*!< flag for extended master secret */ +#endif /* * Callbacks (RNG, debug, I/O, verification) @@ -1414,6 +1425,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_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param ssl SSL context + * \param ems SSL_EXTENDED_MS_ENABLED or SSL_EXTENDED_MS_DISABLED + */ +void ssl_set_extended_master_secret( ssl_context *ssl, char ems ); +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + #if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Set the maximum fragment length to emit and/or negotiate diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 50ab05f2c..065f3a83a 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -359,6 +359,31 @@ static void ssl_write_truncated_hmac_ext( ssl_context *ssl, } #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " + "extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + #if defined(POLARSSL_SSL_SESSION_TICKETS) static void ssl_write_session_ticket_ext( ssl_context *ssl, unsigned char *buf, size_t *olen ) @@ -662,6 +687,11 @@ static int ssl_write_client_hello( ssl_context *ssl ) 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; +#endif + #if defined(POLARSSL_SSL_SESSION_TICKETS) ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; @@ -780,6 +810,25 @@ static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, } #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED || + len != 0 ) + { + return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->extended_ms = SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + #if defined(POLARSSL_SSL_SESSION_TICKETS) static int ssl_parse_session_ticket_ext( ssl_context *ssl, const unsigned char *buf, @@ -1152,6 +1201,19 @@ static int ssl_parse_server_hello( ssl_context *ssl ) break; #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + case TLS_EXT_EXTENDED_MASTER_SECRET: + SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) ); + + if( ( ret = ssl_parse_extended_ms_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + #if defined(POLARSSL_SSL_SESSION_TICKETS) case TLS_EXT_SESSION_TICKET: SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 57b0ecf30..f65338edc 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -635,6 +635,26 @@ static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, } #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_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->extended_ms == SSL_EXTENDED_MS_ENABLED ) + ssl->handshake->extended_ms = SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + #if defined(POLARSSL_SSL_SESSION_TICKETS) static int ssl_parse_session_ticket_ext( ssl_context *ssl, unsigned char *buf, @@ -1500,6 +1520,16 @@ static int ssl_parse_client_hello( ssl_context *ssl ) break; #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + case TLS_EXT_EXTENDED_MASTER_SECRET: + SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + #if defined(POLARSSL_SSL_SESSION_TICKETS) case TLS_EXT_SESSION_TICKET: SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); @@ -1649,6 +1679,32 @@ static void ssl_write_truncated_hmac_ext( ssl_context *ssl, } #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_DISABLED ) + { + *olen = 0; + return; + } + + SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* POLARSSL_SSL_EXTENDED_MASTER_SECRET */ + #if defined(POLARSSL_SSL_SESSION_TICKETS) static void ssl_write_session_ticket_ext( ssl_context *ssl, unsigned char *buf, @@ -1952,6 +2008,11 @@ static int ssl_write_server_hello( ssl_context *ssl ) 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; +#endif + #if defined(POLARSSL_SSL_SESSION_TICKETS) ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index bd4494f55..1fe3a95ca 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -470,6 +470,11 @@ int ssl_derive_keys( ssl_context *ssl ) SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, handshake->pmslen ); +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_ENABLED ) + SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + // XXX to be continued, WIP +#endif handshake->tls_prf( handshake->premaster, handshake->pmslen, "master secret", handshake->randbytes, 64, session->master, 48 ); @@ -3437,6 +3442,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_EXTENDED_MASTER_SECRET) + ssl->extended_ms = SSL_EXTENDED_MS_ENABLED; +#endif + #if defined(POLARSSL_SSL_SESSION_TICKETS) ssl->ticket_lifetime = SSL_DEFAULT_TICKET_LIFETIME; #endif @@ -3984,6 +3993,13 @@ void ssl_set_fallback( ssl_context *ssl, char fallback ) } #endif +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +void ssl_set_extended_master_secret( ssl_context *ssl, char ems ) +{ + ssl->extended_ms = ems; +} +#endif + #if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH) int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ) { diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 8ca83ebe3..d4cde0f14 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -96,6 +96,7 @@ int main( int argc, char *argv[] ) #define DFL_TICKETS SSL_SESSION_TICKETS_ENABLED #define DFL_ALPN_STRING NULL #define DFL_FALLBACK -1 +#define DFL_EXTENDED_MS -1 #define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: " #define GET_REQUEST_END "\r\n\r\n" @@ -134,6 +135,7 @@ struct options int tickets; /* enable / disable session tickets */ const char *alpn_string; /* ALPN supported protocols */ int fallback; /* is this a fallback connection? */ + char extended_ms; /* negotiate extended master secret? */ } opt; static void my_debug( void *ctx, int level, const char *str ) @@ -293,6 +295,13 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags ) #define USAGE_FALLBACK "" #endif +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +#define USAGE_EMS \ + " extended_ms=0/1 default: (library default: on)\n" +#else +#define USAGE_EMS "" +#endif + #define USAGE \ "\n usage: ssl_client2 param=<>...\n" \ "\n acceptable parameters:\n" \ @@ -323,6 +332,7 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags ) USAGE_TRUNC_HMAC \ USAGE_ALPN \ USAGE_FALLBACK \ + USAGE_EMS \ "\n" \ " min_version=%%s default: \"\" (ssl3)\n" \ " max_version=%%s default: \"\" (tls1_2)\n" \ @@ -424,6 +434,7 @@ int main( int argc, char *argv[] ) opt.tickets = DFL_TICKETS; opt.alpn_string = DFL_ALPN_STRING; opt.fallback = DFL_FALLBACK; + opt.extended_ms = DFL_EXTENDED_MS; for( i = 1; i < argc; i++ ) { @@ -539,6 +550,15 @@ int main( int argc, char *argv[] ) default: goto usage; } } + else if( strcmp( p, "extended_ms" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.extended_ms = SSL_EXTENDED_MS_DISABLED; break; + case 1: opt.extended_ms = SSL_EXTENDED_MS_ENABLED; break; + default: goto usage; + } + } else if( strcmp( p, "min_version" ) == 0 ) { if( strcmp( q, "ssl3" ) == 0 ) @@ -902,6 +922,11 @@ int main( int argc, char *argv[] ) } #endif +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + if( opt.extended_ms != DFL_EXTENDED_MS ) + ssl_set_extended_master_secret( &ssl, opt.extended_ms ); +#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 721dab42e..35a156bdf 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -116,6 +116,7 @@ int main( int argc, char *argv[] ) #define DFL_SNI NULL #define DFL_ALPN_STRING NULL #define DFL_DHM_FILE NULL +#define DFL_EXTENDED_MS -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" \ @@ -176,6 +177,7 @@ struct options char *sni; /* string describing sni information */ 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? */ } opt; static void my_debug( void *ctx, int level, const char *str ) @@ -299,6 +301,13 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len ) #define USAGE_ALPN "" #endif /* POLARSSL_SSL_ALPN */ +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) +#define USAGE_EMS \ + " extended_ms=0/1 default: (library default: on)\n" +#else +#define USAGE_EMS "" +#endif + #define USAGE \ "\n usage: ssl_server2 param=<>...\n" \ "\n acceptable parameters:\n" \ @@ -324,6 +333,7 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len ) USAGE_CACHE \ USAGE_MAX_FRAG_LEN \ USAGE_ALPN \ + USAGE_EMS \ "\n" \ " min_version=%%s default: \"ssl3\"\n" \ " max_version=%%s default: \"tls1_2\"\n" \ @@ -713,6 +723,7 @@ int main( int argc, char *argv[] ) opt.sni = DFL_SNI; opt.alpn_string = DFL_ALPN_STRING; opt.dhm_file = DFL_DHM_FILE; + opt.extended_ms = DFL_EXTENDED_MS; for( i = 1; i < argc; i++ ) { @@ -880,6 +891,15 @@ int main( int argc, char *argv[] ) { opt.alpn_string = q; } + else if( strcmp( p, "extended_ms" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.extended_ms = SSL_EXTENDED_MS_DISABLED; break; + case 1: opt.extended_ms = SSL_EXTENDED_MS_ENABLED; break; + default: goto usage; + } + } else if( strcmp( p, "tickets" ) == 0 ) { opt.tickets = atoi( q ); @@ -1257,6 +1277,11 @@ int main( int argc, char *argv[] ) }; #endif +#if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) + if( opt.extended_ms != DFL_EXTENDED_MS ) + ssl_set_extended_master_secret( &ssl, opt.extended_ms ); +#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 b0dcad95f..eeac11bc8 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -440,6 +440,41 @@ run_test "Truncated HMAC: actual test" \ 0 \ -s "dumping 'computed mac' (10 bytes)" +# Tests for Extended Master Secret extension + +run_test "Extended Master Secret: default" \ + "$P_SRV debug_level=3" \ + "$P_CLI debug_level=3" \ + 0 \ + -c "client hello, adding extended_master_secret extension" \ + -s "found extended master secret extension" \ + -s "server hello, adding extended master secret extension" \ + -c "found extended_master_secret extension" \ + -c "using extended master secret" \ + -s "using extended master secret" + +run_test "Extended Master Secret: client enabled, server disabled" \ + "$P_SRV debug_level=3 extended_ms=0" \ + "$P_CLI debug_level=3 extended_ms=1" \ + 0 \ + -c "client hello, adding extended_master_secret extension" \ + -s "found extended master secret extension" \ + -S "server hello, adding extended master secret extension" \ + -C "found extended_master_secret extension" \ + -C "using extended master secret" \ + -S "using extended master secret" + +run_test "Extended Master Secret: client disabled, server enabled" \ + "$P_SRV debug_level=3 extended_ms=1" \ + "$P_CLI debug_level=3 extended_ms=0" \ + 0 \ + -C "client hello, adding extended_master_secret extension" \ + -S "found extended master secret extension" \ + -S "server hello, adding extended master secret extension" \ + -C "found extended_master_secret extension" \ + -C "using extended master secret" \ + -S "using extended master secret" + # Tests for FALLBACK_SCSV run_test "Fallback SCSV: default" \ From ada303048534d90c23e711d9ec5cacf606400195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Oct 2014 20:33:10 +0200 Subject: [PATCH 2/7] Implement extended master secret --- library/ssl_cli.c | 19 +++++++++++++------ library/ssl_tls.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 065f3a83a..d7b16b855 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2326,12 +2326,6 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); } - if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) - { - SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); - return( ret ); - } - ssl->out_msglen = i + n; ssl->out_msgtype = SSL_MSG_HANDSHAKE; ssl->out_msg[0] = SSL_HS_CLIENT_KEY_EXCHANGE; @@ -2356,9 +2350,16 @@ static int ssl_write_client_key_exchange( ssl_context *ssl ) static int ssl_write_certificate_verify( ssl_context *ssl ) { const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + int ret; SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || @@ -2385,6 +2386,12 @@ static int ssl_write_certificate_verify( ssl_context *ssl ) SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + if( ( ret = ssl_derive_keys( ssl ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "ssl_derive_keys", ret ); + return( ret ); + } + if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK || diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 1fe3a95ca..c8b7fa2a9 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -472,13 +472,45 @@ int ssl_derive_keys( ssl_context *ssl ) #if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_ENABLED ) + { + unsigned char session_hash[48]; + size_t hash_len; + SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); - // XXX to be continued, WIP + + ssl->handshake->calc_verify( ssl, session_hash ); + +#if defined(POLARSSL_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == SSL_MINOR_VERSION_3 ) + { +#if defined(POLARSSL_SHA512_C) + if( ssl->transform_negotiate->ciphersuite_info->mac == + POLARSSL_MD_SHA384 ) + { + hash_len = 48; + } + else +#endif + hash_len = 32; + } + else +#endif /* POLARSSL_SSL_PROTO_TLS1_2 */ + hash_len = 36; + + SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); + + handshake->tls_prf( handshake->premaster, handshake->pmslen, + "extended master secret", + session_hash, hash_len, session->master, 48 ); + + } + else #endif handshake->tls_prf( handshake->premaster, handshake->pmslen, "master secret", handshake->randbytes, 64, session->master, 48 ); + polarssl_zeroize( handshake->premaster, sizeof(handshake->premaster) ); } else From 85a4178f827bd0020f25f07c56a83956a9070bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 Oct 2014 12:47:26 +0200 Subject: [PATCH 3/7] compat.sh: make options a bit more robust --- tests/compat.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/compat.sh b/tests/compat.sh index 861d20e10..b020f3643 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -102,6 +102,10 @@ get_options() { esac shift done + + # sanitize some options (modes checked later) + VERIFIES="$( echo $VERIFIES | tr [a-z] [A-Z] )" + TYPES="$( echo $TYPES | tr [a-z] [A-Z] )" } log() { From dd4592774b9f40e8068f5620ca4a801840307e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 Oct 2014 12:57:37 +0200 Subject: [PATCH 4/7] compat.sh: allow git version of gnutls --- tests/compat.sh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/compat.sh b/tests/compat.sh index b020f3643..390445eb6 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -26,14 +26,19 @@ SRVMEM=0 # do we have a recent enough GnuTLS? if ( which $GNUTLS_CLI && which $GNUTLS_SERV ) >/dev/null; then - eval $( $GNUTLS_CLI --version | head -n1 | sed 's/.* \([0-9]*\)\.\([0-9]\)*\.\([0-9]*\)$/MAJOR="\1" MINOR="\2" PATCH="\3"/' ) - if [ $MAJOR -lt 3 -o \ - \( $MAJOR -eq 3 -a $MINOR -lt 2 \) -o \ - \( $MAJOR -eq 3 -a $MINOR -eq 2 -a $PATCH -lt 15 \) ] - then - PEER_GNUTLS="" - else + G_VER="$( $GNUTLS_CLI --version | head -n1 )" + if echo "$G_VER" | grep '@VERSION@' > /dev/null; then # git version PEER_GNUTLS=" GnuTLS" + else + eval $( echo $G_VER | sed 's/.* \([0-9]*\)\.\([0-9]\)*\.\([0-9]*\)$/MAJOR="\1" MINOR="\2" PATCH="\3"/' ) + if [ $MAJOR -lt 3 -o \ + \( $MAJOR -eq 3 -a $MINOR -lt 2 \) -o \ + \( $MAJOR -eq 3 -a $MINOR -eq 2 -a $PATCH -lt 15 \) ] + then + PEER_GNUTLS="" + else + PEER_GNUTLS=" GnuTLS" + fi fi else PEER_GNUTLS="" From b575b54cb9fc211b5fc03bff36d62fa138ca9d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 Oct 2014 15:12:31 +0200 Subject: [PATCH 5/7] Forbid extended master secret with SSLv3 --- library/ssl_cli.c | 4 +++- library/ssl_srv.c | 8 ++++++-- tests/ssl-opt.sh | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index d7b16b855..c40d62ec0 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -365,7 +365,8 @@ static void ssl_write_extended_ms_ext( ssl_context *ssl, { unsigned char *p = buf; - if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED ) + if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED || + ssl->max_minor_ver == SSL_MINOR_VERSION_0 ) { *olen = 0; return; @@ -816,6 +817,7 @@ static int ssl_parse_extended_ms_ext( ssl_context *ssl, size_t len ) { if( ssl->extended_ms == SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == SSL_MINOR_VERSION_0 || len != 0 ) { return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); diff --git a/library/ssl_srv.c b/library/ssl_srv.c index f65338edc..ad67c2215 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -648,8 +648,11 @@ static int ssl_parse_extended_ms_ext( ssl_context *ssl, ((void) buf); - if( ssl->extended_ms == SSL_EXTENDED_MS_ENABLED ) + if( ssl->extended_ms == SSL_EXTENDED_MS_ENABLED && + ssl->minor_ver != SSL_MINOR_VERSION_0 ) + { ssl->handshake->extended_ms = SSL_EXTENDED_MS_ENABLED; + } return( 0 ); } @@ -1686,7 +1689,8 @@ static void ssl_write_extended_ms_ext( ssl_context *ssl, { unsigned char *p = buf; - if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_DISABLED ) + if( ssl->handshake->extended_ms == SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == SSL_MINOR_VERSION_0 ) { *olen = 0; return; diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index eeac11bc8..38bc89b7a 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -475,6 +475,28 @@ run_test "Extended Master Secret: client disabled, server enabled" \ -C "using extended master secret" \ -S "using extended master secret" +run_test "Extended Master Secret: client SSLv3, server enabled" \ + "$P_SRV debug_level=3" \ + "$P_CLI debug_level=3 force_version=ssl3" \ + 0 \ + -C "client hello, adding extended_master_secret extension" \ + -S "found extended master secret extension" \ + -S "server hello, adding extended master secret extension" \ + -C "found extended_master_secret extension" \ + -C "using extended master secret" \ + -S "using extended master secret" + +run_test "Extended Master Secret: client enabled, server SSLv3" \ + "$P_SRV debug_level=3 force_version=ssl3" \ + "$P_CLI debug_level=3" \ + 0 \ + -c "client hello, adding extended_master_secret extension" \ + -s "found extended master secret extension" \ + -S "server hello, adding extended master secret extension" \ + -C "found extended_master_secret extension" \ + -C "using extended master secret" \ + -S "using extended master secret" + # Tests for FALLBACK_SCSV run_test "Fallback SCSV: default" \ From 769c6b63511e85e914dca9e55ad5640c3ccaa23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 28 Oct 2014 14:13:55 +0100 Subject: [PATCH 6/7] Make session-hash depend on TLS versions --- include/polarssl/check_config.h | 7 +++++++ include/polarssl/config.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/include/polarssl/check_config.h b/include/polarssl/check_config.h index 328b881ea..b4ae54144 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_EXTENDED_MASTER_SECRET) && \ + !defined(POLARSSL_SSL_PROTO_TLS1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_1) && \ + !defined(POLARSSL_SSL_PROTO_TLS1_2) +#error "POLARSSL_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + #if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \ ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) || \ !defined(POLARSSL_CIPHER_MODE_CBC) ) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 9ca39e71d..dfe2764e5 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -821,6 +821,10 @@ * renegotiation), since it actually fixes a more fundamental issue in the * original SSL/TLS design, and has implications beyond Triple Handshake. * + * Requires: POLARSSL_SSL_PROTO_TLS1 or + * POLARSSL_SSL_PROTO_TLS1_1 or + * POLARSSL_SSL_PROTO_TLS1_2 + * * Comment this macro to disable support for Extended Master Secret. */ #define POLARSSL_SSL_EXTENDED_MASTER_SECRET From b3c6a97b31eebbd8867f1ee99e54d34fb9028d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 4 Nov 2014 18:24:04 +0100 Subject: [PATCH 7/7] Update Changelog for session-hash --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 900361a88..e3774d413 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,10 +2,11 @@ PolarSSL ChangeLog (Sorted per branch, date) = 1.3 branch -Reminder: bump SONAME for ABI change (FALLBACK_SCSV) +Reminder: bump SONAME for ABI change (FALLBACK_SCSV, session-hash) Features * Add support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv) + * Add support for Extended Master Secret (draft-ietf-tls-session-hash) = PolarSSL 1.3.9 released 2014-10-20 Security