nx_hmac_candidate_t187.nx
buildroot/runtime/nx_hmac_candidate_t187.nx
about
hmac.nx -- HMAC-SHA-256 (RFC 2104, FIPS 198-1).
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/nist/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).
References:
RFC 2104 (HMAC), FIPS 198-1, NIST SP 800-107. Test vectors
from RFC 4231 (HMAC-SHA-256 specifically).
nx_safety_envelope:
intended_use: "HMAC-SHA-256 -- TLS 1.3 MAC + HKDF foundation
+ general keyed-hash authentication"
sil_target: SIL3 (authentication primitive; MAC
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_sha256.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
| 62 | const HMAC_BLOCK: i64 = 64 // SHA-256 block size |
| 63 | const HMAC_HASH: i64 = 32 // SHA-256 output size |
| 64 | const IPAD: i64 = 0x36 |
| 65 | const OPAD: i64 = 0x5C |
| 128 | const HMAC_E_WORKSPACE:i64=0-2 |
| 129 | const HMAC_E_INPUT:i64=0-1 |
functions
| 68 | func hmac_sha256(key: *u8, key_len: i64, msg: *u8, msg_len: i64, |
| 116 | func main() -> i64 { |
| 130 | func hmac_sha256_workspace_bytes()->i64 |
| 133 | func hmac_sha256_workspace(key:*u8,key_len:i64,msg:*u8,msg_len:i64,out:*u8,workspace:*u8,capacity:i64)->i64 |