From eb238134e0a0fb5ac5c8239ade1dfe77a815aba5 Mon Sep 17 00:00:00 2001
From: Kurt Roeckx <kurt@roeckx.be>
Date: Sun, 18 Feb 2018 19:26:55 +0100
Subject: [PATCH] Propagate the request for prediction resistance to the get
 entropy call

Reviewed-by: Dr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
GH: #5402
---
 crypto/include/internal/rand_int.h |  3 ++-
 crypto/rand/drbg_lib.c             | 14 +++++++++-----
 crypto/rand/rand_lib.c             |  5 +++--
 include/openssl/rand_drbg.h        |  6 ++++--
 test/drbgtest.c                    | 20 +++++++++++---------
 5 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/crypto/include/internal/rand_int.h b/crypto/include/internal/rand_int.h
index d90d9c5f63..27ca703fcf 100644
--- a/crypto/include/internal/rand_int.h
+++ b/crypto/include/internal/rand_int.h
@@ -34,7 +34,8 @@ size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool);
 /* DRBG entropy callbacks. */
 size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
                              unsigned char **pout,
-                             int entropy, size_t min_len, size_t max_len);
+                             int entropy, size_t min_len, size_t max_len,
+                             int prediction_resistance);
 void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
                                unsigned char *out, size_t outlen);
 size_t rand_drbg_get_additional_data(unsigned char **pout, size_t max_len);
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index 02ad071ad4..360ea7ce3d 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -327,7 +327,8 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
     drbg->state = DRBG_ERROR;
     if (drbg->get_entropy != NULL)
         entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
-                                   drbg->min_entropylen, drbg->max_entropylen);
+                                       drbg->min_entropylen,
+                                       drbg->max_entropylen, 0);
     if (entropylen < drbg->min_entropylen
         || entropylen > drbg->max_entropylen) {
         RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_ENTROPY);
@@ -411,7 +412,8 @@ int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
  * Returns 1 on success, 0 on failure.
  */
 int RAND_DRBG_reseed(RAND_DRBG *drbg,
-                     const unsigned char *adin, size_t adinlen)
+                     const unsigned char *adin, size_t adinlen,
+                     int prediction_resistance)
 {
     unsigned char *entropy = NULL;
     size_t entropylen = 0;
@@ -435,7 +437,9 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
     drbg->state = DRBG_ERROR;
     if (drbg->get_entropy != NULL)
         entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
-                                   drbg->min_entropylen, drbg->max_entropylen);
+                                       drbg->min_entropylen,
+                                       drbg->max_entropylen,
+                                       prediction_resistance);
     if (entropylen < drbg->min_entropylen
         || entropylen > drbg->max_entropylen) {
         RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ERROR_RETRIEVING_ENTROPY);
@@ -551,7 +555,7 @@ int rand_drbg_restart(RAND_DRBG *drbg,
             drbg->meth->reseed(drbg, adin, adinlen, NULL, 0);
         } else if (reseeded == 0) {
             /* do a full reseeding if it has not been done yet above */
-            RAND_DRBG_reseed(drbg, NULL, 0);
+            RAND_DRBG_reseed(drbg, NULL, 0, 0);
         }
     }
 
@@ -627,7 +631,7 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
     }
 
     if (reseed_required || prediction_resistance) {
-        if (!RAND_DRBG_reseed(drbg, adin, adinlen)) {
+        if (!RAND_DRBG_reseed(drbg, adin, adinlen, prediction_resistance)) {
             RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_RESEED_ERROR);
             return 0;
         }
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 76d5767ccd..1e60ec4bb6 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -171,8 +171,9 @@ size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool)
  * its entropy will be used up first.
  */
 size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
-                        unsigned char **pout,
-                        int entropy, size_t min_len, size_t max_len)
+                             unsigned char **pout,
+                             int entropy, size_t min_len, size_t max_len,
+                             int prediction_resistance)
 {
     size_t ret = 0;
     size_t entropy_available = 0;
diff --git a/include/openssl/rand_drbg.h b/include/openssl/rand_drbg.h
index 17ca979da2..790dca5e88 100644
--- a/include/openssl/rand_drbg.h
+++ b/include/openssl/rand_drbg.h
@@ -61,7 +61,8 @@ void RAND_DRBG_free(RAND_DRBG *drbg);
  * Object "use" functions.
  */
 int RAND_DRBG_reseed(RAND_DRBG *drbg,
-                     const unsigned char *adin, size_t adinlen);
+                     const unsigned char *adin, size_t adinlen,
+                     int prediction_resistance);
 int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
                        int prediction_resistance,
                        const unsigned char *adin, size_t adinlen);
@@ -95,7 +96,8 @@ void *RAND_DRBG_get_ex_data(const RAND_DRBG *dctx, int idx);
 typedef size_t (*RAND_DRBG_get_entropy_fn)(RAND_DRBG *ctx,
                                            unsigned char **pout,
                                            int entropy, size_t min_len,
-                                           size_t max_len);
+                                           size_t max_len,
+                                           int prediction_resistance);
 typedef void (*RAND_DRBG_cleanup_entropy_fn)(RAND_DRBG *ctx,
                                              unsigned char *out, size_t outlen);
 typedef size_t (*RAND_DRBG_get_nonce_fn)(RAND_DRBG *ctx, unsigned char **pout,
diff --git a/test/drbgtest.c b/test/drbgtest.c
index c64628a756..4c872f8871 100644
--- a/test/drbgtest.c
+++ b/test/drbgtest.c
@@ -118,7 +118,8 @@ typedef struct test_ctx_st {
 } TEST_CTX;
 
 static size_t kat_entropy(RAND_DRBG *drbg, unsigned char **pout,
-                          int entropy, size_t min_len, size_t max_len)
+                          int entropy, size_t min_len, size_t max_len,
+                          int prediction_resistance)
 {
     TEST_CTX *t = (TEST_CTX *)RAND_DRBG_get_ex_data(drbg, app_data_index);
 
@@ -182,7 +183,7 @@ static int single_kat(DRBG_SELFTEST_DATA *td)
     /* Reseed DRBG with test entropy and additional input */
     t.entropy = td->entropyreseed;
     t.entropylen = td->entropyreseedlen;
-    if (!TEST_true(RAND_DRBG_reseed(drbg, td->adinreseed, td->adinreseedlen)
+    if (!TEST_true(RAND_DRBG_reseed(drbg, td->adinreseed, td->adinreseedlen, 0)
             || !TEST_true(RAND_DRBG_generate(drbg, buff, td->kat2len, 0,
                                              td->adin2, td->adin2len))
             || !TEST_mem_eq(td->kat2, td->kat2len, buff, td->kat2len)))
@@ -415,12 +416,12 @@ static int error_check(DRBG_SELFTEST_DATA *td)
 
     /* Test explicit reseed with too large additional input */
     if (!init(drbg, td, &t)
-            || RAND_DRBG_reseed(drbg, td->adin, drbg->max_adinlen + 1) > 0)
+            || RAND_DRBG_reseed(drbg, td->adin, drbg->max_adinlen + 1, 0) > 0)
         goto err;
 
     /* Test explicit reseed with entropy source failure */
     t.entropylen = 0;
-    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen), 0)
+    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
             || !uninstantiate(drbg))
         goto err;
 
@@ -428,7 +429,7 @@ static int error_check(DRBG_SELFTEST_DATA *td)
     if (!init(drbg, td, &t))
         goto err;
     t.entropylen = drbg->max_entropylen + 1;
-    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen), 0)
+    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
             || !uninstantiate(drbg))
         goto err;
 
@@ -436,7 +437,7 @@ static int error_check(DRBG_SELFTEST_DATA *td)
     if (!init(drbg, td, &t))
         goto err;
     t.entropylen = drbg->min_entropylen - 1;
-    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen), 0)
+    if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
             || !uninstantiate(drbg))
         goto err;
 
@@ -504,7 +505,8 @@ static HOOK_CTX *get_hook_ctx(RAND_DRBG *drbg)
 
 /* Intercepts and counts calls to the get_entropy() callback */
 static size_t get_entropy_hook(RAND_DRBG *drbg, unsigned char **pout,
-                          int entropy, size_t min_len, size_t max_len)
+                              int entropy, size_t min_len, size_t max_len,
+                              int prediction_resistance)
 {
     size_t ret;
     HOOK_CTX *ctx = get_hook_ctx(drbg);
@@ -512,8 +514,8 @@ static size_t get_entropy_hook(RAND_DRBG *drbg, unsigned char **pout,
     if (ctx->fail != 0)
         return 0;
 
-    ret = ctx->get_entropy(
-        drbg, pout, entropy, min_len, max_len);
+    ret = ctx->get_entropy(drbg, pout, entropy, min_len, max_len,
+                           prediction_resistance);
 
     if (ret != 0)
         ctx->reseed_count++;
-- 
2.25.1