xref: /freebsd/crypto/openssl/test/helpers/quictestlib.h (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
1 /*
2  * Copyright 2022-2025 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 <openssl/ssl.h>
11 #include <internal/quic_tserver.h>
12 
13 /* Type to represent the Fault Injector */
14 typedef struct qtest_fault QTEST_FAULT;
15 
16 typedef struct bio_qtest_data {
17     size_t short_conn_id_len;
18     struct qtest_fault *fault;
19 } QTEST_DATA;
20 
21 /*
22  * Structure representing a parsed EncryptedExtension message. Listeners can
23  * make changes to the contents of structure objects as required and the fault
24  * injector will reconstruct the message to be sent on
25  */
26 typedef struct qtest_fault_encrypted_extensions {
27     /* EncryptedExtension messages just have an extensions block */
28     unsigned char *extensions;
29     size_t extensionslen;
30 } QTEST_ENCRYPTED_EXTENSIONS;
31 
32 /* Flags for use with qtest_create_quic_objects() */
33 
34 /* Indicates whether we are using blocking mode or not */
35 #define QTEST_FLAG_BLOCK (1 << 0)
36 /* Use fake time rather than real time */
37 #define QTEST_FLAG_FAKE_TIME (1 << 1)
38 /* Introduce noise in the BIO */
39 #define QTEST_FLAG_NOISE (1 << 2)
40 /* Split datagrams such that each datagram contains one packet */
41 #define QTEST_FLAG_PACKET_SPLIT (1 << 3)
42 /* Turn on client side tracing */
43 #define QTEST_FLAG_CLIENT_TRACE (1 << 4)
44 /*
45  * Given an SSL_CTX for the client and filenames for the server certificate and
46  * keyfile, create a server and client instances as well as a fault injector
47  * instance. |flags| is the logical or of flags defined above, or 0 if none.
48  */
49 int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx,
50     SSL_CTX *serverctx, char *certfile, char *keyfile,
51     int flags, QUIC_TSERVER **qtserv, SSL **cssl,
52     QTEST_FAULT **fault, BIO **tracebio);
53 
54 /* Where QTEST_FLAG_FAKE_TIME is used, add millis to the current time */
55 void qtest_add_time(uint64_t millis);
56 
57 /* Starts time measurement */
58 void qtest_start_stopwatch(void);
59 /* Returns the duration from the start in millis */
60 uint64_t qtest_get_stopwatch_time(void);
61 
62 QTEST_FAULT *qtest_create_injector(QUIC_TSERVER *ts);
63 
64 BIO_METHOD *qtest_get_bio_method(void);
65 
66 /*
67  * Free up a Fault Injector instance
68  */
69 void qtest_fault_free(QTEST_FAULT *fault);
70 
71 /* Returns 1 if the quictestlib supports blocking tests */
72 int qtest_supports_blocking(void);
73 
74 /*
75  * Run the TLS handshake to create a QUIC connection between the client and
76  * server.
77  */
78 int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl);
79 
80 /*
81  * Check if both client and server have no data to read and are waiting on a
82  * timeout. If so, wait until the timeout has expired.
83  */
84 int qtest_wait_for_timeout(SSL *s, QUIC_TSERVER *qtserv);
85 
86 /*
87  * Same as qtest_create_quic_connection but will stop (successfully) if the
88  * clientssl indicates SSL_ERROR_WANT_XXX as specified by |wanterr|
89  */
90 int qtest_create_quic_connection_ex(QUIC_TSERVER *qtserv, SSL *clientssl,
91     int wanterr);
92 
93 /*
94  * Shutdown the client SSL object gracefully
95  */
96 int qtest_shutdown(QUIC_TSERVER *qtserv, SSL *clientssl);
97 
98 /*
99  * Confirm that the server has received the given transport error code.
100  */
101 int qtest_check_server_transport_err(QUIC_TSERVER *qtserv, uint64_t code);
102 
103 /*
104  * Confirm the server has received a protocol error. Equivalent to calling
105  * qtest_check_server_transport_err with a code of QUIC_ERR_PROTOCOL_VIOLATION
106  */
107 int qtest_check_server_protocol_err(QUIC_TSERVER *qtserv);
108 
109 /*
110  * Confirm the server has received a frame encoding error. Equivalent to calling
111  * qtest_check_server_transport_err with a code of QUIC_ERR_FRAME_ENCODING_ERROR
112  */
113 int qtest_check_server_frame_encoding_err(QUIC_TSERVER *qtserv);
114 
115 /*
116  * Enable tests to listen for pre-encryption QUIC packets being sent
117  */
118 typedef int (*qtest_fault_on_packet_plain_cb)(QTEST_FAULT *fault,
119     QUIC_PKT_HDR *hdr,
120     unsigned char *buf,
121     size_t len,
122     void *cbarg);
123 
124 int qtest_fault_set_packet_plain_listener(QTEST_FAULT *fault,
125     qtest_fault_on_packet_plain_cb pplaincb,
126     void *pplaincbarg);
127 
128 /*
129  * Helper function to be called from a packet_plain_listener callback if it
130  * wants to resize the packet (either to add new data to it, or to truncate it).
131  * The buf provided to packet_plain_listener is over allocated, so this just
132  * changes the logical size and never changes the actual address of the buf.
133  * This will fail if a large resize is attempted that exceeds the over
134  * allocation.
135  */
136 int qtest_fault_resize_plain_packet(QTEST_FAULT *fault, size_t newlen);
137 
138 /*
139  * Prepend frame data into a packet. To be called from a packet_plain_listener
140  * callback
141  */
142 int qtest_fault_prepend_frame(QTEST_FAULT *fault, const unsigned char *frame,
143     size_t frame_len);
144 
145 /*
146  * The general handshake message listener is sent the entire handshake message
147  * data block, including the handshake header itself
148  */
149 typedef int (*qtest_fault_on_handshake_cb)(QTEST_FAULT *fault,
150     unsigned char *msg,
151     size_t msglen,
152     void *handshakecbarg);
153 
154 int qtest_fault_set_handshake_listener(QTEST_FAULT *fault,
155     qtest_fault_on_handshake_cb handshakecb,
156     void *handshakecbarg);
157 
158 /*
159  * Helper function to be called from a handshake_listener callback if it wants
160  * to resize the handshake message (either to add new data to it, or to truncate
161  * it). newlen must include the length of the handshake message header. The
162  * handshake message buffer is over allocated, so this just changes the logical
163  * size and never changes the actual address of the buf.
164  * This will fail if a large resize is attempted that exceeds the over
165  * allocation.
166  */
167 int qtest_fault_resize_handshake(QTEST_FAULT *fault, size_t newlen);
168 
169 /*
170  * Add listeners for specific types of frame here. E.g. we might
171  * expect to see an "ACK" frame listener which will be passed pre-parsed ack
172  * data that can be modified as required.
173  */
174 
175 /*
176  * Handshake message specific listeners. Unlike the general handshake message
177  * listener these messages are pre-parsed and supplied with message specific
178  * data and exclude the handshake header
179  */
180 typedef int (*qtest_fault_on_enc_ext_cb)(QTEST_FAULT *fault,
181     QTEST_ENCRYPTED_EXTENSIONS *ee,
182     size_t eelen,
183     void *encextcbarg);
184 
185 int qtest_fault_set_hand_enc_ext_listener(QTEST_FAULT *fault,
186     qtest_fault_on_enc_ext_cb encextcb,
187     void *encextcbarg);
188 
189 /* Add listeners for other types of handshake message here */
190 
191 /*
192  * Helper function to be called from message specific listener callbacks. newlen
193  * is the new length of the specific message excluding the handshake message
194  * header.  The buffers provided to the message specific listeners are over
195  * allocated, so this just changes the logical size and never changes the actual
196  * address of the buffer. This will fail if a large resize is attempted that
197  * exceeds the over allocation.
198  */
199 int qtest_fault_resize_message(QTEST_FAULT *fault, size_t newlen);
200 
201 /*
202  * Helper function to delete an extension from an extension block. |exttype| is
203  * the type of the extension to be deleted. |ext| points to the extension block.
204  * On entry |*extlen| contains the length of the extension block. It is updated
205  * with the new length on exit. If old_ext is non-NULL, the deleted extension
206  * is appended to the given BUF_MEM.
207  */
208 int qtest_fault_delete_extension(QTEST_FAULT *fault,
209     unsigned int exttype, unsigned char *ext,
210     size_t *extlen,
211     BUF_MEM *old_ext);
212 
213 /*
214  * Add additional helper functions for querying extensions here (e.g.
215  * finding or adding them). We could also provide a "listener" API for listening
216  * for specific extension types
217  */
218 
219 /*
220  * Enable tests to listen for post-encryption QUIC packets being sent
221  */
222 typedef int (*qtest_fault_on_packet_cipher_cb)(QTEST_FAULT *fault,
223     /* The parsed packet header */
224     QUIC_PKT_HDR *hdr,
225     /* The packet payload data */
226     unsigned char *buf,
227     /* Length of the payload */
228     size_t len,
229     void *cbarg);
230 
231 int qtest_fault_set_packet_cipher_listener(QTEST_FAULT *fault,
232     qtest_fault_on_packet_cipher_cb pciphercb,
233     void *picphercbarg);
234 
235 /*
236  * Enable tests to listen for datagrams being sent
237  */
238 typedef int (*qtest_fault_on_datagram_cb)(QTEST_FAULT *fault,
239     BIO_MSG *m,
240     size_t stride,
241     void *cbarg);
242 
243 int qtest_fault_set_datagram_listener(QTEST_FAULT *fault,
244     qtest_fault_on_datagram_cb datagramcb,
245     void *datagramcbarg);
246 
247 /*
248  * To be called from a datagram_listener callback. The datagram buffer is over
249  * allocated, so this just changes the logical size and never changes the actual
250  * address of the buffer. This will fail if a large resize is attempted that
251  * exceeds the over allocation.
252  */
253 int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen);
254 
255 /*
256  * Set bandwidth and noise rate on noisy dgram filter.
257  * Arguments with values of 0 mean no limit/no noise.
258  */
259 
260 int qtest_fault_set_bw_limit(QTEST_FAULT *fault,
261     size_t ctos_bw, size_t stoc_bw,
262     int noise_rate);
263 
264 /* Copy a BIO_MSG */
265 int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src);
266 
267 #define BIO_CTRL_NOISE_BACK_OFF 1001
268 #define BIO_CTRL_NOISE_RATE 1002
269 #define BIO_CTRL_NOISE_RECV_BANDWIDTH 1003
270 #define BIO_CTRL_NOISE_SEND_BANDWIDTH 1004
271 #define BIO_CTRL_NOISE_SET_NOW_CB 1005
272 
273 struct bio_noise_now_cb_st {
274     OSSL_TIME (*now_cb)(void *);
275     void *now_cb_arg;
276 };
277 
278 /* BIO filter for simulating a noisy UDP socket */
279 const BIO_METHOD *bio_f_noisy_dgram_filter(void);
280 
281 /* Free the BIO filter method object */
282 void bio_f_noisy_dgram_filter_free(void);
283 
284 /*
285  * BIO filter for splitting QUIC datagrams containing multiple packets into
286  * individual datagrams.
287  */
288 const BIO_METHOD *bio_f_pkt_split_dgram_filter(void);
289 
290 /* Free the BIO filter method object */
291 void bio_f_pkt_split_dgram_filter_free(void);
292