code wiki / _hdl_build / nx_tor_aes.nx

nx_tor_aes.nx source

↩ module page · 53 lines · 2746 B

1// nx_tor_aes.nx -- AES-128-CTR for the Tor RELAY-cell cipher (tor-spec sec.5.5). THIN wrapper over the 2// existing FIPS-197 AES-128 core (nx_aes.nx): the ONLY difference from nx_aes_ctr.nx is a FULL 128-bit 3// big-endian counter increment (OpenSSL/Tor semantics) instead of the 32-bit low-word increment -- Tor's 4// relay cipher is a CONTINUOUS keystream across many cells, so (a) the counter must carry past byte 12, 5// and (b) it must advance every block INCLUDING the last so the next call/cell resumes at the right block. 6// IV for relay use = 16 zero bytes; the per-hop key Kf/Kb comes from the ntor KDF (Phase 1). 7// 8// Reuses aes128_expand_key + aes128_encrypt_block; no new cipher. Gated vs NIST SP 800-38A F.5.1/F.5.2. 9// license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_aes.nx" // aes128_expand_key, aes128_encrypt_block, AES_BLOCK, AES_EXP_LEN 12 13// Full 128-bit big-endian counter increment (carries across the whole block; OpenSSL AES-CTR semantics). 14func tor_ctr_inc128(ctr: *u8) -> i64 { 15 var i: i64 = 15 16 while i >= 0 { 17 let b: i64 = (ctr[i] as i64) & 0xff 18 if b == 255 { ctr[i] = 0 as u8; i = i - 1 } else { ctr[i] = (b + 1) as u8; return 0 } 19 } 20 return 0 // full wrap 0xff..ff -> 0x00..00 (2^128 blocks; never reached in practice) 21} 22 23// AES-128-CTR crypt (symmetric: encrypt == decrypt). sched = 176-byte expanded key; ctr16 = 16-byte counter 24// block, ADVANCED IN PLACE so a subsequent call continues the same keystream (the Tor relay pattern). 25func tor_aes128_ctr_crypt(sched: *u8, ctr16: *u8, in_buf: *u8, in_len: i64, out_buf: *u8) -> i64 { 26 if in_len <= 0 { return 0 } 27 let ks: *u8 = sys_mmap(32) 28 var off: i64 = 0 29 while off < in_len { 30 aes128_encrypt_block(ctr16, sched, ks) 31 var take: i64 = in_len - off 32 if take > AES_BLOCK { take = AES_BLOCK } 33 var i: i64 = 0 34 while i < take { 35 let pin: *u8 = (in_buf as i64 + off + i) as *u8 36 let pout: *u8 = (out_buf as i64 + off + i) as *u8 37 pout[0] = (((pin[0] as i64) & 0xff) ^ ((ks[i] as i64) & 0xff)) as u8 38 i = i + 1 39 } 40 off = off + take 41 tor_ctr_inc128(ctr16) // advance EVERY block (incl. partial/last) -- continuous-stream correctness 42 } 43 return in_len 44} 45 46// Convenience one-shot: expand key16, seed a fresh counter from iv16, crypt. Tor relay use: iv16 = 16 zeros. 47func tor_aes128_ctr(key16: *u8, iv16: *u8, in_buf: *u8, in_len: i64, out_buf: *u8) -> i64 { 48 let sched: *u8 = sys_mmap(AES_EXP_LEN + 16) 49 aes128_expand_key(key16, sched) 50 let ctr: *u8 = sys_mmap(16) 51 var i: i64 = 0; while i < 16 { ctr[i] = iv16[i]; i = i + 1 } 52 return tor_aes128_ctr_crypt(sched, ctr, in_buf, in_len, out_buf) 53}