1use super::{
16 elem::{binary_op, binary_op_assign},
17 elem_sqr_mul, elem_sqr_mul_acc, Modulus, *,
18};
19use core::marker::PhantomData;
20
21macro_rules! p256_limbs {
22 [ $($limb:expr),+ ] => {
23 limbs![$($limb),+, 0, 0, 0, 0]
24 };
25}
26
27pub static COMMON_OPS: CommonOps = CommonOps {
28 num_limbs: 256 / LIMB_BITS,
29
30 q: Modulus {
31 p: p256_limbs![
32 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
33 0xffffffff
34 ],
35 rr: p256_limbs![
36 0x00000003, 0x00000000, 0xffffffff, 0xfffffffb, 0xfffffffe, 0xffffffff, 0xfffffffd,
37 0x00000004
38 ],
39 },
40
41 n: Elem {
42 limbs: p256_limbs![
43 0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, 0xffffffff, 0xffffffff, 0x00000000,
44 0xffffffff
45 ],
46 m: PhantomData,
47 encoding: PhantomData, },
49
50 a: Elem {
51 limbs: p256_limbs![
52 0xfffffffc, 0xffffffff, 0xffffffff, 0x00000003, 0x00000000, 0x00000000, 0x00000004,
53 0xfffffffc
54 ],
55 m: PhantomData,
56 encoding: PhantomData, },
58 b: Elem {
59 limbs: p256_limbs![
60 0x29c4bddf, 0xd89cdf62, 0x78843090, 0xacf005cd, 0xf7212ed6, 0xe5a220ab, 0x04874834,
61 0xdc30061d
62 ],
63 m: PhantomData,
64 encoding: PhantomData, },
66
67 elem_add_impl: GFp_nistz256_add,
68 elem_mul_mont: GFp_nistz256_mul_mont,
69 elem_sqr_mont: GFp_nistz256_sqr_mont,
70
71 point_add_jacobian_impl: GFp_nistz256_point_add,
72};
73
74pub static PRIVATE_KEY_OPS: PrivateKeyOps = PrivateKeyOps {
75 common: &COMMON_OPS,
76 elem_inv_squared: p256_elem_inv_squared,
77 point_mul_base_impl: p256_point_mul_base_impl,
78 point_mul_impl: GFp_nistz256_point_mul,
79};
80
81fn p256_elem_inv_squared(a: &Elem<R>) -> Elem<R> {
82 #[inline]
89 fn sqr_mul(a: &Elem<R>, squarings: usize, b: &Elem<R>) -> Elem<R> {
90 elem_sqr_mul(&COMMON_OPS, a, squarings, b)
91 }
92
93 #[inline]
94 fn sqr_mul_acc(a: &mut Elem<R>, squarings: usize, b: &Elem<R>) {
95 elem_sqr_mul_acc(&COMMON_OPS, a, squarings, b)
96 }
97
98 let b_1 = &a;
99 let b_11 = sqr_mul(b_1, 1, b_1);
100 let b_111 = sqr_mul(&b_11, 1, b_1);
101 let f_11 = sqr_mul(&b_111, 3, &b_111);
102 let fff = sqr_mul(&f_11, 6, &f_11);
103 let fff_111 = sqr_mul(&fff, 3, &b_111);
104 let fffffff_11 = sqr_mul(&fff_111, 15, &fff_111);
105 let ffffffff = sqr_mul(&fffffff_11, 2, &b_11);
106
107 let mut acc = sqr_mul(&ffffffff, 31 + 1, b_1);
109
110 sqr_mul_acc(&mut acc, 96 + 32, &ffffffff);
112
113 sqr_mul_acc(&mut acc, 32, &ffffffff);
115
116 sqr_mul_acc(&mut acc, 30, &fffffff_11);
118
119 COMMON_OPS.elem_square(&mut acc);
121 COMMON_OPS.elem_square(&mut acc);
122
123 acc
124}
125
126fn p256_point_mul_base_impl(g_scalar: &Scalar) -> Point {
127 let mut r = Point::new_at_infinity();
128
129 #[cfg(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64"))]
134 {
135 extern "C" {
136 fn GFp_nistz256_point_mul_base(
137 r: *mut Limb, g_scalar: *const Limb, );
140 }
141 unsafe {
142 GFp_nistz256_point_mul_base(r.xyz.as_mut_ptr(), g_scalar.limbs.as_ptr());
143 }
144 }
145
146 #[cfg(not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")))]
147 {
148 static GENERATOR: (Elem<R>, Elem<R>) = (
149 Elem {
150 limbs: p256_limbs![
151 0x18a9143c, 0x79e730d4, 0x5fedb601, 0x75ba95fc, 0x77622510, 0x79fb732b,
152 0xa53755c6, 0x18905f76
153 ],
154 m: PhantomData,
155 encoding: PhantomData,
156 },
157 Elem {
158 limbs: p256_limbs![
159 0xce95560a, 0xddf25357, 0xba19e45c, 0x8b4ab8e4, 0xdd21f325, 0xd2e88688,
160 0x25885d85, 0x8571ff18
161 ],
162 m: PhantomData,
163 encoding: PhantomData,
164 },
165 );
166
167 unsafe {
168 GFp_nistz256_point_mul(
169 r.xyz.as_mut_ptr(),
170 g_scalar.limbs.as_ptr(),
171 GENERATOR.0.limbs.as_ptr(),
172 GENERATOR.1.limbs.as_ptr(),
173 );
174 }
175 }
176
177 r
178}
179
180pub static PUBLIC_KEY_OPS: PublicKeyOps = PublicKeyOps {
181 common: &COMMON_OPS,
182};
183
184pub static SCALAR_OPS: ScalarOps = ScalarOps {
185 common: &COMMON_OPS,
186 scalar_inv_to_mont_impl: p256_scalar_inv_to_mont,
187 scalar_mul_mont: GFp_p256_scalar_mul_mont,
188};
189
190pub static PUBLIC_SCALAR_OPS: PublicScalarOps = PublicScalarOps {
191 scalar_ops: &SCALAR_OPS,
192 public_key_ops: &PUBLIC_KEY_OPS,
193 private_key_ops: &PRIVATE_KEY_OPS,
194
195 q_minus_n: Elem {
196 limbs: p256_limbs![0x039cdaae, 0x0c46353d, 0x58e8617b, 0x43190553, 0, 0, 0, 0],
197 m: PhantomData,
198 encoding: PhantomData, },
200};
201
202pub static PRIVATE_SCALAR_OPS: PrivateScalarOps = PrivateScalarOps {
203 scalar_ops: &SCALAR_OPS,
204
205 oneRR_mod_n: Scalar {
206 limbs: p256_limbs![
207 0xbe79eea2, 0x83244c95, 0x49bd6fa6, 0x4699799c, 0x2b6bec59, 0x2845b239, 0xf3d95620,
208 0x66e12d94
209 ],
210 m: PhantomData,
211 encoding: PhantomData, },
213};
214
215fn p256_scalar_inv_to_mont(a: &Scalar<Unencoded>) -> Scalar<R> {
216 #[inline]
226 fn mul(a: &Scalar<R>, b: &Scalar<R>) -> Scalar<R> {
227 binary_op(GFp_p256_scalar_mul_mont, a, b)
228 }
229
230 #[inline]
231 fn sqr(a: &Scalar<R>) -> Scalar<R> {
232 unary_op(GFp_p256_scalar_sqr_mont, a)
233 }
234
235 fn sqr_mul(a: &Scalar<R>, squarings: Limb, b: &Scalar<R>) -> Scalar<R> {
237 debug_assert!(squarings >= 1);
238 let mut tmp = Scalar::zero();
239 unsafe { GFp_p256_scalar_sqr_rep_mont(tmp.limbs.as_mut_ptr(), a.limbs.as_ptr(), squarings) }
240 mul(&tmp, b)
241 }
242
243 fn sqr_mul_acc(acc: &mut Scalar<R>, squarings: Limb, b: &Scalar<R>) {
245 debug_assert!(squarings >= 1);
246 unsafe {
247 GFp_p256_scalar_sqr_rep_mont(acc.limbs.as_mut_ptr(), acc.limbs.as_ptr(), squarings)
248 }
249 binary_op_assign(GFp_p256_scalar_mul_mont, acc, b);
250 }
251
252 fn to_mont(a: &Scalar) -> Scalar<R> {
253 static N_RR: Scalar<Unencoded> = Scalar {
254 limbs: p256_limbs![
255 0xbe79eea2, 0x83244c95, 0x49bd6fa6, 0x4699799c, 0x2b6bec59, 0x2845b239, 0xf3d95620,
256 0x66e12d94
257 ],
258 m: PhantomData,
259 encoding: PhantomData,
260 };
261 binary_op(GFp_p256_scalar_mul_mont, a, &N_RR)
262 }
263
264 const B_1: usize = 0;
266 const B_10: usize = 1;
267 const B_11: usize = 2;
268 const B_101: usize = 3;
269 const B_111: usize = 4;
270 const B_1111: usize = 5;
271 const B_10101: usize = 6;
272 const B_101111: usize = 7;
273 const DIGIT_COUNT: usize = 8;
274
275 let mut d = [Scalar::zero(); DIGIT_COUNT];
276
277 d[B_1] = to_mont(a);
278 d[B_10] = sqr(&d[B_1]);
279 d[B_11] = mul(&d[B_10], &d[B_1]);
280 d[B_101] = mul(&d[B_10], &d[B_11]);
281 d[B_111] = mul(&d[B_101], &d[B_10]);
282 let b_1010 = sqr(&d[B_101]);
283 d[B_1111] = mul(&b_1010, &d[B_101]);
284 d[B_10101] = sqr_mul(&b_1010, 0 + 1, &d[B_1]);
285 let b_101010 = sqr(&d[B_10101]);
286 d[B_101111] = mul(&b_101010, &d[B_101]);
287 let b_111111 = mul(&b_101010, &d[B_10101]);
288
289 let ff = sqr_mul(&b_111111, 0 + 2, &d[B_11]);
290 let ffff = sqr_mul(&ff, 0 + 8, &ff);
291 let ffffffff = sqr_mul(&ffff, 0 + 16, &ffff);
292
293 let mut acc = sqr_mul(&ffffffff, 32 + 32, &ffffffff);
295
296 sqr_mul_acc(&mut acc, 0 + 32, &ffffffff);
298
299 static REMAINING_WINDOWS: [(u8, u8); 26] = [
305 (6, B_101111 as u8),
306 (2 + 3, B_111 as u8),
307 (2 + 2, B_11 as u8),
308 (1 + 4, B_1111 as u8),
309 (5, B_10101 as u8),
310 (1 + 3, B_101 as u8),
311 (3, B_101 as u8),
312 (3, B_101 as u8),
313 (2 + 3, B_111 as u8),
314 (3 + 6, B_101111 as u8),
315 (2 + 4, B_1111 as u8),
316 (1 + 1, B_1 as u8),
317 (4 + 1, B_1 as u8),
318 (2 + 4, B_1111 as u8),
319 (2 + 3, B_111 as u8),
320 (1 + 3, B_111 as u8),
321 (2 + 3, B_111 as u8),
322 (2 + 3, B_101 as u8),
323 (1 + 2, B_11 as u8),
324 (4 + 6, B_101111 as u8),
325 (2, B_11 as u8),
326 (3 + 2, B_11 as u8),
327 (3 + 2, B_11 as u8),
328 (2 + 1, B_1 as u8),
329 (2 + 5, B_10101 as u8),
330 (2 + 4, B_1111 as u8),
331 ];
332
333 for &(squarings, digit) in &REMAINING_WINDOWS {
334 sqr_mul_acc(&mut acc, Limb::from(squarings), &d[usize::from(digit)]);
335 }
336
337 acc
338}
339
340extern "C" {
341 fn GFp_nistz256_add(
342 r: *mut Limb, a: *const Limb, b: *const Limb, );
346 fn GFp_nistz256_mul_mont(
347 r: *mut Limb, a: *const Limb, b: *const Limb, );
351 fn GFp_nistz256_sqr_mont(
352 r: *mut Limb, a: *const Limb, );
355
356 fn GFp_nistz256_point_add(
357 r: *mut Limb, a: *const Limb, b: *const Limb, );
361 fn GFp_nistz256_point_mul(
362 r: *mut Limb, p_scalar: *const Limb, p_x: *const Limb, p_y: *const Limb, );
367
368 fn GFp_p256_scalar_mul_mont(
369 r: *mut Limb, a: *const Limb, b: *const Limb, );
373 fn GFp_p256_scalar_sqr_mont(
374 r: *mut Limb, a: *const Limb, );
377 fn GFp_p256_scalar_sqr_rep_mont(
378 r: *mut Limb, a: *const Limb, rep: Limb,
381 );
382}