nx_p256_point_add_test.nx source
↩ module page · 121 lines · 4502 B
1// nx_p256_point_add_test.nx -- KAT for P-256 Jacobian point addition.
2//
3// Verifies:
4// - G + O = G (infinity identity)
5// - O + G = G (commutative identity)
6// - O + O = O (infinity-only)
7// - G + G = 2G (matches point_double(G))
8// - G + (-G) = O (additive inverse)
9// - G + 2G is on curve, != G, != 2G, != O
10// - (G + 2G) + G = 4G (cross-check: 4G also = double(2G))
11// - 2G + G = G + 2G (commutativity)
12// - (G + 2G) + G = G + (2G + G) (associativity spot-check)
13// - aliasing: out aliases p1, out aliases p2, all aliases
14//
15// expect_exit: 0
16// license_tier: ORIGINAL
17
18import "nx_syscalls.nx"
19import "nx_u256.nx"
20import "nx_p256_field.nx"
21import "nx_p256_field_mul.nx"
22import "nx_p256_point.nx"
23import "nx_p256_point_add.nx"
24
25func main() -> i64 {
26 let G: *P256Point = p256_point_alloc()
27 p256_point_load_g(G)
28 let O: *P256Point = p256_point_alloc()
29 p256_point_zero(O)
30
31 // ---- Test A: G + O = G ----
32 let r: *P256Point = p256_point_alloc()
33 p256_point_add(r, G, O)
34 if p256_point_eq(r, G) != 1 { return 1 }
35
36 // ---- Test B: O + G = G ----
37 p256_point_add(r, O, G)
38 if p256_point_eq(r, G) != 1 { return 2 }
39
40 // ---- Test C: O + O = O ----
41 p256_point_add(r, O, O)
42 if p256_point_is_infinity(r) != 1 { return 3 }
43
44 // ---- Test D: G + G = 2G (matches double) ----
45 let two_G_dbl: *P256Point = p256_point_alloc()
46 p256_point_double(two_G_dbl, G)
47 let two_G_add: *P256Point = p256_point_alloc()
48 p256_point_add(two_G_add, G, G)
49 if p256_point_eq(two_G_add, two_G_dbl) != 1 { return 4 }
50
51 // ---- Test E: G + (-G) = O ----
52 // -G has same x, y_neg = p - Gy.
53 let neg_G: *P256Point = p256_point_alloc()
54 let neg_Gy: *i64 = u256_alloc()
55 p256_field_neg(neg_Gy, G.y)
56 p256_point_set_affine(neg_G, G.x, neg_Gy)
57 p256_point_add(r, G, neg_G)
58 if p256_point_is_infinity(r) != 1 { return 5 }
59
60 // ---- Test F: G + 2G = 3G is on curve, != G, != 2G, != O ----
61 let three_G: *P256Point = p256_point_alloc()
62 p256_point_add(three_G, G, two_G_add)
63 if p256_point_is_infinity(three_G) == 1 { return 6 }
64 p256_point_to_affine(three_G)
65 if p256_point_on_curve(three_G) != 1 { return 7 }
66 if p256_point_eq(three_G, G) == 1 { return 8 }
67 if p256_point_eq(three_G, two_G_add) == 1 { return 9 }
68
69 // ---- Test G: 4G via two paths ----
70 // path 1: double(2G)
71 let four_G_dbl: *P256Point = p256_point_alloc()
72 p256_point_double(four_G_dbl, two_G_add)
73 // path 2: (G + 2G) + G = 3G + G
74 let four_G_add: *P256Point = p256_point_alloc()
75 p256_point_add(four_G_add, three_G, G)
76 if p256_point_eq(four_G_add, four_G_dbl) != 1 { return 10 }
77
78 // ---- Test H: commutativity 2G + G = G + 2G ----
79 let comm1: *P256Point = p256_point_alloc()
80 let comm2: *P256Point = p256_point_alloc()
81 p256_point_add(comm1, two_G_add, G)
82 p256_point_add(comm2, G, two_G_add)
83 if p256_point_eq(comm1, comm2) != 1 { return 11 }
84
85 // ---- Test I: associativity (G + 2G) + G == G + (2G + G) ----
86 let assoc1: *P256Point = p256_point_alloc()
87 let assoc2: *P256Point = p256_point_alloc()
88 let g_plus_2g: *P256Point = p256_point_alloc()
89 p256_point_add(g_plus_2g, G, two_G_add)
90 p256_point_add(assoc1, g_plus_2g, G) // (G + 2G) + G
91 let two_g_plus_g: *P256Point = p256_point_alloc()
92 p256_point_add(two_g_plus_g, two_G_add, G)
93 p256_point_add(assoc2, G, two_g_plus_g) // G + (2G + G)
94 if p256_point_eq(assoc1, assoc2) != 1 { return 12 }
95
96 // ---- Test J: aliasing -- out aliases p1 ----
97 let p: *P256Point = p256_point_alloc()
98 let q: *P256Point = p256_point_alloc()
99 p256_point_copy(p, G)
100 p256_point_copy(q, two_G_add)
101 p256_point_add(p, p, q) // p := p + q
102 if p256_point_eq(p, three_G) != 1 { return 13 }
103
104 // ---- Test K: aliasing -- out aliases p2 ----
105 p256_point_copy(p, G)
106 p256_point_copy(q, two_G_add)
107 p256_point_add(q, p, q) // q := p + q
108 if p256_point_eq(q, three_G) != 1 { return 14 }
109
110 // ---- Test L: 8G via 4G + 4G ----
111 let eight_G: *P256Point = p256_point_alloc()
112 p256_point_add(eight_G, four_G_dbl, four_G_dbl)
113 p256_point_to_affine(eight_G)
114 if p256_point_on_curve(eight_G) != 1 { return 15 }
115 // Cross-check: 8G via double(double(2G))
116 let eight_G_dbl: *P256Point = p256_point_alloc()
117 p256_point_double(eight_G_dbl, four_G_dbl)
118 if p256_point_eq(eight_G, eight_G_dbl) != 1 { return 16 }
119
120 return 0
121}