From 75f12d7cbffcaa31cc8ff5c7fee02e614785632a Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 8 Jan 2017 00:09:08 +0000 Subject: [PATCH] Add new ssl_test option. Add option ExpectedTmpKeyType to test the temporary key the server sends is of the correct type. Reviewed-by: Kurt Roeckx Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/2191) (cherry picked from commit b93ad05dba3e3d2ceb79799a883ae43d42ba16e2) --- test/README.ssltest.md | 2 ++ test/handshake_helper.c | 14 ++++++++++++++ test/handshake_helper.h | 2 ++ test/ssl_test.c | 12 ++++++++++++ test/ssl_test_ctx.c | 25 +++++++++++++++++++++++++ test/ssl_test_ctx.h | 2 ++ 6 files changed, 57 insertions(+) diff --git a/test/README.ssltest.md b/test/README.ssltest.md index e28d4b0d47..c1edda5aed 100644 --- a/test/README.ssltest.md +++ b/test/README.ssltest.md @@ -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` diff --git a/test/handshake_helper.c b/test/handshake_helper.c index 1d0e2a4b99..0a421b1597 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -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); diff --git a/test/handshake_helper.h b/test/handshake_helper.h index 8425b2aa61..4f70592a18 100644 --- a/test/handshake_helper.h +++ b/test/handshake_helper.h @@ -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); diff --git a/test/ssl_test.c b/test/ssl_test.c index 9f146180f3..60ccbe7f0f 100644 --- a/test/ssl_test.c +++ b/test/ssl_test.c @@ -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; } diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c index 0a528d805b..09e7a89e9b 100644 --- a/test/ssl_test_ctx.c +++ b/test/ssl_test_ctx.c @@ -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. */ diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index 14acaff6f7..995d518ed3 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -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); -- 2.25.1