1use super::{
16 elem::{binary_op, binary_op_assign},
17 elem_sqr_mul, elem_sqr_mul_acc, Modulus, *,
18};
19
20pub static COMMON_OPS: CommonOps = CommonOps {
21 num_limbs: 256 / LIMB_BITS,
22
23 q: Modulus {
24 p: limbs_from_hex("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"),
25 rr: limbs_from_hex("4fffffffdfffffffffffffffefffffffbffffffff0000000000000003"),
26 },
27 n: Elem::from_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"),
28
29 a: Elem::from_hex("fffffffc00000004000000000000000000000003fffffffffffffffffffffffc"),
30 b: Elem::from_hex("dc30061d04874834e5a220abf7212ed6acf005cd78843090d89cdf6229c4bddf"),
31
32 elem_mul_mont: p256_mul_mont,
33 elem_sqr_mont: p256_sqr_mont,
34
35 point_add_jacobian_impl: p256_point_add,
36};
37
38#[cfg(test)]
39pub(super) static GENERATOR: (Elem<R>, Elem<R>) = (
40 Elem::from_hex("18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c"),
41 Elem::from_hex("8571ff1825885d85d2e88688dd21f3258b4ab8e4ba19e45cddf25357ce95560a"),
42);
43
44pub static PRIVATE_KEY_OPS: PrivateKeyOps = PrivateKeyOps {
45 common: &COMMON_OPS,
46 elem_inv_squared: p256_elem_inv_squared,
47 point_mul_base_impl: p256_point_mul_base_impl,
48 point_mul_impl: p256_point_mul,
49};
50
51fn p256_elem_inv_squared(a: &Elem<R>) -> Elem<R> {
52 #[inline]
59 fn sqr_mul(a: &Elem<R>, squarings: usize, b: &Elem<R>) -> Elem<R> {
60 elem_sqr_mul(&COMMON_OPS, a, squarings, b)
61 }
62
63 #[inline]
64 fn sqr_mul_acc(a: &mut Elem<R>, squarings: usize, b: &Elem<R>) {
65 elem_sqr_mul_acc(&COMMON_OPS, a, squarings, b)
66 }
67
68 let b_1 = &a;
69 let b_11 = sqr_mul(b_1, 1, b_1);
70 let b_111 = sqr_mul(&b_11, 1, b_1);
71 let f_11 = sqr_mul(&b_111, 3, &b_111);
72 let fff = sqr_mul(&f_11, 6, &f_11);
73 let fff_111 = sqr_mul(&fff, 3, &b_111);
74 let fffffff_11 = sqr_mul(&fff_111, 15, &fff_111);
75 let ffffffff = sqr_mul(&fffffff_11, 2, &b_11);
76
77 let mut acc = sqr_mul(&ffffffff, 31 + 1, b_1);
79
80 sqr_mul_acc(&mut acc, 96 + 32, &ffffffff);
82
83 sqr_mul_acc(&mut acc, 32, &ffffffff);
85
86 sqr_mul_acc(&mut acc, 30, &fffffff_11);
88
89 COMMON_OPS.elem_square(&mut acc);
91 COMMON_OPS.elem_square(&mut acc);
92
93 acc
94}
95
96fn p256_point_mul_base_impl(g_scalar: &Scalar) -> Point {
97 prefixed_extern! {
98 fn p256_point_mul_base(
99 r: *mut Limb, g_scalar: *const Limb, );
102 }
103
104 let mut r = Point::new_at_infinity();
105 unsafe {
106 p256_point_mul_base(r.xyz.as_mut_ptr(), g_scalar.limbs.as_ptr());
107 }
108 r
109}
110
111pub static PUBLIC_KEY_OPS: PublicKeyOps = PublicKeyOps {
112 common: &COMMON_OPS,
113};
114
115pub static SCALAR_OPS: ScalarOps = ScalarOps {
116 common: &COMMON_OPS,
117 scalar_mul_mont: p256_scalar_mul_mont,
118};
119
120pub static PUBLIC_SCALAR_OPS: PublicScalarOps = PublicScalarOps {
121 scalar_ops: &SCALAR_OPS,
122 public_key_ops: &PUBLIC_KEY_OPS,
123
124 #[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
125 twin_mul: twin_mul_nistz256,
126
127 #[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))]
128 twin_mul: |g_scalar, p_scalar, p_xy| {
129 twin_mul_inefficient(&PRIVATE_KEY_OPS, g_scalar, p_scalar, p_xy)
130 },
131
132 q_minus_n: Elem::from_hex("4319055358e8617b0c46353d039cdaae"),
133
134 scalar_inv_to_mont_vartime: |s| PRIVATE_SCALAR_OPS.scalar_inv_to_mont(s),
136};
137
138#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
139fn twin_mul_nistz256(g_scalar: &Scalar, p_scalar: &Scalar, p_xy: &(Elem<R>, Elem<R>)) -> Point {
140 let scaled_g = point_mul_base_vartime(g_scalar);
141 let scaled_p = PRIVATE_KEY_OPS.point_mul(p_scalar, p_xy);
142 PRIVATE_KEY_OPS.common.point_sum(&scaled_g, &scaled_p)
143}
144
145#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
146fn point_mul_base_vartime(g_scalar: &Scalar) -> Point {
147 prefixed_extern! {
148 fn p256_point_mul_base_vartime(r: *mut Limb, g_scalar: *const Limb, );
151 }
152 let mut scaled_g = Point::new_at_infinity();
153 unsafe {
154 p256_point_mul_base_vartime(scaled_g.xyz.as_mut_ptr(), g_scalar.limbs.as_ptr());
155 }
156 scaled_g
157}
158
159pub static PRIVATE_SCALAR_OPS: PrivateScalarOps = PrivateScalarOps {
160 scalar_ops: &SCALAR_OPS,
161
162 oneRR_mod_n: Scalar::from_hex(
163 "66e12d94f3d956202845b2392b6bec594699799c49bd6fa683244c95be79eea2",
164 ),
165 scalar_inv_to_mont: p256_scalar_inv_to_mont,
166};
167
168fn p256_scalar_inv_to_mont(a: Scalar<R>) -> Scalar<R> {
169 #[inline]
179 fn mul(a: &Scalar<R>, b: &Scalar<R>) -> Scalar<R> {
180 binary_op(p256_scalar_mul_mont, a, b)
181 }
182
183 #[inline]
184 fn sqr(a: &Scalar<R>) -> Scalar<R> {
185 let mut tmp = Scalar::zero();
186 unsafe { p256_scalar_sqr_rep_mont(tmp.limbs.as_mut_ptr(), a.limbs.as_ptr(), 1) }
187 tmp
188 }
189
190 fn sqr_mul(a: &Scalar<R>, squarings: Limb, b: &Scalar<R>) -> Scalar<R> {
192 debug_assert!(squarings >= 1);
193 let mut tmp = Scalar::zero();
194 unsafe { p256_scalar_sqr_rep_mont(tmp.limbs.as_mut_ptr(), a.limbs.as_ptr(), squarings) }
195 mul(&tmp, b)
196 }
197
198 fn sqr_mul_acc(acc: &mut Scalar<R>, squarings: Limb, b: &Scalar<R>) {
200 debug_assert!(squarings >= 1);
201 unsafe { p256_scalar_sqr_rep_mont(acc.limbs.as_mut_ptr(), acc.limbs.as_ptr(), squarings) }
202 binary_op_assign(p256_scalar_mul_mont, acc, b);
203 }
204
205 const B_1: usize = 0;
207 const B_10: usize = 1;
208 const B_11: usize = 2;
209 const B_101: usize = 3;
210 const B_111: usize = 4;
211 const B_1111: usize = 5;
212 const B_10101: usize = 6;
213 const B_101111: usize = 7;
214 const DIGIT_COUNT: usize = 8;
215
216 let mut d = [Scalar::zero(); DIGIT_COUNT];
217
218 d[B_1] = a;
219 d[B_10] = sqr(&d[B_1]);
220 d[B_11] = mul(&d[B_10], &d[B_1]);
221 d[B_101] = mul(&d[B_10], &d[B_11]);
222 d[B_111] = mul(&d[B_101], &d[B_10]);
223 let b_1010 = sqr(&d[B_101]);
224 d[B_1111] = mul(&b_1010, &d[B_101]);
225 d[B_10101] = sqr_mul(&b_1010, 0 + 1, &d[B_1]);
226 let b_101010 = sqr(&d[B_10101]);
227 d[B_101111] = mul(&b_101010, &d[B_101]);
228 let b_111111 = mul(&b_101010, &d[B_10101]);
229
230 let ff = sqr_mul(&b_111111, 0 + 2, &d[B_11]);
231 let ffff = sqr_mul(&ff, 0 + 8, &ff);
232 let ffffffff = sqr_mul(&ffff, 0 + 16, &ffff);
233
234 let mut acc = sqr_mul(&ffffffff, 32 + 32, &ffffffff);
236
237 sqr_mul_acc(&mut acc, 0 + 32, &ffffffff);
239
240 #[allow(clippy::cast_possible_truncation)]
246 static REMAINING_WINDOWS: [(u8, u8); 26] = [
247 (6, B_101111 as u8),
248 (2 + 3, B_111 as u8),
249 (2 + 2, B_11 as u8),
250 (1 + 4, B_1111 as u8),
251 (5, B_10101 as u8),
252 (1 + 3, B_101 as u8),
253 (3, B_101 as u8),
254 (3, B_101 as u8),
255 (2 + 3, B_111 as u8),
256 (3 + 6, B_101111 as u8),
257 (2 + 4, B_1111 as u8),
258 (1 + 1, B_1 as u8),
259 (4 + 1, B_1 as u8),
260 (2 + 4, B_1111 as u8),
261 (2 + 3, B_111 as u8),
262 (1 + 3, B_111 as u8),
263 (2 + 3, B_111 as u8),
264 (2 + 3, B_101 as u8),
265 (1 + 2, B_11 as u8),
266 (4 + 6, B_101111 as u8),
267 (2, B_11 as u8),
268 (3 + 2, B_11 as u8),
269 (3 + 2, B_11 as u8),
270 (2 + 1, B_1 as u8),
271 (2 + 5, B_10101 as u8),
272 (2 + 4, B_1111 as u8),
273 ];
274
275 for &(squarings, digit) in &REMAINING_WINDOWS {
276 sqr_mul_acc(&mut acc, Limb::from(squarings), &d[usize::from(digit)]);
277 }
278
279 acc
280}
281
282prefixed_extern! {
283 pub(super) fn p256_mul_mont(
284 r: *mut Limb, a: *const Limb, b: *const Limb, );
288 pub(super) fn p256_sqr_mont(
289 r: *mut Limb, a: *const Limb, );
292
293 fn p256_point_add(
294 r: *mut Limb, a: *const Limb, b: *const Limb, );
298 fn p256_point_mul(
299 r: *mut Limb, p_scalar: *const Limb, p_x: *const Limb, p_y: *const Limb, );
304
305 fn p256_scalar_mul_mont(
306 r: *mut Limb, a: *const Limb, b: *const Limb, );
310 fn p256_scalar_sqr_rep_mont(
311 r: *mut Limb, a: *const Limb, rep: Limb,
314 );
315}
316
317#[cfg(test)]
318mod tests {
319 #[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
320 #[test]
321 fn p256_point_mul_base_vartime_test() {
322 use super::{super::tests::point_mul_base_tests, *};
323 point_mul_base_tests(
324 &PRIVATE_KEY_OPS,
325 point_mul_base_vartime,
326 test_file!("p256_point_mul_base_tests.txt"),
327 );
328 }
329}