blob: f8d11a305e29fd1ac70952f0719dd1fb094e767a [file] [log] [blame]
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001#include <string.h>
2
3#include <openssl/ssl.h>
4
5#if defined(OPENSSL_IS_BORINGSSL)
6#include <openssl/hkdf.h>
7#else
8#include <openssl/evp.h>
9#include <openssl/kdf.h>
10#endif
11
12#include <haproxy/buf.h>
13#include <haproxy/chunk.h>
14//#include <haproxy/quic_tls-t.h>
15#include <haproxy/xprt_quic.h>
16
17
Frédéric Lécaillefc768ec2021-11-23 21:02:04 +010018DECLARE_POOL(pool_head_quic_tls_secret, "quic_tls_secret", QUIC_TLS_SECRET_LEN);
19DECLARE_POOL(pool_head_quic_tls_iv, "quic_tls_iv", QUIC_TLS_IV_LEN);
20DECLARE_POOL(pool_head_quic_tls_key, "quic_tls_key", QUIC_TLS_KEY_LEN);
21
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010022__attribute__((format (printf, 3, 4)))
23void hexdump(const void *buf, size_t buflen, const char *title_fmt, ...);
24
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010025/* Dump the RX/TX secrets of <secs> QUIC TLS secrets. */
Amaury Denoyelle4fd53d72021-12-21 14:28:26 +010026void quic_tls_keys_hexdump(struct buffer *buf,
27 const struct quic_tls_secrets *secs)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010028{
29 int i;
30 size_t aead_keylen = (size_t)EVP_CIPHER_key_length(secs->aead);
31 size_t aead_ivlen = (size_t)EVP_CIPHER_iv_length(secs->aead);
32 size_t hp_len = (size_t)EVP_CIPHER_key_length(secs->hp);
33
34 chunk_appendf(buf, "\n key=");
35 for (i = 0; i < aead_keylen; i++)
36 chunk_appendf(buf, "%02x", secs->key[i]);
37 chunk_appendf(buf, "\n iv=");
38 for (i = 0; i < aead_ivlen; i++)
39 chunk_appendf(buf, "%02x", secs->iv[i]);
40 chunk_appendf(buf, "\n hp=");
41 for (i = 0; i < hp_len; i++)
42 chunk_appendf(buf, "%02x", secs->hp_key[i]);
43}
44
45/* Dump <secret> TLS secret. */
46void quic_tls_secret_hexdump(struct buffer *buf,
47 const unsigned char *secret, size_t secret_len)
48{
49 int i;
50
51 chunk_appendf(buf, " secret=");
52 for (i = 0; i < secret_len; i++)
53 chunk_appendf(buf, "%02x", secret[i]);
54}
55
56#if defined(OPENSSL_IS_BORINGSSL)
57int quic_hkdf_extract(const EVP_MD *md,
58 unsigned char *buf, size_t *buflen,
59 const unsigned char *key, size_t keylen,
Frédéric Lécaille2fc76cf2021-08-31 19:10:40 +020060 const unsigned char *salt, size_t saltlen)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010061{
62 return HKDF_extract(buf, buflen, md, key, keylen, salt, saltlen);
63}
64
65int quic_hkdf_expand(const EVP_MD *md,
66 unsigned char *buf, size_t buflen,
67 const unsigned char *key, size_t keylen,
68 const unsigned char *label, size_t labellen)
69{
70 return HKDF_expand(buf, buflen, md, key, keylen, label, labellen);
71}
72#else
73int quic_hkdf_extract(const EVP_MD *md,
74 unsigned char *buf, size_t *buflen,
75 const unsigned char *key, size_t keylen,
Frédéric Lécaille2fc76cf2021-08-31 19:10:40 +020076 const unsigned char *salt, size_t saltlen)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010077{
78 EVP_PKEY_CTX *ctx;
79
80 ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
81 if (!ctx)
82 return 0;
83
84 if (EVP_PKEY_derive_init(ctx) <= 0 ||
85 EVP_PKEY_CTX_hkdf_mode(ctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) <= 0 ||
86 EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0 ||
87 EVP_PKEY_CTX_set1_hkdf_salt(ctx, salt, saltlen) <= 0 ||
88 EVP_PKEY_CTX_set1_hkdf_key(ctx, key, keylen) <= 0 ||
89 EVP_PKEY_derive(ctx, buf, buflen) <= 0)
90 goto err;
91
92 EVP_PKEY_CTX_free(ctx);
93 return 1;
94
95 err:
96 EVP_PKEY_CTX_free(ctx);
97 return 0;
98}
99
100int quic_hkdf_expand(const EVP_MD *md,
101 unsigned char *buf, size_t buflen,
102 const unsigned char *key, size_t keylen,
103 const unsigned char *label, size_t labellen)
104{
105 EVP_PKEY_CTX *ctx;
106
107 ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
108 if (!ctx)
109 return 0;
110
111 if (EVP_PKEY_derive_init(ctx) <= 0 ||
112 EVP_PKEY_CTX_hkdf_mode(ctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) <= 0 ||
113 EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0 ||
114 EVP_PKEY_CTX_set1_hkdf_key(ctx, key, keylen) <= 0 ||
115 EVP_PKEY_CTX_add1_hkdf_info(ctx, label, labellen) <= 0 ||
116 EVP_PKEY_derive(ctx, buf, &buflen) <= 0)
117 goto err;
118
119 EVP_PKEY_CTX_free(ctx);
120 return 1;
121
122 err:
123 EVP_PKEY_CTX_free(ctx);
124 return 0;
125}
126#endif
127
128/* https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#protection-keys
129 * refers to:
130 *
131 * https://tools.ietf.org/html/rfc8446#section-7.1:
132 * 7.1. Key Schedule
133 *
134 * The key derivation process makes use of the HKDF-Extract and
135 * HKDF-Expand functions as defined for HKDF [RFC5869], as well as the
136 * functions defined below:
137 *
138 * HKDF-Expand-Label(Secret, Label, Context, Length) =
139 * HKDF-Expand(Secret, HkdfLabel, Length)
140 *
141 * Where HkdfLabel is specified as:
142 *
143 * struct {
144 * uint16 length = Length;
145 * opaque label<7..255> = "tls13 " + Label;
146 * opaque context<0..255> = Context;
147 * } HkdfLabel;
148 *
149 * Derive-Secret(Secret, Label, Messages) =
150 * HKDF-Expand-Label(Secret, Label,
151 * Transcript-Hash(Messages), Hash.length)
152 *
153 */
154int quic_hkdf_expand_label(const EVP_MD *md,
155 unsigned char *buf, size_t buflen,
156 const unsigned char *key, size_t keylen,
157 const unsigned char *label, size_t labellen)
158{
159 unsigned char hdkf_label[256], *pos;
160 const unsigned char hdkf_label_label[] = "tls13 ";
161 size_t hdkf_label_label_sz = sizeof hdkf_label_label - 1;
162
163 pos = hdkf_label;
164 *pos++ = buflen >> 8;
165 *pos++ = buflen & 0xff;
166 *pos++ = hdkf_label_label_sz + labellen;
167 memcpy(pos, hdkf_label_label, hdkf_label_label_sz);
168 pos += hdkf_label_label_sz;
169 memcpy(pos, label, labellen);
170 pos += labellen;
171 *pos++ = '\0';
172
173 return quic_hkdf_expand(md, buf, buflen,
174 key, keylen, hdkf_label, pos - hdkf_label);
175}
176
177/*
178 * This function derives two keys from <secret> is <ctx> as TLS cryptographic context.
179 * ->key is the TLS key to be derived to encrypt/decrypt data at TLS level.
180 * ->iv is the initialization vector to be used with ->key.
181 * ->hp_key is the key to be derived for header protection.
182 * Obviouly these keys have the same size becaused derived with the same TLS cryptographic context.
183 */
184int quic_tls_derive_keys(const EVP_CIPHER *aead, const EVP_CIPHER *hp,
185 const EVP_MD *md,
186 unsigned char *key, size_t keylen,
187 unsigned char *iv, size_t ivlen,
188 unsigned char *hp_key, size_t hp_keylen,
189 const unsigned char *secret, size_t secretlen)
190{
191 size_t aead_keylen = (size_t)EVP_CIPHER_key_length(aead);
192 size_t aead_ivlen = (size_t)EVP_CIPHER_iv_length(aead);
Frédéric Lécaille6e351d62021-11-30 11:06:41 +0100193 size_t hp_len = hp ? (size_t)EVP_CIPHER_key_length(hp) : 0;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100194 const unsigned char key_label[] = "quic key";
195 const unsigned char iv_label[] = "quic iv";
196 const unsigned char hp_key_label[] = "quic hp";
197
198 if (aead_keylen > keylen || aead_ivlen > ivlen || hp_len > hp_keylen)
199 return 0;
200
201 if (!quic_hkdf_expand_label(md, key, aead_keylen, secret, secretlen,
202 key_label, sizeof key_label - 1) ||
203 !quic_hkdf_expand_label(md, iv, aead_ivlen, secret, secretlen,
204 iv_label, sizeof iv_label - 1) ||
Frédéric Lécaille6e351d62021-11-30 11:06:41 +0100205 (hp_key && !quic_hkdf_expand_label(md, hp_key, hp_len, secret, secretlen,
206 hp_key_label, sizeof hp_key_label - 1)))
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100207 return 0;
208
209 return 1;
210}
211
212/*
213 * Derive the initial secret from <secret> and QUIC version dependent salt.
214 * Returns the size of the derived secret if succeeded, 0 if not.
215 */
216int quic_derive_initial_secret(const EVP_MD *md,
Frédéric Lécaille2fc76cf2021-08-31 19:10:40 +0200217 const unsigned char *initial_salt, size_t initial_salt_sz,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100218 unsigned char *initial_secret, size_t initial_secret_sz,
219 const unsigned char *secret, size_t secret_sz)
220{
221 if (!quic_hkdf_extract(md, initial_secret, &initial_secret_sz, secret, secret_sz,
Frédéric Lécaille2fc76cf2021-08-31 19:10:40 +0200222 initial_salt, initial_salt_sz))
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100223 return 0;
224
225 return 1;
226}
227
228/*
229 * Derive the client initial secret from the initial secret.
230 * Returns the size of the derived secret if succeeded, 0 if not.
231 */
232int quic_tls_derive_initial_secrets(const EVP_MD *md,
233 unsigned char *rx, size_t rx_sz,
234 unsigned char *tx, size_t tx_sz,
235 const unsigned char *secret, size_t secret_sz,
236 int server)
237{
238 const unsigned char client_label[] = "client in";
239 const unsigned char server_label[] = "server in";
240 const unsigned char *tx_label, *rx_label;
241 size_t rx_label_sz, tx_label_sz;
242
243 if (server) {
244 rx_label = client_label;
245 rx_label_sz = sizeof client_label;
246 tx_label = server_label;
247 tx_label_sz = sizeof server_label;
248 }
249 else {
250 rx_label = server_label;
251 rx_label_sz = sizeof server_label;
252 tx_label = client_label;
253 tx_label_sz = sizeof client_label;
254 }
255
256 if (!quic_hkdf_expand_label(md, rx, rx_sz, secret, secret_sz,
257 rx_label, rx_label_sz - 1) ||
258 !quic_hkdf_expand_label(md, tx, tx_sz, secret, secret_sz,
259 tx_label, tx_label_sz - 1))
260 return 0;
261
262 return 1;
263}
264
Frédéric Lécaille39484de2021-11-30 10:10:24 +0100265/* Update <sec> secret key into <new_sec> according to RFC 9001 6.1.
266 * Always succeeds.
267 */
268int quic_tls_sec_update(const EVP_MD *md,
269 unsigned char *new_sec, size_t new_seclen,
270 const unsigned char *sec, size_t seclen)
271{
272 const unsigned char ku_label[] = "quic ku";
273
274 return quic_hkdf_expand_label(md, new_sec, new_seclen, sec, seclen,
275 ku_label, sizeof ku_label - 1);
276}
277
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100278/*
279 * Build an IV into <iv> buffer with <ivlen> as size from <aead_iv> with
280 * <aead_ivlen> as size depending on <pn> packet number.
281 * This is the function which must be called to build an AEAD IV for the AEAD cryptographic algorithm
282 * used to encrypt/decrypt the QUIC packet payloads depending on the packet number <pn>.
283 * This function fails and return 0 only if the two buffer lengths are different, 1 if not.
284 */
285int quic_aead_iv_build(unsigned char *iv, size_t ivlen,
286 unsigned char *aead_iv, size_t aead_ivlen, uint64_t pn)
287{
288 int i;
289 unsigned int shift;
290 unsigned char *pos = iv;
291
292 if (ivlen != aead_ivlen)
293 return 0;
294
295 for (i = 0; i < ivlen - sizeof pn; i++)
296 *pos++ = *aead_iv++;
297
298 /* Only the remaining (sizeof pn) bytes are XOR'ed. */
299 shift = 56;
300 for (i = aead_ivlen - sizeof pn; i < aead_ivlen ; i++, shift -= 8)
301 *pos++ = *aead_iv++ ^ (pn >> shift);
302
303 return 1;
304}
305
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200306/* Initialize the cipher context for RX part of <tls_ctx> QUIC TLS context.
307 * Return 1 if succeeded, 0 if not.
308 */
309int quic_tls_rx_ctx_init(EVP_CIPHER_CTX **rx_ctx,
310 const EVP_CIPHER *aead, unsigned char *key)
311{
312 EVP_CIPHER_CTX *ctx;
313 int aead_nid = EVP_CIPHER_nid(aead);
314
315 ctx = EVP_CIPHER_CTX_new();
316 if (!ctx)
317 return 0;
318
319 if (!EVP_DecryptInit_ex(ctx, aead, NULL, NULL, NULL) ||
Frédéric Lécaillef2f4a4e2022-04-05 12:18:46 +0200320 !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, QUIC_TLS_IV_LEN, NULL) ||
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200321 (aead_nid == NID_aes_128_ccm &&
322 !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, QUIC_TLS_TAG_LEN, NULL)) ||
323 !EVP_DecryptInit_ex(ctx, NULL, NULL, key, NULL))
324 goto err;
325
326 *rx_ctx = ctx;
327
328 return 1;
329
330 err:
331 EVP_CIPHER_CTX_free(ctx);
332 return 0;
333}
334
335/* Initialize the cipher context for TX part of <tls_ctx> QUIC TLS context.
336 * Return 1 if succeeded, 0 if not.
337 */
338int quic_tls_tx_ctx_init(EVP_CIPHER_CTX **tx_ctx,
339 const EVP_CIPHER *aead, unsigned char *key)
340{
341 EVP_CIPHER_CTX *ctx;
342 int aead_nid = EVP_CIPHER_nid(aead);
343
344 ctx = EVP_CIPHER_CTX_new();
345 if (!ctx)
346 return 0;
347
348 if (!EVP_EncryptInit_ex(ctx, aead, NULL, NULL, NULL) ||
Frédéric Lécaillef2f4a4e2022-04-05 12:18:46 +0200349 !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, QUIC_TLS_IV_LEN, NULL) ||
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200350 (aead_nid == NID_aes_128_ccm &&
351 !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, QUIC_TLS_TAG_LEN, NULL)) ||
352 !EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL))
353 goto err;
354
355 *tx_ctx = ctx;
356
357 return 1;
358
359 err:
360 EVP_CIPHER_CTX_free(ctx);
361 return 0;
362}
363
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100364/*
365 * https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#aead
366 *
367 * 5.3. AEAD Usage
368 *
369 * Packets are protected prior to applying header protection (Section 5.4).
370 * The unprotected packet header is part of the associated data (A). When removing
371 * packet protection, an endpoint first removes the header protection.
372 * (...)
373 * These ciphersuites have a 16-byte authentication tag and produce an output 16
374 * bytes larger than their input.
375 * The key and IV for the packet are computed as described in Section 5.1. The nonce,
376 * N, is formed by combining the packet protection IV with the packet number. The 62
377 * bits of the reconstructed QUIC packet number in network byte order are left-padded
378 * with zeros to the size of the IV. The exclusive OR of the padded packet number and
379 * the IV forms the AEAD nonce.
380 *
381 * The associated data, A, for the AEAD is the contents of the QUIC header, starting
382 * from the flags byte in either the short or long header, up to and including the
383 * unprotected packet number.
384 *
385 * The input plaintext, P, for the AEAD is the payload of the QUIC packet, as described
386 * in [QUIC-TRANSPORT].
387 *
388 * The output ciphertext, C, of the AEAD is transmitted in place of P.
389 *
390 * Some AEAD functions have limits for how many packets can be encrypted under the same
391 * key and IV (see for example [AEBounds]). This might be lower than the packet number limit.
392 * An endpoint MUST initiate a key update (Section 6) prior to exceeding any limit set for
393 * the AEAD that is in use.
394 */
395
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200396/* Encrypt in place <buf> plaintext with <len> as length with QUIC_TLS_TAG_LEN
397 * included tailing bytes for the tag.
398 * Note that for CCM mode, we must set the the ciphertext length if AAD data
399 * are provided from <aad> buffer with <aad_len> as length. This is always the
400 * case here. So the caller of this function must provide <aad>.
401 *
402 * https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
403 */
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100404int quic_tls_encrypt(unsigned char *buf, size_t len,
405 const unsigned char *aad, size_t aad_len,
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200406 EVP_CIPHER_CTX *ctx, const EVP_CIPHER *aead,
407 const unsigned char *key, const unsigned char *iv)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100408{
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200409 int outlen;
410 int aead_nid = EVP_CIPHER_nid(aead);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100411
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200412 if (!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) ||
413 (aead_nid == NID_aes_128_ccm &&
414 !EVP_EncryptUpdate(ctx, NULL, &outlen, NULL, len)) ||
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100415 !EVP_EncryptUpdate(ctx, NULL, &outlen, aad, aad_len) ||
416 !EVP_EncryptUpdate(ctx, buf, &outlen, buf, len) ||
417 !EVP_EncryptFinal_ex(ctx, buf + outlen, &outlen) ||
418 !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, QUIC_TLS_TAG_LEN, buf + len))
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200419 return 0;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100420
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200421 return 1;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100422}
423
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200424/* Decrypt in place <buf> ciphertext with <len> as length with QUIC_TLS_TAG_LEN
425 * included tailing bytes for the tag.
426 * Note that for CCM mode, we must set the the ciphertext length if AAD data
427 * are provided from <aad> buffer with <aad_len> as length. This is always the
428 * case here. So the caller of this function must provide <aad>. Also not the
429 * there is no need to call EVP_DecryptFinal_ex for CCM mode.
430 *
431 * https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
432 */
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100433int quic_tls_decrypt(unsigned char *buf, size_t len,
434 unsigned char *aad, size_t aad_len,
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200435 EVP_CIPHER_CTX *ctx, const EVP_CIPHER *aead,
436 const unsigned char *key, const unsigned char *iv)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100437{
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200438 int outlen;
439 int aead_nid = EVP_CIPHER_nid(aead);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100440
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200441 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv) ||
442 !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, QUIC_TLS_TAG_LEN,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100443 buf + len - QUIC_TLS_TAG_LEN) ||
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200444 (aead_nid == NID_aes_128_ccm &&
445 !EVP_DecryptUpdate(ctx, NULL, &outlen, NULL, len - QUIC_TLS_TAG_LEN)) ||
446 !EVP_DecryptUpdate(ctx, NULL, &outlen, aad, aad_len) ||
447 !EVP_DecryptUpdate(ctx, buf, &outlen, buf, len - QUIC_TLS_TAG_LEN) ||
448 (aead_nid != NID_aes_128_ccm &&
449 !EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen)))
450 return 0;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100451
Frédéric Lécaillef4605742022-04-05 10:28:29 +0200452 return 1;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100453}
Amaury Denoyelle6efec292022-01-11 11:57:00 +0100454
455/* Generate the AEAD tag for the Retry packet <pkt> of <pkt_len> bytes and
456 * write it to <tag>. The tag is written just after the <pkt> area. It should
457 * be at least 16 bytes longs. <odcid> is the CID of the Initial packet
458 * received which triggers the Retry.
459 *
460 * Returns non-zero on success else zero.
461 */
462int quic_tls_generate_retry_integrity_tag(unsigned char *odcid,
463 unsigned char odcid_len,
464 unsigned char *pkt, size_t pkt_len)
465{
466 const EVP_CIPHER *evp = EVP_aes_128_gcm();
467 EVP_CIPHER_CTX *ctx;
468
469 /* key/nonce from rfc9001 5.8. Retry Packet Integrity */
470 const unsigned char key[] = {
471 0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
472 0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e,
473 };
474 const unsigned char nonce[] = {
475 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb,
476 };
477
478 /* encryption buffer - not used as only AEAD tag generation is proceed */
479 unsigned char *out = NULL;
480 /* address to store the AEAD tag */
481 unsigned char *tag = pkt + pkt_len;
482 int outlen, ret = 0;
483
484 ctx = EVP_CIPHER_CTX_new();
485 if (!ctx)
486 return 0;
487
488 /* rfc9001 5.8. Retry Packet Integrity
489 *
490 * AEAD is proceed over a pseudo-Retry packet used as AAD. It contains
491 * the ODCID len + data and the Retry packet itself.
492 */
493 if (!EVP_EncryptInit_ex(ctx, evp, NULL, key, nonce) ||
494 /* specify pseudo-Retry as AAD */
495 !EVP_EncryptUpdate(ctx, NULL, &outlen, &odcid_len, sizeof(odcid_len)) ||
496 !EVP_EncryptUpdate(ctx, NULL, &outlen, odcid, odcid_len) ||
497 !EVP_EncryptUpdate(ctx, NULL, &outlen, pkt, pkt_len) ||
498 /* finalize */
499 !EVP_EncryptFinal_ex(ctx, out, &outlen) ||
500 /* store the tag */
501 !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, QUIC_TLS_TAG_LEN, tag)) {
502 goto out;
503 }
504 ret = 1;
505
506 out:
507 EVP_CIPHER_CTX_free(ctx);
508 return ret;
509}