Add option to disable Extended Master Secret

Add SSL_OP64_NO_EXTENDED_MASTER_SECRET, that can be set on either
an SSL or an SSL_CTX. When processing a ClientHello, if this flag
is set, do not indicate that the EMS TLS extension was received in
either the ssl3 object or the SSL_SESSION.  Retain most of the
sanity checks between the previous and current session during
session resumption, but weaken the check when the current SSL
object is configured to not use EMS.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3910)
This commit is contained in:
Todd Short 2017-07-10 13:28:35 -04:00 committed by Matt Caswell
parent 9fc8f18f59
commit 088dfa1335
12 changed files with 411 additions and 14 deletions

View File

@ -486,6 +486,10 @@ specification. Some applications may be able to mitigate the replay risks in
other ways and in such cases the built-in OpenSSL functionality is not required.
Disabling anti-replay is equivalent to setting B<SSL_OP_NO_ANTI_REPLAY>.
B<ExtendedMasterSecret>: use extended master secret extension, enabled by
default. Inverse of B<SSL_OP_NO_EXTENDED_MASTER_SECRET>: that is,
B<-ExtendedMasterSecret> is the same as setting B<SSL_OP_NO_EXTENDED_MASTER_SECRET>.
=item B<VerifyMode>
The B<value> argument is a comma separated list of flags to set.

View File

@ -198,6 +198,14 @@ RFC7366 Encrypt-then-MAC option on TLS and DTLS connection.
If this option is set, Encrypt-then-MAC is disabled. Clients will not
propose, and servers will not accept the extension.
=item SSL_OP_NO_EXTENDED_MASTER_SECRET
Normally clients and servers will transparently attempt to negotiate the
RFC7627 Extended Master Secret option on TLS and DTLS connection.
If this option is set, Extended Master Secret is disabled. Clients will
not propose, and servers will not accept the extension.
=item SSL_OP_NO_RENEGOTIATION
Disable all renegotiation in TLSv1.2 and earlier. Do not send HelloRequest
@ -366,9 +374,11 @@ OpenSSL 0.9.8m.
The B<SSL_OP_PRIORITIZE_CHACHA> and B<SSL_OP_NO_RENEGOTIATION> options
were added in OpenSSL 1.1.1.
The B<SSL_OP_NO_EXTENDED_MASTER_SECRET> option was added in OpenSSL 3.0.0.
=head1 COPYRIGHT
Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy

View File

@ -297,23 +297,26 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);
/*
* Some values are reserved until OpenSSL 1.2.0 because they were previously
* Some values are reserved until OpenSSL 3.0.0 because they were previously
* included in SSL_OP_ALL in a 1.1.x release.
*
* Reserved value (until OpenSSL 1.2.0) 0x00000001U
* Reserved value (until OpenSSL 1.2.0) 0x00000002U
*/
/* Disable Extended master secret */
# define SSL_OP_NO_EXTENDED_MASTER_SECRET 0x00000001U
/* Reserved value (until OpenSSL 3.0.0) 0x00000002U */
/* Allow initial connection to servers that don't support RI */
# define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004U
/* Reserved value (until OpenSSL 1.2.0) 0x00000008U */
/* Reserved value (until OpenSSL 3.0.0) 0x00000008U */
# define SSL_OP_TLSEXT_PADDING 0x00000010U
/* Reserved value (until OpenSSL 1.2.0) 0x00000020U */
/* Reserved value (until OpenSSL 3.0.0) 0x00000020U */
# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040U
/*
* Reserved value (until OpenSSL 1.2.0) 0x00000080U
* Reserved value (until OpenSSL 1.2.0) 0x00000100U
* Reserved value (until OpenSSL 1.2.0) 0x00000200U
* Reserved value (until OpenSSL 3.0.0) 0x00000080U
* Reserved value (until OpenSSL 3.0.0) 0x00000100U
* Reserved value (until OpenSSL 3.0.0) 0x00000200U
*/
/* In TLSv1.3 allow a non-(ec)dhe based kex_mode */

View File

@ -380,7 +380,8 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
SSL_FLAG_TBL("AllowNoDHEKEX", SSL_OP_ALLOW_NO_DHE_KEX),
SSL_FLAG_TBL("PrioritizeChaCha", SSL_OP_PRIORITIZE_CHACHA),
SSL_FLAG_TBL("MiddleboxCompat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT),
SSL_FLAG_TBL_INV("AntiReplay", SSL_OP_NO_ANTI_REPLAY)
SSL_FLAG_TBL_INV("AntiReplay", SSL_OP_NO_ANTI_REPLAY),
SSL_FLAG_TBL_INV("ExtendedMasterSecret", SSL_OP_NO_EXTENDED_MASTER_SECRET)
};
if (value == NULL)
return -3;

View File

@ -1169,8 +1169,7 @@ static int init_etm(SSL *s, unsigned int context)
static int init_ems(SSL *s, unsigned int context)
{
if (!s->server)
s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
return 1;
}

View File

@ -494,6 +494,9 @@ EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->options & SSL_OP_NO_EXTENDED_MASTER_SECRET)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS,
@ -1743,6 +1746,8 @@ int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
if (s->options & SSL_OP_NO_EXTENDED_MASTER_SECRET)
return 1;
s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
if (!s->hit)
s->session->flags |= SSL_SESS_FLAG_EXTMS;

View File

@ -989,6 +989,9 @@ int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 0;
}
if (s->options & SSL_OP_NO_EXTENDED_MASTER_SECRET)
return 1;
s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
return 1;

View File

@ -28,7 +28,7 @@ map { s/\^// } @conf_files if $^O eq "VMS";
# We hard-code the number of tests to double-check that the globbing above
# finds all files as expected.
plan tests => 29; # = scalar @conf_srcs
plan tests => 30; # = scalar @conf_srcs
# Some test results depend on the configuration of enabled protocols. We only
# verify generated sources in the default configuration.
@ -70,6 +70,7 @@ my %conf_dependent_tests = (
"25-cipher.conf" => disabled("poly1305") || disabled("chacha"),
"27-ticket-appdata.conf" => !$is_default_tls,
"28-seclevel.conf" => disabled("tls1_2") || $no_ec,
"30-extended-master-secret.conf" => disabled("tls1_2"),
);
# Add your test here if it should be skipped for some compile-time

View File

@ -0,0 +1,203 @@
# Generated with generate_ssl_tests.pl
num_tests = 7
test-0 = 0-disable-extended-master-secret-server-sha
test-1 = 1-disable-extended-master-secret-client-sha
test-2 = 2-disable-extended-master-secret-both-sha
test-3 = 3-disable-extended-master-secret-both-resume
test-4 = 4-disable-extended-master-secret-server-sha2
test-5 = 5-disable-extended-master-secret-client-sha2
test-6 = 6-disable-extended-master-secret-both-sha2
# ===========================================================
[0-disable-extended-master-secret-server-sha]
ssl_conf = 0-disable-extended-master-secret-server-sha-ssl
[0-disable-extended-master-secret-server-sha-ssl]
server = 0-disable-extended-master-secret-server-sha-server
client = 0-disable-extended-master-secret-server-sha-client
[0-disable-extended-master-secret-server-sha-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = -ExtendedMasterSecret
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[0-disable-extended-master-secret-server-sha-client]
CipherString = AES128-SHA
MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-0]
ExpectedResult = Success
# ===========================================================
[1-disable-extended-master-secret-client-sha]
ssl_conf = 1-disable-extended-master-secret-client-sha-ssl
[1-disable-extended-master-secret-client-sha-ssl]
server = 1-disable-extended-master-secret-client-sha-server
client = 1-disable-extended-master-secret-client-sha-client
[1-disable-extended-master-secret-client-sha-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[1-disable-extended-master-secret-client-sha-client]
CipherString = AES128-SHA
MaxProtocol = TLSv1.2
Options = -ExtendedMasterSecret
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-1]
ExpectedResult = Success
# ===========================================================
[2-disable-extended-master-secret-both-sha]
ssl_conf = 2-disable-extended-master-secret-both-sha-ssl
[2-disable-extended-master-secret-both-sha-ssl]
server = 2-disable-extended-master-secret-both-sha-server
client = 2-disable-extended-master-secret-both-sha-client
[2-disable-extended-master-secret-both-sha-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = -ExtendedMasterSecret
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[2-disable-extended-master-secret-both-sha-client]
CipherString = AES128-SHA
MaxProtocol = TLSv1.2
Options = -ExtendedMasterSecret
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-2]
ExpectedResult = Success
# ===========================================================
[3-disable-extended-master-secret-both-resume]
ssl_conf = 3-disable-extended-master-secret-both-resume-ssl
[3-disable-extended-master-secret-both-resume-ssl]
server = 3-disable-extended-master-secret-both-resume-server
client = 3-disable-extended-master-secret-both-resume-client
resume-server = 3-disable-extended-master-secret-both-resume-resume-server
resume-client = 3-disable-extended-master-secret-both-resume-resume-client
[3-disable-extended-master-secret-both-resume-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = -ExtendedMasterSecret
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[3-disable-extended-master-secret-both-resume-resume-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[3-disable-extended-master-secret-both-resume-client]
CipherString = AES128-SHA
MaxProtocol = TLSv1.2
Options = -ExtendedMasterSecret
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[3-disable-extended-master-secret-both-resume-resume-client]
CipherString = AES128-SHA
MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-3]
ExpectedResult = Success
HandshakeMode = Resume
# ===========================================================
[4-disable-extended-master-secret-server-sha2]
ssl_conf = 4-disable-extended-master-secret-server-sha2-ssl
[4-disable-extended-master-secret-server-sha2-ssl]
server = 4-disable-extended-master-secret-server-sha2-server
client = 4-disable-extended-master-secret-server-sha2-client
[4-disable-extended-master-secret-server-sha2-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = -ExtendedMasterSecret
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[4-disable-extended-master-secret-server-sha2-client]
CipherString = AES128-SHA256
MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-4]
ExpectedResult = Success
# ===========================================================
[5-disable-extended-master-secret-client-sha2]
ssl_conf = 5-disable-extended-master-secret-client-sha2-ssl
[5-disable-extended-master-secret-client-sha2-ssl]
server = 5-disable-extended-master-secret-client-sha2-server
client = 5-disable-extended-master-secret-client-sha2-client
[5-disable-extended-master-secret-client-sha2-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[5-disable-extended-master-secret-client-sha2-client]
CipherString = AES128-SHA256
MaxProtocol = TLSv1.2
Options = -ExtendedMasterSecret
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-5]
ExpectedResult = Success
# ===========================================================
[6-disable-extended-master-secret-both-sha2]
ssl_conf = 6-disable-extended-master-secret-both-sha2-ssl
[6-disable-extended-master-secret-both-sha2-ssl]
server = 6-disable-extended-master-secret-both-sha2-server
client = 6-disable-extended-master-secret-both-sha2-client
[6-disable-extended-master-secret-both-sha2-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = -ExtendedMasterSecret
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[6-disable-extended-master-secret-both-sha2-client]
CipherString = AES128-SHA256
MaxProtocol = TLSv1.2
Options = -ExtendedMasterSecret
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-6]
ExpectedResult = Success

View File

@ -0,0 +1,122 @@
# -*- mode: perl; -*-
# Copyright 2016-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
## SSL test configurations
package ssltests;
use OpenSSL::Test::Utils;
our @tests = ();
my @tests_tls1_2 = (
{
name => "disable-extended-master-secret-server-sha",
server => {
"Options" => "-ExtendedMasterSecret",
},
client => {
"CipherString" => "AES128-SHA",
"MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedResult" => "Success",
},
},
{
name => "disable-extended-master-secret-client-sha",
server => {
},
client => {
"CipherString" => "AES128-SHA",
"Options" => "-ExtendedMasterSecret",
"MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedResult" => "Success",
},
},
{
name => "disable-extended-master-secret-both-sha",
server => {
"Options" => "-ExtendedMasterSecret",
},
client => {
"CipherString" => "AES128-SHA",
"Options" => "-ExtendedMasterSecret",
"MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedResult" => "Success",
},
},
{
name => "disable-extended-master-secret-both-resume",
server => {
"Options" => "-ExtendedMasterSecret",
},
resume_server => {
},
client => {
"CipherString" => "AES128-SHA",
"Options" => "-ExtendedMasterSecret",
"MaxProtocol" => "TLSv1.2"
},
resume_client => {
"CipherString" => "AES128-SHA",
"MaxProtocol" => "TLSv1.2"
},
test => {
"HandshakeMode" => "Resume",
"ExpectedResult" => "Success",
},
},
{
name => "disable-extended-master-secret-server-sha2",
server => {
"Options" => "-ExtendedMasterSecret",
},
client => {
"CipherString" => "AES128-SHA256",
"MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedResult" => "Success",
},
},
{
name => "disable-extended-master-secret-client-sha2",
server => {
},
client => {
"CipherString" => "AES128-SHA256",
"Options" => "-ExtendedMasterSecret",
"MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedResult" => "Success",
},
},
{
name => "disable-extended-master-secret-both-sha2",
server => {
"Options" => "-ExtendedMasterSecret",
},
client => {
"CipherString" => "AES128-SHA256",
"Options" => "-ExtendedMasterSecret",
"MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedResult" => "Success",
},
},
);
push @tests, @tests_tls1_2 unless disabled("tls1_2");

View File

@ -571,6 +571,51 @@ static int test_client_hello_cb(void)
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
return testresult;
}
static int test_no_ems(void)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(),
TLS1_VERSION, TLS1_2_VERSION,
&sctx, &cctx, cert, privkey)) {
printf("Unable to create SSL_CTX pair\n");
goto end;
}
SSL_CTX_set_options(sctx, SSL_OP_NO_EXTENDED_MASTER_SECRET);
if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
printf("Unable to create SSL objects\n");
goto end;
}
if (!create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) {
printf("Creating SSL connection failed\n");
goto end;
}
if (SSL_get_extms_support(serverssl)) {
printf("Server reports Extended Master Secret support\n");
goto end;
}
if (SSL_get_extms_support(clientssl)) {
printf("Client reports Extended Master Secret support\n");
goto end;
}
testresult = 1;
end:
SSL_free(serverssl);
SSL_free(clientssl);
@ -6087,6 +6132,7 @@ int setup_tests(void)
#endif
#ifndef OPENSSL_NO_TLS1_2
ADD_TEST(test_client_hello_cb);
ADD_TEST(test_no_ems);
#endif
#ifndef OPENSSL_NO_TLS1_3
ADD_ALL_TESTS(test_early_data_read_write, 3);