#include "postgres.h"
#include <sys/time.h>
#include "rijndael.h"
#include "sha2.h"
#include "fortuna.h"
Go to the source code of this file.
Data Structures | |
struct | fortuna_state |
Defines | |
#define | NUM_POOLS 23 |
#define | RESEED_INTERVAL 100000 |
#define | RESEED_BYTES (1024*1024) |
#define | POOL0_FILL (256/8) |
#define | BLOCK 32 |
#define | CIPH_BLOCK 16 |
#define | MD_CTX SHA256_CTX |
#define | CIPH_CTX rijndael_ctx |
Typedefs | |
typedef struct fortuna_state | FState |
Functions | |
static void | ciph_init (CIPH_CTX *ctx, const uint8 *key, int klen) |
static void | ciph_encrypt (CIPH_CTX *ctx, const uint8 *in, uint8 *out) |
static void | md_init (MD_CTX *ctx) |
static void | md_update (MD_CTX *ctx, const uint8 *data, int len) |
static void | md_result (MD_CTX *ctx, uint8 *dst) |
static void | init_state (FState *st) |
static void | inc_counter (FState *st) |
static void | encrypt_counter (FState *st, uint8 *dst) |
static int | enough_time_passed (FState *st) |
static void | reseed (FState *st) |
static unsigned | get_rand_pool (FState *st) |
static void | add_entropy (FState *st, const uint8 *data, unsigned len) |
static void | rekey (FState *st) |
static void | startup_tricks (FState *st) |
static void | extract_data (FState *st, unsigned count, uint8 *dst) |
void | fortuna_add_entropy (const uint8 *data, unsigned len) |
void | fortuna_get_bytes (unsigned len, uint8 *dst) |
Variables | |
static FState | main_state |
static int | init_done = 0 |
#define BLOCK 32 |
Definition at line 108 of file fortuna.c.
Referenced by add_entropy(), get_rand_pool(), rekey(), reseed(), and startup_tricks().
#define CIPH_BLOCK 16 |
Definition at line 111 of file fortuna.c.
Referenced by extract_data(), rekey(), and startup_tricks().
#define CIPH_CTX rijndael_ctx |
#define MD_CTX SHA256_CTX |
Definition at line 114 of file fortuna.c.
Referenced by add_entropy(), and reseed().
#define POOL0_FILL (256/8) |
Definition at line 101 of file fortuna.c.
Referenced by extract_data().
#define RESEED_BYTES (1024*1024) |
Definition at line 95 of file fortuna.c.
Referenced by extract_data().
#define RESEED_INTERVAL 100000 |
Definition at line 92 of file fortuna.c.
Referenced by enough_time_passed().
typedef struct fortuna_state FState |
Definition at line 321 of file fortuna.c.
References BLOCK, get_rand_pool(), hash(), MD_CTX, md_init(), md_result(), md_update(), fortuna_state::pool, fortuna_state::pool0_bytes, and fortuna_state::reseed_count.
Referenced by fortuna_add_entropy().
{ unsigned pos; uint8 hash[BLOCK]; MD_CTX md; /* hash given data */ md_init(&md); md_update(&md, data, len); md_result(&md, hash); /* * Make sure the pool 0 is initialized, then update randomly. */ if (st->reseed_count == 0) pos = 0; else pos = get_rand_pool(st); md_update(&st->pool[pos], hash, BLOCK); if (pos == 0) st->pool0_bytes += len; memset(hash, 0, BLOCK); memset(&md, 0, sizeof(md)); }
Definition at line 148 of file fortuna.c.
References rijndael_encrypt().
Referenced by encrypt_counter().
{ rijndael_encrypt(ctx, (const uint32 *) in, (uint32 *) out); }
static void ciph_init | ( | CIPH_CTX * | ctx, | |
const uint8 * | key, | |||
int | klen | |||
) | [static] |
Definition at line 142 of file fortuna.c.
References rijndael_set_key().
Referenced by rekey(), and reseed().
{ rijndael_set_key(ctx, (const uint32 *) key, klen, 1); }
Definition at line 210 of file fortuna.c.
References fortuna_state::ciph, ciph_encrypt(), fortuna_state::counter, and inc_counter().
Referenced by extract_data(), rekey(), and startup_tricks().
{ ciph_encrypt(&st->ciph, st->counter, dst); inc_counter(st); }
static int enough_time_passed | ( | FState * | st | ) | [static] |
Definition at line 222 of file fortuna.c.
References gettimeofday(), fortuna_state::last_reseed_time, NULL, and RESEED_INTERVAL.
Referenced by extract_data().
{ int ok; struct timeval tv; struct timeval *last = &st->last_reseed_time; gettimeofday(&tv, NULL); /* check how much time has passed */ ok = 0; if (tv.tv_sec > last->tv_sec + 1) ok = 1; else if (tv.tv_sec == last->tv_sec + 1) { if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL) ok = 1; } else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL) ok = 1; /* reseed will happen, update last_reseed_time */ if (ok) memcpy(last, &tv, sizeof(tv)); memset(&tv, 0, sizeof(tv)); return ok; }
Definition at line 391 of file fortuna.c.
References CIPH_BLOCK, encrypt_counter(), enough_time_passed(), fortuna_state::pool0_bytes, POOL0_FILL, rekey(), reseed(), RESEED_BYTES, fortuna_state::reseed_count, fortuna_state::result, startup_tricks(), and fortuna_state::tricks_done.
Referenced by fortuna_get_bytes().
{ unsigned n; unsigned block_nr = 0; /* Should we reseed? */ if (st->pool0_bytes >= POOL0_FILL || st->reseed_count == 0) if (enough_time_passed(st)) reseed(st); /* Do some randomization on first call */ if (!st->tricks_done) startup_tricks(st); while (count > 0) { /* produce bytes */ encrypt_counter(st, st->result); /* copy result */ if (count > CIPH_BLOCK) n = CIPH_BLOCK; else n = count; memcpy(dst, st->result, n); dst += n; count -= n; /* must not give out too many bytes with one key */ block_nr++; if (block_nr > (RESEED_BYTES / CIPH_BLOCK)) { rekey(st); block_nr = 0; } } /* Set new key for next request. */ rekey(st); }
void fortuna_add_entropy | ( | const uint8 * | data, | |
unsigned | len | |||
) |
Definition at line 439 of file fortuna.c.
References add_entropy(), init_done, and init_state().
Referenced by px_add_entropy(), and system_reseed().
{ if (!init_done) { init_state(&main_state); init_done = 1; } if (!data || !len) return; add_entropy(&main_state, data, len); }
void fortuna_get_bytes | ( | unsigned | len, | |
uint8 * | dst | |||
) |
Definition at line 452 of file fortuna.c.
References extract_data(), init_done, and init_state().
Referenced by px_get_random_bytes().
{ if (!init_done) { init_state(&main_state); init_done = 1; } if (!dst || !len) return; extract_data(&main_state, len, dst); }
static unsigned get_rand_pool | ( | FState * | st | ) | [static] |
Definition at line 301 of file fortuna.c.
References BLOCK, fortuna_state::key, and fortuna_state::rnd_pos.
Referenced by add_entropy().
static void inc_counter | ( | FState * | st | ) | [static] |
Definition at line 193 of file fortuna.c.
References fortuna_state::counter, and val.
Referenced by encrypt_counter().
static void init_state | ( | FState * | st | ) | [static] |
Definition at line 179 of file fortuna.c.
References i, md_init(), and fortuna_state::pool.
Referenced by fortuna_add_entropy(), and fortuna_get_bytes().
static void md_init | ( | MD_CTX * | ctx | ) | [static] |
Definition at line 154 of file fortuna.c.
References SHA256_Init.
Referenced by add_entropy(), init_state(), and reseed().
{ SHA256_Init(ctx); }
static void md_result | ( | MD_CTX * | ctx, | |
uint8 * | dst | |||
) | [static] |
Definition at line 166 of file fortuna.c.
References SHA256_Final.
Referenced by add_entropy(), and reseed().
{ SHA256_CTX tmp; memcpy(&tmp, ctx, sizeof(*ctx)); SHA256_Final(dst, &tmp); memset(&tmp, 0, sizeof(tmp)); }
static void md_update | ( | MD_CTX * | ctx, | |
const uint8 * | data, | |||
int | len | |||
) | [static] |
Definition at line 160 of file fortuna.c.
References SHA256_Update.
Referenced by add_entropy(), reseed(), and startup_tricks().
{ SHA256_Update(ctx, data, len); }
static void rekey | ( | FState * | st | ) | [static] |
Definition at line 352 of file fortuna.c.
References BLOCK, fortuna_state::ciph, CIPH_BLOCK, ciph_init(), encrypt_counter(), and fortuna_state::key.
Referenced by extract_data(), and startup_tricks().
{ encrypt_counter(st, st->key); encrypt_counter(st, st->key + CIPH_BLOCK); ciph_init(&st->ciph, st->key, BLOCK); }
static void reseed | ( | FState * | st | ) | [static] |
Definition at line 255 of file fortuna.c.
References BLOCK, buf, fortuna_state::ciph, ciph_init(), fortuna_state::key, MD_CTX, md_init(), md_result(), md_update(), fortuna_state::pool, fortuna_state::pool0_bytes, and fortuna_state::reseed_count.
Referenced by extract_data().
{ unsigned k; unsigned n; MD_CTX key_md; uint8 buf[BLOCK]; /* set pool as empty */ st->pool0_bytes = 0; /* * Both #0 and #1 reseed would use only pool 0. Just skip #0 then. */ n = ++st->reseed_count; /* * The goal: use k-th pool only 1/(2^k) of the time. */ md_init(&key_md); for (k = 0; k < NUM_POOLS; k++) { md_result(&st->pool[k], buf); md_update(&key_md, buf, BLOCK); if (n & 1 || !n) break; n >>= 1; } /* add old key into mix too */ md_update(&key_md, st->key, BLOCK); /* now we have new key */ md_result(&key_md, st->key); /* use new key */ ciph_init(&st->ciph, st->key, BLOCK); memset(&key_md, 0, sizeof(key_md)); memset(buf, 0, BLOCK); }
static void startup_tricks | ( | FState * | st | ) | [static] |
Definition at line 366 of file fortuna.c.
References BLOCK, buf, CIPH_BLOCK, fortuna_state::counter, encrypt_counter(), i, md_update(), fortuna_state::pool, rekey(), and fortuna_state::tricks_done.
Referenced by extract_data().
{ int i; uint8 buf[BLOCK]; /* Use next block as counter. */ encrypt_counter(st, st->counter); /* Now shuffle pools, excluding #0 */ for (i = 1; i < NUM_POOLS; i++) { encrypt_counter(st, buf); encrypt_counter(st, buf + CIPH_BLOCK); md_update(&st->pool[i], buf, BLOCK); } memset(buf, 0, BLOCK); /* Hide the key. */ rekey(st); /* This can be done only once. */ st->tricks_done = 1; }
int init_done = 0 [static] |
Definition at line 436 of file fortuna.c.
Referenced by fortuna_add_entropy(), and fortuna_get_bytes().
FState main_state [static] |