Allow qtestlib to use a "fake_now" implementation

We then use it in test_corrupted_data() to remove an OSSL_sleep() which
may fail in some builds.

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21332)
This commit is contained in:
Matt Caswell 2023-07-03 16:58:46 +01:00 committed by Pauli
parent d001006e50
commit f9fcc7c727
4 changed files with 40 additions and 18 deletions

View File

@ -66,9 +66,16 @@ static void handshake_finish(void *arg);
static BIO_METHOD *get_bio_method(void);
static OSSL_TIME fake_now;
static OSSL_TIME fake_now_cb(void *arg)
{
return fake_now;
}
int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
char *certfile, char *keyfile,
int block, QUIC_TSERVER **qtserv, SSL **cssl,
int flags, QUIC_TSERVER **qtserv, SSL **cssl,
QTEST_FAULT **fault)
{
/* ALPN value as recognised by QUIC_TSERVER */
@ -92,7 +99,7 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
if (!TEST_ptr(peeraddr = BIO_ADDR_new()))
goto err;
if (block) {
if ((flags & QTEST_FLAG_BLOCK) != 0) {
#if !defined(OPENSSL_NO_POSIX_IO)
int cfd, sfd;
@ -132,7 +139,8 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
SSL_set_bio(*cssl, cbio, cbio);
if (!TEST_true(SSL_set_blocking_mode(*cssl, block)))
if (!TEST_true(SSL_set_blocking_mode(*cssl,
(flags & QTEST_FLAG_BLOCK) != 0 ? 1 : 0)))
goto err;
if (!TEST_true(SSL_set_initial_peer_addr(*cssl, peeraddr)))
@ -157,6 +165,10 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
tserver_args.net_rbio = sbio;
tserver_args.net_wbio = fisbio;
tserver_args.alpn = NULL;
if ((flags & QTEST_FLAG_FAKE_TIME) != 0) {
fake_now = ossl_time_zero();
tserver_args.now_cb = fake_now_cb;
}
if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile,
keyfile)))
@ -186,6 +198,11 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
return 0;
}
void qtest_add_time(uint64_t millis)
{
fake_now = ossl_time_add(fake_now, ossl_ms2time(millis));
}
int qtest_supports_blocking(void)
{
#if !defined(OPENSSL_NO_POSIX_IO) && defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
@ -271,6 +288,7 @@ int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl)
if (!clienterr && retc <= 0)
SSL_handle_events(clientssl);
if (!servererr && rets <= 0) {
qtest_add_time(1);
ossl_quic_tserver_tick(qtserv);
servererr = ossl_quic_tserver_is_term_any(qtserv);
if (!servererr)

View File

@ -24,16 +24,26 @@ typedef struct qtest_fault_encrypted_extensions {
size_t extensionslen;
} QTEST_ENCRYPTED_EXTENSIONS;
/* Flags for use with qtest_create_quic_objects() */
/* Indicates whether we are using blocking mode or not */
#define QTEST_FLAG_BLOCK 1
/* Use fake time rather than real time */
#define QTEST_FLAG_FAKE_TIME 2
/*
* Given an SSL_CTX for the client and filenames for the server certificate and
* keyfile, create a server and client instances as well as a fault injector
* instance. |block| indicates whether we are using blocking mode or not.
* instance. |flags| is the logical or of flags defined above, or 0 if none.
*/
int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
char *certfile, char *keyfile, int block,
char *certfile, char *keyfile, int flags,
QUIC_TSERVER **qtserv, SSL **cssl,
QTEST_FAULT **fault);
/* Where QTEST_FLAG_FAKE_TIME is used, add millis to the current time */
void qtest_add_time(uint64_t millis);
/*
* Free up a Fault Injector instance
*/

View File

@ -58,8 +58,8 @@ static int test_quic_write_read(int idx)
if (!TEST_ptr(cctx)
|| !TEST_true(qtest_create_quic_objects(libctx, cctx, cert, privkey,
idx, &qtserv, &clientquic,
NULL))
idx == 1 ? QTEST_FLAG_BLOCK : 0,
&qtserv, &clientquic, NULL))
|| !TEST_true(SSL_set_tlsext_host_name(clientquic, "localhost"))
|| !TEST_true(qtest_create_quic_connection(qtserv, clientquic)))
goto end;

View File

@ -273,8 +273,9 @@ static int test_corrupted_data(int idx)
if (!TEST_ptr(cctx))
goto err;
if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey, 0,
&qtserv, &cssl, &fault)))
if (!TEST_true(qtest_create_quic_objects(NULL, cctx, cert, privkey,
QTEST_FLAG_FAKE_TIME, &qtserv,
&cssl, &fault)))
goto err;
if (idx == 0) {
@ -315,16 +316,9 @@ static int test_corrupted_data(int idx)
* Introduce a small delay so that the above packet has time to be detected
* as lost. Loss detection times are based on RTT which should be very
* fast for us since there isn't really a network. The loss delay timer is
* always at least 1ms though. We sleep for 100ms.
* TODO(QUIC): This assumes the calculated RTT will always be way less than
* 100ms - which it should be...but can we always guarantee this? An
* alternative might be to put in our own ossl_time_now() implementation for
* these tests and control the timer as part of the test. This approach has
* the added advantage that the test will behave reliably when run in a
* debugger. Without it may get unreliable debugging results. This would
* require some significant refactoring of the ssl/quic code though.
* always at least 1ms though. We skip forward 100ms
*/
OSSL_sleep(100);
qtest_add_time(100);
/* Send rest of message */
if (!TEST_true(ossl_quic_tserver_write(qtserv, sid, (unsigned char *)msg + 5,