2 * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
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
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"
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"
27 #define GROWTH_ALLOWANCE 1024
29 struct noise_args_data_st
{
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
;
49 /* Handshake message mutations */
50 /* Handshake message buffer */
51 unsigned char *handbuf
;
52 /* Allocated size of the handshake message buffer */
54 /* Actual length of the handshake message */
56 qtest_fault_on_handshake_cb handshakecb
;
58 qtest_fault_on_enc_ext_cb encextcb
;
61 /* Cipher packet mutations */
62 qtest_fault_on_packet_cipher_cb pciphercb
;
65 /* Datagram mutations */
66 qtest_fault_on_datagram_cb datagramcb
;
68 /* The currently processed message */
70 /* Allocated size of msg data buffer */
72 struct noise_args_data_st noiseargs
;
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);
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
;
85 static OSSL_TIME
fake_now_cb(void *arg
)
87 return qtest_get_time();
90 static void noise_msg_callback(int write_p
, int version
, int content_type
,
91 const void *buf
, size_t len
, SSL
*ssl
,
94 struct noise_args_data_st
*noiseargs
= (struct noise_args_data_st
*)arg
;
96 if (content_type
== SSL3_RT_QUIC_FRAME_FULL
) {
100 if (!PACKET_buf_init(&pkt
, buf
, len
))
103 if (!ossl_quic_wire_peek_frame_header(&pkt
, &frame_type
, NULL
))
106 if (frame_type
== OSSL_QUIC_FRAME_TYPE_PING
) {
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.
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
);
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
);
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
)
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};
140 *cssl
= SSL_new(clientctx
);
141 if (!TEST_ptr(*cssl
))
146 *fault
= OPENSSL_zalloc(sizeof(**fault
));
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
))
157 SSL_set_msg_callback(*cssl
, SSL_trace
);
158 SSL_set_msg_callback_arg(*cssl
, tmpbio
);
161 if (tracebio
!= NULL
)
164 /* SSL_set_alpn_protos returns 0 for success! */
165 if (!TEST_false(SSL_set_alpn_protos(*cssl
, alpn
, sizeof(alpn
))))
168 if (!TEST_ptr(peeraddr
= BIO_ADDR_new()))
171 if ((flags
& QTEST_FLAG_BLOCK
) != 0) {
172 #if !defined(OPENSSL_NO_POSIX_IO)
176 * For blocking mode we need to create actual sockets rather than doing
177 * everything in memory
179 if (!TEST_true(create_test_sockets(&cfd
, &sfd
, SOCK_DGRAM
, peeraddr
)))
181 cbio
= BIO_new_dgram(cfd
, 1);
182 if (!TEST_ptr(cbio
)) {
187 sbio
= BIO_new_dgram(sfd
, 1);
188 if (!TEST_ptr(sbio
)) {
196 if (!TEST_true(BIO_new_bio_dgram_pair(&cbio
, 0, &sbio
, 0)))
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
)))
203 /* Dummy server address */
204 if (!TEST_true(BIO_ADDR_rawmake(peeraddr
, AF_INET
, &ina
, sizeof(ina
),
209 if ((flags
& QTEST_FLAG_PACKET_SPLIT
) != 0) {
210 BIO
*pktsplitbio
= BIO_new(bio_f_pkt_split_dgram_filter());
212 if (!TEST_ptr(pktsplitbio
))
214 cbio
= BIO_push(pktsplitbio
, cbio
);
216 pktsplitbio
= BIO_new(bio_f_pkt_split_dgram_filter());
217 if (!TEST_ptr(pktsplitbio
))
219 sbio
= BIO_push(pktsplitbio
, sbio
);
222 if ((flags
& QTEST_FLAG_NOISE
) != 0) {
224 struct bio_noise_now_cb_st now_cb
= { fake_now_cb
, NULL
};
227 * It is an error to not have a QTEST_FAULT object when introducing noise
229 if (!TEST_ptr(fault
))
232 noisebio
= BIO_new(bio_f_noisy_dgram_filter());
234 if (!TEST_ptr(noisebio
))
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
,
243 noisebio
= BIO_new(bio_f_noisy_dgram_filter());
245 if (!TEST_ptr(noisebio
))
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
,
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
260 (void)BIO_ctrl(sbio
, BIO_CTRL_NOISE_BACK_OFF
, 0, NULL
);
262 (*fault
)->noiseargs
.cbio
= cbio
;
263 (*fault
)->noiseargs
.sbio
= sbio
;
264 (*fault
)->noiseargs
.tracebio
= tmpbio
;
265 (*fault
)->noiseargs
.flags
= flags
;
267 SSL_set_msg_callback(*cssl
, noise_msg_callback
);
268 SSL_set_msg_callback_arg(*cssl
, &(*fault
)->noiseargs
);
271 SSL_set_bio(*cssl
, cbio
, cbio
);
273 if (!TEST_true(SSL_set_blocking_mode(*cssl
,
274 (flags
& QTEST_FLAG_BLOCK
) != 0 ? 1 : 0)))
277 if (!TEST_true(SSL_set1_initial_peer_addr(*cssl
, peeraddr
)))
280 fisbio
= BIO_new(qtest_get_bio_method());
281 if (!TEST_ptr(fisbio
))
284 BIO_set_data(fisbio
, fault
== NULL
? NULL
: *fault
);
286 if (!BIO_up_ref(sbio
))
288 if (!TEST_ptr(BIO_push(fisbio
, sbio
))) {
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
)))
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
)
305 if ((flags
& QTEST_FLAG_FAKE_TIME
) != 0) {
308 tserver_args
.now_cb
= fake_now_cb
;
309 (void)ossl_quic_conn_set_override_now_cb(*cssl
, fake_now_cb
, NULL
);
314 if (!TEST_ptr(*qtserv
= ossl_quic_tserver_new(&tserver_args
, certfile
,
318 /* Ownership of fisbio and sbio is now held by *qtserv */
322 if ((flags
& QTEST_FLAG_NOISE
) != 0)
323 ossl_quic_tserver_set_msg_callback(*qtserv
, noise_msg_callback
,
324 &(*fault
)->noiseargs
);
327 (*fault
)->qtserv
= *qtserv
;
329 BIO_ADDR_free(peeraddr
);
333 SSL_CTX_free(tserver_args
.ctx
);
334 BIO_ADDR_free(peeraddr
);
336 BIO_free_all(fisbio
);
340 ossl_quic_tserver_free(*qtserv
);
342 OPENSSL_free(*fault
);
344 if (tracebio
!= NULL
)
350 void qtest_add_time(uint64_t millis
)
352 if (!CRYPTO_THREAD_write_lock(fake_now_lock
))
354 fake_now
= ossl_time_add(fake_now
, ossl_ms2time(millis
));
355 CRYPTO_THREAD_unlock(fake_now_lock
);
358 static OSSL_TIME
qtest_get_time(void)
362 if (!CRYPTO_THREAD_read_lock(fake_now_lock
))
363 return ossl_time_zero();
365 CRYPTO_THREAD_unlock(fake_now_lock
);
369 static void qtest_reset_time(void)
371 if (!CRYPTO_THREAD_write_lock(fake_now_lock
))
373 fake_now
= ossl_time_zero();
374 CRYPTO_THREAD_unlock(fake_now_lock
);
375 /* zero time can have a special meaning, bump it */
379 void qtest_start_stopwatch(void)
381 start_time
= qtest_get_time();
384 uint64_t qtest_get_stopwatch_time(void)
386 return ossl_time2ms(ossl_time_subtract(qtest_get_time(), start_time
));
389 QTEST_FAULT
*qtest_create_injector(QUIC_TSERVER
*ts
)
393 f
= OPENSSL_zalloc(sizeof(*f
));
402 int qtest_supports_blocking(void)
404 #if !defined(OPENSSL_NO_POSIX_IO) && defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
411 #define MAXLOOPS 1000
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
;
419 static void run_server_thread(void)
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
426 globserverret
= qtest_create_quic_connection(globtserv
, NULL
);
430 int qtest_wait_for_timeout(SSL
*s
, QUIC_TSERVER
*qtserv
)
433 OSSL_TIME ctimeout
, stimeout
, mintimeout
, now
;
436 /* We don't need to wait in blocking mode */
437 if (s
== NULL
|| SSL_get_blocking_mode(s
))
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)
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.
452 if (!SSL_get_event_timeout(s
, &tv
, &cinf
))
456 now
= qtest_get_time();
458 now
= ossl_time_now();
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
))
467 qtest_add_time(ossl_time2ms(mintimeout
));
469 OSSL_sleep(ossl_time2ms(mintimeout
));
474 int qtest_create_quic_connection_ex(QUIC_TSERVER
*qtserv
, SSL
*clientssl
,
477 int retc
= -1, rets
= 0, abortctr
= 0, ret
= 0;
478 int clienterr
= 0, servererr
= 0;
479 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
481 * Pointless initialisation to avoid bogus compiler warnings about using
484 thread_t t
= thread_zero
;
486 if (clientssl
!= NULL
)
487 abortserverthread
= 0;
490 if (!TEST_ptr(qtserv
)) {
492 } else if (clientssl
== NULL
) {
494 } else if (SSL_get_blocking_mode(clientssl
) > 0) {
495 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
497 * clientssl is blocking. We will need a thread to complete the
501 if (!TEST_true(run_thread(&t
, run_server_thread
)))
507 TEST_error("No thread support in this build");
513 if (!clienterr
&& retc
<= 0) {
516 retc
= SSL_connect(clientssl
);
518 err
= SSL_get_error(clientssl
, retc
);
520 if (err
== wanterr
) {
522 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
523 if (qtserv
== NULL
&& rets
> 0)
524 tsan_store(&abortserverthread
, 1);
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();
540 if (clientssl
!= NULL
)
541 SSL_handle_events(clientssl
);
543 ossl_quic_tserver_tick(qtserv
);
545 if (!servererr
&& rets
<= 0) {
546 servererr
= ossl_quic_tserver_is_term_any(qtserv
);
548 rets
= ossl_quic_tserver_is_handshake_confirmed(qtserv
);
551 if (clienterr
&& servererr
)
554 if (clientssl
!= NULL
&& ++abortctr
== MAXLOOPS
) {
555 TEST_info("No progress made");
559 if ((retc
<= 0 && !clienterr
) || (rets
<= 0 && !servererr
)) {
560 if (!qtest_wait_for_timeout(clientssl
, qtserv
))
563 } while ((retc
<= 0 && !clienterr
)
564 || (rets
<= 0 && !servererr
565 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
566 && !tsan_load(&abortserverthread
)
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
))
575 TEST_error("Should not happen");
580 if (!clienterr
&& !servererr
)
586 int qtest_create_quic_connection(QUIC_TSERVER
*qtserv
, SSL
*clientssl
)
588 return qtest_create_quic_connection_ex(qtserv
, clientssl
, SSL_ERROR_NONE
);
591 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
592 static TSAN_QUALIFIER
int shutdowndone
;
594 static void run_server_shutdown_thread(void)
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
602 ossl_quic_tserver_tick(globtserv
);
603 } while(!tsan_load(&shutdowndone
));
607 int qtest_shutdown(QUIC_TSERVER
*qtserv
, SSL
*clientssl
)
611 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
613 * Pointless initialisation to avoid bogus compiler warnings about using
616 thread_t t
= thread_zero
;
619 if (SSL_get_blocking_mode(clientssl
) > 0) {
620 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
622 * clientssl is blocking. We will need a thread to complete the
627 if (!TEST_true(run_thread(&t
, run_server_shutdown_thread
)))
632 TEST_error("No thread support in this build");
637 /* Busy loop in non-blocking mode. It should be quick because its local */
639 int rc
= SSL_shutdown(clientssl
);
650 ossl_quic_tserver_tick(qtserv
);
653 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
654 tsan_store(&shutdowndone
, 1);
656 if (!TEST_true(wait_for_thread(t
)))
664 int qtest_check_server_transport_err(QUIC_TSERVER
*qtserv
, uint64_t code
)
666 const QUIC_TERMINATE_CAUSE
*cause
;
668 ossl_quic_tserver_tick(qtserv
);
671 * Check that the server has closed with the specified code from the client
673 if (!TEST_true(ossl_quic_tserver_is_term_any(qtserv
)))
676 cause
= ossl_quic_tserver_get_terminate_cause(qtserv
);
678 || !TEST_true(cause
->remote
)
679 || !TEST_false(cause
->app
)
680 || !TEST_uint64_t_eq(cause
->error_code
, code
))
686 int qtest_check_server_protocol_err(QUIC_TSERVER
*qtserv
)
688 return qtest_check_server_transport_err(qtserv
, OSSL_QUIC_ERR_PROTOCOL_VIOLATION
);
691 int qtest_check_server_frame_encoding_err(QUIC_TSERVER
*qtserv
)
693 return qtest_check_server_transport_err(qtserv
, OSSL_QUIC_ERR_FRAME_ENCODING_ERROR
);
696 void qtest_fault_free(QTEST_FAULT
*fault
)
701 packet_plain_finish(fault
);
702 handshake_finish(fault
);
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
,
714 QTEST_FAULT
*fault
= arg
;
718 /* Coalesce our data into a single buffer */
720 /* First calculate required buffer size */
721 for (i
= 0; i
< numin
; i
++)
722 bufsz
+= iovecin
[i
].buf_len
;
724 fault
->pplainio
.buf_len
= bufsz
;
726 /* Add an allowance for possible growth */
727 bufsz
+= GROWTH_ALLOWANCE
;
729 fault
->pplainio
.buf
= cur
= OPENSSL_malloc(bufsz
);
731 fault
->pplainio
.buf_len
= 0;
735 fault
->pplainbuf_alloc
= bufsz
;
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
;
743 fault
->pplainhdr
= *hdrin
;
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
))
752 *hdrout
= &fault
->pplainhdr
;
753 *iovecout
= &fault
->pplainio
;
759 static void packet_plain_finish(void *arg
)
761 QTEST_FAULT
*fault
= arg
;
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
;
770 int qtest_fault_set_packet_plain_listener(QTEST_FAULT
*fault
,
771 qtest_fault_on_packet_plain_cb pplaincb
,
774 fault
->pplaincb
= pplaincb
;
775 fault
->pplaincbarg
= pplaincbarg
;
777 return ossl_quic_tserver_set_plain_packet_mutator(fault
->qtserv
,
783 /* To be called from a packet_plain_listener callback */
784 int qtest_fault_resize_plain_packet(QTEST_FAULT
*fault
, size_t newlen
)
787 size_t oldlen
= fault
->pplainio
.buf_len
;
790 * Alloc'd size should always be non-zero, so if this fails we've been
793 if (fault
->pplainbuf_alloc
== 0)
796 if (newlen
> fault
->pplainbuf_alloc
) {
797 /* This exceeds our growth allowance. Fail */
801 /* Cast below is safe because we allocated the buffer */
802 buf
= (unsigned char *)fault
->pplainio
.buf
;
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 */
809 fault
->pplainio
.buf_len
= newlen
;
810 fault
->pplainhdr
.len
= newlen
;
816 * Prepend frame data into a packet. To be called from a packet_plain_listener
819 int qtest_fault_prepend_frame(QTEST_FAULT
*fault
, const unsigned char *frame
,
826 * Alloc'd size should always be non-zero, so if this fails we've been
829 if (fault
->pplainbuf_alloc
== 0)
832 /* Cast below is safe because we allocated the buffer */
833 buf
= (unsigned char *)fault
->pplainio
.buf
;
834 old_len
= fault
->pplainio
.buf_len
;
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
)))
841 memmove(buf
+ frame_len
, buf
, old_len
);
842 memcpy(buf
, frame
, frame_len
);
847 static int handshake_mutate(const unsigned char *msgin
, size_t msginlen
,
848 unsigned char **msgout
, size_t *msgoutlen
,
851 QTEST_FAULT
*fault
= arg
;
853 unsigned long payloadlen
;
854 unsigned int msgtype
;
857 buf
= OPENSSL_malloc(msginlen
+ GROWTH_ALLOWANCE
);
861 fault
->handbuf
= buf
;
862 fault
->handbuflen
= msginlen
;
863 fault
->handbufalloc
= msginlen
+ GROWTH_ALLOWANCE
;
864 memcpy(buf
, msgin
, msginlen
);
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
)
872 /* Parse specific message types */
874 case SSL3_MT_ENCRYPTED_EXTENSIONS
:
876 QTEST_ENCRYPTED_EXTENSIONS ee
;
878 if (fault
->encextcb
== NULL
)
882 * The EncryptedExtensions message is very simple. It just has an
883 * extensions block in it and nothing else.
885 ee
.extensions
= (unsigned char *)PACKET_data(&pkt
);
886 ee
.extensionslen
= payloadlen
;
887 if (!fault
->encextcb(fault
, &ee
, payloadlen
, fault
->encextcbarg
))
892 /* No specific handlers for these message types yet */
896 if (fault
->handshakecb
!= NULL
897 && !fault
->handshakecb(fault
, buf
, fault
->handbuflen
,
898 fault
->handshakecbarg
))
902 *msgoutlen
= fault
->handbuflen
;
907 static void handshake_finish(void *arg
)
909 QTEST_FAULT
*fault
= arg
;
911 OPENSSL_free(fault
->handbuf
);
912 fault
->handbuf
= NULL
;
915 int qtest_fault_set_handshake_listener(QTEST_FAULT
*fault
,
916 qtest_fault_on_handshake_cb handshakecb
,
917 void *handshakecbarg
)
919 fault
->handshakecb
= handshakecb
;
920 fault
->handshakecbarg
= handshakecbarg
;
922 return ossl_quic_tserver_set_handshake_mutator(fault
->qtserv
,
928 int qtest_fault_set_hand_enc_ext_listener(QTEST_FAULT
*fault
,
929 qtest_fault_on_enc_ext_cb encextcb
,
932 fault
->encextcb
= encextcb
;
933 fault
->encextcbarg
= encextcbarg
;
935 return ossl_quic_tserver_set_handshake_mutator(fault
->qtserv
,
941 /* To be called from a handshake_listener callback */
942 int qtest_fault_resize_handshake(QTEST_FAULT
*fault
, size_t newlen
)
945 size_t oldlen
= fault
->handbuflen
;
948 * Alloc'd size should always be non-zero, so if this fails we've been
951 if (fault
->handbufalloc
== 0)
954 if (newlen
> fault
->handbufalloc
) {
955 /* This exceeds our growth allowance. Fail */
959 buf
= (unsigned char *)fault
->handbuf
;
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 */
966 fault
->handbuflen
= newlen
;
970 /* To be called from message specific listener callbacks */
971 int qtest_fault_resize_message(QTEST_FAULT
*fault
, size_t newlen
)
973 /* First resize the underlying message */
974 if (!qtest_fault_resize_handshake(fault
, newlen
+ SSL3_HM_HEADER_LENGTH
))
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);
985 int qtest_fault_delete_extension(QTEST_FAULT
*fault
,
986 unsigned int exttype
, unsigned char *ext
,
990 PACKET pkt
, sub
, subext
;
991 WPACKET old_ext_wpkt
;
993 const unsigned char *start
, *end
;
995 size_t msglen
= fault
->handbuflen
;
997 if (!PACKET_buf_init(&pkt
, ext
, *extlen
))
1000 /* Extension block starts with 2 bytes for extension block length */
1001 if (!PACKET_as_length_prefixed_2(&pkt
, &sub
))
1005 start
= PACKET_data(&sub
);
1006 if (!PACKET_get_net_2(&sub
, &type
)
1007 || !PACKET_get_length_prefixed_2(&sub
, &subext
))
1009 } while (type
!= exttype
);
1012 end
= PACKET_data(&sub
);
1014 if (old_ext
!= NULL
) {
1015 if (!WPACKET_init(&old_ext_wpkt
, old_ext
))
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
);
1025 WPACKET_finish(&old_ext_wpkt
);
1026 old_ext
->length
= w
;
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.
1034 if (end
< ext
+ *extlen
)
1035 memmove((unsigned char *)start
, end
, end
- start
);
1038 * Calculate new extensions payload length =
1040 * - 2 extension block length bytes
1041 * - length of removed extension
1043 newlen
= *extlen
- 2 - (end
- start
);
1045 /* Fixup the length bytes for the extension block */
1046 ext
[0] = (unsigned char)((newlen
>> 8) & 0xff);
1047 ext
[1] = (unsigned char)((newlen
) & 0xff);
1050 * Length of the whole extension block is the new payload length plus the
1051 * 2 bytes for the length
1053 *extlen
= newlen
+ 2;
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
))
1065 #define BIO_TYPE_CIPHER_PACKET_FILTER (0x80 | BIO_TYPE_FILTER)
1067 static BIO_METHOD
*pcipherbiometh
= NULL
;
1069 # define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n)*(stride)))
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
)
1076 BIO
*next
= BIO_next(b
);
1077 ossl_ssize_t ret
= 0;
1078 size_t i
= 0, tmpnump
;
1081 unsigned char *tmpdata
;
1086 fault
= BIO_get_data(b
);
1088 || (fault
->pciphercb
== NULL
&& fault
->datagramcb
== NULL
))
1089 return BIO_sendmmsg(next
, msg
, stride
, num_msg
, flags
, num_processed
);
1096 for (i
= 0; i
< num_msg
; ++i
) {
1097 fault
->msg
= BIO_MSG_N(msg
, stride
, i
);
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
)
1103 memcpy(tmpdata
, fault
->msg
.data
, fault
->msg
.data_len
);
1104 fault
->msg
.data
= tmpdata
;
1105 fault
->msgalloc
= fault
->msg
.data_len
+ GROWTH_ALLOWANCE
;
1107 if (fault
->pciphercb
!= NULL
) {
1108 if (!PACKET_buf_init(&pkt
, fault
->msg
.data
, fault
->msg
.data_len
))
1112 if (!ossl_quic_wire_decode_pkt_hdr(&pkt
,
1114 * TODO(QUIC SERVER):
1115 * Needs to be set to the actual short header CID length
1116 * when testing the server implementation.
1124 * hdr.data is const - but its our buffer so casting away the
1127 if (!fault
->pciphercb(fault
, &hdr
, (unsigned char *)hdr
.data
,
1128 hdr
.len
, fault
->pciphercbarg
))
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.
1138 } while (PACKET_remaining(&pkt
) > 0);
1141 if (fault
->datagramcb
!= NULL
1142 && !fault
->datagramcb(fault
, &fault
->msg
, stride
,
1143 fault
->datagramcbarg
))
1146 if (!BIO_sendmmsg(next
, &fault
->msg
, stride
, 1, flags
, &tmpnump
)) {
1151 OPENSSL_free(fault
->msg
.data
);
1152 fault
->msg
.data
= NULL
;
1153 fault
->msgalloc
= 0;
1159 OPENSSL_free(fault
->msg
.data
);
1160 fault
->msg
.data
= NULL
;
1164 static long pcipher_ctrl(BIO
*b
, int cmd
, long larg
, void *parg
)
1166 BIO
*next
= BIO_next(b
);
1171 return BIO_ctrl(next
, cmd
, larg
, parg
);
1174 BIO_METHOD
*qtest_get_bio_method(void)
1178 if (pcipherbiometh
!= NULL
)
1179 return pcipherbiometh
;
1181 tmp
= BIO_meth_new(BIO_TYPE_CIPHER_PACKET_FILTER
, "Cipher Packet Filter");
1186 if (!TEST_true(BIO_meth_set_sendmmsg(tmp
, pcipher_sendmmsg
))
1187 || !TEST_true(BIO_meth_set_ctrl(tmp
, pcipher_ctrl
)))
1190 pcipherbiometh
= tmp
;
1194 return pcipherbiometh
;
1197 int qtest_fault_set_packet_cipher_listener(QTEST_FAULT
*fault
,
1198 qtest_fault_on_packet_cipher_cb pciphercb
,
1201 fault
->pciphercb
= pciphercb
;
1202 fault
->pciphercbarg
= pciphercbarg
;
1207 int qtest_fault_set_datagram_listener(QTEST_FAULT
*fault
,
1208 qtest_fault_on_datagram_cb datagramcb
,
1209 void *datagramcbarg
)
1211 fault
->datagramcb
= datagramcb
;
1212 fault
->datagramcbarg
= datagramcbarg
;
1217 /* To be called from a datagram_listener callback */
1218 int qtest_fault_resize_datagram(QTEST_FAULT
*fault
, size_t newlen
)
1220 if (newlen
> fault
->msgalloc
)
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
);
1227 fault
->msg
.data_len
= newlen
;
1232 int qtest_fault_set_bw_limit(QTEST_FAULT
*fault
,
1233 size_t ctos_bw
, size_t stoc_bw
,
1236 BIO
*sbio
= fault
->noiseargs
.sbio
;
1237 BIO
*cbio
= fault
->noiseargs
.cbio
;
1239 if (!TEST_ptr(sbio
) || !TEST_ptr(cbio
))
1241 if (!TEST_int_eq(BIO_ctrl(sbio
, BIO_CTRL_NOISE_RATE
, noise_rate
, NULL
), 1))
1243 if (!TEST_int_eq(BIO_ctrl(cbio
, BIO_CTRL_NOISE_RATE
, noise_rate
, NULL
), 1))
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))
1249 if (!TEST_int_eq(BIO_ctrl(sbio
, BIO_CTRL_NOISE_SEND_BANDWIDTH
,
1250 (long)stoc_bw
, NULL
), 1))
1256 int bio_msg_copy(BIO_MSG
*dst
, BIO_MSG
*src
)
1259 * Note it is assumed that the originally allocated data sizes for dst and
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
)))
1270 BIO_ADDR_clear(dst
->local
);
1273 if (!TEST_true(BIO_ADDR_copy(dst
->peer
, src
->peer
)))