Module Name: src Committed By: bouyer Date: Sat Jan 26 21:35:23 UTC 2013
Modified Files: src/sys/kern [netbsd-6]: subr_cprng.c Log Message: Pull up following revision(s) (requested by tls in ticket #800): sys/kern/subr_cprng.c: revision 1.15 Fix a security issue: when we are reseeding a PRNG seeded early in boot before we had ever had any entropy, if something else has consumed the entropy that triggered the immediate reseed, we can reseed with as little as sizeof(int) bytes of entropy. To generate a diff of this commit: cvs rdiff -u -r1.5.2.6 -r1.5.2.7 src/sys/kern/subr_cprng.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/subr_cprng.c diff -u src/sys/kern/subr_cprng.c:1.5.2.6 src/sys/kern/subr_cprng.c:1.5.2.7 --- src/sys/kern/subr_cprng.c:1.5.2.6 Sat Nov 24 20:58:00 2012 +++ src/sys/kern/subr_cprng.c Sat Jan 26 21:35:23 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_cprng.c,v 1.5.2.6 2012/11/24 20:58:00 jdc Exp $ */ +/* $NetBSD: subr_cprng.c,v 1.5.2.7 2013/01/26 21:35:23 bouyer Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -46,7 +46,7 @@ #include <sys/cprng.h> -__KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.5.2.6 2012/11/24 20:58:00 jdc Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.5.2.7 2013/01/26 21:35:23 bouyer Exp $"); void cprng_init(void) @@ -84,6 +84,8 @@ cprng_strong_doreseed(cprng_strong_t *co &cc, sizeof(cc))) { panic("cprng %s: nist_ctr_drbg_reseed failed.", c->name); } + memset(c->reseed.data, 0, c->reseed.len); + #ifdef RND_VERBOSE printf("cprng %s: reseeded with rnd_filled = %d\n", c->name, rnd_filled); @@ -154,6 +156,17 @@ cprng_strong_reseed(void *const arg) mutex_exit(&c->mtx); } +static size_t +cprng_entropy_try(uint8_t *key, size_t keylen, int hard) +{ + int r; + r = rnd_extract_data(key, keylen, RND_EXTRACT_GOOD); + if (r != keylen && !hard) { + rnd_extract_data(key + r, keylen - r, RND_EXTRACT_ANY); + } + return r; +} + cprng_strong_t * cprng_strong_create(const char *const name, int ipl, int flags) { @@ -183,15 +196,13 @@ cprng_strong_create(const char *const na selinit(&c->selq); - r = rnd_extract_data(key, sizeof(key), RND_EXTRACT_GOOD); + r = cprng_entropy_try(key, sizeof(key), c->flags & CPRNG_INIT_ANY); if (r != sizeof(key)) { if (c->flags & CPRNG_INIT_ANY) { #ifdef DEBUG printf("cprng %s: WARNING insufficient " "entropy at creation.\n", name); #endif - rnd_extract_data(key + r, sizeof(key - r), - RND_EXTRACT_ANY); } else { hard++; } @@ -240,15 +251,18 @@ rekeyany: if (c->flags & CPRNG_REKEY_ANY) { uint8_t key[NIST_BLOCK_KEYLEN_BYTES]; - printf("cprng %s: WARNING pseudorandom rekeying.\n", - c->name); - rnd_extract_data(key, sizeof(key), RND_EXTRACT_ANY); + if (cprng_entropy_try(key, sizeof(key), 0) != + sizeof(key)) { + printf("cprng %s: WARNING " + "pseudorandom rekeying.\n", c->name); + } cc = cprng_counter(); if (nist_ctr_drbg_reseed(&c->drbg, key, sizeof(key), &cc, sizeof(cc))) { panic("cprng %s: nist_ctr_drbg_reseed " "failed.", c->name); } + memset(key, 0, sizeof(key)); } else { int wr;