ring/ec/suite_b/
ops.rs

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 AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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
15use crate::{
16    arithmetic::limbs_from_hex,
17    arithmetic::montgomery::*,
18    bb::LeakyWord,
19    cpu,
20    error::{self, LenMismatchError},
21    limb::*,
22};
23use core::marker::PhantomData;
24
25use elem::{mul_mont, unary_op, unary_op_assign, unary_op_from_binary_op_assign};
26
27/// A field element, i.e. an element of ℤ/qℤ for the curve's field modulus
28/// *q*.
29pub type Elem<E> = elem::Elem<Q, E>;
30type PublicElem<E> = elem::PublicElem<Q, E>;
31
32/// Represents the (prime) order *q* of the curve's prime field.
33#[derive(Clone, Copy)]
34pub enum Q {}
35
36/// A scalar. Its value is in [0, n). Zero-valued scalars are forbidden in most
37/// contexts.
38pub type Scalar<E = Unencoded> = elem::Elem<N, E>;
39type PublicScalar<E> = elem::PublicElem<N, E>;
40
41/// Represents the prime order *n* of the curve's group.
42#[derive(Clone, Copy)]
43pub enum N {}
44
45pub(super) struct Modulus<M> {
46    // TODO: [Limb; elem::NumLimbs::MAX]
47    limbs: &'static [Limb; elem::NumLimbs::MAX],
48    num_limbs: elem::NumLimbs,
49    cops: &'static CommonOps,
50    m: PhantomData<M>,
51    cpu: cpu::Features,
52}
53
54pub struct Point {
55    // The coordinates are stored in a contiguous array, where the first
56    // `ops.num_limbs` elements are the X coordinate, the next
57    // `ops.num_limbs` elements are the Y coordinate, and the next
58    // `ops.num_limbs` elements are the Z coordinate. This layout is dictated
59    // by the requirements of the nistz256 code.
60    xyz: [Limb; 3 * elem::NumLimbs::MAX],
61}
62
63impl Point {
64    pub fn new_at_infinity() -> Self {
65        Self {
66            xyz: [0; 3 * elem::NumLimbs::MAX],
67        }
68    }
69}
70
71/// Operations and values needed by all curve operations.
72pub struct CommonOps {
73    num_limbs: elem::NumLimbs,
74    q: PublicModulus,
75    n: PublicElem<Unencoded>,
76
77    pub a: PublicElem<R>, // Must be -3 mod q
78    pub b: PublicElem<R>,
79
80    // In all cases, `r`, `a`, and `b` may all alias each other.
81    elem_mul_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
82    elem_sqr_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
83}
84
85impl CommonOps {
86    pub(super) fn elem_modulus(&'static self, cpu_features: cpu::Features) -> Modulus<Q> {
87        Modulus {
88            // TODO: limbs: self.q.p.map(Limb::from),
89            limbs: &self.q.p,
90            num_limbs: self.num_limbs,
91            cops: self,
92            m: PhantomData,
93            cpu: cpu_features,
94        }
95    }
96
97    pub(super) fn scalar_modulus(&'static self, cpu_features: cpu::Features) -> Modulus<N> {
98        Modulus {
99            // TODO: limbs: self.n.limbs.map(Limb::from),
100            limbs: &self.n.limbs,
101            num_limbs: self.num_limbs,
102            cops: self,
103            m: PhantomData,
104            cpu: cpu_features,
105        }
106    }
107
108    // The length of a field element, which is the same as the length of a
109    // scalar, in bytes.
110    pub fn len(&self) -> usize {
111        // Keep in sync with `Modulus<M>::len()`
112        self.num_limbs.into() * LIMB_BYTES
113    }
114
115    #[cfg(test)]
116    pub(super) fn n_limbs(&self) -> &[Limb] {
117        &self.n.limbs[..self.num_limbs.into()]
118    }
119}
120
121impl<M> Modulus<M> {
122    pub fn cpu(&self) -> cpu::Features {
123        self.cpu
124    }
125
126    // Keep in sync with `CommonOps::len()`.
127    pub fn bytes_len(&self) -> usize {
128        self.num_limbs.into() * LIMB_BYTES
129    }
130}
131
132impl<M> Modulus<M> {
133    #[inline]
134    pub fn add_assign<E: Encoding>(&self, a: &mut elem::Elem<M, E>, b: &elem::Elem<M, E>) {
135        let num_limbs = self.num_limbs.into();
136        limbs_add_assign_mod(
137            &mut a.limbs[..num_limbs],
138            &b.limbs[..num_limbs],
139            &self.limbs[..num_limbs],
140        )
141        .unwrap_or_else(unwrap_impossible_len_mismatch_error)
142    }
143}
144
145impl Modulus<Q> {
146    #[inline]
147    pub fn elems_are_equal<E: Encoding>(&self, a: &Elem<E>, b: &Elem<E>) -> LimbMask {
148        let num_limbs = self.num_limbs.into();
149        limbs_equal_limbs_consttime(&a.limbs[..num_limbs], &b.limbs[..num_limbs])
150            .unwrap_or_else(unwrap_impossible_len_mismatch_error)
151    }
152
153    #[inline]
154    pub fn elem_unencoded(&self, a: &Elem<R>) -> Elem<Unencoded> {
155        self.elem_product(a, &Elem::one())
156    }
157}
158
159impl CommonOps {
160    #[inline]
161    fn is_zero<M, E: Encoding>(&self, a: &elem::Elem<M, E>) -> bool {
162        let num_limbs = self.num_limbs.into();
163        limbs_are_zero(&a.limbs[..num_limbs]).leak()
164    }
165
166    #[inline]
167    fn elem_mul(&self, a: &mut Elem<R>, b: &Elem<R>, _cpu: cpu::Features) {
168        elem::binary_op_assign(self.elem_mul_mont, a, b)
169    }
170
171    #[inline]
172    fn elem_product<EA: Encoding, EB: Encoding>(
173        &self,
174        a: &Elem<EA>,
175        b: &Elem<EB>,
176        _cpu: cpu::Features,
177    ) -> Elem<<(EA, EB) as ProductEncoding>::Output>
178    where
179        (EA, EB): ProductEncoding,
180    {
181        mul_mont(self.elem_mul_mont, a, b)
182    }
183
184    #[inline]
185    fn elem_square(&self, a: &mut Elem<R>, _cpu: cpu::Features) {
186        unary_op_assign(self.elem_sqr_mont, a);
187    }
188
189    #[inline]
190    fn elem_squared(&self, a: &Elem<R>, _cpu: cpu::Features) -> Elem<R> {
191        unary_op(self.elem_sqr_mont, a)
192    }
193}
194
195impl Modulus<Q> {
196    #[inline]
197    pub fn elem_mul(&self, a: &mut Elem<R>, b: &Elem<R>) {
198        self.cops.elem_mul(a, b, self.cpu)
199    }
200
201    #[inline]
202    pub fn elem_product<EA: Encoding, EB: Encoding>(
203        &self,
204        a: &Elem<EA>,
205        b: &Elem<EB>,
206    ) -> Elem<<(EA, EB) as ProductEncoding>::Output>
207    where
208        (EA, EB): ProductEncoding,
209    {
210        self.cops.elem_product(a, b, self.cpu)
211    }
212
213    #[inline]
214    pub fn elem_square(&self, a: &mut Elem<R>) {
215        self.cops.elem_square(a, self.cpu)
216    }
217
218    #[inline]
219    pub fn elem_squared(&self, a: &Elem<R>) -> Elem<R> {
220        self.cops.elem_squared(a, self.cpu)
221    }
222}
223
224impl<M> Modulus<M> {
225    #[inline]
226    pub fn is_zero<E: Encoding>(&self, a: &elem::Elem<M, E>) -> bool {
227        self.cops.is_zero(a)
228    }
229}
230
231impl Modulus<Q> {
232    pub fn elem_verify_is_not_zero(&self, a: &Elem<R>) -> Result<(), error::Unspecified> {
233        if self.is_zero(a) {
234            Err(error::Unspecified)
235        } else {
236            Ok(())
237        }
238    }
239
240    pub(super) fn a(&self) -> &'static PublicElem<R> {
241        &self.cops.a
242    }
243    pub(super) fn b(&self) -> &'static PublicElem<R> {
244        &self.cops.b
245    }
246}
247
248impl PrivateKeyOps {
249    pub(super) fn point_sum(&self, a: &Point, b: &Point, _cpu: cpu::Features) -> Point {
250        let mut r = Point::new_at_infinity();
251        unsafe {
252            (self.point_add_jacobian_impl)(r.xyz.as_mut_ptr(), a.xyz.as_ptr(), b.xyz.as_ptr())
253        }
254        r
255    }
256}
257
258impl Modulus<Q> {
259    pub fn point_x(&self, p: &Point) -> Elem<R> {
260        let num_limbs = self.num_limbs.into();
261        let mut r = Elem::zero();
262        r.limbs[..num_limbs].copy_from_slice(&p.xyz[0..num_limbs]);
263        r
264    }
265
266    pub fn point_y(&self, p: &Point) -> Elem<R> {
267        let num_limbs = self.num_limbs.into();
268        let mut r = Elem::zero();
269        r.limbs[..num_limbs].copy_from_slice(&p.xyz[num_limbs..(2 * num_limbs)]);
270        r
271    }
272
273    pub fn point_z(&self, p: &Point) -> Elem<R> {
274        let num_limbs = self.num_limbs.into();
275        let mut r = Elem::zero();
276        r.limbs[..num_limbs].copy_from_slice(&p.xyz[(2 * num_limbs)..(3 * num_limbs)]);
277        r
278    }
279}
280
281struct PublicModulus {
282    p: [LeakyLimb; elem::NumLimbs::MAX],
283    rr: PublicElem<RR>,
284}
285
286/// Operations on private keys, for ECDH and ECDSA signing.
287pub struct PrivateKeyOps {
288    pub common: &'static CommonOps,
289    elem_inv_squared: fn(q: &Modulus<Q>, a: &Elem<R>) -> Elem<R>,
290    point_mul_base_impl: fn(a: &Scalar, cpu: cpu::Features) -> Point,
291    point_mul_impl: unsafe extern "C" fn(
292        r: *mut Limb,          // [3][num_limbs]
293        p_scalar: *const Limb, // [num_limbs]
294        p_x: *const Limb,      // [num_limbs]
295        p_y: *const Limb,      // [num_limbs]
296    ),
297    point_add_jacobian_impl: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
298}
299
300impl PrivateKeyOps {
301    pub fn leak_limbs<'a>(&self, a: &'a Elem<Unencoded>) -> &'a [Limb] {
302        &a.limbs[..self.common.num_limbs.into()]
303    }
304
305    #[inline(always)]
306    pub(super) fn point_mul_base(&self, a: &Scalar, cpu: cpu::Features) -> Point {
307        (self.point_mul_base_impl)(a, cpu)
308    }
309
310    #[inline(always)]
311    pub(super) fn point_mul(
312        &self,
313        p_scalar: &Scalar,
314        (p_x, p_y): &(Elem<R>, Elem<R>),
315        _cpu: cpu::Features,
316    ) -> Point {
317        let mut r = Point::new_at_infinity();
318        unsafe {
319            (self.point_mul_impl)(
320                r.xyz.as_mut_ptr(),
321                p_scalar.limbs.as_ptr(),
322                p_x.limbs.as_ptr(),
323                p_y.limbs.as_ptr(),
324            );
325        }
326        r
327    }
328
329    #[inline]
330    pub(super) fn elem_inverse_squared(&self, q: &Modulus<Q>, a: &Elem<R>) -> Elem<R> {
331        (self.elem_inv_squared)(q, a)
332    }
333}
334
335/// Operations and values needed by all operations on public keys (ECDH
336/// agreement and ECDSA verification).
337pub struct PublicKeyOps {
338    pub common: &'static CommonOps,
339}
340
341impl PublicKeyOps {
342    // The serialized bytes are in big-endian order, zero-padded. The limbs
343    // of `Elem` are in the native endianness, least significant limb to
344    // most significant limb. Besides the parsing, conversion, this also
345    // implements NIST SP 800-56A Step 2: "Verify that xQ and yQ are integers
346    // in the interval [0, p-1] in the case that q is an odd prime p[.]"
347    pub(super) fn elem_parse(
348        &self,
349        q: &Modulus<Q>,
350        input: &mut untrusted::Reader,
351    ) -> Result<Elem<R>, error::Unspecified> {
352        let _cpu = cpu::features();
353        let encoded_value = input.read_bytes(self.common.len())?;
354        let parsed = elem_parse_big_endian_fixed_consttime(q, encoded_value)?;
355        let mut r = Elem::zero();
356        let rr = Elem::from(&self.common.q.rr);
357        // Montgomery encode (elem_to_mont).
358        // TODO: do something about this.
359        unsafe {
360            (self.common.elem_mul_mont)(
361                r.limbs.as_mut_ptr(),
362                parsed.limbs.as_ptr(),
363                rr.limbs.as_ptr(),
364            )
365        }
366        Ok(r)
367    }
368}
369
370// Operations used by both ECDSA signing and ECDSA verification. In general
371// these must be side-channel resistant.
372pub struct ScalarOps {
373    pub common: &'static CommonOps,
374
375    scalar_mul_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
376}
377
378impl ScalarOps {
379    pub(super) fn scalar_modulus(&'static self, cpu_features: cpu::Features) -> Modulus<N> {
380        self.common.scalar_modulus(cpu_features)
381    }
382
383    // The (maximum) length of a scalar, not including any padding.
384    pub fn scalar_bytes_len(&self) -> usize {
385        self.common.len()
386    }
387}
388
389impl ScalarOps {
390    pub fn leak_limbs<'s>(&self, s: &'s Scalar) -> &'s [Limb] {
391        &s.limbs[..self.common.num_limbs.into()]
392    }
393
394    #[inline]
395    pub(super) fn scalar_product<EA: Encoding, EB: Encoding>(
396        &self,
397        a: &Scalar<EA>,
398        b: &Scalar<EB>,
399        _cpu: cpu::Features,
400    ) -> Scalar<<(EA, EB) as ProductEncoding>::Output>
401    where
402        (EA, EB): ProductEncoding,
403    {
404        mul_mont(self.scalar_mul_mont, a, b)
405    }
406}
407
408/// Operations on public scalars needed by ECDSA signature verification.
409pub struct PublicScalarOps {
410    pub scalar_ops: &'static ScalarOps,
411    pub public_key_ops: &'static PublicKeyOps,
412
413    pub(super) twin_mul: fn(
414        g_scalar: &Scalar,
415        p_scalar: &Scalar,
416        p_xy: &(Elem<R>, Elem<R>),
417        cpu: cpu::Features,
418    ) -> Point,
419    scalar_inv_to_mont_vartime: fn(s: &Scalar<Unencoded>, cpu: cpu::Features) -> Scalar<R>,
420    pub(super) q_minus_n: PublicElem<Unencoded>,
421}
422
423impl PublicScalarOps {
424    pub fn n(&self) -> &PublicElem<Unencoded> {
425        &self.scalar_ops.common.n
426    }
427
428    #[inline]
429    pub fn scalar_as_elem(&self, a: &Scalar) -> Elem<Unencoded> {
430        Elem {
431            limbs: a.limbs,
432            m: PhantomData,
433            encoding: PhantomData,
434        }
435    }
436}
437
438impl Modulus<Q> {
439    pub fn elem_less_than_vartime(&self, a: &Elem<Unencoded>, b: &PublicElem<Unencoded>) -> bool {
440        let num_limbs = self.num_limbs.into();
441        limbs_less_than_limbs_vartime(&a.limbs[..num_limbs], &b.limbs[..num_limbs])
442            .unwrap_or_else(|LenMismatchError { .. }| unreachable!())
443    }
444}
445
446impl PublicScalarOps {
447    pub(super) fn scalar_inv_to_mont_vartime(
448        &self,
449        s: &Scalar<Unencoded>,
450        cpu: cpu::Features,
451    ) -> Scalar<R> {
452        (self.scalar_inv_to_mont_vartime)(s, cpu)
453    }
454}
455
456#[allow(non_snake_case)]
457pub struct PrivateScalarOps {
458    pub scalar_ops: &'static ScalarOps,
459
460    oneRR_mod_n: PublicScalar<RR>, // 1 * R**2 (mod n). TOOD: Use One<RR>.
461    scalar_inv_to_mont: fn(a: Scalar<R>, cpu: cpu::Features) -> Scalar<R>,
462}
463
464impl PrivateScalarOps {
465    pub(super) fn to_mont(&self, s: &Scalar<Unencoded>, cpu: cpu::Features) -> Scalar<R> {
466        self.scalar_ops
467            .scalar_product(s, &Scalar::from(&self.oneRR_mod_n), cpu)
468    }
469
470    /// Returns the modular inverse of `a` (mod `n`). Panics if `a` is zero.
471    pub(super) fn scalar_inv_to_mont(&self, a: &Scalar, cpu: cpu::Features) -> Scalar<R> {
472        assert!(!self.scalar_ops.common.is_zero(a));
473        let a = self.to_mont(a, cpu);
474        (self.scalar_inv_to_mont)(a, cpu)
475    }
476}
477
478// XXX: Inefficient and unnecessarily depends on `PrivateKeyOps`. TODO: implement interleaved wNAF
479// multiplication.
480fn twin_mul_inefficient(
481    ops: &PrivateKeyOps,
482    g_scalar: &Scalar,
483    p_scalar: &Scalar,
484    p_xy: &(Elem<R>, Elem<R>),
485    cpu: cpu::Features,
486) -> Point {
487    let scaled_g = ops.point_mul_base(g_scalar, cpu);
488    let scaled_p = ops.point_mul(p_scalar, p_xy, cpu);
489    ops.point_sum(&scaled_g, &scaled_p, cpu)
490}
491
492// This assumes n < q < 2*n.
493impl Modulus<N> {
494    pub fn elem_reduced_to_scalar(&self, elem: &Elem<Unencoded>) -> Scalar<Unencoded> {
495        let num_limbs = self.num_limbs.into();
496        let mut r_limbs = elem.limbs;
497        limbs_reduce_once(&mut r_limbs[..num_limbs], &self.limbs[..num_limbs])
498            .unwrap_or_else(unwrap_impossible_len_mismatch_error);
499        Scalar {
500            limbs: r_limbs,
501            m: PhantomData,
502            encoding: PhantomData,
503        }
504    }
505}
506
507// Returns (`a` squared `squarings` times) * `b`.
508fn elem_sqr_mul(
509    ops: &CommonOps,
510    a: &Elem<R>,
511    squarings: LeakyWord,
512    b: &Elem<R>,
513    cpu: cpu::Features,
514) -> Elem<R> {
515    debug_assert!(squarings >= 1);
516    let mut tmp = ops.elem_squared(a, cpu);
517    for _ in 1..squarings {
518        ops.elem_square(&mut tmp, cpu);
519    }
520    ops.elem_product(&tmp, b, cpu)
521}
522
523// Sets `acc` = (`acc` squared `squarings` times) * `b`.
524fn elem_sqr_mul_acc(
525    ops: &CommonOps,
526    acc: &mut Elem<R>,
527    squarings: LeakyWord,
528    b: &Elem<R>,
529    cpu: cpu::Features,
530) {
531    debug_assert!(squarings >= 1);
532    for _ in 0..squarings {
533        ops.elem_square(acc, cpu);
534    }
535    ops.elem_mul(acc, b, cpu)
536}
537
538#[inline]
539pub(super) fn elem_parse_big_endian_fixed_consttime(
540    q: &Modulus<Q>,
541    bytes: untrusted::Input,
542) -> Result<Elem<Unencoded>, error::Unspecified> {
543    parse_big_endian_fixed_consttime(q, bytes, AllowZero::Yes)
544}
545
546#[inline]
547pub(super) fn scalar_parse_big_endian_fixed_consttime(
548    n: &Modulus<N>,
549    bytes: untrusted::Input,
550) -> Result<Scalar, error::Unspecified> {
551    parse_big_endian_fixed_consttime(n, bytes, AllowZero::No)
552}
553
554#[inline]
555pub(super) fn scalar_parse_big_endian_variable(
556    n: &Modulus<N>,
557    allow_zero: AllowZero,
558    bytes: untrusted::Input,
559) -> Result<Scalar, error::Unspecified> {
560    let num_limbs = n.num_limbs.into();
561    let mut r = Scalar::zero();
562    parse_big_endian_in_range_and_pad_consttime(
563        bytes,
564        allow_zero,
565        &n.limbs[..num_limbs],
566        &mut r.limbs[..num_limbs],
567    )?;
568    Ok(r)
569}
570
571pub(super) fn scalar_parse_big_endian_partially_reduced_variable_consttime(
572    n: &Modulus<N>,
573    bytes: untrusted::Input,
574) -> Result<Scalar, error::Unspecified> {
575    let num_limbs = n.num_limbs.into();
576    let mut r = Scalar::zero();
577    {
578        let r = &mut r.limbs[..num_limbs];
579        parse_big_endian_and_pad_consttime(bytes, r)?;
580        limbs_reduce_once(r, &n.limbs[..num_limbs])
581            .unwrap_or_else(unwrap_impossible_len_mismatch_error);
582    }
583
584    Ok(r)
585}
586
587fn parse_big_endian_fixed_consttime<M>(
588    m: &Modulus<M>,
589    bytes: untrusted::Input,
590    allow_zero: AllowZero,
591) -> Result<elem::Elem<M, Unencoded>, error::Unspecified> {
592    let num_limbs = m.num_limbs.into();
593    if bytes.len() != m.bytes_len() {
594        return Err(error::Unspecified);
595    }
596    let mut r = elem::Elem::zero();
597    parse_big_endian_in_range_and_pad_consttime(
598        bytes,
599        allow_zero,
600        &m.limbs[..num_limbs],
601        &mut r.limbs[..num_limbs],
602    )?;
603    Ok(r)
604}
605
606#[cold]
607#[inline(never)]
608fn unwrap_impossible_len_mismatch_error<T>(LenMismatchError { .. }: LenMismatchError) -> T {
609    unreachable!()
610}
611
612#[cfg(test)]
613mod tests {
614    extern crate alloc;
615    use super::*;
616    use crate::testutil as test;
617    use alloc::{format, vec, vec::Vec};
618
619    const ZERO_SCALAR: Scalar = Scalar {
620        limbs: [0; elem::NumLimbs::MAX],
621        m: PhantomData,
622        encoding: PhantomData,
623    };
624
625    trait Convert<E: Encoding> {
626        fn convert(self, q: &Modulus<Q>) -> Elem<E>;
627    }
628
629    impl Convert<R> for Elem<R> {
630        fn convert(self, _q: &Modulus<Q>) -> Elem<R> {
631            self
632        }
633    }
634
635    impl Convert<Unencoded> for Elem<R> {
636        fn convert(self, q: &Modulus<Q>) -> Elem<Unencoded> {
637            q.elem_unencoded(&self)
638        }
639    }
640
641    fn q_minus_n_plus_n_equals_0_test(ops: &PublicScalarOps) {
642        let cops = ops.scalar_ops.common;
643        let q = &cops.elem_modulus(cpu::features());
644        let mut x = Elem::from(&ops.q_minus_n);
645        q.add_assign(&mut x, &Elem::from(&cops.n));
646        assert!(q.is_zero(&x));
647    }
648
649    #[test]
650    fn p256_q_minus_n_plus_n_equals_0_test() {
651        q_minus_n_plus_n_equals_0_test(&p256::PUBLIC_SCALAR_OPS);
652    }
653
654    #[test]
655    fn p384_q_minus_n_plus_n_equals_0_test() {
656        q_minus_n_plus_n_equals_0_test(&p384::PUBLIC_SCALAR_OPS);
657    }
658
659    #[test]
660    fn p256_elem_add_test() {
661        elem_add_test(
662            &p256::PUBLIC_SCALAR_OPS,
663            test_vector_file!("ops/p256_elem_sum_tests.txt"),
664        );
665    }
666
667    #[test]
668    fn p384_elem_add_test() {
669        elem_add_test(
670            &p384::PUBLIC_SCALAR_OPS,
671            test_vector_file!("ops/p384_elem_sum_tests.txt"),
672        );
673    }
674
675    fn elem_add_test(ops: &PublicScalarOps, test_file: test::File) {
676        let cops = ops.public_key_ops.common;
677        let q = &cops.elem_modulus(cpu::features());
678        test::run(test_file, |section, test_case| {
679            assert_eq!(section, "");
680
681            let a = consume_elem(q, test_case, "a");
682            let b = consume_elem(q, test_case, "b");
683            let expected_sum = consume_elem(q, test_case, "r");
684
685            let mut actual_sum = a;
686            q.add_assign(&mut actual_sum, &b);
687            assert_limbs_are_equal(cops, &actual_sum.limbs, &expected_sum.limbs);
688
689            let mut actual_sum = b;
690            q.add_assign(&mut actual_sum, &a);
691            assert_limbs_are_equal(cops, &actual_sum.limbs, &expected_sum.limbs);
692
693            Ok(())
694        })
695    }
696
697    // XXX: There's no `p256_sub` in *ring*; it's logic is inlined into
698    // the point arithmetic functions. Thus, we can't test it.
699
700    #[test]
701    fn p384_elem_sub_test() {
702        prefixed_extern! {
703            fn p384_elem_sub(r: *mut Limb, a: *const Limb, b: *const Limb);
704        }
705        elem_sub_test(
706            &p384::COMMON_OPS,
707            p384_elem_sub,
708            test_vector_file!("ops/p384_elem_sum_tests.txt"),
709        );
710    }
711
712    fn elem_sub_test(
713        ops: &'static CommonOps,
714        elem_sub: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
715        test_file: test::File,
716    ) {
717        let q = &ops.elem_modulus(cpu::features());
718        test::run(test_file, |section, test_case| {
719            assert_eq!(section, "");
720
721            let a = consume_elem(q, test_case, "a");
722            let b = consume_elem(q, test_case, "b");
723            let r = consume_elem(q, test_case, "r");
724
725            let mut actual_difference = Elem::<R>::zero();
726            unsafe {
727                elem_sub(
728                    actual_difference.limbs.as_mut_ptr(),
729                    r.limbs.as_ptr(),
730                    b.limbs.as_ptr(),
731                );
732            }
733            assert_limbs_are_equal(ops, &actual_difference.limbs, &a.limbs);
734
735            let mut actual_difference = Elem::<R>::zero();
736            unsafe {
737                elem_sub(
738                    actual_difference.limbs.as_mut_ptr(),
739                    r.limbs.as_ptr(),
740                    a.limbs.as_ptr(),
741                );
742            }
743            assert_limbs_are_equal(ops, &actual_difference.limbs, &b.limbs);
744
745            Ok(())
746        })
747    }
748
749    // XXX: There's no `p256_div_by_2` in *ring*; it's logic is inlined
750    // into the point arithmetic functions. Thus, we can't test it.
751
752    #[test]
753    fn p384_elem_div_by_2_test() {
754        prefixed_extern! {
755            fn p384_elem_div_by_2(r: *mut Limb, a: *const Limb);
756        }
757        elem_div_by_2_test(
758            &p384::COMMON_OPS,
759            p384_elem_div_by_2,
760            test_vector_file!("ops/p384_elem_div_by_2_tests.txt"),
761        );
762    }
763
764    fn elem_div_by_2_test(
765        ops: &'static CommonOps,
766        elem_div_by_2: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
767        test_file: test::File,
768    ) {
769        let q = &ops.elem_modulus(cpu::features());
770        test::run(test_file, |section, test_case| {
771            assert_eq!(section, "");
772
773            let a = consume_elem(q, test_case, "a");
774            let r = consume_elem(q, test_case, "r");
775
776            let mut actual_result = Elem::<R>::zero();
777            unsafe {
778                elem_div_by_2(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr());
779            }
780            assert_limbs_are_equal(ops, &actual_result.limbs, &r.limbs);
781
782            Ok(())
783        })
784    }
785
786    // There is no `ecp_nistz256_neg` on other targets.
787    #[cfg(target_arch = "x86_64")]
788    #[test]
789    fn p256_elem_neg_test() {
790        prefixed_extern! {
791            fn ecp_nistz256_neg(r: *mut Limb, a: *const Limb);
792        }
793        elem_neg_test(
794            &p256::COMMON_OPS,
795            ecp_nistz256_neg,
796            test_vector_file!("ops/p256_elem_neg_tests.txt"),
797        );
798    }
799
800    #[test]
801    fn p384_elem_neg_test() {
802        prefixed_extern! {
803            fn p384_elem_neg(r: *mut Limb, a: *const Limb);
804        }
805        elem_neg_test(
806            &p384::COMMON_OPS,
807            p384_elem_neg,
808            test_vector_file!("ops/p384_elem_neg_tests.txt"),
809        );
810    }
811
812    fn elem_neg_test(
813        ops: &'static CommonOps,
814        elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
815        test_file: test::File,
816    ) {
817        let q = &ops.elem_modulus(cpu::features());
818        test::run(test_file, |section, test_case| {
819            assert_eq!(section, "");
820
821            let a = consume_elem(q, test_case, "a");
822            let b = consume_elem(q, test_case, "b");
823
824            // Verify -a == b.
825            {
826                let mut actual_result = Elem::<R>::zero();
827                unsafe {
828                    elem_neg(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr());
829                }
830                assert_limbs_are_equal(ops, &actual_result.limbs, &b.limbs);
831            }
832
833            // Verify -b == a.
834            {
835                let mut actual_result = Elem::<R>::zero();
836                unsafe {
837                    elem_neg(actual_result.limbs.as_mut_ptr(), b.limbs.as_ptr());
838                }
839                assert_limbs_are_equal(ops, &actual_result.limbs, &a.limbs);
840            }
841
842            Ok(())
843        })
844    }
845
846    #[test]
847    fn p256_elem_mul_test() {
848        elem_mul_test(
849            &p256::COMMON_OPS,
850            test_vector_file!("ops/p256_elem_mul_tests.txt"),
851        );
852    }
853
854    #[test]
855    fn p384_elem_mul_test() {
856        elem_mul_test(
857            &p384::COMMON_OPS,
858            test_vector_file!("ops/p384_elem_mul_tests.txt"),
859        );
860    }
861
862    fn elem_mul_test(ops: &'static CommonOps, test_file: test::File) {
863        let q = &ops.elem_modulus(cpu::features());
864        test::run(test_file, |section, test_case| {
865            assert_eq!(section, "");
866
867            let mut a = consume_elem(q, test_case, "a");
868            let b = consume_elem(q, test_case, "b");
869            let r = consume_elem(q, test_case, "r");
870            q.elem_mul(&mut a, &b);
871            assert_limbs_are_equal(ops, &a.limbs, &r.limbs);
872
873            Ok(())
874        })
875    }
876
877    #[test]
878    fn p256_scalar_mul_test() {
879        scalar_mul_test(
880            &p256::SCALAR_OPS,
881            test_vector_file!("ops/p256_scalar_mul_tests.txt"),
882        );
883    }
884
885    #[test]
886    fn p384_scalar_mul_test() {
887        scalar_mul_test(
888            &p384::SCALAR_OPS,
889            test_vector_file!("ops/p384_scalar_mul_tests.txt"),
890        );
891    }
892
893    fn scalar_mul_test(ops: &ScalarOps, test_file: test::File) {
894        let cpu = cpu::features();
895        let cops = ops.common;
896        let n = &cops.scalar_modulus(cpu);
897        test::run(test_file, |section, test_case| {
898            assert_eq!(section, "");
899            let a = consume_scalar(n, test_case, "a");
900            let b = consume_scalar_mont(n, test_case, "b");
901            let expected_result = consume_scalar(n, test_case, "r");
902            let actual_result = ops.scalar_product(&a, &b, cpu);
903            assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
904
905            Ok(())
906        })
907    }
908
909    #[test]
910    fn p256_scalar_square_test() {
911        prefixed_extern! {
912            fn p256_scalar_sqr_rep_mont(r: *mut Limb, a: *const Limb, rep: LeakyWord);
913        }
914        scalar_square_test(
915            &p256::SCALAR_OPS,
916            p256_scalar_sqr_rep_mont,
917            test_vector_file!("ops/p256_scalar_square_tests.txt"),
918        );
919    }
920
921    // XXX: There's no `p384_scalar_square_test()` because there's no dedicated
922    // `p384_scalar_sqr_rep_mont()`.
923
924    fn scalar_square_test(
925        ops: &ScalarOps,
926        sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: LeakyWord),
927        test_file: test::File,
928    ) {
929        let cpu = cpu::features();
930        let cops = ops.common;
931        let n = &cops.scalar_modulus(cpu);
932        test::run(test_file, |section, test_case| {
933            assert_eq!(section, "");
934            let cpu = cpu::features();
935            let a = consume_scalar(n, test_case, "a");
936            let expected_result = consume_scalar(n, test_case, "r");
937
938            {
939                let mut actual_result: Scalar<R> = Scalar {
940                    limbs: [0; elem::NumLimbs::MAX],
941                    m: PhantomData,
942                    encoding: PhantomData,
943                };
944                unsafe {
945                    sqr_rep(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr(), 1);
946                }
947                assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
948            }
949
950            {
951                let actual_result = ops.scalar_product(&a, &a, cpu);
952                assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
953            }
954
955            Ok(())
956        })
957    }
958
959    #[test]
960    #[should_panic(expected = "!self.scalar_ops.common.is_zero(a)")]
961    fn p256_scalar_inv_to_mont_zero_panic_test() {
962        let _ = p256::PRIVATE_SCALAR_OPS.scalar_inv_to_mont(&ZERO_SCALAR, cpu::features());
963    }
964
965    #[test]
966    #[should_panic(expected = "!self.scalar_ops.common.is_zero(a)")]
967    fn p384_scalar_inv_to_mont_zero_panic_test() {
968        let _ = p384::PRIVATE_SCALAR_OPS.scalar_inv_to_mont(&ZERO_SCALAR, cpu::features());
969    }
970
971    #[test]
972    fn p256_point_sum_test() {
973        point_sum_test(
974            &p256::PRIVATE_KEY_OPS,
975            test_vector_file!("ops/p256_point_sum_tests.txt"),
976        );
977    }
978
979    #[test]
980    fn p384_point_sum_test() {
981        point_sum_test(
982            &p384::PRIVATE_KEY_OPS,
983            test_vector_file!("ops/p384_point_sum_tests.txt"),
984        );
985    }
986
987    fn point_sum_test(ops: &PrivateKeyOps, test_file: test::File) {
988        let cpu = cpu::features();
989
990        test::run(test_file, |section, test_case| {
991            assert_eq!(section, "");
992
993            let a = consume_jacobian_point(ops, test_case, "a");
994            let b = consume_jacobian_point(ops, test_case, "b");
995            let r_expected: TestPoint<R> = consume_point(ops, test_case, "r");
996
997            let r_actual = ops.point_sum(&a, &b, cpu);
998            assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
999
1000            Ok(())
1001        });
1002    }
1003
1004    #[test]
1005    fn p256_point_sum_mixed_test() {
1006        prefixed_extern! {
1007            fn p256_point_add_affine(
1008                r: *mut Limb,   // [p256::COMMON_OPS.num_limbs*3]
1009                a: *const Limb, // [p256::COMMON_OPS.num_limbs*3]
1010                b: *const Limb, // [p256::COMMON_OPS.num_limbs*2]
1011            );
1012        }
1013        point_sum_mixed_test(
1014            &p256::PRIVATE_KEY_OPS,
1015            p256_point_add_affine,
1016            test_vector_file!("ops/p256_point_sum_mixed_tests.txt"),
1017        );
1018    }
1019
1020    // XXX: There is no `nistz384_point_add_affine()`.
1021
1022    fn point_sum_mixed_test(
1023        ops: &PrivateKeyOps,
1024        point_add_affine: unsafe extern "C" fn(
1025            r: *mut Limb,   // [ops.num_limbs*3]
1026            a: *const Limb, // [ops.num_limbs*3]
1027            b: *const Limb, // [ops.num_limbs*2]
1028        ),
1029        test_file: test::File,
1030    ) {
1031        test::run(test_file, |section, test_case| {
1032            assert_eq!(section, "");
1033
1034            let a = consume_jacobian_point(ops, test_case, "a");
1035            let b = consume_affine_point(ops, test_case, "b");
1036            let r_expected: TestPoint<R> = consume_point(ops, test_case, "r");
1037
1038            let mut r_actual = Point::new_at_infinity();
1039            unsafe {
1040                point_add_affine(r_actual.xyz.as_mut_ptr(), a.xyz.as_ptr(), b.xy.as_ptr());
1041            }
1042
1043            assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
1044
1045            Ok(())
1046        });
1047    }
1048
1049    #[test]
1050    fn p256_point_double_test() {
1051        prefixed_extern! {
1052            fn p256_point_double(
1053                r: *mut Limb,   // [p256::COMMON_OPS.num_limbs*3]
1054                a: *const Limb, // [p256::COMMON_OPS.num_limbs*3]
1055            );
1056        }
1057        point_double_test(
1058            &p256::PRIVATE_KEY_OPS,
1059            p256_point_double,
1060            test_vector_file!("ops/p256_point_double_tests.txt"),
1061        );
1062    }
1063
1064    #[test]
1065    fn p384_point_double_test() {
1066        prefixed_extern! {
1067            fn p384_point_double(
1068                r: *mut Limb,   // [p384::COMMON_OPS.num_limbs*3]
1069                a: *const Limb, // [p384::COMMON_OPS.num_limbs*3]
1070            );
1071        }
1072        point_double_test(
1073            &p384::PRIVATE_KEY_OPS,
1074            p384_point_double,
1075            test_vector_file!("ops/p384_point_double_tests.txt"),
1076        );
1077    }
1078
1079    fn point_double_test(
1080        ops: &PrivateKeyOps,
1081        point_double: unsafe extern "C" fn(
1082            r: *mut Limb,   // [ops.num_limbs*3]
1083            a: *const Limb, // [ops.num_limbs*3]
1084        ),
1085        test_file: test::File,
1086    ) {
1087        test::run(test_file, |section, test_case| {
1088            assert_eq!(section, "");
1089
1090            let a = consume_jacobian_point(ops, test_case, "a");
1091            let r_expected: TestPoint<R> = consume_point(ops, test_case, "r");
1092
1093            let mut r_actual = Point::new_at_infinity();
1094            unsafe {
1095                point_double(r_actual.xyz.as_mut_ptr(), a.xyz.as_ptr());
1096            }
1097
1098            assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
1099
1100            Ok(())
1101        });
1102    }
1103
1104    /// TODO: We should be testing `point_mul` with points other than the generator.
1105    #[test]
1106    fn p256_point_mul_test() {
1107        let generator = (
1108            Elem::from(&p256::GENERATOR.0),
1109            Elem::from(&p256::GENERATOR.1),
1110        );
1111        point_mul_base_tests(
1112            &p256::PRIVATE_KEY_OPS,
1113            |s, cpu| p256::PRIVATE_KEY_OPS.point_mul(s, &generator, cpu),
1114            test_vector_file!("ops/p256_point_mul_base_tests.txt"),
1115        );
1116    }
1117
1118    /// TODO: We should be testing `point_mul` with points other than the generator.
1119    #[test]
1120    fn p384_point_mul_test() {
1121        let generator = (
1122            Elem::from(&p384::GENERATOR.0),
1123            Elem::from(&p384::GENERATOR.1),
1124        );
1125
1126        point_mul_base_tests(
1127            &p384::PRIVATE_KEY_OPS,
1128            |s, cpu| p384::PRIVATE_KEY_OPS.point_mul(s, &generator, cpu),
1129            test_vector_file!("ops/p384_point_mul_base_tests.txt"),
1130        );
1131    }
1132
1133    #[test]
1134    fn p256_point_mul_serialized_test() {
1135        point_mul_serialized_test(
1136            &p256::PRIVATE_KEY_OPS,
1137            &p256::PUBLIC_KEY_OPS,
1138            test_vector_file!("ops/p256_point_mul_serialized_tests.txt"),
1139        );
1140    }
1141
1142    fn point_mul_serialized_test(
1143        priv_ops: &PrivateKeyOps,
1144        pub_ops: &PublicKeyOps,
1145        test_file: test::File,
1146    ) {
1147        let cpu = cpu::features();
1148        let cops = pub_ops.common;
1149        let q = &cops.elem_modulus(cpu);
1150        let n = &cops.scalar_modulus(cpu);
1151        test::run(test_file, |section, test_case| {
1152            assert_eq!(section, "");
1153            let p_scalar = consume_scalar(n, test_case, "p_scalar");
1154
1155            let p = test_case.consume_bytes("p");
1156            let p = super::super::public_key::parse_uncompressed_point(
1157                pub_ops,
1158                q,
1159                untrusted::Input::from(&p),
1160            )
1161            .expect("valid point");
1162
1163            let expected_result = test_case.consume_bytes("r");
1164
1165            let product = priv_ops.point_mul(&p_scalar, &p, cpu::features());
1166
1167            let mut actual_result = vec![4u8; 1 + (2 * cops.len())];
1168            {
1169                let (x, y) = actual_result[1..].split_at_mut(cops.len());
1170                super::super::private_key::big_endian_affine_from_jacobian(
1171                    priv_ops,
1172                    q,
1173                    x,
1174                    Some(y),
1175                    &product,
1176                )
1177                .expect("successful encoding");
1178            }
1179
1180            assert_eq!(expected_result, actual_result);
1181
1182            Ok(())
1183        })
1184    }
1185
1186    #[test]
1187    fn p256_point_mul_base_test() {
1188        point_mul_base_tests(
1189            &p256::PRIVATE_KEY_OPS,
1190            |s, cpu| p256::PRIVATE_KEY_OPS.point_mul_base(s, cpu),
1191            test_vector_file!("ops/p256_point_mul_base_tests.txt"),
1192        );
1193    }
1194
1195    #[test]
1196    fn p384_point_mul_base_test() {
1197        point_mul_base_tests(
1198            &p384::PRIVATE_KEY_OPS,
1199            |s, cpu| p384::PRIVATE_KEY_OPS.point_mul_base(s, cpu),
1200            test_vector_file!("ops/p384_point_mul_base_tests.txt"),
1201        );
1202    }
1203
1204    pub(super) fn point_mul_base_tests(
1205        ops: &PrivateKeyOps,
1206        f: impl Fn(&Scalar, cpu::Features) -> Point,
1207        test_file: test::File,
1208    ) {
1209        let cpu = cpu::features();
1210        let n = &ops.common.scalar_modulus(cpu);
1211        test::run(test_file, |section, test_case| {
1212            assert_eq!(section, "");
1213            let g_scalar = consume_scalar(n, test_case, "g_scalar");
1214            let expected_result: TestPoint<Unencoded> = consume_point(ops, test_case, "r");
1215            let actual_result = f(&g_scalar, cpu);
1216            assert_point_actual_equals_expected(ops, &actual_result, &expected_result);
1217            Ok(())
1218        })
1219    }
1220
1221    fn assert_point_actual_equals_expected<E: Encoding>(
1222        ops: &PrivateKeyOps,
1223        actual_point: &Point,
1224        expected_point: &TestPoint<E>,
1225    ) where
1226        Elem<R>: Convert<E>,
1227    {
1228        let cpu = cpu::features();
1229
1230        let cops = ops.common;
1231        let q = &cops.elem_modulus(cpu);
1232        let actual_x = &q.point_x(actual_point);
1233        let actual_y = &q.point_y(actual_point);
1234        let actual_z = &q.point_z(actual_point);
1235        match expected_point {
1236            TestPoint::Infinity => {
1237                let zero = Elem::zero();
1238                assert_elems_are_equal(q, actual_z, &zero);
1239            }
1240            TestPoint::Affine(expected_x, expected_y) => {
1241                let zz_inv = ops.elem_inverse_squared(q, actual_z);
1242                let x_aff = q.elem_product(actual_x, &zz_inv);
1243                let y_aff = {
1244                    let zzzz_inv = q.elem_squared(&zz_inv);
1245                    let zzz_inv = q.elem_product(actual_z, &zzzz_inv);
1246                    q.elem_product(actual_y, &zzz_inv)
1247                };
1248
1249                let x_aff = x_aff.convert(q);
1250                let y_aff = y_aff.convert(q);
1251
1252                assert_elems_are_equal(q, &x_aff, expected_x);
1253                assert_elems_are_equal(q, &y_aff, expected_y);
1254            }
1255        }
1256    }
1257
1258    fn consume_jacobian_point(
1259        ops: &PrivateKeyOps,
1260        test_case: &mut test::TestCase,
1261        name: &str,
1262    ) -> Point {
1263        let q = &ops.common.elem_modulus(cpu::features());
1264        let input = test_case.consume_string(name);
1265        let elems = input.split(", ").collect::<Vec<&str>>();
1266        assert_eq!(elems.len(), 3);
1267        let mut p = Point::new_at_infinity();
1268        consume_point_elem(q, &mut p.xyz, &elems, 0);
1269        consume_point_elem(q, &mut p.xyz, &elems, 1);
1270        consume_point_elem(q, &mut p.xyz, &elems, 2);
1271        p
1272    }
1273
1274    struct AffinePoint {
1275        xy: [Limb; 2 * elem::NumLimbs::MAX],
1276    }
1277
1278    fn consume_affine_point(
1279        ops: &PrivateKeyOps,
1280        test_case: &mut test::TestCase,
1281        name: &str,
1282    ) -> AffinePoint {
1283        let q = &ops.common.elem_modulus(cpu::features());
1284        let input = test_case.consume_string(name);
1285        let elems = input.split(", ").collect::<Vec<&str>>();
1286        assert_eq!(elems.len(), 2);
1287        let mut p = AffinePoint {
1288            xy: [0; 2 * elem::NumLimbs::MAX],
1289        };
1290        consume_point_elem(q, &mut p.xy, &elems, 0);
1291        consume_point_elem(q, &mut p.xy, &elems, 1);
1292        p
1293    }
1294
1295    fn consume_point_elem(q: &Modulus<Q>, limbs_out: &mut [Limb], elems: &[&str], i: usize) {
1296        let num_limbs = q.num_limbs.into();
1297        let bytes = test::from_hex(elems[i]).unwrap();
1298        let bytes = untrusted::Input::from(&bytes);
1299        let r: Elem<Unencoded> = elem_parse_big_endian_fixed_consttime(q, bytes).unwrap();
1300        // XXX: “Transmute” this to `Elem<R>` limbs.
1301        limbs_out[(i * num_limbs)..((i + 1) * num_limbs)].copy_from_slice(&r.limbs[..num_limbs]);
1302    }
1303
1304    enum TestPoint<E: Encoding> {
1305        Infinity,
1306        Affine(Elem<E>, Elem<E>),
1307    }
1308
1309    fn consume_point<E: Encoding>(
1310        ops: &PrivateKeyOps,
1311        test_case: &mut test::TestCase,
1312        name: &str,
1313    ) -> TestPoint<E> {
1314        let q = &ops.common.elem_modulus(cpu::features());
1315        fn consume_point_elem<E: Encoding>(q: &Modulus<Q>, elems: &[&str], i: usize) -> Elem<E> {
1316            let bytes = test::from_hex(elems[i]).unwrap();
1317            let bytes = untrusted::Input::from(&bytes);
1318            let unencoded: Elem<Unencoded> =
1319                elem_parse_big_endian_fixed_consttime(q, bytes).unwrap();
1320            // XXX: “Transmute” this to `Elem<R>` limbs.
1321            Elem {
1322                limbs: unencoded.limbs,
1323                m: PhantomData,
1324                encoding: PhantomData,
1325            }
1326        }
1327
1328        let input = test_case.consume_string(name);
1329        if input == "inf" {
1330            return TestPoint::Infinity;
1331        }
1332        let elems = input.split(", ").collect::<Vec<&str>>();
1333        assert_eq!(elems.len(), 2);
1334        let x = consume_point_elem(q, &elems, 0);
1335        let y = consume_point_elem(q, &elems, 1);
1336        TestPoint::Affine(x, y)
1337    }
1338
1339    fn assert_elems_are_equal<E: Encoding>(q: &Modulus<Q>, a: &Elem<E>, b: &Elem<E>) {
1340        assert_limbs_are_equal(q.cops, &a.limbs, &b.limbs)
1341    }
1342
1343    fn assert_limbs_are_equal(
1344        ops: &CommonOps,
1345        actual: &[Limb; elem::NumLimbs::MAX],
1346        expected: &[Limb; elem::NumLimbs::MAX],
1347    ) {
1348        let num_limbs = ops.num_limbs.into();
1349        if actual[..num_limbs] != expected[..num_limbs] {
1350            let mut actual_s = alloc::string::String::new();
1351            let mut expected_s = alloc::string::String::new();
1352            for j in 0..num_limbs {
1353                let width = LIMB_BITS / 4;
1354                let formatted = format!("{:0width$x}", actual[num_limbs - j - 1]);
1355                actual_s.push_str(&formatted);
1356                let formatted = format!("{:0width$x}", expected[num_limbs - j - 1]);
1357                expected_s.push_str(&formatted);
1358            }
1359            panic!(
1360                "Actual != Expected,\nActual = {}, Expected = {}",
1361                actual_s, expected_s
1362            );
1363        }
1364    }
1365
1366    fn consume_elem(q: &Modulus<Q>, test_case: &mut test::TestCase, name: &str) -> Elem<R> {
1367        let unpadded_bytes = test_case.consume_bytes(name);
1368        let mut bytes = vec![0; q.bytes_len() - unpadded_bytes.len()];
1369        bytes.extend(&unpadded_bytes);
1370
1371        let bytes = untrusted::Input::from(&bytes);
1372        let r: Elem<Unencoded> = elem_parse_big_endian_fixed_consttime(q, bytes).unwrap();
1373        // XXX: “Transmute” this to an `Elem<R>`.
1374        Elem {
1375            limbs: r.limbs,
1376            m: PhantomData,
1377            encoding: PhantomData,
1378        }
1379    }
1380
1381    fn consume_scalar(n: &Modulus<N>, test_case: &mut test::TestCase, name: &str) -> Scalar {
1382        let bytes = test_case.consume_bytes(name);
1383        let bytes = untrusted::Input::from(&bytes);
1384        scalar_parse_big_endian_variable(n, AllowZero::Yes, bytes).unwrap()
1385    }
1386
1387    fn consume_scalar_mont(
1388        n: &Modulus<N>,
1389        test_case: &mut test::TestCase,
1390        name: &str,
1391    ) -> Scalar<R> {
1392        let bytes = test_case.consume_bytes(name);
1393        let bytes = untrusted::Input::from(&bytes);
1394        let s = scalar_parse_big_endian_variable(n, AllowZero::Yes, bytes).unwrap();
1395        // “Transmute” it to a `Scalar<R>`.
1396        Scalar {
1397            limbs: s.limbs,
1398            m: PhantomData,
1399            encoding: PhantomData,
1400        }
1401    }
1402}
1403
1404mod elem;
1405pub mod p256;
1406pub mod p384;