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