code wiki / (root) / nx_argon2_block_test.nx

nx_argon2_block_test.nx source

↩ module page · 127 lines · 4235 B

1// nx_argon2_block_test.nx -- algebraic-property smoke for G(X, Y). 2// 3// expect_exit: 0 4// 5// Tests: 6// 1. G(0, 0) = 0 -- all-zero in, all-zero out (R = 0 XOR 0 = 0; 7// GB(0,0,0,0) = (0,0,0,0); final XOR yields 0). 8// 2. G(X, X) = 0 -- self-XOR makes R = 0; same as test 1. 9// 3. G(X, Y) symmetric: G(X, Y) == G(Y, X). R = X XOR Y is 10// symmetric, P operates on R, final XOR R is symmetric. 11// 4. G(X, Y) deterministic: two runs yield same output. 12// 5. G(X, Y) sensitive to a single-bit flip in X (avalanche 13// check): flipping one bit of X must change at least 256 14// bits of output (4x SHA-256-style avalanche; Argon2's G 15// empirically has very strong avalanche due to multiplications). 16// 17// license_tier: ORIGINAL 18 19import "nx_syscalls_x86_64.nx" 20import "nx_argon2_block.nx" 21 22func bytes_eq(a: *u8, b: *u8, n: i64) -> i64 { 23 var i: i64 = 0 24 while i < n { 25 if a[i] != b[i] { return 0 } 26 i = i + 1 27 } 28 return 1 29} 30 31func bits_differ(a: *u8, b: *u8, n: i64) -> i64 { 32 var diff: i64 = 0 33 var i: i64 = 0 34 while i < n { 35 let x: i64 = (a[i] as i64) ^ (b[i] as i64) 36 // popcount of x (0..255). 37 var bit: i64 = 0 38 while bit < 8 { 39 if ((x >> bit) & 1) == 1 { diff = diff + 1 } 40 bit = bit + 1 41 } 42 i = i + 1 43 } 44 return diff 45} 46 47func main() -> i64 { 48 let zero1: *u8 = sys_mmap(1024) 49 let zero2: *u8 = sys_mmap(1024) 50 // mmap returns zeroed memory under Linux MAP_ANONYMOUS, so 51 // zero1 + zero2 are already 1024 zero bytes. 52 53 let out1: *u8 = sys_mmap(1024) 54 let out2: *u8 = sys_mmap(1024) 55 let out3: *u8 = sys_mmap(1024) 56 let r_scratch: *i64 = sys_mmap(1024) as *i64 57 let rs_scratch: *i64 = sys_mmap(1024) as *i64 58 let col_tmp: *i64 = sys_mmap(128) as *i64 59 60 // ---- Test 1: G(0, 0) = 0 ---- 61 if nx_argon2_g(zero1, zero2, out1, 62 r_scratch, rs_scratch, col_tmp) != NX_A2B_OK { return 1 } 63 var i: i64 = 0 64 while i < 1024 { 65 if out1[i] != (0 as u8) { return 2 } 66 i = i + 1 67 } 68 69 // ---- Build a non-trivial X (pattern: i mod 251) ---- 70 let x: *u8 = sys_mmap(1024) 71 let y: *u8 = sys_mmap(1024) 72 i = 0 73 while i < 1024 { 74 x[i] = (i % 251) as u8 75 y[i] = ((i * 7 + 13) % 251) as u8 76 i = i + 1 77 } 78 79 // ---- Test 2: G(X, X) = 0 ---- 80 if nx_argon2_g(x, x, out1, 81 r_scratch, rs_scratch, col_tmp) != NX_A2B_OK { return 10 } 82 i = 0 83 while i < 1024 { 84 if out1[i] != (0 as u8) { return 11 } 85 i = i + 1 86 } 87 88 // ---- Test 3: G(X, Y) symmetric ---- 89 if nx_argon2_g(x, y, out1, 90 r_scratch, rs_scratch, col_tmp) != NX_A2B_OK { return 20 } 91 if nx_argon2_g(y, x, out2, 92 r_scratch, rs_scratch, col_tmp) != NX_A2B_OK { return 21 } 93 if bytes_eq(out1, out2, 1024) != 1 { return 22 } 94 95 // ---- Test 4: determinism ---- 96 if nx_argon2_g(x, y, out3, 97 r_scratch, rs_scratch, col_tmp) != NX_A2B_OK { return 30 } 98 if bytes_eq(out1, out3, 1024) != 1 { return 31 } 99 100 // ---- Test 5: avalanche -- flip one bit of x, expect many bits change ---- 101 let x_flipped: *u8 = sys_mmap(1024) 102 i = 0 103 while i < 1024 { 104 x_flipped[i] = x[i] 105 i = i + 1 106 } 107 x_flipped[0] = (x_flipped[0] as i64 ^ 1) as u8 108 if nx_argon2_g(x_flipped, y, out2, 109 r_scratch, rs_scratch, col_tmp) != NX_A2B_OK { return 40 } 110 let diff: i64 = bits_differ(out1, out2, 1024) 111 // Argon2's G has very strong avalanche due to multiplications. 112 // Expect roughly 50% of bits to flip = ~4096 bits. Require >= 1024 113 // (12.5%) as a conservative lower bound that catches obvious 114 // implementation breakage but doesn't false-fail on statistical 115 // variance. 116 if diff < 1024 { return 41 } 117 118 // ---- BAD_ARG ---- 119 if nx_argon2_g(0 as *u8, y, out1, r_scratch, rs_scratch, col_tmp) 120 != NX_A2B_BAD_ARG { return 50 } 121 if nx_argon2_g(x, 0 as *u8, out1, r_scratch, rs_scratch, col_tmp) 122 != NX_A2B_BAD_ARG { return 51 } 123 if nx_argon2_g(x, y, 0 as *u8, r_scratch, rs_scratch, col_tmp) 124 != NX_A2B_BAD_ARG { return 52 } 125 126 return 0 127}