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