Skip to content

net/tls: TLS 1.3 / DTLS 1.3 (epic, in progress)#371

Draft
haaspors wants to merge 8 commits into
masterfrom
net-tls13-329
Draft

net/tls: TLS 1.3 / DTLS 1.3 (epic, in progress)#371
haaspors wants to merge 8 commits into
masterfrom
net-tls13-329

Conversation

@haaspors

Copy link
Copy Markdown
Owner

Implements #329 incrementally on one branch (per discussion), to be merged once
the epic is complete. Built bottom-up; each commit is independently green so CI
is exercised along the way.

Foundation so far

  • crypto: HKDF-Extract / HKDF-Expand (RFC 5869), on the existing HMAC.
  • net/tls: the TLS 1.3 key-schedule primitives r_tls13_expand_label /
    r_tls13_derive_secret (RFC 8446 §7.1), verified against RFC 8448 vectors, in
    a new proto/rtls13.
  • net/tls: split the legacy (<=1.2) PRF into proto/rtls12, leaving
    proto/rtls as the version-agnostic wire layer beside rtls12 / rtls13.

Roadmap (subsequent commits on this branch)

  • Protocol plumbing: 1.3 cipher-suite constants, new handshake messages
    (EncryptedExtensions, KeyUpdate, …) and extensions (supported_versions,
    key_share, …), and the AEAD-only 1.3 record path.
  • The 1-RTT handshake (server + client), branched on supported_versions.
  • Then HelloRetryRequest, PSK resumption + 1.3 NewSessionTicket, 0-RTT, DTLS 1.3,
    and RFC 7507 downgrade detection.

Draft until the handshake is usable end-to-end.

Closes #329

haaspors added 8 commits June 16, 2026 11:41
Add r_hkdf_extract and r_hkdf_expand on top of the existing HMAC -- the
extract-then-expand KDF the TLS 1.3 key schedule (and other callers) build on.
Verified against the RFC 5869 SHA-256 test vectors.
Add rtls13.{c,h} with r_tls13_expand_label (the "tls13 "-prefixed HkdfLabel over
HKDF-Expand) and r_tls13_derive_secret (Expand-Label bound to a transcript hash)
-- the building blocks of the RFC 8446 7.1 key schedule. Verified against the
canonical SHA-256 early-secret and "derived" values from RFC 8448. The
secret-chain orchestration (handshake/master/traffic secrets) lands with the 1.3
handshake that consumes it.
…nostic

Move the TLS <=1.2 PRF family (RTLSPrfFunc, r_tls_1_0_prf, r_tls_1_2_prf_*) and
the r_tls_prf_and_hash_for selector out of proto/rtls into a new proto/rtls12, so
proto/rtls is the version-agnostic wire layer (record, framing, extensions,
suites) sitting beside proto/rtls12 (<=1.2 PRF) and proto/rtls13 (1.3 key
schedule). Pure code move, no behaviour change.
Add the 1.3 suite code points -- TLS_AES_128_GCM_SHA256 (0x1301),
TLS_AES_256_GCM_SHA384 (0x1302), TLS_CHACHA20_POLY1305_SHA256 (0x1303) -- and
table entries for the two AES-GCM suites. A 1.3 suite names only the AEAD and the
hash; the key exchange is negotiated separately (key_share), so key_exchange is
NULL. ChaCha20-Poly1305 gets a code point but no entry until a Poly1305
implementation exists.
Register the 1.3 HandshakeType code points (end_of_early_data, encrypted_extensions,
key_update, message_hash) and the new ExtensionType code points (pre_shared_key,
early_data, supported_versions, cookie, psk_key_exchange_modes,
certificate_authorities, oid_filters, post_handshake_auth, signature_algorithms_cert,
key_share). Constants only -- the parse/write helpers and the 1.3 record path follow.
Add bounds-clamped accessors for the supported_versions extension: the
ClientHello version list (count / indexed getter / a contains() walk that stays
inside the declared length) and the single version a ServerHello or
HelloRetryRequest selects. Version negotiation keys off this -- the server reads
the ClientHello list to detect a 1.3-capable peer, the client confirms the
server's selection -- so it lands before the handshake that uses it.
Add a KeyShareEntry type and bounds-clamped accessors for the three forms the
key_share extension takes: the ClientHello client_shares list (first/next
iterator), the single ServerHello server_share, and the HelloRetryRequest
selected_group. Each KeyShareEntry { group, key_exchange } is validated to sit
inside the extension's declared length so a bogus inner length can't over-read.
This is the offered/negotiated (EC)DHE material the 1.3 handshake consumes.
Add the 1.3 record layer to proto/rtls13: the per-record nonce (static IV XORed
with the big-endian sequence number, RFC 8446 5.3), and protect/unprotect over a
TLSCiphertext. Protect appends the inner content-type byte to form the
TLSInnerPlaintext and seals it; unprotect opens it, strips the optional trailing
zero padding, and recovers the real content type. The additional_data is the
5-byte record header and the tag is 16 bytes (the AES-GCM 1.3 suites).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

net/tls: TLS 1.3 / DTLS 1.3 support

1 participant