1use super::{
16 elem::{binary_op, binary_op_assign},
17 elem_sqr_mul, elem_sqr_mul_acc, PublicModulus, *,
18};
19
20pub(super) const NUM_LIMBS: usize = 256 / LIMB_BITS;
21
22pub static COMMON_OPS: CommonOps = CommonOps {
23 num_limbs: elem::NumLimbs::P256,
24
25 q: PublicModulus {
26 p: limbs_from_hex("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"),
27 rr: PublicElem::from_hex("4fffffffdfffffffffffffffefffffffbffffffff0000000000000003"),
28 },
29 n: PublicElem::from_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"),
30
31 a: PublicElem::from_hex("fffffffc00000004000000000000000000000003fffffffffffffffffffffffc"),
32 b: PublicElem::from_hex("dc30061d04874834e5a220abf7212ed6acf005cd78843090d89cdf6229c4bddf"),
33
34 elem_mul_mont: p256_mul_mont,
35 elem_sqr_mont: p256_sqr_mont,
36};
37
38#[cfg(test)]
39pub(super) static GENERATOR: (PublicElem<R>, PublicElem<R>) = (
40 PublicElem::from_hex("18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c"),
41 PublicElem::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 point_add_jacobian_impl: p256_point_add,
50};
51
52fn p256_elem_inv_squared(q: &Modulus<Q>, a: &Elem<R>) -> Elem<R> {
53 #[inline]
60 fn sqr_mul(q: &Modulus<Q>, a: &Elem<R>, squarings: LeakyWord, b: &Elem<R>) -> Elem<R> {
61 elem_sqr_mul(&COMMON_OPS, a, squarings, b, q.cpu())
62 }
63
64 #[inline]
65 fn sqr_mul_acc(q: &Modulus<Q>, a: &mut Elem<R>, squarings: LeakyWord, b: &Elem<R>) {
66 elem_sqr_mul_acc(&COMMON_OPS, a, squarings, b, q.cpu())
67 }
68
69 let b_1 = &a;
70 let b_11 = sqr_mul(q, b_1, 1, b_1);
71 let b_111 = sqr_mul(q, &b_11, 1, b_1);
72 let f_11 = sqr_mul(q, &b_111, 3, &b_111);
73 let fff = sqr_mul(q, &f_11, 6, &f_11);
74 let fff_111 = sqr_mul(q, &fff, 3, &b_111);
75 let fffffff_11 = sqr_mul(q, &fff_111, 15, &fff_111);
76 let ffffffff = sqr_mul(q, &fffffff_11, 2, &b_11);
77
78 let mut acc = sqr_mul(q, &ffffffff, 31 + 1, b_1);
80
81 sqr_mul_acc(q, &mut acc, 96 + 32, &ffffffff);
83
84 sqr_mul_acc(q, &mut acc, 32, &ffffffff);
86
87 sqr_mul_acc(q, &mut acc, 30, &fffffff_11);
89
90 q.elem_square(&mut acc);
92 q.elem_square(&mut acc);
93
94 acc
95}
96
97fn p256_point_mul_base_impl(g_scalar: &Scalar, _cpu: cpu::Features) -> Point {
98 prefixed_extern! {
99 fn p256_point_mul_base(
100 r: *mut Limb, g_scalar: *const Limb, );
103 }
104
105 let mut r = Point::new_at_infinity();
106 unsafe {
107 p256_point_mul_base(r.xyz.as_mut_ptr(), g_scalar.limbs.as_ptr());
108 }
109 r
110}
111
112pub static PUBLIC_KEY_OPS: PublicKeyOps = PublicKeyOps {
113 common: &COMMON_OPS,
114};
115
116pub static SCALAR_OPS: ScalarOps = ScalarOps {
117 common: &COMMON_OPS,
118 scalar_mul_mont: p256_scalar_mul_mont,
119};
120
121pub static PUBLIC_SCALAR_OPS: PublicScalarOps = PublicScalarOps {
122 scalar_ops: &SCALAR_OPS,
123 public_key_ops: &PUBLIC_KEY_OPS,
124
125 #[cfg(any(
126 all(target_arch = "aarch64", target_endian = "little"),
127 target_arch = "x86_64"
128 ))]
129 twin_mul: twin_mul_nistz256,
130
131 #[cfg(not(any(
132 all(target_arch = "aarch64", target_endian = "little"),
133 target_arch = "x86_64"
134 )))]
135 twin_mul: |g_scalar, p_scalar, p_xy, cpu| {
136 twin_mul_inefficient(&PRIVATE_KEY_OPS, g_scalar, p_scalar, p_xy, cpu)
137 },
138
139 q_minus_n: PublicElem::from_hex("4319055358e8617b0c46353d039cdaae"),
140
141 scalar_inv_to_mont_vartime: |s, cpu| PRIVATE_SCALAR_OPS.scalar_inv_to_mont(s, cpu),
143};
144
145#[cfg(any(
146 all(target_arch = "aarch64", target_endian = "little"),
147 target_arch = "x86_64"
148))]
149fn twin_mul_nistz256(
150 g_scalar: &Scalar,
151 p_scalar: &Scalar,
152 p_xy: &(Elem<R>, Elem<R>),
153 cpu: cpu::Features,
154) -> Point {
155 let scaled_g = point_mul_base_vartime(g_scalar, cpu);
156 let scaled_p = PRIVATE_KEY_OPS.point_mul(p_scalar, p_xy, cpu::features());
157 PRIVATE_KEY_OPS.point_sum(&scaled_g, &scaled_p, cpu)
158}
159
160#[cfg(any(
161 all(target_arch = "aarch64", target_endian = "little"),
162 target_arch = "x86_64"
163))]
164fn point_mul_base_vartime(g_scalar: &Scalar, _cpu: cpu::Features) -> Point {
165 prefixed_extern! {
166 fn p256_point_mul_base_vartime(r: *mut Limb, g_scalar: *const Limb, );
169 }
170 let mut scaled_g = Point::new_at_infinity();
171 unsafe {
172 p256_point_mul_base_vartime(scaled_g.xyz.as_mut_ptr(), g_scalar.limbs.as_ptr());
173 }
174 scaled_g
175}
176
177pub static PRIVATE_SCALAR_OPS: PrivateScalarOps = PrivateScalarOps {
178 scalar_ops: &SCALAR_OPS,
179
180 oneRR_mod_n: PublicScalar::from_hex(
181 "66e12d94f3d956202845b2392b6bec594699799c49bd6fa683244c95be79eea2",
182 ),
183 scalar_inv_to_mont: p256_scalar_inv_to_mont,
184};
185
186#[allow(clippy::just_underscores_and_digits)]
187fn p256_scalar_inv_to_mont(a: Scalar<R>, _cpu: cpu::Features) -> Scalar<R> {
188 #[inline]
198 fn mul(a: &Scalar<R>, b: &Scalar<R>) -> Scalar<R> {
199 binary_op(p256_scalar_mul_mont, a, b)
200 }
201
202 #[inline]
203 fn sqr(a: &Scalar<R>) -> Scalar<R> {
204 let mut tmp = Scalar::zero();
205 unsafe { p256_scalar_sqr_rep_mont(tmp.limbs.as_mut_ptr(), a.limbs.as_ptr(), 1) }
206 tmp
207 }
208
209 fn sqr_mul(a: &Scalar<R>, squarings: LeakyWord, b: &Scalar<R>) -> Scalar<R> {
211 debug_assert!(squarings >= 1);
212 let mut tmp = Scalar::zero();
213 unsafe { p256_scalar_sqr_rep_mont(tmp.limbs.as_mut_ptr(), a.limbs.as_ptr(), squarings) }
214 mul(&tmp, b)
215 }
216
217 fn sqr_mul_acc(acc: &mut Scalar<R>, squarings: LeakyWord, b: &Scalar<R>) {
219 debug_assert!(squarings >= 1);
220 unsafe { p256_scalar_sqr_rep_mont(acc.limbs.as_mut_ptr(), acc.limbs.as_ptr(), squarings) }
221 binary_op_assign(p256_scalar_mul_mont, acc, b);
222 }
223
224 let _1 = &a;
225
226 let _10 = sqr(_1); let _100 = sqr(&_10); let _101 = mul(&_100, _1); let _111 = mul(&_101, &_10); let _1000 = sqr(&_100); let _10000 = sqr(&_1000); let _100000 = sqr(&_10000); let _100111 = mul(&_111, &_100000); let _101011 = mul(&_100, &_100111); let _101111 = mul(&_100, &_101011); let _1001111 = mul(&_100000, &_101111); let _86 = sqr(&_101011); let _1011011 = mul(&_101, &_86); let _92 = mul(_1, &_1011011); let _1100011 = mul(&_111, &_92); let _10111111 = mul(&_92, &_1100011); let _11011111 = mul(&_100000, &_10111111); let ff = mul(&_100000, &_11011111); let ffff = sqr_mul(&ff, 0 + 8, &ff);
248 let ffffffff = sqr_mul(&ffff, 0 + 16, &ffff);
249
250 let mut acc = sqr_mul(&ffffffff, 32 + 32, &ffffffff);
252
253 sqr_mul_acc(&mut acc, 0 + 32, &ffffffff);
255
256 sqr_mul_acc(&mut acc, 6, &_101111);
262 sqr_mul_acc(&mut acc, 2 + 3, &_111);
263 sqr_mul_acc(&mut acc, 2 + 8, &_11011111);
264 sqr_mul_acc(&mut acc, 1 + 3, &_101);
265 sqr_mul_acc(&mut acc, 1 + 7, &_1011011);
266 sqr_mul_acc(&mut acc, 1 + 6, &_100111);
267 sqr_mul_acc(&mut acc, 3 + 6, &_101111);
268 sqr_mul_acc(&mut acc, 2 + 3, &_111);
269 sqr_mul_acc(&mut acc, 3, &_101);
270 sqr_mul_acc(&mut acc, 4 + 7, &_1001111);
271 sqr_mul_acc(&mut acc, 2 + 3, &_111);
272 sqr_mul_acc(&mut acc, 1 + 3, &_111);
273 sqr_mul_acc(&mut acc, 2 + 3, &_111);
274 sqr_mul_acc(&mut acc, 2 + 6, &_101011);
275 sqr_mul_acc(&mut acc, 4 + 8, &_10111111);
276 sqr_mul_acc(&mut acc, 3 + 7, &_1100011);
277 sqr_mul_acc(&mut acc, 2 + 1, _1);
278 sqr_mul_acc(&mut acc, 2 + 3, &_101);
279 sqr_mul_acc(&mut acc, 1 + 7, &_1001111);
280
281 acc
282}
283
284prefixed_extern! {
285 pub(super) fn p256_mul_mont(
286 r: *mut Limb, a: *const Limb, b: *const Limb, );
290 pub(super) fn p256_sqr_mont(
291 r: *mut Limb, a: *const Limb, );
294
295 fn p256_point_add(
296 r: *mut Limb, a: *const Limb, b: *const Limb, );
300 fn p256_point_mul(
301 r: *mut Limb, p_scalar: *const Limb, p_x: *const Limb, p_y: *const Limb, );
306
307 fn p256_scalar_mul_mont(
308 r: *mut Limb, a: *const Limb, b: *const Limb, );
312 fn p256_scalar_sqr_rep_mont(
313 r: *mut Limb, a: *const Limb, rep: LeakyWord,
316 );
317}
318
319#[cfg(test)]
320mod tests {
321 #[cfg(any(
322 all(target_arch = "aarch64", target_endian = "little"),
323 target_arch = "x86_64"
324 ))]
325 #[test]
326 fn p256_point_mul_base_vartime_test() {
327 use super::{super::tests::point_mul_base_tests, *};
328 point_mul_base_tests(
329 &PRIVATE_KEY_OPS,
330 point_mul_base_vartime,
331 test_vector_file!("p256_point_mul_base_tests.txt"),
332 );
333 }
334}