2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
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
11 #include "quictestlib.h"
12 #include "../testutil.h"
13 #include "internal/quic_wire_pkt.h"
14 #include "internal/quic_record_tx.h"
16 #define GROWTH_ALLOWANCE 1024
18 struct ossl_quic_fault {
21 /* Plain packet mutations */
22 /* Header for the plaintext packet */
23 QUIC_PKT_HDR pplainhdr;
24 /* iovec for the plaintext packet data buffer */
25 OSSL_QTX_IOVEC pplainio;
26 /* Allocted size of the plaintext packet data buffer */
27 size_t pplainbuf_alloc;
28 ossl_quic_fault_on_packet_plain_cb pplaincb;
32 int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile,
33 QUIC_TSERVER **qtserv, SSL **cssl,
34 OSSL_QUIC_FAULT **fault)
36 /* ALPN value as recognised by QUIC_TSERVER */
37 unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
38 QUIC_TSERVER_ARGS tserver_args = {0};
39 BIO *bio1 = NULL, *bio2 = NULL;
40 BIO_ADDR *peeraddr = NULL;
41 struct in_addr ina = {0};
46 *cssl = SSL_new(clientctx);
50 if (!TEST_true(SSL_set_blocking_mode(*cssl, 0)))
53 /* SSL_set_alpn_protos returns 0 for success! */
54 if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn))))
57 if (!TEST_true(BIO_new_bio_dgram_pair(&bio1, 0, &bio2, 0)))
60 if (!TEST_true(BIO_dgram_set_caps(bio1, BIO_DGRAM_CAP_HANDLES_DST_ADDR))
61 || !TEST_true(BIO_dgram_set_caps(bio2, BIO_DGRAM_CAP_HANDLES_DST_ADDR)))
64 SSL_set_bio(*cssl, bio1, bio1);
66 if (!TEST_ptr(peeraddr = BIO_ADDR_new()))
69 /* Dummy server address */
70 if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina),
74 if (!TEST_true(SSL_set_initial_peer_addr(*cssl, peeraddr)))
77 /* 2 refs are passed for bio2 */
78 if (!BIO_up_ref(bio2))
80 tserver_args.net_rbio = bio2;
81 tserver_args.net_wbio = bio2;
83 if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile,
85 /* We hold 2 refs to bio2 at the moment */
89 /* Ownership of bio2 is now held by *qtserv */
93 *fault = OPENSSL_zalloc(sizeof(**fault));
97 (*fault)->qtserv = *qtserv;
100 BIO_ADDR_free(peeraddr);
104 BIO_ADDR_free(peeraddr);
108 ossl_quic_tserver_free(*qtserv);
110 OPENSSL_free(*fault);
115 #define MAXLOOPS 1000
117 int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl)
119 int retc = -1, rets = 0, err, abortctr = 0, ret = 0;
120 int clienterr = 0, servererr = 0;
123 err = SSL_ERROR_WANT_WRITE;
124 while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
125 retc = SSL_connect(clientssl);
127 err = SSL_get_error(clientssl, retc);
130 if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
131 TEST_info("SSL_connect() failed %d, %d", retc, err);
132 TEST_openssl_errors();
137 * We're cheating. We don't take any notice of SSL_get_tick_timeout()
138 * and tick everytime around the loop anyway. This is inefficient. We
139 * can get away with it in test code because we control both ends of
140 * the communications and don't expect network delays. This shouldn't
141 * be done in a real application.
146 ossl_quic_tserver_tick(qtserv);
147 servererr = ossl_quic_tserver_is_term_any(qtserv);
148 if (!servererr && !rets)
149 rets = ossl_quic_tserver_is_connected(qtserv);
152 if (clienterr && servererr)
155 if (++abortctr == MAXLOOPS) {
156 TEST_info("No progress made");
159 } while (retc <=0 || rets <= 0);
166 void ossl_quic_fault_free(OSSL_QUIC_FAULT *fault)
174 static int packet_plain_mutate(const QUIC_PKT_HDR *hdrin,
175 const OSSL_QTX_IOVEC *iovecin, size_t numin,
176 QUIC_PKT_HDR **hdrout,
177 const OSSL_QTX_IOVEC **iovecout,
181 OSSL_QUIC_FAULT *fault = arg;
185 /* Coalesce our data into a single buffer */
187 /* First calculate required buffer size */
188 for (i = 0; i < numin; i++)
189 bufsz += iovecin[i].buf_len;
191 fault->pplainio.buf_len = bufsz;
193 /* Add an allowance for possible growth */
194 bufsz += GROWTH_ALLOWANCE;
196 fault->pplainio.buf = cur = OPENSSL_malloc(bufsz);
198 fault->pplainio.buf_len = 0;
202 fault->pplainbuf_alloc = bufsz;
204 /* Copy in the data from the input buffers */
205 for (i = 0; i < numin; i++) {
206 memcpy(cur, iovecin[i].buf, iovecin[i].buf_len);
207 cur += iovecin[i].buf_len;
210 fault->pplainhdr = *hdrin;
212 /* Cast below is safe because we allocated the buffer */
213 if (fault->pplaincb != NULL
214 && !fault->pplaincb(fault, &fault->pplainhdr,
215 (unsigned char *)fault->pplainio.buf,
216 fault->pplainio.buf_len, fault->pplaincbarg))
219 *hdrout = &fault->pplainhdr;
220 *iovecout = &fault->pplainio;
226 static void packet_plain_finish(void *arg)
228 OSSL_QUIC_FAULT *fault = arg;
230 /* Cast below is safe because we allocated the buffer */
231 OPENSSL_free((unsigned char *)fault->pplainio.buf);
232 fault->pplainio.buf_len = 0;
233 fault->pplainbuf_alloc = 0;
236 int ossl_quic_fault_set_packet_plain_listener(OSSL_QUIC_FAULT *fault,
237 ossl_quic_fault_on_packet_plain_cb pplaincb,
240 fault->pplaincb = pplaincb;
241 fault->pplaincbarg = pplaincbarg;
243 return ossl_quic_tserver_set_mutator(fault->qtserv, packet_plain_mutate,
244 packet_plain_finish, fault);
247 /* To be called from a packet_plain_listener callback */
248 int ossl_quic_fault_resize_plain_packet(OSSL_QUIC_FAULT *fault, size_t newlen)
251 size_t oldlen = fault->pplainio.buf_len;
254 * Alloc'd size should always be non-zero, so if this fails we've been
257 if (fault->pplainbuf_alloc == 0)
260 if (newlen > fault->pplainbuf_alloc) {
261 /* This exceeds our growth allowance. Fail */
265 /* Cast below is safe because we allocated the buffer */
266 buf = (unsigned char *)fault->pplainio.buf;
268 if (newlen > oldlen) {
269 /* Extend packet with 0 bytes */
270 memset(buf + oldlen, 0, newlen - oldlen);
271 } /* else we're truncating or staying the same */
273 fault->pplainio.buf_len = newlen;
274 fault->pplainhdr.len = newlen;