Skip to main content

bouncycastle_rng/
lib.rs

1//! RNG objects for cryptographically secure random number generation.
2//!
3//! This crate provides the implementations of the deterministic random bit generator (DRBG) algorithms
4//! which, together with a strong entropy source, form the basis of cryptographic random number generation.
5//!
6//! Here is the basic way to get some random bytes:
7//!
8//! ```
9//! use bouncycastle_core::traits::RNG;
10//! use bouncycastle_rng as rng;
11//!
12//! let random_bytes = rng::DefaultRNG::default().next_bytes(32);
13//! ```
14//! This is secure because `::default()` seeds the RNG from the OS, configured for general use.
15//!
16//! **WARNING: most people should stop reading here and should not attempt to modify the internals of RNGs.
17//! This crate contains dragons and other horrible things. ๐Ÿ‰๐Ÿ๐Ÿœ**
18//!
19//! # ๐Ÿšจ๐Ÿšจ๐ŸšจSecurity Warning ๐Ÿšจ๐Ÿšจ๐Ÿšจ
20//!
21//! Misuse of the objects in this crate can lead to output which may appear random, but
22//! is in fact completely deterministic (ie multiple runs of your application will give the same outputs)
23//! and will therefore compromise any cryptographic operation built on top of those outputs.
24//! You should only be here if your application requires direct control over configuring the internals of the DRBG.
25//!
26//! This crate contains the [`Sp80090ADrbg`] trait, which is intentionally defined here and not in [`bouncycastle_core::traits`]
27//! since misuse of [`Sp80090ADrbg::instantiate`] can completely undermine the security of your entire
28//! cryptographic application.
29
30#![forbid(unsafe_code)]
31#![forbid(missing_docs)]
32
33use crate::hash_drbg80090a::{
34    HashDRBG80090A, HashDRBG80090AParams_SHA256, HashDRBG80090AParams_SHA512,
35};
36use bouncycastle_core::errors::RNGError;
37use bouncycastle_core::key_material::KeyMaterialTrait;
38use bouncycastle_core::traits::SecurityStrength;
39
40// needed for docs
41#[allow(unused_imports)]
42use bouncycastle_core::key_material::KeyType;
43// end doc-only imports
44
45pub mod hash_drbg80090a;
46
47/*** String constants ***/
48///
49pub const HASH_DRBG_SHA256_NAME: &str = "HashDRBG-SHA256";
50///
51pub const HASH_DRBG_SHA512_NAME: &str = "HashDRBG-SHA512";
52
53/*** pub types ***/
54/// Public type for HashDRBG using SHA256.
55#[allow(non_camel_case_types)]
56pub type HashDRBG_SHA256 = HashDRBG80090A<HashDRBG80090AParams_SHA256>;
57/// Public type for HashDRBG using SHA512.
58#[allow(non_camel_case_types)]
59pub type HashDRBG_SHA512 = HashDRBG80090A<HashDRBG80090AParams_SHA512>;
60
61/*** Defaults ***/
62/// The library's default RNG.
63pub type DefaultRNG = HashDRBG_SHA512;
64/// The library's default RNG at the 128-bit security level.
65pub type Default128BitRNG = HashDRBG_SHA256;
66/// The library's default RNG at the 256-bit security level.
67pub type Default256BitRNG = HashDRBG_SHA512;
68
69/// Implements the five functions specified in SP 800-90A section 7.4 are 
70/// - instantate, 
71/// - generate, 
72/// - reseed, 
73/// - uninstantiate, and 
74/// - health_test.
75/// Note: this function implements Rust's Drop on the sensitive working state in place of the explicit 
76/// Uninstantiate function listed in SP 800-90Ar1.
77pub trait Sp80090ADrbg {
78    /// The input KeyMaterial must be of type [`KeyType::Seed`].
79    ///
80    /// """
81    /// 8.6.3 Entropy Requirements for the Entropy Input
82    /// The entropy input shall have entropy that is equal to or greater than the security strength of the
83    /// instantiation. Additional entropy may be provided in the nonce or the optional personalization
84    /// string during instantiation, or in the additional input during reseeding and generation, but this is
85    /// not required and does not increase the โ€œofficialโ€ security strength of the DRBG instantiation that
86    /// is recorded in the internal state.
87    ///
88    /// 8.6.4 Seed Length
89    /// The minimum length of the seed depends on the DRBG mechanism and the security strength
90    /// required by the consuming application, but shall be at least the number of bits of entropy
91    /// required.
92    /// """
93    ///
94    /// This function takes ownership of the seed KeyMaterial object, 
95    /// to reduce the likelihood of its reuse in a second function call.
96    ///
97    /// There is no entropy requirement on the nonce, but it is expected as a KeyMaterial so that it
98    /// benefits from the secure erasure and logging protections in the KeyMaterial object.
99    fn instantiate(
100        &mut self,
101        prediction_resistance: bool,
102        seed: impl KeyMaterialTrait,
103        nonce: &impl KeyMaterialTrait,
104        personalization_string: &[u8],
105        security_strength: SecurityStrength,
106    ) -> Result<(), RNGError>;
107
108    /// Reseeds the DRBG with the provided seed.
109    /// TODO: this needs to be redesigned to take some sort of EntropySource object that will work well 
110    // with DRBGs that require frequent reseeding.
111    fn reseed<K: KeyMaterialTrait + ?Sized>(
112        &mut self,
113        seed: &K,
114        additional_input: &[u8],
115    ) -> Result<(), RNGError>;
116
117    /// Note that for a calling application to be in compliance with SP 800-90A, this requirement
118    /// from section 8.4 must be met:
119    ///    "The pseudorandom bits returned from a DRBG shall not be used for any
120    /// application that requires a higher security strength than the DRBG is instantiated to support. The
121    /// security strength provided in these returned bits is the minimum of the security strength
122    /// supported by the DRBG and the length of the bit string returned"
123    ///
124    /// As required by SP 800-90A section 8.4, `len` cannot exceed the initialized [`SecurityStrength`]
125    /// of this instance, although multiple calls to this function can be made, in which case it is the
126    /// application's responsibility to track that it is not expecting more entropy than the [`SecurityStrength`]
127    /// to which this instance was instantiated. For example, extracting two 128-bit values from an instance
128    /// instantiated to [`SecurityStrength::_128bit`] and then combining tem to form an AES-256 key would likely
129    /// not pass FIPS certification.
130    ///
131    /// Throws a [`RNGError::InsufficientSeedEntropy`] if `len` exceeds [`SecurityStrength`].
132    fn generate(&mut self, additional_input: &[u8], len: usize) -> Result<Vec<u8>, RNGError>;
133
134    /// As per [`Sp80090ADrbg::generate`], but writes to the provided output slice.
135    /// The output slice is filled.
136    /// Throws a [`RNGError::InsufficientSeedEntropy`] if the length of the output slice exceeds [`SecurityStrength`].
137    /// Retruns the number of bits output.
138    fn generate_out(&mut self, additional_input: &[u8], out: &mut [u8]) -> Result<usize, RNGError>;
139
140    /// As per [`Sp80090ADrbg::generate`], but writes to the provided KeyMaterial.
141    /// The output [`KeyMaterialTrait`] is filled to capacity.
142    /// Throws a [`RNGError::InsufficientSeedEntropy`] if the capacity of the output KeyMaterial exceeds [`SecurityStrength`].
143    /// Retruns the number of bits output.
144    fn generate_keymaterial_out<K: KeyMaterialTrait + ?Sized>(
145        &mut self,
146        additional_input: &[u8],
147        out: &mut K,
148    ) -> Result<usize, RNGError>;
149
150    // TODO -- implement FIPS health tests
151    // fn health_test(&mut self) -> Result<bool, RNGError>;
152}