code wiki / (root) / nx_blake2b_long_test.nx

nx_blake2b_long_test.nx source

↩ module page · 155 lines · 5830 B

1// nx_blake2b_long_test.nx -- internal-consistency smoke for H'. 2// 3// expect_exit: 0 4// 5// Verifies: 6// 1. H'(T <= 64, A) = BLAKE2b(le32(T) || A, out=T) 7// 2. H'(T > 64, A)[0..31] = BLAKE2b(le32(T) || A, out=64)[0..31] 8// 3. H'(T = 65, A) trailing byte derived correctly. 9// 4. H'(T = 1024, A) -- the Argon2 use case -- runs to completion 10// without buffer overflow; first/last bytes consistent with 11// BLAKE2b chain. 12// 13// license_tier: ORIGINAL 14 15import "nx_syscalls_x86_64.nx" 16import "nx_blake2b.nx" 17import "nx_blake2b_long.nx" 18 19func bytes_eq(a: *u8, b: *u8, n: i64) -> i64 { 20 var i: i64 = 0 21 while i < n { 22 if a[i] != b[i] { return 0 } 23 i = i + 1 24 } 25 return 1 26} 27 28func main() -> i64 { 29 // Shared BLAKE2b scratch. 30 let ctx_raw: *u8 = sys_mmap(NX_BLAKE2B_CTX_BYTES) 31 let ctx: *NxBlake2b = ctx_raw as *NxBlake2b 32 let buf128: *u8 = sys_mmap(128) 33 let scratch_v: *i64 = sys_mmap(128) as *i64 34 let scratch_m: *i64 = sys_mmap(128) as *i64 35 36 let prepend: *u8 = sys_mmap(2048) 37 let prev: *u8 = sys_mmap(64) 38 let curr: *u8 = sys_mmap(64) 39 40 // ---- Test 1: T = 32, A = "abc" ---- 41 // H'(32, "abc") should equal BLAKE2b(le32(32) || "abc", out=32). 42 let input: *u8 = "abc" as *u8 43 let out32: *u8 = sys_mmap(64) 44 if nx_blake2b_long(input, 3, 45 out32, 32, 46 prepend, prev, curr, 47 ctx, buf128, 48 scratch_v, scratch_m) != NX_B2BL_OK { return 1 } 49 // Manual BLAKE2b reference: build le32(32) || "abc" manually. 50 let ref_in: *u8 = sys_mmap(8) 51 ref_in[0] = 32 as u8 52 ref_in[1] = 0 as u8 53 ref_in[2] = 0 as u8 54 ref_in[3] = 0 as u8 55 ref_in[4] = 0x61 as u8 // 'a' 56 ref_in[5] = 0x62 as u8 // 'b' 57 ref_in[6] = 0x63 as u8 // 'c' 58 let ref_out: *u8 = sys_mmap(64) 59 if nx_blake2b_hash(ref_in, 7, 60 0 as *u8, 0, 61 ref_out, 32, 62 ctx, buf128, 63 scratch_v, scratch_m) != NX_BLAKE2B_OK { return 2 } 64 if bytes_eq(out32, ref_out, 32) != 1 { return 3 } 65 66 // ---- Test 2: T = 64, A = "abc" (boundary) ---- 67 let out64: *u8 = sys_mmap(64) 68 if nx_blake2b_long(input, 3, 69 out64, 64, 70 prepend, prev, curr, 71 ctx, buf128, 72 scratch_v, scratch_m) != NX_B2BL_OK { return 10 } 73 ref_in[0] = 64 as u8 74 if nx_blake2b_hash(ref_in, 7, 75 0 as *u8, 0, 76 ref_out, 64, 77 ctx, buf128, 78 scratch_v, scratch_m) != NX_BLAKE2B_OK { return 11 } 79 if bytes_eq(out64, ref_out, 64) != 1 { return 12 } 80 81 // ---- Test 3: T = 65 (first multi-chunk; r = ceil(65/32)-2 = 1) ---- 82 // Per RFC 9106 sec 3.4 with corrected algorithm: 83 // r = 1, loop runs i = 2..r = 2..1 -> EMPTY. 84 // tail_len = T - 32*r = 65 - 32 = 33. 85 // V_last = BLAKE2b(V_1, 33), written to out[r*32 = 32 .. 64]. 86 // So: out[0..31] = V_1[0..31]; out[32..64] = BLAKE2b(V_1, 33). 87 let out65: *u8 = sys_mmap(128) 88 if nx_blake2b_long(input, 3, 89 out65, 65, 90 prepend, prev, curr, 91 ctx, buf128, 92 scratch_v, scratch_m) != NX_B2BL_OK { return 20 } 93 // V_1 = BLAKE2b(le32(65) || "abc", 64). 94 ref_in[0] = 65 as u8 95 let v1: *u8 = sys_mmap(64) 96 if nx_blake2b_hash(ref_in, 7, 97 0 as *u8, 0, 98 v1, 64, 99 ctx, buf128, 100 scratch_v, scratch_m) != NX_BLAKE2B_OK { return 21 } 101 if bytes_eq(out65, v1, 32) != 1 { return 22 } 102 // V_last = BLAKE2b(V_1, 33); out[32..64] should equal V_last. 103 let vlast_33: *u8 = sys_mmap(64) 104 if nx_blake2b_hash(v1, 64, 105 0 as *u8, 0, 106 vlast_33, 33, 107 ctx, buf128, 108 scratch_v, scratch_m) != NX_BLAKE2B_OK { return 23 } 109 var k: i64 = 0 110 while k < 33 { 111 if out65[32 + k] != vlast_33[k] { return 24 } 112 k = k + 1 113 } 114 115 // ---- Test 4: T = 1024 (the Argon2 block size) ---- 116 // r = ceil(1024/32) - 2 = 32 - 2 = 30 117 // Loop runs ii = 2..r = 2..30 (29 iterations), writes V_2..V_30 to 118 // out[32..959]. 119 // Tail: T - 32*r = 1024 - 960 = 64 bytes -> out[960..1023] = 120 // BLAKE2b(V_30, 64). 121 let out1024: *u8 = sys_mmap(2048) 122 if nx_blake2b_long(input, 3, 123 out1024, 1024, 124 prepend, prev, curr, 125 ctx, buf128, 126 scratch_v, scratch_m) != NX_B2BL_OK { return 30 } 127 // First 32 bytes of out1024 = first 32 of BLAKE2b(le32(1024)||"abc", 64). 128 ref_in[0] = 0 as u8 // 1024 = 0x400 -> bytes 0, 4, 0, 0 LE 129 ref_in[1] = 4 as u8 130 ref_in[2] = 0 as u8 131 ref_in[3] = 0 as u8 132 let v1k: *u8 = sys_mmap(64) 133 if nx_blake2b_hash(ref_in, 7, 134 0 as *u8, 0, 135 v1k, 64, 136 ctx, buf128, 137 scratch_v, scratch_m) != NX_BLAKE2B_OK { return 31 } 138 if bytes_eq(out1024, v1k, 32) != 1 { return 32 } 139 140 // ---- BAD_OUT / BAD_ARG ---- 141 if nx_blake2b_long(input, 3, out32, 0, 142 prepend, prev, curr, 143 ctx, buf128, scratch_v, scratch_m) 144 != NX_B2BL_BAD_OUT { return 40 } 145 if nx_blake2b_long(input, -1, out32, 32, 146 prepend, prev, curr, 147 ctx, buf128, scratch_v, scratch_m) 148 != NX_B2BL_BAD_ARG { return 41 } 149 if nx_blake2b_long(input, 3, 0 as *u8, 32, 150 prepend, prev, curr, 151 ctx, buf128, scratch_v, scratch_m) 152 != NX_B2BL_BAD_ARG { return 42 } 153 154 return 0 155}