提交 cc22cd54 编写于 作者: M Matt Caswell

Provide a test for the Encrypt-Then-Mac renegotiation crash

In 1.1.0 changing the ciphersuite during a renegotiation can result in
a crash leading to a DoS attack. In master this does not occur with TLS
(instead you get an internal error, which is still wrong but not a security
issue) - but the problem still exists in the DTLS code.

This commit provides a test for the issue.

CVE-2017-3733
Reviewed-by: NRichard Levitte <levitte@openssl.org>
上级 7b3a4d61
......@@ -607,10 +607,20 @@ static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer)
* session. The server may or may not resume dependant on the
* setting of SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
*/
if (SSL_is_server(peer->ssl))
if (SSL_is_server(peer->ssl)) {
ret = SSL_renegotiate(peer->ssl);
else
ret = SSL_renegotiate_abbreviated(peer->ssl);
} else {
if (test_ctx->extra.client.reneg_ciphers != NULL) {
if (!SSL_set_cipher_list(peer->ssl,
test_ctx->extra.client.reneg_ciphers)) {
peer->status = PEER_ERROR;
return;
}
ret = SSL_renegotiate(peer->ssl);
} else {
ret = SSL_renegotiate_abbreviated(peer->ssl);
}
}
if (!ret) {
peer->status = PEER_ERROR;
return;
......
# Generated with generate_ssl_tests.pl
num_tests = 6
num_tests = 10
test-0 = 0-renegotiate-client-no-resume
test-1 = 1-renegotiate-client-resume
......@@ -8,6 +8,10 @@ test-2 = 2-renegotiate-server-no-resume
test-3 = 3-renegotiate-server-resume
test-4 = 4-renegotiate-client-auth-require
test-5 = 5-renegotiate-client-auth-once
test-6 = 6-renegotiate-aead-to-non-aead
test-7 = 7-renegotiate-non-aead-to-aead
test-8 = 8-renegotiate-non-aead-to-non-aead
test-9 = 9-renegotiate-aead-to-aead
# ===========================================================
[0-renegotiate-client-no-resume]
......@@ -182,3 +186,131 @@ Method = TLS
ResumptionExpected = No
# ===========================================================
[6-renegotiate-aead-to-non-aead]
ssl_conf = 6-renegotiate-aead-to-non-aead-ssl
[6-renegotiate-aead-to-non-aead-ssl]
server = 6-renegotiate-aead-to-non-aead-server
client = 6-renegotiate-aead-to-non-aead-client
[6-renegotiate-aead-to-non-aead-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
MaxProtocol = TLSv1.2
Options = NoResumptionOnRenegotiation
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[6-renegotiate-aead-to-non-aead-client]
CipherString = AES128-GCM-SHA256
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-6]
ExpectedResult = Success
HandshakeMode = RenegotiateClient
Method = TLS
ResumptionExpected = No
client = 6-renegotiate-aead-to-non-aead-client-extra
[6-renegotiate-aead-to-non-aead-client-extra]
RenegotiateCiphers = AES128-SHA
# ===========================================================
[7-renegotiate-non-aead-to-aead]
ssl_conf = 7-renegotiate-non-aead-to-aead-ssl
[7-renegotiate-non-aead-to-aead-ssl]
server = 7-renegotiate-non-aead-to-aead-server
client = 7-renegotiate-non-aead-to-aead-client
[7-renegotiate-non-aead-to-aead-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
MaxProtocol = TLSv1.2
Options = NoResumptionOnRenegotiation
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[7-renegotiate-non-aead-to-aead-client]
CipherString = AES128-SHA
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-7]
ExpectedResult = Success
HandshakeMode = RenegotiateClient
Method = TLS
ResumptionExpected = No
client = 7-renegotiate-non-aead-to-aead-client-extra
[7-renegotiate-non-aead-to-aead-client-extra]
RenegotiateCiphers = AES128-GCM-SHA256
# ===========================================================
[8-renegotiate-non-aead-to-non-aead]
ssl_conf = 8-renegotiate-non-aead-to-non-aead-ssl
[8-renegotiate-non-aead-to-non-aead-ssl]
server = 8-renegotiate-non-aead-to-non-aead-server
client = 8-renegotiate-non-aead-to-non-aead-client
[8-renegotiate-non-aead-to-non-aead-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
MaxProtocol = TLSv1.2
Options = NoResumptionOnRenegotiation
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[8-renegotiate-non-aead-to-non-aead-client]
CipherString = AES128-SHA
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-8]
ExpectedResult = Success
HandshakeMode = RenegotiateClient
Method = TLS
ResumptionExpected = No
client = 8-renegotiate-non-aead-to-non-aead-client-extra
[8-renegotiate-non-aead-to-non-aead-client-extra]
RenegotiateCiphers = AES256-SHA
# ===========================================================
[9-renegotiate-aead-to-aead]
ssl_conf = 9-renegotiate-aead-to-aead-ssl
[9-renegotiate-aead-to-aead-ssl]
server = 9-renegotiate-aead-to-aead-server
client = 9-renegotiate-aead-to-aead-client
[9-renegotiate-aead-to-aead-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
MaxProtocol = TLSv1.2
Options = NoResumptionOnRenegotiation
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[9-renegotiate-aead-to-aead-client]
CipherString = AES128-GCM-SHA256
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-9]
ExpectedResult = Success
HandshakeMode = RenegotiateClient
Method = TLS
ResumptionExpected = No
client = 9-renegotiate-aead-to-aead-client-extra
[9-renegotiate-aead-to-aead-client-extra]
RenegotiateCiphers = AES256-GCM-SHA384
......@@ -108,5 +108,81 @@ our @tests = (
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
}
},
{
name => "renegotiate-aead-to-non-aead",
server => {
"Options" => "NoResumptionOnRenegotiation",
"MaxProtocol" => "TLSv1.2"
},
client => {
"CipherString" => "AES128-GCM-SHA256",
extra => {
"RenegotiateCiphers" => "AES128-SHA"
}
},
test => {
"Method" => "TLS",
"HandshakeMode" => "RenegotiateClient",
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
},
{
name => "renegotiate-non-aead-to-aead",
server => {
"Options" => "NoResumptionOnRenegotiation",
"MaxProtocol" => "TLSv1.2"
},
client => {
"CipherString" => "AES128-SHA",
extra => {
"RenegotiateCiphers" => "AES128-GCM-SHA256"
}
},
test => {
"Method" => "TLS",
"HandshakeMode" => "RenegotiateClient",
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
},
{
name => "renegotiate-non-aead-to-non-aead",
server => {
"Options" => "NoResumptionOnRenegotiation",
"MaxProtocol" => "TLSv1.2"
},
client => {
"CipherString" => "AES128-SHA",
extra => {
"RenegotiateCiphers" => "AES256-SHA"
}
},
test => {
"Method" => "TLS",
"HandshakeMode" => "RenegotiateClient",
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
},
{
name => "renegotiate-aead-to-aead",
server => {
"Options" => "NoResumptionOnRenegotiation",
"MaxProtocol" => "TLSv1.2"
},
client => {
"CipherString" => "AES128-GCM-SHA256",
extra => {
"RenegotiateCiphers" => "AES256-GCM-SHA384"
}
},
test => {
"Method" => "TLS",
"HandshakeMode" => "RenegotiateClient",
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
},
);
# Generated with generate_ssl_tests.pl
num_tests = 5
num_tests = 9
test-0 = 0-renegotiate-client-no-resume
test-1 = 1-renegotiate-client-resume
test-2 = 2-renegotiate-server-resume
test-3 = 3-renegotiate-client-auth-require
test-4 = 4-renegotiate-client-auth-once
test-5 = 5-renegotiate-aead-to-non-aead
test-6 = 6-renegotiate-non-aead-to-aead
test-7 = 7-renegotiate-non-aead-to-non-aead
test-8 = 8-renegotiate-aead-to-aead
# ===========================================================
[0-renegotiate-client-no-resume]
......@@ -146,3 +150,127 @@ Method = DTLS
ResumptionExpected = No
# ===========================================================
[5-renegotiate-aead-to-non-aead]
ssl_conf = 5-renegotiate-aead-to-non-aead-ssl
[5-renegotiate-aead-to-non-aead-ssl]
server = 5-renegotiate-aead-to-non-aead-server
client = 5-renegotiate-aead-to-non-aead-client
[5-renegotiate-aead-to-non-aead-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = NoResumptionOnRenegotiation
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[5-renegotiate-aead-to-non-aead-client]
CipherString = AES128-GCM-SHA256
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-5]
ExpectedResult = Success
HandshakeMode = RenegotiateClient
Method = DTLS
ResumptionExpected = No
client = 5-renegotiate-aead-to-non-aead-client-extra
[5-renegotiate-aead-to-non-aead-client-extra]
RenegotiateCiphers = AES128-SHA
# ===========================================================
[6-renegotiate-non-aead-to-aead]
ssl_conf = 6-renegotiate-non-aead-to-aead-ssl
[6-renegotiate-non-aead-to-aead-ssl]
server = 6-renegotiate-non-aead-to-aead-server
client = 6-renegotiate-non-aead-to-aead-client
[6-renegotiate-non-aead-to-aead-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = NoResumptionOnRenegotiation
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[6-renegotiate-non-aead-to-aead-client]
CipherString = AES128-SHA
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-6]
ExpectedResult = Success
HandshakeMode = RenegotiateClient
Method = DTLS
ResumptionExpected = No
client = 6-renegotiate-non-aead-to-aead-client-extra
[6-renegotiate-non-aead-to-aead-client-extra]
RenegotiateCiphers = AES128-GCM-SHA256
# ===========================================================
[7-renegotiate-non-aead-to-non-aead]
ssl_conf = 7-renegotiate-non-aead-to-non-aead-ssl
[7-renegotiate-non-aead-to-non-aead-ssl]
server = 7-renegotiate-non-aead-to-non-aead-server
client = 7-renegotiate-non-aead-to-non-aead-client
[7-renegotiate-non-aead-to-non-aead-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = NoResumptionOnRenegotiation
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[7-renegotiate-non-aead-to-non-aead-client]
CipherString = AES128-SHA
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-7]
ExpectedResult = Success
HandshakeMode = RenegotiateClient
Method = DTLS
ResumptionExpected = No
client = 7-renegotiate-non-aead-to-non-aead-client-extra
[7-renegotiate-non-aead-to-non-aead-client-extra]
RenegotiateCiphers = AES256-SHA
# ===========================================================
[8-renegotiate-aead-to-aead]
ssl_conf = 8-renegotiate-aead-to-aead-ssl
[8-renegotiate-aead-to-aead-ssl]
server = 8-renegotiate-aead-to-aead-server
client = 8-renegotiate-aead-to-aead-client
[8-renegotiate-aead-to-aead-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Options = NoResumptionOnRenegotiation
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[8-renegotiate-aead-to-aead-client]
CipherString = AES128-GCM-SHA256
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-8]
ExpectedResult = Success
HandshakeMode = RenegotiateClient
Method = DTLS
ResumptionExpected = No
client = 8-renegotiate-aead-to-aead-client-extra
[8-renegotiate-aead-to-aead-client-extra]
RenegotiateCiphers = AES256-GCM-SHA384
......@@ -94,5 +94,77 @@ our @tests = (
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
}
},
{
name => "renegotiate-aead-to-non-aead",
server => {
"Options" => "NoResumptionOnRenegotiation"
},
client => {
"CipherString" => "AES128-GCM-SHA256",
extra => {
"RenegotiateCiphers" => "AES128-SHA"
}
},
test => {
"Method" => "DTLS",
"HandshakeMode" => "RenegotiateClient",
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
},
{
name => "renegotiate-non-aead-to-aead",
server => {
"Options" => "NoResumptionOnRenegotiation"
},
client => {
"CipherString" => "AES128-SHA",
extra => {
"RenegotiateCiphers" => "AES128-GCM-SHA256"
}
},
test => {
"Method" => "DTLS",
"HandshakeMode" => "RenegotiateClient",
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
},
{
name => "renegotiate-non-aead-to-non-aead",
server => {
"Options" => "NoResumptionOnRenegotiation"
},
client => {
"CipherString" => "AES128-SHA",
extra => {
"RenegotiateCiphers" => "AES256-SHA"
}
},
test => {
"Method" => "DTLS",
"HandshakeMode" => "RenegotiateClient",
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
},
{
name => "renegotiate-aead-to-aead",
server => {
"Options" => "NoResumptionOnRenegotiation"
},
client => {
"CipherString" => "AES128-GCM-SHA256",
extra => {
"RenegotiateCiphers" => "AES256-GCM-SHA384"
}
},
test => {
"Method" => "DTLS",
"HandshakeMode" => "RenegotiateClient",
"ResumptionExpected" => "No",
"ExpectedResult" => "Success"
}
},
);
......@@ -88,9 +88,7 @@ static const char *enum_name(const test_enum *enums, size_t num_enums,
}
/*******************/
/* ExpectedResult. */
/*******************/
/* ExpectedResult */
static const test_enum ssl_test_results[] = {
{"Success", SSL_TEST_SUCCESS},
......@@ -115,9 +113,7 @@ const char *ssl_test_result_name(ssl_test_result_t result)
return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result);
}
/**********************************************/
/* ExpectedClientAlert / ExpectedServerAlert. */
/**********************************************/
/* ExpectedClientAlert / ExpectedServerAlert */
static const test_enum ssl_alerts[] = {
{"UnknownCA", SSL_AD_UNKNOWN_CA},
......@@ -147,9 +143,7 @@ const char *ssl_alert_name(int alert)
return enum_name(ssl_alerts, OSSL_NELEM(ssl_alerts), alert);
}
/********************/
/* ExpectedProtocol */
/********************/
static const test_enum ssl_protocols[] = {
{"TLSv1.3", TLS1_3_VERSION},
......@@ -172,9 +166,7 @@ const char *ssl_protocol_name(int protocol)
return enum_name(ssl_protocols, OSSL_NELEM(ssl_protocols), protocol);
}
/***********************/
/* VerifyCallback. */
/***********************/
/* VerifyCallback */
static const test_enum ssl_verify_callbacks[] = {
{"None", SSL_TEST_VERIFY_NONE},
......@@ -200,9 +192,7 @@ const char *ssl_verify_callback_name(ssl_verify_callback_t callback)
callback);
}
/**************/
/* ServerName */
/**************/
static const test_enum ssl_servername[] = {
{"None", SSL_TEST_SERVERNAME_NONE},
......@@ -241,9 +231,7 @@ const char *ssl_servername_name(ssl_servername_t server)
server);
}
/**********************/
/* ServerNameCallback */
/**********************/
static const test_enum ssl_servername_callbacks[] = {
{"None", SSL_TEST_SERVERNAME_CB_NONE},
......@@ -269,9 +257,7 @@ const char *ssl_servername_callback_name(ssl_servername_callback_t callback)
OSSL_NELEM(ssl_servername_callbacks), callback);
}
/*************************/
/* SessionTicketExpected */
/*************************/
static const test_enum ssl_session_ticket[] = {
{"Ignore", SSL_TEST_SESSION_TICKET_IGNORE},
......@@ -297,9 +283,7 @@ const char *ssl_session_ticket_name(ssl_session_ticket_t server)
server);
}
/***********************/
/* Method */
/***********************/
/* Method */
static const test_enum ssl_test_methods[] = {
{"TLS", SSL_TEST_METHOD_TLS},
......@@ -322,9 +306,7 @@ const char *ssl_test_method_name(ssl_test_method_t method)
return enum_name(ssl_test_methods, OSSL_NELEM(ssl_test_methods), method);
}
/************************************/
/* NPN and ALPN options */
/************************************/
/* NPN and ALPN options */
IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, npn_protocols)
IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, npn_protocols)
......@@ -333,9 +315,7 @@ IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, alpn_protocols)
IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_SERVER_CONF, server, alpn_protocols)
IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_alpn_protocol)
/***********************/
/* Handshake mode */
/***********************/
/* Handshake mode */
static const test_enum ssl_handshake_modes[] = {
{"Simple", SSL_TEST_HANDSHAKE_SIMPLE},
......@@ -361,9 +341,11 @@ const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode)
mode);
}
/***********************/
/* CT Validation */
/***********************/
/* Renegotiation Ciphersuites */
IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, reneg_ciphers)
/* CT Validation */
static const test_enum ssl_ct_validation_modes[] = {
{"None", SSL_TEST_CT_VALIDATION_NONE},
......@@ -392,9 +374,7 @@ const char *ssl_ct_validation_name(ssl_ct_validation_t mode)
IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, resumption_expected)
IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, broken_session_ticket)
/**************/
/* CertStatus */
/**************/
static const test_enum ssl_certstatus[] = {
{"None", SSL_TEST_CERT_STATUS_NONE},
......@@ -420,21 +400,17 @@ const char *ssl_certstatus_name(ssl_cert_status_t cert_status)
OSSL_NELEM(ssl_certstatus), cert_status);
}
/***********************/
/* ApplicationData */
/***********************/
/* ApplicationData */
IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, app_data_size)
/***********************/
/* MaxFragmentSize */
/***********************/
/* MaxFragmentSize */
IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, max_fragment_size)
/*************************************/
/* Expected key and signature types */
/*************************************/
/* Expected key and signature types */
__owur static int parse_expected_key_type(int *ptype, const char *value)
{
......@@ -494,9 +470,8 @@ __owur static int parse_expected_client_sign_type(SSL_TEST_CTX *test_ctx,
value);
}
/*************************/
/* Expected signing hash */
/*************************/
__owur static int parse_expected_sign_hash(int *ptype, const char *value)
{
......@@ -527,9 +502,8 @@ __owur static int parse_expected_client_sign_hash(SSL_TEST_CTX *test_ctx,
value);
}
/*************************************************************/
/* Known test options and their corresponding parse methods. */
/*************************************************************/
/* Top-level options. */
typedef struct {
......@@ -572,6 +546,7 @@ static const ssl_test_client_option ssl_test_client_options[] = {
{ "NPNProtocols", &parse_client_npn_protocols },
{ "ALPNProtocols", &parse_client_alpn_protocols },
{ "CTValidation", &parse_ct_validation },
{ "RenegotiateCiphers", &parse_client_reneg_ciphers},
};
/* Nested server options. */
......
......@@ -84,6 +84,8 @@ typedef struct {
char *npn_protocols;
char *alpn_protocols;
ssl_ct_validation_t ct_validation;
/* Ciphersuites to set on a renegotiation */
char *reneg_ciphers;
} SSL_TEST_CLIENT_CONF;
typedef struct {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册