crypto_bigint_syncless/limb/
rand.rs

1//! Random number generator support
2
3use super::Limb;
4use crate::{Encoding, NonZero, Random, RandomMod};
5use rand_core::TryRngCore;
6use subtle::ConstantTimeLess;
7
8impl Random for Limb {
9    fn try_random<R: TryRngCore + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
10        #[cfg(target_pointer_width = "32")]
11        let val = rng.try_next_u32()?;
12        #[cfg(target_pointer_width = "64")]
13        let val = rng.try_next_u64()?;
14
15        Ok(Self(val))
16    }
17}
18
19impl RandomMod for Limb {
20    fn try_random_mod<R: TryRngCore + ?Sized>(
21        rng: &mut R,
22        modulus: &NonZero<Self>,
23    ) -> Result<Self, R::Error> {
24        let mut bytes = <Self as Encoding>::Repr::default();
25
26        let n_bits = modulus.bits() as usize;
27        let n_bytes = n_bits.div_ceil(8);
28        let mask = 0xffu8 >> (8 * n_bytes - n_bits);
29
30        loop {
31            rng.try_fill_bytes(&mut bytes[..n_bytes])?;
32            bytes[n_bytes - 1] &= mask;
33
34            let n = Limb::from_le_bytes(bytes);
35            if n.ct_lt(modulus).into() {
36                return Ok(n);
37            }
38        }
39    }
40}