Add new ssl_test option.
authorDr. Stephen Henson <steve@openssl.org>
Sun, 8 Jan 2017 00:09:08 +0000 (00:09 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 8 Jan 2017 19:39:33 +0000 (19:39 +0000)
Add option ExpectedTmpKeyType to test the temporary key the server
sends is of the correct type.

Reviewed-by: Kurt Roeckx <kurt@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2191)
(cherry picked from commit b93ad05dba3e3d2ceb79799a883ae43d42ba16e2)

test/README.ssltest.md
test/handshake_helper.c
test/handshake_helper.h
test/ssl_test.c
test/ssl_test_ctx.c
test/ssl_test_ctx.h

index e28d4b0d470103586b0d3217f3cfbe23532c43c3..c1edda5aed73b5fe4c88d7506d62e81bcd98dd95 100644 (file)
@@ -87,6 +87,8 @@ handshake.
 
 * ExpectedNPNProtocol, ExpectedALPNProtocol - NPN and ALPN expectations.
 
+* ExpectedTmpKeyType - the expected algorithm or curve of server temp key
+
 ## Configuring the client and server
 
 The client and server configurations can be any valid `SSL_CTX`
index 1d0e2a4b99f5b2f5ce3502318b325bf88215837c..0a421b1597fb6f0dc98c0d2186bb9e18d99b72be 100644 (file)
@@ -876,6 +876,7 @@ static HANDSHAKE_RESULT *do_handshake_internal(
     const unsigned char *proto = NULL;
     /* API dictates unsigned int rather than size_t. */
     unsigned int proto_len = 0;
+    EVP_PKEY *tmp_key;
 
     memset(&server_ctx_data, 0, sizeof(server_ctx_data));
     memset(&server2_ctx_data, 0, sizeof(server2_ctx_data));
@@ -1035,6 +1036,19 @@ static HANDSHAKE_RESULT *do_handshake_internal(
     if (session_out != NULL)
         *session_out = SSL_get1_session(client.ssl);
 
+    if (SSL_get_server_tmp_key(client.ssl, &tmp_key)) {
+        int nid = EVP_PKEY_id(tmp_key);
+
+#ifndef OPENSSL_NO_EC
+        if (nid == EVP_PKEY_EC) {
+            EC_KEY *ec = EVP_PKEY_get0_EC_KEY(tmp_key);
+            nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+        }
+#endif
+        EVP_PKEY_free(tmp_key);
+        ret->tmp_key_type = nid;
+    }
+
     ctx_data_free_data(&server_ctx_data);
     ctx_data_free_data(&server2_ctx_data);
     ctx_data_free_data(&client_ctx_data);
index 8425b2aa6156eac97ae29a37a814e72c58a274e0..4f70592a1867be9015975dd329417591bba5c3cd 100644 (file)
@@ -43,6 +43,8 @@ typedef struct handshake_result {
     /* Was the handshake resumed? */
     int client_resumed;
     int server_resumed;
+    /* Temporary key type */
+    int tmp_key_type;
 } HANDSHAKE_RESULT;
 
 HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void);
index 9f146180f31b6bd3d80923ad0b446cb2b0340339..60ccbe7f0f1117ff24a14b5dcbe892138b9afd8a 100644 (file)
@@ -198,6 +198,17 @@ static int check_resumption(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
     return 1;
 }
 
+static int check_tmp_key(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
+{
+    if (test_ctx->expected_tmp_key_type == 0
+        || test_ctx->expected_tmp_key_type == result->tmp_key_type)
+        return 1;
+    fprintf(stderr, "Tmp key type mismatch, %s vs %s\n",
+            OBJ_nid2ln(test_ctx->expected_tmp_key_type),
+            OBJ_nid2ln(result->tmp_key_type));
+    return 0;
+}
+
 /*
  * This could be further simplified by constructing an expected
  * HANDSHAKE_RESULT, and implementing comparison methods for
@@ -218,6 +229,7 @@ static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
 #endif
         ret &= check_alpn(result, test_ctx);
         ret &= check_resumption(result, test_ctx);
+        ret &= check_tmp_key(result, test_ctx);
     }
     return ret;
 }
index 0a528d805b47ad9f56a422f4f56a3dda3dc86a19..09e7a89e9bdf0dc8918043e9c91501855009f5ec 100644 (file)
@@ -431,6 +431,30 @@ IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, app_data_size)
 
 IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, max_fragment_size)
 
+/***********************/
+/* ExpectedTmpKeyType  */
+/***********************/
+
+__owur static int parse_expected_tmp_key_type(SSL_TEST_CTX *test_ctx,
+                                              const char *value)
+{
+    int nid;
+
+    if (value == NULL)
+        return 0;
+    nid = OBJ_sn2nid(value);
+    if (nid == NID_undef)
+        nid = OBJ_ln2nid(value);
+#ifndef OPENSSL_NO_EC
+    if (nid == NID_undef)
+        nid = EC_curve_nist2nid(value);
+#endif
+    if (nid == NID_undef)
+        return 0;
+    test_ctx->expected_tmp_key_type = nid;
+    return 1;
+}
+
 /*************************************************************/
 /* Known test options and their corresponding parse methods. */
 /*************************************************************/
@@ -455,6 +479,7 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = {
     { "ResumptionExpected", &parse_test_resumption_expected },
     { "ApplicationData", &parse_test_app_data_size },
     { "MaxFragmentSize", &parse_test_max_fragment_size },
+    { "ExpectedTmpKeyType", &parse_expected_tmp_key_type },
 };
 
 /* Nested client options. */
index 14acaff6f7aaa1eda403e23b3f75d54ac6e9b505..995d518ed37690300e2774088d907f94fc36f788 100644 (file)
@@ -159,6 +159,8 @@ typedef struct {
     char *expected_alpn_protocol;
     /* Whether the second handshake is resumed or a full handshake (boolean). */
     int resumption_expected;
+    /* Expected temporary key type */
+    int expected_tmp_key_type;
 } SSL_TEST_CTX;
 
 const char *ssl_test_result_name(ssl_test_result_t result);