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"
15 #include "internal/packet.h"
17 #define GROWTH_ALLOWANCE 1024
19 struct ossl_quic_fault
{
22 /* Plain packet mutations */
23 /* Header for the plaintext packet */
24 QUIC_PKT_HDR pplainhdr
;
25 /* iovec for the plaintext packet data buffer */
26 OSSL_QTX_IOVEC pplainio
;
27 /* Allocted size of the plaintext packet data buffer */
28 size_t pplainbuf_alloc
;
29 ossl_quic_fault_on_packet_plain_cb pplaincb
;
32 /* Handshake message mutations */
33 /* Handshake message buffer */
34 unsigned char *handbuf
;
35 /* Allocated size of the handshake message buffer */
37 /* Actual length of the handshake message */
39 ossl_quic_fault_on_handshake_cb handshakecb
;
41 ossl_quic_fault_on_enc_ext_cb encextcb
;
45 static void packet_plain_finish(void *arg
);
46 static void handshake_finish(void *arg
);
48 int qtest_create_quic_objects(SSL_CTX
*clientctx
, char *certfile
, char *keyfile
,
49 QUIC_TSERVER
**qtserv
, SSL
**cssl
,
50 OSSL_QUIC_FAULT
**fault
)
52 /* ALPN value as recognised by QUIC_TSERVER */
53 unsigned char alpn
[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
54 QUIC_TSERVER_ARGS tserver_args
= {0};
55 BIO
*bio1
= NULL
, *bio2
= NULL
;
56 BIO_ADDR
*peeraddr
= NULL
;
57 struct in_addr ina
= {0};
62 *cssl
= SSL_new(clientctx
);
66 if (!TEST_true(SSL_set_blocking_mode(*cssl
, 0)))
69 /* SSL_set_alpn_protos returns 0 for success! */
70 if (!TEST_false(SSL_set_alpn_protos(*cssl
, alpn
, sizeof(alpn
))))
73 if (!TEST_true(BIO_new_bio_dgram_pair(&bio1
, 0, &bio2
, 0)))
76 if (!TEST_true(BIO_dgram_set_caps(bio1
, BIO_DGRAM_CAP_HANDLES_DST_ADDR
))
77 || !TEST_true(BIO_dgram_set_caps(bio2
, BIO_DGRAM_CAP_HANDLES_DST_ADDR
)))
80 SSL_set_bio(*cssl
, bio1
, bio1
);
82 if (!TEST_ptr(peeraddr
= BIO_ADDR_new()))
85 /* Dummy server address */
86 if (!TEST_true(BIO_ADDR_rawmake(peeraddr
, AF_INET
, &ina
, sizeof(ina
),
90 if (!TEST_true(SSL_set_initial_peer_addr(*cssl
, peeraddr
)))
93 /* 2 refs are passed for bio2 */
94 if (!BIO_up_ref(bio2
))
96 tserver_args
.net_rbio
= bio2
;
97 tserver_args
.net_wbio
= bio2
;
99 if (!TEST_ptr(*qtserv
= ossl_quic_tserver_new(&tserver_args
, certfile
,
101 /* We hold 2 refs to bio2 at the moment */
105 /* Ownership of bio2 is now held by *qtserv */
109 *fault
= OPENSSL_zalloc(sizeof(**fault
));
113 (*fault
)->qtserv
= *qtserv
;
116 BIO_ADDR_free(peeraddr
);
120 BIO_ADDR_free(peeraddr
);
124 ossl_quic_tserver_free(*qtserv
);
126 OPENSSL_free(*fault
);
131 #define MAXLOOPS 1000
133 int qtest_create_quic_connection(QUIC_TSERVER
*qtserv
, SSL
*clientssl
)
135 int retc
= -1, rets
= 0, err
, abortctr
= 0, ret
= 0;
136 int clienterr
= 0, servererr
= 0;
139 err
= SSL_ERROR_WANT_WRITE
;
140 while (!clienterr
&& retc
<= 0 && err
== SSL_ERROR_WANT_WRITE
) {
141 retc
= SSL_connect(clientssl
);
143 err
= SSL_get_error(clientssl
, retc
);
146 if (!clienterr
&& retc
<= 0 && err
!= SSL_ERROR_WANT_READ
) {
147 TEST_info("SSL_connect() failed %d, %d", retc
, err
);
148 TEST_openssl_errors();
153 * We're cheating. We don't take any notice of SSL_get_tick_timeout()
154 * and tick everytime around the loop anyway. This is inefficient. We
155 * can get away with it in test code because we control both ends of
156 * the communications and don't expect network delays. This shouldn't
157 * be done in a real application.
162 ossl_quic_tserver_tick(qtserv
);
163 servererr
= ossl_quic_tserver_is_term_any(qtserv
, NULL
);
164 if (!servererr
&& !rets
)
165 rets
= ossl_quic_tserver_is_connected(qtserv
);
168 if (clienterr
&& servererr
)
171 if (++abortctr
== MAXLOOPS
) {
172 TEST_info("No progress made");
175 } while (retc
<=0 || rets
<= 0);
182 void ossl_quic_fault_free(OSSL_QUIC_FAULT
*fault
)
187 packet_plain_finish(fault
);
188 handshake_finish(fault
);
193 static int packet_plain_mutate(const QUIC_PKT_HDR
*hdrin
,
194 const OSSL_QTX_IOVEC
*iovecin
, size_t numin
,
195 QUIC_PKT_HDR
**hdrout
,
196 const OSSL_QTX_IOVEC
**iovecout
,
200 OSSL_QUIC_FAULT
*fault
= arg
;
204 /* Coalesce our data into a single buffer */
206 /* First calculate required buffer size */
207 for (i
= 0; i
< numin
; i
++)
208 bufsz
+= iovecin
[i
].buf_len
;
210 fault
->pplainio
.buf_len
= bufsz
;
212 /* Add an allowance for possible growth */
213 bufsz
+= GROWTH_ALLOWANCE
;
215 fault
->pplainio
.buf
= cur
= OPENSSL_malloc(bufsz
);
217 fault
->pplainio
.buf_len
= 0;
221 fault
->pplainbuf_alloc
= bufsz
;
223 /* Copy in the data from the input buffers */
224 for (i
= 0; i
< numin
; i
++) {
225 memcpy(cur
, iovecin
[i
].buf
, iovecin
[i
].buf_len
);
226 cur
+= iovecin
[i
].buf_len
;
229 fault
->pplainhdr
= *hdrin
;
231 /* Cast below is safe because we allocated the buffer */
232 if (fault
->pplaincb
!= NULL
233 && !fault
->pplaincb(fault
, &fault
->pplainhdr
,
234 (unsigned char *)fault
->pplainio
.buf
,
235 fault
->pplainio
.buf_len
, fault
->pplaincbarg
))
238 *hdrout
= &fault
->pplainhdr
;
239 *iovecout
= &fault
->pplainio
;
245 static void packet_plain_finish(void *arg
)
247 OSSL_QUIC_FAULT
*fault
= arg
;
249 /* Cast below is safe because we allocated the buffer */
250 OPENSSL_free((unsigned char *)fault
->pplainio
.buf
);
251 fault
->pplainio
.buf_len
= 0;
252 fault
->pplainbuf_alloc
= 0;
253 fault
->pplainio
.buf
= NULL
;
256 int ossl_quic_fault_set_packet_plain_listener(OSSL_QUIC_FAULT
*fault
,
257 ossl_quic_fault_on_packet_plain_cb pplaincb
,
260 fault
->pplaincb
= pplaincb
;
261 fault
->pplaincbarg
= pplaincbarg
;
263 return ossl_quic_tserver_set_plain_packet_mutator(fault
->qtserv
,
269 /* To be called from a packet_plain_listener callback */
270 int ossl_quic_fault_resize_plain_packet(OSSL_QUIC_FAULT
*fault
, size_t newlen
)
273 size_t oldlen
= fault
->pplainio
.buf_len
;
276 * Alloc'd size should always be non-zero, so if this fails we've been
279 if (fault
->pplainbuf_alloc
== 0)
282 if (newlen
> fault
->pplainbuf_alloc
) {
283 /* This exceeds our growth allowance. Fail */
287 /* Cast below is safe because we allocated the buffer */
288 buf
= (unsigned char *)fault
->pplainio
.buf
;
290 if (newlen
> oldlen
) {
291 /* Extend packet with 0 bytes */
292 memset(buf
+ oldlen
, 0, newlen
- oldlen
);
293 } /* else we're truncating or staying the same */
295 fault
->pplainio
.buf_len
= newlen
;
296 fault
->pplainhdr
.len
= newlen
;
301 static int handshake_mutate(const unsigned char *msgin
, size_t msginlen
,
302 unsigned char **msgout
, size_t *msgoutlen
,
305 OSSL_QUIC_FAULT
*fault
= arg
;
307 unsigned long payloadlen
;
308 unsigned int msgtype
;
311 buf
= OPENSSL_malloc(msginlen
+ GROWTH_ALLOWANCE
);
315 fault
->handbuf
= buf
;
316 fault
->handbuflen
= msginlen
;
317 fault
->handbufalloc
= msginlen
+ GROWTH_ALLOWANCE
;
318 memcpy(buf
, msgin
, msginlen
);
320 if (!PACKET_buf_init(&pkt
, buf
, msginlen
)
321 || !PACKET_get_1(&pkt
, &msgtype
)
322 || !PACKET_get_net_3(&pkt
, &payloadlen
)
323 || PACKET_remaining(&pkt
) != payloadlen
)
326 /* Parse specific message types */
328 case SSL3_MT_ENCRYPTED_EXTENSIONS
:
330 OSSL_QF_ENCRYPTED_EXTENSIONS ee
;
332 if (fault
->encextcb
== NULL
)
336 * The EncryptedExtensions message is very simple. It just has an
337 * extensions block in it and nothing else.
339 ee
.extensions
= (unsigned char *)PACKET_data(&pkt
);
340 ee
.extensionslen
= payloadlen
;
341 if (!fault
->encextcb(fault
, &ee
, payloadlen
, fault
->encextcbarg
))
346 /* No specific handlers for these message types yet */
350 if (fault
->handshakecb
!= NULL
351 && !fault
->handshakecb(fault
, buf
, fault
->handbuflen
,
352 fault
->handshakecbarg
))
356 *msgoutlen
= fault
->handbuflen
;
361 static void handshake_finish(void *arg
)
363 OSSL_QUIC_FAULT
*fault
= arg
;
365 OPENSSL_free(fault
->handbuf
);
366 fault
->handbuf
= NULL
;
369 int ossl_quic_fault_set_handshake_listener(OSSL_QUIC_FAULT
*fault
,
370 ossl_quic_fault_on_handshake_cb handshakecb
,
371 void *handshakecbarg
)
373 fault
->handshakecb
= handshakecb
;
374 fault
->handshakecbarg
= handshakecbarg
;
376 return ossl_quic_tserver_set_handshake_mutator(fault
->qtserv
,
382 int ossl_quic_fault_set_hand_enc_ext_listener(OSSL_QUIC_FAULT
*fault
,
383 ossl_quic_fault_on_enc_ext_cb encextcb
,
386 fault
->encextcb
= encextcb
;
387 fault
->encextcbarg
= encextcbarg
;
389 return ossl_quic_tserver_set_handshake_mutator(fault
->qtserv
,
395 /* To be called from a handshake_listener callback */
396 int ossl_quic_fault_resize_handshake(OSSL_QUIC_FAULT
*fault
, size_t newlen
)
399 size_t oldlen
= fault
->handbuflen
;
402 * Alloc'd size should always be non-zero, so if this fails we've been
405 if (fault
->handbufalloc
== 0)
408 if (newlen
> fault
->handbufalloc
) {
409 /* This exceeds our growth allowance. Fail */
413 buf
= (unsigned char *)fault
->handbuf
;
415 if (newlen
> oldlen
) {
416 /* Extend packet with 0 bytes */
417 memset(buf
+ oldlen
, 0, newlen
- oldlen
);
418 } /* else we're truncating or staying the same */
420 fault
->handbuflen
= newlen
;
424 /* To be called from message specific listener callbacks */
425 int ossl_quic_fault_resize_message(OSSL_QUIC_FAULT
*fault
, size_t newlen
)
427 /* First resize the underlying message */
428 if (!ossl_quic_fault_resize_handshake(fault
, newlen
+ SSL3_HM_HEADER_LENGTH
))
431 /* Fixup the handshake message header */
432 fault
->handbuf
[1] = (unsigned char)((newlen
>> 16) & 0xff);
433 fault
->handbuf
[2] = (unsigned char)((newlen
>> 8) & 0xff);
434 fault
->handbuf
[3] = (unsigned char)((newlen
) & 0xff);
439 int ossl_quic_fault_delete_extension(OSSL_QUIC_FAULT
*fault
,
440 unsigned int exttype
, unsigned char *ext
,
441 size_t *extlen
, size_t *msglen
)
443 PACKET pkt
, sub
, subext
;
445 const unsigned char *start
, *end
;
448 if (!PACKET_buf_init(&pkt
, ext
, *extlen
))
451 /* Extension block starts with 2 bytes for extension block length */
452 if (!PACKET_as_length_prefixed_2(&pkt
, &sub
))
456 start
= PACKET_data(&sub
);
457 if (!PACKET_get_net_2(&sub
, &type
)
458 || !PACKET_as_length_prefixed_2(&sub
, &subext
))
460 } while (type
!= exttype
);
463 end
= PACKET_data(&sub
);
466 * If we're not the last extension we need to move the rest earlier. The
467 * cast below is safe because we own the underlying buffer and we're no
468 * longer making PACKET calls.
470 if (end
< ext
+ *extlen
)
471 memmove((unsigned char *)start
, end
, end
- start
);
474 * Calculate new extensions payload length =
476 * - 2 extension block length bytes
477 * - length of removed extension
479 newlen
= *extlen
- 2 - (end
- start
);
481 /* Fixup the length bytes for the extension block */
482 ext
[0] = (unsigned char)((newlen
>> 8) & 0xff);
483 ext
[1] = (unsigned char)((newlen
) & 0xff);
486 * Length of the whole extension block is the new payload length plus the
487 * 2 bytes for the length
489 *extlen
= newlen
+ 2;
491 /* We can now resize the message */
492 *msglen
-= (end
- start
);
493 if (!ossl_quic_fault_resize_message(fault
, *msglen
))