* Test 3: TLSv1.3, pending NewSessionTicket messages
* Test 4: TLSv1.3, server continues to read/write after client shutdown, server
* sends key update, client reads it
- * Test 5: TLSv1.3, server continues to read/write after client shutdown, client
+ * Test 5: TLSv1.3, server continues to read/write after client shutdown, server
+ * sends CertificateRequest, client reads and ignores it
+ * Test 6: TLSv1.3, server continues to read/write after client shutdown, client
* doesn't read it
*/
static int test_shutdown(int tst)
TLS1_VERSION,
(tst <= 1) ? TLS1_2_VERSION
: TLS1_3_VERSION,
- &sctx, &cctx, cert, privkey))
- || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ &sctx, &cctx, cert, privkey)))
+ goto end;
+
+ if (tst == 5)
+ SSL_CTX_set_post_handshake_auth(cctx, 1);
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;
*/
|| !TEST_true(SSL_write(serverssl, msg, sizeof(msg))))
goto end;
- if (tst == 4 &&
- (!TEST_true(SSL_key_update(serverssl, SSL_KEY_UPDATE_REQUESTED))
- || !TEST_true(SSL_write(serverssl, msg, sizeof(msg)))))
+ if (tst == 4
+ && !TEST_true(SSL_key_update(serverssl,
+ SSL_KEY_UPDATE_REQUESTED)))
+ goto end;
+ if (tst == 5) {
+ SSL_set_verify(serverssl, SSL_VERIFY_PEER, NULL);
+ if (!TEST_true(SSL_verify_client_post_handshake(serverssl)))
+ goto end;
+ }
+ if ((tst == 4 || tst == 5)
+ && !TEST_true(SSL_write(serverssl, msg, sizeof(msg))))
goto end;
if (!TEST_int_eq(SSL_shutdown(serverssl), 1))
goto end;
- if (tst == 4) {
+ if (tst == 4 || tst == 5) {
/* Should still be able to read data from server */
if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf),
&readbytes))
|| !TEST_true(SSL_SESSION_is_resumable(sess))
|| !TEST_int_eq(SSL_shutdown(serverssl), 1))
goto end;
- } else if (tst == 4) {
+ } else if (tst == 4 || tst == 5) {
/*
* In this test the client has sent close_notify and it has been
* received by the server which has responded with a close_notify. The
goto end;
} else {
/*
- * tst == 5
+ * tst == 6
*
* The client has sent close_notify and is expecting a close_notify
* back, but instead there is application data first. The shutdown
return testresult;
}
+#if !defined(OPENSSL_NO_TLS1_2) || !defined(OPENSSL_NO_TLS1_3)
+static int cert_cb_cnt;
+
+static int cert_cb(SSL *s, void *arg)
+{
+ SSL_CTX *ctx = (SSL_CTX *)arg;
+
+ if (cert_cb_cnt == 0) {
+ /* Suspend the handshake */
+ cert_cb_cnt++;
+ return -1;
+ } else if (cert_cb_cnt == 1) {
+ /*
+ * Update the SSL_CTX, set the certificate and private key and then
+ * continue the handshake normally.
+ */
+ if (ctx != NULL && !TEST_ptr(SSL_set_SSL_CTX(s, ctx)))
+ return 0;
+
+ if (!TEST_true(SSL_use_certificate_file(s, cert, SSL_FILETYPE_PEM))
+ || !TEST_true(SSL_use_PrivateKey_file(s, privkey,
+ SSL_FILETYPE_PEM))
+ || !TEST_true(SSL_check_private_key(s)))
+ return 0;
+ cert_cb_cnt++;
+ return 1;
+ }
+
+ /* Abort the handshake */
+ return 0;
+}
+
+/*
+ * Test the certificate callback.
+ * Test 0: Callback fails
+ * Test 1: Success - no SSL_set_SSL_CTX() in the callback
+ * Test 2: Success - SSL_set_SSL_CTX() in the callback
+ */
+static int test_cert_cb_int(int prot, int tst)
+{
+ SSL_CTX *cctx = NULL, *sctx = NULL, *snictx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0, ret;
+
+ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
+ TLS_client_method(),
+ TLS1_VERSION,
+ prot,
+ &sctx, &cctx, NULL, NULL)))
+ goto end;
+
+ if (tst == 0)
+ cert_cb_cnt = -1;
+ else
+ cert_cb_cnt = 0;
+ if (tst == 2)
+ snictx = SSL_CTX_new(TLS_server_method());
+ SSL_CTX_set_cert_cb(sctx, cert_cb, snictx);
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL)))
+ goto end;
+
+ ret = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE);
+ if (!TEST_true(tst == 0 ? !ret : ret)
+ || (tst > 0 && !TEST_int_eq(cert_cb_cnt, 2))) {
+ goto end;
+ }
+
+ testresult = 1;
+
+ end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ SSL_CTX_free(snictx);
+
+ return testresult;
+}
+#endif
+
+static int test_cert_cb(int tst)
+{
+ int testresult = 1;
+
+#ifndef OPENSSL_NO_TLS1_2
+ testresult &= test_cert_cb_int(TLS1_2_VERSION, tst);
+#endif
+#ifndef OPENSSL_NO_TLS1_3
+ testresult &= test_cert_cb_int(TLS1_3_VERSION, tst);
+#endif
+
+ return testresult;
+}
+
+static int client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
+{
+ X509 *xcert, *peer;
+ EVP_PKEY *privpkey;
+ BIO *in = NULL;
+
+ /* Check that SSL_get_peer_certificate() returns something sensible */
+ peer = SSL_get_peer_certificate(ssl);
+ if (!TEST_ptr(peer))
+ return 0;
+ X509_free(peer);
+
+ in = BIO_new_file(cert, "r");
+ if (!TEST_ptr(in))
+ return 0;
+
+ xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
+ BIO_free(in);
+ if (!TEST_ptr(xcert))
+ return 0;
+
+ in = BIO_new_file(privkey, "r");
+ if (!TEST_ptr(in)) {
+ X509_free(xcert);
+ return 0;
+ }
+
+ privpkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
+ BIO_free(in);
+ if (!TEST_ptr(privpkey)) {
+ X509_free(xcert);
+ return 0;
+ }
+
+ *x509 = xcert;
+ *pkey = privpkey;
+
+ return 1;
+}
+
+static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
+{
+ return 1;
+}
+
+static int test_client_cert_cb(int tst)
+{
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+
+#ifdef OPENSSL_NO_TLS1_2
+ if (tst == 0)
+ return 1;
+#endif
+#ifdef OPENSSL_NO_TLS1_3
+ if (tst == 1)
+ return 1;
+#endif
+
+ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
+ TLS_client_method(),
+ TLS1_VERSION,
+ tst == 0 ? TLS1_2_VERSION
+ : TLS1_3_VERSION,
+ &sctx, &cctx, cert, privkey)))
+ goto end;
+
+ /*
+ * Test that setting a client_cert_cb results in a client certificate being
+ * sent.
+ */
+ SSL_CTX_set_client_cert_cb(cctx, client_cert_cb);
+ SSL_CTX_set_verify(sctx,
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ verify_cb);
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL))
+ || !TEST_true(create_ssl_connection(serverssl, clientssl,
+ SSL_ERROR_NONE)))
+ goto end;
+
+ testresult = 1;
+
+ end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+
+ return testresult;
+}
+
+#if !defined(OPENSSL_NO_TLS1_2) || !defined(OPENSSL_NO_TLS1_3)
+/*
+ * Test setting certificate authorities on both client and server.
+ *
+ * Test 0: SSL_CTX_set0_CA_list() only
+ * Test 1: Both SSL_CTX_set0_CA_list() and SSL_CTX_set_client_CA_list()
+ * Test 2: Only SSL_CTX_set_client_CA_list()
+ */
+static int test_ca_names_int(int prot, int tst)
+{
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+ size_t i;
+ X509_NAME *name[] = { NULL, NULL, NULL, NULL };
+ char *strnames[] = { "Jack", "Jill", "John", "Joanne" };
+ STACK_OF(X509_NAME) *sk1 = NULL, *sk2 = NULL;
+ const STACK_OF(X509_NAME) *sktmp = NULL;
+
+ for (i = 0; i < OSSL_NELEM(name); i++) {
+ name[i] = X509_NAME_new();
+ if (!TEST_ptr(name[i])
+ || !TEST_true(X509_NAME_add_entry_by_txt(name[i], "CN",
+ MBSTRING_ASC,
+ (unsigned char *)
+ strnames[i],
+ -1, -1, 0)))
+ goto end;
+ }
+
+ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
+ TLS_client_method(),
+ TLS1_VERSION,
+ prot,
+ &sctx, &cctx, cert, privkey)))
+ goto end;
+
+ SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, NULL);
+
+ if (tst == 0 || tst == 1) {
+ if (!TEST_ptr(sk1 = sk_X509_NAME_new_null())
+ || !TEST_true(sk_X509_NAME_push(sk1, X509_NAME_dup(name[0])))
+ || !TEST_true(sk_X509_NAME_push(sk1, X509_NAME_dup(name[1])))
+ || !TEST_ptr(sk2 = sk_X509_NAME_new_null())
+ || !TEST_true(sk_X509_NAME_push(sk2, X509_NAME_dup(name[0])))
+ || !TEST_true(sk_X509_NAME_push(sk2, X509_NAME_dup(name[1]))))
+ goto end;
+
+ SSL_CTX_set0_CA_list(sctx, sk1);
+ SSL_CTX_set0_CA_list(cctx, sk2);
+ sk1 = sk2 = NULL;
+ }
+ if (tst == 1 || tst == 2) {
+ if (!TEST_ptr(sk1 = sk_X509_NAME_new_null())
+ || !TEST_true(sk_X509_NAME_push(sk1, X509_NAME_dup(name[2])))
+ || !TEST_true(sk_X509_NAME_push(sk1, X509_NAME_dup(name[3])))
+ || !TEST_ptr(sk2 = sk_X509_NAME_new_null())
+ || !TEST_true(sk_X509_NAME_push(sk2, X509_NAME_dup(name[2])))
+ || !TEST_true(sk_X509_NAME_push(sk2, X509_NAME_dup(name[3]))))
+ goto end;
+
+ SSL_CTX_set_client_CA_list(sctx, sk1);
+ SSL_CTX_set_client_CA_list(cctx, sk2);
+ sk1 = sk2 = NULL;
+ }
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL))
+ || !TEST_true(create_ssl_connection(serverssl, clientssl,
+ SSL_ERROR_NONE)))
+ goto end;
+
+ /*
+ * We only expect certificate authorities to have been sent to the server
+ * if we are using TLSv1.3 and SSL_set0_CA_list() was used
+ */
+ sktmp = SSL_get0_peer_CA_list(serverssl);
+ if (prot == TLS1_3_VERSION
+ && (tst == 0 || tst == 1)) {
+ if (!TEST_ptr(sktmp)
+ || !TEST_int_eq(sk_X509_NAME_num(sktmp), 2)
+ || !TEST_int_eq(X509_NAME_cmp(sk_X509_NAME_value(sktmp, 0),
+ name[0]), 0)
+ || !TEST_int_eq(X509_NAME_cmp(sk_X509_NAME_value(sktmp, 1),
+ name[1]), 0))
+ goto end;
+ } else if (!TEST_ptr_null(sktmp)) {
+ goto end;
+ }
+
+ /*
+ * In all tests we expect certificate authorities to have been sent to the
+ * client. However, SSL_set_client_CA_list() should override
+ * SSL_set0_CA_list()
+ */
+ sktmp = SSL_get0_peer_CA_list(clientssl);
+ if (!TEST_ptr(sktmp)
+ || !TEST_int_eq(sk_X509_NAME_num(sktmp), 2)
+ || !TEST_int_eq(X509_NAME_cmp(sk_X509_NAME_value(sktmp, 0),
+ name[tst == 0 ? 0 : 2]), 0)
+ || !TEST_int_eq(X509_NAME_cmp(sk_X509_NAME_value(sktmp, 1),
+ name[tst == 0 ? 1 : 3]), 0))
+ goto end;
+
+ testresult = 1;
+
+ end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ for (i = 0; i < OSSL_NELEM(name); i++)
+ X509_NAME_free(name[i]);
+ sk_X509_NAME_pop_free(sk1, X509_NAME_free);
+ sk_X509_NAME_pop_free(sk2, X509_NAME_free);
+
+ return testresult;
+}
+#endif
+
+static int test_ca_names(int tst)
+{
+ int testresult = 1;
+
+#ifndef OPENSSL_NO_TLS1_2
+ testresult &= test_ca_names_int(TLS1_2_VERSION, tst);
+#endif
+#ifndef OPENSSL_NO_TLS1_3
+ testresult &= test_ca_names_int(TLS1_3_VERSION, tst);
+#endif
+
+ return testresult;
+}
+
int setup_tests(void)
{
if (!TEST_ptr(cert = test_get_argument(0))
ADD_ALL_TESTS(test_ssl_pending, 2);
ADD_ALL_TESTS(test_ssl_get_shared_ciphers, OSSL_NELEM(shared_ciphers_data));
ADD_ALL_TESTS(test_ticket_callbacks, 12);
- ADD_ALL_TESTS(test_shutdown, 6);
+ ADD_ALL_TESTS(test_shutdown, 7);
+ ADD_ALL_TESTS(test_cert_cb, 3);
+ ADD_ALL_TESTS(test_client_cert_cb, 2);
+ ADD_ALL_TESTS(test_ca_names, 3);
return 1;
}