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