nx_p256_scalar_mul_test.nx source
↩ module page · 120 lines · 4156 B
1// nx_p256_scalar_mul_test.nx -- KAT for P-256 scalar multiplication.
2//
3// Verifies for small k values:
4// - 0 * G = O
5// - 1 * G = G
6// - 2 * G = double(G)
7// - 3 * G = G + 2G
8// - 4 * G = double(2G) = via scalar_mul(4, G)
9// - 256 * G = 8 doublings of G
10// - aliasing: out aliases p in scalar_mul
11// - 0 * O = O, k * O = O for various k
12//
13// Larger k values are exercised indirectly via the ECDSA verify
14// KAT (queued for piece 4) -- 256-bit scalars take ~2-3s each in
15// the slow form and would push smoke runtime past budget.
16//
17// expect_exit: 0
18// license_tier: ORIGINAL
19
20import "nx_syscalls.nx"
21import "nx_u256.nx"
22import "nx_p256_field.nx"
23import "nx_p256_point.nx"
24import "nx_p256_point_add.nx"
25import "nx_p256_scalar_mul.nx"
26
27func main() -> i64 {
28 let G: *P256Point = p256_point_alloc()
29 p256_point_load_g(G)
30 let O: *P256Point = p256_point_alloc()
31 p256_point_zero(O)
32
33 let k: *i64 = u256_alloc()
34 let r: *P256Point = p256_point_alloc()
35
36 // ---- Test A: 0 * G = O ----
37 u256_zero(k)
38 p256_scalar_mul(r, k, G)
39 if p256_point_is_infinity(r) != 1 { return 1 }
40
41 // ---- Test B: 1 * G = G ----
42 u256_zero(k); k[0] = 1
43 p256_scalar_mul(r, k, G)
44 if p256_point_eq(r, G) != 1 { return 2 }
45
46 // ---- Test C: 2 * G via scalar_mul matches double(G) ----
47 let two_G_dbl: *P256Point = p256_point_alloc()
48 p256_point_double(two_G_dbl, G)
49 u256_zero(k); k[0] = 2
50 p256_scalar_mul(r, k, G)
51 if p256_point_eq(r, two_G_dbl) != 1 { return 3 }
52
53 // ---- Test D: 3 * G via scalar_mul matches G + 2G ----
54 let three_G_add: *P256Point = p256_point_alloc()
55 p256_point_add(three_G_add, G, two_G_dbl)
56 u256_zero(k); k[0] = 3
57 p256_scalar_mul(r, k, G)
58 if p256_point_eq(r, three_G_add) != 1 { return 4 }
59
60 // ---- Test E: 4 * G via scalar_mul matches double(2G) ----
61 let four_G_dbl: *P256Point = p256_point_alloc()
62 p256_point_double(four_G_dbl, two_G_dbl)
63 u256_zero(k); k[0] = 4
64 p256_scalar_mul(r, k, G)
65 if p256_point_eq(r, four_G_dbl) != 1 { return 5 }
66
67 // ---- Test F: 8 * G via scalar_mul matches double(4G) ----
68 let eight_G_dbl: *P256Point = p256_point_alloc()
69 p256_point_double(eight_G_dbl, four_G_dbl)
70 u256_zero(k); k[0] = 8
71 p256_scalar_mul(r, k, G)
72 if p256_point_eq(r, eight_G_dbl) != 1 { return 6 }
73
74 // ---- Test G: 256 * G via scalar_mul matches 8 successive doubles ----
75 let p2: *P256Point = p256_point_alloc()
76 p256_point_double(p2, G) // 2G
77 p256_point_double(p2, p2) // 4G
78 p256_point_double(p2, p2) // 8G
79 p256_point_double(p2, p2) // 16G
80 p256_point_double(p2, p2) // 32G
81 p256_point_double(p2, p2) // 64G
82 p256_point_double(p2, p2) // 128G
83 p256_point_double(p2, p2) // 256G
84 u256_zero(k); k[0] = 256
85 p256_scalar_mul(r, k, G)
86 if p256_point_eq(r, p2) != 1 { return 7 }
87
88 // ---- Test H: k * O = O for various k ----
89 u256_zero(k); k[0] = 5
90 p256_scalar_mul(r, k, O)
91 if p256_point_is_infinity(r) != 1 { return 10 }
92 u256_zero(k); k[7] = 0x12345678
93 p256_scalar_mul(r, k, O)
94 if p256_point_is_infinity(r) != 1 { return 11 }
95
96 // ---- Test I: aliasing -- out aliases p ----
97 let aliased: *P256Point = p256_point_alloc()
98 p256_point_copy(aliased, G)
99 u256_zero(k); k[0] = 3
100 p256_scalar_mul(aliased, k, aliased) // aliased := 3 * aliased
101 if p256_point_eq(aliased, three_G_add) != 1 { return 20 }
102
103 // ---- Test J: distributivity-via-add (k1+k2)*P = k1*P + k2*P
104 // for small k1, k2 ----
105 // (k1, k2) = (3, 4) -> 7*G should equal 3G + 4G
106 u256_zero(k); k[0] = 3
107 let three_G: *P256Point = p256_point_alloc()
108 p256_scalar_mul(three_G, k, G)
109 u256_zero(k); k[0] = 4
110 let four_G: *P256Point = p256_point_alloc()
111 p256_scalar_mul(four_G, k, G)
112 let seven_G_add: *P256Point = p256_point_alloc()
113 p256_point_add(seven_G_add, three_G, four_G)
114 u256_zero(k); k[0] = 7
115 let seven_G_mul: *P256Point = p256_point_alloc()
116 p256_scalar_mul(seven_G_mul, k, G)
117 if p256_point_eq(seven_G_mul, seven_G_add) != 1 { return 30 }
118
119 return 0
120}