1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery *
4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery */
9*e7be843bSPierre Pronchery #include <openssl/ssl.h>
10*e7be843bSPierre Pronchery #include <openssl/quic.h>
11*e7be843bSPierre Pronchery #include <openssl/bio.h>
12*e7be843bSPierre Pronchery #include "internal/common.h"
13*e7be843bSPierre Pronchery #include "internal/sockets.h"
14*e7be843bSPierre Pronchery #include "internal/quic_tserver.h"
15*e7be843bSPierre Pronchery #include "internal/quic_thread_assist.h"
16*e7be843bSPierre Pronchery #include "internal/quic_ssl.h"
17*e7be843bSPierre Pronchery #include "internal/time.h"
18*e7be843bSPierre Pronchery #include "testutil.h"
19*e7be843bSPierre Pronchery
20*e7be843bSPierre Pronchery static const char msg1[] = "The quick brown fox jumped over the lazy dogs.";
21*e7be843bSPierre Pronchery static char msg2[1024], msg3[1024];
22*e7be843bSPierre Pronchery static OSSL_TIME fake_time;
23*e7be843bSPierre Pronchery static CRYPTO_RWLOCK *fake_time_lock;
24*e7be843bSPierre Pronchery
25*e7be843bSPierre Pronchery static const char *certfile, *keyfile;
26*e7be843bSPierre Pronchery
is_want(SSL * s,int ret)27*e7be843bSPierre Pronchery static int is_want(SSL *s, int ret)
28*e7be843bSPierre Pronchery {
29*e7be843bSPierre Pronchery int ec = SSL_get_error(s, ret);
30*e7be843bSPierre Pronchery
31*e7be843bSPierre Pronchery return ec == SSL_ERROR_WANT_READ || ec == SSL_ERROR_WANT_WRITE;
32*e7be843bSPierre Pronchery }
33*e7be843bSPierre Pronchery
34*e7be843bSPierre Pronchery static unsigned char scratch_buf[2048];
35*e7be843bSPierre Pronchery
fake_now(void * arg)36*e7be843bSPierre Pronchery static OSSL_TIME fake_now(void *arg)
37*e7be843bSPierre Pronchery {
38*e7be843bSPierre Pronchery OSSL_TIME t;
39*e7be843bSPierre Pronchery
40*e7be843bSPierre Pronchery if (!CRYPTO_THREAD_read_lock(fake_time_lock))
41*e7be843bSPierre Pronchery return ossl_time_zero();
42*e7be843bSPierre Pronchery
43*e7be843bSPierre Pronchery t = fake_time;
44*e7be843bSPierre Pronchery
45*e7be843bSPierre Pronchery CRYPTO_THREAD_unlock(fake_time_lock);
46*e7be843bSPierre Pronchery return t;
47*e7be843bSPierre Pronchery }
48*e7be843bSPierre Pronchery
real_now(void * arg)49*e7be843bSPierre Pronchery static OSSL_TIME real_now(void *arg)
50*e7be843bSPierre Pronchery {
51*e7be843bSPierre Pronchery return ossl_time_now();
52*e7be843bSPierre Pronchery }
53*e7be843bSPierre Pronchery
do_test(int use_thread_assist,int use_fake_time,int use_inject)54*e7be843bSPierre Pronchery static int do_test(int use_thread_assist, int use_fake_time, int use_inject)
55*e7be843bSPierre Pronchery {
56*e7be843bSPierre Pronchery int testresult = 0, ret;
57*e7be843bSPierre Pronchery int s_fd = -1, c_fd = -1;
58*e7be843bSPierre Pronchery BIO *s_net_bio = NULL, *s_net_bio_own = NULL;
59*e7be843bSPierre Pronchery BIO *c_net_bio = NULL, *c_net_bio_own = NULL;
60*e7be843bSPierre Pronchery BIO *c_pair_own = NULL, *s_pair_own = NULL;
61*e7be843bSPierre Pronchery QUIC_TSERVER_ARGS tserver_args = {0};
62*e7be843bSPierre Pronchery QUIC_TSERVER *tserver = NULL;
63*e7be843bSPierre Pronchery BIO_ADDR *s_addr_ = NULL;
64*e7be843bSPierre Pronchery struct in_addr ina = {0};
65*e7be843bSPierre Pronchery union BIO_sock_info_u s_info = {0};
66*e7be843bSPierre Pronchery SSL_CTX *c_ctx = NULL;
67*e7be843bSPierre Pronchery SSL *c_ssl = NULL;
68*e7be843bSPierre Pronchery int c_connected = 0, c_write_done = 0, c_begin_read = 0, s_read_done = 0;
69*e7be843bSPierre Pronchery int c_wait_eos = 0, c_done_eos = 0;
70*e7be843bSPierre Pronchery int c_start_idle_test = 0, c_done_idle_test = 0;
71*e7be843bSPierre Pronchery size_t l = 0, s_total_read = 0, s_total_written = 0, c_total_read = 0;
72*e7be843bSPierre Pronchery size_t idle_units_done = 0;
73*e7be843bSPierre Pronchery int s_begin_write = 0;
74*e7be843bSPierre Pronchery OSSL_TIME start_time;
75*e7be843bSPierre Pronchery unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
76*e7be843bSPierre Pronchery size_t limit_ms = 10000;
77*e7be843bSPierre Pronchery
78*e7be843bSPierre Pronchery #if defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
79*e7be843bSPierre Pronchery if (use_thread_assist) {
80*e7be843bSPierre Pronchery TEST_skip("thread assisted mode not enabled");
81*e7be843bSPierre Pronchery return 1;
82*e7be843bSPierre Pronchery }
83*e7be843bSPierre Pronchery #endif
84*e7be843bSPierre Pronchery
85*e7be843bSPierre Pronchery ina.s_addr = htonl(0x7f000001UL);
86*e7be843bSPierre Pronchery
87*e7be843bSPierre Pronchery /* Setup test server. */
88*e7be843bSPierre Pronchery s_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0);
89*e7be843bSPierre Pronchery if (!TEST_int_ge(s_fd, 0))
90*e7be843bSPierre Pronchery goto err;
91*e7be843bSPierre Pronchery
92*e7be843bSPierre Pronchery if (!TEST_true(BIO_socket_nbio(s_fd, 1)))
93*e7be843bSPierre Pronchery goto err;
94*e7be843bSPierre Pronchery
95*e7be843bSPierre Pronchery if (!TEST_ptr(s_addr_ = BIO_ADDR_new()))
96*e7be843bSPierre Pronchery goto err;
97*e7be843bSPierre Pronchery
98*e7be843bSPierre Pronchery if (!TEST_true(BIO_ADDR_rawmake(s_addr_, AF_INET, &ina, sizeof(ina), 0)))
99*e7be843bSPierre Pronchery goto err;
100*e7be843bSPierre Pronchery
101*e7be843bSPierre Pronchery if (!TEST_true(BIO_bind(s_fd, s_addr_, 0)))
102*e7be843bSPierre Pronchery goto err;
103*e7be843bSPierre Pronchery
104*e7be843bSPierre Pronchery s_info.addr = s_addr_;
105*e7be843bSPierre Pronchery if (!TEST_true(BIO_sock_info(s_fd, BIO_SOCK_INFO_ADDRESS, &s_info)))
106*e7be843bSPierre Pronchery goto err;
107*e7be843bSPierre Pronchery
108*e7be843bSPierre Pronchery if (!TEST_int_gt(BIO_ADDR_rawport(s_addr_), 0))
109*e7be843bSPierre Pronchery goto err;
110*e7be843bSPierre Pronchery
111*e7be843bSPierre Pronchery if (!TEST_ptr(s_net_bio = s_net_bio_own = BIO_new_dgram(s_fd, 0)))
112*e7be843bSPierre Pronchery goto err;
113*e7be843bSPierre Pronchery
114*e7be843bSPierre Pronchery if (!BIO_up_ref(s_net_bio))
115*e7be843bSPierre Pronchery goto err;
116*e7be843bSPierre Pronchery
117*e7be843bSPierre Pronchery fake_time = ossl_ms2time(1000);
118*e7be843bSPierre Pronchery
119*e7be843bSPierre Pronchery tserver_args.net_rbio = s_net_bio;
120*e7be843bSPierre Pronchery tserver_args.net_wbio = s_net_bio;
121*e7be843bSPierre Pronchery tserver_args.alpn = NULL;
122*e7be843bSPierre Pronchery tserver_args.ctx = NULL;
123*e7be843bSPierre Pronchery if (use_fake_time)
124*e7be843bSPierre Pronchery tserver_args.now_cb = fake_now;
125*e7be843bSPierre Pronchery
126*e7be843bSPierre Pronchery if (!TEST_ptr(tserver = ossl_quic_tserver_new(&tserver_args, certfile,
127*e7be843bSPierre Pronchery keyfile))) {
128*e7be843bSPierre Pronchery BIO_free(s_net_bio);
129*e7be843bSPierre Pronchery goto err;
130*e7be843bSPierre Pronchery }
131*e7be843bSPierre Pronchery
132*e7be843bSPierre Pronchery s_net_bio_own = NULL;
133*e7be843bSPierre Pronchery
134*e7be843bSPierre Pronchery if (use_inject) {
135*e7be843bSPierre Pronchery /*
136*e7be843bSPierre Pronchery * In inject mode we create a dgram pair to feed to the QUIC client on
137*e7be843bSPierre Pronchery * the read side. We don't feed anything to this, it is just a
138*e7be843bSPierre Pronchery * placeholder to give the client something which never returns any
139*e7be843bSPierre Pronchery * datagrams.
140*e7be843bSPierre Pronchery */
141*e7be843bSPierre Pronchery if (!TEST_true(BIO_new_bio_dgram_pair(&c_pair_own, 5000,
142*e7be843bSPierre Pronchery &s_pair_own, 5000)))
143*e7be843bSPierre Pronchery goto err;
144*e7be843bSPierre Pronchery }
145*e7be843bSPierre Pronchery
146*e7be843bSPierre Pronchery /* Setup test client. */
147*e7be843bSPierre Pronchery c_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0);
148*e7be843bSPierre Pronchery if (!TEST_int_ge(c_fd, 0))
149*e7be843bSPierre Pronchery goto err;
150*e7be843bSPierre Pronchery
151*e7be843bSPierre Pronchery if (!TEST_true(BIO_socket_nbio(c_fd, 1)))
152*e7be843bSPierre Pronchery goto err;
153*e7be843bSPierre Pronchery
154*e7be843bSPierre Pronchery if (!TEST_ptr(c_net_bio = c_net_bio_own = BIO_new_dgram(c_fd, 0)))
155*e7be843bSPierre Pronchery goto err;
156*e7be843bSPierre Pronchery
157*e7be843bSPierre Pronchery if (!BIO_dgram_set_peer(c_net_bio, s_addr_))
158*e7be843bSPierre Pronchery goto err;
159*e7be843bSPierre Pronchery
160*e7be843bSPierre Pronchery if (!TEST_ptr(c_ctx = SSL_CTX_new(use_thread_assist
161*e7be843bSPierre Pronchery ? OSSL_QUIC_client_thread_method()
162*e7be843bSPierre Pronchery : OSSL_QUIC_client_method())))
163*e7be843bSPierre Pronchery goto err;
164*e7be843bSPierre Pronchery
165*e7be843bSPierre Pronchery if (!TEST_ptr(c_ssl = SSL_new(c_ctx)))
166*e7be843bSPierre Pronchery goto err;
167*e7be843bSPierre Pronchery
168*e7be843bSPierre Pronchery if (use_fake_time)
169*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_set_override_now_cb(c_ssl, fake_now, NULL)))
170*e7be843bSPierre Pronchery goto err;
171*e7be843bSPierre Pronchery
172*e7be843bSPierre Pronchery /* 0 is a success for SSL_set_alpn_protos() */
173*e7be843bSPierre Pronchery if (!TEST_false(SSL_set_alpn_protos(c_ssl, alpn, sizeof(alpn))))
174*e7be843bSPierre Pronchery goto err;
175*e7be843bSPierre Pronchery
176*e7be843bSPierre Pronchery /* Takes ownership of our reference to the BIO. */
177*e7be843bSPierre Pronchery if (use_inject) {
178*e7be843bSPierre Pronchery SSL_set0_rbio(c_ssl, c_pair_own);
179*e7be843bSPierre Pronchery c_pair_own = NULL;
180*e7be843bSPierre Pronchery } else {
181*e7be843bSPierre Pronchery SSL_set0_rbio(c_ssl, c_net_bio);
182*e7be843bSPierre Pronchery
183*e7be843bSPierre Pronchery /* Get another reference to be transferred in the SSL_set0_wbio call. */
184*e7be843bSPierre Pronchery if (!TEST_true(BIO_up_ref(c_net_bio))) {
185*e7be843bSPierre Pronchery c_net_bio_own = NULL; /* SSL_free will free the first reference. */
186*e7be843bSPierre Pronchery goto err;
187*e7be843bSPierre Pronchery }
188*e7be843bSPierre Pronchery }
189*e7be843bSPierre Pronchery
190*e7be843bSPierre Pronchery SSL_set0_wbio(c_ssl, c_net_bio);
191*e7be843bSPierre Pronchery c_net_bio_own = NULL;
192*e7be843bSPierre Pronchery
193*e7be843bSPierre Pronchery if (!TEST_true(SSL_set_blocking_mode(c_ssl, 0)))
194*e7be843bSPierre Pronchery goto err;
195*e7be843bSPierre Pronchery
196*e7be843bSPierre Pronchery /*
197*e7be843bSPierre Pronchery * We use real time for the timeout not fake time. Otherwise with fake time
198*e7be843bSPierre Pronchery * we could hit a hang if we never increment the fake time
199*e7be843bSPierre Pronchery */
200*e7be843bSPierre Pronchery start_time = real_now(NULL);
201*e7be843bSPierre Pronchery
202*e7be843bSPierre Pronchery for (;;) {
203*e7be843bSPierre Pronchery if (ossl_time_compare(ossl_time_subtract(real_now(NULL), start_time),
204*e7be843bSPierre Pronchery ossl_ms2time(limit_ms)) >= 0) {
205*e7be843bSPierre Pronchery TEST_error("timeout while attempting QUIC server test");
206*e7be843bSPierre Pronchery goto err;
207*e7be843bSPierre Pronchery }
208*e7be843bSPierre Pronchery
209*e7be843bSPierre Pronchery if (!c_start_idle_test) {
210*e7be843bSPierre Pronchery ret = SSL_connect(c_ssl);
211*e7be843bSPierre Pronchery if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
212*e7be843bSPierre Pronchery goto err;
213*e7be843bSPierre Pronchery
214*e7be843bSPierre Pronchery if (ret == 1) {
215*e7be843bSPierre Pronchery c_connected = 1;
216*e7be843bSPierre Pronchery } else {
217*e7be843bSPierre Pronchery /*
218*e7be843bSPierre Pronchery * keep timer ticking to keep handshake running.
219*e7be843bSPierre Pronchery * The timer is important for calculation of ping deadline.
220*e7be843bSPierre Pronchery * If things stall for whatever reason we at least send
221*e7be843bSPierre Pronchery * ACK eliciting ping to let peer know we are here ready
222*e7be843bSPierre Pronchery * to hear back.
223*e7be843bSPierre Pronchery */
224*e7be843bSPierre Pronchery if (!TEST_true(CRYPTO_THREAD_write_lock(fake_time_lock)))
225*e7be843bSPierre Pronchery goto err;
226*e7be843bSPierre Pronchery fake_time = ossl_time_add(fake_time, ossl_ms2time(100));
227*e7be843bSPierre Pronchery CRYPTO_THREAD_unlock(fake_time_lock);
228*e7be843bSPierre Pronchery }
229*e7be843bSPierre Pronchery }
230*e7be843bSPierre Pronchery
231*e7be843bSPierre Pronchery if (c_connected && !c_write_done) {
232*e7be843bSPierre Pronchery if (!TEST_int_eq(SSL_write(c_ssl, msg1, sizeof(msg1) - 1),
233*e7be843bSPierre Pronchery (int)sizeof(msg1) - 1))
234*e7be843bSPierre Pronchery goto err;
235*e7be843bSPierre Pronchery
236*e7be843bSPierre Pronchery if (!TEST_true(SSL_stream_conclude(c_ssl, 0)))
237*e7be843bSPierre Pronchery goto err;
238*e7be843bSPierre Pronchery
239*e7be843bSPierre Pronchery c_write_done = 1;
240*e7be843bSPierre Pronchery }
241*e7be843bSPierre Pronchery
242*e7be843bSPierre Pronchery if (c_connected && c_write_done && !s_read_done) {
243*e7be843bSPierre Pronchery if (!ossl_quic_tserver_read(tserver, 0,
244*e7be843bSPierre Pronchery (unsigned char *)msg2 + s_total_read,
245*e7be843bSPierre Pronchery sizeof(msg2) - s_total_read, &l)) {
246*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_tserver_has_read_ended(tserver, 0)))
247*e7be843bSPierre Pronchery goto err;
248*e7be843bSPierre Pronchery
249*e7be843bSPierre Pronchery if (!TEST_mem_eq(msg1, sizeof(msg1) - 1, msg2, s_total_read))
250*e7be843bSPierre Pronchery goto err;
251*e7be843bSPierre Pronchery
252*e7be843bSPierre Pronchery s_begin_write = 1;
253*e7be843bSPierre Pronchery s_read_done = 1;
254*e7be843bSPierre Pronchery } else {
255*e7be843bSPierre Pronchery s_total_read += l;
256*e7be843bSPierre Pronchery if (!TEST_size_t_le(s_total_read, sizeof(msg1) - 1))
257*e7be843bSPierre Pronchery goto err;
258*e7be843bSPierre Pronchery }
259*e7be843bSPierre Pronchery }
260*e7be843bSPierre Pronchery
261*e7be843bSPierre Pronchery if (s_begin_write && s_total_written < sizeof(msg1) - 1) {
262*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_tserver_write(tserver, 0,
263*e7be843bSPierre Pronchery (unsigned char *)msg2 + s_total_written,
264*e7be843bSPierre Pronchery sizeof(msg1) - 1 - s_total_written, &l)))
265*e7be843bSPierre Pronchery goto err;
266*e7be843bSPierre Pronchery
267*e7be843bSPierre Pronchery s_total_written += l;
268*e7be843bSPierre Pronchery
269*e7be843bSPierre Pronchery if (s_total_written == sizeof(msg1) - 1) {
270*e7be843bSPierre Pronchery ossl_quic_tserver_conclude(tserver, 0);
271*e7be843bSPierre Pronchery c_begin_read = 1;
272*e7be843bSPierre Pronchery }
273*e7be843bSPierre Pronchery }
274*e7be843bSPierre Pronchery
275*e7be843bSPierre Pronchery if (c_begin_read && c_total_read < sizeof(msg1) - 1) {
276*e7be843bSPierre Pronchery ret = SSL_read_ex(c_ssl, msg3 + c_total_read,
277*e7be843bSPierre Pronchery sizeof(msg1) - 1 - c_total_read, &l);
278*e7be843bSPierre Pronchery if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
279*e7be843bSPierre Pronchery goto err;
280*e7be843bSPierre Pronchery
281*e7be843bSPierre Pronchery c_total_read += l;
282*e7be843bSPierre Pronchery
283*e7be843bSPierre Pronchery if (c_total_read == sizeof(msg1) - 1) {
284*e7be843bSPierre Pronchery if (!TEST_mem_eq(msg1, sizeof(msg1) - 1,
285*e7be843bSPierre Pronchery msg3, c_total_read))
286*e7be843bSPierre Pronchery goto err;
287*e7be843bSPierre Pronchery
288*e7be843bSPierre Pronchery c_wait_eos = 1;
289*e7be843bSPierre Pronchery }
290*e7be843bSPierre Pronchery }
291*e7be843bSPierre Pronchery
292*e7be843bSPierre Pronchery if (c_wait_eos && !c_done_eos) {
293*e7be843bSPierre Pronchery unsigned char c;
294*e7be843bSPierre Pronchery
295*e7be843bSPierre Pronchery ret = SSL_read_ex(c_ssl, &c, sizeof(c), &l);
296*e7be843bSPierre Pronchery if (!TEST_false(ret))
297*e7be843bSPierre Pronchery goto err;
298*e7be843bSPierre Pronchery
299*e7be843bSPierre Pronchery /*
300*e7be843bSPierre Pronchery * Allow the implementation to take as long as it wants to finally
301*e7be843bSPierre Pronchery * notice EOS. Account for varied timings in OS networking stacks.
302*e7be843bSPierre Pronchery */
303*e7be843bSPierre Pronchery if (SSL_get_error(c_ssl, ret) != SSL_ERROR_WANT_READ) {
304*e7be843bSPierre Pronchery if (!TEST_int_eq(SSL_get_error(c_ssl, ret),
305*e7be843bSPierre Pronchery SSL_ERROR_ZERO_RETURN))
306*e7be843bSPierre Pronchery goto err;
307*e7be843bSPierre Pronchery
308*e7be843bSPierre Pronchery c_done_eos = 1;
309*e7be843bSPierre Pronchery if (use_thread_assist && use_fake_time) {
310*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_tserver_is_connected(tserver)))
311*e7be843bSPierre Pronchery goto err;
312*e7be843bSPierre Pronchery c_start_idle_test = 1;
313*e7be843bSPierre Pronchery limit_ms = 120000; /* extend time limit */
314*e7be843bSPierre Pronchery } else {
315*e7be843bSPierre Pronchery /* DONE */
316*e7be843bSPierre Pronchery break;
317*e7be843bSPierre Pronchery }
318*e7be843bSPierre Pronchery }
319*e7be843bSPierre Pronchery }
320*e7be843bSPierre Pronchery
321*e7be843bSPierre Pronchery if (c_start_idle_test && !c_done_idle_test) {
322*e7be843bSPierre Pronchery /* This is more than our default idle timeout of 30s. */
323*e7be843bSPierre Pronchery if (idle_units_done < 600) {
324*e7be843bSPierre Pronchery struct timeval tv;
325*e7be843bSPierre Pronchery int isinf;
326*e7be843bSPierre Pronchery
327*e7be843bSPierre Pronchery if (!TEST_true(CRYPTO_THREAD_write_lock(fake_time_lock)))
328*e7be843bSPierre Pronchery goto err;
329*e7be843bSPierre Pronchery fake_time = ossl_time_add(fake_time, ossl_ms2time(100));
330*e7be843bSPierre Pronchery CRYPTO_THREAD_unlock(fake_time_lock);
331*e7be843bSPierre Pronchery
332*e7be843bSPierre Pronchery ++idle_units_done;
333*e7be843bSPierre Pronchery ossl_quic_conn_force_assist_thread_wake(c_ssl);
334*e7be843bSPierre Pronchery
335*e7be843bSPierre Pronchery /*
336*e7be843bSPierre Pronchery * If the event timeout has expired then give the assistance
337*e7be843bSPierre Pronchery * thread a chance to catch up
338*e7be843bSPierre Pronchery */
339*e7be843bSPierre Pronchery if (!TEST_true(SSL_get_event_timeout(c_ssl, &tv, &isinf)))
340*e7be843bSPierre Pronchery goto err;
341*e7be843bSPierre Pronchery if (!isinf && ossl_time_compare(ossl_time_zero(),
342*e7be843bSPierre Pronchery ossl_time_from_timeval(tv)) >= 0)
343*e7be843bSPierre Pronchery OSSL_sleep(100); /* Ensure CPU scheduling for test purposes */
344*e7be843bSPierre Pronchery } else {
345*e7be843bSPierre Pronchery c_done_idle_test = 1;
346*e7be843bSPierre Pronchery }
347*e7be843bSPierre Pronchery }
348*e7be843bSPierre Pronchery
349*e7be843bSPierre Pronchery if (c_done_idle_test) {
350*e7be843bSPierre Pronchery /*
351*e7be843bSPierre Pronchery * If we have finished the fake idling duration, the connection
352*e7be843bSPierre Pronchery * should still be healthy in TA mode.
353*e7be843bSPierre Pronchery */
354*e7be843bSPierre Pronchery if (!TEST_true(ossl_quic_tserver_is_connected(tserver)))
355*e7be843bSPierre Pronchery goto err;
356*e7be843bSPierre Pronchery
357*e7be843bSPierre Pronchery /* DONE */
358*e7be843bSPierre Pronchery break;
359*e7be843bSPierre Pronchery }
360*e7be843bSPierre Pronchery
361*e7be843bSPierre Pronchery /*
362*e7be843bSPierre Pronchery * This is inefficient because we spin until things work without
363*e7be843bSPierre Pronchery * blocking but this is just a test.
364*e7be843bSPierre Pronchery */
365*e7be843bSPierre Pronchery if (!c_start_idle_test || c_done_idle_test) {
366*e7be843bSPierre Pronchery /* Inhibit manual ticking during idle test to test TA mode. */
367*e7be843bSPierre Pronchery SSL_handle_events(c_ssl);
368*e7be843bSPierre Pronchery }
369*e7be843bSPierre Pronchery
370*e7be843bSPierre Pronchery ossl_quic_tserver_tick(tserver);
371*e7be843bSPierre Pronchery
372*e7be843bSPierre Pronchery if (use_inject) {
373*e7be843bSPierre Pronchery BIO_MSG rmsg = {0};
374*e7be843bSPierre Pronchery size_t msgs_processed = 0;
375*e7be843bSPierre Pronchery
376*e7be843bSPierre Pronchery for (;;) {
377*e7be843bSPierre Pronchery /*
378*e7be843bSPierre Pronchery * Manually spoonfeed received datagrams from the real BIO_dgram
379*e7be843bSPierre Pronchery * into QUIC via the injection interface, thereby testing the
380*e7be843bSPierre Pronchery * injection interface.
381*e7be843bSPierre Pronchery */
382*e7be843bSPierre Pronchery rmsg.data = scratch_buf;
383*e7be843bSPierre Pronchery rmsg.data_len = sizeof(scratch_buf);
384*e7be843bSPierre Pronchery
385*e7be843bSPierre Pronchery if (!BIO_recvmmsg(c_net_bio, &rmsg, sizeof(rmsg), 1, 0, &msgs_processed)
386*e7be843bSPierre Pronchery || msgs_processed == 0 || rmsg.data_len == 0)
387*e7be843bSPierre Pronchery break;
388*e7be843bSPierre Pronchery
389*e7be843bSPierre Pronchery if (!TEST_true(SSL_inject_net_dgram(c_ssl, rmsg.data, rmsg.data_len,
390*e7be843bSPierre Pronchery NULL, NULL)))
391*e7be843bSPierre Pronchery goto err;
392*e7be843bSPierre Pronchery }
393*e7be843bSPierre Pronchery }
394*e7be843bSPierre Pronchery }
395*e7be843bSPierre Pronchery
396*e7be843bSPierre Pronchery testresult = 1;
397*e7be843bSPierre Pronchery err:
398*e7be843bSPierre Pronchery SSL_free(c_ssl);
399*e7be843bSPierre Pronchery SSL_CTX_free(c_ctx);
400*e7be843bSPierre Pronchery ossl_quic_tserver_free(tserver);
401*e7be843bSPierre Pronchery BIO_ADDR_free(s_addr_);
402*e7be843bSPierre Pronchery BIO_free(s_net_bio_own);
403*e7be843bSPierre Pronchery BIO_free(c_net_bio_own);
404*e7be843bSPierre Pronchery BIO_free(c_pair_own);
405*e7be843bSPierre Pronchery BIO_free(s_pair_own);
406*e7be843bSPierre Pronchery if (s_fd >= 0)
407*e7be843bSPierre Pronchery BIO_closesocket(s_fd);
408*e7be843bSPierre Pronchery if (c_fd >= 0)
409*e7be843bSPierre Pronchery BIO_closesocket(c_fd);
410*e7be843bSPierre Pronchery return testresult;
411*e7be843bSPierre Pronchery }
412*e7be843bSPierre Pronchery
test_tserver(int idx)413*e7be843bSPierre Pronchery static int test_tserver(int idx)
414*e7be843bSPierre Pronchery {
415*e7be843bSPierre Pronchery int thread_assisted, use_fake_time, use_inject;
416*e7be843bSPierre Pronchery
417*e7be843bSPierre Pronchery thread_assisted = idx % 2;
418*e7be843bSPierre Pronchery idx /= 2;
419*e7be843bSPierre Pronchery
420*e7be843bSPierre Pronchery use_inject = idx % 2;
421*e7be843bSPierre Pronchery idx /= 2;
422*e7be843bSPierre Pronchery
423*e7be843bSPierre Pronchery use_fake_time = idx % 2;
424*e7be843bSPierre Pronchery
425*e7be843bSPierre Pronchery if (use_fake_time && !thread_assisted)
426*e7be843bSPierre Pronchery return 1;
427*e7be843bSPierre Pronchery
428*e7be843bSPierre Pronchery return do_test(thread_assisted, use_fake_time, use_inject);
429*e7be843bSPierre Pronchery }
430*e7be843bSPierre Pronchery
431*e7be843bSPierre Pronchery OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
432*e7be843bSPierre Pronchery
setup_tests(void)433*e7be843bSPierre Pronchery int setup_tests(void)
434*e7be843bSPierre Pronchery {
435*e7be843bSPierre Pronchery if (!test_skip_common_options()) {
436*e7be843bSPierre Pronchery TEST_error("Error parsing test options\n");
437*e7be843bSPierre Pronchery return 0;
438*e7be843bSPierre Pronchery }
439*e7be843bSPierre Pronchery
440*e7be843bSPierre Pronchery if (!TEST_ptr(certfile = test_get_argument(0))
441*e7be843bSPierre Pronchery || !TEST_ptr(keyfile = test_get_argument(1)))
442*e7be843bSPierre Pronchery return 0;
443*e7be843bSPierre Pronchery
444*e7be843bSPierre Pronchery if ((fake_time_lock = CRYPTO_THREAD_lock_new()) == NULL)
445*e7be843bSPierre Pronchery return 0;
446*e7be843bSPierre Pronchery
447*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_tserver, 2 * 2 * 2);
448*e7be843bSPierre Pronchery return 1;
449*e7be843bSPierre Pronchery }
450