nx_aes_ctr.nx
buildroot/runtime/nx_aes_ctr.nx
about
nx_aes_ctr.nx -- AES-128 Counter (CTR) mode per NIST SP 800-38A §6.5.
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/nist/sp_800_38a
Composes nx_aes (FIPS 197 AES-128 block cipher) with a counter to
produce a keystream, which is then XOR'd with plaintext to give
ciphertext. CTR is a SYMMETRIC mode: encrypt and decrypt are the
same operation (XOR is self-inverse). Foundation for AES-GCM
(which is CTR + GHASH).
Counter format (this implementation):
bytes 0..11 : nonce / IV (caller-provided, must be unique per
message under the same key -- the "N" in NIST
"nonce")
bytes 12..15 : 32-bit big-endian counter starting at 1
(RFC 3686 and TLS 1.3 use this same shape: 12-byte nonce + 4-byte
counter. SP 800-38A allows other splits; we choose the most-
deployed one.)
Algorithm (SP 800-38A §6.5):
for each 16-byte block i of plaintext:
keystream_i = AES-Encrypt(counter_i, key)
ciphertext_i = plaintext_i XOR keystream_i
counter_i+1 = increment_32(counter_i)
The final block may be partial: only len(plaintext_partial) bytes
of the keystream are used.
SECURITY POSTURE:
CTR-only does NOT authenticate. An attacker that knows the
keystream (e.g. via plaintext recovery or nonce reuse) can flip
arbitrary ciphertext bits and the plaintext flips correspondingly
on decrypt. Production use must compose CTR with an authenticator
(HMAC, Poly1305, or full GCM with GHASH). Substrate's named
improvement: nx_aes_gcm.nx (queued).
NONCE-REUSE WARNING:
Two messages encrypted with the same (key, nonce) leak the XOR
dependencies 2 imports · 4 importers
imports: nx_syscalls.nxnx_aes.nx
imported by: nx_aes_ctr_helper_test.nxnx_aes_ctr_test.nxnx_cenc.nxnx_cenc_gate.nx
structs
| none |
consts
| 72 | const AES_CTR_NONCE_LEN: i64 = 12 |
functions
| 78 | func _aes_ctr_inc(block: *u8) -> i64 called by 1: aes128_ctr_xor |
| 101 | func aes128_ctr_build_icb(icb: *u8, nonce: *u8, start_counter: i64) -> i64 called by 1: main |
| 120 | func aes128_ctr_xor(sched: *u8, icb: *u8, in_buf: *u8, in_len: i64, out_buf: *u8) -> i64 |