Skip to main content

p256/arithmetic/
tables.rs

1//! Precomputed tables (optional).
2
3use super::NistP256;
4use crate::ProjectivePoint;
5use primeorder::PrimeCurveWithBasepointTable;
6
7/// Window size for the basepoint table (1 + 32-byte modulus)
8pub(super) const WINDOW_SIZE: usize = 33;
9
10/// Basepoint table for multiples of NIST P-256's generator.
11pub(super) type BasepointTable = primeorder::BasepointTable<ProjectivePoint, WINDOW_SIZE>;
12
13/// Lazily computed basepoint table.
14pub(super) static BASEPOINT_TABLE: BasepointTable = BasepointTable::new();
15
16impl PrimeCurveWithBasepointTable<WINDOW_SIZE> for NistP256 {
17    const BASEPOINT_TABLE: &'static BasepointTable = &BASEPOINT_TABLE;
18}
19
20/// Workaround for rust-lang/rust#140653 to support MSRV 1.85: we can't use the generic
21/// implementation in `primeorder::mul_backend::PrecomputedTables` until MSRV 1.90 due to restrictions
22/// on referencing a type with interior mutability from a `const`.
23// TODO(tarcieri): remove this and switch to `primeorder::mul_backend::PrecomputedTables` when MSRV 1.90
24pub(crate) mod backend {
25    use super::BASEPOINT_TABLE;
26    use crate::{NistP256, ProjectivePoint, Scalar};
27    use primeorder::MulBackend;
28
29    /// Backend based on precomputed tables.
30    #[derive(Clone, Copy, Debug)]
31    pub struct PrecomputedTables;
32
33    impl MulBackend<NistP256> for PrecomputedTables {
34        #[inline]
35        fn mul_by_generator(k: &Scalar) -> ProjectivePoint {
36            BASEPOINT_TABLE.mul(k)
37        }
38
39        #[inline]
40        fn mul_by_generator_vartime(k: &Scalar) -> ProjectivePoint {
41            BASEPOINT_TABLE.mul_vartime(k)
42        }
43    }
44}
45
46/// These are the main tests for `primeorder::BasepointTable` as we need a concrete curve to test
47/// against.
48#[cfg(test)]
49mod tests {
50    use super::BASEPOINT_TABLE;
51    use crate::{ProjectivePoint, Scalar};
52    use elliptic_curve::{
53        array::{Array, sizes::U32},
54        ops::Reduce,
55    };
56    use proptest::prelude::*;
57
58    prop_compose! {
59        fn scalar()(bytes in any::<[u8; 32]>()) -> Scalar {
60            Scalar::reduce(&Array::<u8, U32>::from(bytes))
61        }
62    }
63
64    proptest! {
65        #[test]
66        fn basepoint_table_mul(x in scalar()) {
67            let expected = ProjectivePoint::GENERATOR * x;
68            let actual = BASEPOINT_TABLE.mul(&x);
69            prop_assert_eq!(expected, actual);
70        }
71    }
72
73    proptest! {
74        #[test]
75        fn basepoint_table_mul_vartime(x in scalar()) {
76            let expected = ProjectivePoint::GENERATOR * x;
77            let actual = BASEPOINT_TABLE.mul_vartime(&x);
78            prop_assert_eq!(expected, actual);
79        }
80    }
81}