nx_p256_modn_test.nx source
↩ module page · 138 lines · 4482 B
1// nx_p256_modn_test.nx -- KAT for arithmetic in Z/nZ where n is
2// the NIST P-256 group order.
3//
4// expect_exit: 0
5// license_tier: ORIGINAL
6
7import "nx_syscalls.nx"
8import "nx_u256.nx"
9import "nx_p256_modn.nx"
10
11func main() -> i64 {
12 let a: *i64 = u256_alloc()
13 let b: *i64 = u256_alloc()
14 let r: *i64 = u256_alloc()
15 let tmp: *i64 = u256_alloc()
16 let n: *i64 = u256_alloc()
17 p256_modn_load_n(n)
18 let one: *i64 = u256_alloc()
19 p256_modn_one(one)
20
21 // ---- Test A: load_n byte-exact (BE bytes against FIPS 186-5) ----
22 let n_bytes: *u8 = sys_mmap(32)
23 u256_store_be(n_bytes, n)
24 // Expected BE: FF FF FF FF 00 00 00 00 FF FF FF FF FF FF FF FF
25 // BC E6 FA AD A7 17 9E 84 F3 B9 CA C2 FC 63 25 51
26 if (n_bytes[0] & 0xff) != 0xFF { return 1 }
27 if (n_bytes[3] & 0xff) != 0xFF { return 2 }
28 if (n_bytes[4] & 0xff) != 0x00 { return 3 }
29 if (n_bytes[7] & 0xff) != 0x00 { return 4 }
30 if (n_bytes[15] & 0xff) != 0xFF { return 5 }
31 if (n_bytes[16] & 0xff) != 0xBC { return 6 }
32 if (n_bytes[28] & 0xff) != 0xFC { return 7 }
33 if (n_bytes[31] & 0xff) != 0x51 { return 8 }
34
35 // ---- Test B: load_n_minus_2 differs only in LSB limb ----
36 let nm2: *i64 = u256_alloc()
37 p256_modn_load_n_minus_2(nm2)
38 if nm2[0] != 0xFC63254F { return 11 }
39 var i: i64 = 1
40 while i < 8 {
41 if (nm2[i] & 0xFFFFFFFF) != (n[i] & 0xFFFFFFFF) { return 12 + i }
42 i = i + 1
43 }
44
45 // ---- Test C: add 1 + 1 = 2 ----
46 p256_modn_one(a)
47 p256_modn_one(b)
48 p256_modn_add(r, a, b)
49 if r[0] != 2 { return 20 }
50
51 // ---- Test D: (n-1) + 1 = 0 (boundary wrap) ----
52 let nm1: *i64 = u256_alloc()
53 u256_copy(nm1, n)
54 p256_modn_sub(nm1, nm1, one)
55 p256_modn_add(r, nm1, one)
56 if u256_is_zero(r) != 1 { return 30 }
57
58 // ---- Test E: 0 - 1 = n-1 (underflow + add-n) ----
59 p256_modn_zero(a)
60 p256_modn_sub(r, a, one)
61 if p256_modn_eq(r, nm1) != 1 { return 40 }
62
63 // ---- Test F: -1 = n-1 ----
64 p256_modn_neg(r, one)
65 if p256_modn_eq(r, nm1) != 1 { return 50 }
66
67 // ---- Test G: a*1 = a ----
68 u256_zero(a)
69 a[0] = 0x12345678; a[3] = 0xABCDEF01; a[5] = 0x55555555
70 if u256_cmp(a, n) != (0 - 1) { return 60 } // canonical check
71 p256_modn_mul(r, a, one)
72 if p256_modn_eq(r, a) != 1 { return 61 }
73
74 // ---- Test H: 2 * 3 = 6 ----
75 u256_zero(a); a[0] = 2
76 u256_zero(b); b[0] = 3
77 p256_modn_mul(r, a, b)
78 if r[0] != 6 { return 70 }
79 i = 1
80 while i < 8 {
81 if r[i] != 0 { return 71 }
82 i = i + 1
83 }
84
85 // ---- Test I: (n-1) * (n-1) = 1 (since -1 * -1 = 1 mod n) ----
86 p256_modn_mul(r, nm1, nm1)
87 if p256_modn_eq(r, one) != 1 { return 80 }
88
89 // ---- Test J: commutativity a*b == b*a ----
90 u256_zero(a); a[0] = 0x11111111; a[3] = 0x22222222
91 u256_zero(b); b[1] = 0xABCDEF01; b[7] = 0x00FFFFFF
92 if u256_cmp(a, n) != (0 - 1) { return 90 }
93 if u256_cmp(b, n) != (0 - 1) { return 91 }
94 let r2: *i64 = u256_alloc()
95 p256_modn_mul(r, a, b)
96 p256_modn_mul(r2, b, a)
97 if p256_modn_eq(r, r2) != 1 { return 92 }
98
99 // ---- Test K: inv(1) = 1 ----
100 p256_modn_inv(r, one)
101 if p256_modn_eq(r, one) != 1 { return 100 }
102
103 // ---- Test L: inv(2) * 2 = 1 ----
104 u256_zero(a); a[0] = 2
105 p256_modn_inv(r, a)
106 p256_modn_mul(r2, r, a)
107 if p256_modn_eq(r2, one) != 1 { return 110 }
108
109 // ---- Test M: random a * inv(a) = 1 ----
110 u256_zero(a)
111 a[0] = 0xDEADBEEF; a[2] = 0xCAFEBABE; a[5] = 0x77777777
112 if u256_cmp(a, n) != (0 - 1) { return 120 }
113 p256_modn_inv(r, a)
114 p256_modn_mul(r2, r, a)
115 if p256_modn_eq(r2, one) != 1 { return 121 }
116
117 // ---- Test N: reduce(a) where a < n -> a unchanged ----
118 u256_zero(a); a[0] = 0x12345678
119 p256_modn_reduce(r, a)
120 if p256_modn_eq(r, a) != 1 { return 130 }
121
122 // ---- Test O: reduce(a) where a == 2^256 - 1 (> n) ----
123 i = 0
124 while i < 8 { a[i] = 0xFFFFFFFF; i = i + 1 }
125 // a = 2^256 - 1; n = 2^256 - 2^224 + 2^192 + (some bits); a > n.
126 // Expected: a - n
127 p256_modn_reduce(r, a)
128 // Verify r = (2^256 - 1) - n via re-add: r + n should equal a (with overflow).
129 let check: *i64 = u256_alloc()
130 let carry: i64 = u256_add_with_carry(check, r, n)
131 // Since (2^256 - 1) + n - n = 2^256 - 1, we expect carry == 0 and check == a.
132 if carry != 0 { return 140 }
133 if u256_eq(check, a) != 1 { return 141 }
134 // Also: r < n
135 if u256_cmp(r, n) != (0 - 1) { return 142 }
136
137 return 0
138}