From 05bf322d7d13547f0f94f6c5c66a90effd88d4bd Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 8 Dec 2022 20:46:54 -0700 Subject: [PATCH] elliptic-curve: remove `impl_field_element!` macro Removes macro which was originally added in #1021 Going forward these macros are located in the `primeorder` crate: https://github.com/RustCrypto/elliptic-curves/blob/master/primeorder/src/field.rs --- elliptic-curve/src/dev.rs | 72 ------ elliptic-curve/src/lib.rs | 3 - elliptic-curve/src/macros.rs | 440 ----------------------------------- 3 files changed, 515 deletions(-) delete mode 100644 elliptic-curve/src/macros.rs diff --git a/elliptic-curve/src/dev.rs b/elliptic-curve/src/dev.rs index be0c156e5..8f1f0472b 100644 --- a/elliptic-curve/src/dev.rs +++ b/elliptic-curve/src/dev.rs @@ -707,78 +707,6 @@ impl Neg for ProjectivePoint { } } -/// Constant representing the base field modulus -/// p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1 -pub const MODULUS: U256 = - U256::from_be_hex("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"); - -/// Example base field element. -#[derive(Clone, Copy, Debug)] -pub struct FieldElement(pub(crate) U256); - -/// Internal field element representation. -#[cfg(target_pointer_width = "32")] -type FeWords = [u32; 8]; - -/// Internal field element representation. -#[cfg(target_pointer_width = "64")] -type FeWords = [u64; 4]; - -impl_field_element!( - FieldElement, - FieldBytes, - U256, - MODULUS, - FeWords, - p256_from_montgomery, - p256_to_montgomery, - p256_add, - p256_sub, - p256_mul, - p256_opp, - p256_square -); - -impl FieldElement { - /// Returns the multiplicative inverse of self, if self is non-zero. - pub fn invert(&self) -> CtOption { - unimplemented!() - } - - /// Returns the square root of self mod p, or `None` if no square root exists. - pub fn sqrt(&self) -> CtOption { - unimplemented!() - } -} - -const fn p256_from_montgomery(_: &FeWords) -> FeWords { - unimplemented!() -} - -const fn p256_to_montgomery(w: &FeWords) -> FeWords { - *w -} - -const fn p256_add(_: &FeWords, _: &FeWords) -> FeWords { - unimplemented!() -} - -const fn p256_sub(_: &FeWords, _: &FeWords) -> FeWords { - unimplemented!() -} - -const fn p256_mul(_: &FeWords, _: &FeWords) -> FeWords { - unimplemented!() -} - -const fn p256_opp(_: &FeWords) -> FeWords { - unimplemented!() -} - -const fn p256_square(_: &FeWords) -> FeWords { - unimplemented!() -} - #[cfg(test)] mod tests { use super::Scalar; diff --git a/elliptic-curve/src/lib.rs b/elliptic-curve/src/lib.rs index 62ac7856b..2f9481206 100644 --- a/elliptic-curve/src/lib.rs +++ b/elliptic-curve/src/lib.rs @@ -66,9 +66,6 @@ extern crate std; #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] pub use rand_core; -#[macro_use] -mod macros; - pub mod ops; #[cfg(feature = "dev")] diff --git a/elliptic-curve/src/macros.rs b/elliptic-curve/src/macros.rs deleted file mode 100644 index 6ceadc833..000000000 --- a/elliptic-curve/src/macros.rs +++ /dev/null @@ -1,440 +0,0 @@ -/// Provides both inherent and trait impls for a field element type which are -/// backed by a core set of arithmetic functions specified as macro arguments. -/// -/// # Inherent impls -/// - `const ZERO: Self` -/// - `const ONE: Self` (multiplicative identity) -/// - `pub fn from_be_bytes` -/// - `pub fn from_be_slice` -/// - `pub fn from_le_bytes` -/// - `pub fn from_le_slice` -/// - `pub fn from_uint` -/// - `fn from_uint_unchecked` -/// - `pub fn to_be_bytes` -/// - `pub fn to_le_bytes` -/// - `pub fn to_canonical` -/// - `pub fn is_odd` -/// - `pub fn is_zero` -/// - `pub fn double` -/// -/// NOTE: field implementations must provide their own inherent impls of -/// the following methods in order for the code generated by this macro to -/// compile: -/// -/// - `pub fn invert` -/// - `pub fn sqrt` -/// -/// # Trait impls -/// - `AsRef<$arr>` -/// - `ConditionallySelectable` -/// - `ConstantTimeEq` -/// - `ConstantTimeGreater` -/// - `ConstantTimeLess` -/// - `Default` -/// - `DefaultIsZeroes` -/// - `Eq` -/// - `Field` -/// - `PartialEq` -/// -/// ## Ops -/// - `Add` -/// - `AddAssign` -/// - `Sub` -/// - `SubAssign` -/// - `Mul` -/// - `MulAssign` -/// - `Neg` -#[macro_export] -macro_rules! impl_field_element { - ( - $fe:tt, - $bytes:ty, - $uint:ty, - $modulus:expr, - $arr:ty, - $from_mont:ident, - $to_mont:ident, - $add:ident, - $sub:ident, - $mul:ident, - $neg:ident, - $square:ident - ) => { - impl $fe { - /// Zero element. - pub const ZERO: Self = Self(<$uint>::ZERO); - - /// Multiplicative identity. - pub const ONE: Self = Self::from_uint_unchecked(<$uint>::ONE); - - /// Create a [` - #[doc = stringify!($fe)] - /// `] from a canonical big-endian representation. - pub fn from_be_bytes(repr: $bytes) -> $crate::subtle::CtOption { - use $crate::bigint::ArrayEncoding as _; - Self::from_uint(<$uint>::from_be_byte_array(repr)) - } - - /// Decode [` - #[doc = stringify!($fe)] - /// `] from a big endian byte slice. - pub fn from_be_slice(slice: &[u8]) -> $crate::Result { - <$uint as $crate::bigint::Encoding>::Repr::try_from(slice) - .ok() - .and_then(|array| Self::from_be_bytes(array.into()).into()) - .ok_or($crate::Error) - } - - /// Create a [` - #[doc = stringify!($fe)] - /// `] from a canonical little-endian representation. - pub fn from_le_bytes(repr: $bytes) -> $crate::subtle::CtOption { - use $crate::bigint::ArrayEncoding as _; - Self::from_uint(<$uint>::from_le_byte_array(repr)) - } - - /// Decode [` - #[doc = stringify!($fe)] - /// `] from a little endian byte slice. - pub fn from_le_slice(slice: &[u8]) -> $crate::Result { - <$uint as $crate::bigint::Encoding>::Repr::try_from(slice) - .ok() - .and_then(|array| Self::from_le_bytes(array.into()).into()) - .ok_or($crate::Error) - } - - /// Decode [` - #[doc = stringify!($fe)] - /// `] - /// from [` - #[doc = stringify!($uint)] - /// `] converting it into Montgomery form: - /// - /// ```text - /// w * R^2 * R^-1 mod p = wR mod p - /// ``` - pub fn from_uint(uint: $uint) -> $crate::subtle::CtOption { - use $crate::subtle::ConstantTimeLess as _; - let is_some = uint.ct_lt(&$modulus); - $crate::subtle::CtOption::new(Self::from_uint_unchecked(uint), is_some) - } - - /// Parse a [` - #[doc = stringify!($fe)] - /// `] from big endian hex-encoded bytes. - /// - /// Does *not* perform a check that the field element does not overflow the order. - /// - /// This method is primarily intended for defining internal constants. - #[allow(dead_code)] - pub(crate) const fn from_be_hex(hex: &str) -> Self { - Self::from_uint_unchecked(<$uint>::from_be_hex(hex)) - } - - /// Parse a [` - #[doc = stringify!($fe)] - /// `] from little endian hex-encoded bytes. - /// - /// Does *not* perform a check that the field element does not overflow the order. - /// - /// This method is primarily intended for defining internal constants. - #[allow(dead_code)] - pub(crate) const fn from_le_hex(hex: &str) -> Self { - Self::from_uint_unchecked(<$uint>::from_le_hex(hex)) - } - - /// Decode [` - #[doc = stringify!($fe)] - /// `] from [` - #[doc = stringify!($uint)] - /// `] converting it into Montgomery form. - /// - /// Does *not* perform a check that the field element does not overflow the order. - /// - /// Used incorrectly this can lead to invalid results! - pub(crate) const fn from_uint_unchecked(w: $uint) -> Self { - Self(<$uint>::from_words($to_mont(w.as_words()))) - } - - /// Returns the big-endian encoding of this [` - #[doc = stringify!($fe)] - /// `]. - pub fn to_be_bytes(self) -> $bytes { - use $crate::bigint::ArrayEncoding as _; - self.to_canonical().to_be_byte_array() - } - - /// Returns the little-endian encoding of this [` - #[doc = stringify!($fe)] - /// `]. - pub fn to_le_bytes(self) -> $bytes { - use $crate::bigint::ArrayEncoding as _; - self.to_canonical().to_le_byte_array() - } - - /// Translate [` - #[doc = stringify!($fe)] - /// `] out of the Montgomery domain, returning a [` - #[doc = stringify!($uint)] - /// `] in canonical form. - #[inline] - pub const fn to_canonical(self) -> $uint { - <$uint>::from_words($from_mont(self.0.as_words())) - } - - /// Determine if this [` - #[doc = stringify!($fe)] - /// `] is odd in the SEC1 sense: `self mod 2 == 1`. - /// - /// # Returns - /// - /// If odd, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_odd(&self) -> Choice { - use $crate::bigint::Integer; - self.to_canonical().is_odd() - } - - /// Determine if this [` - #[doc = stringify!($fe)] - /// `] is even in the SEC1 sense: `self mod 2 == 0`. - /// - /// # Returns - /// - /// If even, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_even(&self) -> Choice { - !self.is_odd() - } - - /// Determine if this [` - #[doc = stringify!($fe)] - /// `] is zero. - /// - /// # Returns - /// - /// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_zero(&self) -> Choice { - self.ct_eq(&Self::ZERO) - } - - /// Add elements. - pub const fn add(&self, rhs: &Self) -> Self { - Self(<$uint>::from_words($add( - self.0.as_words(), - rhs.0.as_words(), - ))) - } - - /// Double element (add it to itself). - #[must_use] - pub const fn double(&self) -> Self { - self.add(self) - } - - /// Subtract elements. - pub const fn sub(&self, rhs: &Self) -> Self { - Self(<$uint>::from_words($sub( - self.0.as_words(), - rhs.0.as_words(), - ))) - } - - /// Multiply elements. - pub const fn mul(&self, rhs: &Self) -> Self { - Self(<$uint>::from_words($mul( - self.0.as_words(), - rhs.0.as_words(), - ))) - } - - /// Negate element. - pub const fn neg(&self) -> Self { - Self(<$uint>::from_words($neg(self.0.as_words()))) - } - - /// Compute modular square. - #[must_use] - pub const fn square(&self) -> Self { - Self(<$uint>::from_words($square(self.0.as_words()))) - } - } - - impl AsRef<$arr> for $fe { - fn as_ref(&self) -> &$arr { - self.0.as_ref() - } - } - - impl Default for $fe { - fn default() -> Self { - Self::ZERO - } - } - - impl Eq for $fe {} - - impl PartialEq for $fe { - fn eq(&self, rhs: &Self) -> bool { - self.0.ct_eq(&(rhs.0)).into() - } - } - - impl $crate::subtle::ConditionallySelectable for $fe { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - Self(<$uint>::conditional_select(&a.0, &b.0, choice)) - } - } - - impl $crate::subtle::ConstantTimeEq for $fe { - fn ct_eq(&self, other: &Self) -> $crate::subtle::Choice { - self.0.ct_eq(&other.0) - } - } - - impl $crate::subtle::ConstantTimeGreater for $fe { - fn ct_gt(&self, other: &Self) -> $crate::subtle::Choice { - self.0.ct_gt(&other.0) - } - } - - impl $crate::subtle::ConstantTimeLess for $fe { - fn ct_lt(&self, other: &Self) -> $crate::subtle::Choice { - self.0.ct_lt(&other.0) - } - } - - impl $crate::zeroize::DefaultIsZeroes for $fe {} - - impl $crate::ff::Field for $fe { - fn random(mut rng: impl $crate::rand_core::RngCore) -> Self { - // NOTE: can't use ScalarCore::random due to CryptoRng bound - let mut bytes = <$bytes>::default(); - - loop { - rng.fill_bytes(&mut bytes); - if let Some(fe) = Self::from_be_bytes(bytes).into() { - return fe; - } - } - } - - fn zero() -> Self { - Self::ZERO - } - - fn one() -> Self { - Self::ONE - } - - fn is_zero(&self) -> Choice { - Self::ZERO.ct_eq(self) - } - - #[must_use] - fn square(&self) -> Self { - self.square() - } - - #[must_use] - fn double(&self) -> Self { - self.double() - } - - fn invert(&self) -> CtOption { - self.invert() - } - - fn sqrt(&self) -> CtOption { - self.sqrt() - } - } - - $crate::impl_field_op!($fe, $uint, Add, add, $add); - $crate::impl_field_op!($fe, $uint, Sub, sub, $sub); - $crate::impl_field_op!($fe, $uint, Mul, mul, $mul); - - impl AddAssign<$fe> for $fe { - #[inline] - fn add_assign(&mut self, other: $fe) { - *self = *self + other; - } - } - - impl AddAssign<&$fe> for $fe { - #[inline] - fn add_assign(&mut self, other: &$fe) { - *self = *self + other; - } - } - - impl SubAssign<$fe> for $fe { - #[inline] - fn sub_assign(&mut self, other: $fe) { - *self = *self - other; - } - } - - impl SubAssign<&$fe> for $fe { - #[inline] - fn sub_assign(&mut self, other: &$fe) { - *self = *self - other; - } - } - - impl MulAssign<&$fe> for $fe { - #[inline] - fn mul_assign(&mut self, other: &$fe) { - *self = *self * other; - } - } - - impl MulAssign for $fe { - #[inline] - fn mul_assign(&mut self, other: $fe) { - *self = *self * other; - } - } - - impl Neg for $fe { - type Output = $fe; - - #[inline] - fn neg(self) -> $fe { - Self($neg(self.as_ref()).into()) - } - } - }; -} - -/// Emit impls for a `core::ops` trait for all combinations of reference types, -/// which thunk to the given function. -#[macro_export] -macro_rules! impl_field_op { - ($fe:tt, $uint:ty, $op:tt, $op_fn:ident, $func:ident) => { - impl ::core::ops::$op for $fe { - type Output = $fe; - - #[inline] - fn $op_fn(self, rhs: $fe) -> $fe { - $fe($func(self.as_ref(), rhs.as_ref()).into()) - } - } - - impl ::core::ops::$op<&$fe> for $fe { - type Output = $fe; - - #[inline] - fn $op_fn(self, rhs: &$fe) -> $fe { - $fe($func(self.as_ref(), rhs.as_ref()).into()) - } - } - - impl ::core::ops::$op<&$fe> for &$fe { - type Output = $fe; - - #[inline] - fn $op_fn(self, rhs: &$fe) -> $fe { - $fe($func(self.as_ref(), rhs.as_ref()).into()) - } - } - }; -}