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