From: mdw Date: Sat, 17 Jun 2000 11:53:55 +0000 (+0000) Subject: Deprecate `rand_getgood'. Provide a new interface to ensure that a pool X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/commitdiff_plain/ac2fd5cd29bd9485c6d49badc4ed8287f908b799 Deprecate `rand_getgood'. Provide a new interface to ensure that a pool is well seeded. Use secure arena for memory allocation. --- diff --git a/rand.c b/rand.c index a93bf9b..c3b777d 100644 --- a/rand.c +++ b/rand.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: rand.c,v 1.4 1999/12/13 15:34:28 mdw Exp $ + * $Id: rand.c,v 1.5 2000/06/17 11:53:55 mdw Exp $ * * Secure random number generator * @@ -30,6 +30,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: rand.c,v $ + * Revision 1.5 2000/06/17 11:53:55 mdw + * Deprecate `rand_getgood'. Provide a new interface to ensure that a pool + * is well seeded. Use secure arena for memory allocation. + * * Revision 1.4 1999/12/13 15:34:28 mdw * Increase the entropy threshhold in rand_getgood. * @@ -53,6 +57,7 @@ #include #include +#include "arena.h" #include "blowfish-cbc.h" #include "paranoia.h" #include "rand.h" @@ -68,13 +73,16 @@ typedef struct gctx { rand_pool p; } gctx; -static gctx pool = { { &gops } }; /* Default random pool */ +static gctx *pool = 0; /* Default random pool */ /*----- Macros ------------------------------------------------------------*/ #define RAND_RESOLVE(r) do { \ - if ((r) == RAND_GLOBAL) \ - (r) = &pool.p; \ + if ((r) == RAND_GLOBAL) { \ + if (!pool) \ + pool = (gctx *)rand_create(); \ + (r) = &pool->p; \ + } \ } while (0) #define TIMER(r) do { \ @@ -91,7 +99,9 @@ static gctx pool = { { &gops } }; /* Default random pool */ * Returns: --- * * Use: Initializes a randomness pool. The pool doesn't start out - * very random: that's your job to sort out. + * very random: that's your job to sort out. A good suggestion + * would be to attach an appropriate noise source and call + * @rand_seed@. */ void rand_init(rand_pool *r) @@ -131,6 +141,31 @@ void rand_noisesrc(rand_pool *r, const rand_source *s) r->s = s; } +/* --- @rand_seed@ --- * + * + * Arguments: @rand_pool *r@ = pointer to a randomness pool + * @unsigned bits@ = number of bits to ensure + * + * Returns: --- + * + * Use: Ensures that there are at least @bits@ good bits of entropy + * in the pool. It is recommended that you call this after + * initializing a new pool. Requesting @bits > RAND_IBITS@ is + * doomed to failure (and is an error). + */ + +void rand_seed(rand_pool *r, unsigned bits) +{ + RAND_RESOLVE(r); + + assert(((void)"bits pointlessly large in rand_seed", bits <= RAND_IBITS)); + assert(((void)"no noise source in rand_seed", r->s)); + + while (r->ibits < bits) + r->s->getnoise(r); + rand_gate(r); +} + /* --- @rand_key@ --- * * * Arguments: @rand_pool *r@ = pointer to a randomness pool @@ -364,13 +399,11 @@ void rand_get(rand_pool *r, void *p, size_t sz) * * Returns: --- * - * Use: Gets random data from the pool. The pool's contents can't be - * determined from the output of this function; nor can the - * output data be determined from a knowledge of the data input - * to the pool wihtout also having knowledge of the secret key. - * If a noise source is attached to the pool in question, it is - * called to replenish the supply of good bits in the pool; - * otherwise this call is equivalent to @rand_get@. + * Use: Gets random data from the pool, ensuring that there are + * enough good bits. This interface isn't recommended: it makes + * the generator slow, and doesn't provide much more security + * than @rand_get@, assuming you've previously done a + * @rand_seed@. */ void rand_getgood(rand_pool *r, void *p, size_t sz) @@ -411,20 +444,34 @@ void rand_getgood(rand_pool *r, void *p, size_t sz) /*----- Generic random number generator interface -------------------------*/ +#define GRESOLVE(g, r) do { \ + if (r != &rand_global) \ + g = (gctx *)r; \ + else { \ + if (!pool) \ + pool = (gctx *)rand_create(); \ + g = pool; \ + } \ +} while (0) + static void gdestroy(grand *r) { - gctx *g = (r == &rand_global ? &pool : (gctx *)r); - if (g != &pool) - DESTROY(g); + gctx *g; + GRESOLVE(g, r); + if (g != pool) { + BURN(*g); + S_DESTROY(g); + } } static int gmisc(grand *r, unsigned op, ...) { - gctx *g = (r == &rand_global ? &pool : (gctx *)r); + gctx *g; va_list ap; int rc = 0; va_start(ap, op); + GRESOLVE(g, r); switch (op) { case GRAND_CHECK: switch (va_arg(ap, unsigned)) { @@ -437,6 +484,7 @@ static int gmisc(grand *r, unsigned op, ...) case RAND_STRETCH: case RAND_KEY: case RAND_NOISESRC: + case RAND_SEED: rc = 1; break; default: @@ -477,6 +525,9 @@ static int gmisc(grand *r, unsigned op, ...) case RAND_NOISESRC: rand_noisesrc(&g->p, va_arg(ap, const rand_source *)); break; + case RAND_SEED: + rand_seed(&g->p, va_arg(ap, unsigned)); + break; default: GRAND_BADOP; break; @@ -488,29 +539,32 @@ static int gmisc(grand *r, unsigned op, ...) static octet gbyte(grand *r) { - gctx *g = (r == &rand_global ? &pool : (gctx *)r); + gctx *g; octet o; + GRESOLVE(g, r); rand_getgood(&g->p, &o, 1); return (o); } static uint32 gword(grand *r) { - gctx *g = (r == &rand_global ? &pool : (gctx *)r); + gctx *g; octet b[4]; + GRESOLVE(g, r); rand_getgood(&g->p, &b, sizeof(b)); return (LOAD32(b)); } static void gfill(grand *r, void *p, size_t sz) { - gctx *g = (r == &rand_global ? &pool : (gctx *)r); - rand_getgood(&g->p, p, sz); + gctx *g; + GRESOLVE(g, r); + rand_get(&g->p, p, sz); } static const grand_ops gops = { "rand", - 0, + GRAND_CRYPTO, 0, gmisc, gdestroy, gword, gbyte, gword, grand_range, gfill }; @@ -529,7 +583,7 @@ grand rand_global = { &gops }; grand *rand_create(void) { - gctx *g = CREATE(gctx); + gctx *g = S_CREATE(gctx); g->r.ops = &gops; rand_init(&g->p); return (&g->r);