summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2016-08-30 14:20:18 +0100
committerMatt Caswell <matt@openssl.org>2016-08-30 14:49:10 +0100
commit767ccc3b77cde82c46ab4af541663f6c80e538d3 (patch)
tree1ef22091fd32466f6f6f9fd6df84a5f99079513f
parentf046afb0663fc4514f7fc5d1724439caa6858932 (diff)
downloadopenssl-new-767ccc3b77cde82c46ab4af541663f6c80e538d3.tar.gz
Add some CertStatus tests
The previous commit revealed a long standing problem where CertStatus processing was broken in DTLS. This would have been revealed by better testing - so add some! Reviewed-by: Rich Salz <rsalz@openssl.org>
-rw-r--r--test/handshake_helper.c42
-rw-r--r--test/recipes/80-test_ssl_new.t5
-rw-r--r--test/ssl-tests/15-certstatus.conf62
-rw-r--r--test/ssl-tests/15-certstatus.conf.in45
-rw-r--r--test/ssl-tests/16-certstatus.conf0
-rw-r--r--test/ssl-tests/16-dtls-certstatus.conf62
-rw-r--r--test/ssl-tests/16-dtls-certstatus.conf.in45
-rw-r--r--test/ssl_test_ctx.c29
-rw-r--r--test/ssl_test_ctx.h9
-rw-r--r--test/ssl_test_ctx_test.c6
10 files changed, 303 insertions, 2 deletions
diff --git a/test/handshake_helper.c b/test/handshake_helper.c
index 409f16cf08..90e18fcaaa 100644
--- a/test/handshake_helper.c
+++ b/test/handshake_helper.c
@@ -144,6 +144,38 @@ static int servername_reject_cb(SSL *s, int *ad, void *arg)
return select_server_ctx(s, arg, 0);
}
+static unsigned char dummy_ocsp_resp_good_val = 0xff;
+static unsigned char dummy_ocsp_resp_bad_val = 0xfe;
+
+static int server_ocsp_cb(SSL *s, void *arg)
+{
+ unsigned char *resp;
+
+ resp = OPENSSL_malloc(1);
+ if (resp == NULL)
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+ /*
+ * For the purposes of testing we just send back a dummy OCSP response
+ */
+ *resp = *(unsigned char *)arg;
+ if (!SSL_set_tlsext_status_ocsp_resp(s, resp, 1))
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+static int client_ocsp_cb(SSL *s, void *arg)
+{
+ const unsigned char *resp;
+ int len;
+
+ len = SSL_get_tlsext_status_ocsp_resp(s, &resp);
+ if (len != 1 || *resp != dummy_ocsp_resp_good_val)
+ return 0;
+
+ return 1;
+}
+
static int verify_reject_cb(X509_STORE_CTX *ctx, void *arg) {
X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
return 0;
@@ -319,6 +351,16 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
break;
}
+ if (extra->server.cert_status != SSL_TEST_CERT_STATUS_NONE) {
+ SSL_CTX_set_tlsext_status_type(client_ctx, TLSEXT_STATUSTYPE_ocsp);
+ SSL_CTX_set_tlsext_status_cb(client_ctx, client_ocsp_cb);
+ SSL_CTX_set_tlsext_status_arg(client_ctx, NULL);
+ SSL_CTX_set_tlsext_status_cb(server_ctx, server_ocsp_cb);
+ SSL_CTX_set_tlsext_status_arg(server_ctx,
+ ((extra->server.cert_status == SSL_TEST_CERT_STATUS_GOOD_RESPONSE)
+ ? &dummy_ocsp_resp_good_val : &dummy_ocsp_resp_bad_val));
+ }
+
/*
* The initial_ctx/session_ctx always handles the encrypt/decrypt of the
* session ticket. This ticket_key callback is assigned to the second
diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t
index 175b3b2ad0..46c2f4216c 100644
--- a/test/recipes/80-test_ssl_new.t
+++ b/test/recipes/80-test_ssl_new.t
@@ -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 => 14; # = scalar @conf_srcs
+plan tests => 16; # = scalar @conf_srcs
# Some test results depend on the configuration of enabled protocols. We only
# verify generated sources in the default configuration.
@@ -69,7 +69,8 @@ my %skip = (
# special-casing for.
# We should review this once we have TLS 1.3.
"13-fragmentation.conf" => disabled("tls1_2"),
- "14-curves.conf" => disabled("tls1_2") || $no_ec || $no_ec2m
+ "14-curves.conf" => disabled("tls1_2") || $no_ec || $no_ec2m,
+ "16-dtls-certstatus.conf" => $no_dtls
);
foreach my $conf (@conf_files) {
diff --git a/test/ssl-tests/15-certstatus.conf b/test/ssl-tests/15-certstatus.conf
new file mode 100644
index 0000000000..bf6c41cda2
--- /dev/null
+++ b/test/ssl-tests/15-certstatus.conf
@@ -0,0 +1,62 @@
+# Generated with generate_ssl_tests.pl
+
+num_tests = 2
+
+test-0 = 0-certstatus-good
+test-1 = 1-certstatus-bad
+# ===========================================================
+
+[0-certstatus-good]
+ssl_conf = 0-certstatus-good-ssl
+
+[0-certstatus-good-ssl]
+server = 0-certstatus-good-server
+client = 0-certstatus-good-client
+
+[0-certstatus-good-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[0-certstatus-good-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-0]
+ExpectedResult = Success
+Method = TLS
+server = 0-certstatus-good-server-extra
+
+[0-certstatus-good-server-extra]
+CertStatus = GoodResponse
+
+
+# ===========================================================
+
+[1-certstatus-bad]
+ssl_conf = 1-certstatus-bad-ssl
+
+[1-certstatus-bad-ssl]
+server = 1-certstatus-bad-server
+client = 1-certstatus-bad-client
+
+[1-certstatus-bad-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[1-certstatus-bad-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-1]
+ExpectedResult = ClientFail
+Method = TLS
+server = 1-certstatus-bad-server-extra
+
+[1-certstatus-bad-server-extra]
+CertStatus = BadResponse
+
+
diff --git a/test/ssl-tests/15-certstatus.conf.in b/test/ssl-tests/15-certstatus.conf.in
new file mode 100644
index 0000000000..074602dc35
--- /dev/null
+++ b/test/ssl-tests/15-certstatus.conf.in
@@ -0,0 +1,45 @@
+# -*- mode: perl; -*-
+# Copyright 2016-2016 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 CertStatus messages
+
+use strict;
+use warnings;
+
+package ssltests;
+
+
+our @tests = (
+ {
+ name => "certstatus-good",
+ server => {
+ extra => {
+ "CertStatus" => "GoodResponse",
+ },
+ },
+ client => {},
+ test => {
+ "Method" => "TLS",
+ "ExpectedResult" => "Success"
+ }
+ },
+ {
+ name => "certstatus-bad",
+ server => {
+ extra => {
+ "CertStatus" => "BadResponse",
+ },
+ },
+ client => {},
+ test => {
+ "Method" => "TLS",
+ "ExpectedResult" => "ClientFail"
+ }
+ },
+);
diff --git a/test/ssl-tests/16-certstatus.conf b/test/ssl-tests/16-certstatus.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/ssl-tests/16-certstatus.conf
diff --git a/test/ssl-tests/16-dtls-certstatus.conf b/test/ssl-tests/16-dtls-certstatus.conf
new file mode 100644
index 0000000000..a561803a55
--- /dev/null
+++ b/test/ssl-tests/16-dtls-certstatus.conf
@@ -0,0 +1,62 @@
+# Generated with generate_ssl_tests.pl
+
+num_tests = 2
+
+test-0 = 0-certstatus-good
+test-1 = 1-certstatus-bad
+# ===========================================================
+
+[0-certstatus-good]
+ssl_conf = 0-certstatus-good-ssl
+
+[0-certstatus-good-ssl]
+server = 0-certstatus-good-server
+client = 0-certstatus-good-client
+
+[0-certstatus-good-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[0-certstatus-good-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-0]
+ExpectedResult = Success
+Method = DTLS
+server = 0-certstatus-good-server-extra
+
+[0-certstatus-good-server-extra]
+CertStatus = GoodResponse
+
+
+# ===========================================================
+
+[1-certstatus-bad]
+ssl_conf = 1-certstatus-bad-ssl
+
+[1-certstatus-bad-ssl]
+server = 1-certstatus-bad-server
+client = 1-certstatus-bad-client
+
+[1-certstatus-bad-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[1-certstatus-bad-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-1]
+ExpectedResult = ClientFail
+Method = DTLS
+server = 1-certstatus-bad-server-extra
+
+[1-certstatus-bad-server-extra]
+CertStatus = BadResponse
+
+
diff --git a/test/ssl-tests/16-dtls-certstatus.conf.in b/test/ssl-tests/16-dtls-certstatus.conf.in
new file mode 100644
index 0000000000..7280029e65
--- /dev/null
+++ b/test/ssl-tests/16-dtls-certstatus.conf.in
@@ -0,0 +1,45 @@
+# -*- mode: perl; -*-
+# Copyright 2016-2016 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 DTLS CertStatus messages
+
+use strict;
+use warnings;
+
+package ssltests;
+
+
+our @tests = (
+ {
+ name => "certstatus-good",
+ server => {
+ extra => {
+ "CertStatus" => "GoodResponse",
+ },
+ },
+ client => {},
+ test => {
+ "Method" => "DTLS",
+ "ExpectedResult" => "Success"
+ }
+ },
+ {
+ name => "certstatus-bad",
+ server => {
+ extra => {
+ "CertStatus" => "BadResponse",
+ },
+ },
+ client => {},
+ test => {
+ "Method" => "DTLS",
+ "ExpectedResult" => "ClientFail"
+ }
+ },
+);
diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c
index ac90f199b2..ee2e8a1088 100644
--- a/test/ssl_test_ctx.c
+++ b/test/ssl_test_ctx.c
@@ -390,6 +390,34 @@ const char *ssl_ct_validation_name(ssl_ct_validation_t mode)
IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, resumption_expected)
IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, broken_session_ticket)
+/**************/
+/* CertStatus */
+/**************/
+
+static const test_enum ssl_certstatus[] = {
+ {"None", SSL_TEST_CERT_STATUS_NONE},
+ {"GoodResponse", SSL_TEST_CERT_STATUS_GOOD_RESPONSE},
+ {"BadResponse", SSL_TEST_CERT_STATUS_BAD_RESPONSE}
+};
+
+__owur static int parse_certstatus(SSL_TEST_SERVER_CONF *server_conf,
+ const char *value)
+{
+ int ret_value;
+ if (!parse_enum(ssl_certstatus, OSSL_NELEM(ssl_certstatus), &ret_value,
+ value)) {
+ return 0;
+ }
+ server_conf->cert_status = ret_value;
+ return 1;
+}
+
+const char *ssl_certstatus_name(ssl_cert_status_t cert_status)
+{
+ return enum_name(ssl_certstatus,
+ OSSL_NELEM(ssl_certstatus), cert_status);
+}
+
/***********************/
/* ApplicationData */
/***********************/
@@ -453,6 +481,7 @@ static const ssl_test_server_option ssl_test_server_options[] = {
{ "NPNProtocols", &parse_server_npn_protocols },
{ "ALPNProtocols", &parse_server_alpn_protocols },
{ "BrokenSessionTicket", &parse_server_broken_session_ticket },
+ { "CertStatus", &parse_certstatus },
};
/*
diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h
index 11b6c33321..c8c66d6d70 100644
--- a/test/ssl_test_ctx.h
+++ b/test/ssl_test_ctx.h
@@ -65,6 +65,12 @@ typedef enum {
SSL_TEST_CT_VALIDATION_PERMISSIVE,
SSL_TEST_CT_VALIDATION_STRICT
} ssl_ct_validation_t;
+
+typedef enum {
+ SSL_TEST_CERT_STATUS_NONE = 0, /* Default */
+ SSL_TEST_CERT_STATUS_GOOD_RESPONSE,
+ SSL_TEST_CERT_STATUS_BAD_RESPONSE
+} ssl_cert_status_t;
/*
* Server/client settings that aren't supported by the SSL CONF library,
* such as callbacks.
@@ -88,6 +94,8 @@ typedef struct {
char *alpn_protocols;
/* Whether to set a broken session ticket callback. */
int broken_session_ticket;
+ /* Should we send a CertStatus message? */
+ ssl_cert_status_t cert_status;
} SSL_TEST_SERVER_CONF;
typedef struct {
@@ -164,6 +172,7 @@ const char *ssl_session_ticket_name(ssl_session_ticket_t server);
const char *ssl_test_method_name(ssl_test_method_t method);
const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode);
const char *ssl_ct_validation_name(ssl_ct_validation_t mode);
+const char *ssl_certstatus_name(ssl_cert_status_t cert_status);
/*
* Load the test case context from |conf|.
diff --git a/test/ssl_test_ctx_test.c b/test/ssl_test_ctx_test.c
index b54d7eab36..0f321c60f3 100644
--- a/test/ssl_test_ctx_test.c
+++ b/test/ssl_test_ctx_test.c
@@ -83,6 +83,12 @@ static int SSL_TEST_SERVER_CONF_equal(SSL_TEST_SERVER_CONF *server,
server->broken_session_ticket, server2->broken_session_ticket);
return 0;
}
+ if (server->cert_status != server2->cert_status) {
+ fprintf(stderr, "CertStatus mismatch: %s vs %s.\n",
+ ssl_certstatus_name(server->cert_status),
+ ssl_certstatus_name(server2->cert_status));
+ return 0;
+ }
return 1;
}