code wiki / (root) / hmac.nx

hmac.nx

buildroot/runtime/hmac.nx

4472 B110 linesdepth 6pulls 6 transitivereach 0 importersview sourcekind tooltopic hmac
docsdependenciesstructsconstsfunctions

about

############################################################################################ ## DO NOT IMPORT THIS FILE. USE nx_hmac.nx INSTEAD. (2026-07-31, debt 1785524913) ## ## This is a CODE-IDENTICAL twin of nx_hmac.nx (49/49 statements) that hangs off the ## ## LEGACY syscalls.nx + sha256.nx family. Both files define hmac_sha256 AND main, and the ## ## import expander dedupes BY FILE PATH, NOT BY SYMBOL -- so importing this one anywhere ## ## the nx_ family is also reachable produces `duplicate definition of hmac_sha256` and ## ## breaks EVERY organ in that closure. That is not hypothetical: it happened the moment ## ## nx_https_fetch_follow began importing nx_tls12_req (which imported this file), and it ## ## broke the whole research-fetch family until all 9 importers were repointed. ## ## Kept (not deleted) so no work is destroyed; importers: 0. Keep it that way. ## ############################################################################################ hmac.nx -- HMAC-SHA-256 (RFC 2104, FIPS 198-1). Keyed-hash MAC built on sha256.nx. Used throughout TLS 1.3 key schedule (RFC 8446 ยง7.1) as the HKDF primitive, in older TLS as Finished-message signer, and wherever we need a symmetric authenticator without a fresh nonce (unlike Poly1305). Construction (RFC 2104): HMAC(K, M) = H( (K' xor opad) || H( (K' xor ipad) || M ) ) where H = SHA-256, block size B = 64 bytes, and K' = - H(K) if len(K) > B -- pre-hash oversized keys - K || zeros if len(K) < B -- zero-pad short keys - K if len(K) == B ipad = 0x36 repeated; opad = 0x5c repeated. Why not Poly1305 everywhere: - Poly1305 is one-time-key (P4 in poly1305.nx); reusing a key across messages breaks it. HMAC is many-to-one: a long-lived HMAC key authenticates many messages safely. TLS transcripts span the whole handshake so HMAC is the right tool there. Invariants: HM1 Key processing depends only on key LENGTH, not key VALUE: short keys zero-padded, long keys pre-hashed through SHA- 256 (which is constant-time by construction). HM2 XOR loops read every byte of the block regardless of key content; no early exit. HM3 Output is exactly 32 bytes (SHA-256 digest width).

dependencies 2 imports · 0 importers

syscalls.nx sha256.nx hmac.nx

imports: syscalls.nxsha256.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main hmac_sha256

structs

none

consts

48const HMAC_BLOCK: i64 = 64 // SHA-256 block size
49const HMAC_HASH: i64 = 32 // SHA-256 output size
50const IPAD: i64 = 0x36
51const OPAD: i64 = 0x5C

functions

54func hmac_sha256(key: *u8, key_len: i64, msg: *u8, msg_len: i64,
called by 1: main
102func main() -> i64
calls 1: hmac_sha256