diff --git a/ChangeLog b/ChangeLog index 985c11b51..75f622009 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,6 +28,14 @@ Features which allows copy-less parsing of DER encoded X.509 CRTs, at the cost of additional lifetime constraints on the input buffer, but at the benefit of reduced RAM consumption. + * Add new API function mbedtls_ssl_conf_extended_master_secret_enforce() to + allow enforcing the usage of ExtendedMasterSecret extension. If the + extension is used and this option is enabled, handshakes not leading to + the use of the extended master secret will be aborted. On the server, + fail the handshake if client doesn't advertise the ExtendedMasterSecret + extension. On the client, fail the handshake if the server doesn't + consent to the use of the ExtendedMasterSecret extension in its + ServerHello. API Changes * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`. diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 653f857cc..50668072a 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -158,6 +158,9 @@ #define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 #define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 +#define MBEDTLS_SSL_EXTENDED_MS_ENFORCE_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENFORCE_ENABLED 1 + #define MBEDTLS_SSL_CID_DISABLED 0 #define MBEDTLS_SSL_CID_ENABLED 1 @@ -1031,6 +1034,9 @@ struct mbedtls_ssl_config #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ + unsigned int enforce_extended_master_secret : 1; /*!< enforce the usage + * of extended master + * secret */ #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) unsigned int anti_replay : 1; /*!< detect and prevent replay? */ @@ -2821,6 +2827,26 @@ void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED */ void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); + +/** + * \brief Enable or disable Extended Master Secret enforcing. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENFORCE_DISABLED) + * + * \note If the use of extended master secret is configured (see + * `mbedtls_ssl_conf_extended_master_secret()`) and this + * option is set, handshakes not leading to the use of the + * extended master secret will be aborted: On the server, fail + * the handshake if the client doesn't advertise the + * ExtendedMasterSecret extension. On the client: Fail the + * handshake if the server doesn't consent to the use of the + * ExtendedMasterSecret extension in its ServerHello. + * + * \param conf Currently used SSL configuration struct. + * \param ems_enf MBEDTLS_SSL_EXTENDED_MS_ENFORCE_ENABLED or + * MBEDTLS_SSL_EXTENDED_MS_ENFORCE_DISABLED + */ +void mbedtls_ssl_conf_extended_master_secret_enforce( mbedtls_ssl_config *conf, + char ems_enf ); #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_ARC4_C) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 97aeac4ee..cd9793e46 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2085,6 +2085,21 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_RENEGOTIATION */ + /* + * Check if extended master secret is being enforced + */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && + ssl->conf->enforce_extended_master_secret == + MBEDTLS_SSL_EXTENDED_MS_ENFORCE_ENABLED && + ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Peer not offering extended master " + "secret, while it is enforced") ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + if( handshake_failure == 1 ) { mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, diff --git a/library/ssl_srv.c b/library/ssl_srv.c index a8fd49b6c..d40a21f6f 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -2035,6 +2035,21 @@ read_record_header: } #endif /* MBEDTLS_SSL_RENEGOTIATION */ + /* + * Check if extended master secret is being enforced + */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && + ssl->conf->enforce_extended_master_secret == + MBEDTLS_SSL_EXTENDED_MS_ENFORCE_ENABLED && + ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Peer not offering extended master " + "secret, while it is enforced") ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + if( handshake_failure == 1 ) { mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, diff --git a/library/ssl_tls.c b/library/ssl_tls.c index bab00bb41..ca4ab36f8 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -8413,6 +8413,12 @@ void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems { conf->extended_ms = ems; } + +void mbedtls_ssl_conf_extended_master_secret_enforce( mbedtls_ssl_config *conf, + char ems_enf ) +{ + conf->enforce_extended_master_secret = ems_enf; +} #endif #if defined(MBEDTLS_ARC4_C) @@ -10375,6 +10381,8 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + conf->enforce_extended_master_secret = + MBEDTLS_SSL_EXTENDED_MS_ENFORCE_DISABLED; #endif #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 166578428..bbd4d2555 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -122,6 +122,7 @@ int main( void ) #define DFL_FALLBACK -1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 +#define DFL_EXTENDED_MS_ENFORCE -1 #define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: " #define GET_REQUEST_END "\r\n\r\n" @@ -243,7 +244,8 @@ int main( void ) #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) #define USAGE_EMS \ - " extended_ms=0/1 default: (library default: on)\n" + " extended_ms=0/1 default: (library default: on)\n" \ + " enforce_extended_master_secret=0/1 default: (library default: off)\n" #else #define USAGE_EMS "" #endif @@ -410,6 +412,8 @@ struct options int fallback; /* is this a fallback connection? */ int dgram_packing; /* allow/forbid datagram packing */ int extended_ms; /* negotiate extended master secret? */ + int enforce_extended_master_secret; /* Enforce the usage of extended + * master secret */ int etm; /* negotiate encrypt then mac? */ int cid_enabled; /* whether to use the CID extension or not */ int cid_enabled_renego; /* whether to use the CID extension or not @@ -825,6 +829,7 @@ int main( int argc, char *argv[] ) opt.dtls_mtu = DFL_DTLS_MTU; opt.fallback = DFL_FALLBACK; opt.extended_ms = DFL_EXTENDED_MS; + opt.enforce_extended_master_secret = DFL_EXTENDED_MS_ENFORCE; opt.etm = DFL_ETM; opt.dgram_packing = DFL_DGRAM_PACKING; @@ -1025,6 +1030,21 @@ int main( int argc, char *argv[] ) default: goto usage; } } + else if( strcmp( p, "enforce_extended_master_secret" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: + opt.enforce_extended_master_secret = + MBEDTLS_SSL_EXTENDED_MS_ENFORCE_DISABLED; + break; + case 1: + opt.enforce_extended_master_secret = + MBEDTLS_SSL_EXTENDED_MS_ENFORCE_ENABLED; + break; + default: goto usage; + } + } else if( strcmp( p, "curves" ) == 0 ) opt.curves = q; else if( strcmp( p, "etm" ) == 0 ) @@ -1638,6 +1658,9 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if( opt.extended_ms != DFL_EXTENDED_MS ) mbedtls_ssl_conf_extended_master_secret( &conf, opt.extended_ms ); + if( opt.enforce_extended_master_secret != DFL_EXTENDED_MS_ENFORCE ) + mbedtls_ssl_conf_extended_master_secret_enforce( &conf, + opt.enforce_extended_master_secret ); #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 6d6293adc..b048bc7bd 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -163,6 +163,7 @@ int main( void ) #define DFL_DGRAM_PACKING 1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 +#define DFL_EXTENDED_MS_ENFORCE -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" \ @@ -342,7 +343,8 @@ int main( void ) #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) #define USAGE_EMS \ - " extended_ms=0/1 default: (library default: on)\n" + " extended_ms=0/1 default: (library default: on)\n" \ + " enforce_extended_master_secret=0/1 default: (library default: off)\n" #else #define USAGE_EMS "" #endif @@ -525,6 +527,8 @@ struct options const char *alpn_string; /* ALPN supported protocols */ const char *dhm_file; /* the file with the DH parameters */ int extended_ms; /* allow negotiation of extended MS? */ + int enforce_extended_master_secret; /* Enforce the usage of extended + * master secret */ int etm; /* allow negotiation of encrypt-then-MAC? */ int transport; /* TLS or DTLS? */ int cookies; /* Use cookies for DTLS? -1 to break them */ @@ -1494,6 +1498,7 @@ int main( int argc, char *argv[] ) opt.dgram_packing = DFL_DGRAM_PACKING; opt.badmac_limit = DFL_BADMAC_LIMIT; opt.extended_ms = DFL_EXTENDED_MS; + opt.enforce_extended_master_secret = DFL_EXTENDED_MS_ENFORCE; opt.etm = DFL_ETM; for( i = 1; i < argc; i++ ) @@ -1813,6 +1818,21 @@ int main( int argc, char *argv[] ) default: goto usage; } } + else if( strcmp( p, "enforce_extended_master_secret" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: + opt.enforce_extended_master_secret = + MBEDTLS_SSL_EXTENDED_MS_ENFORCE_DISABLED; + break; + case 1: + opt.enforce_extended_master_secret = + MBEDTLS_SSL_EXTENDED_MS_ENFORCE_ENABLED; + break; + default: goto usage; + } + } else if( strcmp( p, "etm" ) == 0 ) { switch( atoi( q ) ) @@ -2440,6 +2460,9 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if( opt.extended_ms != DFL_EXTENDED_MS ) mbedtls_ssl_conf_extended_master_secret( &conf, opt.extended_ms ); + if( opt.enforce_extended_master_secret != DFL_EXTENDED_MS_ENFORCE ) + mbedtls_ssl_conf_extended_master_secret_enforce( &conf, + opt.enforce_extended_master_secret ); #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index da89642e3..2ba099183 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1763,7 +1763,7 @@ run_test "Encrypt then MAC: client enabled, server SSLv3" \ # Tests for Extended Master Secret extension -run_test "Extended Master Secret: default" \ +run_test "Extended Master Secret: default (not enforcing)" \ "$P_SRV debug_level=3" \ "$P_CLI debug_level=3" \ 0 \ @@ -1774,7 +1774,60 @@ run_test "Extended Master Secret: default" \ -c "session hash for extended master secret" \ -s "session hash for extended master secret" -run_test "Extended Master Secret: client enabled, server disabled" \ +run_test "Extended Master Secret: both enabled, both enforcing" \ + "$P_SRV debug_level=3 enforce_extended_master_secret=1" \ + "$P_CLI debug_level=3 enforce_extended_master_secret=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 "session hash for extended master secret" \ + -s "session hash for extended master secret" + +run_test "Extended Master Secret: both enabled, client enforcing" \ + "$P_SRV debug_level=3 enforce_extended_master_secret=0" \ + "$P_CLI debug_level=3 enforce_extended_master_secret=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 "session hash for extended master secret" \ + -s "session hash for extended master secret" + +run_test "Extended Master Secret: both enabled, server enforcing" \ + "$P_SRV debug_level=3 enforce_extended_master_secret=1" \ + "$P_CLI debug_level=3 enforce_extended_master_secret=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 "session hash for extended master secret" \ + -s "session hash for extended master secret" + +run_test "Extended Master Secret: client enabled, server disabled, client enforcing" \ + "$P_SRV debug_level=3 extended_ms=0" \ + "$P_CLI debug_level=3 extended_ms=1 enforce_extended_master_secret=1" \ + 1 \ + -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 "Peer not offering extended master secret, while it is enforced" + +run_test "Extended Master Secret enforced: client disabled, server enabled, server enforcing" \ + "$P_SRV debug_level=3 extended_ms=1 enforce_extended_master_secret=1" \ + "$P_CLI debug_level=3 extended_ms=0" \ + 1 \ + -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" \ + -s "Peer not offering extended master secret, while it is enforced" + +run_test "Extended Master Secret: client enabled, server disabled, not enforcing" \ "$P_SRV debug_level=3 extended_ms=0" \ "$P_CLI debug_level=3 extended_ms=1" \ 0 \ @@ -1785,7 +1838,7 @@ run_test "Extended Master Secret: client enabled, server disabled" \ -C "session hash for extended master secret" \ -S "session hash for extended master secret" -run_test "Extended Master Secret: client disabled, server enabled" \ +run_test "Extended Master Secret: client disabled, server enabled, not enforcing" \ "$P_SRV debug_level=3 extended_ms=1" \ "$P_CLI debug_level=3 extended_ms=0" \ 0 \ @@ -1796,6 +1849,17 @@ run_test "Extended Master Secret: client disabled, server enabled" \ -C "session hash for extended master secret" \ -S "session hash for extended master secret" +run_test "Extended Master Secret: client disabled, server disabled" \ + "$P_SRV debug_level=3 extended_ms=0" \ + "$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 "session hash for extended master secret" \ + -S "session hash for extended master secret" + requires_config_enabled MBEDTLS_SSL_PROTO_SSL3 run_test "Extended Master Secret: client SSLv3, server enabled" \ "$P_SRV debug_level=3 min_version=ssl3" \