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