hkdf.nx
buildroot/runtime/hkdf.nx
about
hkdf.nx -- HKDF-SHA-256 (RFC 5869).
HMAC-based Extract-and-Expand Key Derivation Function. Central
to TLS 1.3 (RFC 8446 §7.1) key schedule:
Early Secret = HKDF-Extract(0, PSK)
Handshake Secret = HKDF-Extract(Derive-Secret(Early, ""), ECDHE)
Master Secret = HKDF-Extract(Derive-Secret(Handshake, ""), 0)
<traffic secrets> = Derive-Secret(<stage>, "<label>", transcript)
Two-stage design:
Extract(salt, IKM) -> PRK
Treats IKM as an entropy source; produces a uniformly-random
pseudorandom key. Implemented as HMAC-SHA-256(salt, IKM).
Expand(PRK, info, L) -> OKM
Deterministically derives L bytes of keying material from PRK
and a context string `info`. Iterates HMAC over a counter.
Properties (RFC 5869 §3.3):
- Deterministic: same (salt, IKM, info, L) -> same OKM.
- Context-binding: different `info` -> independent OKMs.
- Output limited to 255 * HashLen = 8160 bytes for SHA-256.
Invariants:
HK1 PRK is always exactly HashLen (32 bytes for SHA-256).
HK2 Expand iterates exactly ceil(L / HashLen) times; each
iteration feeds the previous output back in, creating a
chain that prevents block-substitution attacks.
HK3 Counter bytes are 1-indexed; wraps at 255 per RFC 5869
§2.3. We cap L at 8160 and refuse larger requests.
HK4 No branches on salt/IKM/info VALUES; branches only on
LENGTHS.
dependencies 2 imports · 0 importers
imports: syscalls.nxnx_hmac.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 39 | const HKDF_HASH: i64 = 32 // SHA-256 output |
| 40 | const HKDF_MAX_L: i64 = 8160 // 255 * 32 |
functions
| 45 | func hkdf_extract(salt: *u8, salt_len: i64, |
| 61 | func hkdf_expand(prk: *u8, |
| 110 | func main() -> i64 |