summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorTodd Short <tshort@akamai.com>2021-01-27 14:23:33 -0500
committerTodd Short <todd.short@me.com>2023-03-28 13:49:54 -0400
commit3c95ef22df55cb2d9dc64ce1f3be6e5a8ee63206 (patch)
tree0f7fcff4ec4735c778595db4f4a85bce70715d8b /test
parent5ab3f71a33cb0140fc29ae9244cd4f8331c2f3a5 (diff)
downloadopenssl-new-3c95ef22df55cb2d9dc64ce1f3be6e5a8ee63206.tar.gz
RFC7250 (RPK) support
Add support for the RFC7250 certificate-type extensions. Alows the use of only private keys for connection (i.e. certs not needed). Add APIs Add unit tests Add documentation Add s_client/s_server support Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Viktor Dukhovni <viktor@openssl.org> (Merged from https://github.com/openssl/openssl/pull/18185)
Diffstat (limited to 'test')
-rw-r--r--test/build.info8
-rw-r--r--test/ext_internal_test.c2
-rw-r--r--test/recipes/70-test_certtypeext.t96
-rw-r--r--test/recipes/90-test_rpk.t23
-rw-r--r--test/rpktest.c759
-rw-r--r--test/sslapitest.c22
6 files changed, 907 insertions, 3 deletions
diff --git a/test/build.info b/test/build.info
index 56d53445dc..4599770106 100644
--- a/test/build.info
+++ b/test/build.info
@@ -66,6 +66,10 @@ IF[{- !$disabled{tests} -}]
bio_tfo_test membio_test bio_dgram_test list_test fips_version_test \
x509_test hpke_test pairwise_fail_test nodefltctxtest
+ IF[{- !$disabled{'rpk'} -}]
+ PROGRAMS{noinst}=rpktest
+ ENDIF
+
IF[{- !$disabled{'deprecated-3.0'} -}]
PROGRAMS{noinst}=enginetest
ENDIF
@@ -485,6 +489,10 @@ IF[{- !$disabled{tests} -}]
INCLUDE[sslapitest]=../include ../apps/include ..
DEPEND[sslapitest]=../libcrypto ../libssl libtestutil.a
+ SOURCE[rpktest]=rpktest.c helpers/ssltestlib.c
+ INCLUDE[rpktest]=../include ../apps/include ..
+ DEPEND[rpktest]=../libcrypto ../libssl libtestutil.a
+
SOURCE[defltfips_test]=defltfips_test.c
INCLUDE[defltfips_test]=../include ../apps/include
DEPEND[defltfips_test]=../libcrypto libtestutil.a
diff --git a/test/ext_internal_test.c b/test/ext_internal_test.c
index 97a538abf9..b86f82ebf9 100644
--- a/test/ext_internal_test.c
+++ b/test/ext_internal_test.c
@@ -61,6 +61,8 @@ static EXT_LIST ext_list[] = {
EXT_ENTRY(extended_master_secret),
EXT_ENTRY(signature_algorithms_cert),
EXT_ENTRY(post_handshake_auth),
+ EXT_ENTRY(client_cert_type),
+ EXT_ENTRY(server_cert_type),
EXT_ENTRY(signature_algorithms),
EXT_ENTRY(supported_versions),
EXT_ENTRY(psk_kex_modes),
diff --git a/test/recipes/70-test_certtypeext.t b/test/recipes/70-test_certtypeext.t
new file mode 100644
index 0000000000..963468a052
--- /dev/null
+++ b/test/recipes/70-test_certtypeext.t
@@ -0,0 +1,96 @@
+#! /usr/bin/env perl
+# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (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
+
+use strict;
+use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
+use OpenSSL::Test::Utils;
+use TLSProxy::Proxy;
+
+my $test_name = "test_certtypeext";
+setup($test_name);
+
+plan skip_all => "TLSProxy isn't usable on $^O"
+ if $^O =~ /^(VMS)$/;
+
+plan skip_all => "$test_name needs the dynamic engine feature enabled"
+ if disabled("engine") || disabled("dynamic-engine");
+
+plan skip_all => "$test_name needs the sock feature enabled"
+ if disabled("sock");
+
+plan skip_all => "$test_name needs TLSv1.2 enabled"
+ if disabled("tls1_2");
+
+my $proxy = TLSProxy::Proxy->new(
+ \&certtype_filter,
+ cmdstr(app(["openssl"]), display => 1),
+ srctop_file("apps", "server.pem"),
+ (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
+);
+
+use constant {
+ SERVER_CERT_TYPE => 0,
+ CLIENT_CERT_TYPE => 1,
+ NO_CERT_TYPE => 2
+};
+my $testtype;
+
+# Test 1: Just do a verify without cert type
+$proxy->clear();
+$proxy->clientflags("-tls1_2 -cert ".srctop_file("apps", "server.pem"));
+$proxy->serverflags("-verify 4");
+$testtype = NO_CERT_TYPE;
+$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
+plan tests => 4;
+ok(TLSProxy::Message->success, "Simple verify");
+
+# Test 2: Set a bogus server cert type
+$proxy->clear();
+$proxy->serverflags("-enable_server_rpk");
+$testtype = SERVER_CERT_TYPE;
+$proxy->start();
+ok(TLSProxy::Message->fail, "Unsupported server cert type");
+
+# Test 3: Set a bogus client cert type
+$proxy->clear();
+$proxy->serverflags("-enable_client_rpk");
+$testtype = CLIENT_CERT_TYPE;
+$proxy->start();
+ok(TLSProxy::Message->success, "Unsupported client cert type, no verify");
+
+# Test 4: Set a bogus server cert type with verify
+$proxy->clear();
+$testtype = CLIENT_CERT_TYPE;
+$proxy->clientflags("-tls1_2 -cert ".srctop_file("apps", "server.pem"));
+$proxy->serverflags("-verify 4 -enable_client_rpk");
+$proxy->start();
+ok(TLSProxy::Message->fail, "Unsupported client cert type with verify");
+
+sub certtype_filter
+{
+ my $proxy = shift;
+ my $message;
+
+ # We're only interested in the initial ClientHello
+ return if $proxy->flight != 0;
+
+ $message = ${$proxy->message_list}[0];
+
+ # Add unsupported and bogus client and server cert type to the client hello.
+ my $ct = pack "C5", 0x04, 0x01, 0x03, 0x55, 0x66;
+ if ($testtype == CLIENT_CERT_TYPE) {
+ print "SETTING CLIENT CERT TYPE\n";
+ $message->set_extension(TLSProxy::Message::EXT_CLIENT_CERT_TYPE, $ct);
+ }
+ if ($testtype == SERVER_CERT_TYPE) {
+ print "SETTING SERVER CERT TYPE\n";
+ $message->set_extension(TLSProxy::Message::EXT_SERVER_CERT_TYPE, $ct);
+ }
+
+ $message->repack();
+}
diff --git a/test/recipes/90-test_rpk.t b/test/recipes/90-test_rpk.t
new file mode 100644
index 0000000000..2036817199
--- /dev/null
+++ b/test/recipes/90-test_rpk.t
@@ -0,0 +1,23 @@
+#! /usr/bin/env perl
+# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (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
+
+use OpenSSL::Test::Utils;
+use OpenSSL::Test qw/:DEFAULT srctop_dir bldtop_dir/;
+
+BEGIN {
+ setup("test_rpk");
+}
+
+use lib srctop_dir('Configurations');
+use lib bldtop_dir('.');
+
+plan skip_all => "RPK is disabled in this OpenSSL build" if disabled("tls1_2") && disabled("tls1_3");
+
+plan tests => 1;
+
+ok(run(test(["rpktest", srctop_dir("test", "certs")])), "running rpktest");
diff --git a/test/rpktest.c b/test/rpktest.c
new file mode 100644
index 0000000000..89e1fcf638
--- /dev/null
+++ b/test/rpktest.c
@@ -0,0 +1,759 @@
+/*
+ * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+#include <openssl/ssl.h>
+
+#include "helpers/ssltestlib.h"
+#include "internal/dane.h"
+#include "testutil.h"
+
+#undef OSSL_NO_USABLE_TLS1_3
+#if defined(OPENSSL_NO_TLS1_3) \
+ || (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH))
+/*
+ * If we don't have ec or dh then there are no built-in groups that are usable
+ * with TLSv1.3
+ */
+# define OSSL_NO_USABLE_TLS1_3
+#endif
+
+static char *certsdir = NULL;
+static char *rootcert = NULL;
+static char *cert = NULL;
+static char *privkey = NULL;
+static char *cert2 = NULL;
+static char *privkey2 = NULL;
+static char *cert448 = NULL;
+static char *privkey448 = NULL;
+static char *cert25519 = NULL;
+static char *privkey25519 = NULL;
+static OSSL_LIB_CTX *libctx = NULL;
+static OSSL_PROVIDER *defctxnull = NULL;
+
+static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
+static const unsigned char SID_CTX[] = { 'r', 'p', 'k' };
+
+static int rpk_verify_client_cb(int ok, X509_STORE_CTX *ctx)
+{
+ int err = X509_STORE_CTX_get_error(ctx);
+
+ if (X509_STORE_CTX_get0_rpk(ctx) != NULL) {
+ if (err != X509_V_OK) {
+ TEST_info("rpk_verify_client_cb: ok=%d err=%d", ok, err);
+ return 0;
+ }
+ }
+ return 1;
+}
+static int rpk_verify_server_cb(int ok, X509_STORE_CTX *ctx)
+{
+ int err = X509_STORE_CTX_get_error(ctx);
+
+ if (X509_STORE_CTX_get0_rpk(ctx) != NULL) {
+ if (err != X509_V_OK) {
+ TEST_info("rpk_verify_server_cb: ok=%d err=%d", ok, err);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Test dimensions:
+ * (2) server_cert_type RPK off/on for server
+ * (2) client_cert_type RPK off/on for server
+ * (2) server_cert_type RPK off/on for client
+ * (2) client_cert_type RPK off/on for client
+ * (4) RSA vs ECDSA vs Ed25519 vs Ed448 certificates
+ * (2) TLSv1.2 vs TLSv1.3
+ *
+ * Tests:
+ * idx = 0 - is the normal success case, certificate, single peer key
+ * idx = 1 - only a private key
+ * idx = 2 - add client authentication
+ * idx = 3 - add second peer key (rootcert.pem)
+ * idx = 4 - add second peer key (different, RSA or ECDSA)
+ * idx = 5 - reverse peer keys (rootcert.pem, different order)
+ * idx = 6 - reverse peer keys (RSA or ECDSA, different order)
+ * idx = 7 - expects failure due to mismatched key (RSA or ECDSA)
+ * idx = 8 - expects failure due to no configured key on client
+ * idx = 9 - add client authentication (PHA)
+ * idx = 10 - add client authentication (privake key only)
+ * idx = 11 - simple resumption
+ * idx = 12 - simple resumption, no ticket
+ * idx = 13 - resumption with client authentication
+ * idx = 14 - resumption with client authentication, no ticket
+ * idx = 15 - like 0, but use non-default libctx
+ *
+ * 16 * 2 * 4 * 2 * 2 * 2 * 2 = 2048 tests
+ */
+static int test_rpk(int idx)
+{
+# define RPK_TESTS 16
+# define RPK_DIMS (2 * 4 * 2 * 2 * 2 * 2)
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ EVP_PKEY *pkey = NULL, *other_pkey = NULL, *root_pkey = NULL;
+ X509 *x509 = NULL, *other_x509 = NULL, *root_x509 = NULL;
+ int testresult = 0, ret, expected = 1;
+ int client_expected = X509_V_OK;
+ int verify;
+ int tls_version;
+ char *cert_file = NULL;
+ char *privkey_file = NULL;
+ char *other_cert_file = NULL;
+ SSL_SESSION *client_sess = NULL;
+ SSL_SESSION *server_sess = NULL;
+ int idx_server_server_rpk, idx_server_client_rpk;
+ int idx_client_server_rpk, idx_client_client_rpk;
+ int idx_cert, idx_prot;
+ int client_auth = 0;
+ int resumption = 0;
+ long server_verify_result = 0;
+ long client_verify_result = 0;
+ OSSL_LIB_CTX *test_libctx = NULL;
+
+ if (!TEST_int_le(idx, RPK_TESTS * RPK_DIMS))
+ return 0;
+
+ idx_server_server_rpk = idx / (RPK_TESTS * 2 * 4 * 2 * 2 * 2);
+ idx %= RPK_TESTS * 2 * 4 * 2 * 2 * 2;
+ idx_server_client_rpk = idx / (RPK_TESTS * 2 * 4 * 2 * 2);
+ idx %= RPK_TESTS * 2 * 4 * 2 * 2;
+ idx_client_server_rpk = idx / (RPK_TESTS * 2 * 4 * 2);
+ idx %= RPK_TESTS * 2 * 4 * 2;
+ idx_client_client_rpk = idx / (RPK_TESTS * 2 * 4);
+ idx %= RPK_TESTS * 2 * 4;
+ idx_cert = idx / (RPK_TESTS * 2);
+ idx %= RPK_TESTS * 2;
+ idx_prot = idx / RPK_TESTS;
+ idx %= RPK_TESTS;
+
+ /* Load "root" cert/pubkey */
+ root_x509 = load_cert_pem(rootcert, NULL);
+ if (!TEST_ptr(root_x509))
+ goto end;
+ root_pkey = X509_get0_pubkey(root_x509);
+ if (!TEST_ptr(root_pkey))
+ goto end;
+
+ switch (idx_cert) {
+ case 0:
+ /* use RSA */
+ cert_file = cert;
+ privkey_file = privkey;
+ other_cert_file = cert2;
+ break;
+#ifndef OPENSSL_NO_ECDSA
+ case 1:
+ /* use ECDSA */
+ cert_file = cert2;
+ privkey_file = privkey2;
+ other_cert_file = cert;
+ break;
+ case 2:
+ /* use Ed448 */
+ cert_file = cert448;
+ privkey_file = privkey448;
+ other_cert_file = cert;
+ break;
+ case 3:
+ /* use Ed25519 */
+ cert_file = cert25519;
+ privkey_file = privkey25519;
+ other_cert_file = cert;
+ break;
+#endif
+ default:
+ testresult = TEST_skip("EDCSA disabled");
+ goto end;
+ }
+ /* Load primary cert */
+ x509 = load_cert_pem(cert_file, NULL);
+ if (!TEST_ptr(x509))
+ goto end;
+ pkey = X509_get0_pubkey(x509);
+ /* load other cert */
+ other_x509 = load_cert_pem(other_cert_file, NULL);
+ if (!TEST_ptr(other_x509))
+ goto end;
+ other_pkey = X509_get0_pubkey(other_x509);
+#ifdef OPENSSL_NO_ECDSA
+ /* Can't get other_key if it's ECDSA */
+ if (other_pkey == NULL && idx_cert == 0
+ && (idx == 4 || idx == 6 || idx == 7)) {
+ testresult = TEST_skip("EDCSA disabled");
+ goto end;
+ }
+#endif
+
+ switch (idx_prot) {
+ case 0:
+#ifdef OSSL_NO_USABLE_TLS1_3
+ testresult = TEST_skip("TLSv1.3 disabled");
+ goto end;
+#else
+ tls_version = TLS1_3_VERSION;
+ break;
+#endif
+ case 1:
+#ifdef OPENSSL_NO_TLS1_2
+ testresult = TEST_skip("TLSv1.2 disabled");
+ goto end;
+#else
+ tls_version = TLS1_2_VERSION;
+ break;
+#endif
+ default:
+ goto end;
+ }
+
+ if (idx == 15) {
+ test_libctx = libctx;
+ defctxnull = OSSL_PROVIDER_load(NULL, "null");
+ if (!TEST_ptr(defctxnull))
+ goto end;
+ }
+ if (!TEST_true(create_ssl_ctx_pair(test_libctx,
+ TLS_server_method(), TLS_client_method(),
+ tls_version, tls_version,
+ &sctx, &cctx, NULL, NULL)))
+ goto end;
+
+ if (idx_server_server_rpk)
+ if (!TEST_true(SSL_CTX_set1_server_cert_type(sctx, cert_type_rpk, sizeof(cert_type_rpk))))
+ goto end;
+ if (idx_server_client_rpk)
+ if (!TEST_true(SSL_CTX_set1_client_cert_type(sctx, cert_type_rpk, sizeof(cert_type_rpk))))
+ goto end;
+ if (idx_client_server_rpk)
+ if (!TEST_true(SSL_CTX_set1_server_cert_type(cctx, cert_type_rpk, sizeof(cert_type_rpk))))
+ goto end;
+ if (idx_client_client_rpk)
+ if (!TEST_true(SSL_CTX_set1_client_cert_type(cctx, cert_type_rpk, sizeof(cert_type_rpk))))
+ goto end;
+ if (!TEST_true(SSL_CTX_set_session_id_context(sctx, SID_CTX, sizeof(SID_CTX))))
+ goto end;
+ if (!TEST_true(SSL_CTX_set_session_id_context(cctx, SID_CTX, sizeof(SID_CTX))))
+ goto end;
+
+ if (!TEST_int_gt(SSL_CTX_dane_enable(sctx), 0))
+ goto end;
+ if (!TEST_int_gt(SSL_CTX_dane_enable(cctx), 0))
+ goto end;
+
+ /* NEW */
+ SSL_CTX_set_verify(cctx, SSL_VERIFY_PEER, rpk_verify_client_cb);
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL)))
+ goto end;
+
+ if (!TEST_int_gt(SSL_dane_enable(serverssl, NULL), 0))
+ goto end;
+ if (!TEST_int_gt(SSL_dane_enable(clientssl, "example.com"), 0))
+ goto end;
+
+ /* Set private key and certificate */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(serverssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ /* Only a private key */
+ if (idx == 1) {
+ if (idx_server_server_rpk == 0 || idx_client_server_rpk == 0)
+ expected = 0;
+ } else {
+ /* Add certificate */
+ if (!TEST_int_eq(SSL_use_certificate_file(serverssl, cert_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_check_private_key(serverssl), 1))
+ goto end;
+ }
+
+ switch (idx) {
+ default:
+ if (!TEST_true(idx < RPK_TESTS))
+ goto end;
+ break;
+ case 0:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ break;
+ case 1:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ break;
+ case 2:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
+ goto end;
+ /* Use the same key for client auth */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
+ goto end;
+ SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
+ client_auth = 1;
+ break;
+ case 3:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, root_pkey)))
+ goto end;
+ break;
+ case 4:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, other_pkey)))
+ goto end;
+ break;
+ case 5:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, root_pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ break;
+ case 6:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, other_pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ break;
+ case 7:
+ if (idx_server_server_rpk == 1 && idx_client_server_rpk == 1)
+ client_expected = -1;
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, other_pkey)))
+ goto end;
+ client_verify_result = X509_V_ERR_DANE_NO_MATCH;
+ break;
+ case 8:
+ if (idx_server_server_rpk == 1 && idx_client_server_rpk == 1)
+ client_expected = -1;
+ /* no peer keys */
+ client_verify_result = X509_V_ERR_RPK_UNTRUSTED;
+ break;
+ case 9:
+ if (tls_version != TLS1_3_VERSION) {
+ testresult = TEST_skip("PHA requires TLSv1.3");
+ goto end;
+ }
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
+ goto end;
+ /* Use the same key for client auth */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
+ goto end;
+ SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_POST_HANDSHAKE, rpk_verify_server_cb);
+ SSL_set_post_handshake_auth(clientssl, 1);
+ client_auth = 1;
+ break;
+ case 10:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
+ goto end;
+ /* Use the same key for client auth */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ /* Since there's no cert, this is expected to fail without RPK support */
+ if (!idx_server_client_rpk || !idx_client_client_rpk)
+ expected = 0;
+ SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
+ client_auth = 1;
+ break;
+ case 11:
+ if (!idx_server_server_rpk || !idx_client_server_rpk) {
+ testresult = TEST_skip("Only testing resumption with server RPK");
+ goto end;
+ }
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ resumption = 1;
+ break;
+ case 12:
+ if (!idx_server_server_rpk || !idx_client_server_rpk) {
+ testresult = TEST_skip("Only testing resumption with server RPK");
+ goto end;
+ }
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ SSL_set_options(serverssl, SSL_OP_NO_TICKET);
+ SSL_set_options(clientssl, SSL_OP_NO_TICKET);
+ resumption = 1;
+ break;
+ case 13:
+ if (!idx_server_server_rpk || !idx_client_server_rpk) {
+ testresult = TEST_skip("Only testing resumption with server RPK");
+ goto end;
+ }
+ if (!idx_server_client_rpk || !idx_client_client_rpk) {
+ testresult = TEST_skip("Only testing client authentication resumption with client RPK");
+ goto end;
+ }
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
+ goto end;
+ /* Use the same key for client auth */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
+ goto end;
+ SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
+ client_auth = 1;
+ resumption = 1;
+ break;
+ case 14:
+ if (!idx_server_server_rpk || !idx_client_server_rpk) {
+ testresult = TEST_skip("Only testing resumption with server RPK");
+ goto end;
+ }
+ if (!idx_server_client_rpk || !idx_client_client_rpk) {
+ testresult = TEST_skip("Only testing client authentication resumption with client RPK");
+ goto end;
+ }
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(serverssl, pkey)))
+ goto end;
+ /* Use the same key for client auth */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
+ goto end;
+ SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
+ SSL_set_options(serverssl, SSL_OP_NO_TICKET);
+ SSL_set_options(clientssl, SSL_OP_NO_TICKET);
+ client_auth = 1;
+ resumption = 1;
+ break;
+ case 15:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, pkey)))
+ goto end;
+ break;
+ }
+
+ ret = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE);
+ if (!TEST_int_eq(expected, ret))
+ goto end;
+
+ /* Make sure client gets RPK or certificate as configured */
+ if (expected == 1) {
+ if (idx_server_server_rpk && idx_client_server_rpk) {
+ if (!TEST_long_eq(SSL_get_verify_result(clientssl), client_verify_result))
+ goto end;
+ if (!TEST_ptr(SSL_get0_peer_rpk(clientssl)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(serverssl), TLSEXT_cert_type_rpk))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(clientssl), TLSEXT_cert_type_rpk))
+ goto end;
+ } else {
+ if (!TEST_ptr(SSL_get0_peer_certificate(clientssl)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(serverssl), TLSEXT_cert_type_x509))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(clientssl), TLSEXT_cert_type_x509))
+ goto end;
+ }
+ }
+
+ if (idx == 9) {
+ /* Make PHA happen... */
+ if (!TEST_true(SSL_verify_client_post_handshake(serverssl)))
+ goto end;
+ if (!TEST_true(SSL_do_handshake(serverssl)))
+ goto end;
+ if (!TEST_int_le(SSL_read(clientssl, NULL, 0), 0))
+ goto end;
+ if (!TEST_int_le(SSL_read(serverssl, NULL, 0), 0))
+ goto end;
+ }
+
+ /* Make sure server gets an RPK or certificate as configured */
+ if (client_auth) {
+ if (idx_server_client_rpk && idx_client_client_rpk) {
+ if (!TEST_long_eq(SSL_get_verify_result(serverssl), server_verify_result))
+ goto end;
+ if (!TEST_ptr(SSL_get0_peer_rpk(serverssl)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(serverssl), TLSEXT_cert_type_rpk))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(clientssl), TLSEXT_cert_type_rpk))
+ goto end;
+ } else {
+ /* only if connection is expected to succeed */
+ if (expected == 1 && !TEST_ptr(SSL_get0_peer_certificate(serverssl)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(serverssl), TLSEXT_cert_type_x509))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(clientssl), TLSEXT_cert_type_x509))
+ goto end;
+ }
+ }
+
+ if (resumption) {
+ EVP_PKEY *client_pkey = NULL;
+ EVP_PKEY *server_pkey = NULL;
+
+ if (!TEST_ptr((client_sess = SSL_get1_session(clientssl)))
+ || !TEST_ptr((client_pkey = SSL_SESSION_get0_peer_rpk(client_sess))))
+ goto end;
+ if (client_auth) {
+ if (!TEST_ptr((server_sess = SSL_get1_session(serverssl)))
+ || !TEST_ptr((server_pkey = SSL_SESSION_get0_peer_rpk(server_sess))))
+ goto end;
+ }
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+ SSL_free(clientssl);
+ SSL_free(serverssl);
+ serverssl = clientssl = NULL;
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL))
+ || !TEST_true(SSL_set_session(clientssl, client_sess)))
+ goto end;
+
+ /* Set private key (and maybe certificate) */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(serverssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_use_certificate_file(serverssl, cert_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_check_private_key(serverssl), 1))
+ goto end;
+ if (!TEST_int_gt(SSL_dane_enable(serverssl, "example.com"), 0))
+ goto end;
+ if (!TEST_int_gt(SSL_dane_enable(clientssl, "example.com"), 0))
+ goto end;
+
+ switch (idx) {
+ default:
+ break;
+ case 11:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, client_pkey)))
+ goto end;
+ break;
+ case 12:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, client_pkey)))
+ goto end;
+ SSL_set_options(clientssl, SSL_OP_NO_TICKET);
+ SSL_set_options(serverssl, SSL_OP_NO_TICKET);
+ break;
+ case 13:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, client_pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(serverssl, server_pkey)))
+ goto end;
+ /* Use the same key for client auth */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
+ goto end;
+ SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
+ break;
+ case 14:
+ if (!TEST_true(SSL_add_expected_rpk(clientssl, client_pkey)))
+ goto end;
+ if (!TEST_true(SSL_add_expected_rpk(serverssl, server_pkey)))
+ goto end;
+ /* Use the same key for client auth */
+ if (!TEST_int_eq(SSL_use_PrivateKey_file(clientssl, privkey_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_use_certificate_file(clientssl, cert_file, SSL_FILETYPE_PEM), 1))
+ goto end;
+ if (!TEST_int_eq(SSL_check_private_key(clientssl), 1))
+ goto end;
+ SSL_set_verify(serverssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, rpk_verify_server_cb);
+ SSL_set_options(serverssl, SSL_OP_NO_TICKET);
+ SSL_set_options(clientssl, SSL_OP_NO_TICKET);
+ break;
+ }
+
+ ret = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE);
+ if (!TEST_int_eq(expected, ret))
+ goto end;
+ verify = SSL_get_verify_result(clientssl);
+ if (!TEST_int_eq(client_expected, verify))
+ goto end;
+ if (!TEST_true(SSL_session_reused(clientssl)))
+ goto end;
+
+ if (!TEST_ptr(SSL_get0_peer_rpk(clientssl)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(serverssl), TLSEXT_cert_type_rpk))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_server_cert_type(clientssl), TLSEXT_cert_type_rpk))
+ goto end;
+
+ if (client_auth) {
+ if (!TEST_ptr(SSL_get0_peer_rpk(serverssl)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(serverssl), TLSEXT_cert_type_rpk))
+ goto end;
+ if (!TEST_int_eq(SSL_get_negotiated_client_cert_type(clientssl), TLSEXT_cert_type_rpk))
+ goto end;
+ }
+ }
+
+ testresult = 1;
+
+ end:
+ OSSL_PROVIDER_unload(defctxnull);
+ defctxnull = NULL;
+ SSL_SESSION_free(client_sess);
+ SSL_SESSION_free(server_sess);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ X509_free(x509);
+ X509_free(other_x509);
+ X509_free(root_x509);
+
+ if (testresult == 0) {
+ TEST_info("idx_ss_rpk=%d, idx_sc_rpk=%d, idx_cs_rpk=%d, idx_cc_rpk=%d, idx_cert=%d, idx_prot=%d, idx=%d",
+ idx_server_server_rpk, idx_server_client_rpk,
+ idx_client_server_rpk, idx_client_client_rpk,
+ idx_cert, idx_prot, idx);
+ }
+ return testresult;
+}
+
+static int test_rpk_api(void)
+{
+ int ret = 0;
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ unsigned char cert_type_dups[] = { TLSEXT_cert_type_rpk,
+ TLSEXT_cert_type_x509,
+ TLSEXT_cert_type_x509 };
+ unsigned char cert_type_bad[] = { 0xFF };
+ unsigned char cert_type_extra[] = { TLSEXT_cert_type_rpk,
+ TLSEXT_cert_type_x509,
+ 0xFF };
+ unsigned char cert_type_unsup[] = { TLSEXT_cert_type_pgp,
+ TLSEXT_cert_type_1609dot2 };
+ unsigned char cert_type_just_x509[] = { TLSEXT_cert_type_x509 };
+ unsigned char cert_type_just_rpk[] = { TLSEXT_cert_type_rpk };
+
+ if (!TEST_true(create_ssl_ctx_pair(NULL,
+ TLS_server_method(), TLS_client_method(),
+ TLS1_2_VERSION, TLS1_2_VERSION,
+ &sctx, &cctx, NULL, NULL)))
+ goto end;
+
+ if (!TEST_false(SSL_CTX_set1_server_cert_type(sctx, cert_type_dups, sizeof(cert_type_dups))))
+ goto end;
+
+ if (!TEST_false(SSL_CTX_set1_server_cert_type(sctx, cert_type_bad, sizeof(cert_type_bad))))
+ goto end;
+
+ if (!TEST_false(SSL_CTX_set1_server_cert_type(sctx, cert_type_extra, sizeof(cert_type_extra))))
+ goto end;
+
+ if (!TEST_false(SSL_CTX_set1_server_cert_type(sctx, cert_type_unsup, sizeof(cert_type_unsup))))
+ goto end;
+
+ if (!TEST_true(SSL_CTX_set1_server_cert_type(sctx, cert_type_just_x509, sizeof(cert_type_just_x509))))
+ goto end;
+
+ if (!TEST_true(SSL_CTX_set1_server_cert_type(sctx, cert_type_just_rpk, sizeof(cert_type_just_rpk))))
+ goto end;
+
+ ret = 1;
+ end:
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ return ret;
+}
+OPT_TEST_DECLARE_USAGE("certdir\n")
+
+int setup_tests(void)
+{
+ if (!test_skip_common_options()) {
+ TEST_error("Error parsing test options\n");
+ return 0;
+ }
+
+ if (!TEST_ptr(certsdir = test_get_argument(0)))
+ return 0;
+
+ rootcert = test_mk_file_path(certsdir, "rootcert.pem");
+ if (rootcert == NULL)
+ goto err;
+
+ cert = test_mk_file_path(certsdir, "servercert.pem");
+ if (cert == NULL)
+ goto err;
+
+ privkey = test_mk_file_path(certsdir, "serverkey.pem");
+ if (privkey == NULL)
+ goto err;
+
+ cert2 = test_mk_file_path(certsdir, "server-ecdsa-cert.pem");
+ if (cert2 == NULL)
+ goto err;
+
+ privkey2 = test_mk_file_path(certsdir, "server-ecdsa-key.pem");
+ if (privkey2 == NULL)
+ goto err;
+
+ cert448 = test_mk_file_path(certsdir, "server-ed448-cert.pem");
+ if (cert2 == NULL)
+ goto err;
+
+ privkey448 = test_mk_file_path(certsdir, "server-ed448-key.pem");
+ if (privkey2 == NULL)
+ goto err;
+
+ cert25519 = test_mk_file_path(certsdir, "server-ed25519-cert.pem");
+ if (cert2 == NULL)
+ goto err;
+
+ privkey25519 = test_mk_file_path(certsdir, "server-ed25519-key.pem");
+ if (privkey2 == NULL)
+ goto err;
+
+ libctx = OSSL_LIB_CTX_new();
+ if (libctx == NULL)
+ goto err;
+
+ ADD_TEST(test_rpk_api);
+ ADD_ALL_TESTS(test_rpk, RPK_TESTS * RPK_DIMS);
+ return 1;
+
+ err:
+ return 0;
+}
+
+void cleanup_tests(void)
+{
+ OPENSSL_free(rootcert);
+ OPENSSL_free(cert);
+ OPENSSL_free(privkey);
+ OPENSSL_free(cert2);
+ OPENSSL_free(privkey2);
+ OPENSSL_free(cert448);
+ OPENSSL_free(privkey448);
+ OPENSSL_free(cert25519);
+ OPENSSL_free(privkey25519);
+ OSSL_LIB_CTX_free(libctx);
+ }
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 9cf4cf7d35..ae4977bfde 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -8090,7 +8090,7 @@ static int test_ticket_callbacks(int tst)
gen_tick_called = dec_tick_called = tick_key_cb_called = 0;
/* Which tests the ticket key callback should request renewal for */
-
+
if (tst == 10 || tst == 11 || tst == 16 || tst == 17)
tick_key_renew = 1;
else if (tst == 12 || tst == 13 || tst == 18 || tst == 19)
@@ -9558,9 +9558,12 @@ static int create_cert_key(int idx, char *certfilename, char *privkeyfilename)
* correctly establish a TLS (1.3) connection.
* Test 0: Signature algorithm with built-in hashing functionality: "xorhmacsig"
* Test 1: Signature algorithm using external SHA2 hashing: "xorhmacsha2sig"
+ * Test 2: Test 0 using RPK
+ * Test 3: Test 1 using RPK
*/
static int test_pluggable_signature(int idx)
{
+ static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 };
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
@@ -9568,10 +9571,12 @@ static int test_pluggable_signature(int idx)
OSSL_PROVIDER *defaultprov = OSSL_PROVIDER_load(libctx, "default");
char *certfilename = "tls-prov-cert.pem";
char *privkeyfilename = "tls-prov-key.pem";
+ int sigidx = idx % 2;
+ int rpkidx = idx / 2;
/* create key and certificate for the different algorithm types */
if (!TEST_ptr(tlsprov)
- || !TEST_true(create_cert_key(idx, certfilename, privkeyfilename)))
+ || !TEST_true(create_cert_key(sigidx, certfilename, privkeyfilename)))
goto end;
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
@@ -9583,6 +9588,13 @@ static int test_pluggable_signature(int idx)
NULL, NULL)))
goto end;
+ /* Enable RPK for server cert */
+ if (rpkidx) {
+ if (!TEST_true(SSL_set1_server_cert_type(serverssl, cert_type_rpk, sizeof(cert_type_rpk)))
+ || !TEST_true(SSL_set1_server_cert_type(clientssl, cert_type_rpk, sizeof(cert_type_rpk))))
+ goto end;
+ }
+
/* This is necessary to pass minimal setup w/o other groups configured */
if (!TEST_true(SSL_set1_groups_list(serverssl, "xorgroup"))
|| !TEST_true(SSL_set1_groups_list(clientssl, "xorgroup")))
@@ -9596,6 +9608,10 @@ static int test_pluggable_signature(int idx)
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;
+ /* If using RPK, make sure we got one */
+ if (rpkidx && !TEST_long_eq(SSL_get_verify_result(clientssl), X509_V_ERR_RPK_UNTRUSTED))
+ goto end;
+
testresult = 1;
end:
@@ -11083,7 +11099,7 @@ int setup_tests(void)
#endif
#ifndef OPENSSL_NO_TLS1_3
ADD_ALL_TESTS(test_pluggable_group, 2);
- ADD_ALL_TESTS(test_pluggable_signature, 2);
+ ADD_ALL_TESTS(test_pluggable_signature, 4);
#endif
#ifndef OPENSSL_NO_TLS1_2
ADD_TEST(test_ssl_dup);