Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Fix a security issue: when we are reseeding a PRNG ...



details:   https://anonhg.NetBSD.org/src/rev/f9647d3cbfb7
branches:  trunk
changeset: 784351:f9647d3cbfb7
user:      tls <tls%NetBSD.org@localhost>
date:      Sat Jan 26 16:05:34 2013 +0000

description:
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.

diffstat:

 sys/kern/subr_cprng.c |  30 ++++++++++++++++++++++--------
 1 files changed, 22 insertions(+), 8 deletions(-)

diffs (84 lines):

diff -r 7c1914131bcc -r f9647d3cbfb7 sys/kern/subr_cprng.c
--- a/sys/kern/subr_cprng.c     Sat Jan 26 16:00:04 2013 +0000
+++ b/sys/kern/subr_cprng.c     Sat Jan 26 16:05:34 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_cprng.c,v 1.14 2012/11/20 11:06:27 msaitoh Exp $ */
+/*     $NetBSD: subr_cprng.c,v 1.15 2013/01/26 16:05:34 tls 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.14 2012/11/20 11:06:27 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.15 2013/01/26 16:05:34 tls Exp $");
 
 void
 cprng_init(void)
@@ -84,6 +84,8 @@
                                 &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 @@
        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 @@
 
        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 @@
                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;
 



Home | Main Index | Thread Index | Old Index