]> git.ipfire.org Git - thirdparty/openssl.git/blob - test/helpers/quictestlib.c
threads_pthread.c: change inline to ossl_inline
[thirdparty/openssl.git] / test / helpers / quictestlib.c
1 /*
2 * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include <assert.h>
11 #include <openssl/configuration.h>
12 #include <openssl/bio.h>
13 #include "internal/e_os.h" /* For struct timeval */
14 #include "quictestlib.h"
15 #include "ssltestlib.h"
16 #include "../testutil.h"
17 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
18 # include "../threadstest.h"
19 #endif
20 #include "internal/quic_ssl.h"
21 #include "internal/quic_wire_pkt.h"
22 #include "internal/quic_record_tx.h"
23 #include "internal/quic_error.h"
24 #include "internal/packet.h"
25 #include "internal/tsan_assist.h"
26
27 #define GROWTH_ALLOWANCE 1024
28
29 struct noise_args_data_st {
30 BIO *cbio;
31 BIO *sbio;
32 BIO *tracebio;
33 int flags;
34 };
35
36 struct qtest_fault {
37 QUIC_TSERVER *qtserv;
38
39 /* Plain packet mutations */
40 /* Header for the plaintext packet */
41 QUIC_PKT_HDR pplainhdr;
42 /* iovec for the plaintext packet data buffer */
43 OSSL_QTX_IOVEC pplainio;
44 /* Allocated size of the plaintext packet data buffer */
45 size_t pplainbuf_alloc;
46 qtest_fault_on_packet_plain_cb pplaincb;
47 void *pplaincbarg;
48
49 /* Handshake message mutations */
50 /* Handshake message buffer */
51 unsigned char *handbuf;
52 /* Allocated size of the handshake message buffer */
53 size_t handbufalloc;
54 /* Actual length of the handshake message */
55 size_t handbuflen;
56 qtest_fault_on_handshake_cb handshakecb;
57 void *handshakecbarg;
58 qtest_fault_on_enc_ext_cb encextcb;
59 void *encextcbarg;
60
61 /* Cipher packet mutations */
62 qtest_fault_on_packet_cipher_cb pciphercb;
63 void *pciphercbarg;
64
65 /* Datagram mutations */
66 qtest_fault_on_datagram_cb datagramcb;
67 void *datagramcbarg;
68 /* The currently processed message */
69 BIO_MSG msg;
70 /* Allocated size of msg data buffer */
71 size_t msgalloc;
72 struct noise_args_data_st noiseargs;
73 };
74
75 static void packet_plain_finish(void *arg);
76 static void handshake_finish(void *arg);
77 static OSSL_TIME qtest_get_time(void);
78 static void qtest_reset_time(void);
79
80 static int using_fake_time = 0;
81 static OSSL_TIME fake_now;
82 static CRYPTO_RWLOCK *fake_now_lock = NULL;
83 static OSSL_TIME start_time;
84
85 static OSSL_TIME fake_now_cb(void *arg)
86 {
87 return qtest_get_time();
88 }
89
90 static void noise_msg_callback(int write_p, int version, int content_type,
91 const void *buf, size_t len, SSL *ssl,
92 void *arg)
93 {
94 struct noise_args_data_st *noiseargs = (struct noise_args_data_st *)arg;
95
96 if (content_type == SSL3_RT_QUIC_FRAME_FULL) {
97 PACKET pkt;
98 uint64_t frame_type;
99
100 if (!PACKET_buf_init(&pkt, buf, len))
101 return;
102
103 if (!ossl_quic_wire_peek_frame_header(&pkt, &frame_type, NULL))
104 return;
105
106 if (frame_type == OSSL_QUIC_FRAME_TYPE_PING) {
107 /*
108 * If either endpoint issues a ping frame then we are in danger
109 * of our noise being too much such that the connection itself
110 * fails. We back off on the noise for a bit to avoid that.
111 */
112 (void)BIO_ctrl(noiseargs->cbio, BIO_CTRL_NOISE_BACK_OFF, 0, NULL);
113 (void)BIO_ctrl(noiseargs->sbio, BIO_CTRL_NOISE_BACK_OFF, 0, NULL);
114 }
115 }
116
117 #ifndef OPENSSL_NO_SSL_TRACE
118 if ((noiseargs->flags & QTEST_FLAG_CLIENT_TRACE) != 0
119 && !SSL_is_server(ssl))
120 SSL_trace(write_p, version, content_type, buf, len, ssl,
121 noiseargs->tracebio);
122 #endif
123 }
124
125 int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
126 SSL_CTX *serverctx, char *certfile, char *keyfile,
127 int flags, QUIC_TSERVER **qtserv, SSL **cssl,
128 QTEST_FAULT **fault, BIO **tracebio)
129 {
130 /* ALPN value as recognised by QUIC_TSERVER */
131 unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
132 QUIC_TSERVER_ARGS tserver_args = {0};
133 BIO *cbio = NULL, *sbio = NULL, *fisbio = NULL;
134 BIO_ADDR *peeraddr = NULL;
135 struct in_addr ina = {0};
136 BIO *tmpbio = NULL;
137
138 *qtserv = NULL;
139 if (*cssl == NULL) {
140 *cssl = SSL_new(clientctx);
141 if (!TEST_ptr(*cssl))
142 return 0;
143 }
144
145 if (fault != NULL) {
146 *fault = OPENSSL_zalloc(sizeof(**fault));
147 if (*fault == NULL)
148 goto err;
149 }
150
151 #ifndef OPENSSL_NO_SSL_TRACE
152 if ((flags & QTEST_FLAG_CLIENT_TRACE) != 0) {
153 tmpbio = BIO_new_fp(stdout, BIO_NOCLOSE);
154 if (!TEST_ptr(tmpbio))
155 goto err;
156
157 SSL_set_msg_callback(*cssl, SSL_trace);
158 SSL_set_msg_callback_arg(*cssl, tmpbio);
159 }
160 #endif
161 if (tracebio != NULL)
162 *tracebio = tmpbio;
163
164 /* SSL_set_alpn_protos returns 0 for success! */
165 if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn))))
166 goto err;
167
168 if (!TEST_ptr(peeraddr = BIO_ADDR_new()))
169 goto err;
170
171 if ((flags & QTEST_FLAG_BLOCK) != 0) {
172 #if !defined(OPENSSL_NO_POSIX_IO)
173 int cfd, sfd;
174
175 /*
176 * For blocking mode we need to create actual sockets rather than doing
177 * everything in memory
178 */
179 if (!TEST_true(create_test_sockets(&cfd, &sfd, SOCK_DGRAM, peeraddr)))
180 goto err;
181 cbio = BIO_new_dgram(cfd, 1);
182 if (!TEST_ptr(cbio)) {
183 close(cfd);
184 close(sfd);
185 goto err;
186 }
187 sbio = BIO_new_dgram(sfd, 1);
188 if (!TEST_ptr(sbio)) {
189 close(sfd);
190 goto err;
191 }
192 #else
193 goto err;
194 #endif
195 } else {
196 if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0)))
197 goto err;
198
199 if (!TEST_true(BIO_dgram_set_caps(cbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))
200 || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)))
201 goto err;
202
203 /* Dummy server address */
204 if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina),
205 htons(0))))
206 goto err;
207 }
208
209 if ((flags & QTEST_FLAG_PACKET_SPLIT) != 0) {
210 BIO *pktsplitbio = BIO_new(bio_f_pkt_split_dgram_filter());
211
212 if (!TEST_ptr(pktsplitbio))
213 goto err;
214 cbio = BIO_push(pktsplitbio, cbio);
215
216 pktsplitbio = BIO_new(bio_f_pkt_split_dgram_filter());
217 if (!TEST_ptr(pktsplitbio))
218 goto err;
219 sbio = BIO_push(pktsplitbio, sbio);
220 }
221
222 if ((flags & QTEST_FLAG_NOISE) != 0) {
223 BIO *noisebio;
224 struct bio_noise_now_cb_st now_cb = { fake_now_cb, NULL };
225
226 /*
227 * It is an error to not have a QTEST_FAULT object when introducing noise
228 */
229 if (!TEST_ptr(fault))
230 goto err;
231
232 noisebio = BIO_new(bio_f_noisy_dgram_filter());
233
234 if (!TEST_ptr(noisebio))
235 goto err;
236 cbio = BIO_push(noisebio, cbio);
237 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) {
238 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_SET_NOW_CB,
239 0, &now_cb), 1))
240 goto err;
241 }
242
243 noisebio = BIO_new(bio_f_noisy_dgram_filter());
244
245 if (!TEST_ptr(noisebio))
246 goto err;
247 sbio = BIO_push(noisebio, sbio);
248 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) {
249 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_SET_NOW_CB,
250 0, &now_cb), 1))
251 goto err;
252 }
253 /*
254 * TODO(QUIC SERVER):
255 * Currently the simplistic handler of the quic tserver cannot cope
256 * with noise introduced in the first packet received from the
257 * client. This needs to be removed once we have proper server side
258 * handling.
259 */
260 (void)BIO_ctrl(sbio, BIO_CTRL_NOISE_BACK_OFF, 0, NULL);
261
262 (*fault)->noiseargs.cbio = cbio;
263 (*fault)->noiseargs.sbio = sbio;
264 (*fault)->noiseargs.tracebio = tmpbio;
265 (*fault)->noiseargs.flags = flags;
266
267 SSL_set_msg_callback(*cssl, noise_msg_callback);
268 SSL_set_msg_callback_arg(*cssl, &(*fault)->noiseargs);
269 }
270
271 SSL_set_bio(*cssl, cbio, cbio);
272
273 if (!TEST_true(SSL_set_blocking_mode(*cssl,
274 (flags & QTEST_FLAG_BLOCK) != 0 ? 1 : 0)))
275 goto err;
276
277 if (!TEST_true(SSL_set1_initial_peer_addr(*cssl, peeraddr)))
278 goto err;
279
280 fisbio = BIO_new(qtest_get_bio_method());
281 if (!TEST_ptr(fisbio))
282 goto err;
283
284 BIO_set_data(fisbio, fault == NULL ? NULL : *fault);
285
286 if (!BIO_up_ref(sbio))
287 goto err;
288 if (!TEST_ptr(BIO_push(fisbio, sbio))) {
289 BIO_free(sbio);
290 goto err;
291 }
292
293 tserver_args.libctx = libctx;
294 tserver_args.net_rbio = sbio;
295 tserver_args.net_wbio = fisbio;
296 tserver_args.alpn = NULL;
297 if (serverctx != NULL && !TEST_true(SSL_CTX_up_ref(serverctx)))
298 goto err;
299 tserver_args.ctx = serverctx;
300 if (fake_now_lock == NULL) {
301 fake_now_lock = CRYPTO_THREAD_lock_new();
302 if (fake_now_lock == NULL)
303 goto err;
304 }
305 if ((flags & QTEST_FLAG_FAKE_TIME) != 0) {
306 using_fake_time = 1;
307 qtest_reset_time();
308 tserver_args.now_cb = fake_now_cb;
309 (void)ossl_quic_conn_set_override_now_cb(*cssl, fake_now_cb, NULL);
310 } else {
311 using_fake_time = 0;
312 }
313
314 if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile,
315 keyfile)))
316 goto err;
317
318 /* Ownership of fisbio and sbio is now held by *qtserv */
319 sbio = NULL;
320 fisbio = NULL;
321
322 if ((flags & QTEST_FLAG_NOISE) != 0)
323 ossl_quic_tserver_set_msg_callback(*qtserv, noise_msg_callback,
324 &(*fault)->noiseargs);
325
326 if (fault != NULL)
327 (*fault)->qtserv = *qtserv;
328
329 BIO_ADDR_free(peeraddr);
330
331 return 1;
332 err:
333 SSL_CTX_free(tserver_args.ctx);
334 BIO_ADDR_free(peeraddr);
335 BIO_free_all(cbio);
336 BIO_free_all(fisbio);
337 BIO_free_all(sbio);
338 SSL_free(*cssl);
339 *cssl = NULL;
340 ossl_quic_tserver_free(*qtserv);
341 if (fault != NULL)
342 OPENSSL_free(*fault);
343 BIO_free(tmpbio);
344 if (tracebio != NULL)
345 *tracebio = NULL;
346
347 return 0;
348 }
349
350 void qtest_add_time(uint64_t millis)
351 {
352 if (!CRYPTO_THREAD_write_lock(fake_now_lock))
353 return;
354 fake_now = ossl_time_add(fake_now, ossl_ms2time(millis));
355 CRYPTO_THREAD_unlock(fake_now_lock);
356 }
357
358 static OSSL_TIME qtest_get_time(void)
359 {
360 OSSL_TIME ret;
361
362 if (!CRYPTO_THREAD_read_lock(fake_now_lock))
363 return ossl_time_zero();
364 ret = fake_now;
365 CRYPTO_THREAD_unlock(fake_now_lock);
366 return ret;
367 }
368
369 static void qtest_reset_time(void)
370 {
371 if (!CRYPTO_THREAD_write_lock(fake_now_lock))
372 return;
373 fake_now = ossl_time_zero();
374 CRYPTO_THREAD_unlock(fake_now_lock);
375 /* zero time can have a special meaning, bump it */
376 qtest_add_time(1);
377 }
378
379 void qtest_start_stopwatch(void)
380 {
381 start_time = qtest_get_time();
382 }
383
384 uint64_t qtest_get_stopwatch_time(void)
385 {
386 return ossl_time2ms(ossl_time_subtract(qtest_get_time(), start_time));
387 }
388
389 QTEST_FAULT *qtest_create_injector(QUIC_TSERVER *ts)
390 {
391 QTEST_FAULT *f;
392
393 f = OPENSSL_zalloc(sizeof(*f));
394 if (f == NULL)
395 return NULL;
396
397 f->qtserv = ts;
398 return f;
399
400 }
401
402 int qtest_supports_blocking(void)
403 {
404 #if !defined(OPENSSL_NO_POSIX_IO) && defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
405 return 1;
406 #else
407 return 0;
408 #endif
409 }
410
411 #define MAXLOOPS 1000
412
413 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
414 static int globserverret = 0;
415 static TSAN_QUALIFIER int abortserverthread = 0;
416 static QUIC_TSERVER *globtserv;
417 static const thread_t thread_zero;
418
419 static void run_server_thread(void)
420 {
421 /*
422 * This will operate in a busy loop because the server does not block,
423 * but should be acceptable because it is local and we expect this to be
424 * fast
425 */
426 globserverret = qtest_create_quic_connection(globtserv, NULL);
427 }
428 #endif
429
430 int qtest_wait_for_timeout(SSL *s, QUIC_TSERVER *qtserv)
431 {
432 struct timeval tv;
433 OSSL_TIME ctimeout, stimeout, mintimeout, now;
434 int cinf;
435
436 /* We don't need to wait in blocking mode */
437 if (s == NULL || SSL_get_blocking_mode(s))
438 return 1;
439
440 /* Don't wait if either BIO has data waiting */
441 if (BIO_pending(SSL_get_rbio(s)) > 0
442 || BIO_pending(ossl_quic_tserver_get0_rbio(qtserv)) > 0)
443 return 1;
444
445 /*
446 * Neither endpoint has data waiting to be read. We assume data transmission
447 * is instantaneous due to using mem based BIOs, so there is no data "in
448 * flight" and no more data will be sent by either endpoint until some time
449 * based event has occurred. Therefore, wait for a timeout to occur. This
450 * might happen if we are using the noisy BIO and datagrams have been lost.
451 */
452 if (!SSL_get_event_timeout(s, &tv, &cinf))
453 return 0;
454
455 if (using_fake_time)
456 now = qtest_get_time();
457 else
458 now = ossl_time_now();
459
460 ctimeout = cinf ? ossl_time_infinite() : ossl_time_from_timeval(tv);
461 stimeout = ossl_time_subtract(ossl_quic_tserver_get_deadline(qtserv), now);
462 mintimeout = ossl_time_min(ctimeout, stimeout);
463 if (ossl_time_is_infinite(mintimeout))
464 return 0;
465
466 if (using_fake_time)
467 qtest_add_time(ossl_time2ms(mintimeout));
468 else
469 OSSL_sleep(ossl_time2ms(mintimeout));
470
471 return 1;
472 }
473
474 int qtest_create_quic_connection_ex(QUIC_TSERVER *qtserv, SSL *clientssl,
475 int wanterr)
476 {
477 int retc = -1, rets = 0, abortctr = 0, ret = 0;
478 int clienterr = 0, servererr = 0;
479 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
480 /*
481 * Pointless initialisation to avoid bogus compiler warnings about using
482 * t uninitialised
483 */
484 thread_t t = thread_zero;
485
486 if (clientssl != NULL)
487 abortserverthread = 0;
488 #endif
489
490 if (!TEST_ptr(qtserv)) {
491 goto err;
492 } else if (clientssl == NULL) {
493 retc = 1;
494 } else if (SSL_get_blocking_mode(clientssl) > 0) {
495 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
496 /*
497 * clientssl is blocking. We will need a thread to complete the
498 * connection
499 */
500 globtserv = qtserv;
501 if (!TEST_true(run_thread(&t, run_server_thread)))
502 goto err;
503
504 qtserv = NULL;
505 rets = 1;
506 #else
507 TEST_error("No thread support in this build");
508 goto err;
509 #endif
510 }
511
512 do {
513 if (!clienterr && retc <= 0) {
514 int err;
515
516 retc = SSL_connect(clientssl);
517 if (retc <= 0) {
518 err = SSL_get_error(clientssl, retc);
519
520 if (err == wanterr) {
521 retc = 1;
522 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
523 if (qtserv == NULL && rets > 0)
524 tsan_store(&abortserverthread, 1);
525 else
526 #endif
527 rets = 1;
528 } else {
529 if (err != SSL_ERROR_WANT_READ
530 && err != SSL_ERROR_WANT_WRITE) {
531 TEST_info("SSL_connect() failed %d, %d", retc, err);
532 TEST_openssl_errors();
533 clienterr = 1;
534 }
535 }
536 }
537 }
538
539 qtest_add_time(1);
540 if (clientssl != NULL)
541 SSL_handle_events(clientssl);
542 if (qtserv != NULL)
543 ossl_quic_tserver_tick(qtserv);
544
545 if (!servererr && rets <= 0) {
546 servererr = ossl_quic_tserver_is_term_any(qtserv);
547 if (!servererr)
548 rets = ossl_quic_tserver_is_handshake_confirmed(qtserv);
549 }
550
551 if (clienterr && servererr)
552 goto err;
553
554 if (clientssl != NULL && ++abortctr == MAXLOOPS) {
555 TEST_info("No progress made");
556 goto err;
557 }
558
559 if ((retc <= 0 && !clienterr) || (rets <= 0 && !servererr)) {
560 if (!qtest_wait_for_timeout(clientssl, qtserv))
561 goto err;
562 }
563 } while ((retc <= 0 && !clienterr)
564 || (rets <= 0 && !servererr
565 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
566 && !tsan_load(&abortserverthread)
567 #endif
568 ));
569
570 if (qtserv == NULL && rets > 0) {
571 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
572 if (!TEST_true(wait_for_thread(t)) || !TEST_true(globserverret))
573 goto err;
574 #else
575 TEST_error("Should not happen");
576 goto err;
577 #endif
578 }
579
580 if (!clienterr && !servererr)
581 ret = 1;
582 err:
583 return ret;
584 }
585
586 int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl)
587 {
588 return qtest_create_quic_connection_ex(qtserv, clientssl, SSL_ERROR_NONE);
589 }
590
591 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
592 static TSAN_QUALIFIER int shutdowndone;
593
594 static void run_server_shutdown_thread(void)
595 {
596 /*
597 * This will operate in a busy loop because the server does not block,
598 * but should be acceptable because it is local and we expect this to be
599 * fast
600 */
601 do {
602 ossl_quic_tserver_tick(globtserv);
603 } while(!tsan_load(&shutdowndone));
604 }
605 #endif
606
607 int qtest_shutdown(QUIC_TSERVER *qtserv, SSL *clientssl)
608 {
609 int tickserver = 1;
610 int ret = 0;
611 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
612 /*
613 * Pointless initialisation to avoid bogus compiler warnings about using
614 * t uninitialised
615 */
616 thread_t t = thread_zero;
617 #endif
618
619 if (SSL_get_blocking_mode(clientssl) > 0) {
620 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
621 /*
622 * clientssl is blocking. We will need a thread to complete the
623 * connection
624 */
625 globtserv = qtserv;
626 shutdowndone = 0;
627 if (!TEST_true(run_thread(&t, run_server_shutdown_thread)))
628 return 0;
629
630 tickserver = 0;
631 #else
632 TEST_error("No thread support in this build");
633 return 0;
634 #endif
635 }
636
637 /* Busy loop in non-blocking mode. It should be quick because its local */
638 for (;;) {
639 int rc = SSL_shutdown(clientssl);
640
641 if (rc == 1) {
642 ret = 1;
643 break;
644 }
645
646 if (rc < 0)
647 break;
648
649 if (tickserver)
650 ossl_quic_tserver_tick(qtserv);
651 }
652
653 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
654 tsan_store(&shutdowndone, 1);
655 if (!tickserver) {
656 if (!TEST_true(wait_for_thread(t)))
657 ret = 0;
658 }
659 #endif
660
661 return ret;
662 }
663
664 int qtest_check_server_transport_err(QUIC_TSERVER *qtserv, uint64_t code)
665 {
666 const QUIC_TERMINATE_CAUSE *cause;
667
668 ossl_quic_tserver_tick(qtserv);
669
670 /*
671 * Check that the server has closed with the specified code from the client
672 */
673 if (!TEST_true(ossl_quic_tserver_is_term_any(qtserv)))
674 return 0;
675
676 cause = ossl_quic_tserver_get_terminate_cause(qtserv);
677 if (!TEST_ptr(cause)
678 || !TEST_true(cause->remote)
679 || !TEST_false(cause->app)
680 || !TEST_uint64_t_eq(cause->error_code, code))
681 return 0;
682
683 return 1;
684 }
685
686 int qtest_check_server_protocol_err(QUIC_TSERVER *qtserv)
687 {
688 return qtest_check_server_transport_err(qtserv, OSSL_QUIC_ERR_PROTOCOL_VIOLATION);
689 }
690
691 int qtest_check_server_frame_encoding_err(QUIC_TSERVER *qtserv)
692 {
693 return qtest_check_server_transport_err(qtserv, OSSL_QUIC_ERR_FRAME_ENCODING_ERROR);
694 }
695
696 void qtest_fault_free(QTEST_FAULT *fault)
697 {
698 if (fault == NULL)
699 return;
700
701 packet_plain_finish(fault);
702 handshake_finish(fault);
703
704 OPENSSL_free(fault);
705 }
706
707 static int packet_plain_mutate(const QUIC_PKT_HDR *hdrin,
708 const OSSL_QTX_IOVEC *iovecin, size_t numin,
709 QUIC_PKT_HDR **hdrout,
710 const OSSL_QTX_IOVEC **iovecout,
711 size_t *numout,
712 void *arg)
713 {
714 QTEST_FAULT *fault = arg;
715 size_t i, bufsz = 0;
716 unsigned char *cur;
717
718 /* Coalesce our data into a single buffer */
719
720 /* First calculate required buffer size */
721 for (i = 0; i < numin; i++)
722 bufsz += iovecin[i].buf_len;
723
724 fault->pplainio.buf_len = bufsz;
725
726 /* Add an allowance for possible growth */
727 bufsz += GROWTH_ALLOWANCE;
728
729 fault->pplainio.buf = cur = OPENSSL_malloc(bufsz);
730 if (cur == NULL) {
731 fault->pplainio.buf_len = 0;
732 return 0;
733 }
734
735 fault->pplainbuf_alloc = bufsz;
736
737 /* Copy in the data from the input buffers */
738 for (i = 0; i < numin; i++) {
739 memcpy(cur, iovecin[i].buf, iovecin[i].buf_len);
740 cur += iovecin[i].buf_len;
741 }
742
743 fault->pplainhdr = *hdrin;
744
745 /* Cast below is safe because we allocated the buffer */
746 if (fault->pplaincb != NULL
747 && !fault->pplaincb(fault, &fault->pplainhdr,
748 (unsigned char *)fault->pplainio.buf,
749 fault->pplainio.buf_len, fault->pplaincbarg))
750 return 0;
751
752 *hdrout = &fault->pplainhdr;
753 *iovecout = &fault->pplainio;
754 *numout = 1;
755
756 return 1;
757 }
758
759 static void packet_plain_finish(void *arg)
760 {
761 QTEST_FAULT *fault = arg;
762
763 /* Cast below is safe because we allocated the buffer */
764 OPENSSL_free((unsigned char *)fault->pplainio.buf);
765 fault->pplainio.buf_len = 0;
766 fault->pplainbuf_alloc = 0;
767 fault->pplainio.buf = NULL;
768 }
769
770 int qtest_fault_set_packet_plain_listener(QTEST_FAULT *fault,
771 qtest_fault_on_packet_plain_cb pplaincb,
772 void *pplaincbarg)
773 {
774 fault->pplaincb = pplaincb;
775 fault->pplaincbarg = pplaincbarg;
776
777 return ossl_quic_tserver_set_plain_packet_mutator(fault->qtserv,
778 packet_plain_mutate,
779 packet_plain_finish,
780 fault);
781 }
782
783 /* To be called from a packet_plain_listener callback */
784 int qtest_fault_resize_plain_packet(QTEST_FAULT *fault, size_t newlen)
785 {
786 unsigned char *buf;
787 size_t oldlen = fault->pplainio.buf_len;
788
789 /*
790 * Alloc'd size should always be non-zero, so if this fails we've been
791 * incorrectly called
792 */
793 if (fault->pplainbuf_alloc == 0)
794 return 0;
795
796 if (newlen > fault->pplainbuf_alloc) {
797 /* This exceeds our growth allowance. Fail */
798 return 0;
799 }
800
801 /* Cast below is safe because we allocated the buffer */
802 buf = (unsigned char *)fault->pplainio.buf;
803
804 if (newlen > oldlen) {
805 /* Extend packet with 0 bytes */
806 memset(buf + oldlen, 0, newlen - oldlen);
807 } /* else we're truncating or staying the same */
808
809 fault->pplainio.buf_len = newlen;
810 fault->pplainhdr.len = newlen;
811
812 return 1;
813 }
814
815 /*
816 * Prepend frame data into a packet. To be called from a packet_plain_listener
817 * callback
818 */
819 int qtest_fault_prepend_frame(QTEST_FAULT *fault, const unsigned char *frame,
820 size_t frame_len)
821 {
822 unsigned char *buf;
823 size_t old_len;
824
825 /*
826 * Alloc'd size should always be non-zero, so if this fails we've been
827 * incorrectly called
828 */
829 if (fault->pplainbuf_alloc == 0)
830 return 0;
831
832 /* Cast below is safe because we allocated the buffer */
833 buf = (unsigned char *)fault->pplainio.buf;
834 old_len = fault->pplainio.buf_len;
835
836 /* Extend the size of the packet by the size of the new frame */
837 if (!TEST_true(qtest_fault_resize_plain_packet(fault,
838 old_len + frame_len)))
839 return 0;
840
841 memmove(buf + frame_len, buf, old_len);
842 memcpy(buf, frame, frame_len);
843
844 return 1;
845 }
846
847 static int handshake_mutate(const unsigned char *msgin, size_t msginlen,
848 unsigned char **msgout, size_t *msgoutlen,
849 void *arg)
850 {
851 QTEST_FAULT *fault = arg;
852 unsigned char *buf;
853 unsigned long payloadlen;
854 unsigned int msgtype;
855 PACKET pkt;
856
857 buf = OPENSSL_malloc(msginlen + GROWTH_ALLOWANCE);
858 if (buf == NULL)
859 return 0;
860
861 fault->handbuf = buf;
862 fault->handbuflen = msginlen;
863 fault->handbufalloc = msginlen + GROWTH_ALLOWANCE;
864 memcpy(buf, msgin, msginlen);
865
866 if (!PACKET_buf_init(&pkt, buf, msginlen)
867 || !PACKET_get_1(&pkt, &msgtype)
868 || !PACKET_get_net_3(&pkt, &payloadlen)
869 || PACKET_remaining(&pkt) != payloadlen)
870 return 0;
871
872 /* Parse specific message types */
873 switch (msgtype) {
874 case SSL3_MT_ENCRYPTED_EXTENSIONS:
875 {
876 QTEST_ENCRYPTED_EXTENSIONS ee;
877
878 if (fault->encextcb == NULL)
879 break;
880
881 /*
882 * The EncryptedExtensions message is very simple. It just has an
883 * extensions block in it and nothing else.
884 */
885 ee.extensions = (unsigned char *)PACKET_data(&pkt);
886 ee.extensionslen = payloadlen;
887 if (!fault->encextcb(fault, &ee, payloadlen, fault->encextcbarg))
888 return 0;
889 }
890
891 default:
892 /* No specific handlers for these message types yet */
893 break;
894 }
895
896 if (fault->handshakecb != NULL
897 && !fault->handshakecb(fault, buf, fault->handbuflen,
898 fault->handshakecbarg))
899 return 0;
900
901 *msgout = buf;
902 *msgoutlen = fault->handbuflen;
903
904 return 1;
905 }
906
907 static void handshake_finish(void *arg)
908 {
909 QTEST_FAULT *fault = arg;
910
911 OPENSSL_free(fault->handbuf);
912 fault->handbuf = NULL;
913 }
914
915 int qtest_fault_set_handshake_listener(QTEST_FAULT *fault,
916 qtest_fault_on_handshake_cb handshakecb,
917 void *handshakecbarg)
918 {
919 fault->handshakecb = handshakecb;
920 fault->handshakecbarg = handshakecbarg;
921
922 return ossl_quic_tserver_set_handshake_mutator(fault->qtserv,
923 handshake_mutate,
924 handshake_finish,
925 fault);
926 }
927
928 int qtest_fault_set_hand_enc_ext_listener(QTEST_FAULT *fault,
929 qtest_fault_on_enc_ext_cb encextcb,
930 void *encextcbarg)
931 {
932 fault->encextcb = encextcb;
933 fault->encextcbarg = encextcbarg;
934
935 return ossl_quic_tserver_set_handshake_mutator(fault->qtserv,
936 handshake_mutate,
937 handshake_finish,
938 fault);
939 }
940
941 /* To be called from a handshake_listener callback */
942 int qtest_fault_resize_handshake(QTEST_FAULT *fault, size_t newlen)
943 {
944 unsigned char *buf;
945 size_t oldlen = fault->handbuflen;
946
947 /*
948 * Alloc'd size should always be non-zero, so if this fails we've been
949 * incorrectly called
950 */
951 if (fault->handbufalloc == 0)
952 return 0;
953
954 if (newlen > fault->handbufalloc) {
955 /* This exceeds our growth allowance. Fail */
956 return 0;
957 }
958
959 buf = (unsigned char *)fault->handbuf;
960
961 if (newlen > oldlen) {
962 /* Extend packet with 0 bytes */
963 memset(buf + oldlen, 0, newlen - oldlen);
964 } /* else we're truncating or staying the same */
965
966 fault->handbuflen = newlen;
967 return 1;
968 }
969
970 /* To be called from message specific listener callbacks */
971 int qtest_fault_resize_message(QTEST_FAULT *fault, size_t newlen)
972 {
973 /* First resize the underlying message */
974 if (!qtest_fault_resize_handshake(fault, newlen + SSL3_HM_HEADER_LENGTH))
975 return 0;
976
977 /* Fixup the handshake message header */
978 fault->handbuf[1] = (unsigned char)((newlen >> 16) & 0xff);
979 fault->handbuf[2] = (unsigned char)((newlen >> 8) & 0xff);
980 fault->handbuf[3] = (unsigned char)((newlen ) & 0xff);
981
982 return 1;
983 }
984
985 int qtest_fault_delete_extension(QTEST_FAULT *fault,
986 unsigned int exttype, unsigned char *ext,
987 size_t *extlen,
988 BUF_MEM *old_ext)
989 {
990 PACKET pkt, sub, subext;
991 WPACKET old_ext_wpkt;
992 unsigned int type;
993 const unsigned char *start, *end;
994 size_t newlen, w;
995 size_t msglen = fault->handbuflen;
996
997 if (!PACKET_buf_init(&pkt, ext, *extlen))
998 return 0;
999
1000 /* Extension block starts with 2 bytes for extension block length */
1001 if (!PACKET_as_length_prefixed_2(&pkt, &sub))
1002 return 0;
1003
1004 do {
1005 start = PACKET_data(&sub);
1006 if (!PACKET_get_net_2(&sub, &type)
1007 || !PACKET_get_length_prefixed_2(&sub, &subext))
1008 return 0;
1009 } while (type != exttype);
1010
1011 /* Found it */
1012 end = PACKET_data(&sub);
1013
1014 if (old_ext != NULL) {
1015 if (!WPACKET_init(&old_ext_wpkt, old_ext))
1016 return 0;
1017
1018 if (!WPACKET_memcpy(&old_ext_wpkt, PACKET_data(&subext),
1019 PACKET_remaining(&subext))
1020 || !WPACKET_get_total_written(&old_ext_wpkt, &w)) {
1021 WPACKET_cleanup(&old_ext_wpkt);
1022 return 0;
1023 }
1024
1025 WPACKET_finish(&old_ext_wpkt);
1026 old_ext->length = w;
1027 }
1028
1029 /*
1030 * If we're not the last extension we need to move the rest earlier. The
1031 * cast below is safe because we own the underlying buffer and we're no
1032 * longer making PACKET calls.
1033 */
1034 if (end < ext + *extlen)
1035 memmove((unsigned char *)start, end, end - start);
1036
1037 /*
1038 * Calculate new extensions payload length =
1039 * Original length
1040 * - 2 extension block length bytes
1041 * - length of removed extension
1042 */
1043 newlen = *extlen - 2 - (end - start);
1044
1045 /* Fixup the length bytes for the extension block */
1046 ext[0] = (unsigned char)((newlen >> 8) & 0xff);
1047 ext[1] = (unsigned char)((newlen ) & 0xff);
1048
1049 /*
1050 * Length of the whole extension block is the new payload length plus the
1051 * 2 bytes for the length
1052 */
1053 *extlen = newlen + 2;
1054
1055 /* We can now resize the message */
1056 if ((size_t)(end - start) + SSL3_HM_HEADER_LENGTH > msglen)
1057 return 0; /* Should not happen */
1058 msglen -= (end - start) + SSL3_HM_HEADER_LENGTH;
1059 if (!qtest_fault_resize_message(fault, msglen))
1060 return 0;
1061
1062 return 1;
1063 }
1064
1065 #define BIO_TYPE_CIPHER_PACKET_FILTER (0x80 | BIO_TYPE_FILTER)
1066
1067 static BIO_METHOD *pcipherbiometh = NULL;
1068
1069 # define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n)*(stride)))
1070
1071 static int pcipher_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride,
1072 size_t num_msg, uint64_t flags,
1073 size_t *num_processed)
1074 {
1075 QTEST_FAULT *fault;
1076 BIO *next = BIO_next(b);
1077 ossl_ssize_t ret = 0;
1078 size_t i = 0, tmpnump;
1079 QUIC_PKT_HDR hdr;
1080 PACKET pkt;
1081 unsigned char *tmpdata;
1082
1083 if (next == NULL)
1084 return 0;
1085
1086 fault = BIO_get_data(b);
1087 if (fault == NULL
1088 || (fault->pciphercb == NULL && fault->datagramcb == NULL))
1089 return BIO_sendmmsg(next, msg, stride, num_msg, flags, num_processed);
1090
1091 if (num_msg == 0) {
1092 *num_processed = 0;
1093 return 1;
1094 }
1095
1096 for (i = 0; i < num_msg; ++i) {
1097 fault->msg = BIO_MSG_N(msg, stride, i);
1098
1099 /* Take a copy of the data so that callbacks can modify it */
1100 tmpdata = OPENSSL_malloc(fault->msg.data_len + GROWTH_ALLOWANCE);
1101 if (tmpdata == NULL)
1102 return 0;
1103 memcpy(tmpdata, fault->msg.data, fault->msg.data_len);
1104 fault->msg.data = tmpdata;
1105 fault->msgalloc = fault->msg.data_len + GROWTH_ALLOWANCE;
1106
1107 if (fault->pciphercb != NULL) {
1108 if (!PACKET_buf_init(&pkt, fault->msg.data, fault->msg.data_len))
1109 return 0;
1110
1111 do {
1112 if (!ossl_quic_wire_decode_pkt_hdr(&pkt,
1113 /*
1114 * TODO(QUIC SERVER):
1115 * Needs to be set to the actual short header CID length
1116 * when testing the server implementation.
1117 */
1118 0,
1119 1,
1120 0, &hdr, NULL))
1121 goto out;
1122
1123 /*
1124 * hdr.data is const - but its our buffer so casting away the
1125 * const is safe
1126 */
1127 if (!fault->pciphercb(fault, &hdr, (unsigned char *)hdr.data,
1128 hdr.len, fault->pciphercbarg))
1129 goto out;
1130
1131 /*
1132 * At the moment modifications to hdr by the callback
1133 * are ignored. We might need to rewrite the QUIC header to
1134 * enable tests to change this. We also don't yet have a
1135 * mechanism for the callback to change the encrypted data
1136 * length. It's not clear if that's needed or not.
1137 */
1138 } while (PACKET_remaining(&pkt) > 0);
1139 }
1140
1141 if (fault->datagramcb != NULL
1142 && !fault->datagramcb(fault, &fault->msg, stride,
1143 fault->datagramcbarg))
1144 goto out;
1145
1146 if (!BIO_sendmmsg(next, &fault->msg, stride, 1, flags, &tmpnump)) {
1147 *num_processed = i;
1148 goto out;
1149 }
1150
1151 OPENSSL_free(fault->msg.data);
1152 fault->msg.data = NULL;
1153 fault->msgalloc = 0;
1154 }
1155
1156 *num_processed = i;
1157 out:
1158 ret = i > 0;
1159 OPENSSL_free(fault->msg.data);
1160 fault->msg.data = NULL;
1161 return ret;
1162 }
1163
1164 static long pcipher_ctrl(BIO *b, int cmd, long larg, void *parg)
1165 {
1166 BIO *next = BIO_next(b);
1167
1168 if (next == NULL)
1169 return -1;
1170
1171 return BIO_ctrl(next, cmd, larg, parg);
1172 }
1173
1174 BIO_METHOD *qtest_get_bio_method(void)
1175 {
1176 BIO_METHOD *tmp;
1177
1178 if (pcipherbiometh != NULL)
1179 return pcipherbiometh;
1180
1181 tmp = BIO_meth_new(BIO_TYPE_CIPHER_PACKET_FILTER, "Cipher Packet Filter");
1182
1183 if (!TEST_ptr(tmp))
1184 return NULL;
1185
1186 if (!TEST_true(BIO_meth_set_sendmmsg(tmp, pcipher_sendmmsg))
1187 || !TEST_true(BIO_meth_set_ctrl(tmp, pcipher_ctrl)))
1188 goto err;
1189
1190 pcipherbiometh = tmp;
1191 tmp = NULL;
1192 err:
1193 BIO_meth_free(tmp);
1194 return pcipherbiometh;
1195 }
1196
1197 int qtest_fault_set_packet_cipher_listener(QTEST_FAULT *fault,
1198 qtest_fault_on_packet_cipher_cb pciphercb,
1199 void *pciphercbarg)
1200 {
1201 fault->pciphercb = pciphercb;
1202 fault->pciphercbarg = pciphercbarg;
1203
1204 return 1;
1205 }
1206
1207 int qtest_fault_set_datagram_listener(QTEST_FAULT *fault,
1208 qtest_fault_on_datagram_cb datagramcb,
1209 void *datagramcbarg)
1210 {
1211 fault->datagramcb = datagramcb;
1212 fault->datagramcbarg = datagramcbarg;
1213
1214 return 1;
1215 }
1216
1217 /* To be called from a datagram_listener callback */
1218 int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen)
1219 {
1220 if (newlen > fault->msgalloc)
1221 return 0;
1222
1223 if (newlen > fault->msg.data_len)
1224 memset((unsigned char *)fault->msg.data + fault->msg.data_len, 0,
1225 newlen - fault->msg.data_len);
1226
1227 fault->msg.data_len = newlen;
1228
1229 return 1;
1230 }
1231
1232 int qtest_fault_set_bw_limit(QTEST_FAULT *fault,
1233 size_t ctos_bw, size_t stoc_bw,
1234 int noise_rate)
1235 {
1236 BIO *sbio = fault->noiseargs.sbio;
1237 BIO *cbio = fault->noiseargs.cbio;
1238
1239 if (!TEST_ptr(sbio) || !TEST_ptr(cbio))
1240 return 0;
1241 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_RATE, noise_rate, NULL), 1))
1242 return 0;
1243 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_RATE, noise_rate, NULL), 1))
1244 return 0;
1245 /* We set the bandwidth limit on the sending side */
1246 if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_SEND_BANDWIDTH,
1247 (long)ctos_bw, NULL), 1))
1248 return 0;
1249 if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_SEND_BANDWIDTH,
1250 (long)stoc_bw, NULL), 1))
1251 return 0;
1252 return 1;
1253 }
1254
1255
1256 int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src)
1257 {
1258 /*
1259 * Note it is assumed that the originally allocated data sizes for dst and
1260 * src are the same
1261 */
1262 memcpy(dst->data, src->data, src->data_len);
1263 dst->data_len = src->data_len;
1264 dst->flags = src->flags;
1265 if (dst->local != NULL) {
1266 if (src->local != NULL) {
1267 if (!TEST_true(BIO_ADDR_copy(dst->local, src->local)))
1268 return 0;
1269 } else {
1270 BIO_ADDR_clear(dst->local);
1271 }
1272 }
1273 if (!TEST_true(BIO_ADDR_copy(dst->peer, src->peer)))
1274 return 0;
1275
1276 return 1;
1277 }