elliptic_curve/
macros.rs

1/// Provides both inherent and trait impls for a field element type which are
2/// backed by a core set of arithmetic functions specified as macro arguments.
3///
4/// # Inherent impls
5/// - `const ZERO: Self`
6/// - `const ONE: Self` (multiplicative identity)
7/// - `pub fn from_be_bytes`
8/// - `pub fn from_be_slice`
9/// - `pub fn from_le_bytes`
10/// - `pub fn from_le_slice`
11/// - `pub fn from_uint`
12/// - `fn from_uint_unchecked`
13/// - `pub fn to_be_bytes`
14/// - `pub fn to_le_bytes`
15/// - `pub fn to_canonical`
16/// - `pub fn is_odd`
17/// - `pub fn is_zero`
18/// - `pub fn double`
19///
20/// NOTE: field implementations must provide their own inherent impls of
21/// the following methods in order for the code generated by this macro to
22/// compile:
23///
24/// - `pub fn invert`
25/// - `pub fn sqrt`
26///
27/// # Trait impls
28/// - `AsRef<$arr>`
29/// - `ConditionallySelectable`
30/// - `ConstantTimeEq`
31/// - `ConstantTimeGreater`
32/// - `ConstantTimeLess`
33/// - `Default`
34/// - `DefaultIsZeroes`
35/// - `Eq`
36/// - `Field`
37/// - `PartialEq`
38///
39/// ## Ops
40/// - `Add`
41/// - `AddAssign`
42/// - `Sub`
43/// - `SubAssign`
44/// - `Mul`
45/// - `MulAssign`
46/// - `Neg`
47#[macro_export]
48macro_rules! impl_field_element {
49    (
50        $fe:tt,
51        $bytes:ty,
52        $uint:ty,
53        $modulus:expr,
54        $arr:ty,
55        $from_mont:ident,
56        $to_mont:ident,
57        $add:ident,
58        $sub:ident,
59        $mul:ident,
60        $neg:ident,
61        $square:ident
62    ) => {
63        impl $fe {
64            /// Zero element.
65            pub const ZERO: Self = Self(<$uint>::ZERO);
66
67            /// Multiplicative identity.
68            pub const ONE: Self = Self::from_uint_unchecked(<$uint>::ONE);
69
70            /// Create a [`
71            #[doc = stringify!($fe)]
72            /// `] from a canonical big-endian representation.
73            pub fn from_be_bytes(repr: $bytes) -> $crate::subtle::CtOption<Self> {
74                use $crate::bigint::ArrayEncoding as _;
75                Self::from_uint(<$uint>::from_be_byte_array(repr))
76            }
77
78            /// Decode [`
79            #[doc = stringify!($fe)]
80            /// `] from a big endian byte slice.
81            pub fn from_be_slice(slice: &[u8]) -> $crate::Result<Self> {
82                <$uint as $crate::bigint::Encoding>::Repr::try_from(slice)
83                    .ok()
84                    .and_then(|array| Self::from_be_bytes(array.into()).into())
85                    .ok_or($crate::Error)
86            }
87
88            /// Create a [`
89            #[doc = stringify!($fe)]
90            /// `] from a canonical little-endian representation.
91            pub fn from_le_bytes(repr: $bytes) -> $crate::subtle::CtOption<Self> {
92                use $crate::bigint::ArrayEncoding as _;
93                Self::from_uint(<$uint>::from_le_byte_array(repr))
94            }
95
96            /// Decode [`
97            #[doc = stringify!($fe)]
98            /// `] from a little endian byte slice.
99            pub fn from_le_slice(slice: &[u8]) -> $crate::Result<Self> {
100                <$uint as $crate::bigint::Encoding>::Repr::try_from(slice)
101                    .ok()
102                    .and_then(|array| Self::from_le_bytes(array.into()).into())
103                    .ok_or($crate::Error)
104            }
105
106            /// Decode [`
107            #[doc = stringify!($fe)]
108            /// `]
109            /// from [`
110            #[doc = stringify!($uint)]
111            /// `] converting it into Montgomery form:
112            ///
113            /// ```text
114            /// w * R^2 * R^-1 mod p = wR mod p
115            /// ```
116            pub fn from_uint(uint: $uint) -> $crate::subtle::CtOption<Self> {
117                use $crate::subtle::ConstantTimeLess as _;
118                let is_some = uint.ct_lt(&$modulus);
119                $crate::subtle::CtOption::new(Self::from_uint_unchecked(uint), is_some)
120            }
121
122            /// Parse a [`
123            #[doc = stringify!($fe)]
124            /// `] from big endian hex-encoded bytes.
125            ///
126            /// Does *not* perform a check that the field element does not overflow the order.
127            ///
128            /// This method is primarily intended for defining internal constants.
129            #[allow(dead_code)]
130            pub(crate) const fn from_be_hex(hex: &str) -> Self {
131                Self::from_uint_unchecked(<$uint>::from_be_hex(hex))
132            }
133
134            /// Parse a [`
135            #[doc = stringify!($fe)]
136            /// `] from little endian hex-encoded bytes.
137            ///
138            /// Does *not* perform a check that the field element does not overflow the order.
139            ///
140            /// This method is primarily intended for defining internal constants.
141            #[allow(dead_code)]
142            pub(crate) const fn from_le_hex(hex: &str) -> Self {
143                Self::from_uint_unchecked(<$uint>::from_le_hex(hex))
144            }
145
146            /// Decode [`
147            #[doc = stringify!($fe)]
148            /// `] from [`
149            #[doc = stringify!($uint)]
150            /// `] converting it into Montgomery form.
151            ///
152            /// Does *not* perform a check that the field element does not overflow the order.
153            ///
154            /// Used incorrectly this can lead to invalid results!
155            pub(crate) const fn from_uint_unchecked(w: $uint) -> Self {
156                Self(<$uint>::from_words($to_mont(w.as_words())))
157            }
158
159            /// Returns the big-endian encoding of this [`
160            #[doc = stringify!($fe)]
161            /// `].
162            pub fn to_be_bytes(self) -> $bytes {
163                use $crate::bigint::ArrayEncoding as _;
164                self.to_canonical().to_be_byte_array()
165            }
166
167            /// Returns the little-endian encoding of this [`
168            #[doc = stringify!($fe)]
169            /// `].
170            pub fn to_le_bytes(self) -> $bytes {
171                use $crate::bigint::ArrayEncoding as _;
172                self.to_canonical().to_le_byte_array()
173            }
174
175            /// Translate [`
176            #[doc = stringify!($fe)]
177            /// `] out of the Montgomery domain, returning a [`
178            #[doc = stringify!($uint)]
179            /// `] in canonical form.
180            #[inline]
181            pub const fn to_canonical(self) -> $uint {
182                <$uint>::from_words($from_mont(self.0.as_words()))
183            }
184
185            /// Determine if this [`
186            #[doc = stringify!($fe)]
187            /// `] is odd in the SEC1 sense: `self mod 2 == 1`.
188            ///
189            /// # Returns
190            ///
191            /// If odd, return `Choice(1)`.  Otherwise, return `Choice(0)`.
192            pub fn is_odd(&self) -> Choice {
193                use $crate::bigint::Integer;
194                self.to_canonical().is_odd()
195            }
196
197            /// Determine if this [`
198            #[doc = stringify!($fe)]
199            /// `] is even in the SEC1 sense: `self mod 2 == 0`.
200            ///
201            /// # Returns
202            ///
203            /// If even, return `Choice(1)`.  Otherwise, return `Choice(0)`.
204            pub fn is_even(&self) -> Choice {
205                !self.is_odd()
206            }
207
208            /// Determine if this [`
209            #[doc = stringify!($fe)]
210            /// `] is zero.
211            ///
212            /// # Returns
213            ///
214            /// If zero, return `Choice(1)`.  Otherwise, return `Choice(0)`.
215            pub fn is_zero(&self) -> Choice {
216                self.ct_eq(&Self::ZERO)
217            }
218
219            /// Add elements.
220            pub const fn add(&self, rhs: &Self) -> Self {
221                Self(<$uint>::from_words($add(
222                    self.0.as_words(),
223                    rhs.0.as_words(),
224                )))
225            }
226
227            /// Double element (add it to itself).
228            #[must_use]
229            pub const fn double(&self) -> Self {
230                self.add(self)
231            }
232
233            /// Subtract elements.
234            pub const fn sub(&self, rhs: &Self) -> Self {
235                Self(<$uint>::from_words($sub(
236                    self.0.as_words(),
237                    rhs.0.as_words(),
238                )))
239            }
240
241            /// Multiply elements.
242            pub const fn mul(&self, rhs: &Self) -> Self {
243                Self(<$uint>::from_words($mul(
244                    self.0.as_words(),
245                    rhs.0.as_words(),
246                )))
247            }
248
249            /// Negate element.
250            pub const fn neg(&self) -> Self {
251                Self(<$uint>::from_words($neg(self.0.as_words())))
252            }
253
254            /// Compute modular square.
255            #[must_use]
256            pub const fn square(&self) -> Self {
257                Self(<$uint>::from_words($square(self.0.as_words())))
258            }
259        }
260
261        impl AsRef<$arr> for $fe {
262            fn as_ref(&self) -> &$arr {
263                self.0.as_ref()
264            }
265        }
266
267        impl Default for $fe {
268            fn default() -> Self {
269                Self::ZERO
270            }
271        }
272
273        impl Eq for $fe {}
274
275        impl PartialEq for $fe {
276            fn eq(&self, rhs: &Self) -> bool {
277                self.0.ct_eq(&(rhs.0)).into()
278            }
279        }
280
281        impl $crate::subtle::ConditionallySelectable for $fe {
282            fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
283                Self(<$uint>::conditional_select(&a.0, &b.0, choice))
284            }
285        }
286
287        impl $crate::subtle::ConstantTimeEq for $fe {
288            fn ct_eq(&self, other: &Self) -> $crate::subtle::Choice {
289                self.0.ct_eq(&other.0)
290            }
291        }
292
293        impl $crate::subtle::ConstantTimeGreater for $fe {
294            fn ct_gt(&self, other: &Self) -> $crate::subtle::Choice {
295                self.0.ct_gt(&other.0)
296            }
297        }
298
299        impl $crate::subtle::ConstantTimeLess for $fe {
300            fn ct_lt(&self, other: &Self) -> $crate::subtle::Choice {
301                self.0.ct_lt(&other.0)
302            }
303        }
304
305        impl $crate::zeroize::DefaultIsZeroes for $fe {}
306
307        impl $crate::ff::Field for $fe {
308            fn random(mut rng: impl $crate::rand_core::RngCore) -> Self {
309                // NOTE: can't use ScalarCore::random due to CryptoRng bound
310                let mut bytes = <$bytes>::default();
311
312                loop {
313                    rng.fill_bytes(&mut bytes);
314                    if let Some(fe) = Self::from_be_bytes(bytes).into() {
315                        return fe;
316                    }
317                }
318            }
319
320            fn zero() -> Self {
321                Self::ZERO
322            }
323
324            fn one() -> Self {
325                Self::ONE
326            }
327
328            fn is_zero(&self) -> Choice {
329                Self::ZERO.ct_eq(self)
330            }
331
332            #[must_use]
333            fn square(&self) -> Self {
334                self.square()
335            }
336
337            #[must_use]
338            fn double(&self) -> Self {
339                self.double()
340            }
341
342            fn invert(&self) -> CtOption<Self> {
343                self.invert()
344            }
345
346            fn sqrt(&self) -> CtOption<Self> {
347                self.sqrt()
348            }
349        }
350
351        $crate::impl_field_op!($fe, $uint, Add, add, $add);
352        $crate::impl_field_op!($fe, $uint, Sub, sub, $sub);
353        $crate::impl_field_op!($fe, $uint, Mul, mul, $mul);
354
355        impl AddAssign<$fe> for $fe {
356            #[inline]
357            fn add_assign(&mut self, other: $fe) {
358                *self = *self + other;
359            }
360        }
361
362        impl AddAssign<&$fe> for $fe {
363            #[inline]
364            fn add_assign(&mut self, other: &$fe) {
365                *self = *self + other;
366            }
367        }
368
369        impl SubAssign<$fe> for $fe {
370            #[inline]
371            fn sub_assign(&mut self, other: $fe) {
372                *self = *self - other;
373            }
374        }
375
376        impl SubAssign<&$fe> for $fe {
377            #[inline]
378            fn sub_assign(&mut self, other: &$fe) {
379                *self = *self - other;
380            }
381        }
382
383        impl MulAssign<&$fe> for $fe {
384            #[inline]
385            fn mul_assign(&mut self, other: &$fe) {
386                *self = *self * other;
387            }
388        }
389
390        impl MulAssign for $fe {
391            #[inline]
392            fn mul_assign(&mut self, other: $fe) {
393                *self = *self * other;
394            }
395        }
396
397        impl Neg for $fe {
398            type Output = $fe;
399
400            #[inline]
401            fn neg(self) -> $fe {
402                Self($neg(self.as_ref()).into())
403            }
404        }
405    };
406}
407
408/// Emit impls for a `core::ops` trait for all combinations of reference types,
409/// which thunk to the given function.
410#[macro_export]
411macro_rules! impl_field_op {
412    ($fe:tt, $uint:ty, $op:tt, $op_fn:ident, $func:ident) => {
413        impl ::core::ops::$op for $fe {
414            type Output = $fe;
415
416            #[inline]
417            fn $op_fn(self, rhs: $fe) -> $fe {
418                $fe($func(self.as_ref(), rhs.as_ref()).into())
419            }
420        }
421
422        impl ::core::ops::$op<&$fe> for $fe {
423            type Output = $fe;
424
425            #[inline]
426            fn $op_fn(self, rhs: &$fe) -> $fe {
427                $fe($func(self.as_ref(), rhs.as_ref()).into())
428            }
429        }
430
431        impl ::core::ops::$op<&$fe> for &$fe {
432            type Output = $fe;
433
434            #[inline]
435            fn $op_fn(self, rhs: &$fe) -> $fe {
436                $fe($func(self.as_ref(), rhs.as_ref()).into())
437            }
438        }
439    };
440}