halo2curves_axiom/secp256r1/
fp.rs

1use crate::arithmetic::{adc, bigint_geq, mac, macx, sbb};
2use crate::extend_field_legendre;
3use crate::ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup};
4use crate::{
5    field_arithmetic, field_bits, field_common, field_specific, impl_add_binop_specify_output,
6    impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative,
7    impl_binops_multiplicative_mixed, impl_from_u64, impl_sub_binop_specify_output, impl_sum_prod,
8};
9use core::convert::TryInto;
10use core::fmt;
11use core::ops::{Add, Mul, Neg, Sub};
12use rand::RngCore;
13use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
14
15/// This represents an element of $\mathbb{F}_p$ where
16///
17/// `p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
18///
19/// is the base field of the secp256r1 curve.
20// The internal representation of this type is four 64-bit unsigned
21// integers in little-endian order. `Fp` values are always in
22// Montgomery form; i.e., Fp(a) = aR mod p, with R = 2^256.
23#[derive(Clone, Copy, PartialEq, Eq, Hash)]
24pub struct Fp(pub(crate) [u64; 4]);
25
26#[cfg(feature = "derive_serde")]
27crate::serialize_deserialize_32_byte_primefield!(Fp);
28
29/// Constant representing the modulus
30/// p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
31const MODULUS: Fp = Fp([
32    0xffffffffffffffff,
33    0x00000000ffffffff,
34    0x0000000000000000,
35    0xffffffff00000001,
36]);
37
38/// Constant representing the multiplicative generator of the modulus.
39/// It's derived with SageMath with: `GF(MODULUS).primitive_element()`.
40const MULTIPLICATIVE_GENERATOR: Fp = Fp::from_raw([0x06, 0x00, 0x00, 0x00]);
41
42/// The modulus as u32 limbs.
43#[cfg(not(target_pointer_width = "64"))]
44const MODULUS_LIMBS_32: [u32; 8] = [
45    0xffff_ffff,
46    0xffff_ffff,
47    0xffff_ffff,
48    0x0000_0000,
49    0x0000_0000,
50    0x0000_0000,
51    0x0000_0001,
52    0xffff_ffff,
53];
54
55/// Constant representing the modolus as static str
56const MODULUS_STR: &str = "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff";
57
58/// INV = -(p^{-1} mod 2^64) mod 2^64
59const INV: u64 = 0x1;
60
61/// R = 2^256 mod p
62/// 0xfffffffeffffffffffffffffffffffff000000000000000000000001
63const R: Fp = Fp([
64    0x0000000000000001,
65    0xffffffff00000000,
66    0xffffffffffffffff,
67    0xfffffffe,
68]);
69
70/// R^2 = 2^512 mod p
71/// 0x4fffffffdfffffffffffffffefffffffbffffffff0000000000000003
72const R2: Fp = Fp([
73    0x0000000000000003,
74    0xfffffffbffffffff,
75    0xfffffffffffffffe,
76    0x4fffffffd,
77]);
78
79/// R^3 = 2^768 mod p
80/// 0x180000000100000005fffffffcffffffedfffffff7fffffffd0000000a
81const R3: Fp = Fp([
82    0xfffffffd0000000a,
83    0xffffffedfffffff7,
84    0x00000005fffffffc,
85    0x1800000001,
86]);
87
88/// 1 / 2 mod p
89/// 0x7fffffff80000000800000000000000000000000800000000000000000000000
90const TWO_INV: Fp = Fp::from_raw([
91    0x0000000000000000,
92    0x0000000080000000,
93    0x8000000000000000,
94    0x7fffffff80000000,
95]);
96
97const ZETA: Fp = Fp::from_raw([
98    0xd964598eb819acce,
99    0x2e68c59bdef3e53f,
100    0x62388a8e0ef62331,
101    0x4d6ea8928adb86cf,
102]);
103
104/// Generator of the t-order multiplicative subgroup.
105/// Computed by exponentiating Self::MULTIPLICATIVE_GENERATOR by 2^s, where s is Self::S.
106/// `0x0000000000000000000000000000000000000000000000000000000000000024`.
107const DELTA: Fp = Fp::from_raw([0x24, 0, 0, 0]);
108
109/// Implementations of this trait MUST ensure that this is the generator used to derive Self::ROOT_OF_UNITY.
110/// Derived from:
111/// ```ignore
112/// Zp(Zp(mul_generator)^t) where t = (modulus - 1 )/ 2
113/// 115792089237316195423570985008687907853269984665640564039457584007908834671662
114/// ```
115/// `0xffffffff00000001000000000000000000000000fffffffffffffffffffffffe`
116const ROOT_OF_UNITY: Fp = Fp::from_raw([
117    0xfffffffffffffffe,
118    0x00000000ffffffff,
119    0x0000000000000000,
120    0xffffffff00000001,
121]);
122
123/// Inverse of [`ROOT_OF_UNITY`].
124/// `0xffffffff00000001000000000000000000000000fffffffffffffffffffffffe`
125const ROOT_OF_UNITY_INV: Fp = Fp::from_raw([
126    0xfffffffffffffffe,
127    0x00000000ffffffff,
128    0x0000000000000000,
129    0xffffffff00000001,
130]);
131
132impl_binops_additive!(Fp, Fp);
133impl_binops_multiplicative!(Fp, Fp);
134field_common!(
135    Fp,
136    MODULUS,
137    INV,
138    MODULUS_STR,
139    TWO_INV,
140    ROOT_OF_UNITY_INV,
141    DELTA,
142    ZETA,
143    R,
144    R2,
145    R3
146);
147impl_from_u64!(Fp, R2);
148field_arithmetic!(Fp, MODULUS, INV, dense);
149impl_sum_prod!(Fp);
150
151#[cfg(target_pointer_width = "64")]
152field_bits!(Fp, MODULUS);
153#[cfg(not(target_pointer_width = "64"))]
154field_bits!(Fp, MODULUS, MODULUS_LIMBS_32);
155
156impl Fp {
157    pub const fn size() -> usize {
158        32
159    }
160}
161
162impl ff::Field for Fp {
163    const ZERO: Self = Self::zero();
164    const ONE: Self = Self::one();
165
166    fn random(mut rng: impl RngCore) -> Self {
167        Self::from_u512([
168            rng.next_u64(),
169            rng.next_u64(),
170            rng.next_u64(),
171            rng.next_u64(),
172            rng.next_u64(),
173            rng.next_u64(),
174            rng.next_u64(),
175            rng.next_u64(),
176        ])
177    }
178
179    fn double(&self) -> Self {
180        self.double()
181    }
182
183    #[inline(always)]
184    fn square(&self) -> Self {
185        self.square()
186    }
187
188    /// Computes the square root of this element, if it exists.
189    fn sqrt(&self) -> CtOption<Self> {
190        let tmp = self.pow([
191            0x0000000000000000,
192            0x0000000040000000,
193            0x4000000000000000,
194            0x3fffffffc0000000,
195        ]);
196
197        CtOption::new(tmp, tmp.square().ct_eq(self))
198    }
199
200    /// Returns the multiplicative inverse of the
201    /// element. If it is zero, the method fails.
202    fn invert(&self) -> CtOption<Self> {
203        self.invert()
204    }
205
206    fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
207        let mut res = Self::one();
208        let mut found_one = false;
209        for e in exp.as_ref().iter().rev() {
210            for i in (0..64).rev() {
211                if found_one {
212                    res = res.square();
213                }
214
215                if ((*e >> i) & 1) == 1 {
216                    found_one = true;
217                    res *= self;
218                }
219            }
220        }
221        res
222    }
223
224    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
225        ff::helpers::sqrt_ratio_generic(num, div)
226    }
227}
228
229impl ff::PrimeField for Fp {
230    type Repr = [u8; 32];
231
232    const MODULUS: &'static str = MODULUS_STR;
233    const MULTIPLICATIVE_GENERATOR: Self = MULTIPLICATIVE_GENERATOR;
234    const TWO_INV: Self = TWO_INV;
235    const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
236    const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV;
237    const DELTA: Self = DELTA;
238    const NUM_BITS: u32 = 256;
239    const CAPACITY: u32 = 255;
240    const S: u32 = 1;
241
242    fn from_repr(repr: Self::Repr) -> CtOption<Self> {
243        let mut tmp = Fp([0, 0, 0, 0]);
244
245        tmp.0[0] = u64::from_le_bytes(repr[0..8].try_into().unwrap());
246        tmp.0[1] = u64::from_le_bytes(repr[8..16].try_into().unwrap());
247        tmp.0[2] = u64::from_le_bytes(repr[16..24].try_into().unwrap());
248        tmp.0[3] = u64::from_le_bytes(repr[24..32].try_into().unwrap());
249
250        // Try to subtract the modulus
251        let (_, borrow) = sbb(tmp.0[0], MODULUS.0[0], 0);
252        let (_, borrow) = sbb(tmp.0[1], MODULUS.0[1], borrow);
253        let (_, borrow) = sbb(tmp.0[2], MODULUS.0[2], borrow);
254        let (_, borrow) = sbb(tmp.0[3], MODULUS.0[3], borrow);
255
256        // If the element is smaller than MODULUS then the
257        // subtraction will underflow, producing a borrow value
258        // of 0xffff...ffff. Otherwise, it'll be zero.
259        let is_some = (borrow as u8) & 1;
260
261        // Convert to Montgomery form by computing
262        // (a.R^0 * R^2) / R = a.R
263        tmp *= &R2;
264
265        CtOption::new(tmp, Choice::from(is_some))
266    }
267
268    fn to_repr(&self) -> Self::Repr {
269        let tmp: [u64; 4] = (*self).into();
270        let mut res = [0; 32];
271        res[0..8].copy_from_slice(&tmp[0].to_le_bytes());
272        res[8..16].copy_from_slice(&tmp[1].to_le_bytes());
273        res[16..24].copy_from_slice(&tmp[2].to_le_bytes());
274        res[24..32].copy_from_slice(&tmp[3].to_le_bytes());
275
276        res
277    }
278
279    fn from_u128(v: u128) -> Self {
280        Self::from_raw([v as u64, (v >> 64) as u64, 0, 0])
281    }
282
283    fn is_odd(&self) -> Choice {
284        Choice::from(self.to_repr()[0] & 1)
285    }
286}
287
288impl FromUniformBytes<64> for Fp {
289    /// Converts a 512-bit little endian integer into
290    /// an `Fp` by reducing by the modulus.
291    fn from_uniform_bytes(bytes: &[u8; 64]) -> Self {
292        Self::from_u512([
293            u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
294            u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
295            u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
296            u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
297            u64::from_le_bytes(bytes[32..40].try_into().unwrap()),
298            u64::from_le_bytes(bytes[40..48].try_into().unwrap()),
299            u64::from_le_bytes(bytes[48..56].try_into().unwrap()),
300            u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
301        ])
302    }
303}
304
305impl WithSmallOrderMulGroup<3> for Fp {
306    const ZETA: Self = ZETA;
307}
308
309extend_field_legendre!(Fp);
310
311#[cfg(test)]
312mod test {
313    use super::*;
314    use ff::Field;
315    use rand_core::OsRng;
316
317    #[test]
318    fn test_sqrt() {
319        // NB: TWO_INV is standing in as a "random" field element
320        let v = (Fp::TWO_INV).square().sqrt().unwrap();
321        assert!(v == Fp::TWO_INV || (-v) == Fp::TWO_INV);
322
323        for _ in 0..10000 {
324            let a = Fp::random(OsRng);
325            let mut b = a;
326            b = b.square();
327
328            let b = b.sqrt().unwrap();
329            let mut negb = b;
330            negb = negb.neg();
331
332            assert!(a == b || a == negb);
333        }
334    }
335
336    #[test]
337    fn test_constants() {
338        assert_eq!(
339            Fp::MODULUS,
340            "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
341        );
342
343        assert_eq!(Fp::from(2) * Fp::TWO_INV, Fp::ONE);
344    }
345
346    #[test]
347    fn test_delta() {
348        assert_eq!(Fp::DELTA, MULTIPLICATIVE_GENERATOR.pow([1u64 << Fp::S]));
349    }
350
351    #[test]
352    fn test_root_of_unity() {
353        assert_eq!(Fp::ROOT_OF_UNITY.pow_vartime([1 << Fp::S]), Fp::one());
354    }
355
356    #[test]
357    fn test_inv_root_of_unity() {
358        assert_eq!(Fp::ROOT_OF_UNITY_INV, Fp::ROOT_OF_UNITY.invert().unwrap());
359    }
360
361    #[test]
362    fn test_field() {
363        crate::tests::field::random_field_tests::<Fp>("secp256r1 base".to_string());
364    }
365
366    #[test]
367    fn test_conversion() {
368        crate::tests::field::random_conversion_tests::<Fp>("secp256r1 base".to_string());
369    }
370
371    #[test]
372    #[cfg(feature = "bits")]
373    fn test_bits() {
374        crate::tests::field::random_bits_tests::<Fp>("secp256r1 base".to_string());
375    }
376
377    #[test]
378    fn test_serialization() {
379        crate::tests::field::random_serialization_test::<Fp>("secp256r1 base".to_string());
380        #[cfg(feature = "derive_serde")]
381        crate::tests::field::random_serde_test::<Fp>("secp256r1 base".to_string());
382    }
383
384    #[test]
385    fn test_quadratic_residue() {
386        crate::tests::field::random_quadratic_residue_test::<Fp>();
387    }
388}