summaryrefslogtreecommitdiffstats
path: root/vendor/crypto-bigint/src/uint/modular
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/crypto-bigint/src/uint/modular
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/crypto-bigint/src/uint/modular')
-rw-r--r--vendor/crypto-bigint/src/uint/modular/constant_mod.rs20
-rw-r--r--vendor/crypto-bigint/src/uint/modular/div_by_2.rs30
-rw-r--r--vendor/crypto-bigint/src/uint/modular/reduction.rs53
-rw-r--r--vendor/crypto-bigint/src/uint/modular/runtime_mod.rs33
4 files changed, 105 insertions, 31 deletions
diff --git a/vendor/crypto-bigint/src/uint/modular/constant_mod.rs b/vendor/crypto-bigint/src/uint/modular/constant_mod.rs
index f94e4c475..3e9b522ef 100644
--- a/vendor/crypto-bigint/src/uint/modular/constant_mod.rs
+++ b/vendor/crypto-bigint/src/uint/modular/constant_mod.rs
@@ -4,7 +4,7 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
use crate::{Limb, Uint, Zero};
-use super::{reduction::montgomery_reduction, Retrieve};
+use super::{div_by_2::div_by_2, reduction::montgomery_reduction, Retrieve};
#[cfg(feature = "rand_core")]
use crate::{rand_core::CryptoRngCore, NonZero, Random, RandomMod};
@@ -67,6 +67,12 @@ where
phantom: PhantomData<MOD>,
}
+#[cfg(feature = "zeroize")]
+impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> zeroize::DefaultIsZeroes
+ for Residue<MOD, LIMBS>
+{
+}
+
impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
/// The representation of 0 mod `MOD`.
pub const ZERO: Self = Self {
@@ -100,6 +106,18 @@ impl<MOD: ResidueParams<LIMBS>, const LIMBS: usize> Residue<MOD, LIMBS> {
MOD::MOD_NEG_INV,
)
}
+
+ /// Performs the modular division by 2, that is for given `x` returns `y`
+ /// such that `y * 2 = x mod p`. This means:
+ /// - if `x` is even, returns `x / 2`,
+ /// - if `x` is odd, returns `(x + p) / 2`
+ /// (since the modulus `p` in Montgomery form is always odd, this divides entirely).
+ pub fn div_by_2(&self) -> Self {
+ Self {
+ montgomery_form: div_by_2(&self.montgomery_form, &MOD::MODULUS),
+ phantom: PhantomData,
+ }
+ }
}
impl<MOD: ResidueParams<LIMBS> + Copy, const LIMBS: usize> ConditionallySelectable
diff --git a/vendor/crypto-bigint/src/uint/modular/div_by_2.rs b/vendor/crypto-bigint/src/uint/modular/div_by_2.rs
new file mode 100644
index 000000000..20c0a5d86
--- /dev/null
+++ b/vendor/crypto-bigint/src/uint/modular/div_by_2.rs
@@ -0,0 +1,30 @@
+use crate::Uint;
+
+pub(crate) fn div_by_2<const LIMBS: usize>(a: &Uint<LIMBS>, modulus: &Uint<LIMBS>) -> Uint<LIMBS> {
+ // We are looking for such `x` that `x * 2 = y mod modulus`,
+ // where the given `a = M(y)` is the Montgomery representation of some `y`.
+ // This means that in Montgomery representation it would still apply:
+ // `M(x) + M(x) = a mod modulus`.
+ // So we can just forget about Montgomery representation, and return whatever is
+ // `a` divided by 2, and this will be the Montgomery representation of `x`.
+ // (Which means that this function works regardless of whether `a`
+ // is in Montgomery representation or not, but the algorithm below
+ // does need `modulus` to be odd)
+
+ // Two possibilities:
+ // - if `a` is even, we can just divide by 2;
+ // - if `a` is odd, we divide `(a + modulus)` by 2.
+ // To stay within the modulus we open the parentheses turning it into `a / 2 + modulus / 2 + 1`
+ // ("+1" because both `a` and `modulus` are odd, we lose 0.5 in each integer division).
+ // This will not overflow, so we can just use wrapping operations.
+
+ let (half, is_odd) = a.shr_1();
+ let half_modulus = modulus.shr_vartime(1);
+
+ let if_even = half;
+ let if_odd = half
+ .wrapping_add(&half_modulus)
+ .wrapping_add(&Uint::<LIMBS>::ONE);
+
+ Uint::<LIMBS>::ct_select(&if_even, &if_odd, is_odd)
+}
diff --git a/vendor/crypto-bigint/src/uint/modular/reduction.rs b/vendor/crypto-bigint/src/uint/modular/reduction.rs
index d3543bf97..b206ae32f 100644
--- a/vendor/crypto-bigint/src/uint/modular/reduction.rs
+++ b/vendor/crypto-bigint/src/uint/modular/reduction.rs
@@ -1,4 +1,14 @@
-use crate::{CtChoice, Limb, Uint, WideWord, Word};
+use crate::{Limb, Uint, WideWord, Word};
+
+/// Returns `(hi, lo)` such that `hi * R + lo = x * y + z + w`.
+#[inline(always)]
+const fn muladdcarry(x: Word, y: Word, z: Word, w: Word) -> (Word, Word) {
+ let res = (x as WideWord)
+ .wrapping_mul(y as WideWord)
+ .wrapping_add(z as WideWord)
+ .wrapping_add(w as WideWord);
+ ((res >> Word::BITS) as Word, res as Word)
+}
/// Algorithm 14.32 in Handbook of Applied Cryptography <https://cacr.uwaterloo.ca/hac/about/chap14.pdf>
pub const fn montgomery_reduction<const LIMBS: usize>(
@@ -8,49 +18,38 @@ pub const fn montgomery_reduction<const LIMBS: usize>(
) -> Uint<LIMBS> {
let (mut lower, mut upper) = *lower_upper;
- let mut meta_carry: WideWord = 0;
+ let mut meta_carry = Limb(0);
+ let mut new_sum;
let mut i = 0;
while i < LIMBS {
- let u = (lower.limbs[i].0.wrapping_mul(mod_neg_inv.0)) as WideWord;
+ let u = lower.limbs[i].0.wrapping_mul(mod_neg_inv.0);
- let new_limb =
- (u * modulus.limbs[0].0 as WideWord).wrapping_add(lower.limbs[i].0 as WideWord);
- let mut carry = new_limb >> Word::BITS;
+ let (mut carry, _) = muladdcarry(u, modulus.limbs[0].0, lower.limbs[i].0, 0);
+ let mut new_limb;
let mut j = 1;
while j < (LIMBS - i) {
- let new_limb = (u * modulus.limbs[j].0 as WideWord)
- .wrapping_add(lower.limbs[i + j].0 as WideWord)
- .wrapping_add(carry);
- carry = new_limb >> Word::BITS;
- lower.limbs[i + j] = Limb(new_limb as Word);
-
+ (carry, new_limb) = muladdcarry(u, modulus.limbs[j].0, lower.limbs[i + j].0, carry);
+ lower.limbs[i + j] = Limb(new_limb);
j += 1;
}
while j < LIMBS {
- let new_limb = (u * modulus.limbs[j].0 as WideWord)
- .wrapping_add(upper.limbs[i + j - LIMBS].0 as WideWord)
- .wrapping_add(carry);
- carry = new_limb >> Word::BITS;
- upper.limbs[i + j - LIMBS] = Limb(new_limb as Word);
-
+ (carry, new_limb) =
+ muladdcarry(u, modulus.limbs[j].0, upper.limbs[i + j - LIMBS].0, carry);
+ upper.limbs[i + j - LIMBS] = Limb(new_limb);
j += 1;
}
- let new_sum = (upper.limbs[i].0 as WideWord)
- .wrapping_add(carry)
- .wrapping_add(meta_carry);
- meta_carry = new_sum >> Word::BITS;
- upper.limbs[i] = Limb(new_sum as Word);
+ (new_sum, meta_carry) = upper.limbs[i].adc(Limb(carry), meta_carry);
+ upper.limbs[i] = new_sum;
i += 1;
}
// Division is simply taking the upper half of the limbs
- // Final reduction (at this point, the value is at most 2 * modulus)
- let must_reduce = CtChoice::from_lsb(meta_carry as Word).or(Uint::ct_gt(modulus, &upper).not());
- upper = upper.wrapping_sub(&Uint::ct_select(&Uint::ZERO, modulus, must_reduce));
+ // Final reduction (at this point, the value is at most 2 * modulus,
+ // so `meta_carry` is either 0 or 1)
- upper
+ upper.sub_mod_with_carry(meta_carry, modulus, modulus)
}
diff --git a/vendor/crypto-bigint/src/uint/modular/runtime_mod.rs b/vendor/crypto-bigint/src/uint/modular/runtime_mod.rs
index 72f1094cf..84622d167 100644
--- a/vendor/crypto-bigint/src/uint/modular/runtime_mod.rs
+++ b/vendor/crypto-bigint/src/uint/modular/runtime_mod.rs
@@ -1,6 +1,6 @@
use crate::{Limb, Uint, Word};
-use super::{reduction::montgomery_reduction, Retrieve};
+use super::{div_by_2::div_by_2, reduction::montgomery_reduction, Retrieve};
/// Additions between residues with a modulus set at runtime
mod runtime_add;
@@ -33,11 +33,16 @@ pub struct DynResidueParams<const LIMBS: usize> {
impl<const LIMBS: usize> DynResidueParams<LIMBS> {
/// Instantiates a new set of `ResidueParams` representing the given `modulus`.
- pub fn new(modulus: &Uint<LIMBS>) -> Self {
+ pub const fn new(modulus: &Uint<LIMBS>) -> Self {
let r = Uint::MAX.const_rem(modulus).0.wrapping_add(&Uint::ONE);
let r2 = Uint::const_rem_wide(r.square_wide(), modulus).0;
+
+ // Since we are calculating the inverse modulo (Word::MAX+1),
+ // we can take the modulo right away and calculate the inverse of the first limb only.
+ let modulus_lo = Uint::<1>::from_words([modulus.limbs[0].0]);
let mod_neg_inv =
- Limb(Word::MIN.wrapping_sub(modulus.inv_mod2k(Word::BITS as usize).limbs[0].0));
+ Limb(Word::MIN.wrapping_sub(modulus_lo.inv_mod2k(Word::BITS as usize).limbs[0].0));
+
let r3 = montgomery_reduction(&r2.square_wide(), modulus, mod_neg_inv);
Self {
@@ -48,6 +53,11 @@ impl<const LIMBS: usize> DynResidueParams<LIMBS> {
mod_neg_inv,
}
}
+
+ /// Returns the modulus which was used to initialize these parameters.
+ pub const fn modulus(&self) -> &Uint<LIMBS> {
+ &self.modulus
+ }
}
/// A residue represented using `LIMBS` limbs. The odd modulus of this residue is set at runtime.
@@ -97,6 +107,23 @@ impl<const LIMBS: usize> DynResidue<LIMBS> {
residue_params,
}
}
+
+ /// Returns the parameter struct used to initialize this residue.
+ pub const fn params(&self) -> &DynResidueParams<LIMBS> {
+ &self.residue_params
+ }
+
+ /// Performs the modular division by 2, that is for given `x` returns `y`
+ /// such that `y * 2 = x mod p`. This means:
+ /// - if `x` is even, returns `x / 2`,
+ /// - if `x` is odd, returns `(x + p) / 2`
+ /// (since the modulus `p` in Montgomery form is always odd, this divides entirely).
+ pub fn div_by_2(&self) -> Self {
+ Self {
+ montgomery_form: div_by_2(&self.montgomery_form, &self.residue_params.modulus),
+ residue_params: self.residue_params,
+ }
+ }
}
impl<const LIMBS: usize> Retrieve for DynResidue<LIMBS> {