X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=test%2Fsslapitest.c;h=bc1f006a9570d0e67e2775f8147b87c7a3f4e626;hp=26ef4354176ef41d88ac6a83fde414ce29c224cb;hb=7cb8fb07e8b71dc1fdcb0de10af7fed4347f6ea4;hpb=e825109236f6795fbe24c0c6a489ef89ca05a906 diff --git a/test/sslapitest.c b/test/sslapitest.c index 26ef435417..bc1f006a95 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -1,12 +1,13 @@ /* * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 #include #include @@ -16,13 +17,34 @@ #include #include #include +#include +#include #include "ssltestlib.h" #include "testutil.h" #include "testutil/output.h" #include "internal/nelem.h" +#include "internal/ktls.h" #include "../ssl/ssl_locl.h" +#ifndef OPENSSL_NO_TLS1_3 + +static SSL_SESSION *clientpsk = NULL; +static SSL_SESSION *serverpsk = NULL; +static const char *pskid = "Identity"; +static const char *srvid; + +static int use_session_cb(SSL *ssl, const EVP_MD *md, const unsigned char **id, + size_t *idlen, SSL_SESSION **sess); +static int find_session_cb(SSL *ssl, const unsigned char *identity, + size_t identity_len, SSL_SESSION **sess); + +static int use_session_cb_cnt = 0; +static int find_session_cb_cnt = 0; + +static SSL_SESSION *create_a_psk(SSL *ssl); +#endif + static char *cert = NULL; static char *privkey = NULL; static char *srpvfile = NULL; @@ -286,9 +308,10 @@ static int test_keylog(void) SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; int testresult = 0; - struct sslapitest_log_counts expected = {0}; + struct sslapitest_log_counts expected; /* Clean up logging space */ + memset(&expected, 0, sizeof(expected)); memset(client_log_buffer, 0, sizeof(client_log_buffer)); memset(server_log_buffer, 0, sizeof(server_log_buffer)); client_log_buffer_index = 0; @@ -297,7 +320,7 @@ static int test_keylog(void) if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) return 0; @@ -367,11 +390,12 @@ static int test_keylog_no_master_key(void) SSL *clientssl = NULL, *serverssl = NULL; SSL_SESSION *sess = NULL; int testresult = 0; - struct sslapitest_log_counts expected = {0}; + struct sslapitest_log_counts expected; unsigned char buf[1]; size_t readbytes, written; /* Clean up logging space */ + memset(&expected, 0, sizeof(expected)); memset(client_log_buffer, 0, sizeof(client_log_buffer)); memset(server_log_buffer, 0, sizeof(server_log_buffer)); client_log_buffer_index = 0; @@ -379,7 +403,7 @@ static int test_keylog_no_master_key(void) error_writing_log = 0; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey)) || !TEST_true(SSL_CTX_set_max_early_data(sctx, SSL3_RT_MAX_PLAIN_LENGTH))) @@ -525,7 +549,7 @@ static int test_client_hello_cb(void) int testctr = 0, testresult = 0; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; SSL_CTX_set_client_hello_cb(sctx, full_client_hello_callback, &testctr); @@ -551,6 +575,51 @@ static int test_client_hello_cb(void) testresult = 1; +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +static int test_no_ems(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + + if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), + TLS1_VERSION, TLS1_2_VERSION, + &sctx, &cctx, cert, privkey)) { + printf("Unable to create SSL_CTX pair\n"); + goto end; + } + + SSL_CTX_set_options(sctx, SSL_OP_NO_EXTENDED_MASTER_SECRET); + + if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) { + printf("Unable to create SSL objects\n"); + goto end; + } + + if (!create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) { + printf("Creating SSL connection failed\n"); + goto end; + } + + if (SSL_get_extms_support(serverssl)) { + printf("Server reports Extended Master Secret support\n"); + goto end; + } + + if (SSL_get_extms_support(clientssl)) { + printf("Client reports Extended Master Secret support\n"); + goto end; + } + testresult = 1; + end: SSL_free(serverssl); SSL_free(clientssl); @@ -637,18 +706,416 @@ static int execute_test_large_message(const SSL_METHOD *smeth, return testresult; } +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_KTLS) \ + && !defined(OPENSSL_NO_SOCK) + +/* sock must be connected */ +static int ktls_chk_platform(int sock) +{ + if (!ktls_enable(sock)) + return 0; + return 1; +} + +static int ping_pong_query(SSL *clientssl, SSL *serverssl, int cfd, int sfd) +{ + static char count = 1; + unsigned char cbuf[16000] = {0}; + unsigned char sbuf[16000]; + size_t err = 0; + char crec_wseq_before[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + char crec_wseq_after[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + char crec_rseq_before[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + char crec_rseq_after[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + char srec_wseq_before[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + char srec_wseq_after[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + char srec_rseq_before[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + char srec_rseq_after[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE]; + + cbuf[0] = count++; + memcpy(crec_wseq_before, &clientssl->rlayer.write_sequence, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy(crec_rseq_before, &clientssl->rlayer.read_sequence, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy(srec_wseq_before, &serverssl->rlayer.write_sequence, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy(srec_rseq_before, &serverssl->rlayer.read_sequence, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + + if (!TEST_true(SSL_write(clientssl, cbuf, sizeof(cbuf)) == sizeof(cbuf))) + goto end; + + while ((err = SSL_read(serverssl, &sbuf, sizeof(sbuf))) != sizeof(sbuf)) { + if (SSL_get_error(serverssl, err) != SSL_ERROR_WANT_READ) { + goto end; + } + } + + if (!TEST_true(SSL_write(serverssl, sbuf, sizeof(sbuf)) == sizeof(sbuf))) + goto end; + + while ((err = SSL_read(clientssl, &cbuf, sizeof(cbuf))) != sizeof(cbuf)) { + if (SSL_get_error(clientssl, err) != SSL_ERROR_WANT_READ) { + goto end; + } + } + + memcpy(crec_wseq_after, &clientssl->rlayer.write_sequence, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy(crec_rseq_after, &clientssl->rlayer.read_sequence, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy(srec_wseq_after, &serverssl->rlayer.write_sequence, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + memcpy(srec_rseq_after, &serverssl->rlayer.read_sequence, + TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE); + + /* verify the payload */ + if (!TEST_mem_eq(cbuf, sizeof(cbuf), sbuf, sizeof(sbuf))) + goto end; + + /* ktls is used then kernel sequences are used instead of OpenSSL sequences */ + if (clientssl->mode & SSL_MODE_NO_KTLS_TX) { + if (!TEST_mem_ne(crec_wseq_before, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE, + crec_wseq_after, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE)) + goto end; + } else { + if (!TEST_mem_eq(crec_wseq_before, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE, + crec_wseq_after, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE)) + goto end; + } + + if (serverssl->mode & SSL_MODE_NO_KTLS_TX) { + if (!TEST_mem_ne(srec_wseq_before, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE, + srec_wseq_after, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE)) + goto end; + } else { + if (!TEST_mem_eq(srec_wseq_before, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE, + srec_wseq_after, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE)) + goto end; + } + + if (clientssl->mode & SSL_MODE_NO_KTLS_RX) { + if (!TEST_mem_ne(crec_rseq_before, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE, + crec_rseq_after, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE)) + goto end; + } else { + if (!TEST_mem_eq(crec_rseq_before, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE, + crec_rseq_after, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE)) + goto end; + } + + if (serverssl->mode & SSL_MODE_NO_KTLS_RX) { + if (!TEST_mem_ne(srec_rseq_before, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE, + srec_rseq_after, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE)) + goto end; + } else { + if (!TEST_mem_eq(srec_rseq_before, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE, + srec_rseq_after, TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE)) + goto end; + } + + return 1; +end: + return 0; +} + +static int execute_test_ktls(int cis_ktls_tx, int cis_ktls_rx, + int sis_ktls_tx, int sis_ktls_rx) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + int cfd, sfd; + + if (!TEST_true(create_test_sockets(&cfd, &sfd))) + goto end; + + /* Skip this test if the platform does not support ktls */ + if (!ktls_chk_platform(cfd)) + return 1; + + /* Create a session based on SHA-256 */ + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_2_VERSION, TLS1_2_VERSION, + &sctx, &cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_cipher_list(cctx, + "AES128-GCM-SHA256")) + || !TEST_true(create_ssl_objects2(sctx, cctx, &serverssl, + &clientssl, sfd, cfd))) + goto end; + + if (!cis_ktls_tx) { + if (!TEST_true(SSL_set_mode(clientssl, SSL_MODE_NO_KTLS_TX))) + goto end; + } + + if (!sis_ktls_tx) { + if (!TEST_true(SSL_set_mode(serverssl, SSL_MODE_NO_KTLS_TX))) + goto end; + } + + if (!cis_ktls_rx) { + if (!TEST_true(SSL_set_mode(clientssl, SSL_MODE_NO_KTLS_RX))) + goto end; + } + + if (!sis_ktls_rx) { + if (!TEST_true(SSL_set_mode(serverssl, SSL_MODE_NO_KTLS_RX))) + goto end; + } + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + if (!cis_ktls_tx) { + if (!TEST_false(BIO_get_ktls_send(clientssl->wbio))) + goto end; + } else { + if (!TEST_true(BIO_get_ktls_send(clientssl->wbio))) + goto end; + } + + if (!sis_ktls_tx) { + if (!TEST_false(BIO_get_ktls_send(serverssl->wbio))) + goto end; + } else { + if (!TEST_true(BIO_get_ktls_send(serverssl->wbio))) + goto end; + } + + if (!cis_ktls_rx) { + if (!TEST_false(BIO_get_ktls_recv(clientssl->rbio))) + goto end; + } else { + if (!TEST_true(BIO_get_ktls_recv(clientssl->rbio))) + goto end; + } + + if (!sis_ktls_rx) { + if (!TEST_false(BIO_get_ktls_recv(serverssl->rbio))) + goto end; + } else { + if (!TEST_true(BIO_get_ktls_recv(serverssl->rbio))) + goto end; + } + + if (!TEST_true(ping_pong_query(clientssl, serverssl, cfd, sfd))) + goto end; + + testresult = 1; +end: + if (clientssl) { + SSL_shutdown(clientssl); + SSL_free(clientssl); + } + if (serverssl) { + SSL_shutdown(serverssl); + SSL_free(serverssl); + } + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + serverssl = clientssl = NULL; + return testresult; +} + +#define SENDFILE_SZ (16 * 4096) +#define SENDFILE_CHUNK (4 * 4096) +#define min(a,b) ((a) > (b) ? (b) : (a)) + +static int test_ktls_sendfile(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + unsigned char *buf, *buf_dst; + BIO *out = NULL, *in = NULL; + int cfd, sfd, ffd, err; + ssize_t chunk_size = 0; + off_t chunk_off = 0; + int testresult = 0; + FILE *ffdp; + + buf = OPENSSL_zalloc(SENDFILE_SZ); + buf_dst = OPENSSL_zalloc(SENDFILE_SZ); + if (!TEST_ptr(buf) || !TEST_ptr(buf_dst) + || !TEST_true(create_test_sockets(&cfd, &sfd))) + goto end; + + /* Skip this test if the platform does not support ktls */ + if (!ktls_chk_platform(sfd)) { + testresult = 1; + goto end; + } + + /* Create a session based on SHA-256 */ + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_2_VERSION, TLS1_2_VERSION, + &sctx, &cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_cipher_list(cctx, + "AES128-GCM-SHA256")) + || !TEST_true(create_ssl_objects2(sctx, cctx, &serverssl, + &clientssl, sfd, cfd))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_true(BIO_get_ktls_send(serverssl->wbio))) + goto end; + + RAND_bytes(buf, SENDFILE_SZ); + out = BIO_new_file(tmpfilename, "wb"); + if (!TEST_ptr(out)) + goto end; + + if (BIO_write(out, buf, SENDFILE_SZ) != SENDFILE_SZ) + goto end; + + BIO_free(out); + out = NULL; + in = BIO_new_file(tmpfilename, "rb"); + BIO_get_fp(in, &ffdp); + ffd = fileno(ffdp); + + while (chunk_off < SENDFILE_SZ) { + chunk_size = min(SENDFILE_CHUNK, SENDFILE_SZ - chunk_off); + while ((err = SSL_sendfile(serverssl, + ffd, + chunk_off, + chunk_size, + 0)) != chunk_size) { + if (SSL_get_error(serverssl, err) != SSL_ERROR_WANT_WRITE) + goto end; + } + while ((err = SSL_read(clientssl, + buf_dst + chunk_off, + chunk_size)) != chunk_size) { + if (SSL_get_error(clientssl, err) != SSL_ERROR_WANT_READ) + goto end; + } + + /* verify the payload */ + if (!TEST_mem_eq(buf_dst + chunk_off, + chunk_size, + buf + chunk_off, + chunk_size)) + goto end; + + chunk_off += chunk_size; + } + + testresult = 1; +end: + if (clientssl) { + SSL_shutdown(clientssl); + SSL_free(clientssl); + } + if (serverssl) { + SSL_shutdown(serverssl); + SSL_free(serverssl); + } + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + serverssl = clientssl = NULL; + BIO_free(out); + BIO_free(in); + OPENSSL_free(buf); + OPENSSL_free(buf_dst); + return testresult; +} + +static int test_ktls_no_txrx_client_no_txrx_server(void) +{ + return execute_test_ktls(0, 0, 0, 0); +} + +static int test_ktls_no_rx_client_no_txrx_server(void) +{ + return execute_test_ktls(1, 0, 0, 0); +} + +static int test_ktls_no_tx_client_no_txrx_server(void) +{ + return execute_test_ktls(0, 1, 0, 0); +} + +static int test_ktls_client_no_txrx_server(void) +{ + return execute_test_ktls(1, 1, 0, 0); +} + +static int test_ktls_no_txrx_client_no_rx_server(void) +{ + return execute_test_ktls(0, 0, 1, 0); +} + +static int test_ktls_no_rx_client_no_rx_server(void) +{ + return execute_test_ktls(1, 0, 1, 0); +} + +static int test_ktls_no_tx_client_no_rx_server(void) +{ + return execute_test_ktls(0, 1, 1, 0); +} + +static int test_ktls_client_no_rx_server(void) +{ + return execute_test_ktls(1, 1, 1, 0); +} + +static int test_ktls_no_txrx_client_no_tx_server(void) +{ + return execute_test_ktls(0, 0, 0, 1); +} + +static int test_ktls_no_rx_client_no_tx_server(void) +{ + return execute_test_ktls(1, 0, 0, 1); +} + +static int test_ktls_no_tx_client_no_tx_server(void) +{ + return execute_test_ktls(0, 1, 0, 1); +} + +static int test_ktls_client_no_tx_server(void) +{ + return execute_test_ktls(1, 1, 0, 1); +} + +static int test_ktls_no_txrx_client_server(void) +{ + return execute_test_ktls(0, 0, 1, 1); +} + +static int test_ktls_no_rx_client_server(void) +{ + return execute_test_ktls(1, 0, 1, 1); +} + +static int test_ktls_no_tx_client_server(void) +{ + return execute_test_ktls(0, 1, 1, 1); +} + +static int test_ktls_client_server(void) +{ + return execute_test_ktls(1, 1, 1, 1); +} +#endif + static int test_large_message_tls(void) { return execute_test_large_message(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, - 0); + TLS1_VERSION, 0, 0); } static int test_large_message_tls_read_ahead(void) { return execute_test_large_message(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, - 1); + TLS1_VERSION, 0, 1); } #ifndef OPENSSL_NO_DTLS @@ -660,8 +1127,7 @@ static int test_large_message_dtls(void) */ return execute_test_large_message(DTLS_server_method(), DTLS_client_method(), - DTLS1_VERSION, DTLS_MAX_VERSION, - 0); + DTLS1_VERSION, 0, 0); } #endif @@ -721,7 +1187,7 @@ static int test_tlsext_status_type(void) BIO *certbio = NULL; if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey)) return 0; @@ -881,12 +1347,16 @@ static int execute_test_session(int maxprot, int use_int_cache, SSL *serverssl3 = NULL, *clientssl3 = NULL; # endif SSL_SESSION *sess1 = NULL, *sess2 = NULL; - int testresult = 0; + int testresult = 0, numnewsesstick = 1; new_called = remove_called = 0; + /* TLSv1.3 sends 2 NewSessionTickets */ + if (maxprot == TLS1_3_VERSION) + numnewsesstick = 2; + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) return 0; @@ -922,7 +1392,9 @@ static int execute_test_session(int maxprot, int use_int_cache, if (use_int_cache && !TEST_false(SSL_CTX_add_session(cctx, sess1))) goto end; if (use_ext_cache - && (!TEST_int_eq(new_called, 1) || !TEST_int_eq(remove_called, 0))) + && (!TEST_int_eq(new_called, numnewsesstick) + + || !TEST_int_eq(remove_called, 0))) goto end; new_called = remove_called = 0; @@ -937,7 +1409,8 @@ static int execute_test_session(int maxprot, int use_int_cache, if (maxprot == TLS1_3_VERSION) { /* * In TLSv1.3 we should have created a new session even though we have - * resumed. The original session should also have been removed. + * resumed. Since we attempted a resume we should also have removed the + * old ticket from the cache so that we try to only use tickets once. */ if (use_ext_cache && (!TEST_int_eq(new_called, 1) @@ -971,7 +1444,8 @@ static int execute_test_session(int maxprot, int use_int_cache, goto end; if (use_ext_cache - && (!TEST_int_eq(new_called, 1) || !TEST_int_eq(remove_called, 0))) + && (!TEST_int_eq(new_called, numnewsesstick) + || !TEST_int_eq(remove_called, 0))) goto end; new_called = remove_called = 0; @@ -1054,7 +1528,8 @@ static int execute_test_session(int maxprot, int use_int_cache, sess2 = NULL; SSL_CTX_set_max_proto_version(sctx, maxprot); - SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET); + if (maxprot == TLS1_2_VERSION) + SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET); new_called = remove_called = get_called = 0; if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl1, &clientssl1, NULL, NULL)) @@ -1064,14 +1539,27 @@ static int execute_test_session(int maxprot, int use_int_cache, || !TEST_ptr(sess2 = SSL_get1_session(serverssl1))) goto end; - /* Should fail because it should already be in the cache */ - if (use_int_cache && !TEST_false(SSL_CTX_add_session(sctx, sess2))) - goto end; + if (use_int_cache) { + if (maxprot == TLS1_3_VERSION && !use_ext_cache) { + /* + * In TLSv1.3 it should not have been added to the internal cache, + * except in the case where we also have an external cache (in that + * case it gets added to the cache in order to generate remove + * events after timeout). + */ + if (!TEST_false(SSL_CTX_remove_session(sctx, sess2))) + goto end; + } else { + /* Should fail because it should already be in the cache */ + if (!TEST_false(SSL_CTX_add_session(sctx, sess2))) + goto end; + } + } if (use_ext_cache) { SSL_SESSION *tmp = sess2; - if (!TEST_int_eq(new_called, 1) + if (!TEST_int_eq(new_called, numnewsesstick) || !TEST_int_eq(remove_called, 0) || !TEST_int_eq(get_called, 0)) goto end; @@ -1080,7 +1568,7 @@ static int execute_test_session(int maxprot, int use_int_cache, * the external cache. We take a copy first because * SSL_CTX_remove_session() also marks the session as non-resumable. */ - if (use_int_cache) { + if (use_int_cache && maxprot != TLS1_3_VERSION) { if (!TEST_ptr(tmp = SSL_SESSION_dup(sess2)) || !TEST_true(SSL_CTX_remove_session(sctx, sess2))) goto end; @@ -1104,10 +1592,6 @@ static int execute_test_session(int maxprot, int use_int_cache, goto end; if (maxprot == TLS1_3_VERSION) { - /* - * Every time we issue a NewSessionTicket we are creating a new - * session for next time in TLSv1.3 - */ if (!TEST_int_eq(new_called, 1) || !TEST_int_eq(get_called, 0)) goto end; @@ -1180,6 +1664,294 @@ static int test_session_with_both_cache(void) #endif } +#ifndef OPENSSL_NO_TLS1_3 +static SSL_SESSION *sesscache[6]; +static int do_cache; + +static int new_cachesession_cb(SSL *ssl, SSL_SESSION *sess) +{ + if (do_cache) { + sesscache[new_called] = sess; + } else { + /* We don't need the reference to the session, so free it */ + SSL_SESSION_free(sess); + } + new_called++; + + return 1; +} + +static int post_handshake_verify(SSL *sssl, SSL *cssl) +{ + SSL_set_verify(sssl, SSL_VERIFY_PEER, NULL); + if (!TEST_true(SSL_verify_client_post_handshake(sssl))) + return 0; + + /* Start handshake on the server and client */ + if (!TEST_int_eq(SSL_do_handshake(sssl), 1) + || !TEST_int_le(SSL_read(cssl, NULL, 0), 0) + || !TEST_int_le(SSL_read(sssl, NULL, 0), 0) + || !TEST_true(create_ssl_connection(sssl, cssl, + SSL_ERROR_NONE))) + return 0; + + return 1; +} + +static int setup_ticket_test(int stateful, int idx, SSL_CTX **sctx, + SSL_CTX **cctx) +{ + int sess_id_ctx = 1; + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), + TLS1_VERSION, 0, sctx, + cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_num_tickets(*sctx, idx)) + || !TEST_true(SSL_CTX_set_session_id_context(*sctx, + (void *)&sess_id_ctx, + sizeof(sess_id_ctx)))) + return 0; + + if (stateful) + SSL_CTX_set_options(*sctx, SSL_OP_NO_TICKET); + + SSL_CTX_set_session_cache_mode(*cctx, SSL_SESS_CACHE_CLIENT + | SSL_SESS_CACHE_NO_INTERNAL_STORE); + SSL_CTX_sess_set_new_cb(*cctx, new_cachesession_cb); + + return 1; +} + +static int check_resumption(int idx, SSL_CTX *sctx, SSL_CTX *cctx, int succ) +{ + SSL *serverssl = NULL, *clientssl = NULL; + int i; + + /* Test that we can resume with all the tickets we got given */ + for (i = 0; i < idx * 2; i++) { + new_called = 0; + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL)) + || !TEST_true(SSL_set_session(clientssl, sesscache[i]))) + goto end; + + SSL_set_post_handshake_auth(clientssl, 1); + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + /* + * Following a successful resumption we only get 1 ticket. After a + * failed one we should get idx tickets. + */ + if (succ) { + if (!TEST_true(SSL_session_reused(clientssl)) + || !TEST_int_eq(new_called, 1)) + goto end; + } else { + if (!TEST_false(SSL_session_reused(clientssl)) + || !TEST_int_eq(new_called, idx)) + goto end; + } + + new_called = 0; + /* After a post-handshake authentication we should get 1 new ticket */ + if (succ + && (!post_handshake_verify(serverssl, clientssl) + || !TEST_int_eq(new_called, 1))) + goto end; + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + SSL_SESSION_free(sesscache[i]); + sesscache[i] = NULL; + } + + return 1; + + end: + SSL_free(clientssl); + SSL_free(serverssl); + return 0; +} + +static int test_tickets(int stateful, int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + size_t j; + + /* idx is the test number, but also the number of tickets we want */ + + new_called = 0; + do_cache = 1; + + if (!setup_ticket_test(stateful, idx, &sctx, &cctx)) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + /* Check we got the number of tickets we were expecting */ + || !TEST_int_eq(idx, new_called)) + goto end; + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + clientssl = serverssl = NULL; + sctx = cctx = NULL; + + /* + * Now we try to resume with the tickets we previously created. The + * resumption attempt is expected to fail (because we're now using a new + * SSL_CTX). We should see idx number of tickets issued again. + */ + + /* Stop caching sessions - just count them */ + do_cache = 0; + + if (!setup_ticket_test(stateful, idx, &sctx, &cctx)) + goto end; + + if (!check_resumption(idx, sctx, cctx, 0)) + goto end; + + /* Start again with caching sessions */ + new_called = 0; + do_cache = 1; + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + sctx = cctx = NULL; + + if (!setup_ticket_test(stateful, idx, &sctx, &cctx)) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL))) + goto end; + + SSL_set_post_handshake_auth(clientssl, 1); + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + /* Check we got the number of tickets we were expecting */ + || !TEST_int_eq(idx, new_called)) + goto end; + + /* After a post-handshake authentication we should get new tickets issued */ + if (!post_handshake_verify(serverssl, clientssl) + || !TEST_int_eq(idx * 2, new_called)) + goto end; + + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + + /* Stop caching sessions - just count them */ + do_cache = 0; + + /* + * Check we can resume with all the tickets we created. This time around the + * resumptions should all be successful. + */ + if (!check_resumption(idx, sctx, cctx, 1)) + goto end; + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + for (j = 0; j < OSSL_NELEM(sesscache); j++) { + SSL_SESSION_free(sesscache[j]); + sesscache[j] = NULL; + } + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +static int test_stateless_tickets(int idx) +{ + return test_tickets(0, idx); +} + +static int test_stateful_tickets(int idx) +{ + return test_tickets(1, idx); +} + +static int test_psk_tickets(void) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + int sess_id_ctx = 1; + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), + TLS1_VERSION, 0, &sctx, + &cctx, NULL, NULL)) + || !TEST_true(SSL_CTX_set_session_id_context(sctx, + (void *)&sess_id_ctx, + sizeof(sess_id_ctx)))) + goto end; + + SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT + | SSL_SESS_CACHE_NO_INTERNAL_STORE); + SSL_CTX_set_psk_use_session_callback(cctx, use_session_cb); + SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb); + SSL_CTX_sess_set_new_cb(cctx, new_session_cb); + use_session_cb_cnt = 0; + find_session_cb_cnt = 0; + srvid = pskid; + new_called = 0; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + clientpsk = serverpsk = create_a_psk(clientssl); + if (!TEST_ptr(clientpsk)) + goto end; + SSL_SESSION_up_ref(clientpsk); + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_int_eq(1, find_session_cb_cnt) + || !TEST_int_eq(1, use_session_cb_cnt) + /* We should always get 1 ticket when using external PSK */ + || !TEST_int_eq(1, new_called)) + goto end; + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + SSL_SESSION_free(clientpsk); + SSL_SESSION_free(serverpsk); + clientpsk = serverpsk = NULL; + + return testresult; +} +#endif + #define USE_NULL 0 #define USE_BIO_1 1 #define USE_BIO_2 2 @@ -1197,7 +1969,6 @@ static int test_session_with_both_cache(void) # define TOTAL_CONN_FAIL_SSL_SET_BIO_TESTS 0 #endif - #define TOTAL_SSL_SET_BIO_TESTS TOTAL_NO_CONN_SSL_SET_BIO_TESTS \ + TOTAL_CONN_SUCCESS_SSL_SET_BIO_TESTS \ + TOTAL_CONN_FAIL_SSL_SET_BIO_TESTS @@ -1259,7 +2030,7 @@ static int test_ssl_set_bio(int idx) } if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; @@ -1484,7 +2255,7 @@ static int test_set_sigalgs(int idx) : &testsigalgs[idx - OSSL_NELEM(testsigalgs)]; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) return 0; @@ -1555,14 +2326,6 @@ static int test_set_sigalgs(int idx) #endif #ifndef OPENSSL_NO_TLS1_3 - -static SSL_SESSION *clientpsk = NULL; -static SSL_SESSION *serverpsk = NULL; -static const char *pskid = "Identity"; -static const char *srvid; - -static int use_session_cb_cnt = 0; -static int find_session_cb_cnt = 0; static int psk_client_cb_cnt = 0; static int psk_server_cb_cnt = 0; @@ -1693,6 +2456,35 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, #define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02") #define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01") + +static SSL_SESSION *create_a_psk(SSL *ssl) +{ + const SSL_CIPHER *cipher = NULL; + const unsigned char key[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f + }; + SSL_SESSION *sess = NULL; + + cipher = SSL_CIPHER_find(ssl, TLS13_AES_256_GCM_SHA384_BYTES); + sess = SSL_SESSION_new(); + if (!TEST_ptr(sess) + || !TEST_ptr(cipher) + || !TEST_true(SSL_SESSION_set1_master_key(sess, key, + sizeof(key))) + || !TEST_true(SSL_SESSION_set_cipher(sess, cipher)) + || !TEST_true( + SSL_SESSION_set_protocol_version(sess, + TLS1_3_VERSION))) { + SSL_SESSION_free(sess); + return NULL; + } + return sess; +} + /* * Helper method to setup objects for early data test. Caller frees objects on * error. @@ -1700,11 +2492,14 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl, SSL **serverssl, SSL_SESSION **sess, int idx) { - if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, - sctx, cctx, cert, privkey)) - || !TEST_true(SSL_CTX_set_max_early_data(*sctx, - SSL3_RT_MAX_PLAIN_LENGTH))) + if (*sctx == NULL + && !TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_VERSION, 0, + sctx, cctx, cert, privkey))) + return 0; + + if (!TEST_true(SSL_CTX_set_max_early_data(*sctx, SSL3_RT_MAX_PLAIN_LENGTH))) return 0; if (idx == 1) { @@ -1735,26 +2530,8 @@ static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl, return 0; if (idx == 2) { - /* Create the PSK */ - const SSL_CIPHER *cipher = NULL; - const unsigned char key[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, - 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x2c, 0x2d, 0x2e, 0x2f - }; - - cipher = SSL_CIPHER_find(*clientssl, TLS13_AES_256_GCM_SHA384_BYTES); - clientpsk = SSL_SESSION_new(); + clientpsk = create_a_psk(*clientssl); if (!TEST_ptr(clientpsk) - || !TEST_ptr(cipher) - || !TEST_true(SSL_SESSION_set1_master_key(clientpsk, key, - sizeof(key))) - || !TEST_true(SSL_SESSION_set_cipher(clientpsk, cipher)) - || !TEST_true( - SSL_SESSION_set_protocol_version(clientpsk, - TLS1_3_VERSION)) /* * We just choose an arbitrary value for max_early_data which * should be big enough for testing purposes. @@ -1768,8 +2545,15 @@ static int setupearly_data_test(SSL_CTX **cctx, SSL_CTX **sctx, SSL **clientssl, } serverpsk = clientpsk; - if (sess != NULL) + if (sess != NULL) { + if (!TEST_true(SSL_SESSION_up_ref(clientpsk))) { + SSL_SESSION_free(clientpsk); + SSL_SESSION_free(serverpsk); + clientpsk = serverpsk = NULL; + return 0; + } *sess = clientpsk; + } return 1; } @@ -1925,10 +2709,13 @@ static int test_early_data_read_write(int idx) goto end; /* - * Make sure we process the NewSessionTicket. This arrives post-handshake. - * We attempt a read which we do not expect to return any data. + * Make sure we process the two NewSessionTickets. These arrive + * post-handshake. We attempt reads which we do not expect to return any + * data. */ - if (!TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))) + if (!TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)) + || !TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), + &readbytes))) goto end; /* Server should be able to write normal data */ @@ -1938,9 +2725,7 @@ static int test_early_data_read_write(int idx) || !TEST_mem_eq(buf, readbytes, MSG7, strlen(MSG7))) goto end; - /* We keep the PSK session around if using PSK */ - if (idx != 2) - SSL_SESSION_free(sess); + SSL_SESSION_free(sess); sess = SSL_get1_session(clientssl); use_session_cb_cnt = 0; find_session_cb_cnt = 0; @@ -1990,8 +2775,7 @@ static int test_early_data_read_write(int idx) testresult = 1; end: - if (sess != clientpsk) - SSL_SESSION_free(sess); + SSL_SESSION_free(sess); SSL_SESSION_free(clientpsk); SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; @@ -2002,12 +2786,65 @@ static int test_early_data_read_write(int idx) return testresult; } -static int test_early_data_replay(int idx) +static int allow_ed_cb_called = 0; + +static int allow_early_data_cb(SSL *s, void *arg) +{ + int *usecb = (int *)arg; + + allow_ed_cb_called++; + + if (*usecb == 1) + return 0; + + return 1; +} + +/* + * idx == 0: Standard early_data setup + * idx == 1: early_data setup using read_ahead + * usecb == 0: Don't use a custom early data callback + * usecb == 1: Use a custom early data callback and reject the early data + * usecb == 2: Use a custom early data callback and accept the early data + * confopt == 0: Configure anti-replay directly + * confopt == 1: Configure anti-replay using SSL_CONF + */ +static int test_early_data_replay_int(int idx, int usecb, int confopt) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; int testresult = 0; SSL_SESSION *sess = NULL; + size_t readbytes, written; + unsigned char buf[20]; + + allow_ed_cb_called = 0; + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), + TLS1_VERSION, 0, &sctx, + &cctx, cert, privkey))) + return 0; + + if (usecb > 0) { + if (confopt == 0) { + SSL_CTX_set_options(sctx, SSL_OP_NO_ANTI_REPLAY); + } else { + SSL_CONF_CTX *confctx = SSL_CONF_CTX_new(); + + if (!TEST_ptr(confctx)) + goto end; + SSL_CONF_CTX_set_flags(confctx, SSL_CONF_FLAG_FILE + | SSL_CONF_FLAG_SERVER); + SSL_CONF_CTX_set_ssl_ctx(confctx, sctx); + if (!TEST_int_eq(SSL_CONF_cmd(confctx, "Options", "-AntiReplay"), + 2)) { + SSL_CONF_CTX_free(confctx); + goto end; + } + SSL_CONF_CTX_free(confctx); + } + SSL_CTX_set_allow_early_data_cb(sctx, allow_early_data_cb, &usecb); + } if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl, &serverssl, &sess, idx))) @@ -2029,23 +2866,57 @@ static int test_early_data_replay(int idx) if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) - || !TEST_true(SSL_set_session(clientssl, sess)) - || !TEST_true(create_ssl_connection(serverssl, clientssl, - SSL_ERROR_NONE)) - /* - * This time we should not have resumed the session because we - * already used it once. - */ - || !TEST_false(SSL_session_reused(clientssl))) + || !TEST_true(SSL_set_session(clientssl, sess))) goto end; - testresult = 1; + /* Write and read some early data */ + if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1), + &written)) + || !TEST_size_t_eq(written, strlen(MSG1))) + goto end; - end: - if (sess != clientpsk) - SSL_SESSION_free(sess); - SSL_SESSION_free(clientpsk); - SSL_SESSION_free(serverpsk); + if (usecb <= 1) { + if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), + &readbytes), + SSL_READ_EARLY_DATA_FINISH) + /* + * The ticket was reused, so the we should have rejected the + * early data + */ + || !TEST_int_eq(SSL_get_early_data_status(serverssl), + SSL_EARLY_DATA_REJECTED)) + goto end; + } else { + /* In this case the callback decides to accept the early data */ + if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), + &readbytes), + SSL_READ_EARLY_DATA_SUCCESS) + || !TEST_mem_eq(MSG1, strlen(MSG1), buf, readbytes) + /* + * Server will have sent its flight so client can now send + * end of early data and complete its half of the handshake + */ + || !TEST_int_gt(SSL_connect(clientssl), 0) + || !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), + &readbytes), + SSL_READ_EARLY_DATA_FINISH) + || !TEST_int_eq(SSL_get_early_data_status(serverssl), + SSL_EARLY_DATA_ACCEPTED)) + goto end; + } + + /* Complete the connection */ + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) + || !TEST_int_eq(SSL_session_reused(clientssl), (usecb > 0) ? 1 : 0) + || !TEST_int_eq(allow_ed_cb_called, usecb > 0 ? 1 : 0)) + goto end; + + testresult = 1; + + end: + SSL_SESSION_free(sess); + SSL_SESSION_free(clientpsk); + SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; SSL_free(serverssl); SSL_free(clientssl); @@ -2054,11 +2925,27 @@ static int test_early_data_replay(int idx) return testresult; } +static int test_early_data_replay(int idx) +{ + int ret = 1, usecb, confopt; + + for (usecb = 0; usecb < 3; usecb++) { + for (confopt = 0; confopt < 2; confopt++) + ret &= test_early_data_replay_int(idx, usecb, confopt); + } + + return ret; +} + /* * Helper function to test that a server attempting to read early data can * handle a connection from a client where the early data should be skipped. + * testtype: 0 == No HRR + * testtype: 1 == HRR + * testtype: 2 == HRR, invalid early_data sent after HRR + * testtype: 3 == recv_max_early_data set to 0 */ -static int early_data_skip_helper(int hrr, int idx) +static int early_data_skip_helper(int testtype, int idx) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; @@ -2071,10 +2958,15 @@ static int early_data_skip_helper(int hrr, int idx) &serverssl, &sess, idx))) goto end; - if (hrr) { + if (testtype == 1 || testtype == 2) { /* Force an HRR to occur */ +#if defined(OPENSSL_NO_EC) + if (!TEST_true(SSL_set1_groups_list(serverssl, "ffdhe3072"))) + goto end; +#else if (!TEST_true(SSL_set1_groups_list(serverssl, "P-256"))) goto end; +#endif } else if (idx == 2) { /* * We force early_data rejection by ensuring the PSK identity is @@ -2091,13 +2983,17 @@ static int early_data_skip_helper(int hrr, int idx) goto end; } + if (testtype == 3 + && !TEST_true(SSL_set_recv_max_early_data(serverssl, 0))) + goto end; + /* Write some early data */ if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1), &written)) || !TEST_size_t_eq(written, strlen(MSG1))) goto end; - /* Server should reject the early data and skip over it */ + /* Server should reject the early data */ if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), &readbytes), SSL_READ_EARLY_DATA_FINISH) @@ -2106,7 +3002,12 @@ static int early_data_skip_helper(int hrr, int idx) SSL_EARLY_DATA_REJECTED)) goto end; - if (hrr) { + switch (testtype) { + case 0: + /* Nothing to do */ + break; + + case 1: /* * Finish off the handshake. We perform the same writes and reads as * further down but we expect them to fail due to the incomplete @@ -2116,9 +3017,58 @@ static int early_data_skip_helper(int hrr, int idx) || !TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))) goto end; + break; + + case 2: + { + BIO *wbio = SSL_get_wbio(clientssl); + /* A record that will appear as bad early_data */ + const unsigned char bad_early_data[] = { + 0x17, 0x03, 0x03, 0x00, 0x01, 0x00 + }; + + /* + * We force the client to attempt a write. This will fail because + * we're still in the handshake. It will cause the second + * ClientHello to be sent. + */ + if (!TEST_false(SSL_write_ex(clientssl, MSG2, strlen(MSG2), + &written))) + goto end; + + /* + * Inject some early_data after the second ClientHello. This should + * cause the server to fail + */ + if (!TEST_true(BIO_write_ex(wbio, bad_early_data, + sizeof(bad_early_data), &written))) + goto end; + } + /* fallthrough */ + + case 3: + /* + * This client has sent more early_data than we are willing to skip + * (case 3) or sent invalid early_data (case 2) so the connection should + * abort. + */ + if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)) + || !TEST_int_eq(SSL_get_error(serverssl, 0), SSL_ERROR_SSL)) + goto end; + + /* Connection has failed - nothing more to do */ + testresult = 1; + goto end; + + default: + TEST_error("Invalid test type"); + goto end; } - /* Should be able to send normal data despite rejection of early data */ + /* + * Should be able to send normal data despite rejection of early data. The + * early_data should be skipped. + */ if (!TEST_true(SSL_write_ex(clientssl, MSG2, strlen(MSG2), &written)) || !TEST_size_t_eq(written, strlen(MSG2)) || !TEST_int_eq(SSL_get_early_data_status(clientssl), @@ -2130,8 +3080,7 @@ static int early_data_skip_helper(int hrr, int idx) testresult = 1; end: - if (sess != clientpsk) - SSL_SESSION_free(clientpsk); + SSL_SESSION_free(clientpsk); SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; SSL_SESSION_free(sess); @@ -2160,6 +3109,25 @@ static int test_early_data_skip_hrr(int idx) return early_data_skip_helper(1, idx); } +/* + * Test that a server attempting to read early data can handle a connection + * from a client where an HRR occurs and correctly fails if early_data is sent + * after the HRR + */ +static int test_early_data_skip_hrr_fail(int idx) +{ + return early_data_skip_helper(2, idx); +} + +/* + * Test that a server attempting to read early data will abort if it tries to + * skip over too much. + */ +static int test_early_data_skip_abort(int idx) +{ + return early_data_skip_helper(3, idx); +} + /* * Test that a server attempting to read early data can handle a connection * from a client that doesn't send any. @@ -2202,15 +3170,6 @@ static int test_early_data_not_sent(int idx) || !TEST_size_t_eq(written, strlen(MSG2))) goto end; - /* - * Should block due to the NewSessionTicket arrival unless we're using - * read_ahead - */ - if (idx != 1) { - if (!TEST_false(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes))) - goto end; - } - if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)) || !TEST_mem_eq(buf, readbytes, MSG2, strlen(MSG2))) goto end; @@ -2218,8 +3177,8 @@ static int test_early_data_not_sent(int idx) testresult = 1; end: - /* If using PSK then clientpsk and sess are the same */ SSL_SESSION_free(sess); + SSL_SESSION_free(clientpsk); SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; SSL_free(serverssl); @@ -2427,6 +3386,7 @@ static int test_early_data_psk(int idx) testresult = 1; end: + SSL_SESSION_free(sess); SSL_SESSION_free(clientpsk); SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; @@ -2484,8 +3444,8 @@ static int test_early_data_not_expected(int idx) testresult = 1; end: - /* If using PSK then clientpsk and sess are the same */ SSL_SESSION_free(sess); + SSL_SESSION_free(clientpsk); SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; SSL_free(serverssl); @@ -2558,7 +3518,6 @@ static int test_early_data_tls1_2(int idx) testresult = 1; end: - /* If using PSK then clientpsk and sess are the same */ SSL_SESSION_free(clientpsk); SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; @@ -2592,7 +3551,7 @@ static int test_set_ciphersuite(int idx) int testresult = 0; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey)) || !TEST_true(SSL_CTX_set_ciphersuites(sctx, "TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256"))) @@ -2662,7 +3621,7 @@ static int test_ciphersuite_change(void) /* Create a session based on SHA-256 */ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey)) || !TEST_true(SSL_CTX_set_ciphersuites(cctx, "TLS_AES_128_GCM_SHA256")) @@ -2781,6 +3740,122 @@ static int test_ciphersuite_change(void) return testresult; } +/* + * Test TLSv1.3 Key exchange + * Test 0 = Test ECDHE Key exchange + * Test 1 = Test ECDHE with TLSv1.2 client and TLSv1.2 server + * Test 2 = Test FFDHE Key exchange + * Test 3 = Test FFDHE with TLSv1.2 client and TLSv1.2 server + */ +static int test_tls13_key_exchange(int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; +#ifndef OPENSSL_NO_EC + int ecdhe_kexch_groups[] = {NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, + NID_X25519, NID_X448}; +#endif +#ifndef OPENSSL_NO_DH + int ffdhe_kexch_groups[] = {NID_ffdhe2048, NID_ffdhe3072, NID_ffdhe4096, + NID_ffdhe6144, NID_ffdhe8192}; +#endif + int *kexch_groups = NULL; + int kexch_groups_size = 0; + int max_version = TLS1_3_VERSION; + int want_err = SSL_ERROR_NONE; + int expected_err_func = 0; + int expected_err_reason = 0; + + switch (idx) { +#ifndef OPENSSL_NO_DH + case 3: + max_version = TLS1_2_VERSION; + /* Fall through */ + case 2: + kexch_groups = ffdhe_kexch_groups; + kexch_groups_size = OSSL_NELEM(ffdhe_kexch_groups); + break; +#endif +#ifndef OPENSSL_NO_EC + case 1: + max_version = TLS1_2_VERSION; + /* Fall through */ + case 0: + kexch_groups = ecdhe_kexch_groups; + kexch_groups_size = OSSL_NELEM(ecdhe_kexch_groups); + break; +#endif + default: + /* We're skipping this test */ + return 1; + } + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), + TLS1_VERSION, max_version, + &sctx, &cctx, cert, privkey))) + goto end; + + if (!TEST_true(SSL_CTX_set_ciphersuites(sctx, TLS1_3_RFC_AES_128_GCM_SHA256))) + goto end; + + if (!TEST_true(SSL_CTX_set_ciphersuites(cctx, TLS1_3_RFC_AES_128_GCM_SHA256))) + goto end; + + if (!TEST_true(SSL_CTX_set_cipher_list(sctx, TLS1_TXT_RSA_WITH_AES_128_SHA))) + goto end; + + /* + * Must include an EC ciphersuite so that we send supported groups in + * TLSv1.2 + */ + if (!TEST_true(SSL_CTX_set_cipher_list(cctx, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CCM ":" + TLS1_TXT_RSA_WITH_AES_128_SHA))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + if (!TEST_true(SSL_set1_groups(serverssl, kexch_groups, kexch_groups_size)) + || !TEST_true(SSL_set1_groups(clientssl, kexch_groups, kexch_groups_size))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, want_err))) { + /* Fail only if no error is expected in handshake */ + if (expected_err_func == 0) + goto end; + } + + /* Fail if expected error is not happening for failure testcases */ + if (expected_err_func) { + unsigned long err_code = ERR_get_error(); + ERR_print_errors_fp(stdout); + if (TEST_int_eq(ERR_GET_FUNC(err_code), expected_err_func) + && TEST_int_eq(ERR_GET_REASON(err_code), expected_err_reason)) + testresult = 1; + goto end; + } + + /* + * If Handshake succeeds the negotiated kexch alg should the first one in + * configured, except in the case of FFDHE groups which are TLSv1.3 only + * so we expect no shared group to exist. + */ + if (!TEST_int_eq(SSL_get_shared_group(serverssl, 0), + idx == 3 ? 0 : kexch_groups[0])) + goto end; + + testresult = 1; + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + return testresult; +} + /* * Test TLSv1.3 PSKs * Test 0 = Test new style callbacks @@ -2802,7 +3877,7 @@ static int test_tls13_psk(int idx) int testresult = 0; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, idx == 3 ? NULL : cert, idx == 3 ? NULL : privkey))) goto end; @@ -2924,8 +3999,13 @@ static int test_tls13_psk(int idx) goto end; /* Force an HRR */ +#if defined(OPENSSL_NO_EC) + if (!TEST_true(SSL_set1_groups_list(serverssl, "ffdhe3072"))) + goto end; +#else if (!TEST_true(SSL_set1_groups_list(serverssl, "P-256"))) goto end; +#endif /* * Check we can create a connection, the PSK is used and the callbacks are @@ -3050,7 +4130,7 @@ static int test_stateless(void) int testresult = 0; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; @@ -3274,13 +4354,13 @@ static int test_custom_exts(int tst) snicb = 0; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; if (tst == 2 && !TEST_true(create_ssl_ctx_pair(TLS_server_method(), NULL, - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx2, NULL, cert, privkey))) goto end; @@ -3389,9 +4469,10 @@ static int test_custom_exts(int tst) || (tst == 2 && snicb != 1)) goto end; } else { + /* In this case there 2 NewSessionTicket messages created */ if (clntaddnewcb != 1 - || clntparsenewcb != 4 - || srvaddnewcb != 4 + || clntparsenewcb != 5 + || srvaddnewcb != 5 || srvparsenewcb != 1) goto end; } @@ -3435,10 +4516,13 @@ static int test_custom_exts(int tst) || srvparsenewcb != 2) goto end; } else { - /* No Certificate message extensions in the resumption handshake */ + /* + * No Certificate message extensions in the resumption handshake, + * 2 NewSessionTickets in the initial handshake, 1 in the resumption + */ if (clntaddnewcb != 2 - || clntparsenewcb != 7 - || srvaddnewcb != 7 + || clntparsenewcb != 8 + || srvaddnewcb != 8 || srvparsenewcb != 2) goto end; } @@ -3517,20 +4601,25 @@ static int test_serverinfo(int tst) * no test vectors so all we do is test that both sides of the communication * produce the same results for different protocol versions. */ +#define SMALL_LABEL_LEN 10 +#define LONG_LABEL_LEN 249 static int test_export_key_mat(int tst) { int testresult = 0; SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL; SSL *clientssl = NULL, *serverssl = NULL; - const char label[] = "test label"; + const char label[LONG_LABEL_LEN + 1] = "test label"; const unsigned char context[] = "context"; const unsigned char *emptycontext = NULL; unsigned char ckeymat1[80], ckeymat2[80], ckeymat3[80]; unsigned char skeymat1[80], skeymat2[80], skeymat3[80]; + size_t labellen; const int protocols[] = { TLS1_VERSION, TLS1_1_VERSION, TLS1_2_VERSION, + TLS1_3_VERSION, + TLS1_3_VERSION, TLS1_3_VERSION }; @@ -3547,11 +4636,11 @@ static int test_export_key_mat(int tst) return 1; #endif #ifdef OPENSSL_NO_TLS1_3 - if (tst == 3) + if (tst >= 3) return 1; #endif if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; @@ -3565,33 +4654,52 @@ static int test_export_key_mat(int tst) SSL_ERROR_NONE))) goto end; + if (tst == 5) { + /* + * TLSv1.3 imposes a maximum label len of 249 bytes. Check we fail if we + * go over that. + */ + if (!TEST_int_le(SSL_export_keying_material(clientssl, ckeymat1, + sizeof(ckeymat1), label, + LONG_LABEL_LEN + 1, context, + sizeof(context) - 1, 1), 0)) + goto end; + + testresult = 1; + goto end; + } else if (tst == 4) { + labellen = LONG_LABEL_LEN; + } else { + labellen = SMALL_LABEL_LEN; + } + if (!TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat1, sizeof(ckeymat1), label, - sizeof(label) - 1, context, + labellen, context, sizeof(context) - 1, 1), 1) || !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat2, sizeof(ckeymat2), label, - sizeof(label) - 1, + labellen, emptycontext, 0, 1), 1) || !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat3, sizeof(ckeymat3), label, - sizeof(label) - 1, + labellen, NULL, 0, 0), 1) || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat1, sizeof(skeymat1), label, - sizeof(label) - 1, + labellen, context, sizeof(context) -1, 1), 1) || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat2, sizeof(skeymat2), label, - sizeof(label) - 1, + labellen, emptycontext, 0, 1), 1) || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat3, sizeof(skeymat3), label, - sizeof(label) - 1, + labellen, NULL, 0, 0), 1) /* * Check that both sides created the same key material with the @@ -3620,10 +4728,10 @@ static int test_export_key_mat(int tst) * Check that an empty context and no context produce different results in * protocols less than TLSv1.3. In TLSv1.3 they should be the same. */ - if ((tst != 3 && !TEST_mem_ne(ckeymat2, sizeof(ckeymat2), ckeymat3, + if ((tst < 3 && !TEST_mem_ne(ckeymat2, sizeof(ckeymat2), ckeymat3, sizeof(ckeymat3))) - || (tst ==3 && !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), ckeymat3, - sizeof(ckeymat3)))) + || (tst >= 3 && !TEST_mem_eq(ckeymat2, sizeof(ckeymat2), ckeymat3, + sizeof(ckeymat3)))) goto end; testresult = 1; @@ -3704,8 +4812,7 @@ static int test_export_key_mat_early(int idx) testresult = 1; end: - if (sess != clientpsk) - SSL_SESSION_free(sess); + SSL_SESSION_free(sess); SSL_SESSION_free(clientpsk); SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; @@ -3716,6 +4823,148 @@ static int test_export_key_mat_early(int idx) return testresult; } + +#define NUM_KEY_UPDATE_MESSAGES 40 +/* + * Test KeyUpdate. + */ +static int test_key_update(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0, i, j; + char buf[20]; + static char *mess = "A test message"; + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_3_VERSION, + 0, + &sctx, &cctx, cert, privkey)) + || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + for (j = 0; j < 2; j++) { + /* Send lots of KeyUpdate messages */ + for (i = 0; i < NUM_KEY_UPDATE_MESSAGES; i++) { + if (!TEST_true(SSL_key_update(clientssl, + (j == 0) + ? SSL_KEY_UPDATE_NOT_REQUESTED + : SSL_KEY_UPDATE_REQUESTED)) + || !TEST_true(SSL_do_handshake(clientssl))) + goto end; + } + + /* Check that sending and receiving app data is ok */ + if (!TEST_int_eq(SSL_write(clientssl, mess, strlen(mess)), strlen(mess)) + || !TEST_int_eq(SSL_read(serverssl, buf, sizeof(buf)), + strlen(mess))) + goto end; + + if (!TEST_int_eq(SSL_write(serverssl, mess, strlen(mess)), strlen(mess)) + || !TEST_int_eq(SSL_read(clientssl, buf, sizeof(buf)), + strlen(mess))) + goto end; + } + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +/* + * Test we can handle a KeyUpdate (update requested) message while write data + * is pending. + * Test 0: Client sends KeyUpdate while Server is writing + * Test 1: Server sends KeyUpdate while Client is writing + */ +static int test_key_update_in_write(int tst) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + char buf[20]; + static char *mess = "A test message"; + BIO *bretry = BIO_new(bio_s_always_retry()); + BIO *tmp = NULL; + SSL *peerupdate = NULL, *peerwrite = NULL; + + if (!TEST_ptr(bretry) + || !TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_3_VERSION, + 0, + &sctx, &cctx, cert, privkey)) + || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + peerupdate = tst == 0 ? clientssl : serverssl; + peerwrite = tst == 0 ? serverssl : clientssl; + + if (!TEST_true(SSL_key_update(peerupdate, SSL_KEY_UPDATE_REQUESTED)) + || !TEST_true(SSL_do_handshake(peerupdate))) + goto end; + + /* Swap the writing endpoint's write BIO to force a retry */ + tmp = SSL_get_wbio(peerwrite); + if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) { + tmp = NULL; + goto end; + } + SSL_set0_wbio(peerwrite, bretry); + bretry = NULL; + + /* Write data that we know will fail with SSL_ERROR_WANT_WRITE */ + if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), -1) + || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE)) + goto end; + + /* Reinstate the original writing endpoint's write BIO */ + SSL_set0_wbio(peerwrite, tmp); + tmp = NULL; + + /* Now read some data - we will read the key update */ + if (!TEST_int_eq(SSL_read(peerwrite, buf, sizeof(buf)), -1) + || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ)) + goto end; + + /* + * Complete the write we started previously and read it from the other + * endpoint + */ + if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), strlen(mess)) + || !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess))) + goto end; + + /* Write more data to ensure we send the KeyUpdate message back */ + if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), strlen(mess)) + || !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess))) + goto end; + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + BIO_free(bretry); + BIO_free(tmp); + + return testresult; +} #endif /* OPENSSL_NO_TLS1_3 */ static int test_ssl_clear(int idx) @@ -3731,7 +4980,7 @@ static int test_ssl_clear(int idx) /* Create an initial connection */ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey)) || (idx == 1 && !TEST_true(SSL_CTX_set_max_proto_version(cctx, @@ -3777,12 +5026,16 @@ static int get_MFL_from_client_hello(BIO *bio, int *mfl_codemfl_code) { long len; unsigned char *data; - PACKET pkt = {0}, pkt2 = {0}, pkt3 = {0}; + PACKET pkt, pkt2, pkt3; unsigned int MFL_code = 0, type = 0; if (!TEST_uint_gt( len = BIO_get_mem_data( bio, (char **) &data ), 0 ) ) goto end; + memset(&pkt, 0, sizeof(pkt)); + memset(&pkt2, 0, sizeof(pkt2)); + memset(&pkt3, 0, sizeof(pkt3)); + if (!TEST_true( PACKET_buf_init( &pkt, data, len ) ) /* Skip the record header */ || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH) @@ -3887,7 +5140,7 @@ static int test_pha_key_update(void) int testresult = 0; if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) return 0; @@ -3897,13 +5150,12 @@ static int test_pha_key_update(void) || !TEST_true(SSL_CTX_set_max_proto_version(cctx, TLS1_3_VERSION))) goto end; + SSL_CTX_set_post_handshake_auth(cctx, 1); if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL))) goto end; - SSL_force_post_handshake_auth(clientssl); - if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) goto end; @@ -4111,7 +5363,7 @@ static int test_srp(int tst) } if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; @@ -4201,16 +5453,14 @@ static struct info_cb_states_st { {SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWEE"}, {SSL_CB_LOOP, "TWSC"}, {SSL_CB_LOOP, "TRSCV"}, {SSL_CB_LOOP, "TWFIN"}, {SSL_CB_LOOP, "TED"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TED"}, {SSL_CB_LOOP, "TRFIN"}, - {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_HANDSHAKE_START, NULL}, - {SSL_CB_LOOP, "TWST"}, {SSL_CB_HANDSHAKE_DONE, NULL}, - {SSL_CB_EXIT, NULL}, {SSL_CB_ALERT, NULL}, + {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_LOOP, "TWST"}, + {SSL_CB_LOOP, "TWST"}, {SSL_CB_EXIT, NULL}, {SSL_CB_ALERT, NULL}, {SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT "}, {SSL_CB_LOOP, "PINIT "}, {SSL_CB_LOOP, "TRCH"}, {SSL_CB_LOOP, "TWSH"}, {SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWEE"}, {SSL_CB_LOOP, "TWFIN"}, {SSL_CB_LOOP, "TED"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TED"}, {SSL_CB_LOOP, "TRFIN"}, {SSL_CB_HANDSHAKE_DONE, NULL}, - {SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "TWST"}, - {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL}, {0, NULL}, + {SSL_CB_LOOP, "TWST"}, {SSL_CB_EXIT, NULL}, {0, NULL}, }, { /* TLSv1.3 client followed by resumption */ {SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT "}, @@ -4218,17 +5468,16 @@ static struct info_cb_states_st { {SSL_CB_LOOP, "TRSH"}, {SSL_CB_LOOP, "TREE"}, {SSL_CB_LOOP, "TRSC"}, {SSL_CB_LOOP, "TRSCV"}, {SSL_CB_LOOP, "TRFIN"}, {SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWFIN"}, {SSL_CB_HANDSHAKE_DONE, NULL}, - {SSL_CB_EXIT, NULL}, {SSL_CB_HANDSHAKE_START, NULL}, - {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "TRST"}, - {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL}, + {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "SSLOK "}, + {SSL_CB_LOOP, "TRST"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "SSLOK "}, + {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "TRST"}, {SSL_CB_EXIT, NULL}, {SSL_CB_ALERT, NULL}, {SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT "}, {SSL_CB_LOOP, "TWCH"}, {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "TWCH"}, {SSL_CB_LOOP, "TRSH"}, {SSL_CB_LOOP, "TREE"}, {SSL_CB_LOOP, "TRFIN"}, {SSL_CB_LOOP, "TWCCS"}, {SSL_CB_LOOP, "TWFIN"}, {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL}, - {SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "SSLOK "}, - {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "TRST"}, - {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL}, {0, NULL}, + {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "TRST"}, + {SSL_CB_EXIT, NULL}, {0, NULL}, }, { /* TLSv1.3 server, early_data */ {SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT "}, @@ -4237,8 +5486,7 @@ static struct info_cb_states_st { {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL}, {SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "TED"}, {SSL_CB_LOOP, "TED"}, {SSL_CB_LOOP, "TWEOED"}, {SSL_CB_LOOP, "TRFIN"}, - {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_HANDSHAKE_START, NULL}, - {SSL_CB_LOOP, "TWST"}, {SSL_CB_HANDSHAKE_DONE, NULL}, + {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_LOOP, "TWST"}, {SSL_CB_EXIT, NULL}, {0, NULL}, }, { /* TLSv1.3 client, early_data */ @@ -4249,9 +5497,8 @@ static struct info_cb_states_st { {SSL_CB_LOOP, "TED"}, {SSL_CB_LOOP, "TRSH"}, {SSL_CB_LOOP, "TREE"}, {SSL_CB_LOOP, "TRFIN"}, {SSL_CB_LOOP, "TPEDE"}, {SSL_CB_LOOP, "TWEOED"}, {SSL_CB_LOOP, "TWFIN"}, {SSL_CB_HANDSHAKE_DONE, NULL}, - {SSL_CB_EXIT, NULL}, {SSL_CB_HANDSHAKE_START, NULL}, - {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "TRST"}, - {SSL_CB_HANDSHAKE_DONE, NULL}, {SSL_CB_EXIT, NULL}, {0, NULL}, + {SSL_CB_EXIT, NULL}, {SSL_CB_LOOP, "SSLOK "}, {SSL_CB_LOOP, "SSLOK "}, + {SSL_CB_LOOP, "TRST"}, {SSL_CB_EXIT, NULL}, {0, NULL}, }, { {0, NULL}, } @@ -4290,8 +5537,11 @@ static void sslapi_info_callback(const SSL *s, int where, int ret) return; } - /* Check that, if we've got SSL_CB_HANDSHAKE_DONE we are not in init */ - if ((where & SSL_CB_HANDSHAKE_DONE) && SSL_in_init((SSL *)s) != 0) { + /* + * Check that, if we've got SSL_CB_HANDSHAKE_DONE we are not in init + */ + if ((where & SSL_CB_HANDSHAKE_DONE) + && SSL_in_init((SSL *)s) != 0) { info_cb_failed = 1; return; } @@ -4316,7 +5566,9 @@ static int test_info_callback(int tst) int tlsvers; if (tst < 2) { -#ifndef OPENSSL_NO_TLS1_2 +/* We need either ECDHE or DHE for the TLSv1.2 test to work */ +#if !defined(OPENSSL_NO_TLS1_2) && (!defined(OPENSSL_NO_EC) \ + || !defined(OPENSSL_NO_DH)) tlsvers = TLS1_2_VERSION; #else return 1; @@ -4433,14 +5685,14 @@ static int test_ssl_pending(int tst) if (tst == 0) { if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), - TLS1_VERSION, TLS_MAX_VERSION, + TLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; } else { #ifndef OPENSSL_NO_DTLS if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(), DTLS_client_method(), - DTLS1_VERSION, DTLS_MAX_VERSION, + DTLS1_VERSION, 0, &sctx, &cctx, cert, privkey))) goto end; #else @@ -4593,17 +5845,768 @@ static int test_ssl_get_shared_ciphers(int tst) return testresult; } -int setup_tests(void) +static const char *appdata = "Hello World"; +static int gen_tick_called, dec_tick_called, tick_key_cb_called; +static int tick_key_renew = 0; +static SSL_TICKET_RETURN tick_dec_ret = SSL_TICKET_RETURN_ABORT; + +static int gen_tick_cb(SSL *s, void *arg) { - if (!TEST_ptr(cert = test_get_argument(0)) - || !TEST_ptr(privkey = test_get_argument(1)) - || !TEST_ptr(srpvfile = test_get_argument(2)) - || !TEST_ptr(tmpfilename = test_get_argument(3))) - return 0; + gen_tick_called = 1; - if (getenv("OPENSSL_TEST_GETCOUNTS") != NULL) { -#ifdef OPENSSL_NO_CRYPTO_MDEBUG - TEST_error("not supported in this build"); + return SSL_SESSION_set1_ticket_appdata(SSL_get_session(s), appdata, + strlen(appdata)); +} + +static SSL_TICKET_RETURN dec_tick_cb(SSL *s, SSL_SESSION *ss, + const unsigned char *keyname, + size_t keyname_length, + SSL_TICKET_STATUS status, + void *arg) +{ + void *tickdata; + size_t tickdlen; + + dec_tick_called = 1; + + if (status == SSL_TICKET_EMPTY) + return SSL_TICKET_RETURN_IGNORE_RENEW; + + if (!TEST_true(status == SSL_TICKET_SUCCESS + || status == SSL_TICKET_SUCCESS_RENEW)) + return SSL_TICKET_RETURN_ABORT; + + if (!TEST_true(SSL_SESSION_get0_ticket_appdata(ss, &tickdata, + &tickdlen)) + || !TEST_size_t_eq(tickdlen, strlen(appdata)) + || !TEST_int_eq(memcmp(tickdata, appdata, tickdlen), 0)) + return SSL_TICKET_RETURN_ABORT; + + if (tick_key_cb_called) { + /* Don't change what the ticket key callback wanted to do */ + switch (status) { + case SSL_TICKET_NO_DECRYPT: + return SSL_TICKET_RETURN_IGNORE_RENEW; + + case SSL_TICKET_SUCCESS: + return SSL_TICKET_RETURN_USE; + + case SSL_TICKET_SUCCESS_RENEW: + return SSL_TICKET_RETURN_USE_RENEW; + + default: + return SSL_TICKET_RETURN_ABORT; + } + } + return tick_dec_ret; + +} + +static int tick_key_cb(SSL *s, unsigned char key_name[16], + unsigned char iv[EVP_MAX_IV_LENGTH], EVP_CIPHER_CTX *ctx, + HMAC_CTX *hctx, int enc) +{ + const unsigned char tick_aes_key[16] = "0123456789abcdef"; + const unsigned char tick_hmac_key[16] = "0123456789abcdef"; + + tick_key_cb_called = 1; + memset(iv, 0, AES_BLOCK_SIZE); + memset(key_name, 0, 16); + if (!EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, tick_aes_key, iv, enc) + || !HMAC_Init_ex(hctx, tick_hmac_key, sizeof(tick_hmac_key), + EVP_sha256(), NULL)) + return -1; + + return tick_key_renew ? 2 : 1; +} + +/* + * Test the various ticket callbacks + * Test 0: TLSv1.2, no ticket key callback, no ticket, no renewal + * Test 1: TLSv1.3, no ticket key callback, no ticket, no renewal + * Test 2: TLSv1.2, no ticket key callback, no ticket, renewal + * Test 3: TLSv1.3, no ticket key callback, no ticket, renewal + * Test 4: TLSv1.2, no ticket key callback, ticket, no renewal + * Test 5: TLSv1.3, no ticket key callback, ticket, no renewal + * Test 6: TLSv1.2, no ticket key callback, ticket, renewal + * Test 7: TLSv1.3, no ticket key callback, ticket, renewal + * Test 8: TLSv1.2, ticket key callback, ticket, no renewal + * Test 9: TLSv1.3, ticket key callback, ticket, no renewal + * Test 10: TLSv1.2, ticket key callback, ticket, renewal + * Test 11: TLSv1.3, ticket key callback, ticket, renewal + */ +static int test_ticket_callbacks(int tst) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + SSL_SESSION *clntsess = NULL; + int testresult = 0; + +#ifdef OPENSSL_NO_TLS1_2 + if (tst % 2 == 0) + return 1; +#endif +#ifdef OPENSSL_NO_TLS1_3 + if (tst % 2 == 1) + return 1; +#endif + + 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) + tick_key_renew = 1; + else + tick_key_renew = 0; + + /* Which tests the decrypt ticket callback should request renewal for */ + switch (tst) { + case 0: + case 1: + tick_dec_ret = SSL_TICKET_RETURN_IGNORE; + break; + + case 2: + case 3: + tick_dec_ret = SSL_TICKET_RETURN_IGNORE_RENEW; + break; + + case 4: + case 5: + tick_dec_ret = SSL_TICKET_RETURN_USE; + break; + + case 6: + case 7: + tick_dec_ret = SSL_TICKET_RETURN_USE_RENEW; + break; + + default: + tick_dec_ret = SSL_TICKET_RETURN_ABORT; + } + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_VERSION, + ((tst % 2) == 0) ? TLS1_2_VERSION + : TLS1_3_VERSION, + &sctx, &cctx, cert, privkey))) + goto end; + + /* + * We only want sessions to resume from tickets - not the session cache. So + * switch the cache off. + */ + if (!TEST_true(SSL_CTX_set_session_cache_mode(sctx, SSL_SESS_CACHE_OFF))) + goto end; + + if (!TEST_true(SSL_CTX_set_session_ticket_cb(sctx, gen_tick_cb, dec_tick_cb, + NULL))) + goto end; + + if (tst >= 8 + && !TEST_true(SSL_CTX_set_tlsext_ticket_key_cb(sctx, tick_key_cb))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + /* + * The decrypt ticket key callback in TLSv1.2 should be called even though + * we have no ticket yet, because it gets called with a status of + * SSL_TICKET_EMPTY (the client indicates support for tickets but does not + * actually send any ticket data). This does not happen in TLSv1.3 because + * it is not valid to send empty ticket data in TLSv1.3. + */ + if (!TEST_int_eq(gen_tick_called, 1) + || !TEST_int_eq(dec_tick_called, ((tst % 2) == 0) ? 1 : 0)) + goto end; + + gen_tick_called = dec_tick_called = 0; + + clntsess = SSL_get1_session(clientssl); + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + + /* Now do a resumption */ + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, + NULL)) + || !TEST_true(SSL_set_session(clientssl, clntsess)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + if (tick_dec_ret == SSL_TICKET_RETURN_IGNORE + || tick_dec_ret == SSL_TICKET_RETURN_IGNORE_RENEW) { + if (!TEST_false(SSL_session_reused(clientssl))) + goto end; + } else { + if (!TEST_true(SSL_session_reused(clientssl))) + goto end; + } + + if (!TEST_int_eq(gen_tick_called, + (tick_key_renew + || tick_dec_ret == SSL_TICKET_RETURN_IGNORE_RENEW + || tick_dec_ret == SSL_TICKET_RETURN_USE_RENEW) + ? 1 : 0) + || !TEST_int_eq(dec_tick_called, 1)) + goto end; + + testresult = 1; + + end: + SSL_SESSION_free(clntsess); + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +/* + * Test bi-directional shutdown. + * Test 0: TLSv1.2 + * Test 1: TLSv1.2, server continues to read/write after client shutdown + * Test 2: TLSv1.3, no pending NewSessionTicket messages + * 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, 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) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + char msg[] = "A test message"; + char buf[80]; + size_t written, readbytes; + SSL_SESSION *sess; + +#ifdef OPENSSL_NO_TLS1_2 + if (tst <= 1) + return 1; +#endif +#ifdef OPENSSL_NO_TLS1_3 + if (tst >= 2) + return 1; +#endif + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_VERSION, + (tst <= 1) ? TLS1_2_VERSION + : TLS1_3_VERSION, + &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; + + if (tst == 3) { + if (!TEST_true(create_bare_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE, 1)) + || !TEST_ptr_ne(sess = SSL_get_session(clientssl), NULL) + || !TEST_false(SSL_SESSION_is_resumable(sess))) + goto end; + } else if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_ptr_ne(sess = SSL_get_session(clientssl), NULL) + || !TEST_true(SSL_SESSION_is_resumable(sess))) { + goto end; + } + + if (!TEST_int_eq(SSL_shutdown(clientssl), 0)) + goto end; + + if (tst >= 4) { + /* + * Reading on the server after the client has sent close_notify should + * fail and provide SSL_ERROR_ZERO_RETURN + */ + if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes)) + || !TEST_int_eq(SSL_get_error(serverssl, 0), + SSL_ERROR_ZERO_RETURN) + || !TEST_int_eq(SSL_get_shutdown(serverssl), + SSL_RECEIVED_SHUTDOWN) + /* + * Even though we're shutdown on receive we should still be + * able to write. + */ + || !TEST_true(SSL_write(serverssl, msg, sizeof(msg)))) + goto end; + 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 || tst == 5) { + /* Should still be able to read data from server */ + if (!TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), + &readbytes)) + || !TEST_size_t_eq(readbytes, sizeof(msg)) + || !TEST_int_eq(memcmp(msg, buf, readbytes), 0) + || !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), + &readbytes)) + || !TEST_size_t_eq(readbytes, sizeof(msg)) + || !TEST_int_eq(memcmp(msg, buf, readbytes), 0)) + goto end; + } + } + + /* Writing on the client after sending close_notify shouldn't be possible */ + if (!TEST_false(SSL_write_ex(clientssl, msg, sizeof(msg), &written))) + goto end; + + if (tst < 4) { + /* + * For these tests the client has sent close_notify but it has not yet + * been received by the server. The server has not sent close_notify + * yet. + */ + if (!TEST_int_eq(SSL_shutdown(serverssl), 0) + /* + * Writing on the server after sending close_notify shouldn't + * be possible. + */ + || !TEST_false(SSL_write_ex(serverssl, msg, sizeof(msg), &written)) + || !TEST_int_eq(SSL_shutdown(clientssl), 1) + || !TEST_ptr_ne(sess = SSL_get_session(clientssl), NULL) + || !TEST_true(SSL_SESSION_is_resumable(sess)) + || !TEST_int_eq(SSL_shutdown(serverssl), 1)) + goto end; + } 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 + * client needs to read the close_notify sent by the server. + */ + if (!TEST_int_eq(SSL_shutdown(clientssl), 1) + || !TEST_ptr_ne(sess = SSL_get_session(clientssl), NULL) + || !TEST_true(SSL_SESSION_is_resumable(sess))) + goto end; + } else { + /* + * tst == 6 + * + * The client has sent close_notify and is expecting a close_notify + * back, but instead there is application data first. The shutdown + * should fail with a fatal error. + */ + if (!TEST_int_eq(SSL_shutdown(clientssl), -1) + || !TEST_int_eq(SSL_get_error(clientssl, -1), SSL_ERROR_SSL)) + 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) +static int cert_cb_cnt; + +static int cert_cb(SSL *s, void *arg) +{ + SSL_CTX *ctx = (SSL_CTX *)arg; + BIO *in = NULL; + EVP_PKEY *pkey = NULL; + X509 *x509 = NULL; + + 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; + } else if (cert_cb_cnt == 3) { + int rv; + if (!TEST_ptr(in = BIO_new(BIO_s_file())) + || !TEST_int_ge(BIO_read_filename(in, cert), 0) + || !TEST_ptr(x509 = PEM_read_bio_X509(in, NULL, NULL, NULL))) + goto out; + BIO_free(in); + if (!TEST_ptr(in = BIO_new(BIO_s_file())) + || !TEST_int_ge(BIO_read_filename(in, privkey), 0) + || !TEST_ptr(pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL))) + goto out; + rv = SSL_check_chain(s, x509, pkey, NULL); + /* + * If the cert doesn't show as valid here (e.g., because we don't + * have any shared sigalgs), then we will not set it, and there will + * be no certificate at all on the SSL or SSL_CTX. This, in turn, + * will cause tls_choose_sigalgs() to fail the connection. + */ + if ((rv & CERT_PKEY_VALID)) { + if (!SSL_use_cert_and_key(s, x509, pkey, NULL, 1)) + goto out; + } + BIO_free(in); + EVP_PKEY_free(pkey); + X509_free(x509); + return 1; + } + + /* Abort the handshake */ + out: + BIO_free(in); + EVP_PKEY_free(pkey); + X509_free(x509); + 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 if (tst == 3) + cert_cb_cnt = 3; + 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) * (cert_cb_cnt - 3), 0))) { + 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; +} + + +OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile\n") + +int setup_tests(void) +{ + if (!TEST_ptr(cert = test_get_argument(0)) + || !TEST_ptr(privkey = test_get_argument(1)) + || !TEST_ptr(srpvfile = test_get_argument(2)) + || !TEST_ptr(tmpfilename = test_get_argument(3))) + return 0; + + if (getenv("OPENSSL_TEST_GETCOUNTS") != NULL) { +#ifdef OPENSSL_NO_CRYPTO_MDEBUG + TEST_error("not supported in this build"); return 0; #else int i, mcount, rcount, fcount; @@ -4617,6 +6620,26 @@ int setup_tests(void) #endif } +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_KTLS) \ + && !defined(OPENSSL_NO_SOCK) + ADD_TEST(test_ktls_no_txrx_client_no_txrx_server); + ADD_TEST(test_ktls_no_rx_client_no_txrx_server); + ADD_TEST(test_ktls_no_tx_client_no_txrx_server); + ADD_TEST(test_ktls_client_no_txrx_server); + ADD_TEST(test_ktls_no_txrx_client_no_rx_server); + ADD_TEST(test_ktls_no_rx_client_no_rx_server); + ADD_TEST(test_ktls_no_tx_client_no_rx_server); + ADD_TEST(test_ktls_client_no_rx_server); + ADD_TEST(test_ktls_no_txrx_client_no_tx_server); + ADD_TEST(test_ktls_no_rx_client_no_tx_server); + ADD_TEST(test_ktls_no_tx_client_no_tx_server); + ADD_TEST(test_ktls_client_no_tx_server); + ADD_TEST(test_ktls_no_txrx_client_server); + ADD_TEST(test_ktls_no_rx_client_server); + ADD_TEST(test_ktls_no_tx_client_server); + ADD_TEST(test_ktls_client_server); + ADD_TEST(test_ktls_sendfile); +#endif ADD_TEST(test_large_message_tls); ADD_TEST(test_large_message_tls_read_ahead); #ifndef OPENSSL_NO_DTLS @@ -4628,6 +6651,11 @@ int setup_tests(void) ADD_TEST(test_session_with_only_int_cache); ADD_TEST(test_session_with_only_ext_cache); ADD_TEST(test_session_with_both_cache); +#ifndef OPENSSL_NO_TLS1_3 + ADD_ALL_TESTS(test_stateful_tickets, 3); + ADD_ALL_TESTS(test_stateless_tickets, 3); + ADD_TEST(test_psk_tickets); +#endif ADD_ALL_TESTS(test_ssl_set_bio, TOTAL_SSL_SET_BIO_TESTS); ADD_TEST(test_ssl_bio_pop_next_bio); ADD_TEST(test_ssl_bio_pop_ssl_bio); @@ -4642,6 +6670,7 @@ int setup_tests(void) #endif #ifndef OPENSSL_NO_TLS1_2 ADD_TEST(test_client_hello_cb); + ADD_TEST(test_no_ems); #endif #ifndef OPENSSL_NO_TLS1_3 ADD_ALL_TESTS(test_early_data_read_write, 3); @@ -4652,6 +6681,8 @@ int setup_tests(void) ADD_ALL_TESTS(test_early_data_replay, 2); ADD_ALL_TESTS(test_early_data_skip, 3); ADD_ALL_TESTS(test_early_data_skip_hrr, 3); + ADD_ALL_TESTS(test_early_data_skip_hrr_fail, 3); + ADD_ALL_TESTS(test_early_data_skip_abort, 3); ADD_ALL_TESTS(test_early_data_not_sent, 3); ADD_ALL_TESTS(test_early_data_psk, 8); ADD_ALL_TESTS(test_early_data_not_expected, 3); @@ -4667,6 +6698,7 @@ int setup_tests(void) #else ADD_ALL_TESTS(test_tls13_psk, 4); #endif /* OPENSSL_NO_PSK */ + ADD_ALL_TESTS(test_tls13_key_exchange, 4); ADD_ALL_TESTS(test_custom_exts, 5); ADD_TEST(test_stateless); ADD_TEST(test_pha_key_update); @@ -4674,9 +6706,11 @@ int setup_tests(void) ADD_ALL_TESTS(test_custom_exts, 3); #endif ADD_ALL_TESTS(test_serverinfo, 8); - ADD_ALL_TESTS(test_export_key_mat, 4); + ADD_ALL_TESTS(test_export_key_mat, 6); #ifndef OPENSSL_NO_TLS1_3 ADD_ALL_TESTS(test_export_key_mat_early, 3); + ADD_TEST(test_key_update); + ADD_ALL_TESTS(test_key_update_in_write, 2); #endif ADD_ALL_TESTS(test_ssl_clear, 2); ADD_ALL_TESTS(test_max_fragment_len_ext, OSSL_NELEM(max_fragment_len_test)); @@ -4686,10 +6720,16 @@ int setup_tests(void) ADD_ALL_TESTS(test_info_callback, 6); 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, 7); + ADD_ALL_TESTS(test_cert_cb, 4); + ADD_ALL_TESTS(test_client_cert_cb, 2); + ADD_ALL_TESTS(test_ca_names, 3); return 1; } void cleanup_tests(void) { bio_s_mempacket_test_free(); + bio_s_always_retry_free(); }