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