diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:47:55 +0000 |
commit | 2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 (patch) | |
tree | 033cc839730fda84ff08db877037977be94e5e3a /vendor/crypto-bigint/src/limb | |
parent | Initial commit. (diff) | |
download | cargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.tar.xz cargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.zip |
Adding upstream version 0.70.1+ds1.upstream/0.70.1+ds1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/crypto-bigint/src/limb')
-rw-r--r-- | vendor/crypto-bigint/src/limb/add.rs | 180 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/bit_and.rs | 21 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/bit_not.rs | 19 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/bit_or.rs | 19 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/bit_xor.rs | 19 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/bits.rs | 18 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/cmp.rs | 200 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/encoding.rs | 64 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/from.rs | 74 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/mul.rs | 195 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/neg.rs | 20 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/rand.rs | 38 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/shl.rs | 74 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/shr.rs | 74 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/sub.rs | 182 |
15 files changed, 1197 insertions, 0 deletions
diff --git a/vendor/crypto-bigint/src/limb/add.rs b/vendor/crypto-bigint/src/limb/add.rs new file mode 100644 index 0000000..0ef793b --- /dev/null +++ b/vendor/crypto-bigint/src/limb/add.rs @@ -0,0 +1,180 @@ +//! Limb addition + +use crate::{Checked, CheckedAdd, Limb, WideWord, Word, Wrapping, Zero}; +use core::ops::{Add, AddAssign}; +use subtle::CtOption; + +impl Limb { + /// Computes `self + rhs + carry`, returning the result along with the new carry. + #[inline(always)] + pub const fn adc(self, rhs: Limb, carry: Limb) -> (Limb, Limb) { + let a = self.0 as WideWord; + let b = rhs.0 as WideWord; + let carry = carry.0 as WideWord; + let ret = a + b + carry; + (Limb(ret as Word), Limb((ret >> Self::BITS) as Word)) + } + + /// Perform saturating addition. + #[inline] + pub const fn saturating_add(&self, rhs: Self) -> Self { + Limb(self.0.saturating_add(rhs.0)) + } + + /// Perform wrapping addition, discarding overflow. + #[inline(always)] + pub const fn wrapping_add(&self, rhs: Self) -> Self { + Limb(self.0.wrapping_add(rhs.0)) + } +} + +impl CheckedAdd for Limb { + type Output = Self; + + #[inline] + fn checked_add(&self, rhs: Self) -> CtOption<Self> { + let (result, carry) = self.adc(rhs, Limb::ZERO); + CtOption::new(result, carry.is_zero()) + } +} + +impl Add for Wrapping<Limb> { + type Output = Self; + + fn add(self, rhs: Self) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_add(rhs.0)) + } +} + +impl Add<&Wrapping<Limb>> for Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn add(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_add(rhs.0)) + } +} + +impl Add<Wrapping<Limb>> for &Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn add(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_add(rhs.0)) + } +} + +impl Add<&Wrapping<Limb>> for &Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn add(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_add(rhs.0)) + } +} + +impl AddAssign for Wrapping<Limb> { + fn add_assign(&mut self, other: Self) { + *self = *self + other; + } +} + +impl AddAssign<&Wrapping<Limb>> for Wrapping<Limb> { + fn add_assign(&mut self, other: &Self) { + *self = *self + other; + } +} + +impl Add for Checked<Limb> { + type Output = Self; + + fn add(self, rhs: Self) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))), + ) + } +} + +impl Add<&Checked<Limb>> for Checked<Limb> { + type Output = Checked<Limb>; + + fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))), + ) + } +} + +impl Add<Checked<Limb>> for &Checked<Limb> { + type Output = Checked<Limb>; + + fn add(self, rhs: Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))), + ) + } +} + +impl Add<&Checked<Limb>> for &Checked<Limb> { + type Output = Checked<Limb>; + + fn add(self, rhs: &Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_add(rhs))), + ) + } +} + +impl AddAssign for Checked<Limb> { + fn add_assign(&mut self, other: Self) { + *self = *self + other; + } +} + +impl AddAssign<&Checked<Limb>> for Checked<Limb> { + fn add_assign(&mut self, other: &Self) { + *self = *self + other; + } +} + +#[cfg(test)] +mod tests { + use crate::{CheckedAdd, Limb}; + + #[test] + fn adc_no_carry() { + let (res, carry) = Limb::ZERO.adc(Limb::ONE, Limb::ZERO); + assert_eq!(res, Limb::ONE); + assert_eq!(carry, Limb::ZERO); + } + + #[test] + fn adc_with_carry() { + let (res, carry) = Limb::MAX.adc(Limb::ONE, Limb::ZERO); + assert_eq!(res, Limb::ZERO); + assert_eq!(carry, Limb::ONE); + } + + #[test] + fn wrapping_add_no_carry() { + assert_eq!(Limb::ZERO.wrapping_add(Limb::ONE), Limb::ONE); + } + + #[test] + fn wrapping_add_with_carry() { + assert_eq!(Limb::MAX.wrapping_add(Limb::ONE), Limb::ZERO); + } + + #[test] + fn checked_add_ok() { + let result = Limb::ZERO.checked_add(Limb::ONE); + assert_eq!(result.unwrap(), Limb::ONE); + } + + #[test] + fn checked_add_overflow() { + let result = Limb::MAX.checked_add(Limb::ONE); + assert!(!bool::from(result.is_some())); + } +} diff --git a/vendor/crypto-bigint/src/limb/bit_and.rs b/vendor/crypto-bigint/src/limb/bit_and.rs new file mode 100644 index 0000000..3f0bfba --- /dev/null +++ b/vendor/crypto-bigint/src/limb/bit_and.rs @@ -0,0 +1,21 @@ +//! Limb bit and operations. + +use super::Limb; +use core::ops::BitAnd; + +impl Limb { + /// Calculates `a & b`. + #[inline(always)] + pub const fn bitand(self, rhs: Self) -> Self { + Limb(self.0 & rhs.0) + } +} + +impl BitAnd for Limb { + type Output = Limb; + + #[inline(always)] + fn bitand(self, rhs: Self) -> Self::Output { + self.bitand(rhs) + } +} diff --git a/vendor/crypto-bigint/src/limb/bit_not.rs b/vendor/crypto-bigint/src/limb/bit_not.rs new file mode 100644 index 0000000..26676d5 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/bit_not.rs @@ -0,0 +1,19 @@ +//! Limb bit not operations. + +use super::Limb; +use core::ops::Not; + +impl Limb { + /// Calculates `!a`. + pub const fn not(self) -> Self { + Limb(!self.0) + } +} + +impl Not for Limb { + type Output = Limb; + + fn not(self) -> <Self as Not>::Output { + self.not() + } +} diff --git a/vendor/crypto-bigint/src/limb/bit_or.rs b/vendor/crypto-bigint/src/limb/bit_or.rs new file mode 100644 index 0000000..cafac18 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/bit_or.rs @@ -0,0 +1,19 @@ +//! Limb bit or operations. + +use super::Limb; +use core::ops::BitOr; + +impl Limb { + /// Calculates `a | b`. + pub const fn bitor(self, rhs: Self) -> Self { + Limb(self.0 | rhs.0) + } +} + +impl BitOr for Limb { + type Output = Limb; + + fn bitor(self, rhs: Self) -> Self::Output { + self.bitor(rhs) + } +} diff --git a/vendor/crypto-bigint/src/limb/bit_xor.rs b/vendor/crypto-bigint/src/limb/bit_xor.rs new file mode 100644 index 0000000..a507822 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/bit_xor.rs @@ -0,0 +1,19 @@ +//! Limb bit xor operations. + +use super::Limb; +use core::ops::BitXor; + +impl Limb { + /// Calculates `a ^ b`. + pub const fn bitxor(self, rhs: Self) -> Self { + Limb(self.0 ^ rhs.0) + } +} + +impl BitXor for Limb { + type Output = Limb; + + fn bitxor(self, rhs: Self) -> Self::Output { + self.bitxor(rhs) + } +} diff --git a/vendor/crypto-bigint/src/limb/bits.rs b/vendor/crypto-bigint/src/limb/bits.rs new file mode 100644 index 0000000..02a74de --- /dev/null +++ b/vendor/crypto-bigint/src/limb/bits.rs @@ -0,0 +1,18 @@ +use super::Limb; + +impl Limb { + /// Calculate the number of bits needed to represent this number. + pub const fn bits(self) -> usize { + Limb::BITS - (self.0.leading_zeros() as usize) + } + + /// Calculate the number of leading zeros in the binary representation of this number. + pub const fn leading_zeros(self) -> usize { + self.0.leading_zeros() as usize + } + + /// Calculate the number of trailing zeros in the binary representation of this number. + pub const fn trailing_zeros(self) -> usize { + self.0.trailing_zeros() as usize + } +} diff --git a/vendor/crypto-bigint/src/limb/cmp.rs b/vendor/crypto-bigint/src/limb/cmp.rs new file mode 100644 index 0000000..4cdec5b --- /dev/null +++ b/vendor/crypto-bigint/src/limb/cmp.rs @@ -0,0 +1,200 @@ +//! Limb comparisons + +use super::HI_BIT; +use crate::{CtChoice, Limb}; +use core::cmp::Ordering; +use subtle::{Choice, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess}; + +impl Limb { + /// Is this limb an odd number? + #[inline] + pub fn is_odd(&self) -> Choice { + Choice::from(self.0 as u8 & 1) + } + + /// Perform a comparison of the inner value in variable-time. + /// + /// Note that the [`PartialOrd`] and [`Ord`] impls wrap constant-time + /// comparisons using the `subtle` crate. + pub fn cmp_vartime(&self, other: &Self) -> Ordering { + self.0.cmp(&other.0) + } + + /// Performs an equality check in variable-time. + pub const fn eq_vartime(&self, other: &Self) -> bool { + self.0 == other.0 + } + + /// Return `b` if `c` is truthy, otherwise return `a`. + #[inline] + pub(crate) const fn ct_select(a: Self, b: Self, c: CtChoice) -> Self { + Self(c.select(a.0, b.0)) + } + + /// Returns the truthy value if `self != 0` and the falsy value otherwise. + #[inline] + pub(crate) const fn ct_is_nonzero(&self) -> CtChoice { + let inner = self.0; + CtChoice::from_lsb((inner | inner.wrapping_neg()) >> HI_BIT) + } + + /// Returns the truthy value if `lhs == rhs` and the falsy value otherwise. + #[inline] + pub(crate) const fn ct_eq(lhs: Self, rhs: Self) -> CtChoice { + let x = lhs.0; + let y = rhs.0; + + // x ^ y == 0 if and only if x == y + Self(x ^ y).ct_is_nonzero().not() + } + + /// Returns the truthy value if `lhs < rhs` and the falsy value otherwise. + #[inline] + pub(crate) const fn ct_lt(lhs: Self, rhs: Self) -> CtChoice { + let x = lhs.0; + let y = rhs.0; + let bit = (((!x) & y) | (((!x) | y) & (x.wrapping_sub(y)))) >> (Limb::BITS - 1); + CtChoice::from_lsb(bit) + } + + /// Returns the truthy value if `lhs <= rhs` and the falsy value otherwise. + #[inline] + pub(crate) const fn ct_le(lhs: Self, rhs: Self) -> CtChoice { + let x = lhs.0; + let y = rhs.0; + let bit = (((!x) | y) & ((x ^ y) | !(y.wrapping_sub(x)))) >> (Limb::BITS - 1); + CtChoice::from_lsb(bit) + } +} + +impl ConstantTimeEq for Limb { + #[inline] + fn ct_eq(&self, other: &Self) -> Choice { + self.0.ct_eq(&other.0) + } +} + +impl ConstantTimeGreater for Limb { + #[inline] + fn ct_gt(&self, other: &Self) -> Choice { + self.0.ct_gt(&other.0) + } +} + +impl ConstantTimeLess for Limb { + #[inline] + fn ct_lt(&self, other: &Self) -> Choice { + self.0.ct_lt(&other.0) + } +} + +impl Eq for Limb {} + +impl Ord for Limb { + fn cmp(&self, other: &Self) -> Ordering { + let mut n = 0i8; + n -= self.ct_lt(other).unwrap_u8() as i8; + n += self.ct_gt(other).unwrap_u8() as i8; + + match n { + -1 => Ordering::Less, + 1 => Ordering::Greater, + _ => { + debug_assert_eq!(n, 0); + debug_assert!(bool::from(self.ct_eq(other))); + Ordering::Equal + } + } + } +} + +impl PartialOrd for Limb { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl PartialEq for Limb { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.ct_eq(other).into() + } +} + +#[cfg(test)] +mod tests { + use crate::{Limb, Zero}; + use core::cmp::Ordering; + use subtle::{ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess}; + + #[test] + fn is_zero() { + assert!(bool::from(Limb::ZERO.is_zero())); + assert!(!bool::from(Limb::ONE.is_zero())); + assert!(!bool::from(Limb::MAX.is_zero())); + } + + #[test] + fn is_odd() { + assert!(!bool::from(Limb::ZERO.is_odd())); + assert!(bool::from(Limb::ONE.is_odd())); + assert!(bool::from(Limb::MAX.is_odd())); + } + + #[test] + fn ct_eq() { + let a = Limb::ZERO; + let b = Limb::MAX; + + assert!(bool::from(a.ct_eq(&a))); + assert!(!bool::from(a.ct_eq(&b))); + assert!(!bool::from(b.ct_eq(&a))); + assert!(bool::from(b.ct_eq(&b))); + } + + #[test] + fn ct_gt() { + let a = Limb::ZERO; + let b = Limb::ONE; + let c = Limb::MAX; + + assert!(bool::from(b.ct_gt(&a))); + assert!(bool::from(c.ct_gt(&a))); + assert!(bool::from(c.ct_gt(&b))); + + assert!(!bool::from(a.ct_gt(&a))); + assert!(!bool::from(b.ct_gt(&b))); + assert!(!bool::from(c.ct_gt(&c))); + + assert!(!bool::from(a.ct_gt(&b))); + assert!(!bool::from(a.ct_gt(&c))); + assert!(!bool::from(b.ct_gt(&c))); + } + + #[test] + fn ct_lt() { + let a = Limb::ZERO; + let b = Limb::ONE; + let c = Limb::MAX; + + assert!(bool::from(a.ct_lt(&b))); + assert!(bool::from(a.ct_lt(&c))); + assert!(bool::from(b.ct_lt(&c))); + + assert!(!bool::from(a.ct_lt(&a))); + assert!(!bool::from(b.ct_lt(&b))); + assert!(!bool::from(c.ct_lt(&c))); + + assert!(!bool::from(b.ct_lt(&a))); + assert!(!bool::from(c.ct_lt(&a))); + assert!(!bool::from(c.ct_lt(&b))); + } + + #[test] + fn cmp() { + assert_eq!(Limb::ZERO.cmp(&Limb::ONE), Ordering::Less); + assert_eq!(Limb::ONE.cmp(&Limb::ONE), Ordering::Equal); + assert_eq!(Limb::MAX.cmp(&Limb::ONE), Ordering::Greater); + } +} diff --git a/vendor/crypto-bigint/src/limb/encoding.rs b/vendor/crypto-bigint/src/limb/encoding.rs new file mode 100644 index 0000000..ab28a6a --- /dev/null +++ b/vendor/crypto-bigint/src/limb/encoding.rs @@ -0,0 +1,64 @@ +//! Limb encoding + +use super::{Limb, Word}; +use crate::Encoding; + +impl Encoding for Limb { + #[cfg(target_pointer_width = "32")] + type Repr = [u8; 4]; + #[cfg(target_pointer_width = "64")] + type Repr = [u8; 8]; + + #[inline] + fn from_be_bytes(bytes: Self::Repr) -> Self { + Limb(Word::from_be_bytes(bytes)) + } + + #[inline] + fn from_le_bytes(bytes: Self::Repr) -> Self { + Limb(Word::from_le_bytes(bytes)) + } + + #[inline] + fn to_be_bytes(&self) -> Self::Repr { + self.0.to_be_bytes() + } + + #[inline] + fn to_le_bytes(&self) -> Self::Repr { + self.0.to_le_bytes() + } +} + +#[cfg(test)] +mod test { + use super::*; + use proptest::prelude::*; + + prop_compose! { + fn limb()(inner in any::<Word>()) -> Limb { + Limb(inner) + } + } + + proptest! { + #[test] + fn roundtrip(a in limb()) { + assert_eq!(a, Limb::from_be_bytes(a.to_be_bytes())); + assert_eq!(a, Limb::from_le_bytes(a.to_le_bytes())); + } + } + + proptest! { + #[test] + fn reverse(a in limb()) { + let mut bytes = a.to_be_bytes(); + bytes.reverse(); + assert_eq!(a, Limb::from_le_bytes(bytes)); + + let mut bytes = a.to_le_bytes(); + bytes.reverse(); + assert_eq!(a, Limb::from_be_bytes(bytes)); + } + } +} diff --git a/vendor/crypto-bigint/src/limb/from.rs b/vendor/crypto-bigint/src/limb/from.rs new file mode 100644 index 0000000..aa64992 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/from.rs @@ -0,0 +1,74 @@ +//! `From`-like conversions for [`Limb`]. + +use super::{Limb, WideWord, Word}; + +impl Limb { + /// Create a [`Limb`] from a `u8` integer (const-friendly) + // TODO(tarcieri): replace with `const impl From<u8>` when stable + pub const fn from_u8(n: u8) -> Self { + Limb(n as Word) + } + + /// Create a [`Limb`] from a `u16` integer (const-friendly) + // TODO(tarcieri): replace with `const impl From<u16>` when stable + pub const fn from_u16(n: u16) -> Self { + Limb(n as Word) + } + + /// Create a [`Limb`] from a `u32` integer (const-friendly) + // TODO(tarcieri): replace with `const impl From<u32>` when stable + pub const fn from_u32(n: u32) -> Self { + #[allow(trivial_numeric_casts)] + Limb(n as Word) + } + + /// Create a [`Limb`] from a `u64` integer (const-friendly) + // TODO(tarcieri): replace with `const impl From<u64>` when stable + #[cfg(target_pointer_width = "64")] + pub const fn from_u64(n: u64) -> Self { + Limb(n) + } +} + +impl From<u8> for Limb { + #[inline] + fn from(n: u8) -> Limb { + Limb(n.into()) + } +} + +impl From<u16> for Limb { + #[inline] + fn from(n: u16) -> Limb { + Limb(n.into()) + } +} + +impl From<u32> for Limb { + #[inline] + fn from(n: u32) -> Limb { + Limb(n.into()) + } +} + +#[cfg(target_pointer_width = "64")] +impl From<u64> for Limb { + #[inline] + fn from(n: u64) -> Limb { + Limb(n) + } +} + +impl From<Limb> for Word { + #[inline] + fn from(limb: Limb) -> Word { + limb.0 + } +} + +impl From<Limb> for WideWord { + #[inline] + fn from(limb: Limb) -> WideWord { + limb.0.into() + } +} diff --git a/vendor/crypto-bigint/src/limb/mul.rs b/vendor/crypto-bigint/src/limb/mul.rs new file mode 100644 index 0000000..7f8b084 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/mul.rs @@ -0,0 +1,195 @@ +//! Limb multiplication + +use crate::{Checked, CheckedMul, Limb, WideWord, Word, Wrapping, Zero}; +use core::ops::{Mul, MulAssign}; +use subtle::CtOption; + +impl Limb { + /// Computes `self + (b * c) + carry`, returning the result along with the new carry. + #[inline(always)] + pub const fn mac(self, b: Limb, c: Limb, carry: Limb) -> (Limb, Limb) { + let a = self.0 as WideWord; + let b = b.0 as WideWord; + let c = c.0 as WideWord; + let carry = carry.0 as WideWord; + let ret = a + (b * c) + carry; + (Limb(ret as Word), Limb((ret >> Self::BITS) as Word)) + } + + /// Perform saturating multiplication. + #[inline] + pub const fn saturating_mul(&self, rhs: Self) -> Self { + Limb(self.0.saturating_mul(rhs.0)) + } + + /// Perform wrapping multiplication, discarding overflow. + #[inline(always)] + pub const fn wrapping_mul(&self, rhs: Self) -> Self { + Limb(self.0.wrapping_mul(rhs.0)) + } + + /// Compute "wide" multiplication, with a product twice the size of the input. + pub(crate) const fn mul_wide(&self, rhs: Self) -> WideWord { + (self.0 as WideWord) * (rhs.0 as WideWord) + } +} + +impl CheckedMul for Limb { + type Output = Self; + + #[inline] + fn checked_mul(&self, rhs: Self) -> CtOption<Self> { + let result = self.mul_wide(rhs); + let overflow = Limb((result >> Self::BITS) as Word); + CtOption::new(Limb(result as Word), overflow.is_zero()) + } +} + +impl Mul for Wrapping<Limb> { + type Output = Self; + + fn mul(self, rhs: Self) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_mul(rhs.0)) + } +} + +impl Mul<&Wrapping<Limb>> for Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn mul(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_mul(rhs.0)) + } +} + +impl Mul<Wrapping<Limb>> for &Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn mul(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_mul(rhs.0)) + } +} + +impl Mul<&Wrapping<Limb>> for &Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn mul(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_mul(rhs.0)) + } +} + +impl MulAssign for Wrapping<Limb> { + fn mul_assign(&mut self, other: Self) { + *self = *self * other; + } +} + +impl MulAssign<&Wrapping<Limb>> for Wrapping<Limb> { + fn mul_assign(&mut self, other: &Self) { + *self = *self * other; + } +} + +impl Mul for Checked<Limb> { + type Output = Self; + + fn mul(self, rhs: Self) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(rhs))), + ) + } +} + +impl Mul<&Checked<Limb>> for Checked<Limb> { + type Output = Checked<Limb>; + + fn mul(self, rhs: &Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(rhs))), + ) + } +} + +impl Mul<Checked<Limb>> for &Checked<Limb> { + type Output = Checked<Limb>; + + fn mul(self, rhs: Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(rhs))), + ) + } +} + +impl Mul<&Checked<Limb>> for &Checked<Limb> { + type Output = Checked<Limb>; + + fn mul(self, rhs: &Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_mul(rhs))), + ) + } +} + +impl MulAssign for Checked<Limb> { + fn mul_assign(&mut self, other: Self) { + *self = *self * other; + } +} + +impl MulAssign<&Checked<Limb>> for Checked<Limb> { + fn mul_assign(&mut self, other: &Self) { + *self = *self * other; + } +} + +#[cfg(test)] +mod tests { + use super::{CheckedMul, Limb, WideWord}; + + #[test] + fn mul_wide_zero_and_one() { + assert_eq!(Limb::ZERO.mul_wide(Limb::ZERO), 0); + assert_eq!(Limb::ZERO.mul_wide(Limb::ONE), 0); + assert_eq!(Limb::ONE.mul_wide(Limb::ZERO), 0); + assert_eq!(Limb::ONE.mul_wide(Limb::ONE), 1); + } + + #[test] + fn mul_wide() { + let primes: &[u32] = &[3, 5, 17, 257, 65537]; + + for &a_int in primes { + for &b_int in primes { + let actual = Limb::from_u32(a_int).mul_wide(Limb::from_u32(b_int)); + let expected = a_int as WideWord * b_int as WideWord; + assert_eq!(actual, expected); + } + } + } + + #[test] + #[cfg(target_pointer_width = "32")] + fn checked_mul_ok() { + let n = Limb::from_u16(0xffff); + assert_eq!(n.checked_mul(n).unwrap(), Limb::from_u32(0xfffe_0001)); + } + + #[test] + #[cfg(target_pointer_width = "64")] + fn checked_mul_ok() { + let n = Limb::from_u32(0xffff_ffff); + assert_eq!( + n.checked_mul(n).unwrap(), + Limb::from_u64(0xffff_fffe_0000_0001) + ); + } + + #[test] + fn checked_mul_overflow() { + let n = Limb::MAX; + assert!(bool::from(n.checked_mul(n).is_none())); + } +} diff --git a/vendor/crypto-bigint/src/limb/neg.rs b/vendor/crypto-bigint/src/limb/neg.rs new file mode 100644 index 0000000..b658bb9 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/neg.rs @@ -0,0 +1,20 @@ +//! Limb negation + +use crate::{Limb, Wrapping}; +use core::ops::Neg; + +impl Neg for Wrapping<Limb> { + type Output = Self; + + fn neg(self) -> Self::Output { + Self(self.0.wrapping_neg()) + } +} + +impl Limb { + /// Perform wrapping negation. + #[inline(always)] + pub const fn wrapping_neg(self) -> Self { + Limb(self.0.wrapping_neg()) + } +} diff --git a/vendor/crypto-bigint/src/limb/rand.rs b/vendor/crypto-bigint/src/limb/rand.rs new file mode 100644 index 0000000..4347168 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/rand.rs @@ -0,0 +1,38 @@ +//! Random number generator support + +use super::Limb; +use crate::{Encoding, NonZero, Random, RandomMod}; +use rand_core::CryptoRngCore; +use subtle::ConstantTimeLess; + +impl Random for Limb { + #[cfg(target_pointer_width = "32")] + fn random(rng: &mut impl CryptoRngCore) -> Self { + Self(rng.next_u32()) + } + + #[cfg(target_pointer_width = "64")] + fn random(rng: &mut impl CryptoRngCore) -> Self { + Self(rng.next_u64()) + } +} + +impl RandomMod for Limb { + fn random_mod(rng: &mut impl CryptoRngCore, modulus: &NonZero<Self>) -> Self { + let mut bytes = <Self as Encoding>::Repr::default(); + + let n_bits = modulus.bits(); + let n_bytes = (n_bits + 7) / 8; + let mask = 0xff >> (8 * n_bytes - n_bits); + + loop { + rng.fill_bytes(&mut bytes[..n_bytes]); + bytes[n_bytes - 1] &= mask; + + let n = Limb::from_le_bytes(bytes); + if n.ct_lt(modulus).into() { + return n; + } + } + } +} diff --git a/vendor/crypto-bigint/src/limb/shl.rs b/vendor/crypto-bigint/src/limb/shl.rs new file mode 100644 index 0000000..88e37f0 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/shl.rs @@ -0,0 +1,74 @@ +//! Limb left bitshift + +use crate::{Limb, Word}; +use core::ops::{Shl, ShlAssign}; + +impl Limb { + /// Computes `self << rhs`. + /// Panics if `rhs` overflows `Limb::BITS`. + #[inline(always)] + pub const fn shl(self, rhs: Self) -> Self { + Limb(self.0 << rhs.0) + } +} + +impl Shl for Limb { + type Output = Self; + + #[inline(always)] + fn shl(self, rhs: Self) -> Self::Output { + self.shl(rhs) + } +} + +impl Shl<usize> for Limb { + type Output = Self; + + #[inline(always)] + fn shl(self, rhs: usize) -> Self::Output { + self.shl(Limb(rhs as Word)) + } +} + +impl ShlAssign for Limb { + #[inline(always)] + fn shl_assign(&mut self, other: Self) { + *self = self.shl(other); + } +} + +impl ShlAssign<usize> for Limb { + #[inline(always)] + fn shl_assign(&mut self, other: usize) { + *self = self.shl(Limb(other as Word)); + } +} + +#[cfg(test)] +mod tests { + use crate::Limb; + + #[test] + fn shl1() { + assert_eq!(Limb(1) << 1, Limb(2)); + } + + #[test] + fn shl2() { + assert_eq!(Limb(1) << 2, Limb(4)); + } + + #[test] + fn shl_assign1() { + let mut l = Limb(1); + l <<= 1; + assert_eq!(l, Limb(2)); + } + + #[test] + fn shl_assign2() { + let mut l = Limb(1); + l <<= 2; + assert_eq!(l, Limb(4)); + } +} diff --git a/vendor/crypto-bigint/src/limb/shr.rs b/vendor/crypto-bigint/src/limb/shr.rs new file mode 100644 index 0000000..7c422e0 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/shr.rs @@ -0,0 +1,74 @@ +//! Limb right bitshift + +use crate::{Limb, Word}; +use core::ops::{Shr, ShrAssign}; + +impl Limb { + /// Computes `self >> rhs`. + /// Panics if `rhs` overflows `Limb::BITS`. + #[inline(always)] + pub const fn shr(self, rhs: Self) -> Self { + Limb(self.0 >> rhs.0) + } +} + +impl Shr for Limb { + type Output = Self; + + #[inline(always)] + fn shr(self, rhs: Self) -> Self::Output { + self.shr(rhs) + } +} + +impl Shr<usize> for Limb { + type Output = Self; + + #[inline(always)] + fn shr(self, rhs: usize) -> Self::Output { + self.shr(Limb(rhs as Word)) + } +} + +impl ShrAssign for Limb { + #[inline(always)] + fn shr_assign(&mut self, other: Self) { + *self = self.shr(other); + } +} + +impl ShrAssign<usize> for Limb { + #[inline(always)] + fn shr_assign(&mut self, other: usize) { + *self = self.shr(Limb(other as Word)); + } +} + +#[cfg(test)] +mod tests { + use crate::Limb; + + #[test] + fn shr1() { + assert_eq!(Limb(2) >> 1, Limb(1)); + } + + #[test] + fn shr2() { + assert_eq!(Limb(16) >> 2, Limb(4)); + } + + #[test] + fn shr_assign1() { + let mut l = Limb::ONE; + l >>= 1; + assert_eq!(l, Limb::ZERO); + } + + #[test] + fn shr_assign2() { + let mut l = Limb(32); + l >>= 2; + assert_eq!(l, Limb(8)); + } +} diff --git a/vendor/crypto-bigint/src/limb/sub.rs b/vendor/crypto-bigint/src/limb/sub.rs new file mode 100644 index 0000000..0fc7a4a --- /dev/null +++ b/vendor/crypto-bigint/src/limb/sub.rs @@ -0,0 +1,182 @@ +//! Limb subtraction + +use crate::{Checked, CheckedSub, Limb, WideWord, Word, Wrapping, Zero}; +use core::ops::{Sub, SubAssign}; +use subtle::CtOption; + +impl Limb { + /// Computes `self - (rhs + borrow)`, returning the result along with the new borrow. + #[inline(always)] + pub const fn sbb(self, rhs: Limb, borrow: Limb) -> (Limb, Limb) { + let a = self.0 as WideWord; + let b = rhs.0 as WideWord; + let borrow = (borrow.0 >> (Self::BITS - 1)) as WideWord; + let ret = a.wrapping_sub(b + borrow); + (Limb(ret as Word), Limb((ret >> Self::BITS) as Word)) + } + + /// Perform saturating subtraction. + #[inline] + pub const fn saturating_sub(&self, rhs: Self) -> Self { + Limb(self.0.saturating_sub(rhs.0)) + } + + /// Perform wrapping subtraction, discarding underflow and wrapping around + /// the boundary of the type. + #[inline(always)] + pub const fn wrapping_sub(&self, rhs: Self) -> Self { + Limb(self.0.wrapping_sub(rhs.0)) + } +} + +impl CheckedSub for Limb { + type Output = Self; + + #[inline] + fn checked_sub(&self, rhs: Self) -> CtOption<Self> { + let (result, underflow) = self.sbb(rhs, Limb::ZERO); + CtOption::new(result, underflow.is_zero()) + } +} + +impl Sub for Wrapping<Limb> { + type Output = Self; + + fn sub(self, rhs: Self) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_sub(rhs.0)) + } +} + +impl Sub<&Wrapping<Limb>> for Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn sub(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_sub(rhs.0)) + } +} + +impl Sub<Wrapping<Limb>> for &Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn sub(self, rhs: Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_sub(rhs.0)) + } +} + +impl Sub<&Wrapping<Limb>> for &Wrapping<Limb> { + type Output = Wrapping<Limb>; + + fn sub(self, rhs: &Wrapping<Limb>) -> Wrapping<Limb> { + Wrapping(self.0.wrapping_sub(rhs.0)) + } +} + +impl SubAssign for Wrapping<Limb> { + fn sub_assign(&mut self, other: Self) { + *self = *self - other; + } +} + +impl SubAssign<&Wrapping<Limb>> for Wrapping<Limb> { + fn sub_assign(&mut self, other: &Self) { + *self = *self - other; + } +} + +impl Sub for Checked<Limb> { + type Output = Self; + + fn sub(self, rhs: Self) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(rhs))), + ) + } +} + +impl Sub<&Checked<Limb>> for Checked<Limb> { + type Output = Checked<Limb>; + + fn sub(self, rhs: &Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(rhs))), + ) + } +} + +impl Sub<Checked<Limb>> for &Checked<Limb> { + type Output = Checked<Limb>; + + fn sub(self, rhs: Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(rhs))), + ) + } +} + +impl Sub<&Checked<Limb>> for &Checked<Limb> { + type Output = Checked<Limb>; + + fn sub(self, rhs: &Checked<Limb>) -> Checked<Limb> { + Checked( + self.0 + .and_then(|lhs| rhs.0.and_then(|rhs| lhs.checked_sub(rhs))), + ) + } +} + +impl SubAssign for Checked<Limb> { + fn sub_assign(&mut self, other: Self) { + *self = *self - other; + } +} + +impl SubAssign<&Checked<Limb>> for Checked<Limb> { + fn sub_assign(&mut self, other: &Self) { + *self = *self - other; + } +} + +#[cfg(test)] +mod tests { + use crate::{CheckedSub, Limb}; + + #[test] + fn sbb_no_borrow() { + let (res, borrow) = Limb::ONE.sbb(Limb::ONE, Limb::ZERO); + assert_eq!(res, Limb::ZERO); + assert_eq!(borrow, Limb::ZERO); + } + + #[test] + fn sbb_with_borrow() { + let (res, borrow) = Limb::ZERO.sbb(Limb::ONE, Limb::ZERO); + + assert_eq!(res, Limb::MAX); + assert_eq!(borrow, Limb::MAX); + } + + #[test] + fn wrapping_sub_no_borrow() { + assert_eq!(Limb::ONE.wrapping_sub(Limb::ONE), Limb::ZERO); + } + + #[test] + fn wrapping_sub_with_borrow() { + assert_eq!(Limb::ZERO.wrapping_sub(Limb::ONE), Limb::MAX); + } + + #[test] + fn checked_sub_ok() { + let result = Limb::ONE.checked_sub(Limb::ONE); + assert_eq!(result.unwrap(), Limb::ZERO); + } + + #[test] + fn checked_sub_overflow() { + let result = Limb::ZERO.checked_sub(Limb::ONE); + assert!(!bool::from(result.is_some())); + } +} |