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