[openssl] master update

Dr. Paul Dale pauli at openssl.org
Wed Feb 17 03:12:19 UTC 2021


The branch master has been updated
       via  68883d9db86534176d744c7691ac7565f5def884 (commit)
       via  335e85f54246cec8b58cb43dd2263ab9d506d622 (commit)
       via  78436fd146313b31151252576c4e523eac55c47c (commit)
       via  e2730b8426eb9f1334412a026ea87c0c309b14b9 (commit)
       via  9ed185a926cc1b8527bba8efa28a6b15392484ce (commit)
       via  381289f6c7bd0e782cfd97d21c80656e470064d7 (commit)
       via  79d68c4fb4d5763a1f199ca9676c250e6dd01f74 (commit)
      from  574ca403c81edc1f21229526e2a8a67bcdabeb99 (commit)


- Log -----------------------------------------------------------------
commit 68883d9db86534176d744c7691ac7565f5def884
Author: Pauli <ppzgs1 at gmail.com>
Date:   Fri Feb 12 13:20:09 2021 +1000

    doc: document the two new RAND functions
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/14162)

commit 335e85f54246cec8b58cb43dd2263ab9d506d622
Author: Pauli <ppzgs1 at gmail.com>
Date:   Fri Feb 12 12:54:59 2021 +1000

    rand: update DRBGs to use the get_entropy call for seeding
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/14162)

commit 78436fd146313b31151252576c4e523eac55c47c
Author: Pauli <ppzgs1 at gmail.com>
Date:   Fri Feb 12 12:45:03 2021 +1000

    core: add get_entropy and clear_entropy calls to RAND
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/14162)

commit e2730b8426eb9f1334412a026ea87c0c309b14b9
Author: Pauli <ppzgs1 at gmail.com>
Date:   Fri Feb 12 12:44:43 2021 +1000

    RNG test: add get_entropy hook for testing.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/14162)

commit 9ed185a926cc1b8527bba8efa28a6b15392484ce
Author: Pauli <ppzgs1 at gmail.com>
Date:   Fri Feb 12 12:44:21 2021 +1000

    RNG seed: add get_entropy hook for seeding.
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/14162)

commit 381289f6c7bd0e782cfd97d21c80656e470064d7
Author: Pauli <ppzgs1 at gmail.com>
Date:   Fri Feb 12 12:44:02 2021 +1000

    err: generated error files
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/14162)

commit 79d68c4fb4d5763a1f199ca9676c250e6dd01f74
Author: Pauli <ppzgs1 at gmail.com>
Date:   Fri Feb 12 12:26:54 2021 +1000

    test: DRBG test with long seed.
    
    Fixes: #14101
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/14162)

-----------------------------------------------------------------------

Summary of changes:
 crypto/err/openssl.txt                       |   4 +-
 doc/man7/provider-rand.pod                   |  23 +++++-
 include/openssl/core_dispatch.h              |   9 +++
 include/openssl/proverr.h                    |   4 +-
 providers/common/provider_err.c              |  11 ++-
 providers/implementations/rands/drbg.c       | 107 +++++++++++++++------------
 providers/implementations/rands/drbg_ctr.c   |   2 +
 providers/implementations/rands/drbg_hash.c  |   2 +
 providers/implementations/rands/drbg_hmac.c  |   2 +
 providers/implementations/rands/drbg_local.h |   7 +-
 providers/implementations/rands/seed_src.c   |  45 +++++++++++
 providers/implementations/rands/test_rng.c   |  14 ++++
 test/recipes/30-test_evp_data/evprand.txt    |  16 ++++
 13 files changed, 192 insertions(+), 54 deletions(-)

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 296aa6eaad..002a7a0f10 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -947,6 +947,7 @@ PROV_R_BN_ERROR:160:bn error
 PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
 PROV_R_DERIVATION_FUNCTION_INIT_FAILED:205:derivation function init failed
 PROV_R_DIGEST_NOT_ALLOWED:174:digest not allowed
+PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK:186:entropy source strength too weak
 PROV_R_ERROR_INSTANTIATING_DRBG:188:error instantiating drbg
 PROV_R_ERROR_RETRIEVING_ENTROPY:189:error retrieving entropy
 PROV_R_ERROR_RETRIEVING_NONCE:190:error retrieving nonce
@@ -1023,6 +1024,7 @@ PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:178:\
 PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
 PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS:228:\
 	parent cannot generate random numbers
+PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED:187:parent cannot supply entropy seed
 PROV_R_PARENT_LOCKING_NOT_ENABLED:182:parent locking not enabled
 PROV_R_PARENT_STRENGTH_TOO_WEAK:194:parent strength too weak
 PROV_R_PATH_MUST_BE_ABSOLUTE:219:path must be absolute
@@ -1037,8 +1039,8 @@ PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT:229:\
 	seed sources must not have a parent
 PROV_R_SELF_TEST_KAT_FAILURE:215:self test kat failure
 PROV_R_SELF_TEST_POST_FAILURE:216:self test post failure
-PROV_R_TAG_NOT_SET:119:tag not set
 PROV_R_TAG_NOT_NEEDED:120:tag not needed
+PROV_R_TAG_NOT_SET:119:tag not set
 PROV_R_TOO_MANY_RECORDS:126:too many records
 PROV_R_UNABLE_TO_FIND_CIPHERS:207:unable to find ciphers
 PROV_R_UNABLE_TO_GET_PARENT_STRENGTH:199:unable to get parent strength
diff --git a/doc/man7/provider-rand.pod b/doc/man7/provider-rand.pod
index d75a36d01e..795924e6b7 100644
--- a/doc/man7/provider-rand.pod
+++ b/doc/man7/provider-rand.pod
@@ -37,7 +37,13 @@ functions
 
  /* Random number generator functions: additional */
  size_t OSSL_FUNC_rand_nonce(void *ctx, unsigned char *out, size_t outlen,
-                             int strength, size_t min_noncelen, size_t max_noncelen);
+                             int strength, size_t min_noncelen,
+                             size_t max_noncelen);
+ size_t OSSL_FUNC_rand_get_seed(void *ctx, unsigned char **buffer,
+                                int entropy, size_t min_len, size_t max_len,
+                                int prediction_resistance,
+                                const unsigned char *adin, size_t adin_len);
+ void OSSL_FUNC_rand_clear_seed(void *ctx, unsigned char *buffer, size_t b_len);
  int OSSL_FUNC_rand_verify_zeroization(void *ctx);
 
  /* Context Locking */
@@ -110,6 +116,18 @@ OSSL_FUNC_rand_nonce() is used to generate a nonce of the given I<strength> with
 length from I<min_noncelen> to I<max_noncelen>. If the output buffer I<out> is
 NULL, the length of the nonce should be returned.
 
+OSSL_FUNC_rand_get_seed() is used by deterministic generators to obtain their
+seeding material from their parent.  The seed bytes will meet the specified
+security level of I<entropy> bits and there will be between I<min_len>
+and I<max_len> inclusive bytes in total.  If I<prediction_resistance> is
+true, the bytes will be produced from a live entropy source.  Additional
+input I<addin> of length I<addin_len> bytes can optionally be provided.
+A pointer to the seed material is returned in I<*buffer> and this must be
+freed by a later call to OSSL_FUNC_rand_clear_seed().
+
+OSSL_FUNC_rand_clear_seed() frees a seed I<buffer> of length I<b_len> bytes
+which was previously allocated by OSSL_FUNC_rand_get_seed().
+
 OSSL_FUNC_rand_verify_zeroization() is used to determine if the internal state of the
 DRBG is zero.  This capability is mandated by NIST as part of the self
 tests, it is unlikely to be useful in other circumstances.
@@ -240,6 +258,9 @@ array, or NULL if none is offered.
 
 OSSL_FUNC_rand_nonce() returns the size of the generated nonce, or 0 on error.
 
+OSSL_FUNC_rand_get_seed() returns the size of the generated seed, or 0 on
+error.
+
 All of the remaining functions should return 1 for success or 0 on error.
 
 =head1 SEE ALSO
diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h
index 7823af7cbd..f9786e1d37 100644
--- a/include/openssl/core_dispatch.h
+++ b/include/openssl/core_dispatch.h
@@ -399,6 +399,8 @@ OSSL_CORE_MAKE_FUNC(int, kdf_set_ctx_params,
 # define OSSL_FUNC_RAND_GET_CTX_PARAMS               15
 # define OSSL_FUNC_RAND_SET_CTX_PARAMS               16
 # define OSSL_FUNC_RAND_VERIFY_ZEROIZATION           17
+# define OSSL_FUNC_RAND_GET_SEED                     18
+# define OSSL_FUNC_RAND_CLEAR_SEED                   19
 
 OSSL_CORE_MAKE_FUNC(void *,rand_newctx,
                     (void *provctx, void *parent,
@@ -440,6 +442,13 @@ OSSL_CORE_MAKE_FUNC(void,rand_set_callbacks,
                      OSSL_CALLBACK *cleanup_nonce, void *arg))
 OSSL_CORE_MAKE_FUNC(int,rand_verify_zeroization,
                     (void *vctx))
+OSSL_CORE_MAKE_FUNC(size_t,rand_get_seed,
+                    (void *vctx, unsigned char **buffer,
+                     int entropy, size_t min_len, size_t max_len,
+                     int prediction_resistance,
+                     const unsigned char *adin, size_t adin_len))
+OSSL_CORE_MAKE_FUNC(void,rand_clear_seed,
+                    (void *vctx, unsigned char *buffer, size_t b_len))
 
 /*-
  * Key management
diff --git a/include/openssl/proverr.h b/include/openssl/proverr.h
index 6e5c0debe7..99a937f1e3 100644
--- a/include/openssl/proverr.h
+++ b/include/openssl/proverr.h
@@ -32,6 +32,7 @@
 # define PROV_R_CIPHER_OPERATION_FAILED                   102
 # define PROV_R_DERIVATION_FUNCTION_INIT_FAILED           205
 # define PROV_R_DIGEST_NOT_ALLOWED                        174
+# define PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK          186
 # define PROV_R_ERROR_INSTANTIATING_DRBG                  188
 # define PROV_R_ERROR_RETRIEVING_ENTROPY                  189
 # define PROV_R_ERROR_RETRIEVING_NONCE                    190
@@ -105,6 +106,7 @@
 # define PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE  178
 # define PROV_R_OUTPUT_BUFFER_TOO_SMALL                   106
 # define PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS     228
+# define PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED         187
 # define PROV_R_PARENT_LOCKING_NOT_ENABLED                182
 # define PROV_R_PARENT_STRENGTH_TOO_WEAK                  194
 # define PROV_R_PATH_MUST_BE_ABSOLUTE                     219
@@ -117,8 +119,8 @@
 # define PROV_R_SEED_SOURCES_MUST_NOT_HAVE_A_PARENT       229
 # define PROV_R_SELF_TEST_KAT_FAILURE                     215
 # define PROV_R_SELF_TEST_POST_FAILURE                    216
-# define PROV_R_TAG_NOT_SET                               119
 # define PROV_R_TAG_NOT_NEEDED                            120
+# define PROV_R_TAG_NOT_SET                               119
 # define PROV_R_TOO_MANY_RECORDS                          126
 # define PROV_R_UNABLE_TO_FIND_CIPHERS                    207
 # define PROV_R_UNABLE_TO_GET_PARENT_STRENGTH             199
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
index a64c5d2ece..30574f4c6c 100644
--- a/providers/common/provider_err.c
+++ b/providers/common/provider_err.c
@@ -33,6 +33,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "derivation function init failed"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_DIGEST_NOT_ALLOWED),
     "digest not allowed"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK),
+    "entropy source strength too weak"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ERROR_INSTANTIATING_DRBG),
     "error instantiating drbg"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ERROR_RETRIEVING_ENTROPY),
@@ -99,14 +101,13 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_STATE), "invalid state"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG), "invalid tag"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG_LENGTH),
-    "invalid tag_length"},
+    "invalid tag length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_UKM_LENGTH),
     "invalid ukm length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_X931_DIGEST),
     "invalid x931 digest"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_IN_ERROR_STATE), "in error state"},
-    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SETUP_FAILED),
-    "key setup failed"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SETUP_FAILED), "key setup failed"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SIZE_TOO_SMALL),
     "key size too small"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"},
@@ -144,6 +145,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "output buffer too small"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_CANNOT_GENERATE_RANDOM_NUMBERS),
     "parent cannot generate random numbers"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED),
+    "parent cannot supply entropy seed"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_LOCKING_NOT_ENABLED),
     "parent locking not enabled"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_PARENT_STRENGTH_TOO_WEAK),
@@ -167,8 +170,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "self test kat failure"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_SELF_TEST_POST_FAILURE),
     "self test post failure"},
-    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_SET), "tag not set"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_NEEDED), "tag not needed"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TAG_NOT_SET), "tag not set"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_TOO_MANY_RECORDS), "too many records"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNABLE_TO_FIND_CIPHERS),
     "unable to find ciphers"},
diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c
index bdc980ef59..239000ec16 100644
--- a/providers/implementations/rands/drbg.c
+++ b/providers/implementations/rands/drbg.c
@@ -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;
diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c
index caf885c4cb..1f5b14247b 100644
--- a/providers/implementations/rands/drbg_ctr.c
+++ b/providers/implementations/rands/drbg_ctr.c
@@ -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 }
 };
diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c
index 9c44c0bdb4..c799ef107a 100644
--- a/providers/implementations/rands/drbg_hash.c
+++ b/providers/implementations/rands/drbg_hash.c
@@ -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 }
 };
diff --git a/providers/implementations/rands/drbg_hmac.c b/providers/implementations/rands/drbg_hmac.c
index 314243d8ab..f166d69c51 100644
--- a/providers/implementations/rands/drbg_hmac.c
+++ b/providers/implementations/rands/drbg_hmac.c
@@ -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 }
 };
diff --git a/providers/implementations/rands/drbg_local.h b/providers/implementations/rands/drbg_local.h
index fbae882535..ab8ad9586e 100644
--- a/providers/implementations/rands/drbg_local.h
+++ b/providers/implementations/rands/drbg_local.h
@@ -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)    \
     {                                       \
diff --git a/providers/implementations/rands/seed_src.c b/providers/implementations/rands/seed_src.c
index 60088b2779..c93036cb60 100644
--- a/providers/implementations/rands/seed_src.c
+++ b/providers/implementations/rands/seed_src.c
@@ -34,6 +34,8 @@ static OSSL_FUNC_rand_verify_zeroization_fn seed_src_verify_zeroization;
 static OSSL_FUNC_rand_enable_locking_fn seed_src_enable_locking;
 static OSSL_FUNC_rand_lock_fn seed_src_lock;
 static OSSL_FUNC_rand_unlock_fn seed_src_unlock;
+static OSSL_FUNC_rand_get_seed_fn seed_get_seed;
+static OSSL_FUNC_rand_clear_seed_fn seed_clear_seed;
 
 typedef struct {
     void *provctx;
@@ -170,6 +172,47 @@ static int seed_src_verify_zeroization(ossl_unused void *vseed)
     return 1;
 }
 
+static size_t seed_get_seed(void *vseed, unsigned char **pout,
+                            int entropy, size_t min_len, size_t max_len,
+                            int prediction_resistance,
+                            const unsigned char *adin, size_t adin_len)
+{
+    size_t bytes_needed;
+    unsigned char *p;
+
+    /*
+     * Figure out how many bytes we need.
+     * This assumes that the seed sources provide eight bits of entropy
+     * per byte.  For lower quality sources, the formula will need to be
+     * different.
+     */
+    bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0;
+    if (bytes_needed < min_len)
+        bytes_needed = min_len;
+    if (bytes_needed > max_len) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK);
+        return 0;
+    }
+
+    p = OPENSSL_secure_malloc(bytes_needed);
+    if (p == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    *pout = p;
+    if (seed_src_generate(vseed, p, bytes_needed, 0, prediction_resistance,
+                          adin, adin_len) != 0)
+        return bytes_needed;
+    OPENSSL_secure_clear_free(p, bytes_needed);
+    return 0;
+}
+
+static void seed_clear_seed(ossl_unused void *vdrbg,
+                            unsigned char *out, size_t outlen)
+{
+    OPENSSL_secure_clear_free(out, outlen);
+}
+
 static int seed_src_enable_locking(ossl_unused void *vseed)
 {
     return 1;
@@ -201,5 +244,7 @@ const OSSL_DISPATCH ossl_seed_src_functions[] = {
     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))seed_src_get_ctx_params },
     { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
       (void(*)(void))seed_src_verify_zeroization },
+    { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))seed_get_seed },
+    { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))seed_clear_seed },
     { 0, NULL }
 };
diff --git a/providers/implementations/rands/test_rng.c b/providers/implementations/rands/test_rng.c
index 33cbd20e9b..0c0e0e3b42 100644
--- a/providers/implementations/rands/test_rng.c
+++ b/providers/implementations/rands/test_rng.c
@@ -35,6 +35,7 @@ static OSSL_FUNC_rand_verify_zeroization_fn test_rng_verify_zeroization;
 static OSSL_FUNC_rand_enable_locking_fn test_rng_enable_locking;
 static OSSL_FUNC_rand_lock_fn test_rng_lock;
 static OSSL_FUNC_rand_unlock_fn test_rng_unlock;
+static OSSL_FUNC_rand_get_seed_fn test_rng_get_seed;
 
 typedef struct {
     void *provctx;
@@ -228,6 +229,18 @@ static int test_rng_verify_zeroization(ossl_unused void *vtest)
     return 1;
 }
 
+static size_t test_rng_get_seed(void *vtest, unsigned char **pout,
+                                int entropy, size_t min_len, size_t max_len,
+                                ossl_unused int prediction_resistance,
+                                ossl_unused const unsigned char *adin,
+                                ossl_unused size_t adin_len)
+{
+    PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
+
+    *pout = t->entropy;
+    return  t->entropy_len > max_len ? max_len : t->entropy_len;
+}
+
 static int test_rng_enable_locking(void *vtest)
 {
     PROV_TEST_RNG *t = (PROV_TEST_RNG *)vtest;
@@ -280,5 +293,6 @@ const OSSL_DISPATCH ossl_test_rng_functions[] = {
     { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))test_rng_get_ctx_params },
     { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
       (void(*)(void))test_rng_verify_zeroization },
+    { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))test_rng_get_seed },
     { 0, NULL }
 };
diff --git a/test/recipes/30-test_evp_data/evprand.txt b/test/recipes/30-test_evp_data/evprand.txt
index b91f5483ae..f504dc3e0b 100644
--- a/test/recipes/30-test_evp_data/evprand.txt
+++ b/test/recipes/30-test_evp_data/evprand.txt
@@ -12,6 +12,22 @@
 # and continue until a blank line.  Lines starting with a pound sign,
 # like this prolog, are ignored.
 
+# Test vector from NISTs CAVP tool
+
+Title = CAVP Large Seed
+
+RAND = CTR-DRBG
+Cipher = AES-192-CTR
+DerivationFunction = 1
+PredictionResistance = 1
+GenerateBits = 256
+Entropy.0 = 22ED7A66C9E9F494C8D2B8F81D0D49BCDD0C03863FF5979212211EFE3E945758B6228CDD9E9EEC5F7984AEF7212699F3
+Nonce.0 = 5BF245B95F8E1377D5A17EB331AABCD9
+EntropyPredictionResistanceA.0 = C0535ACD3D715A0B1453AB3447D53D9131C939AEE1D9CA24A75B285CF58D79403A4111E2F3DEE011154D31D646D93001
+EntropyPredictionResistanceB.0 = 9FBC48890273FCAFCA1904B6486D1877CAD91EB601E979259506F93BA462AC17D8676C570B2231D4D98EC617C4826573
+Output.0 = 19CED57563D065B606DA27DD5E8DE83B93BB7C8F8B02D0288F475550C3F44B77
+
+
 # Test vectors come from:
 # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
 


More information about the openssl-commits mailing list