1 /* 2 * Copyright 2022-2025 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 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 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 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 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 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 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 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 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 * fail_cause is a bitmask of the reasons decode might have failed 469 * as defined below, useful when you need to interrogate parts of 470 * a header even if its otherwise undecodeable. May be NULL. 471 * 472 * Returns 1 on success and 0 on failure. 473 */ 474 475 # define QUIC_PKT_HDR_DECODE_DECODE_ERR (1 << 0) 476 # define QUIC_PKT_HDR_DECODE_BAD_VERSION (1 << 1) 477 478 int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt, 479 size_t short_conn_id_len, 480 int partial, 481 int nodata, 482 QUIC_PKT_HDR *hdr, 483 QUIC_PKT_HDR_PTRS *ptrs, 484 uint64_t *fail_cause); 485 486 /* 487 * Encodes a packet header. The packet is written to pkt. 488 * 489 * The length of the (encrypted) packet payload should be written to hdr->len 490 * and will be placed in the serialized packet header. The payload data itself 491 * is not copied; the caller should write hdr->len bytes of encrypted payload to 492 * the WPACKET immediately after the call to this function. However, 493 * WPACKET_reserve_bytes is called for the payload size. 494 * 495 * This function does not apply header protection. You must apply header 496 * protection yourself after calling this function. *ptrs is filled with 497 * pointers which can be passed to a header protector, but this must be 498 * performed after the encrypted payload is written. 499 * 500 * The pointers in *ptrs are direct pointers into the WPACKET buffer. If more 501 * data is written to the WPACKET buffer, WPACKET buffer reallocations may 502 * occur, causing these pointers to become invalid. Therefore, you must not call 503 * any write WPACKET function between this call and the call to 504 * ossl_quic_hdr_protector_encrypt. This function calls WPACKET_reserve_bytes 505 * for the payload length, so you may assume hdr->len bytes are already free to 506 * write at the WPACKET cursor location once this function returns successfully. 507 * It is recommended that you call this function, write the encrypted payload, 508 * call ossl_quic_hdr_protector_encrypt, and then call 509 * WPACKET_allocate_bytes(hdr->len). 510 * 511 * Version Negotiation and Retry packets do not use header protection; for these 512 * header types, the fields in *ptrs are all written as zero. Version 513 * Negotiation, Retry and 1-RTT packets do not contain a Length field, but 514 * hdr->len bytes of data are still reserved in the WPACKET. 515 * 516 * If serializing a short packet and short_conn_id_len does not match the DCID 517 * specified in hdr, the function fails. 518 * 519 * Returns 1 on success and 0 on failure. 520 */ 521 int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt, 522 size_t short_conn_id_len, 523 const QUIC_PKT_HDR *hdr, 524 QUIC_PKT_HDR_PTRS *ptrs); 525 526 /* 527 * Retrieves only the DCID from a packet header. This is intended for demuxer 528 * use. It avoids the need to parse the rest of the packet header twice. 529 * 530 * Information on packet length is not decoded, as this only needs to be used on 531 * the first packet in a datagram, therefore this takes a buffer and not a 532 * PACKET. 533 * 534 * Returns 1 on success and 0 on failure. 535 */ 536 int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf, 537 size_t buf_len, 538 size_t short_conn_id_len, 539 QUIC_CONN_ID *dst_conn_id); 540 541 /* 542 * Precisely predicts the encoded length of a packet header structure. 543 * 544 * May return 0 if the packet header is not valid, but the fact that this 545 * function returns non-zero does not guarantee that 546 * ossl_quic_wire_encode_pkt_hdr() will succeed. 547 */ 548 int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len, 549 const QUIC_PKT_HDR *hdr); 550 551 /* 552 * Packet Number Encoding 553 * ====================== 554 */ 555 556 /* 557 * Decode an encoded packet header QUIC PN. 558 * 559 * enc_pn is the raw encoded PN to decode. enc_pn_len is its length in bytes as 560 * indicated by packet headers. largest_pn is the largest PN successfully 561 * processed in the relevant PN space. 562 * 563 * The resulting PN is written to *res_pn. 564 * 565 * Returns 1 on success or 0 on failure. 566 */ 567 int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn, 568 size_t enc_pn_len, 569 QUIC_PN largest_pn, 570 QUIC_PN *res_pn); 571 572 /* 573 * Determine how many bytes should be used to encode a PN. Returns the number of 574 * bytes (which will be in range [1, 4]). 575 */ 576 int ossl_quic_wire_determine_pn_len(QUIC_PN pn, QUIC_PN largest_acked); 577 578 /* 579 * Encode a PN for a packet header using the specified number of bytes, which 580 * should have been determined by calling ossl_quic_wire_determine_pn_len. The 581 * PN encoding process is done in two parts to allow the caller to override PN 582 * encoding length if it wishes. 583 * 584 * Returns 1 on success and 0 on failure. 585 */ 586 int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn, 587 unsigned char *enc_pn, 588 size_t enc_pn_len); 589 590 /* 591 * Retry Integrity Tags 592 * ==================== 593 */ 594 595 # define QUIC_RETRY_INTEGRITY_TAG_LEN 16 596 597 /* 598 * Validate a retry integrity tag. Returns 1 if the tag is valid. 599 * 600 * Must be called on a hdr with a type of QUIC_PKT_TYPE_RETRY with a valid data 601 * pointer. 602 * 603 * client_initial_dcid must be the original DCID used by the client in its first 604 * Initial packet, as this is used to calculate the Retry Integrity Tag. 605 * 606 * Returns 0 if the tag is invalid, if called on any other type of packet or if 607 * the body is too short. 608 */ 609 int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx, 610 const char *propq, 611 const QUIC_PKT_HDR *hdr, 612 const QUIC_CONN_ID *client_initial_dcid); 613 614 /* 615 * Calculates a retry integrity tag. Returns 0 on error, for example if hdr does 616 * not have a type of QUIC_PKT_TYPE_RETRY. 617 * 618 * client_initial_dcid must be the original DCID used by the client in its first 619 * Initial packet, as this is used to calculate the Retry Integrity Tag. 620 * 621 * tag must point to a buffer of QUIC_RETRY_INTEGRITY_TAG_LEN bytes in size. 622 * 623 * Note that hdr->data must point to the Retry packet body, and hdr->len must 624 * include the space for the Retry Integrity Tag. (This means that you can 625 * easily fill in a tag in a Retry packet you are generating by calling this 626 * function and passing (hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) as 627 * the tag argument.) This function fails if hdr->len is too short to contain a 628 * Retry Integrity Tag. 629 */ 630 int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx, 631 const char *propq, 632 const QUIC_PKT_HDR *hdr, 633 const QUIC_CONN_ID *client_initial_dcid, 634 unsigned char *tag); 635 636 # endif 637 638 #endif 639