diff options
Diffstat (limited to 'vendor/crypto-bigint/src/uint/rand.rs')
-rw-r--r-- | vendor/crypto-bigint/src/uint/rand.rs | 45 |
1 files changed, 15 insertions, 30 deletions
diff --git a/vendor/crypto-bigint/src/uint/rand.rs b/vendor/crypto-bigint/src/uint/rand.rs index df551c71b..e283e2246 100644 --- a/vendor/crypto-bigint/src/uint/rand.rs +++ b/vendor/crypto-bigint/src/uint/rand.rs @@ -1,14 +1,13 @@ //! Random number generator support -use super::UInt; +use super::Uint; use crate::{Limb, NonZero, Random, RandomMod}; -use rand_core::{CryptoRng, RngCore}; +use rand_core::CryptoRngCore; use subtle::ConstantTimeLess; -#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] -impl<const LIMBS: usize> Random for UInt<LIMBS> { - /// Generate a cryptographically secure random [`UInt`]. - fn random(mut rng: impl CryptoRng + RngCore) -> Self { +impl<const LIMBS: usize> Random for Uint<LIMBS> { + /// Generate a cryptographically secure random [`Uint`]. + fn random(mut rng: &mut impl CryptoRngCore) -> Self { let mut limbs = [Limb::ZERO; LIMBS]; for limb in &mut limbs { @@ -19,44 +18,30 @@ impl<const LIMBS: usize> Random for UInt<LIMBS> { } } -#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))] -impl<const LIMBS: usize> RandomMod for UInt<LIMBS> { - /// Generate a cryptographically secure random [`UInt`] which is less than +impl<const LIMBS: usize> RandomMod for Uint<LIMBS> { + /// Generate a cryptographically secure random [`Uint`] which is less than /// a given `modulus`. /// /// This function uses rejection sampling, a method which produces an /// unbiased distribution of in-range values provided the underlying - /// [`CryptoRng`] is unbiased, but runs in variable-time. + /// CSRNG is unbiased, but runs in variable-time. /// /// The variable-time nature of the algorithm should not pose a security /// issue so long as the underlying random number generator is truly a - /// [`CryptoRng`], where previous outputs are unrelated to subsequent + /// CSRNG, where previous outputs are unrelated to subsequent /// outputs and do not reveal information about the RNG's internal state. - fn random_mod(mut rng: impl CryptoRng + RngCore, modulus: &NonZero<Self>) -> Self { + fn random_mod(mut rng: &mut impl CryptoRngCore, modulus: &NonZero<Self>) -> Self { let mut n = Self::ZERO; - // TODO(tarcieri): use `div_ceil` when available - // See: https://github.com/rust-lang/rust/issues/88581 - let mut n_limbs = modulus.bits_vartime() / Limb::BIT_SIZE; - if n_limbs < LIMBS { - n_limbs += 1; - } - - // Compute the highest limb of `modulus` as a `NonZero`. - // Add one to ensure `Limb::random_mod` returns values inclusive of this limb. - let modulus_hi = - NonZero::new(modulus.limbs[n_limbs.saturating_sub(1)].saturating_add(Limb::ONE)) - .unwrap(); // Always at least one due to `saturating_add` + let n_bits = modulus.as_ref().bits_vartime(); + let n_limbs = (n_bits + Limb::BITS - 1) / Limb::BITS; + let mask = Limb::MAX >> (Limb::BITS * n_limbs - n_bits); loop { for i in 0..n_limbs { - n.limbs[i] = if (i + 1 == n_limbs) && (*modulus_hi != Limb::MAX) { - // Highest limb - Limb::random_mod(&mut rng, &modulus_hi) - } else { - Limb::random(&mut rng) - } + n.limbs[i] = Limb::random(&mut rng); } + n.limbs[n_limbs - 1] = n.limbs[n_limbs - 1] & mask; if n.ct_lt(modulus).into() { return n; |