1 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4 // option. This file may not be copied, modified, or distributed
5 // except according to those terms.
6
7 /*!
8 * An implementation of the Fortuna CSPRNG
9 *
10 * First create a `FortunaRng` object using either the `new_unseeded`
11 * constructor or `SeedableRng::from_seed`. Additional entropy may be
12 * added using the method `add_random_event`, or the underlying RNG
13 * maybe reseeded directly by `SeedableRng::reseed`. Note that this is
14 * not recommended, since the generator automatically reseeds itself
15 * using the data provided by `add_random_events` through an
16 * accumulator. The accumulator is part of Fortuna's design and using
17 * `SeedableRng::reseed` directly bypasses it.
18 *
19 * Note that the underlying block cipher is `AesSafe256Encryptor` which
20 * is designed to be timing-attack resistant. The speed hit from this
21 * is in line with a "safety first" API, but be aware of it.
22 *
23 * Fortuna was originally described in
24 * Practical Cryptography, Niels Ferguson and Bruce Schneier.
25 * John Wiley & Sons, 2003.
26 *
27 * Comments throughout this file contain references of the form
28 * (PC 1.2.3); these refer to sections within this text.
29 *
30 * # A note on forking
31 *
32 * Proper behaviour for a CSRNG on a process fork is to reseed itself with
33 * the timestamp and new process ID, to ensure that after forking the child
34 * process does not share the same RNG state (and therefore the same output)
35 * as its parent.
36 *
37 * However, this appears not to be possible in Rust, due to
38 * https://github.com/rust-lang/rust/issues/16799
39 * The reason is that Rust's process management all happens through its
40 * stdlib runtime, which explicitly does not support forking, so it provides
41 * no mechanism with which to detect forks.
42 *
43 * What this means is that if you are writing forking code (using `#![no_std]`
44 * say) then you need to EXPLICITLY RESEED THE RNG AFTER FORKING.
45 */
46
47 use cryptoutil::copy_memory;
48
49 use rand::{Rng, SeedableRng};
50 use time::precise_time_s;
51
52 use aessafe::AesSafe256Encryptor;
53 use cryptoutil::read_u32_le;
54 use digest::Digest;
55 use sha2::Sha256;
56 use symmetriccipher::BlockEncryptor;
57
58 /// Length in bytes that the first pool must be before a "catastrophic
59 /// reseed" is allowed to happen. (A direct reseed through the
60 /// `SeedableRng` API is not affected by this limit.)
61 pub const MIN_POOL_SIZE: usize = 64;
62 /// Maximum number of bytes to generate before rekeying
63 const MAX_GEN_SIZE: usize = (1 << 20);
64 /// Length in bytes of the AES key
65 const KEY_LEN: usize = 32;
66 /// Length in bytes of the AES counter
67 const CTR_LEN: usize = 16;
68 /// Length in bytes of the AES block
69 const AES_BLOCK_SIZE: usize = 16;
70 /// Number of pools used to accumulate entropy
71 const NUM_POOLS: usize = 32;
72
73 /// The underlying PRNG (PC 9.4)
74 struct FortunaGenerator {
75 key: [u8; KEY_LEN],
76 ctr: [u8; CTR_LEN],
77 }
78
79 impl FortunaGenerator {
80 /// Creates a new generator (PC 9.4.1)
new() -> FortunaGenerator81 fn new() -> FortunaGenerator {
82 FortunaGenerator {
83 key: [0; KEY_LEN],
84 ctr: [0; CTR_LEN],
85 }
86 }
87
88 /// Increments the counter in place
increment_counter(&mut self)89 fn increment_counter(&mut self) {
90 for i in 0..self.ctr.len() {
91 self.ctr[i] = self.ctr[i].wrapping_add(1);
92 // As soon as we don't carry, stop
93 if self.ctr[i] != 0 {
94 break;
95 }
96 }
97 }
98
99 /// Reseeds the generator (PC 9.4.2)
reseed(&mut self, s: &[u8])100 fn reseed(&mut self, s: &[u8]) {
101 // Compute key as Sha256d( key || s )
102 let mut hasher = Sha256::new();
103 hasher.input(&self.key[..]);
104 hasher.input(s);
105 hasher.result(&mut self.key);
106 hasher = Sha256::new();
107 hasher.input(&self.key[..]);
108 hasher.result(&mut self.key[..]);
109 // Increment the counter
110 self.increment_counter();
111 }
112
113 /// Generates some `k` 16-byte blocks of random output (PC 9.4.3)
114 /// This should never be used directly, except by `generate_random_data`.
generate_blocks(&mut self, k: usize, out: &mut [u8])115 fn generate_blocks(&mut self, k: usize, out: &mut [u8]) {
116 assert!(self.ctr[..] != [0; CTR_LEN][..]);
117
118 // Setup AES encryptor
119 let block_encryptor = AesSafe256Encryptor::new(&self.key[..]);
120 // Concatenate all the blocks
121 for j in 0..k {
122 block_encryptor.encrypt_block(&self.ctr[..],
123 &mut out[AES_BLOCK_SIZE * j..AES_BLOCK_SIZE * (j + 1)]);
124 self.increment_counter();
125 }
126 }
127
128 /// Generates `n` bytes of random data (9.4.4)
generate_random_data(&mut self, out: &mut [u8])129 fn generate_random_data(&mut self, out: &mut [u8]) {
130 let (n, rem) = (out.len() / AES_BLOCK_SIZE, out.len() % AES_BLOCK_SIZE);
131 assert!(n <= MAX_GEN_SIZE);
132
133 // Generate output
134 self.generate_blocks(n, &mut out[..(n * AES_BLOCK_SIZE)]);
135 if rem > 0 {
136 let mut buf = [0; AES_BLOCK_SIZE];
137 self.generate_blocks(1, &mut buf);
138 copy_memory(&buf[..rem], &mut out[(n * AES_BLOCK_SIZE)..]);
139 }
140
141 // Rekey
142 let mut new_key = [0; KEY_LEN];
143 self.generate_blocks(KEY_LEN / AES_BLOCK_SIZE, &mut new_key);
144 self.key = new_key;
145 }
146 }
147
148
149 /// A single entropy pool (not public)
150 #[derive(Clone, Copy)]
151 struct Pool {
152 state: Sha256,
153 count: usize
154 }
155
156 impl Pool {
new() -> Pool157 fn new() -> Pool {
158 Pool { state: Sha256::new(), count: 0 }
159 }
160
input(&mut self, data: &[u8])161 fn input(&mut self, data: &[u8]) {
162 self.state.input(data);
163 self.count += data.len();
164 }
165
result(&mut self, output: &mut [u8])166 fn result(&mut self, output: &mut [u8]) {
167 self.state.result(output);
168 // Double-SHA256 it
169 self.state = Sha256::new();
170 self.state.input(output);
171 self.state.result(output);
172 // Clear the pool state
173 self.state = Sha256::new();
174 self.count = 0;
175 }
176 }
177
178 /// The `Fortuna` CSPRNG (PC 9.5)
179 pub struct Fortuna {
180 pool: [Pool; NUM_POOLS],
181 generator: FortunaGenerator,
182 reseed_count: u32,
183 last_reseed_time: f64
184 }
185
186 impl Fortuna {
187 /// Creates a new unseeded `Fortuna` (PC 9.5.4)
new_unseeded() -> Fortuna188 pub fn new_unseeded() -> Fortuna {
189 Fortuna {
190 pool: [Pool::new(); NUM_POOLS],
191 generator: FortunaGenerator::new(),
192 reseed_count: 0,
193 last_reseed_time: 0.0
194 }
195 }
196
197 /// Adds a random event `e` from source `s` to entropy pool `i` (PC 9.5.6)
add_random_event(&mut self, s: u8, i: usize, e: &[u8])198 pub fn add_random_event(&mut self, s: u8, i: usize, e: &[u8]) {
199 assert!(i <= NUM_POOLS);
200 // These restrictions (and `s` in [0, 255]) are part of the Fortuna spec.
201 assert!(e.len() > 0);
202 assert!(e.len() <= 32);
203 (&mut self.pool[i]).input(&[s]);
204 (&mut self.pool[i]).input(&[e.len() as u8]);
205 (&mut self.pool[i]).input(e);
206 }
207 }
208
209 impl Rng for Fortuna {
210 /// Generate a bunch of random data into `dest` (PC 9.5.5)
211 ///
212 /// # Failure modes
213 ///
214 /// If the RNG has not been seeded, and there is less than
215 /// `MIN_POOL_SIZE` bytes of data in the first accumulator
216 /// pool, this function will fail the task.
fill_bytes(&mut self, dest: &mut [u8])217 fn fill_bytes(&mut self, dest: &mut [u8]) {
218 // Reseed if necessary
219 let now = precise_time_s();
220 if self.pool[0].count >= MIN_POOL_SIZE &&
221 now - self.last_reseed_time > 0.1 {
222 self.reseed_count += 1;
223 self.last_reseed_time = now;
224 // Compute key as Sha256d( key || s )
225 let mut hash = [0; (32 * NUM_POOLS)];
226 let mut n_pools = 0;
227 while self.reseed_count % (1 << n_pools) == 0 {
228 (&mut self.pool[n_pools]).result(&mut hash[n_pools * 32..(n_pools + 1) * 32]);
229 n_pools += 1;
230 assert!(n_pools < NUM_POOLS);
231 assert!(n_pools < 32); // width of counter
232 }
233 self.generator.reseed(&hash[..n_pools * 32]);
234 }
235 // Fail on unseeded RNG
236 if self.reseed_count == 0 {
237 panic!("rust-crypto: an unseeded Fortuna was asked for random bytes!");
238 }
239 // Generate return data
240 for dest in dest.chunks_mut(MAX_GEN_SIZE) {
241 self.generator.generate_random_data(dest);
242 }
243 }
244
next_u32(&mut self) -> u32245 fn next_u32(&mut self) -> u32 {
246 let mut ret = [0; 4];
247 self.fill_bytes(&mut ret);
248 read_u32_le(&ret[..])
249 }
250 }
251
252
253 impl<'a> SeedableRng<&'a [u8]> for Fortuna {
from_seed(seed: &'a [u8]) -> Fortuna254 fn from_seed(seed: &'a [u8]) -> Fortuna {
255 let mut ret = Fortuna::new_unseeded();
256 ret.reseed(seed);
257 ret
258 }
259
reseed(&mut self, seed: &'a [u8])260 fn reseed(&mut self, seed: &'a [u8]) {
261 self.reseed_count += 1;
262 self.last_reseed_time = precise_time_s();
263 self.generator.reseed(seed);
264 }
265 }
266
267 #[cfg(test)]
test_force_reseed(f: &mut Fortuna)268 fn test_force_reseed(f: &mut Fortuna) {
269 f.last_reseed_time -= 0.2;
270 }
271
272 #[cfg(test)]
273 mod tests {
274 use rand::{SeedableRng, Rng};
275
276 use super::{Fortuna, Pool, NUM_POOLS, test_force_reseed};
277
278 #[test]
test_create_unseeded()279 fn test_create_unseeded() {
280 let _: Fortuna = Fortuna::new_unseeded();
281 }
282
283 #[test]
284 #[should_panic]
test_use_unseeded()285 fn test_use_unseeded() {
286 let mut f: Fortuna = Fortuna::new_unseeded();
287 let _ = f.next_u32();
288 }
289
290 #[test]
291 #[should_panic]
test_badly_seeded()292 fn test_badly_seeded() {
293 let mut f: Fortuna = Fortuna::new_unseeded();
294 f.add_random_event(0, 0, &[10; 32]);
295 let _ = f.next_u32();
296 }
297
298 #[test]
299 #[should_panic]
test_too_big_event()300 fn test_too_big_event() {
301 let mut f: Fortuna = Fortuna::new_unseeded();
302 f.add_random_event(0, 0, &[10; 33]);
303 }
304
305 #[test]
test_seeded()306 fn test_seeded() {
307 // NB for this test I'm just trusting the output of the RNG to be correct.
308 // I do check for some high-level features: changing most anything should
309 // change the output, there should be no tests, etc.
310 let mut f1: Fortuna = SeedableRng::from_seed(&[0, 1, 2, 3, 4, 5][..]);
311 assert_eq!(f1.next_u32(), 3369034117);
312
313 let mut f2: Fortuna = Fortuna::new_unseeded();
314 f2.reseed(&[0, 1, 2, 3, 4, 5]);
315 assert_eq!(f2.next_u32(), 3369034117);
316
317 // Ensure reseeding doesn't totally reset the seed. That is, this output should
318 // be different from the above
319 let mut f3: Fortuna = Fortuna::new_unseeded();
320 f3.reseed(&[0, 1, 2, 3, 4, 5]);
321 f3.reseed(&[0, 1, 2, 3, 4, 5]);
322 assert_eq!(f3.next_u32(), 2689122182);
323
324 // These three should all be different
325 let mut f4: Fortuna = Fortuna::new_unseeded();
326 f4.add_random_event(0, 0, &[10; 32]);
327 f4.add_random_event(0, 0, &[10; 32]);
328 let x = f4.next_u32();
329
330 let mut f5: Fortuna = Fortuna::new_unseeded();
331 f5.add_random_event(0, 0, &[10; 32]);
332 f5.add_random_event(0, 0, &[20; 32]);
333 let y = f5.next_u32();
334
335 let mut f6: Fortuna = Fortuna::new_unseeded();
336 f6.add_random_event(0, 0, &[20; 32]);
337 f6.add_random_event(0, 0, &[10; 32]);
338 let z = f6.next_u32();
339
340 assert!(x != y);
341 assert!(y != z);
342 assert!(x != z);
343 }
344
345 #[test]
test_generator_correctness()346 fn test_generator_correctness() {
347 let mut output = [0; 100];
348 // Expected output as in http://www.seehuhn.de/pages/fortuna
349 let expected = [ 82, 254, 233, 139, 254, 85, 6, 222, 222, 149,
350 120, 35, 173, 71, 89, 232, 51, 182, 252, 139,
351 153, 153, 111, 30, 16, 7, 124, 185, 159, 24,
352 50, 68, 236, 107, 133, 18, 217, 219, 46, 134,
353 169, 156, 211, 74, 163, 17, 100, 173, 26, 70,
354 246, 193, 57, 164, 167, 175, 233, 220, 160, 114,
355 2, 200, 215, 80, 207, 218, 85, 58, 235, 117,
356 177, 223, 87, 192, 50, 251, 61, 65, 141, 100,
357 59, 228, 23, 215, 58, 107, 248, 248, 103, 57,
358 127, 31, 241, 91, 230, 33, 0, 164, 77, 46];
359 let mut f: Fortuna = SeedableRng::from_seed(&[1, 2, 3, 4][..]);
360 f.fill_bytes(&mut output);
361 assert_eq!(&expected[..], &output[..]);
362
363 let mut scratch = [0; (1 << 20)];
364 f.generator.generate_random_data(&mut scratch);
365
366 let expected = [122, 164, 26, 67, 102, 65, 30, 217, 219, 113,
367 14, 86, 214, 146, 185, 17, 107, 135, 183, 7,
368 18, 162, 126, 206, 46, 38, 54, 172, 248, 194,
369 118, 84, 162, 146, 83, 156, 152, 96, 192, 15,
370 23, 224, 113, 76, 21, 8, 226, 41, 161, 171,
371 197, 180, 138, 236, 126, 137, 101, 25, 219, 225,
372 3, 189, 16, 242, 33, 91, 34, 27, 8, 171,
373 171, 115, 157, 109, 248, 198, 227, 18, 204, 211,
374 42, 184, 92, 42, 171, 222, 198, 117, 162, 134,
375 116, 109, 77, 195, 187, 139, 37, 78, 224, 63];
376 f.fill_bytes(&mut output);
377 assert_eq!(&expected[..], &output[..]);
378
379 f.reseed(&[5]);
380
381 let expected = [217, 168, 141, 167, 46, 9, 218, 188, 98, 124,
382 109, 128, 242, 22, 189, 120, 180, 124, 15, 192,
383 116, 149, 211, 136, 253, 132, 60, 3, 29, 250,
384 95, 66, 133, 195, 37, 78, 242, 255, 160, 209,
385 185, 106, 68, 105, 83, 145, 165, 72, 179, 167,
386 53, 254, 183, 251, 128, 69, 78, 156, 219, 26,
387 124, 202, 35, 9, 174, 167, 41, 128, 184, 25,
388 2, 1, 63, 142, 205, 162, 69, 68, 207, 251,
389 101, 10, 29, 33, 133, 87, 189, 36, 229, 56,
390 17, 100, 138, 49, 79, 239, 210, 189, 141, 46];
391
392 f.fill_bytes(&mut output);
393 assert_eq!(&expected[..], &output[..]);
394 }
395
396 #[test]
test_accumulator_correctness()397 fn test_accumulator_correctness() {
398 let mut output = [0; 100];
399 // Expected output from experiments with pycryto
400 // Note that this does not match the results for the Go implementation
401 // as described at http://www.seehuhn.de/pages/fortuna ... I believe
402 // this is because the author there is reusing some Fortuna state from
403 // the previous test. These results agree with pycrypto on a fresh slate
404 let mut f = Fortuna::new_unseeded();
405 f.pool = [Pool::new(); NUM_POOLS];
406 f.add_random_event(0, 0, &[0; 32]);
407 f.add_random_event(0, 0, &[0; 32]);
408 for i in 0..32 {
409 f.add_random_event(1, i, &[1, 2]);
410 }
411
412 // from Crypto.Random.Fortuna import FortunaAccumulator
413 // x = FortunaAccumulator.FortunaAccumulator()
414 // x.add_random_event(0, 0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
415 // x.add_random_event(0, 0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
416 // x.add_random_event(1, 0, "\1\2")
417 // x.add_random_event(1, 1, "\1\2")
418 // print list(bytearray(x.random_data(100)))
419 let expected = [ 21, 42, 103, 180, 211, 46, 177, 231, 172, 210,
420 109, 198, 34, 40, 245, 199, 76, 114, 105, 185,
421 186, 112, 183, 213, 19, 72, 186, 26, 182, 211,
422 254, 88, 67, 142, 246, 102, 80, 93, 144, 152,
423 123, 191, 168, 26, 21, 194, 69, 214, 249, 80,
424 182, 165, 203, 69, 134, 140, 11, 208, 50, 175,
425 180, 210, 110, 119, 3, 75, 1, 8, 5, 142,
426 226, 168, 179, 246, 82, 42, 223, 239, 201, 23,
427 28, 30, 195, 195, 9, 154, 31, 172, 209, 232,
428 238, 111, 75, 251, 196, 43, 217, 241, 93, 237];
429 f.fill_bytes(&mut output);
430 assert_eq!(&expected[..], &output[..]);
431
432 // Immediately (less than 100ms)
433 f.add_random_event(0, 0, &[0; 32]);
434 f.add_random_event(0, 0, &[0; 32]);
435
436 // x.add_random_event(0, 0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
437 // x.add_random_event(0, 0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
438 // print list(bytearray(x.random_data(100)))
439 let expected = [101, 123, 175, 157, 142, 202, 211, 47, 149, 214,
440 135, 249, 148, 19, 50, 116, 169, 188, 240, 218,
441 91, 62, 35, 44, 142, 108, 95, 20, 37, 185,
442 19, 121, 128, 231, 213, 23, 94, 147, 14, 41,
443 199, 253, 246, 14, 230, 152, 11, 17, 118, 254,
444 96, 251, 171, 115, 66, 21, 196, 164, 82, 6,
445 139, 238, 135, 22, 179, 6, 6, 252, 115, 87,
446 19, 167, 56, 192, 140, 93, 132, 78, 22, 16,
447 114, 68, 123, 200, 37, 183, 163, 224, 201, 155,
448 233, 71, 111, 26, 8, 114, 232, 181, 13, 51];
449 f.fill_bytes(&mut output);
450 assert_eq!(&expected[..], &output[..]);
451
452 // Simulate more than 100 ms passing
453 test_force_reseed(&mut f);
454 // time.sleep(0.2)
455 // print list(bytearray(x.random_data(100)))
456 let expected = [ 62, 147, 205, 228, 22, 3, 225, 217, 211, 202,
457 49, 148, 236, 125, 132, 43, 25, 177, 172, 93,
458 98, 177, 112, 160, 76, 101, 60, 98, 225, 9,
459 223, 120, 161, 98, 173, 178, 71, 15, 90, 153,
460 64, 179, 143, 22, 43, 165, 87, 147, 177, 128,
461 21, 105, 214, 197, 224, 187, 22, 139, 16, 153,
462 251, 48, 244, 87, 10, 104, 119, 179, 27, 255,
463 67, 148, 192, 52, 147, 216, 79, 204, 106, 112,
464 238, 0, 239, 99, 159, 96, 184, 90, 54, 122,
465 184, 241, 221, 151, 169, 29, 197, 45, 80, 6];
466 f.fill_bytes(&mut output);
467 assert_eq!(&expected[..], &output[..]);
468 }
469 }
470
471 #[cfg(all(test, feature = "with-bench"))]
472 mod bench {
473 use rand::{SeedableRng, Rng};
474 use test::Bencher;
475
476 use super::Fortuna;
477
478 #[bench]
fortuna_new_32(bh: &mut Bencher)479 pub fn fortuna_new_32(bh: &mut Bencher) {
480 let mut f: Fortuna = SeedableRng::from_seed(&[100; 64][..]);
481 bh.iter( || {
482 f.next_u32();
483 });
484 bh.bytes = 4;
485 }
486
487 #[bench]
fortuna_new_64(bh: &mut Bencher)488 pub fn fortuna_new_64(bh: &mut Bencher) {
489 let mut f: Fortuna = SeedableRng::from_seed(&[100; 64][..]);
490 bh.iter( || {
491 f.next_u64();
492 });
493 bh.bytes = 8;
494 }
495
496 #[bench]
fortuna_new_1k(bh: &mut Bencher)497 pub fn fortuna_new_1k(bh: &mut Bencher) {
498 let mut f: Fortuna = SeedableRng::from_seed(&[100; 64][..]);
499 let mut bytes = [0u8; 1024];
500 bh.iter( || {
501 f.fill_bytes(&mut bytes);
502 });
503 bh.bytes = bytes.len() as u64;
504 }
505
506 #[bench]
fortuna_new_64k(bh: &mut Bencher)507 pub fn fortuna_new_64k(bh: &mut Bencher) {
508 let mut f: Fortuna = SeedableRng::from_seed(&[100; 64][..]);
509 let mut bytes = [0u8; 65536];
510 bh.iter( || {
511 f.fill_bytes(&mut bytes);
512 });
513 bh.bytes = bytes.len() as u64;
514 }
515 }
516