Home | History | Annotate | Line # | Download | only in helpers
      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