Provide a test for the Encrypt-Then-Mac renegotiation crash
authorMatt Caswell <matt@openssl.org>
Fri, 3 Feb 2017 11:21:07 +0000 (11:21 +0000)
committerMatt Caswell <matt@openssl.org>
Thu, 16 Feb 2017 09:35:56 +0000 (09:35 +0000)
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: Richard Levitte <levitte@openssl.org>
test/handshake_helper.c
test/ssl-tests/17-renegotiate.conf
test/ssl-tests/17-renegotiate.conf.in
test/ssl-tests/18-dtls-renegotiate.conf
test/ssl-tests/18-dtls-renegotiate.conf.in
test/ssl_test_ctx.c
test/ssl_test_ctx.h

index a789899..2b869a4 100644 (file)
@@ -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;
index 58992c0..8376eea 100644 (file)
@@ -1,6 +1,6 @@
 # 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
+
+
index 3f76cb8..77264c4 100644 (file)
@@ -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"
+        }
+    },
 );
index fbde68a..3d8ebd7 100644 (file)
@@ -1,12 +1,16 @@
 # 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
+
+
index 3f877f6..43046e3 100644 (file)
@@ -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"
+        }
+    },
 );
index e88e577..1f3495f 100644 (file)
@@ -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. */
index 13652b0..6036a02 100644 (file)
@@ -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 {