Blame SOURCES/gnutls-3.3.8-fips-reseed.patch

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