2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include "internal/quic_wire_pkt.h"
12 int ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR *hpr,
16 const unsigned char *quic_hp_key,
17 size_t quic_hp_key_len)
19 const char *cipher_name = NULL;
22 case QUIC_HDR_PROT_CIPHER_AES_128:
23 cipher_name = "AES-128-ECB";
25 case QUIC_HDR_PROT_CIPHER_AES_256:
26 cipher_name = "AES-256-ECB";
28 case QUIC_HDR_PROT_CIPHER_CHACHA:
29 cipher_name = "ChaCha20";
35 hpr->cipher_ctx = EVP_CIPHER_CTX_new();
36 if (hpr->cipher_ctx == NULL)
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))
44 if (!EVP_CipherInit_ex(hpr->cipher_ctx, hpr->cipher, NULL,
45 quic_hp_key, NULL, 1))
50 hpr->cipher_id = cipher_id;
54 ossl_quic_hdr_protector_cleanup(hpr);
58 void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr)
60 EVP_CIPHER_CTX_free(hpr->cipher_ctx);
61 hpr->cipher_ctx = NULL;
63 EVP_CIPHER_free(hpr->cipher);
67 static int hdr_generate_mask(QUIC_HDR_PROTECTOR *hpr,
68 const unsigned char *sample, size_t sample_len,
72 unsigned char dst[16];
73 static const unsigned char zeroes[5] = {0};
76 if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_128
77 || hpr->cipher_id == QUIC_HDR_PROT_CIPHER_AES_256) {
81 if (!EVP_CipherInit_ex(hpr->cipher_ctx, NULL, NULL, NULL, NULL, 1)
82 || !EVP_CipherUpdate(hpr->cipher_ctx, dst, &l, sample, 16))
85 for (i = 0; i < 5; ++i)
87 } else if (hpr->cipher_id == QUIC_HDR_PROT_CIPHER_CHACHA) {
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)))
103 int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr,
104 QUIC_PKT_HDR_PTRS *ptrs)
106 return ossl_quic_hdr_protector_decrypt_fields(hpr,
108 ptrs->raw_sample_len,
113 int ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR *hpr,
114 const unsigned char *sample,
116 unsigned char *first_byte,
117 unsigned char *pn_bytes)
119 unsigned char mask[5], pn_len, i;
121 if (!hdr_generate_mask(hpr, sample, sample_len, mask))
124 *first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
125 pn_len = (*first_byte & 0x3) + 1;
127 for (i = 0; i < pn_len; ++i)
128 pn_bytes[i] ^= mask[i + 1];
133 int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr,
134 QUIC_PKT_HDR_PTRS *ptrs)
136 return ossl_quic_hdr_protector_encrypt_fields(hpr,
138 ptrs->raw_sample_len,
143 int ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR *hpr,
144 const unsigned char *sample,
146 unsigned char *first_byte,
147 unsigned char *pn_bytes)
149 unsigned char mask[5], pn_len, i;
151 if (!hdr_generate_mask(hpr, sample, sample_len, mask))
154 pn_len = (*first_byte & 0x3) + 1;
155 for (i = 0; i < pn_len; ++i)
156 pn_bytes[i] ^= mask[i + 1];
158 *first_byte ^= mask[0] & ((*first_byte & 0x80) != 0 ? 0xf : 0x1f);
162 int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
163 size_t short_conn_id_len,
167 QUIC_PKT_HDR_PTRS *ptrs)
170 unsigned char *pn = NULL;
171 size_t l = PACKET_remaining(pkt);
174 ptrs->raw_start = (unsigned char *)PACKET_data(pkt);
175 ptrs->raw_sample = NULL;
176 ptrs->raw_sample_len = 0;
180 if (l < QUIC_MIN_VALID_PKT_LEN
181 || !PACKET_get_1(pkt, &b0))
184 hdr->partial = partial;
187 if ((b0 & 0x80) == 0) {
189 if (short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
192 if ((b0 & 0x40) == 0 /* fixed bit not set? */
193 || l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
196 hdr->type = QUIC_PKT_TYPE_1RTT;
198 hdr->spin_bit = (b0 & 0x20) != 0;
200 hdr->key_phase = 0; /* protected, zero for now */
201 hdr->pn_len = 0; /* protected, zero for now */
203 hdr->key_phase = (b0 & 0x4) != 0;
204 hdr->pn_len = (b0 & 0x3) + 1;
207 /* Copy destination connection ID field to header structure. */
208 if (!PACKET_copy_bytes(pkt, hdr->dst_conn_id.id, short_conn_id_len))
211 hdr->dst_conn_id.id_len = (unsigned char)short_conn_id_len;
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
219 memset(hdr->pn, 0, sizeof(hdr->pn));
220 pn = (unsigned char *)PACKET_data(pkt);
222 if (!PACKET_forward(pkt, sizeof(hdr->pn)))
225 if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
229 /* Fields not used in short-header packets. */
231 hdr->src_conn_id.id_len = 0;
236 * Short-header packets always come last in a datagram, the length
237 * is the remainder of the buffer.
239 hdr->len = PACKET_remaining(pkt);
240 hdr->data = PACKET_data(pkt);
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
247 if (!PACKET_forward(pkt, hdr->len))
251 unsigned long version;
252 unsigned int dst_conn_id_len, src_conn_id_len, raw_type;
254 if (!PACKET_get_net_4(pkt, &version))
258 * All QUIC packets must have the fixed bit set, except exceptionally
259 * for Version Negotiation packets.
261 if (version != 0 && (b0 & 0x40) == 0)
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))
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;
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).
282 hdr->type = QUIC_PKT_TYPE_VERSION_NEG;
283 hdr->fixed = (b0 & 0x40) != 0;
285 hdr->data = PACKET_data(pkt);
286 hdr->len = PACKET_remaining(pkt);
288 /* Version negotiation packets are always fully decoded. */
291 /* Fields not used in version negotiation packets. */
297 memset(hdr->pn, 0, sizeof(hdr->pn));
299 if (!PACKET_forward(pkt, hdr->len))
301 } else if (version != QUIC_VERSION_1) {
302 /* Unknown version, do not decode. */
305 if (l < QUIC_MIN_VALID_PKT_LEN_CRYPTO)
308 /* Get long packet type and decode to QUIC_PKT_TYPE_*. */
309 raw_type = ((b0 >> 4) & 0x3);
313 hdr->type = QUIC_PKT_TYPE_INITIAL;
316 hdr->type = QUIC_PKT_TYPE_0RTT;
319 hdr->type = QUIC_PKT_TYPE_HANDSHAKE;
322 hdr->type = QUIC_PKT_TYPE_RETRY;
329 /* Fields not used in long-header packets. */
333 if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
334 /* Initial packet. */
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))
342 hdr->token_len = (size_t)token_len;
350 if (hdr->type == QUIC_PKT_TYPE_RETRY) {
352 hdr->data = PACKET_data(pkt);
353 hdr->len = PACKET_remaining(pkt);
355 /* Retry packets are always fully decoded. */
358 /* Unused bits in Retry header. */
359 hdr->unused = b0 & 0x0f;
361 /* Fields not used in Retry packets. */
362 memset(hdr->pn, 0, sizeof(hdr->pn));
364 if (!PACKET_forward(pkt, hdr->len))
367 /* Initial, 0-RTT or Handshake packet. */
370 hdr->pn_len = partial ? 0 : (b0 & 3) + 1;
372 if (!PACKET_get_quic_vlint(pkt, &len)
373 || len < sizeof(hdr->pn))
376 if (!nodata && len > PACKET_remaining(pkt))
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.
385 pn = (unsigned char *)PACKET_data(pkt);
386 memset(hdr->pn, 0, sizeof(hdr->pn));
388 if (!PACKET_forward(pkt, sizeof(hdr->pn)))
391 hdr->len = (size_t)(len - sizeof(hdr->pn));
393 if (!PACKET_copy_bytes(pkt, hdr->pn, hdr->pn_len))
396 hdr->len = (size_t)(len - hdr->pn_len);
402 hdr->data = PACKET_data(pkt);
404 /* Skip over packet body. */
405 if (!PACKET_forward(pkt, hdr->len))
415 ptrs->raw_sample = pn + 4;
416 ptrs->raw_sample_len = PACKET_end(pkt) - ptrs->raw_sample;
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)
429 size_t off_start, off_sample, off_pn;
430 unsigned char *start = WPACKET_get_curr(pkt);
432 if (!WPACKET_get_total_written(pkt, &off_start))
436 ptrs->raw_start = NULL;
437 ptrs->raw_sample = NULL;
438 ptrs->raw_sample_len = 0;
442 /* Cannot serialize a partial header, or one whose DCID length is wrong. */
444 || (hdr->type == QUIC_PKT_TYPE_1RTT
445 && hdr->dst_conn_id.id_len != short_conn_id_len))
448 if (hdr->type == QUIC_PKT_TYPE_1RTT) {
452 * Cannot serialize a header whose DCID length is wrong, or with an
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)
460 b0 = (hdr->spin_bit << 5)
461 | (hdr->key_phase << 2)
463 | 0x40; /* fixed bit */
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))
472 unsigned int raw_type;
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)
478 if (ossl_quic_pkt_type_has_pn(hdr->type)
479 && (hdr->pn_len < 1 || hdr->pn_len > 4))
483 case QUIC_PKT_TYPE_VERSION_NEG:
484 if (hdr->version != 0)
487 /* Version negotiation packets use zero for the type bits */
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;
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)
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))
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))
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))
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))
537 if (hdr->len > 0 && !WPACKET_reserve_bytes(pkt, hdr->len, NULL))
540 off_sample = off_pn + 4;
543 ptrs->raw_start = start;
544 ptrs->raw_sample = start + (off_sample - off_start);
546 = WPACKET_get_curr(pkt) + hdr->len - ptrs->raw_sample;
547 ptrs->raw_pn = start + (off_pn - off_start);
553 int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
554 const QUIC_PKT_HDR *hdr)
556 size_t len = 0, enclen;
558 /* Cannot serialize a partial header, or one whose DCID length is wrong. */
560 || (hdr->type == QUIC_PKT_TYPE_1RTT
561 && hdr->dst_conn_id.id_len != short_conn_id_len))
564 if (hdr->type == QUIC_PKT_TYPE_1RTT) {
568 * Cannot serialize a header whose DCID length is wrong, or with an
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)
576 return 1 + short_conn_id_len + hdr->pn_len;
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)
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 */
588 if (ossl_quic_pkt_type_has_pn(hdr->type)) {
589 if (hdr->pn_len < 1 || hdr->pn_len > 4)
595 if (hdr->type == QUIC_PKT_TYPE_INITIAL) {
596 enclen = ossl_quic_vlint_encode_len(hdr->token_len);
600 len += enclen + hdr->token_len;
603 if (!ossl_quic_pkt_type_must_be_last(hdr->type)) {
604 enclen = ossl_quic_vlint_encode_len(hdr->len + hdr->pn_len);
615 int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf,
617 size_t short_conn_id_len,
618 QUIC_CONN_ID *dst_conn_id)
623 if (buf_len < QUIC_MIN_VALID_PKT_LEN
624 || short_conn_id_len > QUIC_MAX_CONN_ID_LEN)
628 if ((b0 & 0x80) != 0) {
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
636 * If the version field is non-zero (meaning that this is not a Version
637 * Negotiation packet), the fixed bit must be set.
639 if ((buf[1] || buf[2] || buf[3] || buf[4]) && (b0 & 0x40) == 0)
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)
647 dst_conn_id->id_len = (unsigned char)blen;
648 memcpy(dst_conn_id->id, buf + 6, blen);
652 if ((b0 & 0x40) == 0)
653 /* Fixed bit not set, not a valid QUIC packet header. */
656 if (buf_len < QUIC_MIN_VALID_PKT_LEN_CRYPTO + short_conn_id_len)
659 dst_conn_id->id_len = (unsigned char)short_conn_id_len;
660 memcpy(dst_conn_id->id, buf + 1, short_conn_id_len);
665 int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn,
670 int64_t expected_pn, truncated_pn, candidate_pn, pn_win, pn_hwin, pn_mask;
672 switch (enc_pn_len) {
674 truncated_pn = enc_pn[0];
677 truncated_pn = ((QUIC_PN)enc_pn[0] << 8)
678 | (QUIC_PN)enc_pn[1];
681 truncated_pn = ((QUIC_PN)enc_pn[0] << 16)
682 | ((QUIC_PN)enc_pn[1] << 8)
683 | (QUIC_PN)enc_pn[2];
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];
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;
708 *res_pn = candidate_pn;
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)
717 = (largest_acked == QUIC_PN_INVALID) ? pn + 1 : pn - largest_acked;
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
726 if (num_unacked <= (1U<<7)) return 1;
727 if (num_unacked <= (1U<<15)) return 2;
728 if (num_unacked <= (1U<<23)) return 3;
732 int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
733 unsigned char *enc_pn,
736 switch (enc_pn_len) {
738 enc_pn[0] = (unsigned char)pn;
741 enc_pn[1] = (unsigned char)pn;
742 enc_pn[0] = (unsigned char)(pn >> 8);
745 enc_pn[2] = (unsigned char)pn;
746 enc_pn[1] = (unsigned char)(pn >> 8);
747 enc_pn[0] = (unsigned char)(pn >> 16);
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);
762 int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
764 const QUIC_PKT_HDR *hdr,
765 const QUIC_CONN_ID *client_initial_dcid)
767 unsigned char expected_tag[QUIC_RETRY_INTEGRITY_TAG_LEN];
768 const unsigned char *actual_tag;
770 if (hdr == NULL || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN)
773 if (!ossl_quic_calculate_retry_integrity_tag(libctx, propq,
774 hdr, client_initial_dcid,
778 actual_tag = hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN;
780 return !CRYPTO_memcmp(expected_tag, actual_tag,
781 QUIC_RETRY_INTEGRITY_TAG_LEN);
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
790 static const unsigned char retry_integrity_nonce[] = {
791 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2,
792 0x23, 0x98, 0x25, 0xbb
795 int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
797 const QUIC_PKT_HDR *hdr,
798 const QUIC_CONN_ID *client_initial_dcid,
801 EVP_CIPHER *cipher = NULL;
802 EVP_CIPHER_CTX *cctx = NULL;
803 int ok = 0, l = 0, l2 = 0, wpkt_valid = 0;
805 /* Worst case length of the Retry Psuedo-Packet header is 68 bytes. */
806 unsigned char buf[128];
808 size_t hdr_enc_len = 0;
810 if (hdr->type != QUIC_PKT_TYPE_RETRY || hdr->version == 0
811 || hdr->len < QUIC_RETRY_INTEGRITY_TAG_LEN
813 || client_initial_dcid == NULL || tag == NULL
814 || client_initial_dcid->id_len > QUIC_MAX_CONN_ID_LEN)
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.
825 /* Assemble retry psuedo-packet. */
826 if (!WPACKET_init_static_len(&wpkt, buf, sizeof(buf), 0))
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))
837 /* Encode main retry header. */
838 if (!ossl_quic_wire_encode_pkt_hdr(&wpkt, hdr2.dst_conn_id.id_len,
842 if (!WPACKET_get_total_written(&wpkt, &hdr_enc_len))
845 /* Create and initialise cipher context. */
846 /* TODO(QUIC): Cipher fetch caching. */
847 if ((cipher = EVP_CIPHER_fetch(libctx, "AES-128-GCM", propq)) == NULL)
850 if ((cctx = EVP_CIPHER_CTX_new()) == NULL)
853 if (!EVP_CipherInit_ex(cctx, cipher, NULL,
854 retry_integrity_key, retry_integrity_nonce, /*enc=*/1))
857 /* Feed packet header as AAD data. */
858 if (EVP_CipherUpdate(cctx, NULL, &l, buf, hdr_enc_len) != 1)
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)
866 /* Finalise and get tag. */
867 if (EVP_CipherFinal_ex(cctx, NULL, &l2) != 1)
870 if (EVP_CIPHER_CTX_ctrl(cctx, EVP_CTRL_AEAD_GET_TAG,
871 QUIC_RETRY_INTEGRITY_TAG_LEN,
877 EVP_CIPHER_free(cipher);
878 EVP_CIPHER_CTX_free(cctx);
880 WPACKET_finish(&wpkt);