xref: /freebsd/crypto/openssl/ssl/quic/quic_wire_pkt.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
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