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}