#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] |
1.7.1