code wiki / _hdl_build / nx_chacha_block_dump.nx

nx_chacha_block_dump.nx source

↩ module page · 53 lines · 2543 B

1// nx_chacha_block_dump.nx -- ground-truth oracle for the SIMD ChaCha rung. Inlines the scalar ChaCha20 2// block (RFC 8439 ยง2.3.2 input: key=0..31, nonce=00 00 00 09 00 00 00 4a 00 00 00 00, counter=1) and 3// prints the 64 keystream bytes as decimals. The SIMD ChaCha must reproduce THIS exactly (SIMD==scalar 4// == the KAT'd-correct oracle). No hallucinated vectors. license_tier: ORIGINAL 5import "nx_syscalls.nx" 6 7func u32(x: i64) -> i64 { return x & 0xFFFFFFFF } 8func rotl32(x: i64, r: i64) -> i64 { let a: i64 = (x << r) & 0xFFFFFFFF; let b: i64 = (x & 0xFFFFFFFF) >> (32 - r); return a | b } 9 10func qr(s: *i64, a: i64, b: i64, c: i64, d: i64) -> i64 { 11 s[a] = u32(s[a] + s[b]); s[d] = rotl32(s[d] ^ s[a], 16) 12 s[c] = u32(s[c] + s[d]); s[b] = rotl32(s[b] ^ s[c], 12) 13 s[a] = u32(s[a] + s[b]); s[d] = rotl32(s[d] ^ s[a], 8) 14 s[c] = u32(s[c] + s[d]); s[b] = rotl32(s[b] ^ s[c], 7) 15 return 0 16} 17 18func pn(v: i64) -> i64 { 19 let bb: *u8 = sys_mmap(16); var m: i64 = v; let t: *u8 = sys_mmap(16); var k: i64 = 0 20 if m == 0 { t[0] = 48; k = 1 } 21 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 22 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 23 sys_write(1, bb, k); sys_write(1, "," as *u8, 1); return 0 24} 25 26func main() -> i64 { 27 let s: *i64 = sys_mmap(8 * 16) as *i64 28 let init: *i64 = sys_mmap(8 * 16) as *i64 29 s[0] = 0x61707865; s[1] = 0x3320646e; s[2] = 0x79622d32; s[3] = 0x6b206574 30 s[4] = 0x03020100; s[5] = 0x07060504; s[6] = 0x0b0a0908; s[7] = 0x0f0e0d0c 31 s[8] = 0x13121110; s[9] = 0x17161514; s[10] = 0x1b1a1918; s[11] = 0x1f1e1d1c 32 s[12] = 1; s[13] = 0x09000000; s[14] = 0x4a000000; s[15] = 0x00000000 33 var i: i64 = 0; while i < 16 { init[i] = s[i]; i = i + 1 } 34 var r: i64 = 0 35 while r < 10 { 36 qr(s, 0, 4, 8, 12); qr(s, 1, 5, 9, 13); qr(s, 2, 6, 10, 14); qr(s, 3, 7, 11, 15) 37 qr(s, 0, 5, 10, 15); qr(s, 1, 6, 11, 12); qr(s, 2, 7, 8, 13); qr(s, 3, 4, 9, 14) 38 r = r + 1 39 } 40 var j: i64 = 0; while j < 16 { s[j] = u32(s[j] + init[j]); j = j + 1 } 41 // serialize little-endian, print 64 decimal bytes 42 var k: i64 = 0 43 while k < 16 { 44 pn(s[k] & 0xff); pn((s[k] >> 8) & 0xff); pn((s[k] >> 16) & 0xff); pn((s[k] >> 24) & 0xff) 45 k = k + 1 46 } 47 sys_write(1, "\n" as *u8, 1) 48 // also print the first 4 words (the SIMD gate checks word0..3 = lane values) for a compact KAT 49 sys_write(1, "W0_3=" as *u8, 5) 50 pn(s[0]); pn(s[1]); pn(s[2]); pn(s[3]) 51 sys_write(1, "\n" as *u8, 1) 52 return 0 53}