Blob Blame History Raw
diff --git a/lib/nettle/int/drbg-aes-self-test.c b/lib/nettle/int/drbg-aes-self-test.c
index 9c87453..eb62cf0 100644
--- a/lib/nettle/int/drbg-aes-self-test.c
+++ b/lib/nettle/int/drbg-aes-self-test.c
@@ -104,7 +104,8 @@ int drbg_aes_self_test(void)
 	struct drbg_aes_ctx test_ctx;
 	struct drbg_aes_ctx test_ctx2;
 	struct priv_st priv;
-	int ret;
+	int ret, saved;
+	uint8_t *tmp;
 	unsigned char result[16];
 
 	memset(&priv, 0, sizeof(priv));
@@ -119,26 +120,32 @@ int drbg_aes_self_test(void)
 		return 0;
 	}
 
+	tmp = gnutls_malloc(MAX_DRBG_AES_GENERATE_SIZE+1);
+	if (tmp == NULL) {
+		gnutls_assert();
+		return 0;
+	}
+
 	for (i = 0; i < sizeof(tv) / sizeof(tv[0]); i++) {
 		/* Setup the key.  */
 		ret =
 		    drbg_aes_init(&test_ctx, DRBG_AES_SEED_SIZE, tv[i].entropy,
 				  strlen(tv[i].pstring), (void *)tv[i].pstring);
 		if (ret == 0)
-			return 0;
+			goto fail;
 
 		if (drbg_aes_is_seeded(&test_ctx) == 0)
-			return 0;
+			goto fail;
 
 		/* Get and compare the first three results.  */
 		for (j = 0; j < 3; j++) {
 			/* Compute the next value.  */
 			if (drbg_aes_random(&test_ctx, 16, result) == 0)
-				return 0;
+				goto fail;
 
 			/* Compare it to the known value.  */
 			if (memcmp(result, tv[i].res[j], 16) != 0) {
-				return 0;
+				goto fail;
 			}
 		}
 
@@ -146,20 +153,72 @@ int drbg_aes_self_test(void)
 		    drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE,
 				    tv[i].entropy, 0, NULL);
 		if (ret == 0)
-			return 0;
+			goto fail;
 
 		if (drbg_aes_random(&test_ctx, 16, result) == 0)
-			return 0;
+			goto fail;
 
 		if (memcmp(result, tv[i].res[3], 16) != 0) {
-			return 0;
+			goto fail;
 		}
 
 		/* test the error handling of drbg_aes_random() */
+		saved = test_ctx.reseed_counter;
 		test_ctx.reseed_counter = DRBG_AES_RESEED_TIME+1;
 		if (drbg_aes_random(&test_ctx, 16, result) != 0) {
 			gnutls_assert();
-			return 0;
+			goto fail;
+		}
+		test_ctx.reseed_counter = saved;
+
+		ret = drbg_aes_random(&test_ctx, MAX_DRBG_AES_GENERATE_SIZE+1, tmp);
+		if (ret == 0) {
+			gnutls_assert();
+			goto fail;
+		}
+
+		/* test the low-level function */
+		ret = drbg_aes_generate(&test_ctx, MAX_DRBG_AES_GENERATE_SIZE+1, tmp, 0, NULL);
+		if (ret != 0) {
+			gnutls_assert();
+			goto fail;
+		}
+
+		/* Test of the reseed function for error handling */
+		ret =
+		    drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE*2,
+				    (uint8_t*)tv, 0, NULL);
+		if (ret != 0)
+			goto fail;
+
+		ret =
+		    drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE,
+				    tv[i].entropy, DRBG_AES_SEED_SIZE*2, (uint8_t*)tv);
+		if (ret != 0)
+			goto fail;
+
+		/* check whether reseed detection works */
+		if (i==0) {
+			ret =
+			    drbg_aes_reseed(&test_ctx, DRBG_AES_SEED_SIZE,
+					    tv[i].entropy, 0, NULL);
+			if (ret == 0)
+				goto fail;
+
+			saved = test_ctx.reseed_counter;
+			test_ctx.reseed_counter = DRBG_AES_RESEED_TIME-4;
+			for (j=0;j<5;j++) {
+				if (drbg_aes_random(&test_ctx, 1, result) == 0) {
+					gnutls_assert();
+					goto fail;
+				}
+			}
+			/* that should fail */
+			if (drbg_aes_random(&test_ctx, 1, result) != 0) {
+				gnutls_assert();
+				goto fail;
+			}
+			test_ctx.reseed_counter = saved;
 		}
 
 		/* test deinit, which is zeroize_key() */
@@ -167,9 +226,15 @@ int drbg_aes_self_test(void)
 		zeroize_key(&test_ctx, sizeof(test_ctx));
 		if (memcmp(&test_ctx, &test_ctx2, sizeof(test_ctx)) == 0) {
 			gnutls_assert();
-			return 0;
+			goto fail;
 		}
+
+
 	}
 
+	free(tmp);
 	return 1;
+ fail:
+ 	free(tmp);
+ 	return 0;
 }
diff --git a/lib/nettle/int/drbg-aes.c b/lib/nettle/int/drbg-aes.c
index 5ff2484..43df5e1 100644
--- a/lib/nettle/int/drbg-aes.c
+++ b/lib/nettle/int/drbg-aes.c
@@ -22,6 +22,7 @@
 
 #include <config.h>
 #include <drbg-aes.h>
+#include <gnutls_errors.h>
 #include <nettle/memxor.h>
 #include <nettle/aes.h>
 #include <minmax.h>
@@ -67,7 +68,6 @@ drbg_aes_update(struct drbg_aes_ctx *ctx,
 
 	memcpy(ctx->v, &tmp[DRBG_AES_KEY_SIZE], AES_BLOCK_SIZE);
 
-	ctx->reseed_counter = 1;
 	ctx->seeded = 1;
 }
 
@@ -93,6 +93,27 @@ drbg_aes_reseed(struct drbg_aes_ctx *ctx,
 	memxor(tmp, entropy, entropy_size);
 
 	drbg_aes_update(ctx, tmp);
+	ctx->reseed_counter = 1;
+
+	return 1;
+}
+
+int drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst)
+{
+	unsigned p_len;
+	int left = length;
+	uint8_t *p = dst;
+	int ret;
+
+	while(left > 0) {
+		p_len = MIN(MAX_DRBG_AES_GENERATE_SIZE, left);
+		ret = drbg_aes_generate(ctx, p_len, p, 0, 0);
+		if (ret == 0)
+			return ret;
+
+		p += p_len;
+		left -= p_len;
+	}
 
 	return 1;
 }
@@ -106,11 +127,14 @@ int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
 	unsigned left;
 
 	if (ctx->seeded == 0)
-		return 0;
+		return gnutls_assert_val(0);
+
+	if (length > MAX_DRBG_AES_GENERATE_SIZE)
+		return gnutls_assert_val(0);
 
 	if (add_size > 0) {
 		if (add_size > DRBG_AES_SEED_SIZE)
-			return 0;
+			return gnutls_assert_val(0);
 		memcpy(seed, add, add_size);
 		if (add_size != DRBG_AES_SEED_SIZE)
 			memset(&seed[add_size], 0, DRBG_AES_SEED_SIZE - add_size);
@@ -140,7 +164,7 @@ int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
 		/* if detected loop */
 		if (memcmp(dst, ctx->prev_block, AES_BLOCK_SIZE) == 0) {
 			_gnutls_switch_lib_state(LIB_STATE_ERROR);
-			return 0;
+			return gnutls_assert_val(0);
 		}
 
 		memcpy(ctx->prev_block, dst, AES_BLOCK_SIZE);
@@ -154,7 +178,7 @@ int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
 		/* if detected loop */
 		if (memcmp(tmp, ctx->prev_block, AES_BLOCK_SIZE) == 0) {
 			_gnutls_switch_lib_state(LIB_STATE_ERROR);
-			return 0;
+			return gnutls_assert_val(0);
 		}
 
 		memcpy(ctx->prev_block, tmp, AES_BLOCK_SIZE);
@@ -162,7 +186,7 @@ int drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length, uint8_t * dst,
 	}
 
 	if (ctx->reseed_counter > DRBG_AES_RESEED_TIME)
-		return 0;
+		return gnutls_assert_val(0);
 	ctx->reseed_counter++;
 
 	drbg_aes_update(ctx, seed);
diff --git a/lib/nettle/int/drbg-aes.h b/lib/nettle/int/drbg-aes.h
index eb89be6..72608de 100644
--- a/lib/nettle/int/drbg-aes.h
+++ b/lib/nettle/int/drbg-aes.h
@@ -55,10 +55,13 @@ struct drbg_aes_ctx {
 	unsigned reseed_counter;
 };
 
+/* max_number_of_bits_per_request */
+#define MAX_DRBG_AES_GENERATE_SIZE 65536 /* 2^19 */
+
 /* This DRBG should be reseeded if reseed_counter exceeds
  * that number. Otherwise drbg_aes_random() will fail.
  */
-#define DRBG_AES_RESEED_TIME 65536
+#define DRBG_AES_RESEED_TIME 16777216
 
 /* The entropy provided in these functions should be of
  * size DRBG_AES_SEED_SIZE. Additional data and pers.
@@ -74,7 +77,10 @@ drbg_aes_reseed(struct drbg_aes_ctx *ctx,
 	unsigned entropy_size, const uint8_t *entropy, 
 	unsigned add_size, const uint8_t* add);
 
-#define drbg_aes_random(ctx, l, dst) drbg_aes_generate(ctx, l, dst, 0, NULL)
+/* our wrapper for the low-level drbg_aes_generate */
+int
+drbg_aes_random(struct drbg_aes_ctx *ctx, unsigned length,
+		uint8_t * dst);
 
 int
 drbg_aes_generate(struct drbg_aes_ctx *ctx, unsigned length,
diff --git a/tests/rng-fork.c b/tests/rng-fork.c
index ba9178e..45a18b4 100644
--- a/tests/rng-fork.c
+++ b/tests/rng-fork.c
@@ -53,6 +53,7 @@ void doit(void)
 	unsigned char buf1[64];
 	unsigned char buf2[64];
 	pid_t pid;
+	unsigned char *tmp;
 	int ret;
 	FILE *fp;
 	unsigned i;
@@ -119,6 +120,20 @@ void doit(void)
 			exit(1);
 		}
 	}
+#define TMP_SIZE (65*1024)
+	tmp = malloc(TMP_SIZE);
+	if (tmp == NULL) {
+		fail("memory error\n");
+		exit(1);
+	}
+	for (i = 0; i <= 65539; i++) {
+		ret = gnutls_rnd(GNUTLS_RND_RANDOM, tmp, TMP_SIZE);
+		if (ret < 0) {
+			fail("Error iterating RNG-random more than %u times for %d data\n", i, TMP_SIZE);
+			exit(1);
+		}
+	}
+	free(tmp);
 
 	gnutls_global_deinit();
 }