]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
rand: update DRBGs to use the get_entropy call for seeding
authorPauli <ppzgs1@gmail.com>
Fri, 12 Feb 2021 02:54:59 +0000 (12:54 +1000)
committerPauli <ppzgs1@gmail.com>
Wed, 17 Feb 2021 03:10:49 +0000 (13:10 +1000)
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/14162)

providers/implementations/rands/drbg.c
providers/implementations/rands/drbg_ctr.c
providers/implementations/rands/drbg_hash.c
providers/implementations/rands/drbg_hmac.c
providers/implementations/rands/drbg_local.h

index bdc980ef59f8b439c5dd49ed29168978cefaa4a5..239000ec16b0ad9cfcac2521db15902028b367be 100644 (file)
@@ -141,30 +141,15 @@ static unsigned int get_parent_reseed_count(PROV_DRBG *drbg)
  * If a random pool has been added to the DRBG using RAND_add(), then
  * its entropy will be used up first.
  */
-static size_t prov_drbg_get_entropy(PROV_DRBG *drbg, unsigned char **pout,
-                                    int entropy, size_t min_len,
-                                    size_t max_len, int prediction_resistance)
+size_t ossl_drbg_get_seed(void *vdrbg, unsigned char **pout,
+                          int entropy, size_t min_len,
+                          size_t max_len, int prediction_resistance,
+                          const unsigned char *adin, size_t adin_len)
 {
-    unsigned int p_str;
-    size_t r, bytes_needed;
+    PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
+    size_t bytes_needed;
     unsigned char *buffer;
 
-    if (!get_parent_strength(drbg, &p_str))
-        return 0;
-    if (drbg->strength > p_str) {
-        /*
-         * We currently don't support the algorithm from NIST SP 800-90C
-         * 10.1.2 to use a weaker DRBG as source
-         */
-        ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
-        return 0;
-    }
-
-    if (drbg->parent_generate == NULL) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS);
-        return 0;
-    }
-
     /* Figure out how many bytes we need */
     bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0;
     if (bytes_needed < min_len)
@@ -180,13 +165,7 @@ static size_t prov_drbg_get_entropy(PROV_DRBG *drbg, unsigned char **pout,
     }
 
     /*
-     * Our lock is already held, but we need to lock our parent before
-     * generating bits from it.  Note: taking the lock will be a no-op
-     * if locking is not required (while drbg->parent->lock == NULL).
-     */
-    ossl_drbg_lock_parent(drbg);
-    /*
-     * Get random data from parent.  Include our DRBG address as
+     * Get random data.  Include our DRBG address as
      * additional input, in order to provide a distinction between
      * different DRBG child instances.
      *
@@ -194,12 +173,9 @@ static size_t prov_drbg_get_entropy(PROV_DRBG *drbg, unsigned char **pout,
      *       a warning in some static code analyzers, but it's
      *       intentional and correct here.
      */
-    r = drbg->parent_generate(drbg->parent, buffer, bytes_needed,
-                              drbg->strength, prediction_resistance,
-                              (unsigned char *)&drbg,
-                              sizeof(drbg));
-    ossl_drbg_unlock_parent(drbg);
-    if (r == 0) {
+    if (!ossl_prov_drbg_generate(drbg, buffer, bytes_needed,
+                                 drbg->strength, prediction_resistance,
+                                 (unsigned char *)&drbg, sizeof(drbg))) {
         OPENSSL_secure_clear_free(buffer, bytes_needed);
         ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
         return 0;
@@ -208,12 +184,9 @@ static size_t prov_drbg_get_entropy(PROV_DRBG *drbg, unsigned char **pout,
     return bytes_needed;
 }
 
-/*
- * Implements the cleanup_entropy() callback
- *
- */
-static void prov_drbg_cleanup_entropy(ossl_unused PROV_DRBG *drbg,
-                                      unsigned char *out, size_t outlen)
+/* Implements the cleanup_entropy() callback */
+void ossl_drbg_clear_seed(ossl_unused void *vdrbg,
+                          unsigned char *out, size_t outlen)
 {
     OPENSSL_secure_clear_free(out, outlen);
 }
@@ -222,6 +195,9 @@ static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy,
                           size_t min_len, size_t max_len,
                           int prediction_resistance)
 {
+    size_t bytes;
+    unsigned int p_str;
+
     if (drbg->parent == NULL)
 #ifdef FIPS_MODULE
         return ossl_crngt_get_entropy(drbg, pout, entropy, min_len, max_len,
@@ -231,8 +207,42 @@ static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy,
                                      max_len);
 #endif
 
-    return prov_drbg_get_entropy(drbg, pout, entropy, min_len, max_len,
-                                 prediction_resistance);
+    if (drbg->parent_get_seed == NULL) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED);
+        return 0;
+    }
+    if (!get_parent_strength(drbg, &p_str))
+        return 0;
+    if (drbg->strength > p_str) {
+        /*
+         * We currently don't support the algorithm from NIST SP 800-90C
+         * 10.1.2 to use a weaker DRBG as source
+         */
+        ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
+        return 0;
+    }
+
+    /*
+     * Our lock is already held, but we need to lock our parent before
+     * generating bits from it.  Note: taking the lock will be a no-op
+     * if locking is not required (while drbg->parent->lock == NULL).
+     */
+    if (!ossl_drbg_lock_parent(drbg))
+        return 0;
+    /*
+     * Get random data from parent.  Include our DRBG address as
+     * additional input, in order to provide a distinction between
+     * different DRBG child instances.
+     *
+     * Note: using the sizeof() operator on a pointer triggers
+     *       a warning in some static code analyzers, but it's
+     *       intentional and correct here.
+     */
+    bytes = drbg->parent_get_seed(drbg->parent, pout, drbg->strength,
+                                  min_len, max_len, prediction_resistance,
+                                  (unsigned char *)&drbg, sizeof(drbg));
+    ossl_drbg_unlock_parent(drbg);
+    return bytes;
 }
 
 static void cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen)
@@ -243,8 +253,11 @@ static void cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen)
 #else
         ossl_prov_cleanup_entropy(drbg->provctx, out, outlen);
 #endif
-    } else {
-        prov_drbg_cleanup_entropy(drbg, out, outlen);
+    } else if (drbg->parent_clear_seed != NULL) {
+        if (!ossl_drbg_lock_parent(drbg))
+            return;
+        drbg->parent_clear_seed(drbg, out, outlen);
+        ossl_drbg_unlock_parent(drbg);
     }
 }
 
@@ -794,10 +807,12 @@ PROV_DRBG *ossl_rand_drbg_new
         drbg->parent_unlock = OSSL_FUNC_rand_unlock(pfunc);
     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_CTX_PARAMS)) != NULL)
         drbg->parent_get_ctx_params = OSSL_FUNC_rand_get_ctx_params(pfunc);
-    if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GENERATE)) != NULL)
-        drbg->parent_generate = OSSL_FUNC_rand_generate(pfunc);
     if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_NONCE)) != NULL)
         drbg->parent_nonce = OSSL_FUNC_rand_nonce(pfunc);
+    if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_SEED)) != NULL)
+        drbg->parent_get_seed = OSSL_FUNC_rand_get_seed(pfunc);
+    if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_CLEAR_SEED)) != NULL)
+        drbg->parent_clear_seed = OSSL_FUNC_rand_clear_seed(pfunc);
 
     /* Set some default maximums up */
     drbg->max_entropylen = DRBG_MAX_LENGTH;
index caf885c4cb001faf5eb712e8bdfab1358c2f4e81..1f5b14247b1e8c2bfae5da957ef71d9dd5787398 100644 (file)
@@ -755,5 +755,7 @@ const OSSL_DISPATCH ossl_drbg_ctr_functions[] = {
     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_ctr_get_ctx_params },
     { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
       (void(*)(void))drbg_ctr_verify_zeroization },
+    { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
+    { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
     { 0, NULL }
 };
index 9c44c0bdb4768dec29806e81c511c75d1243e883..c799ef107ad83c0af4fe7b9c7c11a619b3e37d41 100644 (file)
@@ -518,5 +518,7 @@ const OSSL_DISPATCH ossl_drbg_hash_functions[] = {
     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_hash_get_ctx_params },
     { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
       (void(*)(void))drbg_hash_verify_zeroization },
+    { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
+    { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
     { 0, NULL }
 };
index 314243d8ab06a220aef753a1ec475228b8a40951..f166d69c5170dfc350a138073935deb245e77e11 100644 (file)
@@ -432,5 +432,7 @@ const OSSL_DISPATCH ossl_drbg_ossl_hmac_functions[] = {
     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_hmac_get_ctx_params },
     { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
       (void(*)(void))drbg_hmac_verify_zeroization },
+    { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
+    { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
     { 0, NULL }
 };
index fbae8825352c9bacb39b177f7fed4601d454bcf5..ab8ad9586e488cb5f1dd6e5056a61b8a4b7bedb9 100644 (file)
@@ -91,8 +91,9 @@ struct prov_drbg_st {
     OSSL_FUNC_rand_lock_fn *parent_lock;
     OSSL_FUNC_rand_unlock_fn *parent_unlock;
     OSSL_FUNC_rand_get_ctx_params_fn *parent_get_ctx_params;
-    OSSL_FUNC_rand_generate_fn *parent_generate;
     OSSL_FUNC_rand_nonce_fn *parent_nonce;
+    OSSL_FUNC_rand_get_seed_fn *parent_get_seed;
+    OSSL_FUNC_rand_clear_seed_fn *parent_clear_seed;
 
     const OSSL_DISPATCH *parent_dispatch;
 
@@ -205,6 +206,10 @@ int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,
                             unsigned int strength, int prediction_resistance,
                             const unsigned char *adin, size_t adinlen);
 
+/* Seeding api */
+OSSL_FUNC_rand_get_seed_fn ossl_drbg_get_seed;
+OSSL_FUNC_rand_clear_seed_fn ossl_drbg_clear_seed;
+
 /* Verify that an array of numeric values is all zero */
 #define PROV_DRBG_VERYIFY_ZEROIZATION(v)    \
     {                                       \