]>
Commit | Line | Data |
---|---|---|
adef87a2 MC |
1 | /* |
2 | * Copyright 2022 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 | ||
2f1d8f85 | 10 | #include <assert.h> |
de60deb2 | 11 | #include <openssl/bio.h> |
adef87a2 MC |
12 | #include "quictestlib.h" |
13 | #include "../testutil.h" | |
2f1d8f85 MC |
14 | #include "internal/quic_wire_pkt.h" |
15 | #include "internal/quic_record_tx.h" | |
f10e5885 | 16 | #include "internal/quic_error.h" |
6d1f6933 | 17 | #include "internal/packet.h" |
2f1d8f85 MC |
18 | |
19 | #define GROWTH_ALLOWANCE 1024 | |
adef87a2 MC |
20 | |
21 | struct ossl_quic_fault { | |
22 | QUIC_TSERVER *qtserv; | |
2f1d8f85 MC |
23 | |
24 | /* Plain packet mutations */ | |
25 | /* Header for the plaintext packet */ | |
26 | QUIC_PKT_HDR pplainhdr; | |
27 | /* iovec for the plaintext packet data buffer */ | |
28 | OSSL_QTX_IOVEC pplainio; | |
29 | /* Allocted size of the plaintext packet data buffer */ | |
30 | size_t pplainbuf_alloc; | |
31 | ossl_quic_fault_on_packet_plain_cb pplaincb; | |
32 | void *pplaincbarg; | |
6d1f6933 MC |
33 | |
34 | /* Handshake message mutations */ | |
35 | /* Handshake message buffer */ | |
36 | unsigned char *handbuf; | |
37 | /* Allocated size of the handshake message buffer */ | |
38 | size_t handbufalloc; | |
39 | /* Actual length of the handshake message */ | |
40 | size_t handbuflen; | |
41 | ossl_quic_fault_on_handshake_cb handshakecb; | |
42 | void *handshakecbarg; | |
43 | ossl_quic_fault_on_enc_ext_cb encextcb; | |
44 | void *encextcbarg; | |
de60deb2 MC |
45 | |
46 | /* Cipher packet mutations */ | |
47 | ossl_quic_fault_on_packet_cipher_cb pciphercb; | |
48 | void *pciphercbarg; | |
e4cb6583 MC |
49 | |
50 | /* Datagram mutations */ | |
51 | ossl_quic_fault_on_datagram_cb datagramcb; | |
52 | void *datagramcbarg; | |
53 | /* The currently processed message */ | |
54 | BIO_MSG msg; | |
55 | /* Allocated size of msg data buffer */ | |
56 | size_t msgalloc; | |
adef87a2 MC |
57 | }; |
58 | ||
6d1f6933 MC |
59 | static void packet_plain_finish(void *arg); |
60 | static void handshake_finish(void *arg); | |
61 | ||
de60deb2 MC |
62 | static BIO_METHOD *get_bio_method(void); |
63 | ||
adef87a2 MC |
64 | int qtest_create_quic_objects(SSL_CTX *clientctx, char *certfile, char *keyfile, |
65 | QUIC_TSERVER **qtserv, SSL **cssl, | |
66 | OSSL_QUIC_FAULT **fault) | |
67 | { | |
68 | /* ALPN value as recognised by QUIC_TSERVER */ | |
69 | unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' }; | |
70 | QUIC_TSERVER_ARGS tserver_args = {0}; | |
de60deb2 | 71 | BIO *cbio = NULL, *sbio = NULL, *fisbio = NULL; |
adef87a2 MC |
72 | BIO_ADDR *peeraddr = NULL; |
73 | struct in_addr ina = {0}; | |
74 | ||
75 | *qtserv = NULL; | |
76 | if (fault != NULL) | |
77 | *fault = NULL; | |
78 | *cssl = SSL_new(clientctx); | |
79 | if (!TEST_ptr(*cssl)) | |
80 | return 0; | |
81 | ||
82 | if (!TEST_true(SSL_set_blocking_mode(*cssl, 0))) | |
83 | goto err; | |
84 | ||
85 | /* SSL_set_alpn_protos returns 0 for success! */ | |
86 | if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn)))) | |
87 | goto err; | |
88 | ||
de60deb2 | 89 | if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0))) |
adef87a2 MC |
90 | goto err; |
91 | ||
de60deb2 MC |
92 | if (!TEST_true(BIO_dgram_set_caps(cbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR)) |
93 | || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))) | |
adef87a2 MC |
94 | goto err; |
95 | ||
de60deb2 | 96 | SSL_set_bio(*cssl, cbio, cbio); |
adef87a2 MC |
97 | |
98 | if (!TEST_ptr(peeraddr = BIO_ADDR_new())) | |
99 | goto err; | |
100 | ||
101 | /* Dummy server address */ | |
102 | if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina), | |
103 | htons(0)))) | |
104 | goto err; | |
105 | ||
106 | if (!TEST_true(SSL_set_initial_peer_addr(*cssl, peeraddr))) | |
107 | goto err; | |
108 | ||
de60deb2 MC |
109 | if (fault != NULL) { |
110 | *fault = OPENSSL_zalloc(sizeof(**fault)); | |
111 | if (*fault == NULL) | |
112 | goto err; | |
113 | } | |
114 | ||
115 | fisbio = BIO_new(get_bio_method()); | |
116 | if (!TEST_ptr(fisbio)) | |
117 | goto err; | |
118 | ||
119 | BIO_set_data(fisbio, fault == NULL ? NULL : *fault); | |
120 | ||
121 | if (!TEST_ptr(BIO_push(fisbio, sbio))) | |
adef87a2 | 122 | goto err; |
de60deb2 MC |
123 | |
124 | tserver_args.net_rbio = sbio; | |
125 | tserver_args.net_wbio = fisbio; | |
adef87a2 MC |
126 | |
127 | if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile, | |
de60deb2 | 128 | keyfile))) |
adef87a2 | 129 | goto err; |
adef87a2 | 130 | |
de60deb2 MC |
131 | /* Ownership of fisbio and sbio is now held by *qtserv */ |
132 | sbio = NULL; | |
133 | fisbio = NULL; | |
adef87a2 | 134 | |
de60deb2 | 135 | if (fault != NULL) |
adef87a2 | 136 | (*fault)->qtserv = *qtserv; |
adef87a2 MC |
137 | |
138 | BIO_ADDR_free(peeraddr); | |
139 | ||
140 | return 1; | |
141 | err: | |
142 | BIO_ADDR_free(peeraddr); | |
de60deb2 MC |
143 | BIO_free(cbio); |
144 | BIO_free(fisbio); | |
145 | BIO_free(sbio); | |
adef87a2 MC |
146 | SSL_free(*cssl); |
147 | ossl_quic_tserver_free(*qtserv); | |
148 | if (fault != NULL) | |
149 | OPENSSL_free(*fault); | |
150 | ||
151 | return 0; | |
152 | } | |
153 | ||
154 | #define MAXLOOPS 1000 | |
155 | ||
156 | int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl) | |
157 | { | |
158 | int retc = -1, rets = 0, err, abortctr = 0, ret = 0; | |
159 | int clienterr = 0, servererr = 0; | |
160 | ||
161 | do { | |
162 | err = SSL_ERROR_WANT_WRITE; | |
163 | while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) { | |
164 | retc = SSL_connect(clientssl); | |
165 | if (retc <= 0) | |
166 | err = SSL_get_error(clientssl, retc); | |
167 | } | |
168 | ||
169 | if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) { | |
170 | TEST_info("SSL_connect() failed %d, %d", retc, err); | |
171 | TEST_openssl_errors(); | |
172 | clienterr = 1; | |
173 | } | |
174 | ||
175 | /* | |
176 | * We're cheating. We don't take any notice of SSL_get_tick_timeout() | |
177 | * and tick everytime around the loop anyway. This is inefficient. We | |
178 | * can get away with it in test code because we control both ends of | |
179 | * the communications and don't expect network delays. This shouldn't | |
180 | * be done in a real application. | |
181 | */ | |
f10e5885 | 182 | if (!clienterr && retc <= 0) |
adef87a2 | 183 | SSL_tick(clientssl); |
f10e5885 | 184 | if (!servererr && rets <= 0) { |
adef87a2 | 185 | ossl_quic_tserver_tick(qtserv); |
149a8e6c | 186 | servererr = ossl_quic_tserver_is_term_any(qtserv, NULL); |
f10e5885 | 187 | if (!servererr) |
ce8f20b6 | 188 | rets = ossl_quic_tserver_is_handshake_confirmed(qtserv); |
adef87a2 MC |
189 | } |
190 | ||
191 | if (clienterr && servererr) | |
192 | goto err; | |
193 | ||
194 | if (++abortctr == MAXLOOPS) { | |
195 | TEST_info("No progress made"); | |
196 | goto err; | |
197 | } | |
f10e5885 | 198 | } while ((retc <= 0 && !clienterr) || (rets <= 0 && !servererr)); |
adef87a2 | 199 | |
f10e5885 MC |
200 | if (!clienterr && !servererr) |
201 | ret = 1; | |
adef87a2 MC |
202 | err: |
203 | return ret; | |
204 | } | |
2f1d8f85 | 205 | |
c88de560 | 206 | int qtest_check_server_transport_err(QUIC_TSERVER *qtserv, uint64_t code) |
f10e5885 MC |
207 | { |
208 | QUIC_TERMINATE_CAUSE cause; | |
209 | ||
210 | ossl_quic_tserver_tick(qtserv); | |
211 | ||
212 | /* | |
c88de560 | 213 | * Check that the server has closed with the specified code from the client |
f10e5885 | 214 | */ |
c88de560 MC |
215 | if (!TEST_true(ossl_quic_tserver_is_term_any(qtserv))) |
216 | return 0; | |
217 | ||
218 | cause = ossl_quic_tserver_get_terminate_cause(qtserv); | |
219 | if (!TEST_true(cause.remote) | |
220 | || !TEST_uint64_t_eq(cause.error_code, code)) | |
f10e5885 MC |
221 | return 0; |
222 | ||
223 | return 1; | |
224 | } | |
225 | ||
c88de560 MC |
226 | int qtest_check_server_protocol_err(QUIC_TSERVER *qtserv) |
227 | { | |
228 | return qtest_check_server_transport_err(qtserv, QUIC_ERR_PROTOCOL_VIOLATION); | |
229 | } | |
230 | ||
2f1d8f85 MC |
231 | void ossl_quic_fault_free(OSSL_QUIC_FAULT *fault) |
232 | { | |
233 | if (fault == NULL) | |
234 | return; | |
235 | ||
6d1f6933 MC |
236 | packet_plain_finish(fault); |
237 | handshake_finish(fault); | |
238 | ||
2f1d8f85 MC |
239 | OPENSSL_free(fault); |
240 | } | |
241 | ||
242 | static int packet_plain_mutate(const QUIC_PKT_HDR *hdrin, | |
243 | const OSSL_QTX_IOVEC *iovecin, size_t numin, | |
244 | QUIC_PKT_HDR **hdrout, | |
245 | const OSSL_QTX_IOVEC **iovecout, | |
246 | size_t *numout, | |
247 | void *arg) | |
248 | { | |
249 | OSSL_QUIC_FAULT *fault = arg; | |
250 | size_t i, bufsz = 0; | |
251 | unsigned char *cur; | |
252 | ||
253 | /* Coalesce our data into a single buffer */ | |
254 | ||
255 | /* First calculate required buffer size */ | |
256 | for (i = 0; i < numin; i++) | |
257 | bufsz += iovecin[i].buf_len; | |
258 | ||
259 | fault->pplainio.buf_len = bufsz; | |
260 | ||
261 | /* Add an allowance for possible growth */ | |
262 | bufsz += GROWTH_ALLOWANCE; | |
263 | ||
264 | fault->pplainio.buf = cur = OPENSSL_malloc(bufsz); | |
265 | if (cur == NULL) { | |
266 | fault->pplainio.buf_len = 0; | |
267 | return 0; | |
268 | } | |
269 | ||
270 | fault->pplainbuf_alloc = bufsz; | |
271 | ||
272 | /* Copy in the data from the input buffers */ | |
273 | for (i = 0; i < numin; i++) { | |
274 | memcpy(cur, iovecin[i].buf, iovecin[i].buf_len); | |
275 | cur += iovecin[i].buf_len; | |
276 | } | |
277 | ||
278 | fault->pplainhdr = *hdrin; | |
279 | ||
280 | /* Cast below is safe because we allocated the buffer */ | |
281 | if (fault->pplaincb != NULL | |
282 | && !fault->pplaincb(fault, &fault->pplainhdr, | |
283 | (unsigned char *)fault->pplainio.buf, | |
284 | fault->pplainio.buf_len, fault->pplaincbarg)) | |
285 | return 0; | |
286 | ||
287 | *hdrout = &fault->pplainhdr; | |
288 | *iovecout = &fault->pplainio; | |
289 | *numout = 1; | |
290 | ||
291 | return 1; | |
292 | } | |
293 | ||
294 | static void packet_plain_finish(void *arg) | |
295 | { | |
296 | OSSL_QUIC_FAULT *fault = arg; | |
297 | ||
298 | /* Cast below is safe because we allocated the buffer */ | |
299 | OPENSSL_free((unsigned char *)fault->pplainio.buf); | |
300 | fault->pplainio.buf_len = 0; | |
301 | fault->pplainbuf_alloc = 0; | |
6d1f6933 | 302 | fault->pplainio.buf = NULL; |
2f1d8f85 MC |
303 | } |
304 | ||
305 | int ossl_quic_fault_set_packet_plain_listener(OSSL_QUIC_FAULT *fault, | |
306 | ossl_quic_fault_on_packet_plain_cb pplaincb, | |
307 | void *pplaincbarg) | |
308 | { | |
309 | fault->pplaincb = pplaincb; | |
310 | fault->pplaincbarg = pplaincbarg; | |
311 | ||
d03fe5de MC |
312 | return ossl_quic_tserver_set_plain_packet_mutator(fault->qtserv, |
313 | packet_plain_mutate, | |
314 | packet_plain_finish, | |
315 | fault); | |
2f1d8f85 MC |
316 | } |
317 | ||
318 | /* To be called from a packet_plain_listener callback */ | |
319 | int ossl_quic_fault_resize_plain_packet(OSSL_QUIC_FAULT *fault, size_t newlen) | |
320 | { | |
321 | unsigned char *buf; | |
322 | size_t oldlen = fault->pplainio.buf_len; | |
323 | ||
324 | /* | |
325 | * Alloc'd size should always be non-zero, so if this fails we've been | |
326 | * incorrectly called | |
327 | */ | |
328 | if (fault->pplainbuf_alloc == 0) | |
329 | return 0; | |
330 | ||
331 | if (newlen > fault->pplainbuf_alloc) { | |
332 | /* This exceeds our growth allowance. Fail */ | |
333 | return 0; | |
334 | } | |
335 | ||
336 | /* Cast below is safe because we allocated the buffer */ | |
337 | buf = (unsigned char *)fault->pplainio.buf; | |
338 | ||
339 | if (newlen > oldlen) { | |
340 | /* Extend packet with 0 bytes */ | |
341 | memset(buf + oldlen, 0, newlen - oldlen); | |
342 | } /* else we're truncating or staying the same */ | |
343 | ||
344 | fault->pplainio.buf_len = newlen; | |
345 | fault->pplainhdr.len = newlen; | |
346 | ||
347 | return 1; | |
348 | } | |
6d1f6933 | 349 | |
7eaaaaaa MC |
350 | /* |
351 | * Prepend frame data into a packet. To be called from a packet_plain_listener | |
352 | * callback | |
353 | */ | |
354 | int ossl_quic_fault_prepend_frame(OSSL_QUIC_FAULT *fault, unsigned char *frame, | |
355 | size_t frame_len) | |
356 | { | |
357 | unsigned char *buf; | |
358 | size_t old_len; | |
359 | ||
360 | /* | |
361 | * Alloc'd size should always be non-zero, so if this fails we've been | |
362 | * incorrectly called | |
363 | */ | |
364 | if (fault->pplainbuf_alloc == 0) | |
365 | return 0; | |
366 | ||
367 | /* Cast below is safe because we allocated the buffer */ | |
368 | buf = (unsigned char *)fault->pplainio.buf; | |
369 | old_len = fault->pplainio.buf_len; | |
370 | ||
371 | /* Extend the size of the packet by the size of the new frame */ | |
372 | if (!TEST_true(ossl_quic_fault_resize_plain_packet(fault, | |
373 | old_len + frame_len))) | |
374 | return 0; | |
375 | ||
376 | memmove(buf + frame_len, buf, old_len); | |
377 | memcpy(buf, frame, frame_len); | |
378 | ||
379 | return 1; | |
380 | } | |
381 | ||
6d1f6933 MC |
382 | static int handshake_mutate(const unsigned char *msgin, size_t msginlen, |
383 | unsigned char **msgout, size_t *msgoutlen, | |
384 | void *arg) | |
385 | { | |
386 | OSSL_QUIC_FAULT *fault = arg; | |
387 | unsigned char *buf; | |
388 | unsigned long payloadlen; | |
389 | unsigned int msgtype; | |
390 | PACKET pkt; | |
391 | ||
392 | buf = OPENSSL_malloc(msginlen + GROWTH_ALLOWANCE); | |
393 | if (buf == NULL) | |
394 | return 0; | |
395 | ||
396 | fault->handbuf = buf; | |
397 | fault->handbuflen = msginlen; | |
398 | fault->handbufalloc = msginlen + GROWTH_ALLOWANCE; | |
399 | memcpy(buf, msgin, msginlen); | |
400 | ||
401 | if (!PACKET_buf_init(&pkt, buf, msginlen) | |
402 | || !PACKET_get_1(&pkt, &msgtype) | |
403 | || !PACKET_get_net_3(&pkt, &payloadlen) | |
404 | || PACKET_remaining(&pkt) != payloadlen) | |
405 | return 0; | |
406 | ||
407 | /* Parse specific message types */ | |
408 | switch (msgtype) { | |
409 | case SSL3_MT_ENCRYPTED_EXTENSIONS: | |
410 | { | |
411 | OSSL_QF_ENCRYPTED_EXTENSIONS ee; | |
412 | ||
413 | if (fault->encextcb == NULL) | |
414 | break; | |
415 | ||
416 | /* | |
417 | * The EncryptedExtensions message is very simple. It just has an | |
418 | * extensions block in it and nothing else. | |
419 | */ | |
420 | ee.extensions = (unsigned char *)PACKET_data(&pkt); | |
421 | ee.extensionslen = payloadlen; | |
422 | if (!fault->encextcb(fault, &ee, payloadlen, fault->encextcbarg)) | |
423 | return 0; | |
424 | } | |
425 | ||
426 | default: | |
427 | /* No specific handlers for these message types yet */ | |
428 | break; | |
429 | } | |
430 | ||
431 | if (fault->handshakecb != NULL | |
432 | && !fault->handshakecb(fault, buf, fault->handbuflen, | |
433 | fault->handshakecbarg)) | |
434 | return 0; | |
435 | ||
436 | *msgout = buf; | |
437 | *msgoutlen = fault->handbuflen; | |
438 | ||
439 | return 1; | |
440 | } | |
441 | ||
442 | static void handshake_finish(void *arg) | |
443 | { | |
444 | OSSL_QUIC_FAULT *fault = arg; | |
445 | ||
446 | OPENSSL_free(fault->handbuf); | |
447 | fault->handbuf = NULL; | |
448 | } | |
449 | ||
450 | int ossl_quic_fault_set_handshake_listener(OSSL_QUIC_FAULT *fault, | |
451 | ossl_quic_fault_on_handshake_cb handshakecb, | |
452 | void *handshakecbarg) | |
453 | { | |
454 | fault->handshakecb = handshakecb; | |
455 | fault->handshakecbarg = handshakecbarg; | |
456 | ||
457 | return ossl_quic_tserver_set_handshake_mutator(fault->qtserv, | |
458 | handshake_mutate, | |
459 | handshake_finish, | |
460 | fault); | |
461 | } | |
462 | ||
463 | int ossl_quic_fault_set_hand_enc_ext_listener(OSSL_QUIC_FAULT *fault, | |
464 | ossl_quic_fault_on_enc_ext_cb encextcb, | |
465 | void *encextcbarg) | |
466 | { | |
467 | fault->encextcb = encextcb; | |
468 | fault->encextcbarg = encextcbarg; | |
469 | ||
470 | return ossl_quic_tserver_set_handshake_mutator(fault->qtserv, | |
471 | handshake_mutate, | |
472 | handshake_finish, | |
473 | fault); | |
474 | } | |
475 | ||
476 | /* To be called from a handshake_listener callback */ | |
477 | int ossl_quic_fault_resize_handshake(OSSL_QUIC_FAULT *fault, size_t newlen) | |
478 | { | |
479 | unsigned char *buf; | |
480 | size_t oldlen = fault->handbuflen; | |
481 | ||
482 | /* | |
483 | * Alloc'd size should always be non-zero, so if this fails we've been | |
484 | * incorrectly called | |
485 | */ | |
486 | if (fault->handbufalloc == 0) | |
487 | return 0; | |
488 | ||
489 | if (newlen > fault->handbufalloc) { | |
490 | /* This exceeds our growth allowance. Fail */ | |
491 | return 0; | |
492 | } | |
493 | ||
494 | buf = (unsigned char *)fault->handbuf; | |
495 | ||
496 | if (newlen > oldlen) { | |
497 | /* Extend packet with 0 bytes */ | |
498 | memset(buf + oldlen, 0, newlen - oldlen); | |
499 | } /* else we're truncating or staying the same */ | |
500 | ||
501 | fault->handbuflen = newlen; | |
502 | return 1; | |
503 | } | |
504 | ||
505 | /* To be called from message specific listener callbacks */ | |
506 | int ossl_quic_fault_resize_message(OSSL_QUIC_FAULT *fault, size_t newlen) | |
507 | { | |
508 | /* First resize the underlying message */ | |
509 | if (!ossl_quic_fault_resize_handshake(fault, newlen + SSL3_HM_HEADER_LENGTH)) | |
510 | return 0; | |
511 | ||
512 | /* Fixup the handshake message header */ | |
513 | fault->handbuf[1] = (unsigned char)((newlen >> 16) & 0xff); | |
514 | fault->handbuf[2] = (unsigned char)((newlen >> 8) & 0xff); | |
515 | fault->handbuf[3] = (unsigned char)((newlen ) & 0xff); | |
516 | ||
517 | return 1; | |
518 | } | |
519 | ||
520 | int ossl_quic_fault_delete_extension(OSSL_QUIC_FAULT *fault, | |
521 | unsigned int exttype, unsigned char *ext, | |
f10e5885 | 522 | size_t *extlen) |
6d1f6933 MC |
523 | { |
524 | PACKET pkt, sub, subext; | |
525 | unsigned int type; | |
526 | const unsigned char *start, *end; | |
527 | size_t newlen; | |
f10e5885 | 528 | size_t msglen = fault->handbuflen; |
6d1f6933 MC |
529 | |
530 | if (!PACKET_buf_init(&pkt, ext, *extlen)) | |
531 | return 0; | |
532 | ||
533 | /* Extension block starts with 2 bytes for extension block length */ | |
534 | if (!PACKET_as_length_prefixed_2(&pkt, &sub)) | |
535 | return 0; | |
536 | ||
537 | do { | |
538 | start = PACKET_data(&sub); | |
539 | if (!PACKET_get_net_2(&sub, &type) | |
f10e5885 | 540 | || !PACKET_get_length_prefixed_2(&sub, &subext)) |
6d1f6933 MC |
541 | return 0; |
542 | } while (type != exttype); | |
543 | ||
544 | /* Found it */ | |
545 | end = PACKET_data(&sub); | |
546 | ||
547 | /* | |
548 | * If we're not the last extension we need to move the rest earlier. The | |
549 | * cast below is safe because we own the underlying buffer and we're no | |
550 | * longer making PACKET calls. | |
551 | */ | |
552 | if (end < ext + *extlen) | |
553 | memmove((unsigned char *)start, end, end - start); | |
554 | ||
555 | /* | |
556 | * Calculate new extensions payload length = | |
557 | * Original length | |
558 | * - 2 extension block length bytes | |
559 | * - length of removed extension | |
560 | */ | |
561 | newlen = *extlen - 2 - (end - start); | |
562 | ||
563 | /* Fixup the length bytes for the extension block */ | |
564 | ext[0] = (unsigned char)((newlen >> 8) & 0xff); | |
565 | ext[1] = (unsigned char)((newlen ) & 0xff); | |
566 | ||
567 | /* | |
568 | * Length of the whole extension block is the new payload length plus the | |
569 | * 2 bytes for the length | |
570 | */ | |
571 | *extlen = newlen + 2; | |
572 | ||
573 | /* We can now resize the message */ | |
f10e5885 MC |
574 | if ((size_t)(end - start) + SSL3_HM_HEADER_LENGTH > msglen) |
575 | return 0; /* Should not happen */ | |
576 | msglen -= (end - start) + SSL3_HM_HEADER_LENGTH; | |
577 | if (!ossl_quic_fault_resize_message(fault, msglen)) | |
6d1f6933 MC |
578 | return 0; |
579 | ||
580 | return 1; | |
581 | } | |
de60deb2 MC |
582 | |
583 | #define BIO_TYPE_CIPHER_PACKET_FILTER (0x80 | BIO_TYPE_FILTER) | |
584 | ||
585 | static BIO_METHOD *pcipherbiometh = NULL; | |
586 | ||
587 | # define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n)*(stride))) | |
588 | ||
589 | static int pcipher_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride, | |
590 | size_t num_msg, uint64_t flags, | |
591 | size_t *num_processed) | |
592 | { | |
593 | OSSL_QUIC_FAULT *fault; | |
594 | BIO *next = BIO_next(b); | |
595 | ossl_ssize_t ret = 0; | |
de60deb2 MC |
596 | size_t i = 0, tmpnump; |
597 | QUIC_PKT_HDR hdr; | |
598 | PACKET pkt; | |
e4cb6583 | 599 | unsigned char *tmpdata; |
de60deb2 MC |
600 | |
601 | if (next == NULL) | |
602 | return 0; | |
603 | ||
604 | fault = BIO_get_data(b); | |
e4cb6583 MC |
605 | if (fault == NULL |
606 | || (fault->pciphercb == NULL && fault->datagramcb == NULL)) | |
de60deb2 MC |
607 | return BIO_sendmmsg(next, msg, stride, num_msg, flags, num_processed); |
608 | ||
609 | if (num_msg == 0) { | |
610 | *num_processed = 0; | |
611 | return 1; | |
612 | } | |
613 | ||
614 | for (i = 0; i < num_msg; ++i) { | |
e4cb6583 | 615 | fault->msg = BIO_MSG_N(msg, stride, i); |
de60deb2 MC |
616 | |
617 | /* Take a copy of the data so that callbacks can modify it */ | |
e4cb6583 MC |
618 | tmpdata = OPENSSL_malloc(fault->msg.data_len + GROWTH_ALLOWANCE); |
619 | if (tmpdata == NULL) | |
de60deb2 | 620 | return 0; |
e4cb6583 MC |
621 | memcpy(tmpdata, fault->msg.data, fault->msg.data_len); |
622 | fault->msg.data = tmpdata; | |
623 | fault->msgalloc = fault->msg.data_len + GROWTH_ALLOWANCE; | |
624 | ||
625 | if (fault->pciphercb != NULL) { | |
626 | if (!PACKET_buf_init(&pkt, fault->msg.data, fault->msg.data_len)) | |
627 | return 0; | |
628 | ||
629 | do { | |
630 | if (!ossl_quic_wire_decode_pkt_hdr(&pkt, | |
631 | 0 /* TODO(QUIC): Not sure how this should be set*/, 1, | |
632 | &hdr, NULL)) | |
633 | goto out; | |
634 | ||
635 | /* | |
636 | * hdr.data is const - but its our buffer so casting away the | |
637 | * const is safe | |
638 | */ | |
639 | if (!fault->pciphercb(fault, &hdr, (unsigned char *)hdr.data, | |
640 | hdr.len, fault->pciphercbarg)) | |
641 | goto out; | |
642 | ||
643 | /* | |
644 | * TODO(QUIC): At the moment modifications to hdr by the callback | |
645 | * are ignored. We might need to rewrite the QUIC header to | |
646 | * enable tests to change this. We also don't yet have a | |
647 | * mechanism for the callback to change the encrypted data | |
648 | * length. It's not clear if that's needed or not. | |
649 | */ | |
650 | } while (PACKET_remaining(&pkt) > 0); | |
651 | } | |
de60deb2 | 652 | |
e4cb6583 MC |
653 | if (fault->datagramcb != NULL |
654 | && !fault->datagramcb(fault, &fault->msg, stride, | |
655 | fault->datagramcbarg)) | |
656 | goto out; | |
de60deb2 | 657 | |
e4cb6583 | 658 | if (!BIO_sendmmsg(next, &fault->msg, stride, 1, flags, &tmpnump)) { |
de60deb2 MC |
659 | *num_processed = i; |
660 | goto out; | |
661 | } | |
662 | ||
e4cb6583 MC |
663 | OPENSSL_free(fault->msg.data); |
664 | fault->msg.data = NULL; | |
665 | fault->msgalloc = 0; | |
de60deb2 MC |
666 | } |
667 | ||
668 | *num_processed = i; | |
669 | ret = 1; | |
670 | out: | |
671 | if (i > 0) | |
672 | ret = 1; | |
673 | else | |
674 | ret = 0; | |
e4cb6583 MC |
675 | OPENSSL_free(fault->msg.data); |
676 | fault->msg.data = NULL; | |
de60deb2 MC |
677 | return ret; |
678 | } | |
679 | ||
680 | static long pcipher_ctrl(BIO *b, int cmd, long larg, void *parg) | |
681 | { | |
682 | BIO *next = BIO_next(b); | |
683 | ||
684 | if (next == NULL) | |
685 | return -1; | |
686 | ||
687 | return BIO_ctrl(next, cmd, larg, parg); | |
688 | } | |
689 | ||
690 | static BIO_METHOD *get_bio_method(void) | |
691 | { | |
692 | BIO_METHOD *tmp; | |
693 | ||
694 | if (pcipherbiometh != NULL) | |
695 | return pcipherbiometh; | |
696 | ||
697 | tmp = BIO_meth_new(BIO_TYPE_CIPHER_PACKET_FILTER, "Cipher Packet Filter"); | |
698 | ||
699 | if (!TEST_ptr(tmp)) | |
700 | return NULL; | |
701 | ||
702 | if (!TEST_true(BIO_meth_set_sendmmsg(tmp, pcipher_sendmmsg)) | |
703 | || !TEST_true(BIO_meth_set_ctrl(tmp, pcipher_ctrl))) | |
704 | goto err; | |
705 | ||
706 | pcipherbiometh = tmp; | |
707 | tmp = NULL; | |
708 | err: | |
709 | BIO_meth_free(tmp); | |
710 | return pcipherbiometh; | |
711 | } | |
712 | ||
713 | int ossl_quic_fault_set_packet_cipher_listener(OSSL_QUIC_FAULT *fault, | |
714 | ossl_quic_fault_on_packet_cipher_cb pciphercb, | |
715 | void *pciphercbarg) | |
716 | { | |
717 | fault->pciphercb = pciphercb; | |
718 | fault->pciphercbarg = pciphercbarg; | |
719 | ||
720 | return 1; | |
e4cb6583 MC |
721 | } |
722 | ||
723 | int ossl_quic_fault_set_datagram_listener(OSSL_QUIC_FAULT *fault, | |
724 | ossl_quic_fault_on_datagram_cb datagramcb, | |
725 | void *datagramcbarg) | |
726 | { | |
727 | fault->datagramcb = datagramcb; | |
728 | fault->datagramcbarg = datagramcbarg; | |
729 | ||
730 | return 1; | |
731 | } | |
732 | ||
733 | /* To be called from a datagram_listener callback */ | |
734 | int ossl_quic_fault_resize_datagram(OSSL_QUIC_FAULT *fault, size_t newlen) | |
735 | { | |
736 | if (newlen > fault->msgalloc) | |
737 | return 0; | |
738 | ||
739 | if (newlen > fault->msg.data_len) | |
740 | memset((unsigned char *)fault->msg.data + fault->msg.data_len, 0, | |
741 | newlen - fault->msg.data_len); | |
742 | ||
743 | fault->msg.data_len = newlen; | |
744 | ||
745 | return 1; | |
746 | } |