crypto_bigint/limb/
rand.rs

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