1#![allow(
15    clippy::should_implement_trait,
16    clippy::suspicious_op_assign_impl,
17    clippy::unused_unit,
18    clippy::unnecessary_cast,
19    clippy::too_many_arguments,
20    clippy::identity_op
21)]
22
23#[cfg_attr(target_pointer_width = "32", path = "field/p384_32.rs")]
24#[cfg_attr(target_pointer_width = "64", path = "field/p384_64.rs")]
25mod field_impl;
26
27use self::field_impl::*;
28use crate::{FieldBytes, NistP384};
29use core::{
30    iter::{Product, Sum},
31    ops::{AddAssign, MulAssign, Neg, SubAssign},
32};
33use elliptic_curve::{
34    bigint::{self, Limb, U384},
35    ff::PrimeField,
36    subtle::{Choice, ConstantTimeEq, CtOption},
37};
38
39pub(crate) const MODULUS: U384 = U384::from_be_hex(FieldElement::MODULUS);
42
43#[derive(Clone, Copy, Debug)]
45pub struct FieldElement(pub(super) U384);
46
47primeorder::impl_mont_field_element!(
48    NistP384,
49    FieldElement,
50    FieldBytes,
51    U384,
52    MODULUS,
53    fiat_p384_montgomery_domain_field_element,
54    fiat_p384_from_montgomery,
55    fiat_p384_to_montgomery,
56    fiat_p384_add,
57    fiat_p384_sub,
58    fiat_p384_mul,
59    fiat_p384_opp,
60    fiat_p384_square
61);
62
63impl FieldElement {
64    pub fn invert(&self) -> CtOption<Self> {
66        CtOption::new(self.invert_unchecked(), !self.is_zero())
67    }
68
69    const fn invert_unchecked(&self) -> Self {
73        let words = impl_field_invert!(
74            self.to_canonical().as_words(),
75            Self::ONE.0.to_words(),
76            Limb::BITS,
77            bigint::nlimbs!(U384::BITS),
78            fiat_p384_mul,
79            fiat_p384_opp,
80            fiat_p384_divstep_precomp,
81            fiat_p384_divstep,
82            fiat_p384_msat,
83            fiat_p384_selectznz,
84        );
85
86        Self(U384::from_words(words))
87    }
88
89    pub fn sqrt(&self) -> CtOption<Self> {
92        let t1 = *self;
95        let t10 = t1.square();
96        let t11 = t1 * t10;
97        let t110 = t11.square();
98        let t111 = t1 * t110;
99        let t111000 = t111.sqn(3);
100        let t111111 = t111 * t111000;
101        let t1111110 = t111111.square();
102        let t1111111 = t1 * t1111110;
103        let x12 = t1111110.sqn(5) * t111111;
104        let x24 = x12.sqn(12) * x12;
105        let x31 = x24.sqn(7) * t1111111;
106        let x32 = x31.square() * t1;
107        let x63 = x32.sqn(31) * x31;
108        let x126 = x63.sqn(63) * x63;
109        let x252 = x126.sqn(126) * x126;
110        let x255 = x252.sqn(3) * t111;
111        let x = ((x255.sqn(33) * x32).sqn(64) * t1).sqn(30);
112        CtOption::new(x, x.square().ct_eq(&t1))
113    }
114
115    fn sqn(&self, n: usize) -> Self {
117        let mut x = *self;
118        for _ in 0..n {
119            x = x.square();
120        }
121        x
122    }
123}
124
125impl PrimeField for FieldElement {
126    type Repr = FieldBytes;
127
128    const MODULUS: &'static str = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff";
129    const NUM_BITS: u32 = 384;
130    const CAPACITY: u32 = 383;
131    const TWO_INV: Self = Self::from_u64(2).invert_unchecked();
132    const MULTIPLICATIVE_GENERATOR: Self = Self::from_u64(19);
133    const S: u32 = 1;
134    const ROOT_OF_UNITY: Self = Self::from_hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe");
135    const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked();
136    const DELTA: Self = Self::from_u64(49);
137
138    #[inline]
139    fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
140        Self::from_bytes(&bytes)
141    }
142
143    #[inline]
144    fn to_repr(&self) -> FieldBytes {
145        self.to_bytes()
146    }
147
148    #[inline]
149    fn is_odd(&self) -> Choice {
150        self.is_odd()
151    }
152}
153
154#[cfg(test)]
155mod tests {
156    use super::FieldElement;
157    use elliptic_curve::ff::PrimeField;
158    use primeorder::impl_primefield_tests;
159
160    const T: [u64; 6] = [
162        0x000000007fffffff,
163        0x7fffffff80000000,
164        0xffffffffffffffff,
165        0xffffffffffffffff,
166        0xffffffffffffffff,
167        0x7fffffffffffffff,
168    ];
169
170    impl_primefield_tests!(FieldElement, T);
171
172    #[test]
174    fn invert() {
175        let one = FieldElement::ONE;
176        assert_eq!(one.invert().unwrap(), one);
177
178        let three = one + &one + &one;
179        let inv_three = three.invert().unwrap();
180        assert_eq!(three * &inv_three, one);
181
182        let minus_three = -three;
183        let inv_minus_three = minus_three.invert().unwrap();
184        assert_eq!(inv_minus_three, -inv_three);
185        assert_eq!(three * &inv_minus_three, -one);
186    }
187
188    #[test]
189    fn sqrt() {
190        let one = FieldElement::ONE;
191        let two = one + &one;
192        let four = two.square();
193        assert_eq!(four.sqrt().unwrap(), two);
194    }
195}