nx_aes.nx
buildroot/runtime/nx_aes.nx
about
nx_aes.nx -- AES-128 block cipher (FIPS 197).
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/nist/fips_197
128-bit key, 128-bit block, 10 rounds. Substrate-original NishiLang
implementation of the Rijndael algorithm as specified by FIPS PUB
197 (NIST, 2001). Closes substrate's symmetric-cipher gap alongside
the existing nx_chacha20 stream cipher; required for TLS 1.3
interop (TLS_AES_128_GCM_SHA256 is the most common cipher suite).
Algorithm (FIPS 197 §5):
Encrypt(plaintext, expanded_key):
state = plaintext XOR round_key[0]
for round in 1..9:
state = SubBytes(state)
state = ShiftRows(state)
state = MixColumns(state)
state = state XOR round_key[round]
state = SubBytes(state)
state = ShiftRows(state)
state = state XOR round_key[10]
return state
KeyExpansion (FIPS 197 §5.2): expands the 128-bit key into 11
128-bit round keys (176 bytes total). Each new word is either
XOR of previous + word-4-back, or (every 4 words) goes through
RotWord -> SubWord -> XOR with Rcon.
State layout: 16-byte array indexed [r,c] = state[r + 4*c] per
FIPS 197 §3.4 (column-major in the bytes-on-the-wire order).
TIMING SIDE-CHANNEL POSTURE (honest):
The S-box is implemented as a 256-byte table lookup with
secret-dependent index. On shared-cache architectures this
leaks key bits via cache-timing analysis (Bernstein 2005).
Substrate-acceptable for MCU/sensor targets where there is no
shared cache. For server-class targets, substrate's named
improvement is BITSLICE-AES which is timing-side-channel
resistant by construction; queued as nx_aes_bitslice.nx.
dependencies 2 imports · 14 importers
diagram shows first 10 each side; +0 more imports, +4 more importers in the complete lists below.
imports: nx_syscalls.nxnx_safety.nx
imported by: nx_aes128_gcm.nxnx_aes256_gcm.nxnx_aes_cbc.nxnx_aes_cbc_enc.nxnx_aes_ctr.nxnx_aes_ctr_helper_test.nxnx_aes_ctr_test.nxnx_aes_test.nxnx_cenc.nxnx_cenc_gate.nxnx_hls_get.nxnx_mtls_pkcs12.nxnx_tor_aes.nxnx_tor_aes_gate.nx
structs
| none |
consts
| 141 | const AES_BLOCK: i64 = 16 |
| 142 | const AES_KEY: i64 = 16 // 128-bit key |
| 143 | const AES_ROUNDS: i64 = 10 |
| 144 | const AES_EXP_LEN: i64 = 176 // 11 round keys * 16 bytes |
functions
| 102 | func _nx_aes_evidence_ids() -> *i64 |
| 113 | func _nx_aes_hazard_ids() -> *i64 |
| 123 | func nx_aes_safety_envelope() -> *SafetyEnvelope |
| 153 | func _aes_sbox(i: i64) -> i64 |
| 226 | func _aes_rcon(i: i64) -> i64 |
| 245 | func _aes_xtime(b: i64) -> i64 |
| 258 | func aes128_expand_key(key: *u8, out: *u8) -> i64 |
| 311 | func _aes_sub_bytes(state: *u8) -> i64 |
| 326 | func _aes_shift_rows(state: *u8) -> i64 |
| 363 | func _aes_mix_columns(state: *u8) -> i64 |
| 390 | func _aes_add_round_key(state: *u8, sched: *u8, round: i64) -> i64 |
| 409 | func aes128_encrypt_block_sw(in_block: *u8, sched: *u8, out_block: *u8) -> i64 |
| 429 | func aes128_encrypt_block(in_block: *u8, sched: *u8, out_block: *u8) -> i64 |
| 438 | func _aes_inv_sbox(i: i64) -> i64 called by 1: _aes_inv_sub_bytes |
| 508 | func _aes_inv_sub_bytes(state: *u8) -> i64 |
| 522 | func _aes_inv_shift_rows(state: *u8) -> i64 called by 1: aes128_decrypt_block |
| 557 | func _aes_inv_mix_columns(state: *u8) -> i64 |
| 631 | func aes128_decrypt_block(in_block: *u8, sched: *u8, out_block: *u8) -> i64 |