[patch 2/9] Fortuna tweaks - Mailing list pgsql-patches
From | Marko Kreen |
---|---|
Subject | [patch 2/9] Fortuna tweaks |
Date | |
Msg-id | 20060711195802.524821000@localhost.localdomain Whole thread Raw |
List | pgsql-patches |
* Use Fortuna for pseudo-random bytes too, as those need to be high-quality also. OpenSSL internally acts same way. * Clarify add_entropy logic - before first reseed get_rand_pool() will return only 0, so make it explicit. * On reseeding on first request, don't check if the pool#0 is filled, use whatever is available. * The counter value is already randomized, to avoid known state. Do the same with pools. Thus no publicly known values in state. Index: pgsql/contrib/pgcrypto/internal.c =================================================================== *** pgsql.orig/contrib/pgcrypto/internal.c --- pgsql/contrib/pgcrypto/internal.c *************** px_find_cipher(const char *name, PX_Ciph *** 821,839 **** */ /* ! * Use libc for all 'public' bytes. ! * ! * That way we don't expose bytes from Fortuna ! * to the public, in case it has some bugs. */ int px_get_pseudo_random_bytes(uint8 *dst, unsigned count) { ! int i; ! ! for (i = 0; i < count; i++) ! *dst++ = random(); ! return i; } static time_t seed_time = 0; --- 821,832 ---- */ /* ! * Use always strong randomness. */ int px_get_pseudo_random_bytes(uint8 *dst, unsigned count) { ! return px_get_random_bytes(dst, count); } static time_t seed_time = 0; Index: pgsql/contrib/pgcrypto/fortuna.c =================================================================== *** pgsql.orig/contrib/pgcrypto/fortuna.c --- pgsql/contrib/pgcrypto/fortuna.c *************** struct fortuna_state *** 125,131 **** struct timeval last_reseed_time; unsigned pool0_bytes; unsigned rnd_pos; ! int counter_init; }; typedef struct fortuna_state FState; --- 125,131 ---- struct timeval last_reseed_time; unsigned pool0_bytes; unsigned rnd_pos; ! int tricks_done; }; typedef struct fortuna_state FState; *************** add_entropy(FState * st, const uint8 *da *** 332,338 **** /* * Make sure the pool 0 is initialized, then update randomly. */ ! if (st->reseed_count == 0 && st->pool0_bytes < POOL0_FILL) pos = 0; else pos = get_rand_pool(st); --- 332,338 ---- /* * Make sure the pool 0 is initialized, then update randomly. */ ! if (st->reseed_count == 0) pos = 0; else pos = get_rand_pool(st); *************** rekey(FState * st) *** 357,377 **** } /* ! * Fortuna relies on AES standing known-plaintext attack. ! * In case it does not, slow down the attacker by initialising ! * the couter to random value. */ static void ! init_counter(FState * st) { /* Use next block as counter. */ encrypt_counter(st, st->counter); /* Hide the key. */ rekey(st); ! /* The counter can be shuffled only once. */ ! st->counter_init = 1; } static void --- 357,390 ---- } /* ! * Hide public constants. (counter, pools > 0) ! * ! * This can also be viewed as spreading the startup ! * entropy over all of the components. */ static void ! startup_tricks(FState * st) { + 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; } static void *************** extract_data(FState * st, unsigned count *** 380,392 **** unsigned n; unsigned block_nr = 0; ! /* Can we reseed? */ ! if (st->pool0_bytes >= POOL0_FILL && enough_time_passed(st)) ! reseed(st); ! ! /* Is counter initialized? */ ! if (!st->counter_init) ! init_counter(st); while (count > 0) { --- 393,406 ---- 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) { --
pgsql-patches by date: