1#![forbid(unsafe_code)]
2
3extern crate alloc;
6
7pub mod rand_adapter;
9
10use alloc::vec::Vec;
11use core::{cmp::min, fmt};
12use getrandom::getrandom;
13use hmac::{Hmac, Mac};
14use sha2::Sha512;
15use subtle::ConstantTimeEq;
16use zeroize::{Zeroize, ZeroizeOnDrop};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum Error {
21 RequestTooLarge,
23 ReseedRequired,
25 EntropyUnavailable,
27 EntropyHealthFailed,
29}
30
31impl fmt::Display for Error {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "{:?}", self)
34 }
35}
36
37#[cfg(feature = "std")]
38impl std::error::Error for Error {}
39
40const DEFAULT_RESEED_INTERVAL: u64 = 1u64 << 48;
42const BLOCK_LEN: usize = 64;
43const MAX_REQUEST: usize = 65536; const DEFAULT_MAX_BYTES_BETWEEN_RESEED: u128 = 1u128 << 20;
45
46#[derive(Zeroize, ZeroizeOnDrop)]
48pub struct HmacDrbg {
49 k: [u8; BLOCK_LEN],
50 v: [u8; BLOCK_LEN],
51 reseed_counter: u64,
52 reseed_interval: u64,
53 generated_bytes: u128,
54 max_bytes_between_reseed: u128,
55 last_entropy: Vec<u8>,
56}
57
58impl HmacDrbg {
59 pub fn new(
61 entropy: &[u8],
62 nonce: &[u8],
63 personalization: Option<&[u8]>,
64 ) -> Result<Self, Error> {
65 Self::validate_entropy(entropy)?;
66
67 let mut seed = Vec::with_capacity(
68 entropy.len() + nonce.len() + personalization.map_or(0, |p| p.len()),
69 );
70 seed.extend_from_slice(entropy);
71 seed.extend_from_slice(nonce);
72 if let Some(pers) = personalization {
73 seed.extend_from_slice(pers);
74 }
75
76 let mut drbg = Self {
77 k: [0u8; BLOCK_LEN],
78 v: [0x01u8; BLOCK_LEN],
79 reseed_counter: 1,
80 reseed_interval: DEFAULT_RESEED_INTERVAL,
81 generated_bytes: 0,
82 max_bytes_between_reseed: DEFAULT_MAX_BYTES_BETWEEN_RESEED,
83 last_entropy: entropy.to_vec(),
84 };
85 drbg.update(Some(&seed));
86 seed.zeroize();
87 Ok(drbg)
88 }
89
90 pub fn from_os(personalization: Option<&[u8]>) -> Result<Self, Error> {
92 let mut entropy = [0u8; 48];
93 let mut nonce = [0u8; 16];
94 getrandom(&mut entropy).map_err(|_| Error::EntropyUnavailable)?;
95 getrandom(&mut nonce).map_err(|_| Error::EntropyUnavailable)?;
96 Self::validate_entropy(&nonce)?;
97 let drbg = Self::new(&entropy, &nonce, personalization)?;
98 entropy.zeroize();
99 nonce.zeroize();
100 Ok(drbg)
101 }
102
103 pub fn set_reseed_interval(&mut self, interval: u64) {
105 self.reseed_interval = interval.max(1);
106 }
107
108 pub fn set_max_bytes_between_reseed(&mut self, max_bytes: u128) {
110 self.max_bytes_between_reseed = max_bytes.max(1);
111 }
112
113 pub fn reseed(&mut self, entropy: &[u8], additional_input: Option<&[u8]>) -> Result<(), Error> {
115 self.check_new_entropy(entropy)?;
116 let mut seed = Vec::with_capacity(entropy.len() + additional_input.map_or(0, |a| a.len()));
117 seed.extend_from_slice(entropy);
118 if let Some(ai) = additional_input {
119 seed.extend_from_slice(ai);
120 }
121 self.update(Some(&seed));
122 seed.zeroize();
123 self.last_entropy.clear();
124 self.last_entropy.extend_from_slice(entropy);
125 self.reseed_counter = 1;
126 self.generated_bytes = 0;
127 Ok(())
128 }
129
130 pub fn generate(
132 &mut self,
133 out: &mut [u8],
134 additional_input: Option<&[u8]>,
135 ) -> Result<(), Error> {
136 if out.len() > MAX_REQUEST {
137 return Err(Error::RequestTooLarge);
138 }
139 if self.reseed_counter > self.reseed_interval {
140 return Err(Error::ReseedRequired);
141 }
142 if self.generated_bytes + out.len() as u128 >= self.max_bytes_between_reseed {
143 return Err(Error::ReseedRequired);
144 }
145
146 if let Some(ai) = additional_input {
147 if !ai.is_empty() {
148 self.update(Some(ai));
149 }
150 }
151
152 let mut produced = 0usize;
153 while produced < out.len() {
154 self.v = self.hmac(&self.v);
155 let take = min(BLOCK_LEN, out.len() - produced);
156 out[produced..produced + take].copy_from_slice(&self.v[..take]);
157 produced += take;
158 }
159
160 if let Some(ai) = additional_input {
162 if !ai.is_empty() {
163 self.update(Some(ai));
164 } else {
165 self.update(None);
166 }
167 } else {
168 self.update(None);
169 }
170
171 self.reseed_counter = self.reseed_counter.saturating_add(1);
172 self.generated_bytes = self.generated_bytes.saturating_add(out.len() as u128);
173 Ok(())
174 }
175
176 pub fn ct_eq(&self, other: &Self) -> subtle::Choice {
178 let mut acc = self.k.ct_eq(&other.k);
179 acc &= self.v.ct_eq(&other.v);
180 if self.reseed_counter == other.reseed_counter
181 && self.reseed_interval == other.reseed_interval
182 && self.generated_bytes == other.generated_bytes
183 && self.max_bytes_between_reseed == other.max_bytes_between_reseed
184 {
185 acc &= subtle::Choice::from(1);
186 } else {
187 acc &= subtle::Choice::from(0);
188 }
189
190 if self.last_entropy.len() == other.last_entropy.len() {
191 acc &= self
192 .last_entropy
193 .as_slice()
194 .ct_eq(other.last_entropy.as_slice());
195 } else {
196 acc &= subtle::Choice::from(0);
197 }
198 acc
199 }
200
201 fn validate_entropy(entropy: &[u8]) -> Result<(), Error> {
202 if entropy.is_empty() {
203 return Err(Error::EntropyHealthFailed);
204 }
205 if entropy.iter().all(|&b| b == entropy[0]) {
206 return Err(Error::EntropyHealthFailed);
207 }
208 Ok(())
209 }
210
211 fn check_new_entropy(&self, entropy: &[u8]) -> Result<(), Error> {
212 Self::validate_entropy(entropy)?;
213 if !self.last_entropy.is_empty() && entropy == self.last_entropy.as_slice() {
214 return Err(Error::EntropyHealthFailed);
215 }
216 Ok(())
217 }
218 fn hmac(&self, data: &[u8]) -> [u8; BLOCK_LEN] {
219 let mut mac = Hmac::<Sha512>::new_from_slice(&self.k).expect("HMAC key length valid");
220 mac.update(data);
221 let out = mac.finalize().into_bytes();
222 let mut buf = [0u8; BLOCK_LEN];
223 buf.copy_from_slice(&out);
224 buf
225 }
226
227 fn update(&mut self, provided_data: Option<&[u8]>) {
228 let mut buf = Vec::with_capacity(self.v.len() + 1 + provided_data.map_or(0, |d| d.len()));
231 buf.extend_from_slice(&self.v);
232 buf.push(0x00);
233 if let Some(data) = provided_data {
234 buf.extend_from_slice(data);
235 }
236 let new_k = {
237 let mut mac = Hmac::<Sha512>::new_from_slice(&self.k).expect("HMAC key length valid");
238 mac.update(&buf);
239 mac.finalize().into_bytes()
240 };
241 self.k.copy_from_slice(&new_k);
242 self.v = self.hmac(&self.v);
243 buf.zeroize();
244
245 if let Some(data) = provided_data {
246 let mut buf = Vec::with_capacity(self.v.len() + 1 + data.len());
247 buf.extend_from_slice(&self.v);
248 buf.push(0x01);
249 buf.extend_from_slice(data);
250 let new_k = {
251 let mut mac =
252 Hmac::<Sha512>::new_from_slice(&self.k).expect("HMAC key length valid");
253 mac.update(&buf);
254 mac.finalize().into_bytes()
255 };
256 self.k.copy_from_slice(&new_k);
257 self.v = self.hmac(&self.v);
258 buf.zeroize();
259 }
260 }
261}
262
263#[cfg(feature = "aes")]
264mod aes_ctr_drbg {
265 use super::Error;
266 use aes::Aes256;
267 use ctr::cipher::{KeyIvInit, StreamCipher};
268 use zeroize::{Zeroize, ZeroizeOnDrop};
269
270 type Ctr128 = ctr::Ctr128BE<Aes256>;
271
272 #[derive(Zeroize, ZeroizeOnDrop)]
274 pub struct AesCtrDrbg {
275 key: [u8; 32],
276 v: [u8; 16],
277 reseed_counter: u64,
278 reseed_interval: u64,
279 }
280
281 impl AesCtrDrbg {
282 pub fn new(seed_key: &[u8; 32], seed_v: &[u8; 16]) -> Self {
283 Self {
284 key: *seed_key,
285 v: *seed_v,
286 reseed_counter: 1,
287 reseed_interval: super::DEFAULT_RESEED_INTERVAL,
288 }
289 }
290
291 pub fn generate(&mut self, out: &mut [u8]) -> Result<(), Error> {
292 if self.reseed_counter > self.reseed_interval {
293 return Err(Error::ReseedRequired);
294 }
295 let mut cipher = Ctr128::new((&self.key).into(), (&self.v).into());
296 cipher.apply_keystream(out);
297 let blocks = (out.len() as u128 + 15) / 16;
299 let ctr = u128::from_be_bytes(self.v).wrapping_add(blocks);
300 self.v = ctr.to_be_bytes();
301 self.reseed_counter = self.reseed_counter.saturating_add(1);
302 Ok(())
303 }
304 }
305}
306
307#[cfg(test)]
308mod tests {
309 use super::*;
310
311 fn entropy(seed: u8) -> [u8; 48] {
312 let mut out = [0u8; 48];
313 for (i, byte) in out.iter_mut().enumerate() {
314 *byte = seed.wrapping_add(i as u8);
315 }
316 out
317 }
318
319 fn nonce(seed: u8) -> [u8; 16] {
320 let mut out = [0u8; 16];
321 for (i, byte) in out.iter_mut().enumerate() {
322 *byte = seed.wrapping_add((i * 3) as u8);
323 }
324 out
325 }
326
327 #[test]
328 fn identical_seed_produces_identical_stream() {
329 let mut a = HmacDrbg::new(&entropy(1), &nonce(2), Some(b"p")).unwrap();
330 let mut b = HmacDrbg::new(&entropy(1), &nonce(2), Some(b"p")).unwrap();
331 let mut out_a = [0u8; 96];
332 let mut out_b = [0u8; 96];
333 a.generate(&mut out_a, None).unwrap();
334 b.generate(&mut out_b, None).unwrap();
335 assert_eq!(out_a, out_b);
336 assert!(bool::from(a.ct_eq(&b)));
337 }
338
339 #[test]
340 fn reseed_changes_output() {
341 let mut drbg = HmacDrbg::new(&entropy(3), &nonce(4), None).unwrap();
342 let mut first = [0u8; 64];
343 drbg.generate(&mut first, None).unwrap();
344 drbg.reseed(&entropy(9), None).unwrap();
345 let mut second = [0u8; 64];
346 drbg.generate(&mut second, None).unwrap();
347 assert_ne!(first, second);
348 }
349
350 #[test]
351 fn additional_input_affects_stream() {
352 let mut drbg = HmacDrbg::new(&entropy(5), &nonce(6), None).unwrap();
353 let mut buf1 = [0u8; 64];
354 let mut buf2 = [0u8; 64];
355 drbg.generate(&mut buf1, Some(b"ai1")).unwrap();
356 drbg.generate(&mut buf2, Some(b"ai2")).unwrap();
357 assert_ne!(buf1, buf2);
358 }
359
360 #[test]
361 fn request_too_large_fails() {
362 let mut drbg = HmacDrbg::new(&entropy(7), &nonce(8), None).unwrap();
363 let mut buf = vec![0u8; MAX_REQUEST + 1];
364 assert_eq!(drbg.generate(&mut buf, None), Err(Error::RequestTooLarge));
365 }
366
367 #[test]
368 fn reseed_interval_enforced() {
369 let mut drbg = HmacDrbg::new(&entropy(9), &nonce(10), None).unwrap();
370 drbg.set_reseed_interval(1);
371 let mut buf = [0u8; 32];
372 drbg.generate(&mut buf, None).unwrap();
373 assert_eq!(drbg.generate(&mut buf, None), Err(Error::ReseedRequired));
374 }
375 #[test]
376 fn repeated_entropy_fails_health() {
377 let mut drbg = HmacDrbg::new(&entropy(1), &nonce(2), None).unwrap();
378 assert!(matches!(
379 drbg.reseed(&entropy(1), None),
380 Err(Error::EntropyHealthFailed)
381 ));
382 }
383
384 #[test]
385 fn byte_budget_enforced() {
386 let mut drbg = HmacDrbg::new(&entropy(11), &nonce(12), None).unwrap();
387 drbg.set_max_bytes_between_reseed(64);
388 let mut buf = [0u8; 32];
389 drbg.generate(&mut buf, None).unwrap();
390 assert!(matches!(
391 drbg.generate(&mut buf, None),
392 Err(Error::ReseedRequired)
393 ));
394 }
395}