diff --git a/SOURCES/gnutls-3.3.8-fips-reseed.patch b/SOURCES/gnutls-3.3.8-fips-reseed.patch
new file mode 100644
index 0000000..438edda
--- /dev/null
+++ b/SOURCES/gnutls-3.3.8-fips-reseed.patch
@@ -0,0 +1,301 @@
+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();
+ }
diff --git a/SPECS/gnutls.spec b/SPECS/gnutls.spec
index 8dd3b37..c612bb4 100644
--- a/SPECS/gnutls.spec
+++ b/SPECS/gnutls.spec
@@ -3,7 +3,7 @@
 Summary: A TLS protocol implementation
 Name: gnutls
 Version: 3.3.8
-Release: 12%{?dist}
+Release: 12%{?dist}.1
 # The libraries are LGPLv2.1+, utilities are GPLv3+
 License: GPLv3+ and LGPLv2+
 Group: System Environment/Libraries
@@ -57,6 +57,7 @@ Patch21: gnutls-3.3.8-fips-rnd-regr.patch
 Patch22: gnutls-3.3.8-urandom-fd-fips.patch
 Patch23: gnutls-3.3.8-rnd-reregister.patch
 Patch24: gnutls-3.3.8-handshake-reset3.patch
+Patch25: gnutls-3.3.8-fips-reseed.patch
 
 # Wildcard bundling exception https://fedorahosted.org/fpc/ticket/174
 Provides: bundled(gnulib) = 20130424
@@ -181,6 +182,7 @@ This package contains Guile bindings for the library.
 %patch22 -p1 -b .init-fd-fips
 %patch23 -p1 -b .reregister
 %patch24 -p1 -b .handshake-reset3
+%patch25 -p1 -b .fips-reseed
 sed 's/gnutls_srp.c//g' -i lib/Makefile.in
 sed 's/gnutls_srp.lo//g' -i lib/Makefile.in
 rm -f lib/minitasn1/*.c lib/minitasn1/*.h
@@ -326,6 +328,10 @@ fi
 %endif
 
 %changelog
+* Fri Jun  5 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.8-12.1
+- Corrected reseed and respect of max_number_of_bits_per_request in 
+  FIPS140-2 mode. Also enhanced the initial tests. (#1228199)
+
 * Mon Jan  5 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> 3.3.8-12
 - corrected fix of handshake buffer resets (#1153106)