Skip to main content

bouncycastle_factory/
rng_factory.rs

1//! RNG factory for creating instances of algorithms that implement the [RNG] trait.
2//!
3//! As with all Factory objects, this implements constructions from strings and defaults, and
4//! returns a [RNGFactory] object which itself implements the [RNG] trait as a pass-through to the underlying algorithm.
5//!
6//! A quick note about cryptographic random number generators (RNGs), which are also sometimes
7//! cryptographically secure random number generators (CSRNGs) or pseudorandom number generators (PRNGS)).
8//! As the last name suggests, they are based on deterministic permutation functions called
9//! deterministic random bit generators (DRBGs), which, always produce the same output for the same seed value.
10//! Meaning that they are only as cryptographically strong and unique as their seed.
11//!
12//! All RNGs exposed through the [RNGFactory] are seeded from the underlying operating system's entropy pool,
13//! and therefore should be sufficient for most cryptographic use. Additional entropy can be added via the
14//! [RNG::add_seed_keymaterial] function.
15//!
16//! Applications that require direct control over the seed material, for example in order to deterministically
17//! re-generate a key stream from a private seed, or in order to use a specific approved entropy source should
18//! instead use the objects in the [rng] crate, which expose more instantiation functionality.
19//!
20//!
21//! Example usage:
22//! ```
23//! use factory::AlgorithmFactory;
24//! use core_interface::traits::Hash;
25//!
26//! let data: &[u8] = b"Hello, world!";
27//!
28//! let h = factory::hash_factory::HashFactory::new(sha3::SHA3_256_NAME).unwrap();
29//! let output: Vec<u8> = h.hash(data);
30//! ```
31//! You can equivalently invoke this by string instead of using the constant:
32//!
33//! ```
34//! use factory::AlgorithmFactory;
35//! use core_interface::traits::Hash;
36//!
37//! let data: &[u8] = b"Hello, world!";
38//!
39//! let h = factory::hash_factory::HashFactory::new("SHA3-256").unwrap();
40//! let output: Vec<u8> = h.hash(data);
41//! ```
42
43use bouncycastle_core_interface::errors::RNGError;
44use bouncycastle_core_interface::traits::{KeyMaterial, SecurityStrength, RNG};
45use crate::{AlgorithmFactory, FactoryError};
46use crate::{DEFAULT, DEFAULT_128_BIT, DEFAULT_256_BIT};
47
48use bouncycastle_rng as rng;
49use bouncycastle_rng::{HASH_DRBG_SHA256_NAME, HASH_DRBG_SHA512_NAME};
50
51/*** Defaults ***/
52pub const DEFAULT_DRBG_NAME: &str = HASH_DRBG_SHA512_NAME;
53pub const DEFAULT_128BIT_DRBG_NAME: &str = HASH_DRBG_SHA256_NAME;
54pub const DEFAULT_256BIT_DRBG_NAME: &str = HASH_DRBG_SHA512_NAME;
55
56
57
58/// All members must impl RNG.
59pub enum RNGFactory {
60    #[allow(non_camel_case_types)]
61    HashDRBG_SHA256(rng::HashDRBG_SHA256),
62    #[allow(non_camel_case_types)]
63    HashDRBG_SHA512(rng::HashDRBG_SHA512),
64}
65
66impl Default for RNGFactory {
67    fn default() -> Self { Self::new(DEFAULT_DRBG_NAME).unwrap() }
68}
69
70impl AlgorithmFactory for RNGFactory {
71    fn default_128_bit() -> Self { Self::new(DEFAULT_128BIT_DRBG_NAME).unwrap() }
72    fn default_256_bit() -> Self { Self::new(DEFAULT_256BIT_DRBG_NAME).unwrap() }
73
74    fn new(alg_name: &str) -> Result<Self, FactoryError> {
75        match alg_name {
76            DEFAULT => Ok(Self::default()),
77            DEFAULT_128_BIT => Ok(Self::default_128_bit()),
78            DEFAULT_256_BIT => Ok(Self::default_256_bit()),
79            HASH_DRBG_SHA256_NAME => Ok(Self::HashDRBG_SHA256(rng::HashDRBG_SHA256::new_from_os())),
80            HASH_DRBG_SHA512_NAME => Ok(Self::HashDRBG_SHA512(rng::HashDRBG_SHA512::new_from_os())),
81            _ => Err(FactoryError::UnsupportedAlgorithm(format!("The algorithm: \"{}\" is not a known RNG", alg_name))),
82        }
83    }
84}
85
86impl RNG for RNGFactory {
87    fn add_seed_keymaterial(&mut self, additional_seed: impl KeyMaterial) -> Result<(), RNGError> {
88        match self {
89            Self::HashDRBG_SHA256(rng) => {rng.add_seed_keymaterial(additional_seed) },
90            Self::HashDRBG_SHA512(rng) => { rng.add_seed_keymaterial(additional_seed) },
91        }
92    }
93
94    fn next_int(&mut self) -> Result<u32, RNGError> {
95        match self {
96            Self::HashDRBG_SHA256(rng) => {rng.next_int() },
97            Self::HashDRBG_SHA512(rng) => { rng.next_int() },
98        }
99    }
100
101    fn next_bytes(&mut self, len: usize) -> Result<Vec<u8>, RNGError> {
102        match self {
103            Self::HashDRBG_SHA256(rng) => {rng.next_bytes(len) },
104            Self::HashDRBG_SHA512(rng) => { rng.next_bytes(len) },
105        }
106    }
107
108    fn next_bytes_out(&mut self, out: &mut [u8]) -> Result<usize, RNGError> {
109        match self {
110            Self::HashDRBG_SHA256(rng) => {rng.next_bytes_out(out) },
111            Self::HashDRBG_SHA512(rng) => { rng.next_bytes_out(out) },
112        }
113    }
114
115    fn fill_keymaterial_out(&mut self, out: &mut impl KeyMaterial) -> Result<usize, RNGError> {
116        match self {
117            Self::HashDRBG_SHA256(rng) => {rng.fill_keymaterial_out(out) },
118            Self::HashDRBG_SHA512(rng) => { rng.fill_keymaterial_out(out) },
119        }
120    }
121
122    fn security_strength(&self) -> SecurityStrength {
123        match self {
124            Self::HashDRBG_SHA256(rng) => {rng.security_strength() },
125            Self::HashDRBG_SHA512(rng) => { rng.security_strength() },
126        }
127    }
128}