[patch 2/9] Fortuna tweaks

From: Marko Kreen <markokr(at)gmail(dot)com>
To: pgsql-patches(at)postgresql(dot)org
Subject: [patch 2/9] Fortuna tweaks
Date: 2006-07-11 19:57:35
Message-ID: 20060711195802.524821000@localhost.localdomain
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers 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)
{

--

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Marko Kreen 2006-07-11 19:57:36 [patch 3/9] Add support for SHA224
Previous Message Marko Kreen 2006-07-11 19:57:34 [patch 1/9] Silence compiler warnings in openssl.c

Browse pgsql-patches by date

  From Date Subject
Next Message Marko Kreen 2006-07-11 19:57:36 [patch 3/9] Add support for SHA224
Previous Message Marko Kreen 2006-07-11 19:57:34 [patch 1/9] Silence compiler warnings in openssl.c