From 5cf07901c5118a55c9d8e1c704283cfc744bb68b Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 21 May 2006 20:22:16 +0000
Subject: [PATCH] Fix errors in fortuna PRNG reseeding logic that could cause a
 predictable session key to be selected by pgp_sym_encrypt() in some cases. 
 This only affects non-OpenSSL-using builds.  Marko Kreen

---
 contrib/pgcrypto/fortuna.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/contrib/pgcrypto/fortuna.c b/contrib/pgcrypto/fortuna.c
index 1b13337301c..cf69cee28bc 100644
--- a/contrib/pgcrypto/fortuna.c
+++ b/contrib/pgcrypto/fortuna.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.5 2005/10/15 02:49:06 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.6 2006/05/21 20:22:16 tgl Exp $
  */
 
 #include "postgres.h"
@@ -219,7 +219,7 @@ encrypt_counter(FState * st, uint8 *dst)
  * microseconds.
  */
 static int
-too_often(FState * st)
+enough_time_passed(FState * st)
 {
 	int			ok;
 	struct timeval tv;
@@ -227,13 +227,22 @@ too_often(FState * st)
 
 	gettimeofday(&tv, NULL);
 
+	/* check how much time has passed */
 	ok = 0;
-	if (tv.tv_sec != last->tv_sec)
+	if (tv.tv_sec > last->tv_sec + 1)
 		ok = 1;
+	else if (tv.tv_sec == last->tv_sec + 1)
+	{
+		if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
+			ok = 1;
+	}
 	else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
 		ok = 1;
 
-	memcpy(last, &tv, sizeof(tv));
+	/* reseed will happen, update last_reseed_time */
+	if (ok)
+		memcpy(last, &tv, sizeof(tv));
+
 	memset(&tv, 0, sizeof(tv));
 
 	return ok;
@@ -372,7 +381,7 @@ extract_data(FState * st, unsigned count, uint8 *dst)
 	unsigned	block_nr = 0;
 
 	/* Can we reseed? */
-	if (st->pool0_bytes >= POOL0_FILL && !too_often(st))
+	if (st->pool0_bytes >= POOL0_FILL && enough_time_passed(st))
 		reseed(st);
 
 	/* Is counter initialized? */
-- 
GitLab