5 * Copyright (c) 2005 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.8 2006/10/04 00:29:46 momjian Exp $
36 RCSID("$Id: rand-fortuna.c 20029 2007-01-21 09:55:42Z lha $");
49 * Why Fortuna-like: There does not seem to be any definitive reference
50 * on Fortuna in the net. Instead this implementation is based on
51 * following references:
53 * http://en.wikipedia.org/wiki/Fortuna_(PRNG)
55 * http://jlcooke.ca/random/
56 * - Jean-Luc Cooke Fortuna-based /dev/random driver for Linux.
60 * There is some confusion about whether and how to carry forward
61 * the state of the pools. Seems like original Fortuna does not
62 * do it, resetting hash after each request. I guess expecting
63 * feeding to happen more often that requesting. This is absolutely
64 * unsuitable for pgcrypto, as nothing asynchronous happens here.
66 * J.L. Cooke fixed this by feeding previous hash to new re-initialized
69 * Fortuna predecessor Yarrow requires ability to query intermediate
70 * 'final result' from hash, without affecting it.
72 * This implementation uses the Yarrow method - asking intermediate
73 * results, but continuing with old state.
78 * Algorithm parameters
84 #define RESEED_INTERVAL 100000 /* 0.1 sec */
86 /* for one big request, reseed after this many bytes */
87 #define RESEED_BYTES (1024*1024)
90 * Skip reseed if pool 0 has less than this many
91 * bytes added since last reseed.
93 #define POOL0_FILL (256/8)
99 /* Both cipher key size and hash result size */
102 /* cipher block size */
103 #define CIPH_BLOCK 16
105 /* for internal wrappers */
106 #define MD_CTX SHA256_CTX
107 #define CIPH_CTX AES_KEY
111 unsigned char counter[CIPH_BLOCK];
112 unsigned char result[CIPH_BLOCK];
113 unsigned char key[BLOCK];
114 MD_CTX pool[NUM_POOLS];
116 unsigned reseed_count;
117 struct timeval last_reseed_time;
118 unsigned pool0_bytes;
122 typedef struct fortuna_state FState;
126 * Use our own wrappers here.
127 * - Need to get intermediate result from digest, without affecting it.
128 * - Need re-set key on a cipher context.
129 * - Algorithms are guaranteed to exist.
130 * - No memory allocations.
134 ciph_init(CIPH_CTX * ctx, const unsigned char *key, int klen)
136 AES_set_encrypt_key(key, klen * 8, ctx);
140 ciph_encrypt(CIPH_CTX * ctx, const unsigned char *in, unsigned char *out)
142 AES_encrypt(in, out, ctx);
146 md_init(MD_CTX * ctx)
152 md_update(MD_CTX * ctx, const unsigned char *data, int len)
154 SHA256_Update(ctx, data, len);
158 md_result(MD_CTX * ctx, unsigned char *dst)
162 memcpy(&tmp, ctx, sizeof(*ctx));
163 SHA256_Final(dst, &tmp);
164 memset(&tmp, 0, sizeof(tmp));
171 init_state(FState * st)
175 memset(st, 0, sizeof(*st));
176 for (i = 0; i < NUM_POOLS; i++)
177 md_init(&st->pool[i]);
181 * Endianess does not matter.
182 * It just needs to change without repeating.
185 inc_counter(FState * st)
187 uint32_t *val = (uint32_t *) st->counter;
199 * This is called 'cipher in counter mode'.
202 encrypt_counter(FState * st, unsigned char *dst)
204 ciph_encrypt(&st->ciph, st->counter, dst);
210 * The time between reseed must be at least RESEED_INTERVAL
214 enough_time_passed(FState * st)
218 struct timeval *last = &st->last_reseed_time;
220 gettimeofday(&tv, NULL);
222 /* check how much time has passed */
224 if (tv.tv_sec > last->tv_sec + 1)
226 else if (tv.tv_sec == last->tv_sec + 1)
228 if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
231 else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
234 /* reseed will happen, update last_reseed_time */
236 memcpy(last, &tv, sizeof(tv));
238 memset(&tv, 0, sizeof(tv));
244 * generate new key from all the pools
252 unsigned char buf[BLOCK];
254 /* set pool as empty */
258 * Both #0 and #1 reseed would use only pool 0. Just skip #0 then.
260 n = ++st->reseed_count;
263 * The goal: use k-th pool only 1/(2^k) of the time.
266 for (k = 0; k < NUM_POOLS; k++)
268 md_result(&st->pool[k], buf);
269 md_update(&key_md, buf, BLOCK);
276 /* add old key into mix too */
277 md_update(&key_md, st->key, BLOCK);
279 /* now we have new key */
280 md_result(&key_md, st->key);
283 ciph_init(&st->ciph, st->key, BLOCK);
285 memset(&key_md, 0, sizeof(key_md));
286 memset(buf, 0, BLOCK);
290 * Pick a random pool. This uses key bytes as random source.
293 get_rand_pool(FState * st)
298 * This slightly prefers lower pools - thats OK.
300 rnd = st->key[st->rnd_pos] % NUM_POOLS;
303 if (st->rnd_pos >= BLOCK)
313 add_entropy(FState * st, const unsigned char *data, unsigned len)
316 unsigned char hash[BLOCK];
319 /* hash given data */
321 md_update(&md, data, len);
322 md_result(&md, hash);
325 * Make sure the pool 0 is initialized, then update randomly.
327 if (st->reseed_count == 0)
330 pos = get_rand_pool(st);
331 md_update(&st->pool[pos], hash, BLOCK);
334 st->pool0_bytes += len;
336 memset(hash, 0, BLOCK);
337 memset(&md, 0, sizeof(md));
341 * Just take 2 next blocks as new key
346 encrypt_counter(st, st->key);
347 encrypt_counter(st, st->key + CIPH_BLOCK);
348 ciph_init(&st->ciph, st->key, BLOCK);
352 * Hide public constants. (counter, pools > 0)
354 * This can also be viewed as spreading the startup
355 * entropy over all of the components.
358 startup_tricks(FState * st)
361 unsigned char buf[BLOCK];
363 /* Use next block as counter. */
364 encrypt_counter(st, st->counter);
366 /* Now shuffle pools, excluding #0 */
367 for (i = 1; i < NUM_POOLS; i++)
369 encrypt_counter(st, buf);
370 encrypt_counter(st, buf + CIPH_BLOCK);
371 md_update(&st->pool[i], buf, BLOCK);
373 memset(buf, 0, BLOCK);
378 /* This can be done only once. */
383 extract_data(FState * st, unsigned count, unsigned char *dst)
386 unsigned block_nr = 0;
388 /* Should we reseed? */
389 if (st->pool0_bytes >= POOL0_FILL || st->reseed_count == 0)
390 if (enough_time_passed(st))
393 /* Do some randomization on first call */
394 if (!st->tricks_done)
400 encrypt_counter(st, st->result);
403 if (count > CIPH_BLOCK)
407 memcpy(dst, st->result, n);
411 /* must not give out too many bytes with one key */
413 if (block_nr > (RESEED_BYTES / CIPH_BLOCK))
419 /* Set new key for next request. */
427 static FState main_state;
428 static int init_done;
429 static int have_entropy;
432 * Try our best to do an inital seed
434 #define INIT_BYTES 128
445 unsigned char buf[INIT_BYTES];
446 if ((*hc_rand_unix_method.bytes)(buf, sizeof(buf)) == 1) {
447 add_entropy(&main_state, buf, sizeof(buf));
449 memset(buf, 0, sizeof(buf));
452 #ifdef HAVE_ARC4RANDOM
454 uint32_t buf[INIT_BYTES / sizeof(uint32_t)];
457 for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
458 buf[i] = arc4random();
459 add_entropy(&main_state, (void *)buf, sizeof(buf));
464 * Only to get egd entropy if /dev/random or arc4rand failed since
465 * it can be horribly slow to generate new bits.
468 unsigned char buf[INIT_BYTES];
469 if ((*hc_rand_egd_method.bytes)(buf, sizeof(buf)) == 1) {
470 add_entropy(&main_state, buf, sizeof(buf));
472 memset(buf, 0, sizeof(buf));
476 pid_t pid = getpid();
477 add_entropy(&main_state, (void *)&pid, sizeof(pid));
481 gettimeofday(&tv, NULL);
482 add_entropy(&main_state, (void *)&tv, sizeof(tv));
486 add_entropy(&main_state, (void *)&u, sizeof(u));
496 init_state(&main_state);
500 have_entropy = fortuna_reseed();
501 return (init_done && have_entropy);
507 fortuna_seed(const void *indata, int size)
510 add_entropy(&main_state, indata, size);
511 if (size >= INIT_BYTES)
516 fortuna_bytes(unsigned char *outdata, int size)
520 extract_data(&main_state, size, outdata);
525 fortuna_cleanup(void)
529 memset(&main_state, 0, sizeof(main_state));
533 fortuna_add(const void *indata, int size, double entropi)
535 fortuna_seed(indata, size);
539 fortuna_pseudorand(unsigned char *outdata, int size)
541 return fortuna_bytes(outdata, size);
547 return fortuna_init() ? 1 : 0;
550 const RAND_METHOD hc_rand_fortuna_method = {
560 RAND_fortuna_method(void)
562 return &hc_rand_fortuna_method;