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/err.h>
11 #include "internal/common.h"
12 #include "internal/quic_wire_pkt.h"
13
ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR * hpr,OSSL_LIB_CTX * libctx,const char * propq,uint32_t cipher_id,const unsigned char * quic_hp_key,size_t quic_hp_key_len)14 int ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR *hpr,
15 OSSL_LIB_CTX *libctx,
16 const char *propq,
17 uint32_t cipher_id,
18 const unsigned char *quic_hp_key,
19 size_t quic_hp_key_len)
20 {
21 const char *cipher_name = NULL;
22
23 switch (cipher_id) {
24 case QUIC_HDR_PROT_CIPHER_AES_128:
25 cipher_name = "AES-128-ECB";
26 break;
27 case QUIC_HDR_PROT_CIPHER_AES_256:
28 cipher_name = "AES-256-ECB";
29 break;
30 case QUIC_HDR_PROT_CIPHER_CHACHA:
31 cipher_name = "ChaCha20";
32 break;
33 default:
34 ERR_raise(ERR_LIB_SSL, ERR_R_UNSUPPORTED);
35 return 0;
36 }
37
38 hpr->cipher_ctx = EVP_CIPHER_CTX_new();
39 if (hpr->cipher_ctx == NULL) {
40 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
41 return 0;
42 }
43
44 hpr->cipher = EVP_CIPHER_fetch(libctx, cipher_name, propq);
45 if (hpr->cipher == NULL
46 || quic_hp_key_len != (size_t)EVP_CIPHER_get_key_length(hpr->cipher)) {
47 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
48 goto err;
49 }
50
51 if (!EVP_CipherInit_ex(hpr->cipher_ctx, hpr->cipher, NULL,
52 quic_hp_key, NULL, 1)) {
53 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
54 goto err;
55 }
56
57 hpr->libctx = libctx;
58 hpr->propq = propq;
59 hpr->cipher_id = cipher_id;
60 return 1;
61
62 err:
63 ossl_quic_hdr_protector_cleanup(hpr);
64 return 0;
65 }
66
ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR * hpr)67 void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr)
68 {
69 EVP_CIPHER_CTX_free(hpr->cipher_ctx);
70 hpr->cipher_ctx = NULL;
71
72 EVP_CIPHER_free(hpr->cipher);
73 hpr->cipher = NULL;
74 }
75
hdr_generate_mask(QUIC_HDR_PROTECTOR * hpr,const unsigned char * sample,size_t sample_len,unsigned char * mask)76 static int hdr_generate_mask(QUIC_HDR_PROTECTOR *hpr,
77 const unsigned char *sample, size_t sample_len,
78 unsigned char *mask)
79 {
80 int l = 0;
81 unsigned char dst[16];
82 static const unsigned char zeroes[5] = { 0 };
83 size_t i;
84
85 if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_128
86 || hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_256) {
87 if (sample_len < 16) {
88 ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
89 return 0;
90 }
91
92 if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, NULL, 1)
93 || !EVP_CipherUpdate(hpr->cipher_ctx, dst, &l, sample, 16)) {
94 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
95 return 0;
96 }
97
98 for (i = 0; i < 5; ++i)
99 mask[i] = dst[i];
100 } else if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_CHACHA) {
101 if (sample_len < 16) {
102 ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
103 return 0;
104 }
105
106 if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, sample, 1)
107 || !EVP_CipherUpdate(hpr->cipher_ctx, mask, &l,
108 zeroes, sizeof(zeroes))) {
109 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
110 return 0;
111 }
112 } else {
113 ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
114 assert(0);
115 return 0;
116 }
117
118 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
119 /* No matter what we did above we use the same mask in fuzzing mode */
120 memset(mask, 0, 5);
121 #endif
122
123 return 1;
124 }
125
ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR * hpr,QUIC_PKT_HDR_PTRS * ptrs)126 int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr,
127 QUIC_PKT_HDR_PTRS *ptrs)
128 {
129 return ossl_quic_hdr_protector_decrypt_fields(hpr,
130 ptrs->raw_sample,
131 ptrs->raw_sample_len,
132 ptrs->raw_start,
133 ptrs->raw_pn);
134 }
135
ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR * hpr,const unsigned char * sample,size_t sample_len,unsigned char * first_byte,unsigned char * pn_bytes)136 int ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR *hpr,
137 const unsigned char *sample,
138 size_t sample_len,
139 unsigned char *first_byte,
140 unsigned char *pn_bytes)
141 {
142 unsigned char mask[5], pn_len, i;
143
144 if (!hdr_generate_mask(hpr, sample, sample_len, mask))
145 return 0;
146
147 *first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
148 pn_len = (*first_byte & 0x3) + 1;
149
150 for (i = 0; i < pn_len; ++i)
151 pn_bytes[i] ^= mask[i + 1];
152
153 return 1;
154 }
155
ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR * hpr,QUIC_PKT_HDR_PTRS * ptrs)156 int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr,
157 QUIC_PKT_HDR_PTRS *ptrs)
158 {
159 return ossl_quic_hdr_protector_encrypt_fields(hpr,
160 ptrs->raw_sample,
161 ptrs->raw_sample_len,
162 ptrs->raw_start,
163 ptrs->raw_pn);
164 }
165
ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR * hpr,const unsigned char * sample,size_t sample_len,unsigned char * first_byte,unsigned char * pn_bytes)166 int ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR *hpr,
167 const unsigned char *sample,
168 size_t sample_len,
169 unsigned char *first_byte,
170 unsigned char *pn_bytes)
171 {
172 unsigned char mask[5], pn_len, i;
173
174 if (!hdr_generate_mask(hpr, sample, sample_len, mask))
175 return 0;
176
177 pn_len = (*first_byte & 0x3) + 1;
178 for (i = 0; i < pn_len; ++i)
179 pn_bytes[i] ^= mask[i + 1];
180
181 *first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
182 return 1;
183 }
184
ossl_quic_wire_decode_pkt_hdr(PACKET * pkt,size_t short_conn_id_len,int partial,int nodata,QUIC_PKT_HDR * hdr,QUIC_PKT_HDR_PTRS * ptrs,uint64_t * fail_cause)185 int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
186 size_t short_conn_id_len,
187 int partial,
188 int nodata,
189 QUIC_PKT_HDR *hdr,
190 QUIC_PKT_HDR_PTRS *ptrs,
191 uint64_t *fail_cause)
192 {
193 unsigned int b0;
194 unsigned char *pn = NULL;
195 size_t l = PACKET_remaining(pkt);
196
197 if (fail_cause != NULL)
198 *fail_cause = QUIC_PKT_HDR_DECODE_DECODE_ERR;
199
200 if (ptrs != NULL) {
201 ptrs->raw_start = (unsigned char *)PACKET_data(pkt);
202 ptrs->raw_sample = NULL;
203 ptrs->raw_sample_len = 0;
204 ptrs->raw_pn = NULL;
205 }
206
207 if (l < QUIC_MIN_VALID_PKT_LEN
208 || !PACKET_get_1(pkt, &b0))
209 return 0;
210
211 hdr->partial = partial;
212 hdr->unused = 0;
213 hdr->reserved = 0;
214
215 if ((b0 & 0x80) == 0) {
216 /* Short header. */
217 if (short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
218 return 0;
219
220 if ((b0 & 0x40) == 0 /* fixed bit not set? */
221 || l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
222 return 0;
223
224 hdr->type = QUIC_PKT_TYPE_1RTT;
225 hdr->fixed = 1;
226 hdr->spin_bit = (b0 & 0x20) != 0;
227 if (partial) {
228 hdr->key_phase = 0; /* protected, zero for now */
229 hdr->pn_len = 0; /* protected, zero for now */
230 hdr->reserved = 0; /* protected, zero for now */
231 } else {
232 hdr->key_phase = (b0 & 0x04) != 0;
233 hdr->pn_len = (b0 & 0x03) + 1;
234 hdr->reserved = (b0 & 0x18) >> 3;
235 }
236
237 /* Copy destination connection ID field to header structure. */
238 if (!PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, short_conn_id_len))
239 return 0;
240
241 hdr->dst_conn_id.id_len = (unsigned char)short_conn_id_len;
242
243 /*
244 * Skip over the PN. If this is a partial decode, the PN length field
245 * currently has header protection applied. Thus we do not know the
246 * length of the PN but we are allowed to assume it is 4 bytes long at
247 * this stage.
248 */
249 memset(hdr->pn, 0, sizeof(hdr->pn));
250 pn = (unsigned char *)PACKET_data(pkt);
251 if (partial) {
252 if (!PACKET_forward(pkt, sizeof(hdr->pn)))
253 return 0;
254 } else {
255 if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
256 return 0;
257 }
258
259 /* Fields not used in short-header packets. */
260 hdr->version = 0;
261 hdr->src_conn_id.id_len = 0;
262 hdr->token = NULL;
263 hdr->token_len = 0;
264
265 /*
266 * Short-header packets always come last in a datagram, the length
267 * is the remainder of the buffer.
268 */
269 hdr->len = PACKET_remaining(pkt);
270 hdr->data = PACKET_data(pkt);
271
272 /*
273 * Skip over payload. Since this is a short header packet, which cannot
274 * be followed by any other kind of packet, this advances us to the end
275 * of the datagram.
276 */
277 if (!PACKET_forward(pkt, hdr->len))
278 return 0;
279 } else {
280 /* Long header. */
281 unsigned long version;
282 unsigned int dst_conn_id_len, src_conn_id_len, raw_type;
283
284 if (!PACKET_get_net_4(pkt, &version))
285 return 0;
286
287 /*
288 * All QUIC packets must have the fixed bit set, except exceptionally
289 * for Version Negotiation packets.
290 */
291 if (version != 0 && (b0 & 0x40) == 0)
292 return 0;
293
294 if (!PACKET_get_1(pkt, &dst_conn_id_len)
295 || dst_conn_id_len > QUIC_MAX_CONN_ID_LEN
296 || !PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, dst_conn_id_len)
297 || !PACKET_get_1(pkt, &src_conn_id_len)
298 || src_conn_id_len > QUIC_MAX_CONN_ID_LEN
299 || !PACKET_copy_bytes(pkt, hdr->src_conn_id.id, src_conn_id_len))
300 return 0;
301
302 hdr->version = (uint32_t)version;
303 hdr->dst_conn_id.id_len = (unsigned char)dst_conn_id_len;
304 hdr->src_conn_id.id_len = (unsigned char)src_conn_id_len;
305
306 if (version == 0) {
307 /*
308 * Version negotiation packet. Version negotiation packets are
309 * identified by a version field of 0 and the type bits in the first
310 * byte are ignored (they may take any value, and we ignore them).
311 */
312 hdr->type = QUIC_PKT_TYPE_VERSION_NEG;
313 hdr->fixed = (b0 & 0x40) != 0;
314
315 hdr->data = PACKET_data(pkt);
316 hdr->len = PACKET_remaining(pkt);
317
318 /*
319 * Version negotiation packets must contain an array of u32s, so it
320 * is invalid for their payload length to not be divisible by 4.
321 */
322 if ((hdr->len % 4) != 0)
323 return 0;
324
325 /* Version negotiation packets are always fully decoded. */
326 hdr->partial = 0;
327
328 /* Fields not used in version negotiation packets. */
329 hdr->pn_len = 0;
330 hdr->spin_bit = 0;
331 hdr->key_phase = 0;
332 hdr->token = NULL;
333 hdr->token_len = 0;
334 memset(hdr->pn, 0, sizeof(hdr->pn));
335
336 if (!PACKET_forward(pkt, hdr->len))
337 return 0;
338 } else if (version != QUIC_VERSION_1) {
339 if (fail_cause != NULL)
340 *fail_cause |= QUIC_PKT_HDR_DECODE_BAD_VERSION;
341 /* Unknown version, do not decode. */
342 return 0;
343 } else {
344 if (l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
345 return 0;
346
347 /* Get long packet type and decode to QUIC_PKT_TYPE_*. */
348 raw_type = ((b0 >> 4) & 0x3);
349
350 switch (raw_type) {
351 case 0:
352 hdr->type = QUIC_PKT_TYPE_INITIAL;
353 break;
354 case 1:
355 hdr->type = QUIC_PKT_TYPE_0RTT;
356 break;
357 case 2:
358 hdr->type = QUIC_PKT_TYPE_HANDSHAKE;
359 break;
360 case 3:
361 hdr->type = QUIC_PKT_TYPE_RETRY;
362 break;
363 }
364
365 hdr->pn_len = 0;
366 hdr->fixed = 1;
367
368 /* Fields not used in long-header packets. */
369 hdr->spin_bit = 0;
370 hdr->key_phase = 0;
371
372 if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
373 /* Initial packet. */
374 uint64_t token_len;
375
376 if (!PACKET_get_quic_vlint(pkt, &token_len)
377 || token_len > SIZE_MAX
378 || !PACKET_get_bytes(pkt, &hdr->token, (size_t)token_len))
379 return 0;
380
381 hdr->token_len = (size_t)token_len;
382 if (token_len == 0)
383 hdr->token = NULL;
384 } else {
385 hdr->token = NULL;
386 hdr->token_len = 0;
387 }
388
389 if (hdr->type == QUIC_PKT_TYPE_RETRY) {
390 /* Retry packet. */
391 hdr->data = PACKET_data(pkt);
392 hdr->len = PACKET_remaining(pkt);
393
394 /* Retry packets are always fully decoded. */
395 hdr->partial = 0;
396
397 /* Unused bits in Retry header. */
398 hdr->unused = b0 & 0x0f;
399
400 /* Fields not used in Retry packets. */
401 memset(hdr->pn, 0, sizeof(hdr->pn));
402
403 if (!PACKET_forward(pkt, hdr->len))
404 return 0;
405 } else {
406 /* Initial, 0-RTT or Handshake packet. */
407 uint64_t len;
408
409 hdr->pn_len = partial ? 0 : ((b0 & 0x03) + 1);
410 hdr->reserved = partial ? 0 : ((b0 & 0x0C) >> 2);
411
412 if (!PACKET_get_quic_vlint(pkt, &len)
413 || len < sizeof(hdr->pn))
414 return 0;
415
416 if (!nodata && len > PACKET_remaining(pkt))
417 return 0;
418
419 /*
420 * Skip over the PN. If this is a partial decode, the PN length
421 * field currently has header protection applied. Thus we do not
422 * know the length of the PN but we are allowed to assume it is
423 * 4 bytes long at this stage.
424 */
425 pn = (unsigned char *)PACKET_data(pkt);
426 memset(hdr->pn, 0, sizeof(hdr->pn));
427 if (partial) {
428 if (!PACKET_forward(pkt, sizeof(hdr->pn)))
429 return 0;
430
431 hdr->len = (size_t)(len - sizeof(hdr->pn));
432 } else {
433 if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
434 return 0;
435
436 hdr->len = (size_t)(len - hdr->pn_len);
437 }
438
439 if (nodata) {
440 hdr->data = NULL;
441 } else {
442 hdr->data = PACKET_data(pkt);
443
444 /* Skip over packet body. */
445 if (!PACKET_forward(pkt, hdr->len))
446 return 0;
447 }
448 }
449 }
450 }
451
452 if (ptrs != NULL) {
453 ptrs->raw_pn = pn;
454 if (pn != NULL) {
455 ptrs->raw_sample = pn + 4;
456 ptrs->raw_sample_len = PACKET_end(pkt) - ptrs->raw_sample;
457 }
458 }
459
460 /*
461 * Good decode, clear the generic DECODE_ERR flag
462 */
463 if (fail_cause != NULL)
464 *fail_cause &= ~QUIC_PKT_HDR_DECODE_DECODE_ERR;
465
466 return 1;
467 }
468
ossl_quic_wire_encode_pkt_hdr(WPACKET * pkt,size_t short_conn_id_len,const QUIC_PKT_HDR * hdr,QUIC_PKT_HDR_PTRS * ptrs)469 int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
470 size_t short_conn_id_len,
471 const QUIC_PKT_HDR *hdr,
472 QUIC_PKT_HDR_PTRS *ptrs)
473 {
474 unsigned char b0;
475 size_t off_start, off_sample, off_pn;
476 unsigned char *start = WPACKET_get_curr(pkt);
477
478 if (!WPACKET_get_total_written(pkt, &off_start))
479 return 0;
480
481 if (ptrs != NULL) {
482 /* ptrs would not be stable on non-static WPACKET */
483 if (!ossl_assert(pkt->staticbuf != NULL))
484 return 0;
485 ptrs->raw_start = NULL;
486 ptrs->raw_sample = NULL;
487 ptrs->raw_sample_len = 0;
488 ptrs->raw_pn = 0;
489 }
490
491 /* Cannot serialize a partial header, or one whose DCID length is wrong. */
492 if (hdr->partial
493 || (hdr->type == QUIC_PKT_TYPE_1RTT
494 && hdr->dst_conn_id.id_len != short_conn_id_len))
495 return 0;
496
497 if (hdr->type == QUIC_PKT_TYPE_1RTT) {
498 /* Short header. */
499
500 /*
501 * Cannot serialize a header whose DCID length is wrong, or with an
502 * invalid PN length.
503 */
504 if (hdr->dst_conn_id.id_len != short_conn_id_len
505 || short_conn_id_len > QUIC_MAX_CONN_ID_LEN
506 || hdr->pn_len < 1 || hdr->pn_len > 4)
507 return 0;
508
509 b0 = (hdr->spin_bit << 5)
510 | (hdr->key_phase << 2)
511 | (hdr->pn_len - 1)
512 | (hdr->reserved << 3)
513 | 0x40; /* fixed bit */
514
515 if (!WPACKET_put_bytes_u8(pkt, b0)
516 || !WPACKET_memcpy(pkt, hdr->dst_conn_id.id, short_conn_id_len)
517 || !WPACKET_get_total_written(pkt, &off_pn)
518 || !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
519 return 0;
520 } else {
521 /* Long header. */
522 unsigned int raw_type;
523
524 if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
525 || hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
526 return 0;
527
528 if (ossl_quic_pkt_type_has_pn(hdr->type)
529 && (hdr->pn_len < 1 || hdr->pn_len > 4))
530 return 0;
531
532 switch (hdr->type) {
533 case QUIC_PKT_TYPE_VERSION_NEG:
534 if (hdr->version != 0)
535 return 0;
536
537 /* Version negotiation packets use zero for the type bits */
538 raw_type = 0;
539 break;
540
541 case QUIC_PKT_TYPE_INITIAL:
542 raw_type = 0;
543 break;
544 case QUIC_PKT_TYPE_0RTT:
545 raw_type = 1;
546 break;
547 case QUIC_PKT_TYPE_HANDSHAKE:
548 raw_type = 2;
549 break;
550 case QUIC_PKT_TYPE_RETRY:
551 raw_type = 3;
552 break;
553 default:
554 return 0;
555 }
556
557 b0 = (raw_type << 4) | 0x80; /* long */
558 if (hdr->type != QUIC_PKT_TYPE_VERSION_NEG || hdr->fixed)
559 b0 |= 0x40; /* fixed */
560 if (ossl_quic_pkt_type_has_pn(hdr->type)) {
561 b0 |= hdr->pn_len - 1;
562 b0 |= (hdr->reserved << 2);
563 }
564 if (hdr->type == QUIC_PKT_TYPE_RETRY)
565 b0 |= hdr->unused;
566
567 if (!WPACKET_put_bytes_u8(pkt, b0)
568 || !WPACKET_put_bytes_u32(pkt, hdr->version)
569 || !WPACKET_put_bytes_u8(pkt, hdr->dst_conn_id.id_len)
570 || !WPACKET_memcpy(pkt, hdr->dst_conn_id.id,
571 hdr->dst_conn_id.id_len)
572 || !WPACKET_put_bytes_u8(pkt, hdr->src_conn_id.id_len)
573 || !WPACKET_memcpy(pkt, hdr->src_conn_id.id,
574 hdr->src_conn_id.id_len))
575 return 0;
576
577 if (hdr->type == QUIC_PKT_TYPE_VERSION_NEG) {
578 if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
579 return 0;
580
581 return 1;
582 }
583
584 if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
585 if (!WPACKET_quic_write_vlint(pkt, hdr->token_len)
586 || !WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
587 return 0;
588 }
589
590 if (hdr->type == QUIC_PKT_TYPE_RETRY) {
591 if (!WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
592 return 0;
593 return 1;
594 }
595
596 if (!WPACKET_quic_write_vlint(pkt, hdr->len + hdr->pn_len)
597 || !WPACKET_get_total_written(pkt, &off_pn)
598 || !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
599 return 0;
600 }
601
602 if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
603 return 0;
604
605 off_sample = off_pn + 4;
606
607 if (ptrs != NULL) {
608 ptrs->raw_start = start;
609 ptrs->raw_sample = start + (off_sample - off_start);
610 ptrs->raw_sample_len
611 = WPACKET_get_curr(pkt) + hdr->len - ptrs->raw_sample;
612 ptrs->raw_pn = start + (off_pn - off_start);
613 }
614
615 return 1;
616 }
617
ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,const QUIC_PKT_HDR * hdr)618 int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
619 const QUIC_PKT_HDR *hdr)
620 {
621 size_t len = 0, enclen;
622
623 /* Cannot serialize a partial header, or one whose DCID length is wrong. */
624 if (hdr->partial
625 || (hdr->type == QUIC_PKT_TYPE_1RTT
626 && hdr->dst_conn_id.id_len != short_conn_id_len))
627 return 0;
628
629 if (hdr->type == QUIC_PKT_TYPE_1RTT) {
630 /* Short header. */
631
632 /*
633 * Cannot serialize a header whose DCID length is wrong, or with an
634 * invalid PN length.
635 */
636 if (hdr->dst_conn_id.id_len != short_conn_id_len
637 || short_conn_id_len > QUIC_MAX_CONN_ID_LEN
638 || hdr->pn_len < 1 || hdr->pn_len > 4)
639 return 0;
640
641 return 1 + short_conn_id_len + hdr->pn_len;
642 } else {
643 /* Long header. */
644 if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
645 || hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
646 return 0;
647
648 len += 1 /* Initial byte */ + 4 /* Version */
649 + 1 + hdr->dst_conn_id.id_len /* DCID Len, DCID */
650 + 1 + hdr->src_conn_id.id_len /* SCID Len, SCID */
651 ;
652
653 if (ossl_quic_pkt_type_has_pn(hdr->type)) {
654 if (hdr->pn_len < 1 || hdr->pn_len > 4)
655 return 0;
656
657 len += hdr->pn_len;
658 }
659
660 if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
661 enclen = ossl_quic_vlint_encode_len(hdr->token_len);
662 if (!enclen)
663 return 0;
664
665 len += enclen + hdr->token_len;
666 }
667
668 if (!ossl_quic_pkt_type_must_be_last(hdr->type)) {
669 enclen = ossl_quic_vlint_encode_len(hdr->len + hdr->pn_len);
670 if (!enclen)
671 return 0;
672
673 len += enclen;
674 }
675
676 return len;
677 }
678 }
679
ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char * buf,size_t buf_len,size_t short_conn_id_len,QUIC_CONN_ID * dst_conn_id)680 int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf,
681 size_t buf_len,
682 size_t short_conn_id_len,
683 QUIC_CONN_ID *dst_conn_id)
684 {
685 unsigned char b0;
686 size_t blen;
687
688 if (buf_len < QUIC_MIN_VALID_PKT_LEN
689 || short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
690 return 0;
691
692 b0 = buf[0];
693 if ((b0 & 0x80) != 0) {
694 /*
695 * Long header. We need 6 bytes (initial byte, 4 version bytes, DCID
696 * length byte to begin with). This is covered by the buf_len test
697 * above.
698 */
699
700 /*
701 * If the version field is non-zero (meaning that this is not a Version
702 * Negotiation packet), the fixed bit must be set.
703 */
704 if ((buf[1] || buf[2] || buf[3] || buf[4]) && (b0 & 0x40) == 0)
705 return 0;
706
707 blen = (size_t)buf[5]; /* DCID Length */
708 if (blen > QUIC_MAX_CONN_ID_LEN
709 || buf_len < QUIC_MIN_VALID_PKT_LEN + blen)
710 return 0;
711
712 dst_conn_id->id_len = (unsigned char)blen;
713 memcpy(dst_conn_id->id, buf + 6, blen);
714 return 1;
715 } else {
716 /* Short header. */
717 if ((b0 & 0x40) == 0)
718 /* Fixed bit not set, not a valid QUIC packet header. */
719 return 0;
720
721 if (buf_len < QUIC_MIN_VALID_PKT_LEN_CRYPTO + short_conn_id_len)
722 return 0;
723
724 dst_conn_id->id_len = (unsigned char)short_conn_id_len;
725 memcpy(dst_conn_id->id, buf + 1, short_conn_id_len);
726 return 1;
727 }
728 }
729
ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char * enc_pn,size_t enc_pn_len,QUIC_PN largest_pn,QUIC_PN * res_pn)730 int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn,
731 size_t enc_pn_len,
732 QUIC_PN largest_pn,
733 QUIC_PN *res_pn)
734 {
735 int64_t expected_pn, truncated_pn, candidate_pn, pn_win, pn_hwin, pn_mask;
736
737 switch (enc_pn_len) {
738 case 1:
739 truncated_pn = enc_pn[0];
740 break;
741 case 2:
742 truncated_pn = ((QUIC_PN)enc_pn[0] << 8)
743 | (QUIC_PN)enc_pn[1];
744 break;
745 case 3:
746 truncated_pn = ((QUIC_PN)enc_pn[0] << 16)
747 | ((QUIC_PN)enc_pn[1] << 8)
748 | (QUIC_PN)enc_pn[2];
749 break;
750 case 4:
751 truncated_pn = ((QUIC_PN)enc_pn[0] << 24)
752 | ((QUIC_PN)enc_pn[1] << 16)
753 | ((QUIC_PN)enc_pn[2] << 8)
754 | (QUIC_PN)enc_pn[3];
755 break;
756 default:
757 return 0;
758 }
759
760 /* Implemented as per RFC 9000 Section A.3. */
761 expected_pn = largest_pn + 1;
762 pn_win = ((int64_t)1) << (enc_pn_len * 8);
763 pn_hwin = pn_win / 2;
764 pn_mask = pn_win - 1;
765 candidate_pn = (expected_pn & ~pn_mask) | truncated_pn;
766 if (candidate_pn <= expected_pn - pn_hwin
767 && candidate_pn < (((int64_t)1) << 62) - pn_win)
768 *res_pn = candidate_pn + pn_win;
769 else if (candidate_pn > expected_pn + pn_hwin
770 && candidate_pn >= pn_win)
771 *res_pn = candidate_pn - pn_win;
772 else
773 *res_pn = candidate_pn;
774 return 1;
775 }
776
777 /* From RFC 9000 Section A.2. Simplified implementation. */
ossl_quic_wire_determine_pn_len(QUIC_PN pn,QUIC_PN largest_acked)778 int ossl_quic_wire_determine_pn_len(QUIC_PN pn,
779 QUIC_PN largest_acked)
780 {
781 uint64_t num_unacked
782 = (largest_acked == QUIC_PN_INVALID) ? pn + 1 : pn - largest_acked;
783
784 /*
785 * num_unacked \in [ 0, 2** 7] -> 1 byte
786 * num_unacked \in (2** 7, 2**15] -> 2 bytes
787 * num_unacked \in (2**15, 2**23] -> 3 bytes
788 * num_unacked \in (2**23, ] -> 4 bytes
789 */
790
791 if (num_unacked <= (1U << 7))
792 return 1;
793 if (num_unacked <= (1U << 15))
794 return 2;
795 if (num_unacked <= (1U << 23))
796 return 3;
797 return 4;
798 }
799
ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,unsigned char * enc_pn,size_t enc_pn_len)800 int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
801 unsigned char *enc_pn,
802 size_t enc_pn_len)
803 {
804 switch (enc_pn_len) {
805 case 1:
806 enc_pn[0] = (unsigned char)pn;
807 break;
808 case 2:
809 enc_pn[1] = (unsigned char)pn;
810 enc_pn[0] = (unsigned char)(pn >> 8);
811 break;
812 case 3:
813 enc_pn[2] = (unsigned char)pn;
814 enc_pn[1] = (unsigned char)(pn >> 8);
815 enc_pn[0] = (unsigned char)(pn >> 16);
816 break;
817 case 4:
818 enc_pn[3] = (unsigned char)pn;
819 enc_pn[2] = (unsigned char)(pn >> 8);
820 enc_pn[1] = (unsigned char)(pn >> 16);
821 enc_pn[0] = (unsigned char)(pn >> 24);
822 break;
823 default:
824 return 0;
825 }
826
827 return 1;
828 }
829
ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX * libctx,const char * propq,const QUIC_PKT_HDR * hdr,const QUIC_CONN_ID * client_initial_dcid)830 int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
831 const char *propq,
832 const QUIC_PKT_HDR *hdr,
833 const QUIC_CONN_ID *client_initial_dcid)
834 {
835 unsigned char expected_tag[QUIC_RETRY_INTEGRITY_TAG_LEN];
836 const unsigned char *actual_tag;
837
838 if (hdr == NULL || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN)
839 return 0;
840
841 if (!ossl_quic_calculate_retry_integrity_tag(libctx, propq,
842 hdr, client_initial_dcid,
843 expected_tag))
844 return 0;
845
846 actual_tag = hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN;
847
848 return !CRYPTO_memcmp(expected_tag, actual_tag,
849 QUIC_RETRY_INTEGRITY_TAG_LEN);
850 }
851
852 /* RFC 9001 s. 5.8 */
853 static const unsigned char retry_integrity_key[] = {
854 0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
855 0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e
856 };
857
858 static const unsigned char retry_integrity_nonce[] = {
859 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2,
860 0x23, 0x98, 0x25, 0xbb
861 };
862
ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX * libctx,const char * propq,const QUIC_PKT_HDR * hdr,const QUIC_CONN_ID * client_initial_dcid,unsigned char * tag)863 int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
864 const char *propq,
865 const QUIC_PKT_HDR *hdr,
866 const QUIC_CONN_ID *client_initial_dcid,
867 unsigned char *tag)
868 {
869 EVP_CIPHER *cipher = NULL;
870 EVP_CIPHER_CTX *cctx = NULL;
871 int ok = 0, l = 0, l2 = 0, wpkt_valid = 0;
872 WPACKET wpkt;
873 /* Worst case length of the Retry Psuedo-Packet header is 68 bytes. */
874 unsigned char buf[128];
875 QUIC_PKT_HDR hdr2;
876 size_t hdr_enc_len = 0;
877
878 if (hdr->type != QUIC_PKT_TYPE_RETRY || hdr->version == 0
879 || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN
880 || hdr->data == NULL
881 || client_initial_dcid == NULL || tag == NULL
882 || client_initial_dcid->id_len > QUIC_MAX_CONN_ID_LEN) {
883 ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
884 goto err;
885 }
886
887 /*
888 * Do not reserve packet body in WPACKET. Retry packet header
889 * does not contain a Length field so this does not affect
890 * the serialized packet header.
891 */
892 hdr2 = *hdr;
893 hdr2.len = 0;
894
895 /* Assemble retry psuedo-packet. */
896 if (!WPACKET_init_static_len(&wpkt, buf, sizeof(buf), 0)) {
897 ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
898 goto err;
899 }
900
901 wpkt_valid = 1;
902
903 /* Prepend original DCID to the packet. */
904 if (!WPACKET_put_bytes_u8(&wpkt, client_initial_dcid->id_len)
905 || !WPACKET_memcpy(&wpkt, client_initial_dcid->id,
906 client_initial_dcid->id_len)) {
907 ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
908 goto err;
909 }
910
911 /* Encode main retry header. */
912 if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr2.dst_conn_id.id_len,
913 &hdr2, NULL))
914 goto err;
915
916 if (!WPACKET_get_total_written(&wpkt, &hdr_enc_len)) {
917 ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
918 goto err;
919 }
920
921 /* Create and initialise cipher context. */
922 /* TODO(QUIC FUTURE): Cipher fetch caching. */
923 if ((cipher = EVP_CIPHER_fetch(libctx, "AES-128-GCM", propq)) == NULL) {
924 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
925 goto err;
926 }
927
928 if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
929 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
930 goto err;
931 }
932
933 if (!EVP_CipherInit_ex(cctx, cipher, NULL,
934 retry_integrity_key, retry_integrity_nonce, /*enc=*/1)) {
935 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
936 goto err;
937 }
938
939 /* Feed packet header as AAD data. */
940 if (EVP_CipherUpdate(cctx, NULL, &l, buf, hdr_enc_len) != 1) {
941 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
942 goto err;
943 }
944
945 /* Feed packet body as AAD data. */
946 if (EVP_CipherUpdate(cctx, NULL, &l, hdr->data,
947 hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN)
948 != 1) {
949 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
950 goto err;
951 }
952
953 /* Finalise and get tag. */
954 if (EVP_CipherFinal_ex(cctx, NULL, &l2) != 1) {
955 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
956 goto err;
957 }
958
959 if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG,
960 QUIC_RETRY_INTEGRITY_TAG_LEN,
961 tag)
962 != 1) {
963 ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
964 goto err;
965 }
966
967 ok = 1;
968 err:
969 EVP_CIPHER_free(cipher);
970 EVP_CIPHER_CTX_free(cctx);
971 if (wpkt_valid)
972 WPACKET_finish(&wpkt);
973
974 return ok;
975 }
976