Add some KeyUpdate tests
authorMatt Caswell <matt@openssl.org>
Wed, 15 Feb 2017 09:25:52 +0000 (09:25 +0000)
committerMatt Caswell <matt@openssl.org>
Fri, 17 Feb 2017 10:28:01 +0000 (10:28 +0000)
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2609)

test/handshake_helper.c
test/recipes/80-test_ssl_new.t
test/ssl-tests/21-key-update.conf [new file with mode: 0644]
test/ssl-tests/21-key-update.conf.in [new file with mode: 0644]
test/ssl_test_ctx.c
test/ssl_test_ctx.h

index 2b869a4247663122d08e43214c242b309333f394..c82581c57630844a8550fda66fe00a3503f402a8 100644 (file)
@@ -590,7 +590,14 @@ static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer)
 
     TEST_check(peer->status == PEER_RETRY);
     TEST_check(test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER
-                || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT);
+                || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT
+                || test_ctx->handshake_mode
+                   == SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER
+                || test_ctx->handshake_mode
+                   == SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT);
+
+    /* Reset the count of the amount of app data we need to read/write */
+    peer->bytes_to_write = peer->bytes_to_read = test_ctx->app_data_size;
 
     /* Check if we are the peer that is going to initiate */
     if ((test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER
@@ -642,6 +649,29 @@ static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer)
                 peer->status = PEER_RETRY;
             return;
         }
+    } else if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER
+               || test_ctx->handshake_mode
+                  == SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT) {
+        if (SSL_is_server(peer->ssl)
+                != (test_ctx->handshake_mode
+                    == SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER)) {
+            peer->status = PEER_SUCCESS;
+            return;
+        }
+
+        ret = SSL_key_update(peer->ssl, test_ctx->key_update_type);
+        if (!ret) {
+            peer->status = PEER_ERROR;
+            return;
+        }
+        do_handshake_step(peer);
+        /*
+         * This is a one step handshake. We shouldn't get anything other than
+         * PEER_SUCCESS
+         */
+        if (peer->status != PEER_SUCCESS)
+            peer->status = PEER_ERROR;
+        return;
     }
 
     /*
@@ -663,7 +693,7 @@ static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer)
             peer->status = PEER_ERROR;
             return;
         }
-        /* If we're no in init yet then we're not done with setup yet */
+        /* If we're not in init yet then we're not done with setup yet */
         if (!SSL_in_init(peer->ssl))
             return;
     }
@@ -720,12 +750,20 @@ static connect_phase_t next_phase(const SSL_TEST_CTX *test_ctx,
     switch (phase) {
     case HANDSHAKE:
         if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER
-                || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT)
+                || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT
+                || test_ctx->handshake_mode
+                   == SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT
+                || test_ctx->handshake_mode
+                   == SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER)
             return RENEG_APPLICATION_DATA;
         return APPLICATION_DATA;
     case RENEG_APPLICATION_DATA:
         return RENEG_SETUP;
     case RENEG_SETUP:
+        if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER
+                || test_ctx->handshake_mode
+                   == SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT)
+            return APPLICATION_DATA;
         return RENEG_HANDSHAKE;
     case RENEG_HANDSHAKE:
         return APPLICATION_DATA;
index 5c512cf3f559ae9930c2072751a7977ef524f7c0..640f314fbc95f06a766b2965a49829b057c70f61 100644 (file)
@@ -29,7 +29,7 @@ map { s/\.in// } @conf_files;
 
 # We hard-code the number of tests to double-check that the globbing above
 # finds all files as expected.
-plan tests => 20;  # = scalar @conf_srcs
+plan tests => 21;  # = scalar @conf_srcs
 
 # Some test results depend on the configuration of enabled protocols. We only
 # verify generated sources in the default configuration.
@@ -82,6 +82,7 @@ my %skip = (
   "18-dtls-renegotiate.conf" => $no_dtls,
   "19-mac-then-encrypt.conf" => $no_pre_tls1_3,
   "20-cert-select.conf" => disabled("tls1_2") || $no_ec,
+  "21-key-update.conf" => disabled("tls1_3"),
 );
 
 foreach my $conf (@conf_files) {
diff --git a/test/ssl-tests/21-key-update.conf b/test/ssl-tests/21-key-update.conf
new file mode 100644 (file)
index 0000000..b79eb44
--- /dev/null
@@ -0,0 +1,112 @@
+# Generated with generate_ssl_tests.pl
+
+num_tests = 4
+
+test-0 = 0-update-key-client-update-not-requested
+test-1 = 1-update-key-server-update-not-requested
+test-2 = 2-update-key-client-update-requested
+test-3 = 3-update-key-server-update-requested
+# ===========================================================
+
+[0-update-key-client-update-not-requested]
+ssl_conf = 0-update-key-client-update-not-requested-ssl
+
+[0-update-key-client-update-not-requested-ssl]
+server = 0-update-key-client-update-not-requested-server
+client = 0-update-key-client-update-not-requested-client
+
+[0-update-key-client-update-not-requested-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[0-update-key-client-update-not-requested-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-0]
+ExpectedResult = Success
+HandshakeMode = KeyUpdateClient
+KeyUpdateType = KeyUpdateNotRequested
+ResumptionExpected = No
+
+
+# ===========================================================
+
+[1-update-key-server-update-not-requested]
+ssl_conf = 1-update-key-server-update-not-requested-ssl
+
+[1-update-key-server-update-not-requested-ssl]
+server = 1-update-key-server-update-not-requested-server
+client = 1-update-key-server-update-not-requested-client
+
+[1-update-key-server-update-not-requested-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[1-update-key-server-update-not-requested-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-1]
+ExpectedResult = Success
+HandshakeMode = KeyUpdateServer
+KeyUpdateType = KeyUpdateNotRequested
+ResumptionExpected = No
+
+
+# ===========================================================
+
+[2-update-key-client-update-requested]
+ssl_conf = 2-update-key-client-update-requested-ssl
+
+[2-update-key-client-update-requested-ssl]
+server = 2-update-key-client-update-requested-server
+client = 2-update-key-client-update-requested-client
+
+[2-update-key-client-update-requested-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[2-update-key-client-update-requested-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-2]
+ExpectedResult = Success
+HandshakeMode = KeyUpdateClient
+KeyUpdateType = KeyUpdateRequested
+ResumptionExpected = No
+
+
+# ===========================================================
+
+[3-update-key-server-update-requested]
+ssl_conf = 3-update-key-server-update-requested-ssl
+
+[3-update-key-server-update-requested-ssl]
+server = 3-update-key-server-update-requested-server
+client = 3-update-key-server-update-requested-client
+
+[3-update-key-server-update-requested-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[3-update-key-server-update-requested-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-3]
+ExpectedResult = Success
+HandshakeMode = KeyUpdateServer
+KeyUpdateType = KeyUpdateRequested
+ResumptionExpected = No
+
+
diff --git a/test/ssl-tests/21-key-update.conf.in b/test/ssl-tests/21-key-update.conf.in
new file mode 100644 (file)
index 0000000..4bebb48
--- /dev/null
@@ -0,0 +1,62 @@
+# -*- mode: perl; -*-
+# Copyright 2017 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
+
+
+## Test KeyUpdate
+
+use strict;
+use warnings;
+
+package ssltests;
+
+our @tests = (
+    {
+        name => "update-key-client-update-not-requested",
+        server => {},
+        client => {},
+        test => {
+            "HandshakeMode" => "KeyUpdateClient",
+            "KeyUpdateType" => "KeyUpdateNotRequested",
+            "ResumptionExpected" => "No",
+            "ExpectedResult" => "Success"
+        }
+    },
+    {
+        name => "update-key-server-update-not-requested",
+        server => {},
+        client => {},
+        test => {
+            "HandshakeMode" => "KeyUpdateServer",
+            "KeyUpdateType" => "KeyUpdateNotRequested",
+            "ResumptionExpected" => "No",
+            "ExpectedResult" => "Success"
+        }
+    },
+    {
+        name => "update-key-client-update-requested",
+        server => {},
+        client => {},
+        test => {
+            "HandshakeMode" => "KeyUpdateClient",
+            "KeyUpdateType" => "KeyUpdateRequested",
+            "ResumptionExpected" => "No",
+            "ExpectedResult" => "Success"
+        }
+    },
+    {
+        name => "update-key-server-update-requested",
+        server => {},
+        client => {},
+        test => {
+            "HandshakeMode" => "KeyUpdateServer",
+            "KeyUpdateType" => "KeyUpdateRequested",
+            "ResumptionExpected" => "No",
+            "ExpectedResult" => "Success"
+        }
+    }
+);
index c5b9a3ebe69eb4037cd68749ad5b80fd7495a788..66fb31ce5a00847ca00bd735232e1c7d2d99fc3e 100644 (file)
@@ -322,6 +322,8 @@ static const test_enum ssl_handshake_modes[] = {
     {"Resume", SSL_TEST_HANDSHAKE_RESUME},
     {"RenegotiateServer", SSL_TEST_HANDSHAKE_RENEG_SERVER},
     {"RenegotiateClient", SSL_TEST_HANDSHAKE_RENEG_CLIENT},
+    {"KeyUpdateServer", SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER},
+    {"KeyUpdateClient", SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT},
 };
 
 __owur static int parse_handshake_mode(SSL_TEST_CTX *test_ctx, const char *value)
@@ -345,6 +347,24 @@ const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode)
 
 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CLIENT_CONF, client, reneg_ciphers)
 
+/* KeyUpdateType */
+
+static const test_enum ssl_key_update_types[] = {
+    {"KeyUpdateRequested", SSL_KEY_UPDATE_REQUESTED},
+    {"KeyUpdateNotRequested", SSL_KEY_UPDATE_NOT_REQUESTED},
+};
+
+__owur static int parse_key_update_type(SSL_TEST_CTX *test_ctx, const char *value)
+{
+    int ret_value;
+    if (!parse_enum(ssl_key_update_types, OSSL_NELEM(ssl_key_update_types),
+                    &ret_value, value)) {
+        return 0;
+    }
+    test_ctx->key_update_type = ret_value;
+    return 1;
+}
+
 /* CT Validation */
 
 static const test_enum ssl_ct_validation_modes[] = {
@@ -522,6 +542,7 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = {
     { "ExpectedNPNProtocol", &parse_test_expected_npn_protocol },
     { "ExpectedALPNProtocol", &parse_test_expected_alpn_protocol },
     { "HandshakeMode", &parse_handshake_mode },
+    { "KeyUpdateType", &parse_key_update_type },
     { "ResumptionExpected", &parse_test_resumption_expected },
     { "ApplicationData", &parse_test_app_data_size },
     { "MaxFragmentSize", &parse_test_max_fragment_size },
index 6036a02bc90bb356697dfccfb3abb30e82249939..eaeee1fd3cce2da156cc421cd852710a532b92d6 100644 (file)
@@ -57,7 +57,9 @@ typedef enum {
     SSL_TEST_HANDSHAKE_SIMPLE = 0, /* Default */
     SSL_TEST_HANDSHAKE_RESUME,
     SSL_TEST_HANDSHAKE_RENEG_SERVER,
-    SSL_TEST_HANDSHAKE_RENEG_CLIENT
+    SSL_TEST_HANDSHAKE_RENEG_CLIENT,
+    SSL_TEST_HANDSHAKE_KEY_UPDATE_SERVER,
+    SSL_TEST_HANDSHAKE_KEY_UPDATE_CLIENT
 } ssl_handshake_mode_t;
 
 typedef enum {
@@ -121,6 +123,8 @@ typedef struct {
     int app_data_size;
     /* Maximum send fragment size. */
     int max_fragment_size;
+    /* KeyUpdate type */
+    SSL_KEY_UPDATE key_update_type;
 
     /*
      * Extra server/client configurations. Per-handshake.