diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/crypto-bigint/src/limb | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
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 | 8 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/cmp.rs | 176 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/encoding.rs | 67 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/from.rs | 76 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/mul.rs | 195 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/rand.rs | 45 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/shl.rs | 73 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/shr.rs | 73 | ||||
-rw-r--r-- | vendor/crypto-bigint/src/limb/sub.rs | 182 |
14 files changed, 1153 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 000000000..ddeda9e67 --- /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::BIT_SIZE) 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 000000000..3f0bfba0e --- /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 000000000..26676d598 --- /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 000000000..cafac18da --- /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 000000000..a50782293 --- /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 000000000..c470ae9ab --- /dev/null +++ b/vendor/crypto-bigint/src/limb/bits.rs @@ -0,0 +1,8 @@ +use super::Limb; + +impl Limb { + /// Calculate the number of bits needed to represent this number. + pub const fn bits(self) -> usize { + Limb::BIT_SIZE - (self.0.leading_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 000000000..76cc4b07c --- /dev/null +++ b/vendor/crypto-bigint/src/limb/cmp.rs @@ -0,0 +1,176 @@ +//! Limb comparisons + +use super::{Limb, SignedWord, WideSignedWord, Word, HI_BIT}; +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 + } + + /// Returns all 1's if `a`!=0 or 0 if `a`==0. + /// + /// Const-friendly: we can't yet use `subtle` in `const fn` contexts. + #[inline] + pub(crate) const fn is_nonzero(self) -> Word { + let inner = self.0 as SignedWord; + ((inner | inner.saturating_neg()) >> HI_BIT) as Word + } + + #[inline] + pub(crate) const fn ct_cmp(lhs: Self, rhs: Self) -> SignedWord { + let a = lhs.0 as WideSignedWord; + let b = rhs.0 as WideSignedWord; + let gt = ((b - a) >> Limb::BIT_SIZE) & 1; + let lt = ((a - b) >> Limb::BIT_SIZE) & 1 & !gt; + (gt as SignedWord) - (lt as SignedWord) + } +} + +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 000000000..39974b061 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/encoding.rs @@ -0,0 +1,67 @@ +//! Limb encoding + +use super::{Limb, Word}; +use crate::Encoding; + +impl Encoding for Limb { + const BIT_SIZE: usize = Self::BIT_SIZE; + const BYTE_SIZE: usize = Self::BYTE_SIZE; + + #[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 000000000..fd2765bc9 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/from.rs @@ -0,0 +1,76 @@ +//! `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")] + #[cfg_attr(docsrs, doc(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")] +#[cfg_attr(docsrs, doc(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 000000000..a342c6eae --- /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::BIT_SIZE) 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::BIT_SIZE) 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, 256, 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/rand.rs b/vendor/crypto-bigint/src/limb/rand.rs new file mode 100644 index 000000000..0bc8af31a --- /dev/null +++ b/vendor/crypto-bigint/src/limb/rand.rs @@ -0,0 +1,45 @@ +//! Random number generator support + +use super::Limb; +use crate::{Encoding, NonZero, Random, RandomMod}; +use rand_core::{CryptoRng, RngCore}; +use subtle::ConstantTimeLess; + +#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] +impl Random for Limb { + #[cfg(target_pointer_width = "32")] + fn random(mut rng: impl CryptoRng + RngCore) -> Self { + Self(rng.next_u32()) + } + + #[cfg(target_pointer_width = "64")] + fn random(mut rng: impl CryptoRng + RngCore) -> Self { + Self(rng.next_u64()) + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] +impl RandomMod for Limb { + fn random_mod(mut rng: impl CryptoRng + RngCore, modulus: &NonZero<Self>) -> Self { + let mut bytes = <Self as Encoding>::Repr::default(); + + // TODO(tarcieri): use `div_ceil` when available + // See: https://github.com/rust-lang/rust/issues/88581 + let mut n_bytes = modulus.bits() / 8; + + // Ensure the randomly generated value can always be larger than + // the modulus in order to ensure a uniform distribution + if n_bytes < Self::BYTE_SIZE { + n_bytes += 1; + } + + loop { + rng.fill_bytes(&mut bytes[..n_bytes]); + 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 000000000..c0003ddbb --- /dev/null +++ b/vendor/crypto-bigint/src/limb/shl.rs @@ -0,0 +1,73 @@ +//! Limb left bitshift + +use crate::{Limb, Word}; +use core::ops::{Shl, ShlAssign}; + +impl Limb { + /// Computes `self << rhs`. + #[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 000000000..29ee76353 --- /dev/null +++ b/vendor/crypto-bigint/src/limb/shr.rs @@ -0,0 +1,73 @@ +//! Limb right bitshift + +use crate::{Limb, Word}; +use core::ops::{Shr, ShrAssign}; + +impl Limb { + /// Computes `self >> rhs`. + #[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 000000000..1560a1b64 --- /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::BIT_SIZE - 1)) as WideWord; + let ret = a.wrapping_sub(b + borrow); + (Limb(ret as Word), Limb((ret >> Self::BIT_SIZE) 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())); + } +} |