xref: /freebsd/crypto/openssl/ssl/quic/quic_wire_pkt.c (revision e7be843b4a162e68651d3911f0357ed464915629)
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:     raw_type = 0; break;
542             case QUIC_PKT_TYPE_0RTT:        raw_type = 1; break;
543             case QUIC_PKT_TYPE_HANDSHAKE:   raw_type = 2; break;
544             case QUIC_PKT_TYPE_RETRY:       raw_type = 3; break;
545             default:
546                 return 0;
547         }
548 
549         b0 = (raw_type << 4) | 0x80; /* long */
550         if (hdr->type != QUIC_PKT_TYPE_VERSION_NEG || hdr->fixed)
551             b0 |= 0x40; /* fixed */
552         if (ossl_quic_pkt_type_has_pn(hdr->type)) {
553             b0 |= hdr->pn_len - 1;
554             b0 |= (hdr->reserved << 2);
555         }
556         if (hdr->type == QUIC_PKT_TYPE_RETRY)
557             b0 |= hdr->unused;
558 
559         if (!WPACKET_put_bytes_u8(pkt, b0)
560             || !WPACKET_put_bytes_u32(pkt, hdr->version)
561             || !WPACKET_put_bytes_u8(pkt, hdr->dst_conn_id.id_len)
562             || !WPACKET_memcpy(pkt, hdr->dst_conn_id.id,
563                                hdr->dst_conn_id.id_len)
564             || !WPACKET_put_bytes_u8(pkt, hdr->src_conn_id.id_len)
565             || !WPACKET_memcpy(pkt, hdr->src_conn_id.id,
566                                hdr->src_conn_id.id_len))
567             return 0;
568 
569         if (hdr->type == QUIC_PKT_TYPE_VERSION_NEG) {
570             if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
571                 return 0;
572 
573             return 1;
574         }
575 
576         if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
577             if (!WPACKET_quic_write_vlint(pkt, hdr->token_len)
578                 || !WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
579                 return 0;
580         }
581 
582         if (hdr->type == QUIC_PKT_TYPE_RETRY) {
583             if (!WPACKET_memcpy(pkt, hdr->token, hdr->token_len))
584                 return 0;
585             return 1;
586         }
587 
588         if (!WPACKET_quic_write_vlint(pkt, hdr->len + hdr->pn_len)
589             || !WPACKET_get_total_written(pkt, &off_pn)
590             || !WPACKET_memcpy(pkt, hdr->pn, hdr->pn_len))
591             return 0;
592     }
593 
594     if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
595         return 0;
596 
597     off_sample = off_pn + 4;
598 
599     if (ptrs != NULL) {
600         ptrs->raw_start         = start;
601         ptrs->raw_sample        = start + (off_sample - off_start);
602         ptrs->raw_sample_len
603             = WPACKET_get_curr(pkt) + hdr->len - ptrs->raw_sample;
604         ptrs->raw_pn            = start + (off_pn - off_start);
605     }
606 
607     return 1;
608 }
609 
ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,const QUIC_PKT_HDR * hdr)610 int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
611                                            const QUIC_PKT_HDR *hdr)
612 {
613     size_t len = 0, enclen;
614 
615     /* Cannot serialize a partial header, or one whose DCID length is wrong. */
616     if (hdr->partial
617         || (hdr->type == QUIC_PKT_TYPE_1RTT
618             && hdr->dst_conn_id.id_len != short_conn_id_len))
619         return 0;
620 
621     if (hdr->type == QUIC_PKT_TYPE_1RTT) {
622         /* Short header. */
623 
624         /*
625          * Cannot serialize a header whose DCID length is wrong, or with an
626          * invalid PN length.
627          */
628         if (hdr->dst_conn_id.id_len != short_conn_id_len
629             || short_conn_id_len > QUIC_MAX_CONN_ID_LEN
630             || hdr->pn_len < 1 || hdr->pn_len > 4)
631             return 0;
632 
633         return 1 + short_conn_id_len + hdr->pn_len;
634     } else {
635         /* Long header. */
636         if (hdr->dst_conn_id.id_len > QUIC_MAX_CONN_ID_LEN
637             || hdr->src_conn_id.id_len > QUIC_MAX_CONN_ID_LEN)
638             return 0;
639 
640         len += 1 /* Initial byte */ + 4 /* Version */
641             + 1 + hdr->dst_conn_id.id_len /* DCID Len, DCID */
642             + 1 + hdr->src_conn_id.id_len /* SCID Len, SCID */
643             ;
644 
645         if (ossl_quic_pkt_type_has_pn(hdr->type)) {
646             if (hdr->pn_len < 1 || hdr->pn_len > 4)
647                 return 0;
648 
649             len += hdr->pn_len;
650         }
651 
652         if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
653             enclen = ossl_quic_vlint_encode_len(hdr->token_len);
654             if (!enclen)
655                 return 0;
656 
657             len += enclen + hdr->token_len;
658         }
659 
660         if (!ossl_quic_pkt_type_must_be_last(hdr->type)) {
661             enclen = ossl_quic_vlint_encode_len(hdr->len + hdr->pn_len);
662             if (!enclen)
663                 return 0;
664 
665             len += enclen;
666         }
667 
668         return len;
669     }
670 }
671 
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)672 int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf,
673                                            size_t buf_len,
674                                            size_t short_conn_id_len,
675                                            QUIC_CONN_ID *dst_conn_id)
676 {
677     unsigned char b0;
678     size_t blen;
679 
680     if (buf_len < QUIC_MIN_VALID_PKT_LEN
681         || short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
682         return 0;
683 
684     b0 = buf[0];
685     if ((b0 & 0x80) != 0) {
686         /*
687          * Long header. We need 6 bytes (initial byte, 4 version bytes, DCID
688          * length byte to begin with). This is covered by the buf_len test
689          * above.
690          */
691 
692         /*
693          * If the version field is non-zero (meaning that this is not a Version
694          * Negotiation packet), the fixed bit must be set.
695          */
696         if ((buf[1] || buf[2] || buf[3] || buf[4]) && (b0 & 0x40) == 0)
697             return 0;
698 
699         blen = (size_t)buf[5]; /* DCID Length */
700         if (blen > QUIC_MAX_CONN_ID_LEN
701             || buf_len < QUIC_MIN_VALID_PKT_LEN + blen)
702             return 0;
703 
704         dst_conn_id->id_len = (unsigned char)blen;
705         memcpy(dst_conn_id->id, buf + 6, blen);
706         return 1;
707     } else {
708         /* Short header. */
709         if ((b0 & 0x40) == 0)
710             /* Fixed bit not set, not a valid QUIC packet header. */
711             return 0;
712 
713         if (buf_len < QUIC_MIN_VALID_PKT_LEN_CRYPTO + short_conn_id_len)
714             return 0;
715 
716         dst_conn_id->id_len = (unsigned char)short_conn_id_len;
717         memcpy(dst_conn_id->id, buf + 1, short_conn_id_len);
718         return 1;
719     }
720 }
721 
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)722 int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn,
723                                      size_t enc_pn_len,
724                                      QUIC_PN largest_pn,
725                                      QUIC_PN *res_pn)
726 {
727     int64_t expected_pn, truncated_pn, candidate_pn, pn_win, pn_hwin, pn_mask;
728 
729     switch (enc_pn_len) {
730         case 1:
731             truncated_pn = enc_pn[0];
732             break;
733         case 2:
734             truncated_pn = ((QUIC_PN)enc_pn[0] << 8)
735                          |  (QUIC_PN)enc_pn[1];
736             break;
737         case 3:
738             truncated_pn = ((QUIC_PN)enc_pn[0] << 16)
739                          | ((QUIC_PN)enc_pn[1] << 8)
740                          |  (QUIC_PN)enc_pn[2];
741             break;
742         case 4:
743             truncated_pn = ((QUIC_PN)enc_pn[0] << 24)
744                          | ((QUIC_PN)enc_pn[1] << 16)
745                          | ((QUIC_PN)enc_pn[2] << 8)
746                          |  (QUIC_PN)enc_pn[3];
747             break;
748         default:
749             return 0;
750     }
751 
752     /* Implemented as per RFC 9000 Section A.3. */
753     expected_pn     = largest_pn + 1;
754     pn_win          = ((int64_t)1) << (enc_pn_len * 8);
755     pn_hwin         = pn_win / 2;
756     pn_mask         = pn_win - 1;
757     candidate_pn    = (expected_pn & ~pn_mask) | truncated_pn;
758     if (candidate_pn <= expected_pn - pn_hwin
759         && candidate_pn < (((int64_t)1) << 62) - pn_win)
760         *res_pn = candidate_pn + pn_win;
761     else if (candidate_pn > expected_pn + pn_hwin
762              && candidate_pn >= pn_win)
763         *res_pn = candidate_pn - pn_win;
764     else
765         *res_pn = candidate_pn;
766     return 1;
767 }
768 
769 /* From RFC 9000 Section A.2. Simplified implementation. */
ossl_quic_wire_determine_pn_len(QUIC_PN pn,QUIC_PN largest_acked)770 int ossl_quic_wire_determine_pn_len(QUIC_PN pn,
771                                     QUIC_PN largest_acked)
772 {
773     uint64_t num_unacked
774         = (largest_acked == QUIC_PN_INVALID) ? pn + 1 : pn - largest_acked;
775 
776     /*
777      * num_unacked \in [    0, 2** 7] -> 1 byte
778      * num_unacked \in (2** 7, 2**15] -> 2 bytes
779      * num_unacked \in (2**15, 2**23] -> 3 bytes
780      * num_unacked \in (2**23,      ] -> 4 bytes
781      */
782 
783     if (num_unacked <= (1U<<7))  return 1;
784     if (num_unacked <= (1U<<15)) return 2;
785     if (num_unacked <= (1U<<23)) return 3;
786     return 4;
787 }
788 
ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,unsigned char * enc_pn,size_t enc_pn_len)789 int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
790                                      unsigned char *enc_pn,
791                                      size_t enc_pn_len)
792 {
793     switch (enc_pn_len) {
794         case 1:
795             enc_pn[0] = (unsigned char)pn;
796             break;
797         case 2:
798             enc_pn[1] = (unsigned char)pn;
799             enc_pn[0] = (unsigned char)(pn >> 8);
800             break;
801         case 3:
802             enc_pn[2] = (unsigned char)pn;
803             enc_pn[1] = (unsigned char)(pn >> 8);
804             enc_pn[0] = (unsigned char)(pn >> 16);
805             break;
806         case 4:
807             enc_pn[3] = (unsigned char)pn;
808             enc_pn[2] = (unsigned char)(pn >> 8);
809             enc_pn[1] = (unsigned char)(pn >> 16);
810             enc_pn[0] = (unsigned char)(pn >> 24);
811             break;
812         default:
813             return 0;
814     }
815 
816     return 1;
817 }
818 
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)819 int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
820                                            const char *propq,
821                                            const QUIC_PKT_HDR *hdr,
822                                            const QUIC_CONN_ID *client_initial_dcid)
823 {
824     unsigned char expected_tag[QUIC_RETRY_INTEGRITY_TAG_LEN];
825     const unsigned char *actual_tag;
826 
827     if (hdr == NULL || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN)
828         return 0;
829 
830     if (!ossl_quic_calculate_retry_integrity_tag(libctx, propq,
831                                                  hdr, client_initial_dcid,
832                                                  expected_tag))
833         return 0;
834 
835     actual_tag = hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN;
836 
837     return !CRYPTO_memcmp(expected_tag, actual_tag,
838                           QUIC_RETRY_INTEGRITY_TAG_LEN);
839 }
840 
841 /* RFC 9001 s. 5.8 */
842 static const unsigned char retry_integrity_key[] = {
843     0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
844     0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e
845 };
846 
847 static const unsigned char retry_integrity_nonce[] = {
848     0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2,
849     0x23, 0x98, 0x25, 0xbb
850 };
851 
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)852 int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
853                                             const char *propq,
854                                             const QUIC_PKT_HDR *hdr,
855                                             const QUIC_CONN_ID *client_initial_dcid,
856                                             unsigned char *tag)
857 {
858     EVP_CIPHER *cipher = NULL;
859     EVP_CIPHER_CTX *cctx = NULL;
860     int ok = 0, l = 0, l2 = 0, wpkt_valid = 0;
861     WPACKET wpkt;
862     /* Worst case length of the Retry Psuedo-Packet header is 68 bytes. */
863     unsigned char buf[128];
864     QUIC_PKT_HDR hdr2;
865     size_t hdr_enc_len = 0;
866 
867     if (hdr->type != QUIC_PKT_TYPE_RETRY || hdr->version == 0
868         || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN
869         || hdr->data == NULL
870         || client_initial_dcid == NULL || tag == NULL
871         || client_initial_dcid->id_len > QUIC_MAX_CONN_ID_LEN) {
872         ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT);
873         goto err;
874     }
875 
876     /*
877      * Do not reserve packet body in WPACKET. Retry packet header
878      * does not contain a Length field so this does not affect
879      * the serialized packet header.
880      */
881     hdr2 = *hdr;
882     hdr2.len = 0;
883 
884     /* Assemble retry psuedo-packet. */
885     if (!WPACKET_init_static_len(&wpkt, buf, sizeof(buf), 0)) {
886         ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
887         goto err;
888     }
889 
890     wpkt_valid = 1;
891 
892     /* Prepend original DCID to the packet. */
893     if (!WPACKET_put_bytes_u8(&wpkt, client_initial_dcid->id_len)
894         || !WPACKET_memcpy(&wpkt, client_initial_dcid->id,
895                            client_initial_dcid->id_len)) {
896         ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
897         goto err;
898     }
899 
900     /* Encode main retry header. */
901     if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr2.dst_conn_id.id_len,
902                                        &hdr2, NULL))
903         goto err;
904 
905     if (!WPACKET_get_total_written(&wpkt, &hdr_enc_len)) {
906         ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
907         goto err;
908     }
909 
910     /* Create and initialise cipher context. */
911     /* TODO(QUIC FUTURE): Cipher fetch caching. */
912     if ((cipher = EVP_CIPHER_fetch(libctx, "AES-128-GCM", propq)) == NULL) {
913         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
914         goto err;
915     }
916 
917     if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
918         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
919         goto err;
920     }
921 
922     if (!EVP_CipherInit_ex(cctx, cipher, NULL,
923                            retry_integrity_key, retry_integrity_nonce, /*enc=*/1)) {
924         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
925         goto err;
926     }
927 
928     /* Feed packet header as AAD data. */
929     if (EVP_CipherUpdate(cctx, NULL, &l, buf, hdr_enc_len) != 1) {
930         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
931         goto err;
932     }
933 
934     /* Feed packet body as AAD data. */
935     if (EVP_CipherUpdate(cctx, NULL, &l, hdr->data,
936                          hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) != 1) {
937         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
938         goto err;
939     }
940 
941     /* Finalise and get tag. */
942     if (EVP_CipherFinal_ex(cctx, NULL, &l2) != 1) {
943         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
944         goto err;
945     }
946 
947     if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG,
948                             QUIC_RETRY_INTEGRITY_TAG_LEN,
949                             tag) != 1) {
950         ERR_raise(ERR_LIB_SSL, ERR_R_EVP_LIB);
951         goto err;
952     }
953 
954     ok = 1;
955 err:
956     EVP_CIPHER_free(cipher);
957     EVP_CIPHER_CTX_free(cctx);
958     if (wpkt_valid)
959         WPACKET_finish(&wpkt);
960 
961     return ok;
962 }
963