From 7f5f35af223f9c1d641f46446f6bbf9d1493a9e6 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 8 Jan 2017 19:30:41 +0000 Subject: [PATCH] Add options to check certificate types. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reviewed-by: Emilia Käsper (Merged from https://github.com/openssl/openssl/pull/2224) --- test/README.ssltest.md | 3 +++ test/handshake_helper.c | 39 ++++++++++++++++++++++++++++++--------- test/handshake_helper.h | 4 ++++ test/ssl_test.c | 35 +++++++++++++++++++++++++++++------ test/ssl_test_ctx.c | 36 +++++++++++++++++++++++++++++++----- test/ssl_test_ctx.h | 4 ++++ 6 files changed, 101 insertions(+), 20 deletions(-) diff --git a/test/README.ssltest.md b/test/README.ssltest.md index c1edda5aed..48d5474a08 100644 --- a/test/README.ssltest.md +++ b/test/README.ssltest.md @@ -89,6 +89,9 @@ handshake. * ExpectedTmpKeyType - the expected algorithm or curve of server temp key +* ExpectedServerKeyType, ExpectedClientKeyType - the expected algorithm or + curve of server or client certificate + ## 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 9ffd0bf427..01a30c850f 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -847,6 +847,32 @@ static char *dup_str(const unsigned char *in, size_t len) return ret; } +static int pkey_type(EVP_PKEY *pkey) +{ + int nid = EVP_PKEY_id(pkey); + +#ifndef OPENSSL_NO_EC + if (nid == EVP_PKEY_EC) { + const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey); + return EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + } +#endif + return nid; +} + +static int peer_pkey_type(SSL *s) +{ + X509 *x = SSL_get_peer_certificate(s); + + if (x != NULL) { + int nid = pkey_type(X509_get0_pubkey(x)); + + X509_free(x); + return nid; + } + return NID_undef; +} + /* * Note that |extra| points to the correct client/server configuration * within |test_ctx|. When configuring the handshake, general mode settings @@ -1040,18 +1066,13 @@ static HANDSHAKE_RESULT *do_handshake_internal( *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 + ret->tmp_key_type = pkey_type(tmp_key); EVP_PKEY_free(tmp_key); - ret->tmp_key_type = nid; } + ret->server_cert_type = peer_pkey_type(client.ssl); + ret->client_cert_type = peer_pkey_type(server.ssl); + 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 4f70592a18..1cdd6fa055 100644 --- a/test/handshake_helper.h +++ b/test/handshake_helper.h @@ -45,6 +45,10 @@ typedef struct handshake_result { int server_resumed; /* Temporary key type */ int tmp_key_type; + /* server certificate key type */ + int server_cert_type; + /* client certificate key type */ + int client_cert_type; } HANDSHAKE_RESULT; HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void); diff --git a/test/ssl_test.c b/test/ssl_test.c index 61850eb9f6..af92aa13cf 100644 --- a/test/ssl_test.c +++ b/test/ssl_test.c @@ -187,17 +187,38 @@ 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) +static int check_key_type(const char *name,int expected_key_type, int key_type) { - if (test_ctx->expected_tmp_key_type == 0 - || test_ctx->expected_tmp_key_type == result->tmp_key_type) + if (expected_key_type == 0 || expected_key_type == 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)); + fprintf(stderr, "%s type mismatch, %s vs %s\n", + name, OBJ_nid2ln(expected_key_type), + key_type == NID_undef ? "absent" : OBJ_nid2ln(key_type)); return 0; } +static int check_tmp_key(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) +{ + return check_key_type("Tmp key", test_ctx->expected_tmp_key_type, + result->tmp_key_type); +} + +static int check_server_cert_type(HANDSHAKE_RESULT *result, + SSL_TEST_CTX *test_ctx) +{ + return check_key_type("Server certificate", + test_ctx->expected_server_cert_type, + result->server_cert_type); +} + +static int check_client_cert_type(HANDSHAKE_RESULT *result, + SSL_TEST_CTX *test_ctx) +{ + return check_key_type("Client certificate", + test_ctx->expected_client_cert_type, + result->client_cert_type); +} + /* * This could be further simplified by constructing an expected * HANDSHAKE_RESULT, and implementing comparison methods for @@ -219,6 +240,8 @@ static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx) ret &= check_alpn(result, test_ctx); ret &= check_resumption(result, test_ctx); ret &= check_tmp_key(result, test_ctx); + ret &= check_server_cert_type(result, test_ctx); + ret &= check_client_cert_type(result, test_ctx); } return ret; } diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c index 2c5ba1e5bb..f8d5ecda14 100644 --- a/test/ssl_test_ctx.c +++ b/test/ssl_test_ctx.c @@ -433,17 +433,21 @@ 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 */ +/* Expected key types */ /***********************/ -__owur static int parse_expected_tmp_key_type(SSL_TEST_CTX *test_ctx, - const char *value) +__owur static int parse_expected_key_type(int *ptype, const char *value) { int nid; + const EVP_PKEY_ASN1_METHOD *ameth; if (value == NULL) return 0; - nid = OBJ_sn2nid(value); + ameth = EVP_PKEY_asn1_find_str(NULL, value, -1); + if (ameth != NULL) + EVP_PKEY_asn1_get0_info(&nid, NULL, NULL, NULL, NULL, ameth); + else + nid = OBJ_sn2nid(value); if (nid == NID_undef) nid = OBJ_ln2nid(value); #ifndef OPENSSL_NO_EC @@ -452,10 +456,30 @@ __owur static int parse_expected_tmp_key_type(SSL_TEST_CTX *test_ctx, #endif if (nid == NID_undef) return 0; - test_ctx->expected_tmp_key_type = nid; + *ptype = nid; return 1; } +__owur static int parse_expected_tmp_key_type(SSL_TEST_CTX *test_ctx, + const char *value) +{ + return parse_expected_key_type(&test_ctx->expected_tmp_key_type, value); +} + +__owur static int parse_expected_server_cert_type(SSL_TEST_CTX *test_ctx, + const char *value) +{ + return parse_expected_key_type(&test_ctx->expected_server_cert_type, + value); +} + +__owur static int parse_expected_client_cert_type(SSL_TEST_CTX *test_ctx, + const char *value) +{ + return parse_expected_key_type(&test_ctx->expected_client_cert_type, + value); +} + /*************************************************************/ /* Known test options and their corresponding parse methods. */ /*************************************************************/ @@ -481,6 +505,8 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = { { "ApplicationData", &parse_test_app_data_size }, { "MaxFragmentSize", &parse_test_max_fragment_size }, { "ExpectedTmpKeyType", &parse_expected_tmp_key_type }, + { "ExpectedServerCertType", &parse_expected_server_cert_type }, + { "ExpectedClientCertType", &parse_expected_client_cert_type }, }; /* Nested client options. */ diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index 995d518ed3..f67f01ad87 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -161,6 +161,10 @@ typedef struct { int resumption_expected; /* Expected temporary key type */ int expected_tmp_key_type; + /* Expected server certificate key type */ + int expected_server_cert_type; + /* Expected client certificate key type */ + int expected_client_cert_type; } SSL_TEST_CTX; const char *ssl_test_result_name(ssl_test_result_t result); -- 2.25.1