ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
quic_crypto.h File Reference

QUIC packet protection: Initial secrets, AEAD payload protection, header protection, and the Retry integrity tag (RFC 9001). More...

Go to the source code of this file.

Classes

struct  QuicPacketKeys
 The client/server packet-protection secrets for one QUIC encryption level. More...
 
struct  QuicInitialSecrets
 Both directions' Initial secrets derived from the client's Destination Connection ID. More...
 
struct  QuicCryptoNs
 Dispatch table. Addressed by offset, so the layout is asserted below. More...
 

Functions

 PROTOCORE_NS_LAYOUT (QuicCryptoNs, derive_initial_secrets, keys_from_secret, packet_protect, packet_unprotect, retry_integrity_tag)
 
void protocore_quic_crypto_derive_initial_secrets (uint8_t *work, uint8_t *keys_work, const uint8_t *dcid, size_t dcid_len, QuicInitialSecrets *out)
 Derive the Initial packet-protection secrets (RFC 9001 sec 5.2). .
 
void protocore_quic_crypto_keys_from_secret (uint8_t *work, uint8_t *keys_work, const uint8_t *secret, QuicPacketKeys *out)
 Expand one traffic secret into a {key, iv, hp} triple (RFC 9001 sec .
 
size_t protocore_quic_crypto_packet_protect (uint8_t *work, uint8_t *pkt, size_t cap, size_t pn_offset, uint8_t pn_len, uint64_t full_pn, size_t payload_len, QuicPacketKeys *keys, proto_bool is_long)
 Protect one QUIC packet in place: AEAD-seal the payload, then apply .
 
size_t protocore_quic_crypto_packet_unprotect (uint8_t *work, uint8_t *pkt, size_t pn_offset, size_t length, uint64_t largest_pn, QuicPacketKeys *keys, proto_bool is_long, uint8_t *out, uint64_t *out_pn)
 Remove header protection and AEAD-open one QUIC packet in place .
 
void protocore_quic_crypto_retry_integrity_tag (uint8_t *work, const uint8_t *odcid, size_t odcid_len, const uint8_t *retry, size_t retry_len, uint8_t *tag)
 Compute the Retry Integrity Tag (RFC 9001 sec 5.8). .
 

Variables

PROTOCORE_NS QuicCryptoNs QuicCrypto PROTOCORE_UNUSED
 Module namespace.
 

Detailed Description

QUIC packet protection: Initial secrets, AEAD payload protection, header protection, and the Retry integrity tag (RFC 9001).

This ties the HKDF key schedule (protocore_hkdf) and AEAD_AES_128_GCM (aes128gcm) into the two QUIC packet-protection operations of RFC 9001 sec 5:

  • QuicCrypto.derive_initial_secrets runs the sec 5.2 Initial key derivation: a fixed salt and the client's Destination Connection ID produce the client and server {key, iv, hp} triples that protect Initial packets (the only keys available before the TLS handshake yields more).
  • QuicCrypto.packet_protect / QuicCrypto.packet_unprotect perform sec 5.3 AEAD payload protection and sec 5.4 header protection together, on a whole packet in a buffer. They take a {key, iv, hp} triple and a header form, so the same code protects Initial, Handshake, and 1-RTT packets - only the secrets differ. AES-128-GCM header protection samples a 16-byte AES-ECB block.
  • QuicCrypto.retry_integrity_tag computes the sec 5.8 Retry Integrity Tag (a fixed-key AEAD over the Retry Pseudo-Packet).

Pure, zero heap, host-tested against RFC 9001 Appendix A (client Initial A.2, server Initial A.3, Retry A.4).

work is bytes the CALLER holds. This module reads none of them: it carries nothing between calls, so there is no state to keep and nothing to wipe. The parameter is there so a caller drives every namespace the same way.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file quic_crypto.h.

Function Documentation

◆ PROTOCORE_NS_LAYOUT()

PROTOCORE_NS_LAYOUT ( QuicCryptoNs  ,
derive_initial_secrets  ,
keys_from_secret  ,
packet_protect  ,
packet_unprotect  ,
retry_integrity_tag   
)

◆ protocore_quic_crypto_derive_initial_secrets()

void protocore_quic_crypto_derive_initial_secrets ( uint8_t *  work,
uint8_t *  keys_work,
const uint8_t *  dcid,
size_t  dcid_len,
QuicInitialSecrets *  out 
)

Derive the Initial packet-protection secrets (RFC 9001 sec 5.2). .

Parameters
workPROTOCORE_QUIC_CRYPTO_BORROW bytes the caller took. Not held past the call.
keys_workKeys work
dcidDcid
dcid_lenDcid len
outOut

◆ protocore_quic_crypto_keys_from_secret()

void protocore_quic_crypto_keys_from_secret ( uint8_t *  work,
uint8_t *  keys_work,
const uint8_t *  secret,
QuicPacketKeys *  out 
)

Expand one traffic secret into a {key, iv, hp} triple (RFC 9001 sec .

Parameters
workPROTOCORE_QUIC_CRYPTO_BORROW bytes the caller took. Not held past the call.
keys_workKeys work
secretPROTOCORE_HKDF_HASH_LEN bytes
outOut

◆ protocore_quic_crypto_packet_protect()

size_t protocore_quic_crypto_packet_protect ( uint8_t *  work,
uint8_t *  pkt,
size_t  cap,
size_t  pn_offset,
uint8_t  pn_len,
uint64_t  full_pn,
size_t  payload_len,
QuicPacketKeys *  keys,
proto_bool  is_long 
)

Protect one QUIC packet in place: AEAD-seal the payload, then apply .

Parameters
workPROTOCORE_QUIC_CRYPTO_BORROW bytes the caller took. Not held past the call.
pktBuffer holding header || plaintext payload; rewritten to header || ciphertext
capCapacity of pkt; must be >= pn_offset + pn_len + payload_len + 16
pn_offsetOffset of the packet number within the header
pn_lenPacket-number length in bytes (1..4)
full_pnFull (untruncated) packet number, for the AEAD nonce
payload_lenPlaintext payload length in bytes
keysThe {key, iv, hp} triple for this encryption level
is_longTrue for a long header (Initial/Handshake), false for a 1-RTT short header
Returns
The size_t.

◆ protocore_quic_crypto_packet_unprotect()

size_t protocore_quic_crypto_packet_unprotect ( uint8_t *  work,
uint8_t *  pkt,
size_t  pn_offset,
size_t  length,
uint64_t  largest_pn,
QuicPacketKeys *  keys,
proto_bool  is_long,
uint8_t *  out,
uint64_t *  out_pn 
)

Remove header protection and AEAD-open one QUIC packet in place .

Parameters
workPROTOCORE_QUIC_CRYPTO_BORROW bytes the caller took. Not held past the call.
pktBuffer holding the protected packet (mutated: header unprotected in place)
pn_offsetOffset of the protected packet number
lengthQUIC Length field (packet-number + payload + tag bytes)
largest_pnLargest packet number already received at this level (0 if none yet)
keysThe {key, iv, hp} triple for this encryption level
is_longTrue for a long header, false for a 1-RTT short header
outOutput plaintext frames (>= length - pn_len - 16 bytes); may alias pkt payload
out_pnReceives the reconstructed full packet number (may be NULL)
Returns
The size_t.

◆ protocore_quic_crypto_retry_integrity_tag()

void protocore_quic_crypto_retry_integrity_tag ( uint8_t *  work,
const uint8_t *  odcid,
size_t  odcid_len,
const uint8_t *  retry,
size_t  retry_len,
uint8_t *  tag 
)

Compute the Retry Integrity Tag (RFC 9001 sec 5.8). .

Parameters
workPROTOCORE_QUIC_CRYPTO_BORROW bytes the caller took. Not held past the call.
odcidOriginal Destination Connection ID (from the client's first Initial)
odcid_lenODCID length in bytes
retryRetry packet bytes from the first byte up to (not including) the tag
retry_lenLength of retry
tagOutput 16-byte integrity tag 16 bytes

Variable Documentation

◆ PROTOCORE_UNUSED

PROTOCORE_NS QuicCryptoNs QuicCrypto PROTOCORE_UNUSED
Initial value:
= {
void protocore_quic_crypto_keys_from_secret(uint8_t *work, uint8_t *keys_work, const uint8_t *secret, QuicPacketKeys *out)
Expand one traffic secret into a {key, iv, hp} triple (RFC 9001 sec .
size_t protocore_quic_crypto_packet_unprotect(uint8_t *work, uint8_t *pkt, size_t pn_offset, size_t length, uint64_t largest_pn, QuicPacketKeys *keys, proto_bool is_long, uint8_t *out, uint64_t *out_pn)
Remove header protection and AEAD-open one QUIC packet in place .
size_t protocore_quic_crypto_packet_protect(uint8_t *work, uint8_t *pkt, size_t cap, size_t pn_offset, uint8_t pn_len, uint64_t full_pn, size_t payload_len, QuicPacketKeys *keys, proto_bool is_long)
Protect one QUIC packet in place: AEAD-seal the payload, then apply .
void protocore_quic_crypto_retry_integrity_tag(uint8_t *work, const uint8_t *odcid, size_t odcid_len, const uint8_t *retry, size_t retry_len, uint8_t *tag)
Compute the Retry Integrity Tag (RFC 9001 sec 5.8). .
void protocore_quic_crypto_derive_initial_secrets(uint8_t *work, uint8_t *keys_work, const uint8_t *dcid, size_t dcid_len, QuicInitialSecrets *out)
Derive the Initial packet-protection secrets (RFC 9001 sec 5.2). .

Module namespace.

Definition at line 140 of file quic_crypto.h.