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