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