]> git.ipfire.org Git - thirdparty/openssl.git/blob - test/helpers/quictestlib.c
Add a test quicserver utility
[thirdparty/openssl.git] / test / helpers / quictestlib.c
1 /*
2 * Copyright 2022 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 "quictestlib.h"
14 #include "ssltestlib.h"
15 #include "../testutil.h"
16 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
17 # include "../threadstest.h"
18 #endif
19 #include "internal/quic_wire_pkt.h"
20 #include "internal/quic_record_tx.h"
21 #include "internal/quic_error.h"
22 #include "internal/packet.h"
23
24 #define GROWTH_ALLOWANCE 1024
25
26 struct qtest_fault {
27 QUIC_TSERVER *qtserv;
28
29 /* Plain packet mutations */
30 /* Header for the plaintext packet */
31 QUIC_PKT_HDR pplainhdr;
32 /* iovec for the plaintext packet data buffer */
33 OSSL_QTX_IOVEC pplainio;
34 /* Allocated size of the plaintext packet data buffer */
35 size_t pplainbuf_alloc;
36 qtest_fault_on_packet_plain_cb pplaincb;
37 void *pplaincbarg;
38
39 /* Handshake message mutations */
40 /* Handshake message buffer */
41 unsigned char *handbuf;
42 /* Allocated size of the handshake message buffer */
43 size_t handbufalloc;
44 /* Actual length of the handshake message */
45 size_t handbuflen;
46 qtest_fault_on_handshake_cb handshakecb;
47 void *handshakecbarg;
48 qtest_fault_on_enc_ext_cb encextcb;
49 void *encextcbarg;
50
51 /* Cipher packet mutations */
52 qtest_fault_on_packet_cipher_cb pciphercb;
53 void *pciphercbarg;
54
55 /* Datagram mutations */
56 qtest_fault_on_datagram_cb datagramcb;
57 void *datagramcbarg;
58 /* The currently processed message */
59 BIO_MSG msg;
60 /* Allocated size of msg data buffer */
61 size_t msgalloc;
62 };
63
64 static void packet_plain_finish(void *arg);
65 static void handshake_finish(void *arg);
66
67 static BIO_METHOD *get_bio_method(void);
68
69 int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
70 char *certfile, char *keyfile,
71 int block, QUIC_TSERVER **qtserv, SSL **cssl,
72 QTEST_FAULT **fault)
73 {
74 /* ALPN value as recognised by QUIC_TSERVER */
75 unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
76 QUIC_TSERVER_ARGS tserver_args = {0};
77 BIO *cbio = NULL, *sbio = NULL, *fisbio = NULL;
78 BIO_ADDR *peeraddr = NULL;
79 struct in_addr ina = {0};
80
81 *qtserv = NULL;
82 if (fault != NULL)
83 *fault = NULL;
84 *cssl = SSL_new(clientctx);
85 if (!TEST_ptr(*cssl))
86 return 0;
87
88 /* SSL_set_alpn_protos returns 0 for success! */
89 if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn))))
90 goto err;
91
92 if (!TEST_ptr(peeraddr = BIO_ADDR_new()))
93 goto err;
94
95 if (block) {
96 #if !defined(OPENSSL_NO_POSIX_IO)
97 int cfd, sfd;
98
99 /*
100 * For blocking mode we need to create actual sockets rather than doing
101 * everything in memory
102 */
103 if (!TEST_true(create_test_sockets(&cfd, &sfd, SOCK_DGRAM, peeraddr)))
104 goto err;
105 cbio = BIO_new_dgram(cfd, 1);
106 if (!TEST_ptr(cbio)) {
107 close(cfd);
108 close(sfd);
109 goto err;
110 }
111 sbio = BIO_new_dgram(sfd, 1);
112 if (!TEST_ptr(sbio)) {
113 close(sfd);
114 goto err;
115 }
116 #else
117 goto err;
118 #endif
119 } else {
120 if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0)))
121 goto err;
122
123 if (!TEST_true(BIO_dgram_set_caps(cbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))
124 || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)))
125 goto err;
126
127 /* Dummy server address */
128 if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina),
129 htons(0))))
130 goto err;
131 }
132
133 SSL_set_bio(*cssl, cbio, cbio);
134
135 if (!TEST_true(SSL_set_blocking_mode(*cssl, block)))
136 goto err;
137
138 if (!TEST_true(SSL_set_initial_peer_addr(*cssl, peeraddr)))
139 goto err;
140
141 if (fault != NULL) {
142 *fault = OPENSSL_zalloc(sizeof(**fault));
143 if (*fault == NULL)
144 goto err;
145 }
146
147 fisbio = BIO_new(get_bio_method());
148 if (!TEST_ptr(fisbio))
149 goto err;
150
151 BIO_set_data(fisbio, fault == NULL ? NULL : *fault);
152
153 if (!TEST_ptr(BIO_push(fisbio, sbio)))
154 goto err;
155
156 tserver_args.libctx = libctx;
157 tserver_args.net_rbio = sbio;
158 tserver_args.net_wbio = fisbio;
159 tserver_args.alpn = NULL;
160
161 if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile,
162 keyfile)))
163 goto err;
164
165 /* Ownership of fisbio and sbio is now held by *qtserv */
166 sbio = NULL;
167 fisbio = NULL;
168
169 if (fault != NULL)
170 (*fault)->qtserv = *qtserv;
171
172 BIO_ADDR_free(peeraddr);
173
174 return 1;
175 err:
176 BIO_ADDR_free(peeraddr);
177 BIO_free(cbio);
178 BIO_free(fisbio);
179 BIO_free(sbio);
180 SSL_free(*cssl);
181 *cssl = NULL;
182 ossl_quic_tserver_free(*qtserv);
183 if (fault != NULL)
184 OPENSSL_free(*fault);
185
186 return 0;
187 }
188
189 int qtest_supports_blocking(void)
190 {
191 #if !defined(OPENSSL_NO_POSIX_IO) && defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
192 return 1;
193 #else
194 return 0;
195 #endif
196 }
197
198 #define MAXLOOPS 1000
199
200 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
201 static int globserverret = 0;
202 static QUIC_TSERVER *globtserv;
203 static const thread_t thread_zero;
204
205 static void run_server_thread(void)
206 {
207 /*
208 * This will operate in a busy loop because the server does not block,
209 * but should be acceptable because it is local and we expect this to be
210 * fast
211 */
212 globserverret = qtest_create_quic_connection(globtserv, NULL);
213 }
214 #endif
215
216 int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl)
217 {
218 int retc = -1, rets = 0, err, abortctr = 0, ret = 0;
219 int clienterr = 0, servererr = 0;
220 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
221 /*
222 * Pointless initialisation to avoid bogus compiler warnings about using
223 * t uninitialised
224 */
225 thread_t t = thread_zero;
226 #endif
227
228 if (!TEST_ptr(qtserv)) {
229 goto err;
230 } else if (clientssl == NULL) {
231 retc = 1;
232 } else if (SSL_get_blocking_mode(clientssl) > 0) {
233 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
234 /*
235 * clientssl is blocking. We will need a thread to complete the
236 * connection
237 */
238 globtserv = qtserv;
239 if (!TEST_true(run_thread(&t, run_server_thread)))
240 goto err;
241
242 qtserv = NULL;
243 rets = 1;
244 #else
245 TEST_error("No thread support in this build");
246 goto err;
247 #endif
248 }
249
250 do {
251 err = SSL_ERROR_WANT_WRITE;
252 while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
253 retc = SSL_connect(clientssl);
254 if (retc <= 0)
255 err = SSL_get_error(clientssl, retc);
256 }
257
258 if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
259 TEST_info("SSL_connect() failed %d, %d", retc, err);
260 TEST_openssl_errors();
261 clienterr = 1;
262 }
263
264 /*
265 * We're cheating. We don't take any notice of SSL_get_tick_timeout()
266 * and tick every time around the loop anyway. This is inefficient. We
267 * can get away with it in test code because we control both ends of
268 * the communications and don't expect network delays. This shouldn't
269 * be done in a real application.
270 */
271 if (!clienterr && retc <= 0)
272 SSL_handle_events(clientssl);
273 if (!servererr && rets <= 0) {
274 ossl_quic_tserver_tick(qtserv);
275 servererr = ossl_quic_tserver_is_term_any(qtserv);
276 if (!servererr)
277 rets = ossl_quic_tserver_is_handshake_confirmed(qtserv);
278 }
279
280 if (clienterr && servererr)
281 goto err;
282
283 if (clientssl != NULL && ++abortctr == MAXLOOPS) {
284 TEST_info("No progress made");
285 goto err;
286 }
287 } while ((retc <= 0 && !clienterr) || (rets <= 0 && !servererr));
288
289 if (qtserv == NULL && rets > 0) {
290 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
291 if (!TEST_true(wait_for_thread(t)) || !TEST_true(globserverret))
292 goto err;
293 #else
294 TEST_error("Should not happen");
295 goto err;
296 #endif
297 }
298
299 if (!clienterr && !servererr)
300 ret = 1;
301 err:
302 return ret;
303 }
304
305 int qtest_shutdown(QUIC_TSERVER *qtserv, SSL *clientssl)
306 {
307 /* Busy loop in non-blocking mode. It should be quick because its local */
308 while (SSL_shutdown(clientssl) != 1)
309 ossl_quic_tserver_tick(qtserv);
310
311 return 1;
312 }
313
314 int qtest_check_server_transport_err(QUIC_TSERVER *qtserv, uint64_t code)
315 {
316 const QUIC_TERMINATE_CAUSE *cause;
317
318 ossl_quic_tserver_tick(qtserv);
319
320 /*
321 * Check that the server has closed with the specified code from the client
322 */
323 if (!TEST_true(ossl_quic_tserver_is_term_any(qtserv)))
324 return 0;
325
326 cause = ossl_quic_tserver_get_terminate_cause(qtserv);
327 if (!TEST_ptr(cause)
328 || !TEST_true(cause->remote)
329 || !TEST_uint64_t_eq(cause->error_code, code))
330 return 0;
331
332 return 1;
333 }
334
335 int qtest_check_server_protocol_err(QUIC_TSERVER *qtserv)
336 {
337 return qtest_check_server_transport_err(qtserv, QUIC_ERR_PROTOCOL_VIOLATION);
338 }
339
340 void qtest_fault_free(QTEST_FAULT *fault)
341 {
342 if (fault == NULL)
343 return;
344
345 packet_plain_finish(fault);
346 handshake_finish(fault);
347
348 OPENSSL_free(fault);
349 }
350
351 static int packet_plain_mutate(const QUIC_PKT_HDR *hdrin,
352 const OSSL_QTX_IOVEC *iovecin, size_t numin,
353 QUIC_PKT_HDR **hdrout,
354 const OSSL_QTX_IOVEC **iovecout,
355 size_t *numout,
356 void *arg)
357 {
358 QTEST_FAULT *fault = arg;
359 size_t i, bufsz = 0;
360 unsigned char *cur;
361
362 /* Coalesce our data into a single buffer */
363
364 /* First calculate required buffer size */
365 for (i = 0; i < numin; i++)
366 bufsz += iovecin[i].buf_len;
367
368 fault->pplainio.buf_len = bufsz;
369
370 /* Add an allowance for possible growth */
371 bufsz += GROWTH_ALLOWANCE;
372
373 fault->pplainio.buf = cur = OPENSSL_malloc(bufsz);
374 if (cur == NULL) {
375 fault->pplainio.buf_len = 0;
376 return 0;
377 }
378
379 fault->pplainbuf_alloc = bufsz;
380
381 /* Copy in the data from the input buffers */
382 for (i = 0; i < numin; i++) {
383 memcpy(cur, iovecin[i].buf, iovecin[i].buf_len);
384 cur += iovecin[i].buf_len;
385 }
386
387 fault->pplainhdr = *hdrin;
388
389 /* Cast below is safe because we allocated the buffer */
390 if (fault->pplaincb != NULL
391 && !fault->pplaincb(fault, &fault->pplainhdr,
392 (unsigned char *)fault->pplainio.buf,
393 fault->pplainio.buf_len, fault->pplaincbarg))
394 return 0;
395
396 *hdrout = &fault->pplainhdr;
397 *iovecout = &fault->pplainio;
398 *numout = 1;
399
400 return 1;
401 }
402
403 static void packet_plain_finish(void *arg)
404 {
405 QTEST_FAULT *fault = arg;
406
407 /* Cast below is safe because we allocated the buffer */
408 OPENSSL_free((unsigned char *)fault->pplainio.buf);
409 fault->pplainio.buf_len = 0;
410 fault->pplainbuf_alloc = 0;
411 fault->pplainio.buf = NULL;
412 }
413
414 int qtest_fault_set_packet_plain_listener(QTEST_FAULT *fault,
415 qtest_fault_on_packet_plain_cb pplaincb,
416 void *pplaincbarg)
417 {
418 fault->pplaincb = pplaincb;
419 fault->pplaincbarg = pplaincbarg;
420
421 return ossl_quic_tserver_set_plain_packet_mutator(fault->qtserv,
422 packet_plain_mutate,
423 packet_plain_finish,
424 fault);
425 }
426
427 /* To be called from a packet_plain_listener callback */
428 int qtest_fault_resize_plain_packet(QTEST_FAULT *fault, size_t newlen)
429 {
430 unsigned char *buf;
431 size_t oldlen = fault->pplainio.buf_len;
432
433 /*
434 * Alloc'd size should always be non-zero, so if this fails we've been
435 * incorrectly called
436 */
437 if (fault->pplainbuf_alloc == 0)
438 return 0;
439
440 if (newlen > fault->pplainbuf_alloc) {
441 /* This exceeds our growth allowance. Fail */
442 return 0;
443 }
444
445 /* Cast below is safe because we allocated the buffer */
446 buf = (unsigned char *)fault->pplainio.buf;
447
448 if (newlen > oldlen) {
449 /* Extend packet with 0 bytes */
450 memset(buf + oldlen, 0, newlen - oldlen);
451 } /* else we're truncating or staying the same */
452
453 fault->pplainio.buf_len = newlen;
454 fault->pplainhdr.len = newlen;
455
456 return 1;
457 }
458
459 /*
460 * Prepend frame data into a packet. To be called from a packet_plain_listener
461 * callback
462 */
463 int qtest_fault_prepend_frame(QTEST_FAULT *fault, unsigned char *frame,
464 size_t frame_len)
465 {
466 unsigned char *buf;
467 size_t old_len;
468
469 /*
470 * Alloc'd size should always be non-zero, so if this fails we've been
471 * incorrectly called
472 */
473 if (fault->pplainbuf_alloc == 0)
474 return 0;
475
476 /* Cast below is safe because we allocated the buffer */
477 buf = (unsigned char *)fault->pplainio.buf;
478 old_len = fault->pplainio.buf_len;
479
480 /* Extend the size of the packet by the size of the new frame */
481 if (!TEST_true(qtest_fault_resize_plain_packet(fault,
482 old_len + frame_len)))
483 return 0;
484
485 memmove(buf + frame_len, buf, old_len);
486 memcpy(buf, frame, frame_len);
487
488 return 1;
489 }
490
491 static int handshake_mutate(const unsigned char *msgin, size_t msginlen,
492 unsigned char **msgout, size_t *msgoutlen,
493 void *arg)
494 {
495 QTEST_FAULT *fault = arg;
496 unsigned char *buf;
497 unsigned long payloadlen;
498 unsigned int msgtype;
499 PACKET pkt;
500
501 buf = OPENSSL_malloc(msginlen + GROWTH_ALLOWANCE);
502 if (buf == NULL)
503 return 0;
504
505 fault->handbuf = buf;
506 fault->handbuflen = msginlen;
507 fault->handbufalloc = msginlen + GROWTH_ALLOWANCE;
508 memcpy(buf, msgin, msginlen);
509
510 if (!PACKET_buf_init(&pkt, buf, msginlen)
511 || !PACKET_get_1(&pkt, &msgtype)
512 || !PACKET_get_net_3(&pkt, &payloadlen)
513 || PACKET_remaining(&pkt) != payloadlen)
514 return 0;
515
516 /* Parse specific message types */
517 switch (msgtype) {
518 case SSL3_MT_ENCRYPTED_EXTENSIONS:
519 {
520 QTEST_ENCRYPTED_EXTENSIONS ee;
521
522 if (fault->encextcb == NULL)
523 break;
524
525 /*
526 * The EncryptedExtensions message is very simple. It just has an
527 * extensions block in it and nothing else.
528 */
529 ee.extensions = (unsigned char *)PACKET_data(&pkt);
530 ee.extensionslen = payloadlen;
531 if (!fault->encextcb(fault, &ee, payloadlen, fault->encextcbarg))
532 return 0;
533 }
534
535 default:
536 /* No specific handlers for these message types yet */
537 break;
538 }
539
540 if (fault->handshakecb != NULL
541 && !fault->handshakecb(fault, buf, fault->handbuflen,
542 fault->handshakecbarg))
543 return 0;
544
545 *msgout = buf;
546 *msgoutlen = fault->handbuflen;
547
548 return 1;
549 }
550
551 static void handshake_finish(void *arg)
552 {
553 QTEST_FAULT *fault = arg;
554
555 OPENSSL_free(fault->handbuf);
556 fault->handbuf = NULL;
557 }
558
559 int qtest_fault_set_handshake_listener(QTEST_FAULT *fault,
560 qtest_fault_on_handshake_cb handshakecb,
561 void *handshakecbarg)
562 {
563 fault->handshakecb = handshakecb;
564 fault->handshakecbarg = handshakecbarg;
565
566 return ossl_quic_tserver_set_handshake_mutator(fault->qtserv,
567 handshake_mutate,
568 handshake_finish,
569 fault);
570 }
571
572 int qtest_fault_set_hand_enc_ext_listener(QTEST_FAULT *fault,
573 qtest_fault_on_enc_ext_cb encextcb,
574 void *encextcbarg)
575 {
576 fault->encextcb = encextcb;
577 fault->encextcbarg = encextcbarg;
578
579 return ossl_quic_tserver_set_handshake_mutator(fault->qtserv,
580 handshake_mutate,
581 handshake_finish,
582 fault);
583 }
584
585 /* To be called from a handshake_listener callback */
586 int qtest_fault_resize_handshake(QTEST_FAULT *fault, size_t newlen)
587 {
588 unsigned char *buf;
589 size_t oldlen = fault->handbuflen;
590
591 /*
592 * Alloc'd size should always be non-zero, so if this fails we've been
593 * incorrectly called
594 */
595 if (fault->handbufalloc == 0)
596 return 0;
597
598 if (newlen > fault->handbufalloc) {
599 /* This exceeds our growth allowance. Fail */
600 return 0;
601 }
602
603 buf = (unsigned char *)fault->handbuf;
604
605 if (newlen > oldlen) {
606 /* Extend packet with 0 bytes */
607 memset(buf + oldlen, 0, newlen - oldlen);
608 } /* else we're truncating or staying the same */
609
610 fault->handbuflen = newlen;
611 return 1;
612 }
613
614 /* To be called from message specific listener callbacks */
615 int qtest_fault_resize_message(QTEST_FAULT *fault, size_t newlen)
616 {
617 /* First resize the underlying message */
618 if (!qtest_fault_resize_handshake(fault, newlen + SSL3_HM_HEADER_LENGTH))
619 return 0;
620
621 /* Fixup the handshake message header */
622 fault->handbuf[1] = (unsigned char)((newlen >> 16) & 0xff);
623 fault->handbuf[2] = (unsigned char)((newlen >> 8) & 0xff);
624 fault->handbuf[3] = (unsigned char)((newlen ) & 0xff);
625
626 return 1;
627 }
628
629 int qtest_fault_delete_extension(QTEST_FAULT *fault,
630 unsigned int exttype, unsigned char *ext,
631 size_t *extlen)
632 {
633 PACKET pkt, sub, subext;
634 unsigned int type;
635 const unsigned char *start, *end;
636 size_t newlen;
637 size_t msglen = fault->handbuflen;
638
639 if (!PACKET_buf_init(&pkt, ext, *extlen))
640 return 0;
641
642 /* Extension block starts with 2 bytes for extension block length */
643 if (!PACKET_as_length_prefixed_2(&pkt, &sub))
644 return 0;
645
646 do {
647 start = PACKET_data(&sub);
648 if (!PACKET_get_net_2(&sub, &type)
649 || !PACKET_get_length_prefixed_2(&sub, &subext))
650 return 0;
651 } while (type != exttype);
652
653 /* Found it */
654 end = PACKET_data(&sub);
655
656 /*
657 * If we're not the last extension we need to move the rest earlier. The
658 * cast below is safe because we own the underlying buffer and we're no
659 * longer making PACKET calls.
660 */
661 if (end < ext + *extlen)
662 memmove((unsigned char *)start, end, end - start);
663
664 /*
665 * Calculate new extensions payload length =
666 * Original length
667 * - 2 extension block length bytes
668 * - length of removed extension
669 */
670 newlen = *extlen - 2 - (end - start);
671
672 /* Fixup the length bytes for the extension block */
673 ext[0] = (unsigned char)((newlen >> 8) & 0xff);
674 ext[1] = (unsigned char)((newlen ) & 0xff);
675
676 /*
677 * Length of the whole extension block is the new payload length plus the
678 * 2 bytes for the length
679 */
680 *extlen = newlen + 2;
681
682 /* We can now resize the message */
683 if ((size_t)(end - start) + SSL3_HM_HEADER_LENGTH > msglen)
684 return 0; /* Should not happen */
685 msglen -= (end - start) + SSL3_HM_HEADER_LENGTH;
686 if (!qtest_fault_resize_message(fault, msglen))
687 return 0;
688
689 return 1;
690 }
691
692 #define BIO_TYPE_CIPHER_PACKET_FILTER (0x80 | BIO_TYPE_FILTER)
693
694 static BIO_METHOD *pcipherbiometh = NULL;
695
696 # define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n)*(stride)))
697
698 static int pcipher_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride,
699 size_t num_msg, uint64_t flags,
700 size_t *num_processed)
701 {
702 QTEST_FAULT *fault;
703 BIO *next = BIO_next(b);
704 ossl_ssize_t ret = 0;
705 size_t i = 0, tmpnump;
706 QUIC_PKT_HDR hdr;
707 PACKET pkt;
708 unsigned char *tmpdata;
709
710 if (next == NULL)
711 return 0;
712
713 fault = BIO_get_data(b);
714 if (fault == NULL
715 || (fault->pciphercb == NULL && fault->datagramcb == NULL))
716 return BIO_sendmmsg(next, msg, stride, num_msg, flags, num_processed);
717
718 if (num_msg == 0) {
719 *num_processed = 0;
720 return 1;
721 }
722
723 for (i = 0; i < num_msg; ++i) {
724 fault->msg = BIO_MSG_N(msg, stride, i);
725
726 /* Take a copy of the data so that callbacks can modify it */
727 tmpdata = OPENSSL_malloc(fault->msg.data_len + GROWTH_ALLOWANCE);
728 if (tmpdata == NULL)
729 return 0;
730 memcpy(tmpdata, fault->msg.data, fault->msg.data_len);
731 fault->msg.data = tmpdata;
732 fault->msgalloc = fault->msg.data_len + GROWTH_ALLOWANCE;
733
734 if (fault->pciphercb != NULL) {
735 if (!PACKET_buf_init(&pkt, fault->msg.data, fault->msg.data_len))
736 return 0;
737
738 do {
739 if (!ossl_quic_wire_decode_pkt_hdr(&pkt,
740 0 /* TODO(QUIC): Not sure how this should be set*/, 1,
741 0, &hdr, NULL))
742 goto out;
743
744 /*
745 * hdr.data is const - but its our buffer so casting away the
746 * const is safe
747 */
748 if (!fault->pciphercb(fault, &hdr, (unsigned char *)hdr.data,
749 hdr.len, fault->pciphercbarg))
750 goto out;
751
752 /*
753 * TODO(QUIC): At the moment modifications to hdr by the callback
754 * are ignored. We might need to rewrite the QUIC header to
755 * enable tests to change this. We also don't yet have a
756 * mechanism for the callback to change the encrypted data
757 * length. It's not clear if that's needed or not.
758 */
759 } while (PACKET_remaining(&pkt) > 0);
760 }
761
762 if (fault->datagramcb != NULL
763 && !fault->datagramcb(fault, &fault->msg, stride,
764 fault->datagramcbarg))
765 goto out;
766
767 if (!BIO_sendmmsg(next, &fault->msg, stride, 1, flags, &tmpnump)) {
768 *num_processed = i;
769 goto out;
770 }
771
772 OPENSSL_free(fault->msg.data);
773 fault->msg.data = NULL;
774 fault->msgalloc = 0;
775 }
776
777 *num_processed = i;
778 out:
779 ret = i > 0;
780 OPENSSL_free(fault->msg.data);
781 fault->msg.data = NULL;
782 return ret;
783 }
784
785 static long pcipher_ctrl(BIO *b, int cmd, long larg, void *parg)
786 {
787 BIO *next = BIO_next(b);
788
789 if (next == NULL)
790 return -1;
791
792 return BIO_ctrl(next, cmd, larg, parg);
793 }
794
795 static BIO_METHOD *get_bio_method(void)
796 {
797 BIO_METHOD *tmp;
798
799 if (pcipherbiometh != NULL)
800 return pcipherbiometh;
801
802 tmp = BIO_meth_new(BIO_TYPE_CIPHER_PACKET_FILTER, "Cipher Packet Filter");
803
804 if (!TEST_ptr(tmp))
805 return NULL;
806
807 if (!TEST_true(BIO_meth_set_sendmmsg(tmp, pcipher_sendmmsg))
808 || !TEST_true(BIO_meth_set_ctrl(tmp, pcipher_ctrl)))
809 goto err;
810
811 pcipherbiometh = tmp;
812 tmp = NULL;
813 err:
814 BIO_meth_free(tmp);
815 return pcipherbiometh;
816 }
817
818 int qtest_fault_set_packet_cipher_listener(QTEST_FAULT *fault,
819 qtest_fault_on_packet_cipher_cb pciphercb,
820 void *pciphercbarg)
821 {
822 fault->pciphercb = pciphercb;
823 fault->pciphercbarg = pciphercbarg;
824
825 return 1;
826 }
827
828 int qtest_fault_set_datagram_listener(QTEST_FAULT *fault,
829 qtest_fault_on_datagram_cb datagramcb,
830 void *datagramcbarg)
831 {
832 fault->datagramcb = datagramcb;
833 fault->datagramcbarg = datagramcbarg;
834
835 return 1;
836 }
837
838 /* To be called from a datagram_listener callback */
839 int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen)
840 {
841 if (newlen > fault->msgalloc)
842 return 0;
843
844 if (newlen > fault->msg.data_len)
845 memset((unsigned char *)fault->msg.data + fault->msg.data_len, 0,
846 newlen - fault->msg.data_len);
847
848 fault->msg.data_len = newlen;
849
850 return 1;
851 }