1 /*
2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #ifndef OSSL_QUIC_WIRE_PKT_H
11 # define OSSL_QUIC_WIRE_PKT_H
12
13 # include <openssl/ssl.h>
14 # include "internal/packet_quic.h"
15 # include "internal/quic_types.h"
16
17 # ifndef OPENSSL_NO_QUIC
18
19 # define QUIC_VERSION_NONE ((uint32_t)0) /* Used for version negotiation */
20 # define QUIC_VERSION_1 ((uint32_t)1) /* QUIC v1 */
21
22 /* QUIC logical packet type. These do not match wire values. */
23 # define QUIC_PKT_TYPE_INITIAL 1
24 # define QUIC_PKT_TYPE_0RTT 2
25 # define QUIC_PKT_TYPE_HANDSHAKE 3
26 # define QUIC_PKT_TYPE_RETRY 4
27 # define QUIC_PKT_TYPE_1RTT 5
28 # define QUIC_PKT_TYPE_VERSION_NEG 6
29
30 /*
31 * Determine encryption level from packet type. Returns QUIC_ENC_LEVEL_NUM if
32 * the packet is not of a type which is encrypted.
33 */
34 static ossl_inline ossl_unused uint32_t
ossl_quic_pkt_type_to_enc_level(uint32_t pkt_type)35 ossl_quic_pkt_type_to_enc_level(uint32_t pkt_type)
36 {
37 switch (pkt_type) {
38 case QUIC_PKT_TYPE_INITIAL:
39 return QUIC_ENC_LEVEL_INITIAL;
40 case QUIC_PKT_TYPE_HANDSHAKE:
41 return QUIC_ENC_LEVEL_HANDSHAKE;
42 case QUIC_PKT_TYPE_0RTT:
43 return QUIC_ENC_LEVEL_0RTT;
44 case QUIC_PKT_TYPE_1RTT:
45 return QUIC_ENC_LEVEL_1RTT;
46 default:
47 return QUIC_ENC_LEVEL_NUM;
48 }
49 }
50
51 static ossl_inline ossl_unused uint32_t
ossl_quic_enc_level_to_pkt_type(uint32_t enc_level)52 ossl_quic_enc_level_to_pkt_type(uint32_t enc_level)
53 {
54 switch (enc_level) {
55 case QUIC_ENC_LEVEL_INITIAL:
56 return QUIC_PKT_TYPE_INITIAL;
57 case QUIC_ENC_LEVEL_HANDSHAKE:
58 return QUIC_PKT_TYPE_HANDSHAKE;
59 case QUIC_ENC_LEVEL_0RTT:
60 return QUIC_PKT_TYPE_0RTT;
61 case QUIC_ENC_LEVEL_1RTT:
62 return QUIC_PKT_TYPE_1RTT;
63 default:
64 return UINT32_MAX;
65 }
66 }
67
68 /* Determine if a packet type contains an encrypted payload. */
69 static ossl_inline ossl_unused int
ossl_quic_pkt_type_is_encrypted(uint32_t pkt_type)70 ossl_quic_pkt_type_is_encrypted(uint32_t pkt_type)
71 {
72 switch (pkt_type) {
73 case QUIC_PKT_TYPE_RETRY:
74 case QUIC_PKT_TYPE_VERSION_NEG:
75 return 0;
76 default:
77 return 1;
78 }
79 }
80
81 /* Determine if a packet type contains a PN field. */
82 static ossl_inline ossl_unused int
ossl_quic_pkt_type_has_pn(uint32_t pkt_type)83 ossl_quic_pkt_type_has_pn(uint32_t pkt_type)
84 {
85 /*
86 * Currently a packet has a PN iff it is encrypted. This could change
87 * someday.
88 */
89 return ossl_quic_pkt_type_is_encrypted(pkt_type);
90 }
91
92 /*
93 * Determine if a packet type can appear with other packets in a datagram. Some
94 * packet types must be the sole packet in a datagram.
95 */
96 static ossl_inline ossl_unused int
ossl_quic_pkt_type_can_share_dgram(uint32_t pkt_type)97 ossl_quic_pkt_type_can_share_dgram(uint32_t pkt_type)
98 {
99 /*
100 * Currently only the encrypted packet types can share a datagram. This
101 * could change someday.
102 */
103 return ossl_quic_pkt_type_is_encrypted(pkt_type);
104 }
105
106 /*
107 * Determine if the packet type must come at the end of the datagram (due to the
108 * lack of a length field).
109 */
110 static ossl_inline ossl_unused int
ossl_quic_pkt_type_must_be_last(uint32_t pkt_type)111 ossl_quic_pkt_type_must_be_last(uint32_t pkt_type)
112 {
113 /*
114 * Any packet type which cannot share a datagram obviously must come last.
115 * 1-RTT also must come last as it lacks a length field.
116 */
117 return !ossl_quic_pkt_type_can_share_dgram(pkt_type)
118 || pkt_type == QUIC_PKT_TYPE_1RTT;
119 }
120
121 /*
122 * Determine if the packet type has a version field.
123 */
124 static ossl_inline ossl_unused int
ossl_quic_pkt_type_has_version(uint32_t pkt_type)125 ossl_quic_pkt_type_has_version(uint32_t pkt_type)
126 {
127 return pkt_type != QUIC_PKT_TYPE_1RTT && pkt_type != QUIC_PKT_TYPE_VERSION_NEG;
128 }
129
130 /*
131 * Determine if the packet type has a SCID field.
132 */
133 static ossl_inline ossl_unused int
ossl_quic_pkt_type_has_scid(uint32_t pkt_type)134 ossl_quic_pkt_type_has_scid(uint32_t pkt_type)
135 {
136 return pkt_type != QUIC_PKT_TYPE_1RTT;
137 }
138
139 /*
140 * Smallest possible QUIC packet size as per RFC (aside from version negotiation
141 * packets).
142 */
143 # define QUIC_MIN_VALID_PKT_LEN_CRYPTO 21
144 # define QUIC_MIN_VALID_PKT_LEN_VERSION_NEG 7
145 # define QUIC_MIN_VALID_PKT_LEN QUIC_MIN_VALID_PKT_LEN_VERSION_NEG
146
147 typedef struct quic_pkt_hdr_ptrs_st QUIC_PKT_HDR_PTRS;
148
149 /*
150 * QUIC Packet Header Protection
151 * =============================
152 *
153 * Functions to apply and remove QUIC packet header protection. A header
154 * protector is initialised using ossl_quic_hdr_protector_init and must be
155 * destroyed using ossl_quic_hdr_protector_cleanup when no longer needed.
156 */
157 typedef struct quic_hdr_protector_st {
158 OSSL_LIB_CTX *libctx;
159 const char *propq;
160 EVP_CIPHER_CTX *cipher_ctx;
161 EVP_CIPHER *cipher;
162 uint32_t cipher_id;
163 } QUIC_HDR_PROTECTOR;
164
165 # define QUIC_HDR_PROT_CIPHER_AES_128 1
166 # define QUIC_HDR_PROT_CIPHER_AES_256 2
167 # define QUIC_HDR_PROT_CIPHER_CHACHA 3
168
169 /*
170 * Initialises a header protector.
171 *
172 * cipher_id:
173 * The header protection cipher method to use. One of
174 * QUIC_HDR_PROT_CIPHER_*. Must be chosen based on negotiated TLS cipher
175 * suite.
176 *
177 * quic_hp_key:
178 * This must be the "quic hp" key derived from a traffic secret.
179 *
180 * The length of the quic_hp_key must correspond to that expected for the
181 * given cipher ID.
182 *
183 * The header protector performs amortisable initialisation in this function,
184 * therefore a header protector should be used for as long as possible.
185 *
186 * Returns 1 on success and 0 on failure.
187 */
188 int ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR *hpr,
189 OSSL_LIB_CTX *libctx,
190 const char *propq,
191 uint32_t cipher_id,
192 const unsigned char *quic_hp_key,
193 size_t quic_hp_key_len);
194
195 /*
196 * Destroys a header protector. This is also safe to call on a zero-initialized
197 * OSSL_QUIC_HDR_PROTECTOR structure which has not been initialized, or which
198 * has already been destroyed.
199 */
200 void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr);
201
202 /*
203 * Removes header protection from a packet. The packet payload must currently be
204 * encrypted (i.e., you must remove header protection before decrypting packets
205 * received). The function examines the header buffer to determine which bytes
206 * of the header need to be decrypted.
207 *
208 * If this function fails, no data is modified.
209 *
210 * This is implemented as a call to ossl_quic_hdr_protector_decrypt_fields().
211 *
212 * Returns 1 on success and 0 on failure.
213 */
214 int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr,
215 QUIC_PKT_HDR_PTRS *ptrs);
216
217 /*
218 * Applies header protection to a packet. The packet payload must already have
219 * been encrypted (i.e., you must apply header protection after encrypting
220 * a packet). The function examines the header buffer to determine which bytes
221 * of the header need to be encrypted.
222 *
223 * This is implemented as a call to ossl_quic_hdr_protector_encrypt_fields().
224 *
225 * Returns 1 on success and 0 on failure.
226 */
227 int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr,
228 QUIC_PKT_HDR_PTRS *ptrs);
229
230 /*
231 * Removes header protection from a packet. The packet payload must currently
232 * be encrypted. This is a low-level function which assumes you have already
233 * determined which parts of the packet header need to be decrypted.
234 *
235 * sample:
236 * The range of bytes in the packet to be used to generate the header
237 * protection mask. It is permissible to set sample_len to the size of the
238 * remainder of the packet; this function will only use as many bytes as
239 * needed. If not enough sample bytes are provided, this function fails.
240 *
241 * first_byte:
242 * The first byte of the QUIC packet header to be decrypted.
243 *
244 * pn:
245 * Pointer to the start of the PN field. The caller is responsible
246 * for ensuring at least four bytes follow this pointer.
247 *
248 * Returns 1 on success and 0 on failure.
249 */
250 int ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR *hpr,
251 const unsigned char *sample,
252 size_t sample_len,
253 unsigned char *first_byte,
254 unsigned char *pn_bytes);
255
256 /*
257 * Works analogously to ossl_hdr_protector_decrypt_fields, but applies header
258 * protection instead of removing it.
259 */
260 int ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR *hpr,
261 const unsigned char *sample,
262 size_t sample_len,
263 unsigned char *first_byte,
264 unsigned char *pn_bytes);
265
266 /*
267 * QUIC Packet Header
268 * ==================
269 *
270 * This structure provides a logical representation of a QUIC packet header.
271 *
272 * QUIC packet formats fall into the following categories:
273 *
274 * Long Packets, which is subdivided into five possible packet types:
275 * Version Negotiation (a special case);
276 * Initial;
277 * 0-RTT;
278 * Handshake; and
279 * Retry
280 *
281 * Short Packets, which comprises only a single packet type (1-RTT).
282 *
283 * The packet formats vary and common fields are found in some packets but
284 * not others. The below table indicates which fields are present in which
285 * kinds of packet. * indicates header protection is applied.
286 *
287 * SLLLLL Legend: 1=1-RTT, i=Initial, 0=0-RTT, h=Handshake
288 * 1i0hrv r=Retry, v=Version Negotiation
289 * ------
290 * 1i0hrv Header Form (0=Short, 1=Long)
291 * 1i0hr Fixed Bit (always 1)
292 * 1 Spin Bit
293 * 1 * Reserved Bits
294 * 1 * Key Phase
295 * 1i0h * Packet Number Length
296 * i0hr? Long Packet Type
297 * i0h Type-Specific Bits
298 * i0hr Version (note: always 0 for Version Negotiation packets)
299 * 1i0hrv Destination Connection ID
300 * i0hrv Source Connection ID
301 * 1i0h * Packet Number
302 * i Token
303 * i0h Length
304 * r Retry Token
305 * r Retry Integrity Tag
306 *
307 * For each field below, the conditions under which the field is valid are
308 * specified. If a field is not currently valid, it is initialized to a zero or
309 * NULL value.
310 */
311 typedef struct quic_pkt_hdr_st {
312 /* [ALL] A QUIC_PKT_TYPE_* value. Always valid. */
313 unsigned int type :8;
314
315 /* [S] Value of the spin bit. Valid if (type == 1RTT). */
316 unsigned int spin_bit :1;
317
318 /*
319 * [S] Value of the Key Phase bit in the short packet.
320 * Valid if (type == 1RTT && !partial).
321 */
322 unsigned int key_phase :1;
323
324 /*
325 * [1i0h] Length of packet number in bytes. This is the decoded value.
326 * Valid if ((type == 1RTT || (version && type != RETRY)) && !partial).
327 */
328 unsigned int pn_len :4;
329
330 /*
331 * [ALL] Set to 1 if this is a partial decode because the packet header
332 * has not yet been deprotected. pn_len, pn and key_phase are not valid if
333 * this is set.
334 */
335 unsigned int partial :1;
336
337 /*
338 * [ALL] Whether the fixed bit was set. Note that only Version Negotiation
339 * packets are allowed to have this unset, so this will always be 1 for all
340 * other packet types (decode will fail if it is not set). Ignored when
341 * encoding unless encoding a Version Negotiation packet.
342 */
343 unsigned int fixed :1;
344
345 /*
346 * The unused bits in the low 4 bits of a Retry packet header's first byte.
347 * This is used to ensure that Retry packets have the same bit-for-bit
348 * representation in their header when decoding and encoding them again.
349 * This is necessary to validate Retry packet headers.
350 */
351 unsigned int unused :4;
352
353 /*
354 * The 'Reserved' bits in an Initial, Handshake, 0-RTT or 1-RTT packet
355 * header's first byte. These are provided so that the caller can validate
356 * that they are zero, as this must be done after packet protection is
357 * successfully removed to avoid creating a timing channel.
358 */
359 unsigned int reserved :2;
360
361 /* [L] Version field. Valid if (type != 1RTT). */
362 uint32_t version;
363
364 /* [ALL] The destination connection ID. Always valid. */
365 QUIC_CONN_ID dst_conn_id;
366
367 /*
368 * [L] The source connection ID.
369 * Valid if (type != 1RTT).
370 */
371 QUIC_CONN_ID src_conn_id;
372
373 /*
374 * [1i0h] Relatively-encoded packet number in raw, encoded form. The correct
375 * decoding of this value is context-dependent. The number of bytes valid in
376 * this buffer is determined by pn_len above. If the decode was partial,
377 * this field is not valid.
378 *
379 * Valid if ((type == 1RTT || (version && type != RETRY)) && !partial).
380 */
381 unsigned char pn[4];
382
383 /*
384 * [i] Token field in Initial packet. Points to memory inside the decoded
385 * PACKET, and therefore is valid for as long as the PACKET's buffer is
386 * valid. token_len is the length of the token in bytes.
387 *
388 * Valid if (type == INITIAL).
389 */
390 const unsigned char *token;
391 size_t token_len;
392
393 /*
394 * [ALL] Payload length in bytes.
395 *
396 * Though 1-RTT, Retry and Version Negotiation packets do not contain an
397 * explicit length field, this field is always valid and is used by the
398 * packet header encoding and decoding routines to describe the payload
399 * length, regardless of whether the packet type encoded or decoded uses an
400 * explicit length indication.
401 */
402 size_t len;
403
404 /*
405 * Pointer to start of payload data in the packet. Points to memory inside
406 * the decoded PACKET, and therefore is valid for as long as the PACKET'S
407 * buffer is valid. The length of the buffer in bytes is in len above.
408 *
409 * For Version Negotiation packets, points to the array of supported
410 * versions.
411 *
412 * For Retry packets, points to the Retry packet payload, which comprises
413 * the Retry Token followed by a 16-byte Retry Integrity Tag.
414 *
415 * Regardless of whether a packet is a Version Negotiation packet (where the
416 * payload contains a list of supported versions), a Retry packet (where the
417 * payload contains a Retry Token and Retry Integrity Tag), or any other
418 * packet type (where the payload contains frames), the payload is not
419 * validated and the user must parse the payload bearing this in mind.
420 *
421 * If the decode was partial (partial is set), this points to the start of
422 * the packet number field, rather than the protected payload, as the length
423 * of the packet number field is unknown. The len field reflects this in
424 * this case (i.e., the len field is the number of payload bytes plus the
425 * number of bytes comprising the PN).
426 */
427 const unsigned char *data;
428 } QUIC_PKT_HDR;
429
430 /*
431 * Extra information which can be output by the packet header decode functions
432 * for the assistance of the header protector. This avoids the header protector
433 * needing to partially re-decode the packet header.
434 */
435 struct quic_pkt_hdr_ptrs_st {
436 unsigned char *raw_start; /* start of packet */
437 unsigned char *raw_sample; /* start of sampling range */
438 size_t raw_sample_len; /* maximum length of sampling range */
439
440 /*
441 * Start of PN field. Guaranteed to be NULL unless at least four bytes are
442 * available via this pointer.
443 */
444 unsigned char *raw_pn;
445 };
446
447 /*
448 * If partial is 1, reads the unprotected parts of a protected packet header
449 * from a PACKET, performing a partial decode.
450 *
451 * If partial is 0, the input is assumed to have already had header protection
452 * removed, and all header fields are decoded.
453 *
454 * If nodata is 1, the input is assumed to have no payload data in it. Otherwise
455 * payload data must be present.
456 *
457 * On success, the logical decode of the packet header is written to *hdr.
458 * hdr->partial is set or cleared according to whether a partial decode was
459 * performed. *ptrs is filled with pointers to various parts of the packet
460 * buffer.
461 *
462 * In order to decode short packets, the connection ID length being used must be
463 * known contextually, and should be passed as short_conn_id_len. If
464 * short_conn_id_len is set to an invalid value (a value greater than
465 * QUIC_MAX_CONN_ID_LEN), this function fails when trying to decode a short
466 * packet, but succeeds for long packets.
467 *
468 * Returns 1 on success and 0 on failure.
469 */
470 int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt,
471 size_t short_conn_id_len,
472 int partial,
473 int nodata,
474 QUIC_PKT_HDR *hdr,
475 QUIC_PKT_HDR_PTRS *ptrs);
476
477 /*
478 * Encodes a packet header. The packet is written to pkt.
479 *
480 * The length of the (encrypted) packet payload should be written to hdr->len
481 * and will be placed in the serialized packet header. The payload data itself
482 * is not copied; the caller should write hdr->len bytes of encrypted payload to
483 * the WPACKET immediately after the call to this function. However,
484 * WPACKET_reserve_bytes is called for the payload size.
485 *
486 * This function does not apply header protection. You must apply header
487 * protection yourself after calling this function. *ptrs is filled with
488 * pointers which can be passed to a header protector, but this must be
489 * performed after the encrypted payload is written.
490 *
491 * The pointers in *ptrs are direct pointers into the WPACKET buffer. If more
492 * data is written to the WPACKET buffer, WPACKET buffer reallocations may
493 * occur, causing these pointers to become invalid. Therefore, you must not call
494 * any write WPACKET function between this call and the call to
495 * ossl_quic_hdr_protector_encrypt. This function calls WPACKET_reserve_bytes
496 * for the payload length, so you may assume hdr->len bytes are already free to
497 * write at the WPACKET cursor location once this function returns successfully.
498 * It is recommended that you call this function, write the encrypted payload,
499 * call ossl_quic_hdr_protector_encrypt, and then call
500 * WPACKET_allocate_bytes(hdr->len).
501 *
502 * Version Negotiation and Retry packets do not use header protection; for these
503 * header types, the fields in *ptrs are all written as zero. Version
504 * Negotiation, Retry and 1-RTT packets do not contain a Length field, but
505 * hdr->len bytes of data are still reserved in the WPACKET.
506 *
507 * If serializing a short packet and short_conn_id_len does not match the DCID
508 * specified in hdr, the function fails.
509 *
510 * Returns 1 on success and 0 on failure.
511 */
512 int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt,
513 size_t short_conn_id_len,
514 const QUIC_PKT_HDR *hdr,
515 QUIC_PKT_HDR_PTRS *ptrs);
516
517 /*
518 * Retrieves only the DCID from a packet header. This is intended for demuxer
519 * use. It avoids the need to parse the rest of the packet header twice.
520 *
521 * Information on packet length is not decoded, as this only needs to be used on
522 * the first packet in a datagram, therefore this takes a buffer and not a
523 * PACKET.
524 *
525 * Returns 1 on success and 0 on failure.
526 */
527 int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf,
528 size_t buf_len,
529 size_t short_conn_id_len,
530 QUIC_CONN_ID *dst_conn_id);
531
532 /*
533 * Precisely predicts the encoded length of a packet header structure.
534 *
535 * May return 0 if the packet header is not valid, but the fact that this
536 * function returns non-zero does not guarantee that
537 * ossl_quic_wire_encode_pkt_hdr() will succeed.
538 */
539 int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len,
540 const QUIC_PKT_HDR *hdr);
541
542 /*
543 * Packet Number Encoding
544 * ======================
545 */
546
547 /*
548 * Decode an encoded packet header QUIC PN.
549 *
550 * enc_pn is the raw encoded PN to decode. enc_pn_len is its length in bytes as
551 * indicated by packet headers. largest_pn is the largest PN successfully
552 * processed in the relevant PN space.
553 *
554 * The resulting PN is written to *res_pn.
555 *
556 * Returns 1 on success or 0 on failure.
557 */
558 int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn,
559 size_t enc_pn_len,
560 QUIC_PN largest_pn,
561 QUIC_PN *res_pn);
562
563 /*
564 * Determine how many bytes should be used to encode a PN. Returns the number of
565 * bytes (which will be in range [1, 4]).
566 */
567 int ossl_quic_wire_determine_pn_len(QUIC_PN pn, QUIC_PN largest_acked);
568
569 /*
570 * Encode a PN for a packet header using the specified number of bytes, which
571 * should have been determined by calling ossl_quic_wire_determine_pn_len. The
572 * PN encoding process is done in two parts to allow the caller to override PN
573 * encoding length if it wishes.
574 *
575 * Returns 1 on success and 0 on failure.
576 */
577 int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn,
578 unsigned char *enc_pn,
579 size_t enc_pn_len);
580
581 /*
582 * Retry Integrity Tags
583 * ====================
584 */
585
586 # define QUIC_RETRY_INTEGRITY_TAG_LEN 16
587
588 /*
589 * Validate a retry integrity tag. Returns 1 if the tag is valid.
590 *
591 * Must be called on a hdr with a type of QUIC_PKT_TYPE_RETRY with a valid data
592 * pointer.
593 *
594 * client_initial_dcid must be the original DCID used by the client in its first
595 * Initial packet, as this is used to calculate the Retry Integrity Tag.
596 *
597 * Returns 0 if the tag is invalid, if called on any other type of packet or if
598 * the body is too short.
599 */
600 int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
601 const char *propq,
602 const QUIC_PKT_HDR *hdr,
603 const QUIC_CONN_ID *client_initial_dcid);
604
605 /*
606 * Calculates a retry integrity tag. Returns 0 on error, for example if hdr does
607 * not have a type of QUIC_PKT_TYPE_RETRY.
608 *
609 * client_initial_dcid must be the original DCID used by the client in its first
610 * Initial packet, as this is used to calculate the Retry Integrity Tag.
611 *
612 * tag must point to a buffer of QUIC_RETRY_INTEGRITY_TAG_LEN bytes in size.
613 *
614 * Note that hdr->data must point to the Retry packet body, and hdr->len must
615 * include the space for the Retry Integrity Tag. (This means that you can
616 * easily fill in a tag in a Retry packet you are generating by calling this
617 * function and passing (hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) as
618 * the tag argument.) This function fails if hdr->len is too short to contain a
619 * Retry Integrity Tag.
620 */
621 int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx,
622 const char *propq,
623 const QUIC_PKT_HDR *hdr,
624 const QUIC_CONN_ID *client_initial_dcid,
625 unsigned char *tag);
626
627 # endif
628
629 #endif
630