- Fix Weak Entropy Used For Nettle,

reported by X41 D-Sec.
This commit is contained in:
W.C.A. Wijngaards 2019-11-20 11:28:53 +01:00
parent 7e3da817c3
commit d8809c672a
8 changed files with 15 additions and 42 deletions

View file

@ -429,9 +429,7 @@ daemon_create_workers(struct daemon* daemon)
int* shufport; int* shufport;
log_assert(daemon && daemon->cfg); log_assert(daemon && daemon->cfg);
if(!daemon->rand) { if(!daemon->rand) {
unsigned int seed = (unsigned int)time(NULL) ^ daemon->rand = ub_initstate(NULL);
(unsigned int)getpid() ^ 0x438;
daemon->rand = ub_initstate(seed, NULL);
if(!daemon->rand) if(!daemon->rand)
fatal_exit("could not init random generator"); fatal_exit("could not init random generator");
hash_set_raninit((uint32_t)ub_random(daemon->rand)); hash_set_raninit((uint32_t)ub_random(daemon->rand));

View file

@ -1681,11 +1681,7 @@ worker_create(struct daemon* daemon, int id, int* ports, int n)
return NULL; return NULL;
} }
/* create random state here to avoid locking trouble in RAND_bytes */ /* create random state here to avoid locking trouble in RAND_bytes */
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^ if(!(worker->rndstate = ub_initstate(daemon->rand))) {
(((unsigned int)worker->thread_num)<<17);
/* shift thread_num so it does not match out pid bits */
if(!(worker->rndstate = ub_initstate(seed, daemon->rand))) {
explicit_bzero(&seed, sizeof(seed));
log_err("could not init random numbers."); log_err("could not init random numbers.");
tube_delete(worker->cmd); tube_delete(worker->cmd);
free(worker->ports); free(worker->ports);

View file

@ -6,6 +6,8 @@
- Fix Shared Memory World Writeable, - Fix Shared Memory World Writeable,
reported by X41 D-Sec. reported by X41 D-Sec.
- Adjust unbound-control to make stats_shm a read only operation. - Adjust unbound-control to make stats_shm a read only operation.
- Fix Weak Entropy Used For Nettle,
reported by X41 D-Sec.
19 November 2019: Wouter 19 November 2019: Wouter
- Fix CVE-2019-18934, shell execution in ipsecmod. - Fix CVE-2019-18934, shell execution in ipsecmod.

View file

@ -86,7 +86,6 @@ int ctx_logfile_overridden = 0;
static struct ub_ctx* ub_ctx_create_nopipe(void) static struct ub_ctx* ub_ctx_create_nopipe(void)
{ {
struct ub_ctx* ctx; struct ub_ctx* ctx;
unsigned int seed;
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
int r; int r;
WSADATA wsa_data; WSADATA wsa_data;
@ -111,15 +110,12 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
return NULL; return NULL;
} }
alloc_init(&ctx->superalloc, NULL, 0); alloc_init(&ctx->superalloc, NULL, 0);
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid(); if(!(ctx->seed_rnd = ub_initstate(NULL))) {
if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) {
explicit_bzero(&seed, sizeof(seed));
ub_randfree(ctx->seed_rnd); ub_randfree(ctx->seed_rnd);
free(ctx); free(ctx);
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }
explicit_bzero(&seed, sizeof(seed));
lock_basic_init(&ctx->qqpipe_lock); lock_basic_init(&ctx->qqpipe_lock);
lock_basic_init(&ctx->rrpipe_lock); lock_basic_init(&ctx->rrpipe_lock);
lock_basic_init(&ctx->cfglock); lock_basic_init(&ctx->cfglock);

View file

@ -122,7 +122,6 @@ libworker_delete_event(struct libworker* w)
static struct libworker* static struct libworker*
libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb) libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
{ {
unsigned int seed;
struct libworker* w = (struct libworker*)calloc(1, sizeof(*w)); struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
struct config_file* cfg = ctx->env->cfg; struct config_file* cfg = ctx->env->cfg;
int* ports; int* ports;
@ -177,17 +176,13 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
} }
w->env->worker = (struct worker*)w; w->env->worker = (struct worker*)w;
w->env->probe_timer = NULL; w->env->probe_timer = NULL;
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
(((unsigned int)w->thread_num)<<17);
seed ^= (unsigned int)w->env->alloc->next_id;
if(!w->is_bg || w->is_bg_thread) { if(!w->is_bg || w->is_bg_thread) {
lock_basic_lock(&ctx->cfglock); lock_basic_lock(&ctx->cfglock);
} }
if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) { if(!(w->env->rnd = ub_initstate(ctx->seed_rnd))) {
if(!w->is_bg || w->is_bg_thread) { if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock); lock_basic_unlock(&ctx->cfglock);
} }
explicit_bzero(&seed, sizeof(seed));
libworker_delete(w); libworker_delete(w);
return NULL; return NULL;
} }
@ -207,7 +202,6 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
hash_set_raninit((uint32_t)ub_random(w->env->rnd)); hash_set_raninit((uint32_t)ub_random(w->env->rnd));
} }
} }
explicit_bzero(&seed, sizeof(seed));
if(eb) if(eb)
w->base = comm_base_create_event(eb); w->base = comm_base_create_event(eb);

View file

@ -538,10 +538,8 @@ rnd_test(void)
struct ub_randstate* r; struct ub_randstate* r;
int num = 1000, i; int num = 1000, i;
long int a[1000]; long int a[1000];
unsigned int seed = (unsigned)time(NULL);
unit_show_feature("ub_random"); unit_show_feature("ub_random");
printf("ub_random seed is %u\n", seed); unit_assert( (r = ub_initstate(NULL)) );
unit_assert( (r = ub_initstate(seed, NULL)) );
for(i=0; i<num; i++) { for(i=0; i<num; i++) {
a[i] = ub_random(r); a[i] = ub_random(r);
unit_assert(a[i] >= 0); unit_assert(a[i] >= 0);

View file

@ -86,8 +86,7 @@ ub_systemseed(unsigned int ATTR_UNUSED(seed))
} }
struct ub_randstate* struct ub_randstate*
ub_initstate(unsigned int ATTR_UNUSED(seed), ub_initstate(struct ub_randstate* ATTR_UNUSED(from))
struct ub_randstate* ATTR_UNUSED(from))
{ {
struct ub_randstate* s = (struct ub_randstate*)malloc(1); struct ub_randstate* s = (struct ub_randstate*)malloc(1);
if(!s) { if(!s) {
@ -123,8 +122,7 @@ void ub_systemseed(unsigned int ATTR_UNUSED(seed))
{ {
} }
struct ub_randstate* ub_initstate(unsigned int ATTR_UNUSED(seed), struct ub_randstate* ub_initstate(struct ub_randstate* ATTR_UNUSED(from))
struct ub_randstate* ATTR_UNUSED(from))
{ {
struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s)); struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));
if(!s) { if(!s) {
@ -166,8 +164,7 @@ void ub_systemseed(unsigned int ATTR_UNUSED(seed))
log_err("Re-seeding not supported, generator untouched"); log_err("Re-seeding not supported, generator untouched");
} }
struct ub_randstate* ub_initstate(unsigned int seed, struct ub_randstate* ub_initstate(struct ub_randstate* ATTR_UNUSED(from))
struct ub_randstate* ATTR_UNUSED(from))
{ {
struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s)); struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));
uint8_t buf[YARROW256_SEED_FILE_SIZE]; uint8_t buf[YARROW256_SEED_FILE_SIZE];
@ -183,15 +180,10 @@ struct ub_randstate* ub_initstate(unsigned int seed,
yarrow256_seed(&s->ctx, YARROW256_SEED_FILE_SIZE, buf); yarrow256_seed(&s->ctx, YARROW256_SEED_FILE_SIZE, buf);
s->seeded = yarrow256_is_seeded(&s->ctx); s->seeded = yarrow256_is_seeded(&s->ctx);
} else { } else {
/* Stretch the uint32 input seed and feed it to Yarrow */ log_err("nettle random(yarrow) cannot initialize, "
uint32_t v = seed; "getentropy failed: %s", strerror(errno));
size_t i; free(s);
for(i=0; i < (YARROW256_SEED_FILE_SIZE/sizeof(seed)); i++) { return NULL;
memmove(buf+i*sizeof(seed), &v, sizeof(seed));
v = v*seed + (uint32_t)i;
}
yarrow256_seed(&s->ctx, YARROW256_SEED_FILE_SIZE, buf);
s->seeded = yarrow256_is_seeded(&s->ctx);
} }
return s; return s;

View file

@ -57,15 +57,12 @@ void ub_systemseed(unsigned int seed);
/** /**
* Initialize a random generator state for use * Initialize a random generator state for use
* @param seed: seed value to create state contents.
* (ignored for arc4random).
* @param from: if not NULL, the seed is taken from this random structure. * @param from: if not NULL, the seed is taken from this random structure.
* can be used to seed random states via a parent-random-state that * can be used to seed random states via a parent-random-state that
* is itself seeded with entropy. * is itself seeded with entropy.
* @return new state or NULL alloc failure. * @return new state or NULL alloc failure.
*/ */
struct ub_randstate* ub_initstate(unsigned int seed, struct ub_randstate* ub_initstate(struct ub_randstate* from);
struct ub_randstate* from);
/** /**
* Generate next random number from the state passed along. * Generate next random number from the state passed along.