1 // Copyright 2016 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use crate::{arithmetic::montgomery::*, error, limb::*};
16 use core::marker::PhantomData;
17 use libc::size_t;
18 use untrusted;
19 
20 pub use self::elem::*;
21 
22 /// A field element, i.e. an element of ℤ/qℤ for the curve's field modulus
23 /// *q*.
24 pub type Elem<E> = elem::Elem<Q, E>;
25 
26 /// Represents the (prime) order *q* of the curve's prime field.
27 #[derive(Clone, Copy)]
28 pub enum Q {}
29 
30 /// A scalar. Its value is in [0, n). Zero-valued scalars are forbidden in most
31 /// contexts.
32 pub type Scalar<E = Unencoded> = elem::Elem<N, E>;
33 
34 /// Represents the prime order *n* of the curve's group.
35 #[derive(Clone, Copy)]
36 pub enum N {}
37 
38 pub struct Point {
39     // The coordinates are stored in a contiguous array, where the first
40     // `ops.num_limbs` elements are the X coordinate, the next
41     // `ops.num_limbs` elements are the Y coordinate, and the next
42     // `ops.num_limbs` elements are the Z coordinate. This layout is dictated
43     // by the requirements of the GFp_nistz256 code.
44     xyz: [Limb; 3 * MAX_LIMBS],
45 }
46 
47 impl Point {
new_at_infinity() -> Point48     pub fn new_at_infinity() -> Point {
49         Point {
50             xyz: [0; 3 * MAX_LIMBS],
51         }
52     }
53 }
54 
55 #[cfg(all(target_pointer_width = "32", target_endian = "little"))]
56 macro_rules! limbs {
57     ( $limb_b:expr, $limb_a:expr, $limb_9:expr, $limb_8:expr,
58       $limb_7:expr, $limb_6:expr, $limb_5:expr, $limb_4:expr,
59       $limb_3:expr, $limb_2:expr, $limb_1:expr, $limb_0:expr ) => {
60         [
61             $limb_0, $limb_1, $limb_2, $limb_3, $limb_4, $limb_5, $limb_6, $limb_7, $limb_8,
62             $limb_9, $limb_a, $limb_b,
63         ]
64     };
65 }
66 
67 #[cfg(all(target_pointer_width = "64", target_endian = "little"))]
68 macro_rules! limbs {
69     ( $limb_b:expr, $limb_a:expr, $limb_9:expr, $limb_8:expr,
70       $limb_7:expr, $limb_6:expr, $limb_5:expr, $limb_4:expr,
71       $limb_3:expr, $limb_2:expr, $limb_1:expr, $limb_0:expr ) => {
72         [
73             (($limb_1 | 0u64) << 32) | $limb_0,
74             (($limb_3 | 0u64) << 32) | $limb_2,
75             (($limb_5 | 0u64) << 32) | $limb_4,
76             (($limb_7 | 0u64) << 32) | $limb_6,
77             (($limb_9 | 0u64) << 32) | $limb_8,
78             (($limb_b | 0u64) << 32) | $limb_a,
79         ]
80     };
81 }
82 
83 static ONE: Elem<Unencoded> = Elem {
84     limbs: limbs![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
85     m: PhantomData,
86     encoding: PhantomData,
87 };
88 
89 /// Operations and values needed by all curve operations.
90 pub struct CommonOps {
91     pub num_limbs: usize,
92     q: Modulus,
93     pub n: Elem<Unencoded>,
94 
95     pub a: Elem<R>, // Must be -3 mod q
96     pub b: Elem<R>,
97 
98     // In all cases, `r`, `a`, and `b` may all alias each other.
99     elem_add_impl: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
100     elem_mul_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
101     elem_sqr_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
102 
103     point_add_jacobian_impl: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
104 }
105 
106 impl CommonOps {
107     #[inline]
elem_add<E: Encoding>(&self, a: &mut Elem<E>, b: &Elem<E>)108     pub fn elem_add<E: Encoding>(&self, a: &mut Elem<E>, b: &Elem<E>) {
109         binary_op_assign(self.elem_add_impl, a, b)
110     }
111 
elems_are_equal(&self, a: &Elem<R>, b: &Elem<R>) -> bool112     pub fn elems_are_equal(&self, a: &Elem<R>, b: &Elem<R>) -> bool {
113         for i in 0..self.num_limbs {
114             if a.limbs[i] != b.limbs[i] {
115                 return false;
116             }
117         }
118         true
119     }
120 
121     #[inline]
elem_unencoded(&self, a: &Elem<R>) -> Elem<Unencoded>122     pub fn elem_unencoded(&self, a: &Elem<R>) -> Elem<Unencoded> { self.elem_product(a, &ONE) }
123 
124     #[inline]
elem_mul(&self, a: &mut Elem<R>, b: &Elem<R>)125     pub fn elem_mul(&self, a: &mut Elem<R>, b: &Elem<R>) {
126         binary_op_assign(self.elem_mul_mont, a, b)
127     }
128 
129     #[inline]
elem_product<EA: Encoding, EB: Encoding>( &self, a: &Elem<EA>, b: &Elem<EB>, ) -> Elem<<(EA, EB) as ProductEncoding>::Output> where (EA, EB): ProductEncoding,130     pub fn elem_product<EA: Encoding, EB: Encoding>(
131         &self, a: &Elem<EA>, b: &Elem<EB>,
132     ) -> Elem<<(EA, EB) as ProductEncoding>::Output>
133     where
134         (EA, EB): ProductEncoding,
135     {
136         mul_mont(self.elem_mul_mont, a, b)
137     }
138 
139     #[inline]
elem_square(&self, a: &mut Elem<R>)140     pub fn elem_square(&self, a: &mut Elem<R>) { unary_op_assign(self.elem_sqr_mont, a); }
141 
142     #[inline]
elem_squared(&self, a: &Elem<R>) -> Elem<R>143     pub fn elem_squared(&self, a: &Elem<R>) -> Elem<R> { unary_op(self.elem_sqr_mont, a) }
144 
145     #[inline]
is_zero<M, E: Encoding>(&self, a: &elem::Elem<M, E>) -> bool146     pub fn is_zero<M, E: Encoding>(&self, a: &elem::Elem<M, E>) -> bool {
147         limbs_are_zero_constant_time(&a.limbs[..self.num_limbs]) == LimbMask::True
148     }
149 
elem_verify_is_not_zero(&self, a: &Elem<R>) -> Result<(), error::Unspecified>150     pub fn elem_verify_is_not_zero(&self, a: &Elem<R>) -> Result<(), error::Unspecified> {
151         if self.is_zero(a) {
152             Err(error::Unspecified)
153         } else {
154             Ok(())
155         }
156     }
157 
point_sum(&self, a: &Point, b: &Point) -> Point158     pub fn point_sum(&self, a: &Point, b: &Point) -> Point {
159         let mut r = Point::new_at_infinity();
160         unsafe {
161             (self.point_add_jacobian_impl)(r.xyz.as_mut_ptr(), a.xyz.as_ptr(), b.xyz.as_ptr())
162         }
163         r
164     }
165 
point_x(&self, p: &Point) -> Elem<R>166     pub fn point_x(&self, p: &Point) -> Elem<R> {
167         let mut r = Elem::zero();
168         r.limbs[..self.num_limbs].copy_from_slice(&p.xyz[0..self.num_limbs]);
169         r
170     }
171 
point_y(&self, p: &Point) -> Elem<R>172     pub fn point_y(&self, p: &Point) -> Elem<R> {
173         let mut r = Elem::zero();
174         r.limbs[..self.num_limbs].copy_from_slice(&p.xyz[self.num_limbs..(2 * self.num_limbs)]);
175         r
176     }
177 
point_z(&self, p: &Point) -> Elem<R>178     pub fn point_z(&self, p: &Point) -> Elem<R> {
179         let mut r = Elem::zero();
180         r.limbs[..self.num_limbs]
181             .copy_from_slice(&p.xyz[(2 * self.num_limbs)..(3 * self.num_limbs)]);
182         r
183     }
184 }
185 
186 struct Modulus {
187     p: [Limb; MAX_LIMBS],
188     rr: [Limb; MAX_LIMBS],
189 }
190 
191 /// Operations on private keys, for ECDH and ECDSA signing.
192 pub struct PrivateKeyOps {
193     pub common: &'static CommonOps,
194     elem_inv_squared: fn(a: &Elem<R>) -> Elem<R>,
195     point_mul_base_impl: fn(a: &Scalar) -> Point,
196     point_mul_impl: unsafe extern "C" fn(
197         r: *mut Limb,          // [3][num_limbs]
198         p_scalar: *const Limb, // [num_limbs]
199         p_x: *const Limb,      // [num_limbs]
200         p_y: *const Limb,      // [num_limbs]
201     ),
202 }
203 
204 impl PrivateKeyOps {
205     #[inline(always)]
point_mul_base(&self, a: &Scalar) -> Point206     pub fn point_mul_base(&self, a: &Scalar) -> Point { (self.point_mul_base_impl)(a) }
207 
208     #[inline(always)]
point_mul(&self, p_scalar: &Scalar, (p_x, p_y): &(Elem<R>, Elem<R>)) -> Point209     pub fn point_mul(&self, p_scalar: &Scalar, (p_x, p_y): &(Elem<R>, Elem<R>)) -> Point {
210         let mut r = Point::new_at_infinity();
211         unsafe {
212             (self.point_mul_impl)(
213                 r.xyz.as_mut_ptr(),
214                 p_scalar.limbs.as_ptr(),
215                 p_x.limbs.as_ptr(),
216                 p_y.limbs.as_ptr(),
217             );
218         }
219         r
220     }
221 
222     #[inline]
elem_inverse_squared(&self, a: &Elem<R>) -> Elem<R>223     pub fn elem_inverse_squared(&self, a: &Elem<R>) -> Elem<R> { (self.elem_inv_squared)(a) }
224 }
225 
226 /// Operations and values needed by all operations on public keys (ECDH
227 /// agreement and ECDSA verification).
228 pub struct PublicKeyOps {
229     pub common: &'static CommonOps,
230 }
231 
232 impl PublicKeyOps {
233     // The serialized bytes are in big-endian order, zero-padded. The limbs
234     // of `Elem` are in the native endianness, least significant limb to
235     // most significant limb. Besides the parsing, conversion, this also
236     // implements NIST SP 800-56A Step 2: "Verify that xQ and yQ are integers
237     // in the interval [0, p-1] in the case that q is an odd prime p[.]"
elem_parse(&self, input: &mut untrusted::Reader) -> Result<Elem<R>, error::Unspecified>238     pub fn elem_parse(&self, input: &mut untrusted::Reader) -> Result<Elem<R>, error::Unspecified> {
239         let encoded_value = input.skip_and_get_input(self.common.num_limbs * LIMB_BYTES)?;
240         let parsed = elem_parse_big_endian_fixed_consttime(self.common, encoded_value)?;
241         let mut r = Elem::zero();
242         // Montgomery encode (elem_to_mont).
243         // TODO: do something about this.
244         unsafe {
245             (self.common.elem_mul_mont)(
246                 r.limbs.as_mut_ptr(),
247                 parsed.limbs.as_ptr(),
248                 self.common.q.rr.as_ptr(),
249             )
250         }
251         Ok(r)
252     }
253 }
254 
255 // Operations used by both ECDSA signing and ECDSA verification. In general
256 // these must be side-channel resistant.
257 pub struct ScalarOps {
258     pub common: &'static CommonOps,
259 
260     scalar_inv_to_mont_impl: fn(a: &Scalar) -> Scalar<R>,
261     scalar_mul_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
262 }
263 
264 impl ScalarOps {
265     // The (maximum) length of a scalar, not including any padding.
scalar_bytes_len(&self) -> usize266     pub fn scalar_bytes_len(&self) -> usize { self.common.num_limbs * LIMB_BYTES }
267 
268     /// Returns the modular inverse of `a` (mod `n`). Panics of `a` is zero,
269     /// because zero isn't invertible.
scalar_inv_to_mont(&self, a: &Scalar) -> Scalar<R>270     pub fn scalar_inv_to_mont(&self, a: &Scalar) -> Scalar<R> {
271         assert!(!self.common.is_zero(a));
272         (self.scalar_inv_to_mont_impl)(a)
273     }
274 
275     #[inline]
scalar_product<EA: Encoding, EB: Encoding>( &self, a: &Scalar<EA>, b: &Scalar<EB>, ) -> Scalar<<(EA, EB) as ProductEncoding>::Output> where (EA, EB): ProductEncoding,276     pub fn scalar_product<EA: Encoding, EB: Encoding>(
277         &self, a: &Scalar<EA>, b: &Scalar<EB>,
278     ) -> Scalar<<(EA, EB) as ProductEncoding>::Output>
279     where
280         (EA, EB): ProductEncoding,
281     {
282         mul_mont(self.scalar_mul_mont, a, b)
283     }
284 }
285 
286 /// Operations on public scalars needed by ECDSA signature verification.
287 pub struct PublicScalarOps {
288     pub scalar_ops: &'static ScalarOps,
289     pub public_key_ops: &'static PublicKeyOps,
290 
291     // XXX: `PublicScalarOps` shouldn't depend on `PrivateKeyOps`, but it does
292     // temporarily until `twin_mul` is rewritten.
293     pub private_key_ops: &'static PrivateKeyOps,
294 
295     pub q_minus_n: Elem<Unencoded>,
296 }
297 
298 impl PublicScalarOps {
299     #[inline]
scalar_as_elem(&self, a: &Scalar) -> Elem<Unencoded>300     pub fn scalar_as_elem(&self, a: &Scalar) -> Elem<Unencoded> {
301         Elem {
302             limbs: a.limbs,
303             m: PhantomData,
304             encoding: PhantomData,
305         }
306     }
307 
elem_equals(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool308     pub fn elem_equals(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool {
309         for i in 0..self.public_key_ops.common.num_limbs {
310             if a.limbs[i] != b.limbs[i] {
311                 return false;
312             }
313         }
314         true
315     }
316 
elem_less_than(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool317     pub fn elem_less_than(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool {
318         let num_limbs = self.public_key_ops.common.num_limbs;
319         limbs_less_than_limbs_vartime(&a.limbs[..num_limbs], &b.limbs[..num_limbs])
320     }
321 
322     #[inline]
elem_sum(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> Elem<Unencoded>323     pub fn elem_sum(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> Elem<Unencoded> {
324         binary_op(self.public_key_ops.common.elem_add_impl, a, b)
325     }
326 }
327 
328 #[allow(non_snake_case)]
329 pub struct PrivateScalarOps {
330     pub scalar_ops: &'static ScalarOps,
331 
332     pub oneRR_mod_n: Scalar<RR>, // 1 * R**2 (mod n). TOOD: Use One<RR>.
333 }
334 
335 // This assumes n < q < 2*n.
elem_reduced_to_scalar(ops: &CommonOps, elem: &Elem<Unencoded>) -> Scalar<Unencoded>336 pub fn elem_reduced_to_scalar(ops: &CommonOps, elem: &Elem<Unencoded>) -> Scalar<Unencoded> {
337     let num_limbs = ops.num_limbs;
338     let mut r_limbs = elem.limbs;
339     limbs_reduce_once_constant_time(&mut r_limbs[..num_limbs], &ops.n.limbs[..num_limbs]);
340     Scalar {
341         limbs: r_limbs,
342         m: PhantomData,
343         encoding: PhantomData,
344     }
345 }
346 
scalar_sum(ops: &CommonOps, a: &Scalar, b: &Scalar) -> Scalar347 pub fn scalar_sum(ops: &CommonOps, a: &Scalar, b: &Scalar) -> Scalar {
348     let mut r = Scalar::zero();
349     unsafe {
350         LIMBS_add_mod(
351             r.limbs.as_mut_ptr(),
352             a.limbs.as_ptr(),
353             b.limbs.as_ptr(),
354             ops.n.limbs.as_ptr(),
355             ops.num_limbs,
356         )
357     }
358     r
359 }
360 
361 // Returns (`a` squared `squarings` times) * `b`.
elem_sqr_mul(ops: &CommonOps, a: &Elem<R>, squarings: usize, b: &Elem<R>) -> Elem<R>362 fn elem_sqr_mul(ops: &CommonOps, a: &Elem<R>, squarings: usize, b: &Elem<R>) -> Elem<R> {
363     debug_assert!(squarings >= 1);
364     let mut tmp = ops.elem_squared(a);
365     for _ in 1..squarings {
366         ops.elem_square(&mut tmp);
367     }
368     ops.elem_product(&tmp, b)
369 }
370 
371 // Sets `acc` = (`acc` squared `squarings` times) * `b`.
elem_sqr_mul_acc(ops: &CommonOps, acc: &mut Elem<R>, squarings: usize, b: &Elem<R>)372 fn elem_sqr_mul_acc(ops: &CommonOps, acc: &mut Elem<R>, squarings: usize, b: &Elem<R>) {
373     debug_assert!(squarings >= 1);
374     for _ in 0..squarings {
375         ops.elem_square(acc);
376     }
377     ops.elem_mul(acc, b)
378 }
379 
380 #[inline]
elem_parse_big_endian_fixed_consttime( ops: &CommonOps, bytes: untrusted::Input, ) -> Result<Elem<Unencoded>, error::Unspecified>381 pub fn elem_parse_big_endian_fixed_consttime(
382     ops: &CommonOps, bytes: untrusted::Input,
383 ) -> Result<Elem<Unencoded>, error::Unspecified> {
384     parse_big_endian_fixed_consttime(ops, bytes, AllowZero::Yes, &ops.q.p[..ops.num_limbs])
385 }
386 
387 #[inline]
scalar_parse_big_endian_fixed_consttime( ops: &CommonOps, bytes: untrusted::Input, ) -> Result<Scalar, error::Unspecified>388 pub fn scalar_parse_big_endian_fixed_consttime(
389     ops: &CommonOps, bytes: untrusted::Input,
390 ) -> Result<Scalar, error::Unspecified> {
391     parse_big_endian_fixed_consttime(ops, bytes, AllowZero::No, &ops.n.limbs[..ops.num_limbs])
392 }
393 
394 #[inline]
scalar_parse_big_endian_variable( ops: &CommonOps, allow_zero: AllowZero, bytes: untrusted::Input, ) -> Result<Scalar, error::Unspecified>395 pub fn scalar_parse_big_endian_variable(
396     ops: &CommonOps, allow_zero: AllowZero, bytes: untrusted::Input,
397 ) -> Result<Scalar, error::Unspecified> {
398     let mut r = Scalar::zero();
399     parse_big_endian_in_range_and_pad_consttime(
400         bytes,
401         allow_zero,
402         &ops.n.limbs[..ops.num_limbs],
403         &mut r.limbs[..ops.num_limbs],
404     )?;
405     Ok(r)
406 }
407 
scalar_parse_big_endian_partially_reduced_variable_consttime( ops: &CommonOps, allow_zero: AllowZero, bytes: untrusted::Input, ) -> Result<Scalar, error::Unspecified>408 pub fn scalar_parse_big_endian_partially_reduced_variable_consttime(
409     ops: &CommonOps, allow_zero: AllowZero, bytes: untrusted::Input,
410 ) -> Result<Scalar, error::Unspecified> {
411     let mut r = Scalar::zero();
412     parse_big_endian_in_range_partially_reduced_and_pad_consttime(
413         bytes,
414         allow_zero,
415         &ops.n.limbs[..ops.num_limbs],
416         &mut r.limbs[..ops.num_limbs],
417     )?;
418     Ok(r)
419 }
420 
parse_big_endian_fixed_consttime<M>( ops: &CommonOps, bytes: untrusted::Input, allow_zero: AllowZero, max_exclusive: &[Limb], ) -> Result<elem::Elem<M, Unencoded>, error::Unspecified>421 fn parse_big_endian_fixed_consttime<M>(
422     ops: &CommonOps, bytes: untrusted::Input, allow_zero: AllowZero, max_exclusive: &[Limb],
423 ) -> Result<elem::Elem<M, Unencoded>, error::Unspecified> {
424     if bytes.len() != ops.num_limbs * LIMB_BYTES {
425         return Err(error::Unspecified);
426     }
427     let mut r = elem::Elem::zero();
428     parse_big_endian_in_range_and_pad_consttime(
429         bytes,
430         allow_zero,
431         max_exclusive,
432         &mut r.limbs[..ops.num_limbs],
433     )?;
434     Ok(r)
435 }
436 
437 extern "C" {
LIMBS_add_mod( r: *mut Limb, a: *const Limb, b: *const Limb, m: *const Limb, num_limbs: size_t, )438     fn LIMBS_add_mod(
439         r: *mut Limb, a: *const Limb, b: *const Limb, m: *const Limb, num_limbs: size_t,
440     );
441 }
442 
443 #[cfg(test)]
444 mod tests {
445     use super::*;
446     use crate::test;
447     use std;
448     use untrusted;
449 
450     const ZERO_SCALAR: Scalar = Scalar {
451         limbs: [0; MAX_LIMBS],
452         m: PhantomData,
453         encoding: PhantomData,
454     };
455 
q_minus_n_plus_n_equals_0_test(ops: &PublicScalarOps)456     fn q_minus_n_plus_n_equals_0_test(ops: &PublicScalarOps) {
457         let cops = ops.scalar_ops.common;
458         let mut x = ops.q_minus_n;
459         cops.elem_add(&mut x, &cops.n);
460         assert!(cops.is_zero(&x));
461     }
462 
463     #[test]
p256_q_minus_n_plus_n_equals_0_test()464     fn p256_q_minus_n_plus_n_equals_0_test() {
465         q_minus_n_plus_n_equals_0_test(&p256::PUBLIC_SCALAR_OPS);
466     }
467 
468     #[test]
p384_q_minus_n_plus_n_equals_0_test()469     fn p384_q_minus_n_plus_n_equals_0_test() {
470         q_minus_n_plus_n_equals_0_test(&p384::PUBLIC_SCALAR_OPS);
471     }
472 
473     #[test]
p256_elem_add_test()474     fn p256_elem_add_test() {
475         elem_add_test(
476             &p256::PUBLIC_SCALAR_OPS,
477             test_file!("ops/p256_elem_sum_tests.txt"),
478         );
479     }
480 
481     #[test]
p384_elem_add_test()482     fn p384_elem_add_test() {
483         elem_add_test(
484             &p384::PUBLIC_SCALAR_OPS,
485             test_file!("ops/p384_elem_sum_tests.txt"),
486         );
487     }
488 
elem_add_test(ops: &PublicScalarOps, test_file: test::File)489     fn elem_add_test(ops: &PublicScalarOps, test_file: test::File) {
490         test::run(test_file, |section, test_case| {
491             assert_eq!(section, "");
492 
493             let cops = ops.public_key_ops.common;
494             let a = consume_elem(cops, test_case, "a");
495             let b = consume_elem(cops, test_case, "b");
496             let expected_sum = consume_elem(cops, test_case, "r");
497 
498             let mut actual_sum = a.clone();
499             ops.public_key_ops.common.elem_add(&mut actual_sum, &b);
500             assert_limbs_are_equal(cops, &actual_sum.limbs, &expected_sum.limbs);
501 
502             let mut actual_sum = b.clone();
503             ops.public_key_ops.common.elem_add(&mut actual_sum, &a);
504             assert_limbs_are_equal(cops, &actual_sum.limbs, &expected_sum.limbs);
505 
506             Ok(())
507         })
508     }
509 
510     // XXX: There's no `GFp_nistz256_sub` in *ring*; it's logic is inlined into
511     // the point arithmetic functions. Thus, we can't test it.
512 
513     #[test]
p384_elem_sub_test()514     fn p384_elem_sub_test() {
515         extern "C" {
516             fn GFp_p384_elem_sub(r: *mut Limb, a: *const Limb, b: *const Limb);
517         }
518         elem_sub_test(
519             &p384::COMMON_OPS,
520             GFp_p384_elem_sub,
521             test_file!("ops/p384_elem_sum_tests.txt"),
522         );
523     }
524 
elem_sub_test( ops: &CommonOps, elem_sub: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), test_file: test::File, )525     fn elem_sub_test(
526         ops: &CommonOps,
527         elem_sub: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
528         test_file: test::File,
529     ) {
530         test::run(test_file, |section, test_case| {
531             assert_eq!(section, "");
532 
533             let a = consume_elem(ops, test_case, "a");
534             let b = consume_elem(ops, test_case, "b");
535             let r = consume_elem(ops, test_case, "r");
536 
537             let mut actual_difference = Elem::<R>::zero();
538             unsafe {
539                 elem_sub(
540                     actual_difference.limbs.as_mut_ptr(),
541                     r.limbs.as_ptr(),
542                     b.limbs.as_ptr(),
543                 );
544             }
545             assert_limbs_are_equal(ops, &actual_difference.limbs, &a.limbs);
546 
547             let mut actual_difference = Elem::<R>::zero();
548             unsafe {
549                 elem_sub(
550                     actual_difference.limbs.as_mut_ptr(),
551                     r.limbs.as_ptr(),
552                     a.limbs.as_ptr(),
553                 );
554             }
555             assert_limbs_are_equal(ops, &actual_difference.limbs, &b.limbs);
556 
557             Ok(())
558         })
559     }
560 
561     // XXX: There's no `GFp_nistz256_div_by_2` in *ring*; it's logic is inlined
562     // into the point arithmetic functions. Thus, we can't test it.
563 
564     #[test]
p384_elem_div_by_2_test()565     fn p384_elem_div_by_2_test() {
566         extern "C" {
567             fn GFp_p384_elem_div_by_2(r: *mut Limb, a: *const Limb);
568         }
569         elem_div_by_2_test(
570             &p384::COMMON_OPS,
571             GFp_p384_elem_div_by_2,
572             test_file!("ops/p384_elem_div_by_2_tests.txt"),
573         );
574     }
575 
elem_div_by_2_test( ops: &CommonOps, elem_div_by_2: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), test_file: test::File, )576     fn elem_div_by_2_test(
577         ops: &CommonOps, elem_div_by_2: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
578         test_file: test::File,
579     ) {
580         test::run(test_file, |section, test_case| {
581             assert_eq!(section, "");
582 
583             let a = consume_elem(ops, test_case, "a");
584             let r = consume_elem(ops, test_case, "r");
585 
586             let mut actual_result = Elem::<R>::zero();
587             unsafe {
588                 elem_div_by_2(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr());
589             }
590             assert_limbs_are_equal(ops, &actual_result.limbs, &r.limbs);
591 
592             Ok(())
593         })
594     }
595 
596     // TODO: Add test vectors that test the range of values above `q`.
597     #[test]
p256_elem_neg_test()598     fn p256_elem_neg_test() {
599         extern "C" {
600             fn GFp_nistz256_neg(r: *mut Limb, a: *const Limb);
601         }
602         elem_neg_test(
603             &p256::COMMON_OPS,
604             GFp_nistz256_neg,
605             test_file!("ops/p256_elem_neg_tests.txt"),
606         );
607     }
608 
609     #[test]
p384_elem_neg_test()610     fn p384_elem_neg_test() {
611         extern "C" {
612             fn GFp_p384_elem_neg(r: *mut Limb, a: *const Limb);
613         }
614         elem_neg_test(
615             &p384::COMMON_OPS,
616             GFp_p384_elem_neg,
617             test_file!("ops/p384_elem_neg_tests.txt"),
618         );
619     }
620 
elem_neg_test( ops: &CommonOps, elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), test_file: test::File, )621     fn elem_neg_test(
622         ops: &CommonOps, elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
623         test_file: test::File,
624     ) {
625         test::run(test_file, |section, test_case| {
626             assert_eq!(section, "");
627 
628             let a = consume_elem(ops, test_case, "a");
629             let b = consume_elem(ops, test_case, "b");
630 
631             // Verify -a == b.
632             {
633                 let mut actual_result = Elem::<R>::zero();
634                 unsafe {
635                     elem_neg(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr());
636                 }
637                 assert_limbs_are_equal(ops, &actual_result.limbs, &b.limbs);
638             }
639 
640             // Verify -b == a.
641             {
642                 let mut actual_result = Elem::<R>::zero();
643                 unsafe {
644                     elem_neg(actual_result.limbs.as_mut_ptr(), b.limbs.as_ptr());
645                 }
646                 assert_limbs_are_equal(ops, &actual_result.limbs, &a.limbs);
647             }
648 
649             Ok(())
650         })
651     }
652 
653     #[test]
p256_elem_mul_test()654     fn p256_elem_mul_test() {
655         elem_mul_test(&p256::COMMON_OPS, test_file!("ops/p256_elem_mul_tests.txt"));
656     }
657 
658     #[test]
p384_elem_mul_test()659     fn p384_elem_mul_test() {
660         elem_mul_test(&p384::COMMON_OPS, test_file!("ops/p384_elem_mul_tests.txt"));
661     }
662 
elem_mul_test(ops: &CommonOps, test_file: test::File)663     fn elem_mul_test(ops: &CommonOps, test_file: test::File) {
664         test::run(test_file, |section, test_case| {
665             assert_eq!(section, "");
666 
667             let mut a = consume_elem(ops, test_case, "a");
668             let b = consume_elem(ops, test_case, "b");
669             let r = consume_elem(ops, test_case, "r");
670             ops.elem_mul(&mut a, &b);
671             assert_limbs_are_equal(ops, &a.limbs, &r.limbs);
672 
673             Ok(())
674         })
675     }
676 
677     #[test]
p256_scalar_mul_test()678     fn p256_scalar_mul_test() {
679         scalar_mul_test(
680             &p256::SCALAR_OPS,
681             test_file!("ops/p256_scalar_mul_tests.txt"),
682         );
683     }
684 
685     #[test]
p384_scalar_mul_test()686     fn p384_scalar_mul_test() {
687         scalar_mul_test(
688             &p384::SCALAR_OPS,
689             test_file!("ops/p384_scalar_mul_tests.txt"),
690         );
691     }
692 
scalar_mul_test(ops: &ScalarOps, test_file: test::File)693     fn scalar_mul_test(ops: &ScalarOps, test_file: test::File) {
694         test::run(test_file, |section, test_case| {
695             assert_eq!(section, "");
696             let cops = ops.common;
697             let mut a = consume_scalar(cops, test_case, "a");
698             let b = consume_scalar_mont(cops, test_case, "b");
699             let expected_result = consume_scalar(cops, test_case, "r");
700             let actual_result = ops.scalar_product(&mut a, &b);
701             assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
702 
703             Ok(())
704         })
705     }
706 
707     #[test]
p256_scalar_square_test()708     fn p256_scalar_square_test() {
709         extern "C" {
710             fn GFp_p256_scalar_sqr_rep_mont(r: *mut Limb, a: *const Limb, rep: Limb);
711         }
712         scalar_square_test(
713             &p256::SCALAR_OPS,
714             GFp_p256_scalar_sqr_rep_mont,
715             test_file!("ops/p256_scalar_square_tests.txt"),
716         );
717     }
718 
719     // XXX: There's no `p384_scalar_square_test()` because there's no dedicated
720     // `GFp_p384_scalar_sqr_rep_mont()`.
721 
scalar_square_test( ops: &ScalarOps, sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: Limb), test_file: test::File, )722     fn scalar_square_test(
723         ops: &ScalarOps, sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: Limb),
724         test_file: test::File,
725     ) {
726         test::run(test_file, |section, test_case| {
727             assert_eq!(section, "");
728             let cops = &ops.common;
729             let a = consume_scalar(cops, test_case, "a");
730             let expected_result = consume_scalar(cops, test_case, "r");
731 
732             {
733                 let mut actual_result: Scalar<R> = Scalar {
734                     limbs: [0; MAX_LIMBS],
735                     m: PhantomData,
736                     encoding: PhantomData,
737                 };
738                 unsafe {
739                     sqr_rep(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr(), 1);
740                 }
741                 assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
742             }
743 
744             {
745                 let actual_result = ops.scalar_product(&a, &a);
746                 assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
747             }
748 
749             Ok(())
750         })
751     }
752 
753     #[test]
754     #[should_panic(expected = "!self.common.is_zero(a)")]
p256_scalar_inv_to_mont_zero_panic_test()755     fn p256_scalar_inv_to_mont_zero_panic_test() {
756         let _ = p256::SCALAR_OPS.scalar_inv_to_mont(&ZERO_SCALAR);
757     }
758 
759     #[test]
760     #[should_panic(expected = "!self.common.is_zero(a)")]
p384_scalar_inv_to_mont_zero_panic_test()761     fn p384_scalar_inv_to_mont_zero_panic_test() {
762         let _ = p384::SCALAR_OPS.scalar_inv_to_mont(&ZERO_SCALAR);
763     }
764 
765     #[test]
p256_point_sum_test()766     fn p256_point_sum_test() {
767         point_sum_test(
768             &p256::PRIVATE_KEY_OPS,
769             test_file!("ops/p256_point_sum_tests.txt"),
770         );
771     }
772 
773     #[test]
p384_point_sum_test()774     fn p384_point_sum_test() {
775         point_sum_test(
776             &p384::PRIVATE_KEY_OPS,
777             test_file!("ops/p384_point_sum_tests.txt"),
778         );
779     }
780 
point_sum_test(ops: &PrivateKeyOps, test_file: test::File)781     fn point_sum_test(ops: &PrivateKeyOps, test_file: test::File) {
782         test::run(test_file, |section, test_case| {
783             assert_eq!(section, "");
784 
785             let a = consume_jacobian_point(ops, test_case, "a");
786             let b = consume_jacobian_point(ops, test_case, "b");
787             let r_expected = consume_point(ops, test_case, "r");
788 
789             let r_actual = ops.common.point_sum(&a, &b);
790             assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
791 
792             Ok(())
793         });
794     }
795 
796     #[test]
p256_point_sum_mixed_test()797     fn p256_point_sum_mixed_test() {
798         extern "C" {
799             fn GFp_nistz256_point_add_affine(
800                 r: *mut Limb,   // [p256::COMMON_OPS.num_limbs*3]
801                 a: *const Limb, // [p256::COMMON_OPS.num_limbs*3]
802                 b: *const Limb, // [p256::COMMON_OPS.num_limbs*2]
803             );
804         }
805         point_sum_mixed_test(
806             &p256::PRIVATE_KEY_OPS,
807             GFp_nistz256_point_add_affine,
808             test_file!("ops/p256_point_sum_mixed_tests.txt"),
809         );
810     }
811 
812     // XXX: There is no `GFp_nistz384_point_add_affine()`.
813 
point_sum_mixed_test( ops: &PrivateKeyOps, point_add_affine: unsafe extern "C" fn( r: *mut Limb, a: *const Limb, b: *const Limb, ), test_file: test::File, )814     fn point_sum_mixed_test(
815         ops: &PrivateKeyOps,
816         point_add_affine: unsafe extern "C" fn(
817             r: *mut Limb,   // [ops.num_limbs*3]
818             a: *const Limb, // [ops.num_limbs*3]
819             b: *const Limb, // [ops.num_limbs*2]
820         ),
821         test_file: test::File,
822     ) {
823         test::run(test_file, |section, test_case| {
824             assert_eq!(section, "");
825 
826             let a = consume_jacobian_point(ops, test_case, "a");
827             let b = consume_affine_point(ops, test_case, "b");
828             let r_expected = consume_point(ops, test_case, "r");
829 
830             let mut r_actual = Point::new_at_infinity();
831             unsafe {
832                 point_add_affine(r_actual.xyz.as_mut_ptr(), a.xyz.as_ptr(), b.xy.as_ptr());
833             }
834 
835             assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
836 
837             Ok(())
838         });
839     }
840 
841     #[test]
p256_point_double_test()842     fn p256_point_double_test() {
843         extern "C" {
844             fn GFp_nistz256_point_double(
845                 r: *mut Limb,   // [p256::COMMON_OPS.num_limbs*3]
846                 a: *const Limb, // [p256::COMMON_OPS.num_limbs*3]
847             );
848         }
849         point_double_test(
850             &p256::PRIVATE_KEY_OPS,
851             GFp_nistz256_point_double,
852             test_file!("ops/p256_point_double_tests.txt"),
853         );
854     }
855 
856     #[test]
p384_point_double_test()857     fn p384_point_double_test() {
858         extern "C" {
859             fn GFp_nistz384_point_double(
860                 r: *mut Limb,   // [p384::COMMON_OPS.num_limbs*3]
861                 a: *const Limb, // [p384::COMMON_OPS.num_limbs*3]
862             );
863         }
864         point_double_test(
865             &p384::PRIVATE_KEY_OPS,
866             GFp_nistz384_point_double,
867             test_file!("ops/p384_point_double_tests.txt"),
868         );
869     }
870 
point_double_test( ops: &PrivateKeyOps, point_double: unsafe extern "C" fn( r: *mut Limb, a: *const Limb, ), test_file: test::File, )871     fn point_double_test(
872         ops: &PrivateKeyOps,
873         point_double: unsafe extern "C" fn(
874             r: *mut Limb,   // [ops.num_limbs*3]
875             a: *const Limb, // [ops.num_limbs*3]
876         ),
877         test_file: test::File,
878     ) {
879         test::run(test_file, |section, test_case| {
880             assert_eq!(section, "");
881 
882             let a = consume_jacobian_point(ops, test_case, "a");
883             let r_expected = consume_point(ops, test_case, "r");
884 
885             let mut r_actual = Point::new_at_infinity();
886             unsafe {
887                 point_double(r_actual.xyz.as_mut_ptr(), a.xyz.as_ptr());
888             }
889 
890             assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
891 
892             Ok(())
893         });
894     }
895 
896     #[test]
p256_point_mul_test()897     fn p256_point_mul_test() {
898         point_mul_tests(
899             &p256::PRIVATE_KEY_OPS,
900             test_file!("ops/p256_point_mul_tests.txt"),
901         );
902     }
903 
904     #[test]
p384_point_mul_test()905     fn p384_point_mul_test() {
906         point_mul_tests(
907             &p384::PRIVATE_KEY_OPS,
908             test_file!("ops/p384_point_mul_tests.txt"),
909         );
910     }
911 
point_mul_tests(ops: &PrivateKeyOps, test_file: test::File)912     fn point_mul_tests(ops: &PrivateKeyOps, test_file: test::File) {
913         test::run(test_file, |section, test_case| {
914             assert_eq!(section, "");
915             let p_scalar = consume_scalar(ops.common, test_case, "p_scalar");
916             let (x, y) = match consume_point(ops, test_case, "p") {
917                 TestPoint::Infinity => {
918                     panic!("can't be inf.");
919                 },
920                 TestPoint::Affine(x, y) => (x, y),
921             };
922             let expected_result = consume_point(ops, test_case, "r");
923             let actual_result = ops.point_mul(&p_scalar, &(x, y));
924             assert_point_actual_equals_expected(ops, &actual_result, &expected_result);
925             Ok(())
926         })
927     }
928 
929     #[test]
p256_point_mul_serialized_test()930     fn p256_point_mul_serialized_test() {
931         point_mul_serialized_test(
932             &p256::PRIVATE_KEY_OPS,
933             &p256::PUBLIC_KEY_OPS,
934             test_file!("ops/p256_point_mul_serialized_tests.txt"),
935         );
936     }
937 
point_mul_serialized_test( priv_ops: &PrivateKeyOps, pub_ops: &PublicKeyOps, test_file: test::File, )938     fn point_mul_serialized_test(
939         priv_ops: &PrivateKeyOps, pub_ops: &PublicKeyOps, test_file: test::File,
940     ) {
941         let cops = pub_ops.common;
942 
943         test::run(test_file, |section, test_case| {
944             assert_eq!(section, "");
945             let p_scalar = consume_scalar(cops, test_case, "p_scalar");
946 
947             let p = test_case.consume_bytes("p");
948             let p = super::super::public_key::parse_uncompressed_point(
949                 pub_ops,
950                 untrusted::Input::from(&p),
951             )
952             .expect("valid point");
953 
954             let expected_result = test_case.consume_bytes("r");
955 
956             let product = priv_ops.point_mul(&p_scalar, &p);
957 
958             let mut actual_result = vec![4u8; 1 + (2 * (cops.num_limbs * LIMB_BYTES))];
959             {
960                 let (x, y) = actual_result[1..].split_at_mut(cops.num_limbs * LIMB_BYTES);
961                 super::super::private_key::big_endian_affine_from_jacobian(
962                     priv_ops,
963                     Some(x),
964                     Some(y),
965                     &product,
966                 )
967                 .expect("successful encoding");
968             }
969 
970             assert_eq!(expected_result, actual_result);
971 
972             Ok(())
973         })
974     }
975 
976     #[test]
p256_point_mul_base_test()977     fn p256_point_mul_base_test() {
978         point_mul_base_tests(
979             &p256::PRIVATE_KEY_OPS,
980             test_file!("ops/p256_point_mul_base_tests.txt"),
981         );
982     }
983 
984     #[test]
p384_point_mul_base_test()985     fn p384_point_mul_base_test() {
986         point_mul_base_tests(
987             &p384::PRIVATE_KEY_OPS,
988             test_file!("ops/p384_point_mul_base_tests.txt"),
989         );
990     }
991 
point_mul_base_tests(ops: &PrivateKeyOps, test_file: test::File)992     fn point_mul_base_tests(ops: &PrivateKeyOps, test_file: test::File) {
993         test::run(test_file, |section, test_case| {
994             assert_eq!(section, "");
995             let g_scalar = consume_scalar(ops.common, test_case, "g_scalar");
996             let expected_result = consume_point(ops, test_case, "r");
997             let actual_result = ops.point_mul_base(&g_scalar);
998             assert_point_actual_equals_expected(ops, &actual_result, &expected_result);
999             Ok(())
1000         })
1001     }
1002 
assert_point_actual_equals_expected( ops: &PrivateKeyOps, actual_point: &Point, expected_point: &TestPoint, )1003     fn assert_point_actual_equals_expected(
1004         ops: &PrivateKeyOps, actual_point: &Point, expected_point: &TestPoint,
1005     ) {
1006         let cops = ops.common;
1007         let actual_x = &cops.point_x(&actual_point);
1008         let actual_y = &cops.point_y(&actual_point);
1009         let actual_z = &cops.point_z(&actual_point);
1010         match expected_point {
1011             TestPoint::Infinity => {
1012                 let zero = Elem::zero();
1013                 assert_elems_are_equal(cops, &actual_z, &zero);
1014             },
1015             TestPoint::Affine(expected_x, expected_y) => {
1016                 let zz_inv = ops.elem_inverse_squared(&actual_z);
1017                 let x_aff = cops.elem_product(&actual_x, &zz_inv);
1018                 let y_aff = {
1019                     let zzzz_inv = cops.elem_squared(&zz_inv);
1020                     let zzz_inv = cops.elem_product(&actual_z, &zzzz_inv);
1021                     cops.elem_product(&actual_y, &zzz_inv)
1022                 };
1023 
1024                 assert_elems_are_equal(cops, &x_aff, &expected_x);
1025                 assert_elems_are_equal(cops, &y_aff, &expected_y);
1026             },
1027         }
1028     }
1029 
consume_jacobian_point( ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str, ) -> Point1030     fn consume_jacobian_point(
1031         ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str,
1032     ) -> Point {
1033         let input = test_case.consume_string(name);
1034         let elems = input.split(", ").collect::<Vec<&str>>();
1035         assert_eq!(elems.len(), 3);
1036         let mut p = Point::new_at_infinity();
1037         consume_point_elem(ops.common, &mut p.xyz, &elems, 0);
1038         consume_point_elem(ops.common, &mut p.xyz, &elems, 1);
1039         consume_point_elem(ops.common, &mut p.xyz, &elems, 2);
1040         p
1041     }
1042 
1043     struct AffinePoint {
1044         xy: [Limb; 2 * MAX_LIMBS],
1045     }
1046 
consume_affine_point( ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str, ) -> AffinePoint1047     fn consume_affine_point(
1048         ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str,
1049     ) -> AffinePoint {
1050         let input = test_case.consume_string(name);
1051         let elems = input.split(", ").collect::<Vec<&str>>();
1052         assert_eq!(elems.len(), 2);
1053         let mut p = AffinePoint {
1054             xy: [0; 2 * MAX_LIMBS],
1055         };
1056         consume_point_elem(ops.common, &mut p.xy, &elems, 0);
1057         consume_point_elem(ops.common, &mut p.xy, &elems, 1);
1058         p
1059     }
1060 
consume_point_elem(ops: &CommonOps, limbs_out: &mut [Limb], elems: &Vec<&str>, i: usize)1061     fn consume_point_elem(ops: &CommonOps, limbs_out: &mut [Limb], elems: &Vec<&str>, i: usize) {
1062         let bytes = test::from_hex(elems[i]).unwrap();
1063         let bytes = untrusted::Input::from(&bytes);
1064         let r: Elem<Unencoded> = elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1065         // XXX: “Transmute” this to `Elem<R>` limbs.
1066         limbs_out[(i * ops.num_limbs)..((i + 1) * ops.num_limbs)]
1067             .copy_from_slice(&r.limbs[..ops.num_limbs]);
1068     }
1069 
1070     enum TestPoint {
1071         Infinity,
1072         Affine(Elem<R>, Elem<R>),
1073     }
1074 
consume_point(ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str) -> TestPoint1075     fn consume_point(ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str) -> TestPoint {
1076         fn consume_point_elem(ops: &CommonOps, elems: &Vec<&str>, i: usize) -> Elem<R> {
1077             let bytes = test::from_hex(elems[i]).unwrap();
1078             let bytes = untrusted::Input::from(&bytes);
1079             let unencoded: Elem<Unencoded> =
1080                 elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1081             // XXX: “Transmute” this to `Elem<R>` limbs.
1082             Elem {
1083                 limbs: unencoded.limbs,
1084                 m: PhantomData,
1085                 encoding: PhantomData,
1086             }
1087         }
1088 
1089         let input = test_case.consume_string(name);
1090         if input == "inf" {
1091             return TestPoint::Infinity;
1092         }
1093         let elems = input.split(", ").collect::<Vec<&str>>();
1094         assert_eq!(elems.len(), 2);
1095         let x = consume_point_elem(ops.common, &elems, 0);
1096         let y = consume_point_elem(ops.common, &elems, 1);
1097         TestPoint::Affine(x, y)
1098     }
1099 
assert_elems_are_equal(ops: &CommonOps, a: &Elem<R>, b: &Elem<R>)1100     fn assert_elems_are_equal(ops: &CommonOps, a: &Elem<R>, b: &Elem<R>) {
1101         assert_limbs_are_equal(ops, &a.limbs, &b.limbs)
1102     }
1103 
assert_limbs_are_equal( ops: &CommonOps, actual: &[Limb; MAX_LIMBS], expected: &[Limb; MAX_LIMBS], )1104     fn assert_limbs_are_equal(
1105         ops: &CommonOps, actual: &[Limb; MAX_LIMBS], expected: &[Limb; MAX_LIMBS],
1106     ) {
1107         for i in 0..ops.num_limbs {
1108             if actual[i] != expected[i] {
1109                 let mut s = std::string::String::new();
1110                 for j in 0..ops.num_limbs {
1111                     let formatted = format!("{:016x}", actual[ops.num_limbs - j - 1]);
1112                     s.push_str(&formatted);
1113                 }
1114                 print!("\n");
1115                 panic!("Actual != Expected,\nActual = {}", s);
1116             }
1117         }
1118     }
1119 
consume_elem(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Elem<R>1120     fn consume_elem(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Elem<R> {
1121         let bytes = consume_padded_bytes(ops, test_case, name);
1122         let bytes = untrusted::Input::from(&bytes);
1123         let r: Elem<Unencoded> = elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1124         // XXX: “Transmute” this to an `Elem<R>`.
1125         Elem {
1126             limbs: r.limbs,
1127             m: PhantomData,
1128             encoding: PhantomData,
1129         }
1130     }
1131 
consume_scalar(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Scalar1132     fn consume_scalar(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Scalar {
1133         let bytes = test_case.consume_bytes(name);
1134         let bytes = untrusted::Input::from(&bytes);
1135         scalar_parse_big_endian_variable(ops, AllowZero::Yes, bytes).unwrap()
1136     }
1137 
consume_scalar_mont( ops: &CommonOps, test_case: &mut test::TestCase, name: &str, ) -> Scalar<R>1138     fn consume_scalar_mont(
1139         ops: &CommonOps, test_case: &mut test::TestCase, name: &str,
1140     ) -> Scalar<R> {
1141         let bytes = test_case.consume_bytes(name);
1142         let bytes = untrusted::Input::from(&bytes);
1143         let s = scalar_parse_big_endian_variable(ops, AllowZero::Yes, bytes).unwrap();
1144         // “Transmute” it to a `Scalar<R>`.
1145         Scalar {
1146             limbs: s.limbs,
1147             m: PhantomData,
1148             encoding: PhantomData,
1149         }
1150     }
1151 
consume_padded_bytes( ops: &CommonOps, test_case: &mut test::TestCase, name: &str, ) -> Vec<u8>1152     fn consume_padded_bytes(
1153         ops: &CommonOps, test_case: &mut test::TestCase, name: &str,
1154     ) -> Vec<u8> {
1155         let unpadded_bytes = test_case.consume_bytes(name);
1156         let mut bytes = vec![0; (ops.num_limbs * LIMB_BYTES) - unpadded_bytes.len()];
1157         bytes.extend(&unpadded_bytes);
1158         bytes
1159     }
1160 }
1161 
1162 #[cfg(feature = "internal_benches")]
1163 mod internal_benches {
1164     use super::{Limb, MAX_LIMBS};
1165 
1166     pub const LIMBS_1: [Limb; MAX_LIMBS] = limbs![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
1167 
1168     pub const LIMBS_ALTERNATING_10: [Limb; MAX_LIMBS] = limbs![
1169         0b10101010_10101010_10101010_10101010,
1170         0b10101010_10101010_10101010_10101010,
1171         0b10101010_10101010_10101010_10101010,
1172         0b10101010_10101010_10101010_10101010,
1173         0b10101010_10101010_10101010_10101010,
1174         0b10101010_10101010_10101010_10101010,
1175         0b10101010_10101010_10101010_10101010,
1176         0b10101010_10101010_10101010_10101010,
1177         0b10101010_10101010_10101010_10101010,
1178         0b10101010_10101010_10101010_10101010,
1179         0b10101010_10101010_10101010_10101010,
1180         0b10101010_10101010_10101010_10101010
1181     ];
1182 }
1183 
1184 #[cfg(feature = "internal_benches")]
1185 macro_rules! bench_curve {
1186     ( $vectors:expr ) => {
1187         use super::super::{Elem, Scalar};
1188         extern crate test;
1189 
1190         #[bench]
1191         fn elem_inverse_squared_bench(bench: &mut test::Bencher) {
1192             // This benchmark assumes that `elem_inverse_squared()` is
1193             // constant-time so inverting 1 mod q is as good of a choice as
1194             // anything.
1195             let mut a = Elem::zero();
1196             a.limbs[0] = 1;
1197             bench.iter(|| {
1198                 let _ = PRIVATE_KEY_OPS.elem_inverse_squared(&a);
1199             });
1200         }
1201 
1202         #[bench]
1203         fn elem_product_bench(bench: &mut test::Bencher) {
1204             // This benchmark assumes that the multiplication is constant-time
1205             // so 0 * 0 is as good of a choice as anything.
1206             let a: Elem<R> = Elem::zero();
1207             let b: Elem<R> = Elem::zero();
1208             bench.iter(|| {
1209                 let _ = COMMON_OPS.elem_product(&a, &b);
1210             });
1211         }
1212 
1213         #[bench]
1214         fn elem_squared_bench(bench: &mut test::Bencher) {
1215             // This benchmark assumes that the squaring is constant-time so
1216             // 0**2 * 0 is as good of a choice as anything.
1217             let a = Elem::zero();
1218             bench.iter(|| {
1219                 let _ = COMMON_OPS.elem_squared(&a);
1220             });
1221         }
1222 
1223         #[bench]
1224         fn scalar_inv_to_mont_bench(bench: &mut test::Bencher) {
1225             const VECTORS: &[Scalar] = $vectors;
1226             let vectors_len = VECTORS.len();
1227             let mut i = 0;
1228             bench.iter(|| {
1229                 let _ = SCALAR_OPS.scalar_inv_to_mont(&VECTORS[i]);
1230 
1231                 i += 1;
1232                 if i == vectors_len {
1233                     i = 0;
1234                 }
1235             });
1236         }
1237     };
1238 }
1239 
1240 mod elem;
1241 pub mod p256;
1242 pub mod p384;
1243