summaryrefslogtreecommitdiffstats
path: root/vendor/crypto-bigint/src/uint/modular/reduction.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/crypto-bigint/src/uint/modular/reduction.rs')
-rw-r--r--vendor/crypto-bigint/src/uint/modular/reduction.rs53
1 files changed, 26 insertions, 27 deletions
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)
}