X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=test%2Fsslapitest.c;h=cdac8bc4549d912d64051c449f985397e8788891;hp=338c61c6c0faef382a312449929f27fec8960aa4;hb=0d1b778901764f9bc747674f0e23b40c82877e6e;hpb=7d4488bbd7ac34fffb776cccbfff6b4ac0387e03 diff --git a/test/sslapitest.c b/test/sslapitest.c index 338c61c6c0..cdac8bc454 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "ssltestlib.h" #include "testutil.h" @@ -28,7 +29,7 @@ static char *privkey = NULL; static char *srpvfile = NULL; static char *tmpfilename = NULL; -#define LOG_BUFFER_SIZE 1024 +#define LOG_BUFFER_SIZE 2048 static char server_log_buffer[LOG_BUFFER_SIZE + 1] = {0}; static size_t server_log_buffer_index = 0; static char client_log_buffer[LOG_BUFFER_SIZE + 1] = {0}; @@ -54,10 +55,13 @@ static X509 *ocspcert = NULL; struct sslapitest_log_counts { unsigned int rsa_key_exchange_count; unsigned int master_secret_count; + unsigned int client_early_secret_count; unsigned int client_handshake_secret_count; unsigned int server_handshake_secret_count; unsigned int client_application_secret_count; unsigned int server_application_secret_count; + unsigned int early_exporter_secret_count; + unsigned int exporter_secret_count; }; @@ -139,10 +143,13 @@ static int test_keylog_output(char *buffer, const SSL *ssl, size_t master_key_size = SSL_MAX_MASTER_KEY_LENGTH; unsigned int rsa_key_exchange_count = 0; unsigned int master_secret_count = 0; + unsigned int client_early_secret_count = 0; unsigned int client_handshake_secret_count = 0; unsigned int server_handshake_secret_count = 0; unsigned int client_application_secret_count = 0; unsigned int server_application_secret_count = 0; + unsigned int early_exporter_secret_count = 0; + unsigned int exporter_secret_count = 0; for (token = strtok(buffer, " \n"); token != NULL; token = strtok(NULL, " \n")) { @@ -196,17 +203,22 @@ static int test_keylog_output(char *buffer, const SSL *ssl, master_key_size))) return 0; master_secret_count++; - } else if (strcmp(token, "CLIENT_HANDSHAKE_TRAFFIC_SECRET") == 0 + } else if (strcmp(token, "CLIENT_EARLY_TRAFFIC_SECRET") == 0 + || strcmp(token, "CLIENT_HANDSHAKE_TRAFFIC_SECRET") == 0 || strcmp(token, "SERVER_HANDSHAKE_TRAFFIC_SECRET") == 0 || strcmp(token, "CLIENT_TRAFFIC_SECRET_0") == 0 - || strcmp(token, "SERVER_TRAFFIC_SECRET_0") == 0) { + || strcmp(token, "SERVER_TRAFFIC_SECRET_0") == 0 + || strcmp(token, "EARLY_EXPORTER_SECRET") == 0 + || strcmp(token, "EXPORTER_SECRET") == 0) { /* * TLSv1.3 secret. Tokens should be: 64 ASCII bytes of hex-encoded * client random, and then the hex-encoded secret. In this case, * we treat all of these secrets identically and then just * distinguish between them when counting what we saw. */ - if (strcmp(token, "CLIENT_HANDSHAKE_TRAFFIC_SECRET") == 0) + if (strcmp(token, "CLIENT_EARLY_TRAFFIC_SECRET") == 0) + client_early_secret_count++; + else if (strcmp(token, "CLIENT_HANDSHAKE_TRAFFIC_SECRET") == 0) client_handshake_secret_count++; else if (strcmp(token, "SERVER_HANDSHAKE_TRAFFIC_SECRET") == 0) server_handshake_secret_count++; @@ -214,6 +226,10 @@ static int test_keylog_output(char *buffer, const SSL *ssl, client_application_secret_count++; else if (strcmp(token, "SERVER_TRAFFIC_SECRET_0") == 0) server_application_secret_count++; + else if (strcmp(token, "EARLY_EXPORTER_SECRET") == 0) + early_exporter_secret_count++; + else if (strcmp(token, "EXPORTER_SECRET") == 0) + exporter_secret_count++; client_random_size = SSL_get_client_random(ssl, actual_client_random, @@ -247,6 +263,8 @@ static int test_keylog_output(char *buffer, const SSL *ssl, expected->rsa_key_exchange_count) || !TEST_size_t_eq(master_secret_count, expected->master_secret_count) + || !TEST_size_t_eq(client_early_secret_count, + expected->client_early_secret_count) || !TEST_size_t_eq(client_handshake_secret_count, expected->client_handshake_secret_count) || !TEST_size_t_eq(server_handshake_secret_count, @@ -254,7 +272,11 @@ static int test_keylog_output(char *buffer, const SSL *ssl, || !TEST_size_t_eq(client_application_secret_count, expected->client_application_secret_count) || !TEST_size_t_eq(server_application_secret_count, - expected->server_application_secret_count)) + expected->server_application_secret_count) + || !TEST_size_t_eq(early_exporter_secret_count, + expected->early_exporter_secret_count) + || !TEST_size_t_eq(exporter_secret_count, + expected->exporter_secret_count)) return 0; return 1; } @@ -344,8 +366,11 @@ static int test_keylog_no_master_key(void) { SSL_CTX *cctx = NULL, *sctx = NULL; SSL *clientssl = NULL, *serverssl = NULL; + SSL_SESSION *sess = NULL; int testresult = 0; struct sslapitest_log_counts expected = {0}; + unsigned char buf[1]; + size_t readbytes, written; /* Clean up logging space */ memset(client_log_buffer, 0, sizeof(client_log_buffer)); @@ -356,7 +381,9 @@ static int test_keylog_no_master_key(void) if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), TLS1_VERSION, TLS_MAX_VERSION, - &sctx, &cctx, cert, privkey))) + &sctx, &cctx, cert, privkey)) + || !TEST_true(SSL_CTX_set_max_early_data(sctx, + SSL3_RT_MAX_PLAIN_LENGTH))) return 0; if (!TEST_true(SSL_CTX_get_keylog_callback(cctx) == NULL) @@ -390,6 +417,46 @@ static int test_keylog_no_master_key(void) expected.server_handshake_secret_count = 1; expected.client_application_secret_count = 1; expected.server_application_secret_count = 1; + expected.exporter_secret_count = 1; + if (!TEST_true(test_keylog_output(client_log_buffer, clientssl, + SSL_get_session(clientssl), &expected)) + || !TEST_true(test_keylog_output(server_log_buffer, serverssl, + SSL_get_session(serverssl), + &expected))) + goto end; + + /* Terminate old session and resume with early data. */ + sess = SSL_get1_session(clientssl); + SSL_shutdown(clientssl); + SSL_shutdown(serverssl); + SSL_free(serverssl); + SSL_free(clientssl); + serverssl = clientssl = NULL; + + /* Reset key log */ + memset(client_log_buffer, 0, sizeof(client_log_buffer)); + memset(server_log_buffer, 0, sizeof(server_log_buffer)); + client_log_buffer_index = 0; + server_log_buffer_index = 0; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, + &clientssl, NULL, NULL)) + || !TEST_true(SSL_set_session(clientssl, sess)) + /* Here writing 0 length early data is enough. */ + || !TEST_true(SSL_write_early_data(clientssl, NULL, 0, &written)) + || !TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf), + &readbytes), + SSL_READ_EARLY_DATA_ERROR) + || !TEST_int_eq(SSL_get_early_data_status(serverssl), + SSL_EARLY_DATA_ACCEPTED) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_true(SSL_session_reused(clientssl))) + goto end; + + /* In addition to the previous entries, expect early secrets. */ + expected.client_early_secret_count = 1; + expected.early_exporter_secret_count = 1; if (!TEST_true(test_keylog_output(client_log_buffer, clientssl, SSL_get_session(clientssl), &expected)) || !TEST_true(test_keylog_output(server_log_buffer, serverssl, @@ -400,6 +467,7 @@ static int test_keylog_no_master_key(void) testresult = 1; end: + SSL_SESSION_free(sess); SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx); @@ -814,10 +882,14 @@ 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, &sctx, &cctx, cert, privkey))) @@ -855,7 +927,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; @@ -870,7 +944,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) @@ -904,7 +979,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; @@ -987,7 +1063,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)) @@ -997,14 +1074,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; @@ -1013,7 +1103,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; @@ -1037,10 +1127,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; @@ -1113,6 +1199,136 @@ 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 test_tickets(int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0, i; + size_t j; + + /* idx is the test number, but also the number of tickets we want */ + + new_called = 0; + do_cache = 1; + + 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_num_tickets(sctx, idx))) + goto end; + + 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); + + 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)) + /* 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; + + /* 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_force_post_handshake_auth(clientssl); + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_true(SSL_session_reused(clientssl)) + /* Following a resumption we only get 1 ticket */ + || !TEST_int_eq(new_called, 1)) + goto end; + + new_called = 0; + /* After a post-handshake authentication we should get 1 new ticket */ + if (!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; + } + + 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; +} +#endif + #define USE_NULL 0 #define USE_BIO_1 1 #define USE_BIO_2 2 @@ -1130,7 +1346,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 @@ -1633,13 +1848,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)) - || !TEST_true(SSL_CTX_set_max_early_data(*cctx, - SSL3_RT_MAX_PLAIN_LENGTH))) + if (*sctx == NULL + && !TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_VERSION, TLS_MAX_VERSION, + 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) { @@ -1703,8 +1919,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; } @@ -1860,10 +2083,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 */ @@ -1873,9 +2099,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; @@ -1925,8 +2149,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; @@ -1937,12 +2160,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, TLS_MAX_VERSION, &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))) @@ -1964,21 +2240,55 @@ 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; + + /* 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; + + 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: - if (sess != clientpsk) - SSL_SESSION_free(sess); + SSL_SESSION_free(sess); SSL_SESSION_free(clientpsk); SSL_SESSION_free(serverpsk); clientpsk = serverpsk = NULL; @@ -1989,11 +2299,26 @@ 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 == 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; @@ -2006,7 +2331,7 @@ static int early_data_skip_helper(int hrr, int idx) &serverssl, &sess, idx))) goto end; - if (hrr) { + if (testtype == 1) { /* Force an HRR to occur */ if (!TEST_true(SSL_set1_groups_list(serverssl, "P-256"))) goto end; @@ -2026,13 +2351,17 @@ static int early_data_skip_helper(int hrr, int idx) goto end; } + if (testtype == 2 + && !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) @@ -2041,7 +2370,7 @@ static int early_data_skip_helper(int hrr, int idx) SSL_EARLY_DATA_REJECTED)) goto end; - if (hrr) { + if (testtype == 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 @@ -2051,9 +2380,24 @@ static int early_data_skip_helper(int hrr, int idx) || !TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf), &readbytes))) goto end; + } else if (testtype == 2) { + /* + * This client has sent more early_data than we are willing to skip 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; } - /* 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), @@ -2065,8 +2409,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); @@ -2095,6 +2438,15 @@ 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 will abort if it tries to + * skip over too much. + */ +static int test_early_data_skip_abort(int idx) +{ + return early_data_skip_helper(2, idx); +} + /* * Test that a server attempting to read early data can handle a connection * from a client that doesn't send any. @@ -2137,15 +2489,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; @@ -2153,8 +2496,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); @@ -2362,6 +2705,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; @@ -2419,8 +2763,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); @@ -2493,7 +2837,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; @@ -2716,6 +3059,13 @@ static int test_ciphersuite_change(void) return testresult; } +/* + * Test TLSv1.3 PSKs + * Test 0 = Test new style callbacks + * Test 1 = Test both new and old style callbacks + * Test 2 = Test old style callbacks + * Test 3 = Test old style callbacks with no certificate + */ static int test_tls13_psk(int idx) { SSL_CTX *sctx = NULL, *cctx = NULL; @@ -2731,15 +3081,21 @@ static int test_tls13_psk(int idx) if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), TLS1_VERSION, TLS_MAX_VERSION, - &sctx, &cctx, cert, privkey))) + &sctx, &cctx, idx == 3 ? NULL : cert, + idx == 3 ? NULL : privkey))) goto end; - /* - * We use a ciphersuite with SHA256 to ease testing old style PSK callbacks - * which will always default to SHA256 - */ - if (!TEST_true(SSL_CTX_set_ciphersuites(cctx, "TLS_AES_128_GCM_SHA256"))) - goto end; + if (idx != 3) { + /* + * We use a ciphersuite with SHA256 to ease testing old style PSK + * callbacks which will always default to SHA256. This should not be + * necessary if we have no cert/priv key. In that case the server should + * prefer SHA256 automatically. + */ + if (!TEST_true(SSL_CTX_set_ciphersuites(cctx, + "TLS_AES_128_GCM_SHA256"))) + goto end; + } /* * Test 0: New style callbacks only @@ -2751,7 +3107,7 @@ static int test_tls13_psk(int idx) SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb); } #ifndef OPENSSL_NO_PSK - if (idx == 1 || idx == 2) { + if (idx >= 1) { SSL_CTX_set_psk_client_callback(cctx, psk_client_cb); SSL_CTX_set_psk_server_callback(sctx, psk_server_cb); } @@ -2762,39 +3118,44 @@ static int test_tls13_psk(int idx) psk_client_cb_cnt = 0; psk_server_cb_cnt = 0; - /* Check we can create a connection if callback decides not to send a PSK */ + if (idx != 3) { + /* + * Check we can create a connection if callback decides not to send a + * PSK + */ + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_false(SSL_session_reused(clientssl)) + || !TEST_false(SSL_session_reused(serverssl))) + goto end; + + if (idx == 0 || idx == 1) { + if (!TEST_true(use_session_cb_cnt == 1) + || !TEST_true(find_session_cb_cnt == 0) + /* + * If no old style callback then below should be 0 + * otherwise 1 + */ + || !TEST_true(psk_client_cb_cnt == idx) + || !TEST_true(psk_server_cb_cnt == 0)) + goto end; + } else { + if (!TEST_true(use_session_cb_cnt == 0) + || !TEST_true(find_session_cb_cnt == 0) + || !TEST_true(psk_client_cb_cnt == 1) + || !TEST_true(psk_server_cb_cnt == 0)) + goto end; + } + + shutdown_ssl_connection(serverssl, clientssl); + serverssl = clientssl = NULL; + use_session_cb_cnt = psk_client_cb_cnt = 0; + } + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, - NULL, NULL)) - || !TEST_true(create_ssl_connection(serverssl, clientssl, - SSL_ERROR_NONE)) - || !TEST_false(SSL_session_reused(clientssl)) - || !TEST_false(SSL_session_reused(serverssl))) - goto end; - - if (idx == 0 || idx == 1) { - if (!TEST_true(use_session_cb_cnt == 1) - || !TEST_true(find_session_cb_cnt == 0) - /* - * If no old style callback then below should be 0 - * otherwise 1 - */ - || !TEST_true(psk_client_cb_cnt == idx) - || !TEST_true(psk_server_cb_cnt == 0)) - goto end; - } else { - if (!TEST_true(use_session_cb_cnt == 0) - || !TEST_true(find_session_cb_cnt == 0) - || !TEST_true(psk_client_cb_cnt == 1) - || !TEST_true(psk_server_cb_cnt == 0)) - goto end; - } - - shutdown_ssl_connection(serverssl, clientssl); - serverssl = clientssl = NULL; - use_session_cb_cnt = psk_client_cb_cnt = 0; - - if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, - NULL, NULL))) + NULL, NULL))) goto end; /* Create the PSK */ @@ -2872,39 +3233,41 @@ static int test_tls13_psk(int idx) use_session_cb_cnt = find_session_cb_cnt = 0; psk_client_cb_cnt = psk_server_cb_cnt = 0; - /* - * Check that if the server rejects the PSK we can still connect, but with - * a full handshake - */ - srvid = "Dummy Identity"; - if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, - NULL, NULL)) - || !TEST_true(create_ssl_connection(serverssl, clientssl, - SSL_ERROR_NONE)) - || !TEST_false(SSL_session_reused(clientssl)) - || !TEST_false(SSL_session_reused(serverssl))) - goto end; - - if (idx == 0 || idx == 1) { - if (!TEST_true(use_session_cb_cnt == 1) - || !TEST_true(find_session_cb_cnt == 1) - || !TEST_true(psk_client_cb_cnt == 0) - /* - * If no old style callback then below should be 0 - * otherwise 1 - */ - || !TEST_true(psk_server_cb_cnt == idx)) - goto end; - } else { - if (!TEST_true(use_session_cb_cnt == 0) - || !TEST_true(find_session_cb_cnt == 0) - || !TEST_true(psk_client_cb_cnt == 1) - || !TEST_true(psk_server_cb_cnt == 1)) + if (idx != 3) { + /* + * Check that if the server rejects the PSK we can still connect, but with + * a full handshake + */ + srvid = "Dummy Identity"; + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_false(SSL_session_reused(clientssl)) + || !TEST_false(SSL_session_reused(serverssl))) goto end; - } - shutdown_ssl_connection(serverssl, clientssl); - serverssl = clientssl = NULL; + if (idx == 0 || idx == 1) { + if (!TEST_true(use_session_cb_cnt == 1) + || !TEST_true(find_session_cb_cnt == 1) + || !TEST_true(psk_client_cb_cnt == 0) + /* + * If no old style callback then below should be 0 + * otherwise 1 + */ + || !TEST_true(psk_server_cb_cnt == idx)) + goto end; + } else { + if (!TEST_true(use_session_cb_cnt == 0) + || !TEST_true(find_session_cb_cnt == 0) + || !TEST_true(psk_client_cb_cnt == 1) + || !TEST_true(psk_server_cb_cnt == 1)) + goto end; + } + + shutdown_ssl_connection(serverssl, clientssl); + serverssl = clientssl = NULL; + } testresult = 1; end: @@ -3304,9 +3667,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; } @@ -3350,10 +3714,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; } @@ -3619,8 +3986,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; @@ -4118,14 +4484,16 @@ static struct info_cb_states_st { {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_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_HANDSHAKE_DONE, NULL}, {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}, }, { /* TLSv1.3 client followed by resumption */ {SSL_CB_HANDSHAKE_START, NULL}, {SSL_CB_LOOP, "PINIT "}, @@ -4136,6 +4504,9 @@ static struct info_cb_states_st { {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_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_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"}, @@ -4204,6 +4575,12 @@ static void sslapi_info_callback(const SSL *s, int where, int ret) info_cb_failed = 1; 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) { + info_cb_failed = 1; + return; + } } /* @@ -4225,7 +4602,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; @@ -4243,6 +4622,7 @@ static int test_info_callback(int tst) info_cb_this_state = -1; info_cb_offset = tst; +#ifndef OPENSSL_NO_TLS1_3 if (tst >= 4) { SSL_SESSION *sess = NULL; size_t written, readbytes; @@ -4277,6 +4657,7 @@ static int test_info_callback(int tst) testresult = 1; goto end; } +#endif if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), @@ -4328,6 +4709,533 @@ static int test_info_callback(int tst) return testresult; } +static int test_ssl_pending(int tst) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + char msg[] = "A test message"; + char buf[5]; + size_t written, readbytes; + + if (tst == 0) { + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_VERSION, TLS_MAX_VERSION, + &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, + &sctx, &cctx, cert, privkey))) + goto end; +#else + return 1; +#endif + } + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) + goto end; + + if (!TEST_int_eq(SSL_pending(clientssl), 0) + || !TEST_false(SSL_has_pending(clientssl)) + || !TEST_int_eq(SSL_pending(serverssl), 0) + || !TEST_false(SSL_has_pending(serverssl)) + || !TEST_true(SSL_write_ex(serverssl, msg, sizeof(msg), &written)) + || !TEST_size_t_eq(written, sizeof(msg)) + || !TEST_true(SSL_read_ex(clientssl, buf, sizeof(buf), &readbytes)) + || !TEST_size_t_eq(readbytes, sizeof(buf)) + || !TEST_int_eq(SSL_pending(clientssl), (int)(written - readbytes)) + || !TEST_true(SSL_has_pending(clientssl))) + goto end; + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +static struct { + unsigned int maxprot; + const char *clntciphers; + const char *clnttls13ciphers; + const char *srvrciphers; + const char *srvrtls13ciphers; + const char *shared; +} shared_ciphers_data[] = { +/* + * We can't establish a connection (even in TLSv1.1) with these ciphersuites if + * TLSv1.3 is enabled but TLSv1.2 is disabled. + */ +#if defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) + { + TLS1_2_VERSION, + "AES128-SHA:AES256-SHA", + NULL, + "AES256-SHA:DHE-RSA-AES128-SHA", + NULL, + "AES256-SHA" + }, + { + TLS1_2_VERSION, + "AES128-SHA:DHE-RSA-AES128-SHA:AES256-SHA", + NULL, + "AES128-SHA:DHE-RSA-AES256-SHA:AES256-SHA", + NULL, + "AES128-SHA:AES256-SHA" + }, + { + TLS1_2_VERSION, + "AES128-SHA:AES256-SHA", + NULL, + "AES128-SHA:DHE-RSA-AES128-SHA", + NULL, + "AES128-SHA" + }, +#endif +/* + * This test combines TLSv1.3 and TLSv1.2 ciphersuites so they must both be + * enabled. + */ +#if !defined(OPENSSL_NO_TLS1_3) && !defined(OPENSSL_NO_TLS1_2) \ + && !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + { + TLS1_3_VERSION, + "AES128-SHA:AES256-SHA", + NULL, + "AES256-SHA:AES128-SHA256", + NULL, + "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_128_GCM_SHA256:AES256-SHA" + }, +#endif +#ifndef OPENSSL_NO_TLS1_3 + { + TLS1_3_VERSION, + "AES128-SHA", + "TLS_AES_256_GCM_SHA384", + "AES256-SHA", + "TLS_AES_256_GCM_SHA384", + "TLS_AES_256_GCM_SHA384" + }, +#endif +}; + +static int test_ssl_get_shared_ciphers(int tst) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + char buf[1024]; + + if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), + TLS_client_method(), + TLS1_VERSION, + shared_ciphers_data[tst].maxprot, + &sctx, &cctx, cert, privkey))) + goto end; + + if (!TEST_true(SSL_CTX_set_cipher_list(cctx, + shared_ciphers_data[tst].clntciphers)) + || (shared_ciphers_data[tst].clnttls13ciphers != NULL + && !TEST_true(SSL_CTX_set_ciphersuites(cctx, + shared_ciphers_data[tst].clnttls13ciphers))) + || !TEST_true(SSL_CTX_set_cipher_list(sctx, + shared_ciphers_data[tst].srvrciphers)) + || (shared_ciphers_data[tst].srvrtls13ciphers != NULL + && !TEST_true(SSL_CTX_set_ciphersuites(sctx, + shared_ciphers_data[tst].srvrtls13ciphers)))) + 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; + + if (!TEST_ptr(SSL_get_shared_ciphers(serverssl, buf, sizeof(buf))) + || !TEST_int_eq(strcmp(buf, shared_ciphers_data[tst].shared), 0)) { + TEST_info("Shared ciphers are: %s\n", buf); + goto end; + } + + testresult = 1; + + end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +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) +{ + gen_tick_called = 1; + + 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, client + * reads it + * Test 5: 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; + +#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)) + || !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))) + goto end; + } else if (!TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE))) { + 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))) + || !TEST_int_eq(SSL_shutdown(serverssl), 1)) + goto end; + if (tst == 4) { + /* 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)) + 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_int_eq(SSL_shutdown(serverssl), 1)) + goto end; + } else if (tst == 4) { + /* + * 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)) + goto end; + } else { + /* + * tst == 5 + * + * 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; +} + int setup_tests(void) { if (!TEST_ptr(cert = test_get_argument(0)) @@ -4363,6 +5271,9 @@ 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_tickets, 3); +#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); @@ -4387,6 +5298,7 @@ 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_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); @@ -4400,7 +5312,7 @@ int setup_tests(void) #ifdef OPENSSL_NO_PSK ADD_ALL_TESTS(test_tls13_psk, 1); #else - ADD_ALL_TESTS(test_tls13_psk, 3); + ADD_ALL_TESTS(test_tls13_psk, 4); #endif /* OPENSSL_NO_PSK */ ADD_ALL_TESTS(test_custom_exts, 5); ADD_TEST(test_stateless); @@ -4419,6 +5331,10 @@ int setup_tests(void) ADD_ALL_TESTS(test_srp, 6); #endif 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, 6); return 1; }