/*
- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
#include "testutil.h"
#include "testutil/output.h"
#include "internal/nelem.h"
+#include "internal/tlsgroups.h"
#include "internal/ktls.h"
#include "../ssl/ssl_local.h"
#include "../ssl/record/methods/recmethod_local.h"
static int use_session_cb_cnt = 0;
static int find_session_cb_cnt = 0;
-
-static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize);
#endif
static char *certsdir = NULL;
static X509 *ocspcert = NULL;
#endif
-#define NUM_EXTRA_CERTS 40
#define CLIENT_VERSION_LEN 2
/*
int *ctr = arg;
const unsigned char *p;
int *exts;
- /* We only configure two ciphers, but the SCSV is added automatically. */
#ifdef OPENSSL_NO_EC
- const unsigned char expected_ciphers[] = {0x00, 0x9d, 0x00, 0xff};
+ const unsigned char expected_ciphers[] = {0x00, 0x9d};
#else
const unsigned char expected_ciphers[] = {0x00, 0x9d, 0xc0,
- 0x2c, 0x00, 0xff};
+ 0x2c};
#endif
const int expected_extensions[] = {
+ 65281,
#ifndef OPENSSL_NO_EC
11, 10,
#endif
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
int testresult = 0;
- int i;
- BIO *certbio = NULL;
- X509 *chaincert = NULL;
- int certlen;
-
- if (!TEST_ptr(certbio = BIO_new_file(cert, "r")))
- goto end;
-
- if (!TEST_ptr(chaincert = X509_new_ex(libctx, NULL)))
- goto end;
-
- if (PEM_read_bio_X509(certbio, &chaincert, NULL, NULL) == NULL)
- goto end;
- BIO_free(certbio);
- certbio = NULL;
if (!TEST_true(create_ssl_ctx_pair(libctx, smeth, cmeth, min_version,
max_version, &sctx, &cctx, cert,
SSL_CTX_set_read_ahead(cctx, 1);
}
- /*
- * We assume the supplied certificate is big enough so that if we add
- * NUM_EXTRA_CERTS it will make the overall message large enough. The
- * default buffer size is requested to be 16k, but due to the way BUF_MEM
- * works, it ends up allocating a little over 21k (16 * 4/3). So, in this
- * test we need to have a message larger than that.
- */
- certlen = i2d_X509(chaincert, NULL);
- OPENSSL_assert(certlen * NUM_EXTRA_CERTS >
- (SSL3_RT_MAX_PLAIN_LENGTH * 4) / 3);
- for (i = 0; i < NUM_EXTRA_CERTS; i++) {
- if (!X509_up_ref(chaincert))
- goto end;
- if (!SSL_CTX_add_extra_chain_cert(sctx, chaincert)) {
- X509_free(chaincert);
- goto end;
- }
- }
+ if (!ssl_ctx_add_large_cert_chain(libctx, sctx, cert))
+ goto end;
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
testresult = 1;
end:
- BIO_free(certbio);
- X509_free(chaincert);
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
int cfd = -1, sfd = -1;
int rx_supported;
SSL_CONNECTION *clientsc, *serversc;
+ unsigned char *buf = NULL;
+ const size_t bufsz = SSL3_RT_MAX_PLAIN_LENGTH + 16;
+ int ret;
+ size_t offset = 0, i;
if (!TEST_true(create_test_sockets(&cfd, &sfd, SOCK_STREAM, NULL)))
goto end;
if (!TEST_true(ping_pong_query(clientssl, serverssl)))
goto end;
+ buf = OPENSSL_zalloc(bufsz);
+ if (!TEST_ptr(buf))
+ goto end;
+
+ /*
+ * Write some data that exceeds the maximum record length. KTLS may choose
+ * to coalesce this data into a single buffer when we read it again.
+ */
+ while ((ret = SSL_write(clientssl, buf, bufsz)) != (int)bufsz) {
+ if (!TEST_true(SSL_get_error(clientssl, ret) == SSL_ERROR_WANT_WRITE))
+ goto end;
+ }
+
+ /* Now check that we can read all the data we wrote */
+ do {
+ ret = SSL_read(serverssl, buf + offset, bufsz - offset);
+ if (ret <= 0) {
+ if (!TEST_true(SSL_get_error(serverssl, ret) == SSL_ERROR_WANT_READ))
+ goto end;
+ } else {
+ offset += ret;
+ }
+ } while (offset < bufsz);
+
+ if (!TEST_true(offset == bufsz))
+ goto end;
+ for (i = 0; i < bufsz; i++)
+ if (!TEST_true(buf[i] == 0))
+ goto end;
+
testresult = 1;
end:
+ OPENSSL_free(buf);
if (clientssl) {
SSL_shutdown(clientssl);
SSL_free(clientssl);
return testresult;
}
+#if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3) \
+ || !defined(OPENSSL_NO_DTLS)
static int execute_cleanse_plaintext(const SSL_METHOD *smeth,
const SSL_METHOD *cmeth,
int min_version, int max_version)
privkey)))
goto end;
-#ifdef OPENSSL_NO_DTLS1_2
- if (smeth == DTLS_server_method()) {
# ifdef OPENSSL_NO_DTLS1_2
+ if (smeth == DTLS_server_method()) {
/* Not supported in the FIPS provider */
if (is_fips) {
testresult = 1;
goto end;
};
-# endif
/*
* Default sigalgs are SHA1 based in <DTLS1.2 which is in security
* level 0
"DEFAULT:@SECLEVEL=0")))
goto end;
}
-#endif
+# endif
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
return testresult;
}
+#endif /*
+ * !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3)
+ * || !defined(OPENSSL_NO_DTLS)
+ */
static int test_cleanse_plaintext(void)
{
#endif
}
-
#ifndef OSSL_NO_USABLE_TLS1_3
static SSL_SESSION *sesscache[6];
static int do_cache;
{validlist3, OSSL_NELEM(validlist3), NULL, 1, 0},
# endif
{NULL, 0, "RSA+SHA256", 1, 1},
+ {NULL, 0, "RSA+SHA256:?Invalid", 1, 1},
# ifndef OPENSSL_NO_EC
{NULL, 0, "RSA+SHA256:ECDSA+SHA512", 1, 1},
{NULL, 0, "ECDSA+SHA512", 1, 0},
#define MSG6 "test"
#define MSG7 "message."
-#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01")
-#define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02")
-#define TLS13_CHACHA20_POLY1305_SHA256_BYTES ((const unsigned char *)"\x13\x03")
-#define TLS13_AES_128_CCM_SHA256_BYTES ((const unsigned char *)"\x13\x04")
-#define TLS13_AES_128_CCM_8_SHA256_BYTES ((const unsigned char *)"\x13\05")
-
+static int artificial_ticket_time = 0;
-static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize)
+static int sub_session_time(SSL_SESSION *sess)
{
- 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 /* SHA384_DIGEST_LENGTH bytes */
- };
- SSL_SESSION *sess = NULL;
+ OSSL_TIME tick_time;
- if (mdsize == SHA384_DIGEST_LENGTH) {
- cipher = SSL_CIPHER_find(ssl, TLS13_AES_256_GCM_SHA384_BYTES);
- } else if (mdsize == SHA256_DIGEST_LENGTH) {
- /*
- * Any ciphersuite using SHA256 will do - it will be compatible with
- * the actual ciphersuite selected as long as it too is based on SHA256
- */
- cipher = SSL_CIPHER_find(ssl, TLS13_AES_128_GCM_SHA256_BYTES);
- } else {
- /* Should not happen */
- return NULL;
- }
- sess = SSL_SESSION_new();
- if (!TEST_ptr(sess)
- || !TEST_ptr(cipher)
- || !TEST_true(SSL_SESSION_set1_master_key(sess, key, mdsize))
- || !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;
-}
+ tick_time = ossl_time_from_time_t(SSL_SESSION_get_time_ex(sess));
+ tick_time = ossl_time_subtract(tick_time, ossl_seconds2time(10));
-static int artificial_ticket_time = 0;
+ return SSL_SESSION_set_time_ex(sess, ossl_time_to_time_t(tick_time)) != 0;
+}
static int ed_gen_cb(SSL *s, void *arg)
{
return 1;
artificial_ticket_time--;
- if (SSL_SESSION_set_time(sess, SSL_SESSION_get_time(sess) - 10) == 0)
- return 0;
-
- return 1;
+ return sub_session_time(sess);
}
/*
* gave it on the server side
*/
if (artificial
- && !TEST_long_gt(SSL_SESSION_set_time(*sess,
- SSL_SESSION_get_time(*sess) - 10), 0))
+ && !TEST_true(sub_session_time(*sess)))
return 0;
if (!TEST_true(create_ssl_objects(*sctx, *cctx, serverssl,
return 1;
}
+static int check_early_data_timeout(OSSL_TIME timer)
+{
+ int res = 0;
+
+ /*
+ * Early data is time sensitive. We have an approx 8 second allowance
+ * between writing the early data and reading it. If we exceed that time
+ * then this test will fail. This can sometimes (rarely) occur in normal CI
+ * operation. We can try and detect this and just ignore the result of this
+ * test if it has taken too long. We assume anything over 7 seconds is too
+ * long
+ */
+ timer = ossl_time_subtract(ossl_time_now(), timer);
+ if (ossl_time_compare(timer, ossl_seconds2time(7)) >= 0)
+ res = TEST_skip("Test took too long, ignoring result");
+
+ return res;
+}
+
static int test_early_data_read_write(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
unsigned char buf[20], data[1024];
size_t readbytes, written, eoedlen, rawread, rawwritten;
BIO *rbio;
+ OSSL_TIME timer;
/* Artificially give the next 2 tickets some age for non PSK sessions */
if (idx != 2)
artificial_ticket_time = 0;
/* Write and read some early data */
+ timer = ossl_time_now();
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
- || !TEST_size_t_eq(written, strlen(MSG1))
- || !TEST_int_eq(SSL_read_early_data(serverssl, buf,
- sizeof(buf), &readbytes),
- SSL_READ_EARLY_DATA_SUCCESS)
- || !TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1))
+ || !TEST_size_t_eq(written, strlen(MSG1)))
+ goto end;
+
+ if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
+ &readbytes),
+ SSL_READ_EARLY_DATA_SUCCESS)) {
+ testresult = check_early_data_timeout(timer);
+ goto end;
+ }
+
+ if (!TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED))
goto end;
SSL_SESSION *sess = NULL;
size_t readbytes, written;
unsigned char buf[20];
+ OSSL_TIME timer;
allow_ed_cb_called = 0;
goto end;
/* Write and read some early data */
+ timer = ossl_time_now();
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
|| !TEST_size_t_eq(written, strlen(MSG1)))
/* 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)
+ SSL_READ_EARLY_DATA_SUCCESS)) {
+ testresult = check_early_data_timeout(timer);
+ goto end;
+ }
+ if (!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_eq(ERR_GET_REASON(ERR_get_error()), err))
goto end;
} else {
+ OSSL_TIME timer = ossl_time_now();
+
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written)))
goto end;
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
- &readbytes), readearlyres)
- || (readearlyres == SSL_READ_EARLY_DATA_SUCCESS
+ &readbytes), readearlyres)) {
+ testresult = check_early_data_timeout(timer);
+ goto end;
+ }
+
+ if ((readearlyres == SSL_READ_EARLY_DATA_SUCCESS
&& !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1)))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl), edstatus)
|| !TEST_int_eq(SSL_connect(clientssl), connectres))
unsigned char buf[20];
size_t readbytes, written;
const SSL_CIPHER *cipher;
+ OSSL_TIME timer;
const char *cipher_str[] = {
TLS1_3_RFC_AES_128_GCM_SHA256,
TLS1_3_RFC_AES_256_GCM_SHA384,
goto end;
SSL_set_connect_state(clientssl);
+ timer = ossl_time_now();
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written)))
goto end;
if (!TEST_int_eq(SSL_read_early_data(serverssl, buf, sizeof(buf),
&readbytes),
- SSL_READ_EARLY_DATA_SUCCESS)
- || !TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1))
+ SSL_READ_EARLY_DATA_SUCCESS)) {
+ testresult = check_early_data_timeout(timer);
+ goto end;
+ }
+
+ if (!TEST_mem_eq(buf, readbytes, MSG1, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED)
|| !TEST_int_eq(SSL_connect(clientssl), 1)
return testresult;
}
+#ifndef OSSL_NO_USABLE_TLS1_3
+/*
+ * Test TLS1.3 connection establishment succeeds with various configurations of
+ * the options `SSL_OP_ALLOW_NO_DHE_KEX` and `SSL_OP_PREFER_NO_DHE_KEX`.
+ * The verification of whether the right KEX mode is chosen is not covered by
+ * this test but by `test_tls13kexmodes`.
+ *
+ * Tests (idx & 1): Server has `SSL_OP_ALLOW_NO_DHE_KEX` set.
+ * Tests (idx & 2): Server has `SSL_OP_PREFER_NO_DHE_KEX` set.
+ * Tests (idx & 4): Client has `SSL_OP_ALLOW_NO_DHE_KEX` set.
+ */
+static int test_tls13_no_dhe_kex(const int idx)
+{
+ SSL_CTX *sctx = NULL, *cctx = NULL;
+ SSL *serverssl = NULL, *clientssl = NULL;
+ int testresult = 0;
+ size_t j;
+ SSL_SESSION *saved_session;
+
+ int server_allow_no_dhe = (idx & 1) != 0;
+ int server_prefer_no_dhe = (idx & 2) != 0;
+ int client_allow_no_dhe = (idx & 4) != 0;
+
+ uint64_t server_options = 0
+ | (server_allow_no_dhe ? SSL_OP_ALLOW_NO_DHE_KEX : 0)
+ | (server_prefer_no_dhe ? SSL_OP_PREFER_NO_DHE_KEX : 0);
+
+ uint64_t client_options = 0
+ | (client_allow_no_dhe ? SSL_OP_ALLOW_NO_DHE_KEX : 0);
+
+ new_called = 0;
+ do_cache = 1;
+
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(), TLS1_3_VERSION, 0,
+ &sctx, &cctx, cert, privkey)))
+ goto end;
+
+ SSL_CTX_set_session_cache_mode(cctx, SSL_SESS_CACHE_CLIENT
+ | SSL_SESS_CACHE_NO_INTERNAL_STORE);
+
+ SSL_CTX_set_options(sctx, server_options);
+ SSL_CTX_set_options(cctx, client_options);
+
+ SSL_CTX_sess_set_new_cb(cctx, new_cachesession_cb);
+
+ 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(2, new_called))
+ goto end;
+
+ /* We'll reuse the last ticket. */
+ saved_session = sesscache[new_called - 1];
+
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(cctx);
+ clientssl = serverssl = NULL;
+ cctx = NULL;
+
+ /*
+ * Now we resume with the last ticket we created.
+ */
+
+ /* The server context already exists, so we only create the client. */
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(), TLS1_3_VERSION, 0,
+ NULL, &cctx, cert, privkey)))
+ goto end;
+
+ SSL_CTX_set_options(cctx, client_options);
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
+ &clientssl, NULL, NULL))
+ || !TEST_true(SSL_set_session(clientssl, saved_session)))
+ goto end;
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl,
+ SSL_ERROR_NONE)))
+ goto end;
+
+ /*
+ * Make sure, the session was resumed.
+ */
+ if (!TEST_true(SSL_session_reused(clientssl)))
+ goto end;
+
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+
+ 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 /* OSSL_NO_USABLE_TLS1_3 */
+
static unsigned char cookie_magic_value[] = "cookie magic";
static int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
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];
+ unsigned char longcontext[1280];
+ int test_longcontext = fips_provider_version_ge(libctx, 3, 3, 0);
+ unsigned char ckeymat1[80], ckeymat2[80], ckeymat3[80], ckeymat4[80];
+ unsigned char skeymat1[80], skeymat2[80], skeymat3[80], skeymat4[80];
size_t labellen;
const int protocols[] = {
TLS1_VERSION,
labellen = SMALL_LABEL_LEN;
}
+ memset(longcontext, 1, sizeof(longcontext));
+
if (!TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat1,
sizeof(ckeymat1), label,
labellen, context,
sizeof(ckeymat3), label,
labellen,
NULL, 0, 0), 1)
+ || (test_longcontext
+ && !TEST_int_eq(SSL_export_keying_material(clientssl,
+ ckeymat4,
+ sizeof(ckeymat4), label,
+ labellen,
+ longcontext,
+ sizeof(longcontext), 1),
+ 1))
|| !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat1,
sizeof(skeymat1), label,
labellen,
sizeof(skeymat3), label,
labellen,
NULL, 0, 0), 1)
+ || (test_longcontext
+ && !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat4,
+ sizeof(skeymat4), label,
+ labellen,
+ longcontext,
+ sizeof(longcontext), 1),
+ 1))
/*
* Check that both sides created the same key material with the
* same context.
*/
|| !TEST_mem_eq(ckeymat3, sizeof(ckeymat3), skeymat3,
sizeof(skeymat3))
+ /*
+ * Check that both sides created the same key material with a
+ * long context.
+ */
+ || (test_longcontext
+ && !TEST_mem_eq(ckeymat4, sizeof(ckeymat4), skeymat4,
+ sizeof(skeymat4)))
/* Different contexts should produce different results */
|| !TEST_mem_ne(ckeymat1, sizeof(ckeymat1), ckeymat2,
sizeof(ckeymat2)))
/* 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))
+ || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE)
+ || !TEST_true(SSL_want_write(peerwrite))
+ || !TEST_true(SSL_net_write_desired(peerwrite)))
goto end;
/* Reinstate the original writing endpoint's write BIO */
/* 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))
+ || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ)
+ || !TEST_true(SSL_want_read(peerwrite))
+ || !TEST_true(SSL_net_read_desired(peerwrite)))
goto end;
/*
|| !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess)))
goto end;
+ if (!TEST_false(SSL_net_read_desired(peerwrite))
+ || !TEST_false(SSL_net_write_desired(peerwrite))
+ || !TEST_int_eq(SSL_want(peerwrite), SSL_NOTHING))
+ goto end;
+
testresult = 1;
end:
}
#endif /* OSSL_NO_USABLE_TLS1_3 */
+/*
+ * Test clearing a connection via SSL_clear(), or resetting it via
+ * SSL_set_connect_state()/SSL_set_accept_state()
+ * Test 0: SSL_set_connect_state, TLSv1.3
+ * Test 1: SSL_set_connect_state, TLSv1.2
+ * Test 2: SSL_set_accept_state, TLSv1.3
+ * Test 3: SSL_set_accept_state, TLSv1.2
+ * Test 4: SSL_clear (client), TLSv1.3
+ * Test 5: SSL_clear (client), TLSv1.2
+ * Test 6: SSL_clear (server), TLSv1.3
+ * Test 7: SSL_clear (server), TLSv1.2
+ */
static int test_ssl_clear(int idx)
{
SSL_CTX *cctx = NULL, *sctx = NULL;
SSL *clientssl = NULL, *serverssl = NULL;
+ SSL *writer, *reader;
int testresult = 0;
+ int tls12test, servertest, cleartest;
+ size_t written, readbytes;
+ const char *msg = "Hello World";
+ unsigned char buf[5];
+
+ tls12test = idx & 1;
+ idx >>= 1;
+ servertest = idx & 1;
+ idx >>= 1;
+ cleartest = idx & 1;
#ifdef OPENSSL_NO_TLS1_2
- if (idx == 1)
- return 1;
+ if (tls12test == 1)
+ return TEST_skip("No TLSv1.2 in this build");
#endif
/* Create an initial connection */
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION, 0,
&sctx, &cctx, cert, privkey))
- || (idx == 1
+ || (tls12test
&& !TEST_true(SSL_CTX_set_max_proto_version(cctx,
TLS1_2_VERSION)))
|| !TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
SSL_ERROR_NONE)))
goto end;
+ if (servertest) {
+ writer = clientssl;
+ reader = serverssl;
+ } else {
+ writer = serverssl;
+ reader = clientssl;
+ }
+
+ /* Write some data */
+ if (!TEST_true(SSL_write_ex(writer, msg, strlen(msg), &written))
+ || written != strlen(msg))
+ goto end;
+
+ /*
+ * Read a partial record. The remaining buffered data should be cleared by
+ * the subsequent clear/reset
+ */
+ if (!TEST_true(SSL_read_ex(reader, buf, sizeof(buf), &readbytes))
+ || readbytes != sizeof(buf))
+ goto end;
+
SSL_shutdown(clientssl);
SSL_shutdown(serverssl);
- SSL_free(serverssl);
- serverssl = NULL;
- /* Clear clientssl - we're going to reuse the object */
- if (!TEST_true(SSL_clear(clientssl)))
- goto end;
+ /* Reset/clear one SSL object in order to reuse it. We free the other one */
+ if (servertest) {
+ if (cleartest) {
+ if (!TEST_true(SSL_clear(serverssl)))
+ goto end;
+ } else {
+ SSL_set_accept_state(serverssl);
+ }
+ /*
+ * A peculiarity of SSL_clear() is that it does not clear the session.
+ * This is intended behaviour so that a client can create a new
+ * connection and reuse the session. But this doesn't make much sense
+ * on the server side - and causes incorrect behaviour due to the
+ * handshake failing (even though the documentation does say SSL_clear()
+ * is supposed to work on the server side). We clear the session
+ * explicitly - although note that the documentation for
+ * SSL_set_session() says that its only useful for clients!
+ */
+ if (!TEST_true(SSL_set_session(serverssl, NULL)))
+ goto end;
+ SSL_free(clientssl);
+ clientssl = NULL;
+ } else {
+ if (cleartest) {
+ if (!TEST_true(SSL_clear(clientssl)))
+ goto end;
+ } else {
+ SSL_set_connect_state(clientssl);
+ }
+ SSL_free(serverssl);
+ serverssl = NULL;
+ }
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL))
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
SSL_ERROR_NONE))
- || !TEST_true(SSL_session_reused(clientssl)))
+ || !TEST_true(servertest || SSL_session_reused(clientssl)))
goto end;
SSL_shutdown(clientssl);
SSL_SESSION *sess = NULL;
size_t written, readbytes;
unsigned char buf[80];
+ OSSL_TIME timer;
/* early_data tests */
if (!TEST_true(setupearly_data_test(&cctx, &sctx, &clientssl,
sslapi_info_callback);
/* Write and read some early data and then complete the connection */
+ timer = ossl_time_now();
if (!TEST_true(SSL_write_early_data(clientssl, MSG1, strlen(MSG1),
&written))
- || !TEST_size_t_eq(written, strlen(MSG1))
- || !TEST_int_eq(SSL_read_early_data(serverssl, buf,
- sizeof(buf), &readbytes),
- SSL_READ_EARLY_DATA_SUCCESS)
- || !TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1))
+ || !TEST_size_t_eq(written, strlen(MSG1)))
+ goto end;
+
+ if (!TEST_int_eq(SSL_read_early_data(serverssl, buf,
+ sizeof(buf), &readbytes),
+ SSL_READ_EARLY_DATA_SUCCESS)) {
+ testresult = check_early_data_timeout(timer);
+ goto end;
+ }
+
+ if (!TEST_mem_eq(MSG1, readbytes, buf, strlen(MSG1))
|| !TEST_int_eq(SSL_get_early_data_status(serverssl),
SSL_EARLY_DATA_ACCEPTED)
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
* Test session ordering and timeout
* Can't explicitly test performance of the new code,
* but can test to see if the ordering of the sessions
- * are correct, and they they are removed as expected
+ * are correct, and they are removed as expected
*/
SSL_SESSION *early = NULL;
SSL_SESSION *middle = NULL;
}
/*
- * Test 0: Client sets servername and server acknowledges it (TLSv1.2)
- * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2)
- * Test 2: Client sets inconsistent servername on resumption (TLSv1.2)
- * Test 3: Client does not set servername on initial handshake (TLSv1.2)
- * Test 4: Client does not set servername on resumption handshake (TLSv1.2)
- * Test 5: Client sets servername and server acknowledges it (TLSv1.3)
- * Test 6: Client sets servername and server does not acknowledge it (TLSv1.3)
- * Test 7: Client sets inconsistent servername on resumption (TLSv1.3)
- * Test 8: Client does not set servername on initial handshake(TLSv1.3)
- * Test 9: Client does not set servername on resumption handshake (TLSv1.3)
+ * Test that a session cache overflow works as expected
+ * Test 0: TLSv1.3, timeout on new session later than old session
+ * Test 1: TLSv1.2, timeout on new session later than old session
+ * Test 2: TLSv1.3, timeout on new session earlier than old session
+ * Test 3: TLSv1.2, timeout on new session earlier than old session
*/
-static int test_servername(int tst)
+#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
+static int test_session_cache_overflow(int idx)
{
- SSL_CTX *cctx = NULL, *sctx = NULL;
- SSL *clientssl = NULL, *serverssl = NULL;
+ SSL_CTX *sctx = NULL, *cctx = NULL;
+ SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;
- const char *sexpectedhost = NULL, *cexpectedhost = NULL;
-#ifdef OPENSSL_NO_TLS1_2
- if (tst <= 4)
- return 1;
-#endif
#ifdef OSSL_NO_USABLE_TLS1_3
- if (tst >= 5)
- return 1;
+ /* If no TLSv1.3 available then do nothing in this case */
+ if (idx % 2 == 0)
+ return TEST_skip("No TLSv1.3 available");
+#endif
+#ifdef OPENSSL_NO_TLS1_2
+ /* If no TLSv1.2 available then do nothing in this case */
+ if (idx % 2 == 1)
+ return TEST_skip("No TLSv1.2 available");
#endif
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
- TLS_client_method(),
- TLS1_VERSION,
- (tst <= 4) ? TLS1_2_VERSION
- : TLS1_3_VERSION,
+ TLS_client_method(), TLS1_VERSION,
+ (idx % 2 == 0) ? TLS1_3_VERSION
+ : TLS1_2_VERSION,
&sctx, &cctx, cert, privkey))
- || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
- NULL, NULL)))
+ || !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET)))
goto end;
- if (tst != 1 && tst != 6) {
- if (!TEST_true(SSL_CTX_set_tlsext_servername_callback(sctx,
- hostname_cb)))
- goto end;
- }
+ SSL_CTX_sess_set_get_cb(sctx, get_session_cb);
+ get_sess_val = NULL;
- if (tst != 3 && tst != 8) {
- if (!TEST_true(SSL_set_tlsext_host_name(clientssl, "goodhost")))
+ SSL_CTX_sess_set_cache_size(sctx, 1);
+
+ 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)))
+ goto end;
+
+ if (idx > 1) {
+ sess = SSL_get_session(serverssl);
+ if (!TEST_ptr(sess))
+ goto end;
+
+ /*
+ * Cause this session to have a longer timeout than the next session to
+ * be added.
+ */
+ if (!TEST_true(SSL_SESSION_set_timeout(sess, LONG_MAX))) {
+ sess = NULL;
+ goto end;
+ }
+ sess = NULL;
+ }
+
+ SSL_shutdown(serverssl);
+ SSL_shutdown(clientssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ serverssl = clientssl = NULL;
+
+ /*
+ * Session cache size is 1 and we already populated the cache with a session
+ * so the next connection should cause an overflow.
+ */
+
+ 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)))
+ goto end;
+
+ /*
+ * The session we just negotiated may have been already removed from the
+ * internal cache - but we will return it anyway from our external cache.
+ */
+ get_sess_val = SSL_get_session(serverssl);
+ if (!TEST_ptr(get_sess_val))
+ goto end;
+ sess = SSL_get1_session(clientssl);
+ if (!TEST_ptr(sess))
+ goto end;
+
+ SSL_shutdown(serverssl);
+ SSL_shutdown(clientssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ serverssl = clientssl = NULL;
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL)))
+ goto end;
+
+ if (!TEST_true(SSL_set_session(clientssl, sess)))
+ goto end;
+
+ if (!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);
+ SSL_SESSION_free(sess);
+
+ return testresult;
+}
+#endif /* !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) */
+
+/*
+ * Test 0: Client sets servername and server acknowledges it (TLSv1.2)
+ * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2)
+ * Test 2: Client sets inconsistent servername on resumption (TLSv1.2)
+ * Test 3: Client does not set servername on initial handshake (TLSv1.2)
+ * Test 4: Client does not set servername on resumption handshake (TLSv1.2)
+ * Test 5: Client sets servername and server acknowledges it (TLSv1.3)
+ * Test 6: Client sets servername and server does not acknowledge it (TLSv1.3)
+ * Test 7: Client sets inconsistent servername on resumption (TLSv1.3)
+ * Test 8: Client does not set servername on initial handshake(TLSv1.3)
+ * Test 9: Client does not set servername on resumption handshake (TLSv1.3)
+ */
+static int test_servername(int tst)
+{
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+ SSL_SESSION *sess = NULL;
+ const char *sexpectedhost = NULL, *cexpectedhost = NULL;
+
+#ifdef OPENSSL_NO_TLS1_2
+ if (tst <= 4)
+ return 1;
+#endif
+#ifdef OSSL_NO_USABLE_TLS1_3
+ if (tst >= 5)
+ return 1;
+#endif
+
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(),
+ TLS1_VERSION,
+ (tst <= 4) ? 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 != 1 && tst != 6) {
+ if (!TEST_true(SSL_CTX_set_tlsext_servername_callback(sctx,
+ hostname_cb)))
+ goto end;
+ }
+
+ if (tst != 3 && tst != 8) {
+ if (!TEST_true(SSL_set_tlsext_host_name(clientssl, "goodhost")))
goto end;
sexpectedhost = cexpectedhost = "goodhost";
}
return testresult;
}
+static int test_unknown_sigalgs_groups(void)
+{
+ int ret = 0;
+ SSL_CTX *ctx = NULL;
+
+ if (!TEST_ptr(ctx = SSL_CTX_new_ex(libctx, NULL, TLS_server_method())))
+ goto end;
+
+ if (!TEST_int_gt(SSL_CTX_set1_sigalgs_list(ctx,
+ "RSA+SHA256:?nonexistent:?RSA+SHA512"),
+ 0))
+ goto end;
+ if (!TEST_size_t_eq(ctx->cert->conf_sigalgslen, 2)
+ || !TEST_int_eq(ctx->cert->conf_sigalgs[0], TLSEXT_SIGALG_rsa_pkcs1_sha256)
+ || !TEST_int_eq(ctx->cert->conf_sigalgs[1], TLSEXT_SIGALG_rsa_pkcs1_sha512))
+ goto end;
+
+ if (!TEST_int_gt(SSL_CTX_set1_client_sigalgs_list(ctx,
+ "RSA+SHA256:?nonexistent:?RSA+SHA512"),
+ 0))
+ goto end;
+ if (!TEST_size_t_eq(ctx->cert->client_sigalgslen, 2)
+ || !TEST_int_eq(ctx->cert->client_sigalgs[0], TLSEXT_SIGALG_rsa_pkcs1_sha256)
+ || !TEST_int_eq(ctx->cert->client_sigalgs[1], TLSEXT_SIGALG_rsa_pkcs1_sha512))
+ goto end;
+
+ if (!TEST_int_le(SSL_CTX_set1_groups_list(ctx,
+ "nonexistent"),
+ 0))
+ goto end;
+
+ if (!TEST_int_le(SSL_CTX_set1_groups_list(ctx,
+ "?nonexistent1:?nonexistent2:?nonexistent3"),
+ 0))
+ goto end;
+
+#ifndef OPENSSL_NO_EC
+ if (!TEST_int_le(SSL_CTX_set1_groups_list(ctx,
+ "P-256:nonexistent"),
+ 0))
+ goto end;
+
+ if (!TEST_int_gt(SSL_CTX_set1_groups_list(ctx,
+ "P-384:?nonexistent:?P-521"),
+ 0))
+ goto end;
+ if (!TEST_size_t_eq(ctx->ext.supportedgroups_len, 2)
+ || !TEST_int_eq(ctx->ext.supportedgroups[0], OSSL_TLS_GROUP_ID_secp384r1)
+ || !TEST_int_eq(ctx->ext.supportedgroups[1], OSSL_TLS_GROUP_ID_secp521r1))
+ goto end;
+#endif
+
+ ret = 1;
+ end:
+ SSL_CTX_free(ctx);
+ return ret;
+}
+
#if !defined(OPENSSL_NO_EC) \
&& (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2))
/*
OSSL_PROVIDER *tlsprov = OSSL_PROVIDER_load(libctx, "tls-provider");
/* Check that we are not impacted by a provider without any groups */
OSSL_PROVIDER *legacyprov = OSSL_PROVIDER_load(libctx, "legacy");
- const char *group_name = idx == 0 ? "xorgroup" : "xorkemgroup";
+ const char *group_name = idx == 0 ? "xorkemgroup" : "xorgroup";
if (!TEST_ptr(tlsprov))
goto end;
- if (legacyprov == NULL) {
- /*
- * In this case we assume we've been built with "no-legacy" and skip
- * this test (there is no OPENSSL_NO_LEGACY)
- */
- testresult = 1;
- goto end;
- }
-
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(),
TLS1_3_VERSION,
NULL, NULL)))
goto end;
- if (!TEST_true(SSL_set1_groups_list(serverssl, group_name))
+ /* ensure GROUPLIST_INCREMENT (=40) logic triggers: */
+ if (!TEST_true(SSL_set1_groups_list(serverssl, "xorgroup:xorkemgroup:dummy1:dummy2:dummy3:dummy4:dummy5:dummy6:dummy7:dummy8:dummy9:dummy10:dummy11:dummy12:dummy13:dummy14:dummy15:dummy16:dummy17:dummy18:dummy19:dummy20:dummy21:dummy22:dummy23:dummy24:dummy25:dummy26:dummy27:dummy28:dummy29:dummy30:dummy31:dummy32:dummy33:dummy34:dummy35:dummy36:dummy37:dummy38:dummy39:dummy40:dummy41:dummy42:dummy43"))
+ /* removing a single algorithm from the list makes the test pass */
|| !TEST_true(SSL_set1_groups_list(clientssl, group_name)))
goto end;
*/
static int create_cert_key(int idx, char *certfilename, char *privkeyfilename)
{
- EVP_PKEY_CTX * evpctx = EVP_PKEY_CTX_new_from_name(libctx,
+ EVP_PKEY_CTX *evpctx = EVP_PKEY_CTX_new_from_name(libctx,
(idx == 0) ? "xorhmacsig" : "xorhmacsha2sig", NULL);
EVP_PKEY *pkey = NULL;
X509 *x509 = X509_new();
#endif /* OSSL_NO_USABLE_TLS1_3 */
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE)
+
+static ENGINE *load_dasync(void)
+{
+ ENGINE *e;
+
+ if (!TEST_ptr(e = ENGINE_by_id("dasync")))
+ return NULL;
+
+ if (!TEST_true(ENGINE_init(e))) {
+ ENGINE_free(e);
+ return NULL;
+ }
+
+ if (!TEST_true(ENGINE_register_ciphers(e))) {
+ ENGINE_free(e);
+ return NULL;
+ }
+
+ return e;
+}
+
/*
* Test TLSv1.2 with a pipeline capable cipher. TLSv1.3 and DTLS do not
* support this yet. The only pipeline capable cipher that we have is in the
* Test 4: Client has pipelining enabled, server does not: more data than all
* the available pipelines can take
* Test 5: Client has pipelining enabled, server does not: Maximum size pipeline
+ * Test 6: Repeat of test 0, but the engine is loaded late (after the SSL_CTX
+ * is created)
*/
static int test_pipelining(int idx)
{
size_t written, readbytes, offset, msglen, fragsize = 10, numpipes = 5;
size_t expectedreads;
unsigned char *buf = NULL;
- ENGINE *e;
-
- if (!TEST_ptr(e = ENGINE_by_id("dasync")))
- return 0;
+ ENGINE *e = NULL;
- if (!TEST_true(ENGINE_init(e))) {
- ENGINE_free(e);
- return 0;
+ if (idx != 6) {
+ e = load_dasync();
+ if (e == NULL)
+ return 0;
}
- if (!TEST_true(ENGINE_register_ciphers(e)))
- goto end;
-
if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), 0,
TLS1_2_VERSION, &sctx, &cctx, cert,
privkey)))
goto end;
+ if (idx == 6) {
+ e = load_dasync();
+ if (e == NULL)
+ goto end;
+ /* Now act like test 0 */
+ idx = 0;
+ }
+
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
&clientssl, NULL, NULL)))
goto end;
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
- ENGINE_unregister_ciphers(e);
- ENGINE_finish(e);
- ENGINE_free(e);
+ if (e != NULL) {
+ ENGINE_unregister_ciphers(e);
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ }
OPENSSL_free(buf);
- if (idx == 5)
+ if (fragsize == SSL3_RT_MAX_PLAIN_LENGTH)
OPENSSL_free(msg);
return testresult;
}
return testresult;
}
+/*
+ * Force a write retry during handshaking. We test various combinations of
+ * scenarios. We test a large certificate message which will fill the buffering
+ * BIO used in the handshake. We try with client auth on and off. Finally we
+ * also try a BIO that indicates retry via a 0 return. BIO_write() is documented
+ * to indicate retry via -1 - but sometimes BIOs don't do that.
+ *
+ * Test 0: Standard certificate message
+ * Test 1: Large certificate message
+ * Test 2: Standard cert, verify peer
+ * Test 3: Large cert, verify peer
+ * Test 4: Standard cert, BIO returns 0 on retry
+ * Test 5: Large cert, BIO returns 0 on retry
+ * Test 6: Standard cert, verify peer, BIO returns 0 on retry
+ * Test 7: Large cert, verify peer, BIO returns 0 on retry
+ * Test 8-15: Repeat of above with TLSv1.2
+ */
+static int test_handshake_retry(int idx)
+{
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+ BIO *tmp = NULL, *bretry = BIO_new(bio_s_always_retry());
+ int maxversion = 0;
+
+ if (!TEST_ptr(bretry))
+ goto end;
+
+#ifndef OPENSSL_NO_TLS1_2
+ if ((idx & 8) == 8)
+ maxversion = TLS1_2_VERSION;
+#else
+ if ((idx & 8) == 8)
+ return TEST_skip("No TLSv1.2");
+#endif
+
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(), 0, maxversion,
+ &sctx, &cctx, cert, privkey)))
+ goto end;
+
+ /*
+ * Add a large amount of data to fill the buffering BIO used by the SSL
+ * object
+ */
+ if ((idx & 1) == 1 && !ssl_ctx_add_large_cert_chain(libctx, sctx, cert))
+ goto end;
+
+ /*
+ * We don't actually configure a client cert, but neither do we fail if one
+ * isn't present.
+ */
+ if ((idx & 2) == 2)
+ SSL_CTX_set_verify(sctx, SSL_VERIFY_PEER, NULL);
+
+ if ((idx & 4) == 4)
+ set_always_retry_err_val(0);
+
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl,
+ &clientssl, NULL, NULL)))
+ goto end;
+
+ tmp = SSL_get_wbio(serverssl);
+ if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
+ tmp = NULL;
+ goto end;
+ }
+ SSL_set0_wbio(serverssl, bretry);
+ bretry = NULL;
+
+ if (!TEST_int_eq(SSL_connect(clientssl), -1))
+ goto end;
+
+ if (!TEST_int_eq(SSL_accept(serverssl), -1)
+ || !TEST_int_eq(SSL_get_error(serverssl, -1), SSL_ERROR_WANT_WRITE))
+ goto end;
+
+ /* Restore a BIO that will let the write succeed */
+ SSL_set0_wbio(serverssl, tmp);
+ tmp = NULL;
+
+ if (!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);
+ BIO_free(bretry);
+ BIO_free(tmp);
+ set_always_retry_err_val(-1);
+ return testresult;
+}
+
+/*
+ * Test that receiving retries when writing application data works as expected
+ */
+static int test_data_retry(void)
+{
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+ unsigned char inbuf[1200], outbuf[1200];
+ size_t i;
+ BIO *tmp = NULL;
+ BIO *bretry = BIO_new(bio_s_maybe_retry());
+ size_t written, readbytes, totread = 0;
+
+ if (!TEST_ptr(bretry))
+ goto end;
+
+ for (i = 0; i < sizeof(inbuf); i++)
+ inbuf[i] = (unsigned char)(0xff & i);
+ memset(outbuf, 0, sizeof(outbuf));
+
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(), 0, 0, &sctx, &cctx,
+ cert, privkey)))
+ 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)))
+ goto end;
+
+ /* Smallest possible max send fragment is 512 */
+ if (!TEST_true(SSL_set_max_send_fragment(clientssl, 512)))
+ goto end;
+
+ tmp = SSL_get_wbio(clientssl);
+ if (!TEST_ptr(tmp))
+ goto end;
+ if (!TEST_true(BIO_up_ref(tmp)))
+ goto end;
+ BIO_push(bretry, tmp);
+ tmp = NULL;
+ SSL_set0_wbio(clientssl, bretry);
+ if (!BIO_up_ref(bretry)) {
+ bretry = NULL;
+ goto end;
+ }
+
+ for (i = 0; i < 3; i++) {
+ /* We expect this call to make no progress and indicate retry */
+ if (!TEST_false(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_error(clientssl, 0), SSL_ERROR_WANT_WRITE))
+ goto end;
+
+ /* Allow one write to progress, but the next one to signal retry */
+ if (!TEST_true(BIO_ctrl(bretry, MAYBE_RETRY_CTRL_SET_RETRY_AFTER_CNT, 1,
+ NULL)))
+ goto end;
+
+ if (i == 2)
+ break;
+
+ /*
+ * This call will hopefully make progress but will still indicate retry
+ * because there is more data than will fit into a single record.
+ */
+ if (!TEST_false(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written)))
+ goto end;
+ if (!TEST_int_eq(SSL_get_error(clientssl, 0), SSL_ERROR_WANT_WRITE))
+ goto end;
+ }
+
+ /* The final call should write the last chunk of data and succeed */
+ if (!TEST_true(SSL_write_ex(clientssl, inbuf, sizeof(inbuf), &written)))
+ goto end;
+ /* Read all the data available */
+ while (SSL_read_ex(serverssl, outbuf + totread, sizeof(outbuf) - totread,
+ &readbytes))
+ totread += readbytes;
+ if (!TEST_mem_eq(inbuf, sizeof(inbuf), outbuf, totread))
+ goto end;
+
+ testresult = 1;
+end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ BIO_free_all(bretry);
+ BIO_free(tmp);
+ return testresult;
+}
+
+struct resume_servername_cb_data {
+ int i;
+ SSL_CTX *cctx;
+ SSL_CTX *sctx;
+ SSL_SESSION *sess;
+ int recurse;
+};
+
+/*
+ * Servername callback. We use it here to run another complete handshake using
+ * the same session - and mark the session as not_resuamble at the end
+ */
+static int resume_servername_cb(SSL *s, int *ad, void *arg)
+{
+ struct resume_servername_cb_data *cbdata = arg;
+ SSL *serverssl = NULL, *clientssl = NULL;
+ int ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ if (cbdata->recurse)
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ if ((cbdata->i % 3) != 1)
+ return SSL_TLSEXT_ERR_OK;
+
+ cbdata->recurse = 1;
+
+ if (!TEST_true(create_ssl_objects(cbdata->sctx, cbdata->cctx, &serverssl,
+ &clientssl, NULL, NULL))
+ || !TEST_true(SSL_set_session(clientssl, cbdata->sess)))
+ goto end;
+
+ ERR_set_mark();
+ /*
+ * We expect this to fail - because the servername cb will fail. This will
+ * mark the session as not_resumable.
+ */
+ if (!TEST_false(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) {
+ ERR_clear_last_mark();
+ goto end;
+ }
+ ERR_pop_to_mark();
+
+ ret = SSL_TLSEXT_ERR_OK;
+ end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ cbdata->recurse = 0;
+ return ret;
+}
+/*
+ * Test multiple resumptions and cache size handling
+ * Test 0: TLSv1.3 (max_early_data set)
+ * Test 1: TLSv1.3 (SSL_OP_NO_TICKET set)
+ * Test 2: TLSv1.3 (max_early_data and SSL_OP_NO_TICKET set)
+ * Test 3: TLSv1.3 (SSL_OP_NO_TICKET, simultaneous resumes)
+ * Test 4: TLSv1.2
+ */
+static int test_multi_resume(int idx)
+{
+ SSL_CTX *sctx = NULL, *cctx = NULL;
+ SSL *serverssl = NULL, *clientssl = NULL;
+ SSL_SESSION *sess = NULL;
+ int max_version = TLS1_3_VERSION;
+ int i, testresult = 0;
+ struct resume_servername_cb_data cbdata;
+
+#if defined(OPENSSL_NO_TLS1_2)
+ if (idx == 4)
+ return TEST_skip("TLSv1.2 is disabled in this build");
+#else
+ if (idx == 4)
+ max_version = TLS1_2_VERSION;
+#endif
+#if defined(OSSL_NO_USABLE_TLS1_3)
+ if (idx != 4)
+ return TEST_skip("No usable TLSv1.3 in this build");
+#endif
+
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
+ TLS_client_method(), TLS1_VERSION,
+ max_version, &sctx, &cctx, cert,
+ privkey)))
+ goto end;
+
+ /*
+ * TLSv1.3 only uses a session cache if either max_early_data > 0 (used for
+ * replay protection), or if SSL_OP_NO_TICKET is in use
+ */
+ if (idx == 0 || idx == 2) {
+ if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024)))
+ goto end;
+ }
+ if (idx == 1 || idx == 2 || idx == 3)
+ SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET);
+
+ SSL_CTX_sess_set_cache_size(sctx, 5);
+
+ if (idx == 3) {
+ SSL_CTX_set_tlsext_servername_callback(sctx, resume_servername_cb);
+ SSL_CTX_set_tlsext_servername_arg(sctx, &cbdata);
+ cbdata.cctx = cctx;
+ cbdata.sctx = sctx;
+ cbdata.recurse = 0;
+ }
+
+ for (i = 0; i < 30; i++) {
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+ NULL, NULL))
+ || !TEST_true(SSL_set_session(clientssl, sess)))
+ goto end;
+
+ /*
+ * Check simultaneous resumes. We pause the connection part way through
+ * the handshake by (mis)using the servername_cb. The pause occurs after
+ * session resumption has already occurred, but before any session
+ * tickets have been issued. While paused we run another complete
+ * handshake resuming the same session.
+ */
+ if (idx == 3) {
+ cbdata.i = i;
+ cbdata.sess = sess;
+ }
+
+ /*
+ * Recreate a bug where dynamically changing the max_early_data value
+ * can cause sessions in the session cache which cannot be deleted.
+ */
+ if ((idx == 0 || idx == 2) && (i % 3) == 2)
+ SSL_set_max_early_data(serverssl, 0);
+
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
+ goto end;
+
+ if (sess == NULL || (idx == 0 && (i % 3) == 2)) {
+ if (!TEST_false(SSL_session_reused(clientssl)))
+ goto end;
+ } else {
+ if (!TEST_true(SSL_session_reused(clientssl)))
+ goto end;
+ }
+ SSL_SESSION_free(sess);
+
+ /* Do a full handshake, followed by two resumptions */
+ if ((i % 3) == 2) {
+ sess = NULL;
+ } else {
+ if (!TEST_ptr((sess = SSL_get1_session(clientssl))))
+ goto end;
+ }
+
+ SSL_shutdown(clientssl);
+ SSL_shutdown(serverssl);
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ serverssl = clientssl = NULL;
+ }
+
+ /* We should never exceed the session cache size limit */
+ if (!TEST_long_le(SSL_CTX_sess_number(sctx), 5))
+ goto end;
+
+ testresult = 1;
+ end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+ SSL_SESSION_free(sess);
+ return testresult;
+}
+
OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n")
int setup_tests(void)
# else
ADD_ALL_TESTS(test_tls13_psk, 4);
# endif /* OPENSSL_NO_PSK */
+#ifndef OSSL_NO_USABLE_TLS1_3
+ ADD_ALL_TESTS(test_tls13_no_dhe_kex, 8);
+#endif /* OSSL_NO_USABLE_TLS1_3 */
# ifndef OPENSSL_NO_TLS1_2
/* Test with both TLSv1.3 and 1.2 versions */
ADD_ALL_TESTS(test_key_exchange, 14);
ADD_ALL_TESTS(test_key_update_local_in_write, 2);
ADD_ALL_TESTS(test_key_update_local_in_read, 2);
#endif
- ADD_ALL_TESTS(test_ssl_clear, 2);
+ ADD_ALL_TESTS(test_ssl_clear, 8);
ADD_ALL_TESTS(test_max_fragment_len_ext, OSSL_NELEM(max_fragment_len_test));
#if !defined(OPENSSL_NO_SRP) && !defined(OPENSSL_NO_TLS1_2)
ADD_ALL_TESTS(test_srp, 6);
ADD_ALL_TESTS(test_multiblock_write, OSSL_NELEM(multiblock_cipherlist_data));
#endif
ADD_ALL_TESTS(test_servername, 10);
+ ADD_TEST(test_unknown_sigalgs_groups);
#if !defined(OPENSSL_NO_EC) \
&& (!defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2))
ADD_ALL_TESTS(test_sigalgs_available, 6);
ADD_TEST(test_set_verify_cert_store_ssl_ctx);
ADD_TEST(test_set_verify_cert_store_ssl);
ADD_ALL_TESTS(test_session_timeout, 1);
+#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
+ ADD_ALL_TESTS(test_session_cache_overflow, 4);
+#endif
ADD_TEST(test_load_dhfile);
#ifndef OSSL_NO_USABLE_TLS1_3
ADD_TEST(test_read_ahead_key_change);
ADD_ALL_TESTS(test_serverinfo_custom, 4);
#endif
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE)
- ADD_ALL_TESTS(test_pipelining, 6);
+ ADD_ALL_TESTS(test_pipelining, 7);
#endif
ADD_ALL_TESTS(test_version, 6);
ADD_TEST(test_rstate_string);
+ ADD_ALL_TESTS(test_handshake_retry, 16);
+ ADD_TEST(test_data_retry);
+ ADD_ALL_TESTS(test_multi_resume, 5);
return 1;
err:
OPENSSL_free(privkey8192);
bio_s_mempacket_test_free();
bio_s_always_retry_free();
+ bio_s_maybe_retry_free();
OSSL_PROVIDER_unload(defctxnull);
OSSL_LIB_CTX_free(libctx);
}