]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
The AES-CTR-based nonce random number generator was replaced with salsa20.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 26 Jan 2014 10:18:38 +0000 (11:18 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 26 Jan 2014 10:19:13 +0000 (11:19 +0100)
lib/nettle/rnd-common.c
lib/nettle/rnd-fips.c
lib/nettle/rnd.c

index 46f74269a701c92274f9e2ada22acb9d8e7c8c69..9bb9c6fa7cccd31484845487093f003bc64036ab 100644 (file)
@@ -215,39 +215,3 @@ void _rnd_system_entropy_deinit(void)
 }
 #endif
 
-#define PSTRING "gnutls-rng"
-#define PSTRING_SIZE (sizeof(PSTRING)-1)
-int drbg_init(struct drbg_aes_ctx *ctx)
-{
-       uint8_t buffer[DRBG_AES_SEED_SIZE];
-       int ret;
-
-       /* Get a key from the standard RNG or from the entropy source.  */
-       ret = _rnd_get_system_entropy(buffer, sizeof(buffer));
-       if (ret < 0)
-               return gnutls_assert_val(ret);
-
-       ret = drbg_aes_init(ctx, sizeof(buffer), buffer, PSTRING_SIZE, (void*)PSTRING);
-       if (ret == 0)
-               return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
-
-       zeroize_key(buffer, sizeof(buffer));
-
-       return 0;
-}
-
-/* Reseed a generator. */
-int drbg_reseed(struct drbg_aes_ctx *ctx)
-{
-       uint8_t buffer[DRBG_AES_SEED_SIZE];
-       int ret;
-
-       /* The other two generators are seeded from /dev/random.  */
-       ret = _rnd_get_system_entropy(buffer, sizeof(buffer));
-       if (ret < 0)
-               return gnutls_assert_val(ret);
-
-       drbg_aes_reseed(ctx, sizeof(buffer), buffer, 0, NULL);
-
-       return 0;
-}
index 7c3501f1713a3e919691c12c4bb96d129acc55a7..e4b56297467e33c62b2c168d1b87e44f9b06b3e2 100644 (file)
@@ -78,6 +78,43 @@ static int get_random(struct drbg_aes_ctx *ctx, struct fips_ctx *fctx,
        return 0;
 }
 
+#define PSTRING "gnutls-rng"
+#define PSTRING_SIZE (sizeof(PSTRING)-1)
+static int drbg_init(struct drbg_aes_ctx *ctx)
+{
+       uint8_t buffer[DRBG_AES_SEED_SIZE];
+       int ret;
+
+       /* Get a key from the standard RNG or from the entropy source.  */
+       ret = _rnd_get_system_entropy(buffer, sizeof(buffer));
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
+       ret = drbg_aes_init(ctx, sizeof(buffer), buffer, PSTRING_SIZE, (void*)PSTRING);
+       if (ret == 0)
+               return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
+
+       zeroize_key(buffer, sizeof(buffer));
+
+       return 0;
+}
+
+/* Reseed a generator. */
+static int drbg_reseed(struct drbg_aes_ctx *ctx)
+{
+       uint8_t buffer[DRBG_AES_SEED_SIZE];
+       int ret;
+
+       /* The other two generators are seeded from /dev/random.  */
+       ret = _rnd_get_system_entropy(buffer, sizeof(buffer));
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
+       drbg_aes_reseed(ctx, sizeof(buffer), buffer, 0, NULL);
+
+       return 0;
+}
+
 static int _rngfips_ctx_init(struct fips_ctx *fctx)
 {
        int ret;
index aaee309f5f5779328e2c6e78e0998c7b66ed3404..4951b4ed04cc99c9bf90abd561029c275f07d526 100644 (file)
@@ -32,6 +32,7 @@
 #include <locks.h>
 #include <gnutls_num.h>
 #include <nettle/yarrow.h>
+#include <nettle/salsa20.h>
 #ifdef HAVE_GETPID
 #include <unistd.h>            /* getpid */
 #endif
@@ -50,7 +51,18 @@ enum {
 
 static struct yarrow256_ctx yctx;
 static struct yarrow_source ysources[SOURCES];
-static struct drbg_aes_ctx nonce_ctx;
+
+struct nonce_ctx_st {
+       struct salsa20_ctx ctx;
+       unsigned int counter;
+#ifdef HAVE_GETPID
+       pid_t pid;              /* detect fork() */
+#endif
+};
+
+/* after this number of bytes salsa20 will reseed */
+#define NONCE_RESEED_BYTES (1048576)
+static struct nonce_ctx_st nonce_ctx;
 
 static struct timespec device_last_read = { 0, 0 };
 
@@ -153,6 +165,28 @@ static void wrap_nettle_rnd_deinit(void *ctx)
        rnd_mutex = NULL;
 }
 
+static int nonce_rng_init(struct nonce_ctx_st *ctx)
+{
+       uint8_t buffer[SALSA20_KEY_SIZE];
+       int ret;
+
+       /* Get a key from the standard RNG or from the entropy source.  */
+       ret = _rnd_get_system_entropy(buffer, sizeof(buffer));
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
+       salsa20_set_key(&ctx->ctx, sizeof(buffer), buffer);
+
+       zeroize_key(buffer, sizeof(buffer));
+
+       ctx->counter = 0;
+#ifdef HAVE_GETPID
+       ctx->pid = getpid();
+#endif
+
+       return 0;
+}
+
 /* API functions */
 
 static int wrap_nettle_rnd_init(void **ctx)
@@ -165,7 +199,7 @@ static int wrap_nettle_rnd_init(void **ctx)
                gnutls_assert();
                return ret;
        }
-       
+
        ret = _rnd_system_entropy_init();
        if (ret < 0) {
                gnutls_assert();
@@ -190,15 +224,54 @@ static int wrap_nettle_rnd_init(void **ctx)
        }
 
        yarrow256_slow_reseed(&yctx);
-       
+
        /* initialize the nonce RNG */
-       ret = drbg_init(&nonce_ctx);
+       ret = nonce_rng_init(&nonce_ctx);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
        return 0;
 }
 
+static int
+wrap_nettle_rnd_nonce(void *_ctx, void *data, size_t datasize)
+{
+       int ret, reseed = 0;
+#ifdef HAVE_GETPID
+       pid_t tpid = getpid();
+#endif
+
+       RND_LOCK;
+
+#ifdef HAVE_GETPID
+       if (tpid != nonce_ctx.pid) {    /* fork() detected */
+               reseed = 1;
+       }
+#endif
+
+       if (reseed != 0 || nonce_ctx.counter > NONCE_RESEED_BYTES) {
+               /* reseed nonce */
+               ret = nonce_rng_init(&nonce_ctx);
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+       }
+
+       /* we don't really need memset here, but otherwise we
+        * get filled with valgrind warnings */
+       memset(data, 0, datasize);
+       salsa20r12_crypt(&nonce_ctx.ctx, datasize, data, data);
+       nonce_ctx.counter += datasize;
+
+       ret = 0;
+
+cleanup:
+       RND_UNLOCK;
+       return ret;
+}
+
+
 
 static int
 wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
@@ -206,10 +279,13 @@ wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
        int ret, reseed = 0;
        struct event_st event;
 
+       if (level == GNUTLS_RND_NONCE)
+               return wrap_nettle_rnd_nonce(_ctx, data, datasize);
+
        _rnd_get_event(&event);
 
        RND_LOCK;
-       
+
 #ifdef HAVE_GETPID
        if (event.pid != pid) { /* fork() detected */
                memset(&device_last_read, 0, sizeof(device_last_read));
@@ -218,45 +294,26 @@ wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
        }
 #endif
 
-       if (level != GNUTLS_RND_NONCE) {
-               /* reseed main */
-               ret = do_trivia_source(0, &event);
-               if (ret < 0) {
-                       RND_UNLOCK;
-                       gnutls_assert();
-                       return ret;
-               }
+       /* reseed main */
+       ret = do_trivia_source(0, &event);
+       if (ret < 0) {
+               gnutls_assert();
+               goto cleanup;
+       }
 
-               ret = do_device_source(0, &event);
-               if (ret < 0) {
-                       RND_UNLOCK;
-                       gnutls_assert();
-                       return ret;
-               }
-       } else if (nonce_ctx.reseed_counter > DRBG_AES_RESEED_TIME){
-               reseed = 1;
+       ret = do_device_source(0, &event);
+       if (ret < 0) {
+               gnutls_assert();
+               goto cleanup;
        }
 
-       if (level == GNUTLS_RND_NONCE) {
-               if (reseed != 0) {
-                       /* reseed nonce */
-                       ret = drbg_reseed(&nonce_ctx);
-                       if (ret < 0)
-                               return gnutls_assert_val(ret);
-               }
+       if (reseed != 0)
+               yarrow256_slow_reseed(&yctx);
 
-               ret = drbg_aes_random(&nonce_ctx, datasize, data);
-               if (ret == 0)
-                       ret = GNUTLS_E_RANDOM_FAILED;
-               else
-                       ret = 0;
-       } else {
-               if (reseed != 0)
-                       yarrow256_slow_reseed(&yctx);
+       yarrow256_random(&yctx, datasize, data);
+       ret = 0;
 
-               yarrow256_random(&yctx, datasize, data);
-               ret = 0;
-       }
+cleanup:
        RND_UNLOCK;
        return ret;
 }