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 /* 130 * Helper function to be called from a packet_plain_listener callback if it 131 * wants to resize the packet (either to add new data to it, or to truncate it). 132 * The buf provided to packet_plain_listener is over allocated, so this just 133 * changes the logical size and never changes the actual address of the buf. 134 * This will fail if a large resize is attempted that exceeds the over 135 * allocation. 136 */ 137 int qtest_fault_resize_plain_packet(QTEST_FAULT *fault, size_t newlen); 138 139 /* 140 * Prepend frame data into a packet. To be called from a packet_plain_listener 141 * callback 142 */ 143 int qtest_fault_prepend_frame(QTEST_FAULT *fault, const unsigned char *frame, 144 size_t frame_len); 145 146 /* 147 * The general handshake message listener is sent the entire handshake message 148 * data block, including the handshake header itself 149 */ 150 typedef int (*qtest_fault_on_handshake_cb)(QTEST_FAULT *fault, 151 unsigned char *msg, 152 size_t msglen, 153 void *handshakecbarg); 154 155 int qtest_fault_set_handshake_listener(QTEST_FAULT *fault, 156 qtest_fault_on_handshake_cb handshakecb, 157 void *handshakecbarg); 158 159 /* 160 * Helper function to be called from a handshake_listener callback if it wants 161 * to resize the handshake message (either to add new data to it, or to truncate 162 * it). newlen must include the length of the handshake message header. The 163 * handshake message buffer is over allocated, so this just changes the logical 164 * size and never changes the actual address of the buf. 165 * This will fail if a large resize is attempted that exceeds the over 166 * allocation. 167 */ 168 int qtest_fault_resize_handshake(QTEST_FAULT *fault, size_t newlen); 169 170 /* 171 * Add listeners for specific types of frame here. E.g. we might 172 * expect to see an "ACK" frame listener which will be passed pre-parsed ack 173 * data that can be modified as required. 174 */ 175 176 /* 177 * Handshake message specific listeners. Unlike the general handshake message 178 * listener these messages are pre-parsed and supplied with message specific 179 * data and exclude the handshake header 180 */ 181 typedef int (*qtest_fault_on_enc_ext_cb)(QTEST_FAULT *fault, 182 QTEST_ENCRYPTED_EXTENSIONS *ee, 183 size_t eelen, 184 void *encextcbarg); 185 186 int qtest_fault_set_hand_enc_ext_listener(QTEST_FAULT *fault, 187 qtest_fault_on_enc_ext_cb encextcb, 188 void *encextcbarg); 189 190 /* Add listeners for other types of handshake message here */ 191 192 193 /* 194 * Helper function to be called from message specific listener callbacks. newlen 195 * is the new length of the specific message excluding the handshake message 196 * header. The buffers provided to the message specific listeners are over 197 * allocated, so this just changes the logical size and never changes the actual 198 * address of the buffer. This will fail if a large resize is attempted that 199 * exceeds the over allocation. 200 */ 201 int qtest_fault_resize_message(QTEST_FAULT *fault, size_t newlen); 202 203 /* 204 * Helper function to delete an extension from an extension block. |exttype| is 205 * the type of the extension to be deleted. |ext| points to the extension block. 206 * On entry |*extlen| contains the length of the extension block. It is updated 207 * with the new length on exit. If old_ext is non-NULL, the deleted extension 208 * is appended to the given BUF_MEM. 209 */ 210 int qtest_fault_delete_extension(QTEST_FAULT *fault, 211 unsigned int exttype, unsigned char *ext, 212 size_t *extlen, 213 BUF_MEM *old_ext); 214 215 /* 216 * Add additional helper functions for querying extensions here (e.g. 217 * finding or adding them). We could also provide a "listener" API for listening 218 * for specific extension types 219 */ 220 221 /* 222 * Enable tests to listen for post-encryption QUIC packets being sent 223 */ 224 typedef int (*qtest_fault_on_packet_cipher_cb)(QTEST_FAULT *fault, 225 /* The parsed packet header */ 226 QUIC_PKT_HDR *hdr, 227 /* The packet payload data */ 228 unsigned char *buf, 229 /* Length of the payload */ 230 size_t len, 231 void *cbarg); 232 233 int qtest_fault_set_packet_cipher_listener(QTEST_FAULT *fault, 234 qtest_fault_on_packet_cipher_cb pciphercb, 235 void *picphercbarg); 236 237 /* 238 * Enable tests to listen for datagrams being sent 239 */ 240 typedef int (*qtest_fault_on_datagram_cb)(QTEST_FAULT *fault, 241 BIO_MSG *m, 242 size_t stride, 243 void *cbarg); 244 245 int qtest_fault_set_datagram_listener(QTEST_FAULT *fault, 246 qtest_fault_on_datagram_cb datagramcb, 247 void *datagramcbarg); 248 249 /* 250 * To be called from a datagram_listener callback. The datagram buffer is over 251 * allocated, so this just changes the logical size and never changes the actual 252 * address of the buffer. This will fail if a large resize is attempted that 253 * exceeds the over allocation. 254 */ 255 int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen); 256 257 /* 258 * Set bandwidth and noise rate on noisy dgram filter. 259 * Arguments with values of 0 mean no limit/no noise. 260 */ 261 262 int qtest_fault_set_bw_limit(QTEST_FAULT *fault, 263 size_t ctos_bw, size_t stoc_bw, 264 int noise_rate); 265 266 /* Copy a BIO_MSG */ 267 int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src); 268 269 #define BIO_CTRL_NOISE_BACK_OFF 1001 270 #define BIO_CTRL_NOISE_RATE 1002 271 #define BIO_CTRL_NOISE_RECV_BANDWIDTH 1003 272 #define BIO_CTRL_NOISE_SEND_BANDWIDTH 1004 273 #define BIO_CTRL_NOISE_SET_NOW_CB 1005 274 275 struct bio_noise_now_cb_st { 276 OSSL_TIME (*now_cb)(void *); 277 void *now_cb_arg; 278 }; 279 280 /* BIO filter for simulating a noisy UDP socket */ 281 const BIO_METHOD *bio_f_noisy_dgram_filter(void); 282 283 /* Free the BIO filter method object */ 284 void bio_f_noisy_dgram_filter_free(void); 285 286 /* 287 * BIO filter for splitting QUIC datagrams containing multiple packets into 288 * individual datagrams. 289 */ 290 const BIO_METHOD *bio_f_pkt_split_dgram_filter(void); 291 292 /* Free the BIO filter method object */ 293 void bio_f_pkt_split_dgram_filter_free(void); 294