CRNGT: continuous DRBG tests for providers
authorPauli <paul.dale@oracle.com>
Fri, 8 May 2020 00:25:03 +0000 (10:25 +1000)
committerPauli <paul.dale@oracle.com>
Wed, 24 Jun 2020 10:05:41 +0000 (20:05 +1000)
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/11682)

crypto/rand/build.info
crypto/rand/drbg_lib.c
crypto/rand/rand_lib.c
crypto/rand/rand_local.h
providers/implementations/rands/build.info
providers/implementations/rands/crngt.c [new file with mode: 0644]
providers/implementations/rands/rand_crng_test.c [deleted file]

index c4e7476ef75f978833399291473c0b379c5737c3..7840428045634867ea7ba62a2970d1a21583c095 100644 (file)
@@ -1,16 +1,18 @@
 LIBS=../../libcrypto
 
-$COMMON=rand_lib.c rand_crng_test.c rand_unix.c rand_win.c \
-        drbg_lib.c drbg_ctr.c drbg_hash.c drbg_hmac.c
+$COMMON=rand_pool.c rand_lib.c drbg_lib.c drbg_ctr.c drbg_hash.c drbg_hmac.c
+$CRYPTO=rand_unix.c rand_win.c randfile.c rand_err.c
+
 IF[{- !$disabled{'egd'} -}]
-  $COMMON=$COMMON rand_egd.c
+  $CYPTO=$CYPTO rand_egd.c
 ENDIF
 IF[{- $config{target} =~ /vxworks/i -}]
-  $COMMON=$COMMON rand_vxworks.c
+  $CYPTO=$CYPTO rand_vxworks.c
 ENDIF
 IF[{- $config{target} =~ /vms/i -}]
-  $COMMON=$COMMON rand_vms.c
+  $CYPTO=$CYPTO rand_vms.c
 ENDIF
 
-SOURCE[../../libcrypto]=$COMMON randfile.c rand_err.c
+
+SOURCE[../../libcrypto]=$COMMON $CRYPTO
 SOURCE[../../providers/libfips.a]=$COMMON
index cda13595e385617591e3102566676619bde4e41b..94a4e98d73aedb153b9cf42f716d8cf080eecccc 100644 (file)
@@ -14,6 +14,7 @@
 #include "rand_local.h"
 #include "internal/thread_once.h"
 #include "crypto/rand.h"
+#include "crypto/rand_pool.h"
 #include "crypto/cryptlib.h"
 
 /*
@@ -468,13 +469,8 @@ static RAND_DRBG *rand_drbg_new(OPENSSL_CTX *ctx,
     drbg->parent = parent;
 
     if (parent == NULL) {
-#ifdef FIPS_MODULE
-        drbg->get_entropy = rand_crngt_get_entropy;
-        drbg->cleanup_entropy = rand_crngt_cleanup_entropy;
-#else
         drbg->get_entropy = rand_drbg_get_entropy;
         drbg->cleanup_entropy = rand_drbg_cleanup_entropy;
-#endif
 #ifndef RAND_DRBG_GET_RANDOM_NONCE
         drbg->get_nonce = rand_drbg_get_nonce;
         drbg->cleanup_nonce = rand_drbg_cleanup_nonce;
index a5eb0bc7ae318a2f94e32e8cd6ae17c2c574f4fe..a4c9e694726e749f7ce981364f192f0086d85b17 100644 (file)
@@ -110,7 +110,7 @@ size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool)
 }
 #endif
 
-
+#if 0
 /*
  * Implements the get_entropy() callback (see RAND_DRBG_set_callbacks())
  *
@@ -237,6 +237,7 @@ void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out)
 {
     rand_pool_reattach(pool, out);
 }
+#endif
 
 #ifndef FIPS_MODULE
 DEFINE_RUN_ONCE_STATIC(do_rand_init)
@@ -321,9 +322,9 @@ int RAND_poll(void)
         if (drbg == NULL)
             return 0;
 
-        rand_drbg_lock(drbg);
+#if 0
         ret = rand_drbg_restart(drbg, NULL, 0, 0);
-        rand_drbg_unlock(drbg);
+#endif
 
         return ret;
 
@@ -336,10 +337,10 @@ int RAND_poll(void)
                              RAND_POOL_MAX_LENGTH);
         if (pool == NULL)
             return 0;
-
+#if 0
         if (rand_pool_acquire_entropy(pool) == 0)
             goto err;
-
+#endif
         if (meth->add == NULL
             || meth->add(rand_pool_buffer(pool),
                          rand_pool_length(pool),
@@ -354,406 +355,7 @@ int RAND_poll(void)
 
     return ret;
 }
-#endif /* FIPS_MODULE */
-
-/*
- * Allocate memory and initialize a new random pool
- */
-
-RAND_POOL *rand_pool_new(int entropy_requested, int secure,
-                         size_t min_len, size_t max_len)
-{
-    RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool));
-    size_t min_alloc_size = RAND_POOL_MIN_ALLOCATION(secure);
-
-    if (pool == NULL) {
-        RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
-
-    pool->min_len = min_len;
-    pool->max_len = (max_len > RAND_POOL_MAX_LENGTH) ?
-        RAND_POOL_MAX_LENGTH : max_len;
-    pool->alloc_len = min_len < min_alloc_size ? min_alloc_size : min_len;
-    if (pool->alloc_len > pool->max_len)
-        pool->alloc_len = pool->max_len;
-
-    if (secure)
-        pool->buffer = OPENSSL_secure_zalloc(pool->alloc_len);
-    else
-        pool->buffer = OPENSSL_zalloc(pool->alloc_len);
-
-    if (pool->buffer == NULL) {
-        RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-
-    pool->entropy_requested = entropy_requested;
-    pool->secure = secure;
-
-    return pool;
-
-err:
-    OPENSSL_free(pool);
-    return NULL;
-}
-
-/*
- * Attach new random pool to the given buffer
- *
- * This function is intended to be used only for feeding random data
- * provided by RAND_add() and RAND_seed() into the <master> DRBG.
- */
-RAND_POOL *rand_pool_attach(const unsigned char *buffer, size_t len,
-                            size_t entropy)
-{
-    RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool));
-
-    if (pool == NULL) {
-        RANDerr(RAND_F_RAND_POOL_ATTACH, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
-
-    /*
-     * The const needs to be cast away, but attached buffers will not be
-     * modified (in contrary to allocated buffers which are zeroed and
-     * freed in the end).
-     */
-    pool->buffer = (unsigned char *) buffer;
-    pool->len = len;
-
-    pool->attached = 1;
-
-    pool->min_len = pool->max_len = pool->alloc_len = pool->len;
-    pool->entropy = entropy;
-
-    return pool;
-}
-
-/*
- * Free |pool|, securely erasing its buffer.
- */
-void rand_pool_free(RAND_POOL *pool)
-{
-    if (pool == NULL)
-        return;
-
-    /*
-     * Although it would be advisable from a cryptographical viewpoint,
-     * we are not allowed to clear attached buffers, since they are passed
-     * to rand_pool_attach() as `const unsigned char*`.
-     * (see corresponding comment in rand_pool_attach()).
-     */
-    if (!pool->attached) {
-        if (pool->secure)
-            OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len);
-        else
-            OPENSSL_clear_free(pool->buffer, pool->alloc_len);
-    }
-
-    OPENSSL_free(pool);
-}
-
-/*
- * Return the |pool|'s buffer to the caller (readonly).
- */
-const unsigned char *rand_pool_buffer(RAND_POOL *pool)
-{
-    return pool->buffer;
-}
-
-/*
- * Return the |pool|'s entropy to the caller.
- */
-size_t rand_pool_entropy(RAND_POOL *pool)
-{
-    return pool->entropy;
-}
-
-/*
- * Return the |pool|'s buffer length to the caller.
- */
-size_t rand_pool_length(RAND_POOL *pool)
-{
-    return pool->len;
-}
-
-/*
- * Detach the |pool| buffer and return it to the caller.
- * It's the responsibility of the caller to free the buffer
- * using OPENSSL_secure_clear_free() or to re-attach it
- * again to the pool using rand_pool_reattach().
- */
-unsigned char *rand_pool_detach(RAND_POOL *pool)
-{
-    unsigned char *ret = pool->buffer;
-    pool->buffer = NULL;
-    pool->entropy = 0;
-    return ret;
-}
-
-/*
- * Re-attach the |pool| buffer. It is only allowed to pass
- * the |buffer| which was previously detached from the same pool.
- */
-void rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer)
-{
-    pool->buffer = buffer;
-    OPENSSL_cleanse(pool->buffer, pool->len);
-    pool->len = 0;
-}
-
-/*
- * If |entropy_factor| bits contain 1 bit of entropy, how many bytes does one
- * need to obtain at least |bits| bits of entropy?
- */
-#define ENTROPY_TO_BYTES(bits, entropy_factor) \
-    (((bits) * (entropy_factor) + 7) / 8)
-
-
-/*
- * Checks whether the |pool|'s entropy is available to the caller.
- * This is the case when entropy count and buffer length are high enough.
- * Returns
- *
- *  |entropy|  if the entropy count and buffer size is large enough
- *      0      otherwise
- */
-size_t rand_pool_entropy_available(RAND_POOL *pool)
-{
-    if (pool->entropy < pool->entropy_requested)
-        return 0;
-
-    if (pool->len < pool->min_len)
-        return 0;
-
-    return pool->entropy;
-}
-
-/*
- * Returns the (remaining) amount of entropy needed to fill
- * the random pool.
- */
-
-size_t rand_pool_entropy_needed(RAND_POOL *pool)
-{
-    if (pool->entropy < pool->entropy_requested)
-        return pool->entropy_requested - pool->entropy;
-
-    return 0;
-}
-
-/* Increase the allocation size -- not usable for an attached pool */
-static int rand_pool_grow(RAND_POOL *pool, size_t len)
-{
-    if (len > pool->alloc_len - pool->len) {
-        unsigned char *p;
-        const size_t limit = pool->max_len / 2;
-        size_t newlen = pool->alloc_len;
-
-        if (pool->attached || len > pool->max_len - pool->len) {
-            RANDerr(RAND_F_RAND_POOL_GROW, ERR_R_INTERNAL_ERROR);
-            return 0;
-        }
-
-        do
-            newlen = newlen < limit ? newlen * 2 : pool->max_len;
-        while (len > newlen - pool->len);
-
-        if (pool->secure)
-            p = OPENSSL_secure_zalloc(newlen);
-        else
-            p = OPENSSL_zalloc(newlen);
-        if (p == NULL) {
-            RANDerr(RAND_F_RAND_POOL_GROW, ERR_R_MALLOC_FAILURE);
-            return 0;
-        }
-        memcpy(p, pool->buffer, pool->len);
-        if (pool->secure)
-            OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len);
-        else
-            OPENSSL_clear_free(pool->buffer, pool->alloc_len);
-        pool->buffer = p;
-        pool->alloc_len = newlen;
-    }
-    return 1;
-}
-
-/*
- * Returns the number of bytes needed to fill the pool, assuming
- * the input has 1 / |entropy_factor| entropy bits per data bit.
- * In case of an error, 0 is returned.
- */
-
-size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor)
-{
-    size_t bytes_needed;
-    size_t entropy_needed = rand_pool_entropy_needed(pool);
 
-    if (entropy_factor < 1) {
-        RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_ARGUMENT_OUT_OF_RANGE);
-        return 0;
-    }
-
-    bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_factor);
-
-    if (bytes_needed > pool->max_len - pool->len) {
-        /* not enough space left */
-        RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_RANDOM_POOL_OVERFLOW);
-        return 0;
-    }
-
-    if (pool->len < pool->min_len &&
-        bytes_needed < pool->min_len - pool->len)
-        /* to meet the min_len requirement */
-        bytes_needed = pool->min_len - pool->len;
-
-    /*
-     * Make sure the buffer is large enough for the requested amount
-     * of data. This guarantees that existing code patterns where
-     * rand_pool_add_begin, rand_pool_add_end or rand_pool_add
-     * are used to collect entropy data without any error handling
-     * whatsoever, continue to be valid.
-     * Furthermore if the allocation here fails once, make sure that
-     * we don't fall back to a less secure or even blocking random source,
-     * as that could happen by the existing code patterns.
-     * This is not a concern for additional data, therefore that
-     * is not needed if rand_pool_grow fails in other places.
-     */
-    if (!rand_pool_grow(pool, bytes_needed)) {
-        /* persistent error for this pool */
-        pool->max_len = pool->len = 0;
-        return 0;
-    }
-
-    return bytes_needed;
-}
-
-/* Returns the remaining number of bytes available */
-size_t rand_pool_bytes_remaining(RAND_POOL *pool)
-{
-    return pool->max_len - pool->len;
-}
-
-/*
- * Add random bytes to the random pool.
- *
- * It is expected that the |buffer| contains |len| bytes of
- * random input which contains at least |entropy| bits of
- * randomness.
- *
- * Returns 1 if the added amount is adequate, otherwise 0
- */
-int rand_pool_add(RAND_POOL *pool,
-                  const unsigned char *buffer, size_t len, size_t entropy)
-{
-    if (len > pool->max_len - pool->len) {
-        RANDerr(RAND_F_RAND_POOL_ADD, RAND_R_ENTROPY_INPUT_TOO_LONG);
-        return 0;
-    }
-
-    if (pool->buffer == NULL) {
-        RANDerr(RAND_F_RAND_POOL_ADD, ERR_R_INTERNAL_ERROR);
-        return 0;
-    }
-
-    if (len > 0) {
-        /*
-         * This is to protect us from accidentally passing the buffer
-         * returned from rand_pool_add_begin.
-         * The check for alloc_len makes sure we do not compare the
-         * address of the end of the allocated memory to something
-         * different, since that comparison would have an
-         * indeterminate result.
-         */
-        if (pool->alloc_len > pool->len && pool->buffer + pool->len == buffer) {
-            RANDerr(RAND_F_RAND_POOL_ADD, ERR_R_INTERNAL_ERROR);
-            return 0;
-        }
-        /*
-         * We have that only for cases when a pool is used to collect
-         * additional data.
-         * For entropy data, as long as the allocation request stays within
-         * the limits given by rand_pool_bytes_needed this rand_pool_grow
-         * below is guaranteed to succeed, thus no allocation happens.
-         */
-        if (!rand_pool_grow(pool, len))
-            return 0;
-        memcpy(pool->buffer + pool->len, buffer, len);
-        pool->len += len;
-        pool->entropy += entropy;
-    }
-
-    return 1;
-}
-
-/*
- * Start to add random bytes to the random pool in-place.
- *
- * Reserves the next |len| bytes for adding random bytes in-place
- * and returns a pointer to the buffer.
- * The caller is allowed to copy up to |len| bytes into the buffer.
- * If |len| == 0 this is considered a no-op and a NULL pointer
- * is returned without producing an error message.
- *
- * After updating the buffer, rand_pool_add_end() needs to be called
- * to finish the update operation (see next comment).
- */
-unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len)
-{
-    if (len == 0)
-        return NULL;
-
-    if (len > pool->max_len - pool->len) {
-        RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, RAND_R_RANDOM_POOL_OVERFLOW);
-        return NULL;
-    }
-
-    if (pool->buffer == NULL) {
-        RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, ERR_R_INTERNAL_ERROR);
-        return NULL;
-    }
-
-    /*
-     * As long as the allocation request stays within the limits given
-     * by rand_pool_bytes_needed this rand_pool_grow below is guaranteed
-     * to succeed, thus no allocation happens.
-     * We have that only for cases when a pool is used to collect
-     * additional data. Then the buffer might need to grow here,
-     * and of course the caller is responsible to check the return
-     * value of this function.
-     */
-    if (!rand_pool_grow(pool, len))
-        return NULL;
-
-    return pool->buffer + pool->len;
-}
-
-/*
- * Finish to add random bytes to the random pool in-place.
- *
- * Finishes an in-place update of the random pool started by
- * rand_pool_add_begin() (see previous comment).
- * It is expected that |len| bytes of random input have been added
- * to the buffer which contain at least |entropy| bits of randomness.
- * It is allowed to add less bytes than originally reserved.
- */
-int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy)
-{
-    if (len > pool->alloc_len - pool->len) {
-        RANDerr(RAND_F_RAND_POOL_ADD_END, RAND_R_RANDOM_POOL_OVERFLOW);
-        return 0;
-    }
-
-    if (len > 0) {
-        pool->len += len;
-        pool->entropy += entropy;
-    }
-
-    return 1;
-}
-
-#ifndef FIPS_MODULE
 int RAND_set_rand_method(const RAND_METHOD *meth)
 {
     if (!RUN_ONCE(&rand_init, do_rand_init))
@@ -768,7 +370,7 @@ int RAND_set_rand_method(const RAND_METHOD *meth)
     CRYPTO_THREAD_unlock(rand_meth_lock);
     return 1;
 }
-#endif
+#endif /* FIPS_MODULE */
 
 const RAND_METHOD *RAND_get_rand_method(void)
 {
index 76e50fa2fa8fe5e891dc510f8bcc0282185b41a9..85158df76f74d8f2eed03c3ceb3efc4d7e55efe9 100644 (file)
 # include <openssl/rand_drbg.h>
 # include "internal/tsan_assist.h"
 # include "crypto/rand.h"
+# include "crypto/rand_pool.h"
 
 # include "internal/numbers.h"
 
-/* How many times to read the TSC as a randomness source. */
-# define TSC_READ_COUNT                 4
-
 /* Maximum reseed intervals */
 # define MAX_RESEED_INTERVAL                     (1 << 24)
 # define MAX_RESEED_TIME_INTERVAL                (1 << 20) /* approx. 12 days */
@@ -31,8 +29,8 @@
 /* Default reseed intervals */
 # define MASTER_RESEED_INTERVAL                  (1 << 8)
 # define SLAVE_RESEED_INTERVAL                   (1 << 16)
-# define MASTER_RESEED_TIME_INTERVAL             (60*60)   /* 1 hour */
-# define SLAVE_RESEED_TIME_INTERVAL              (7*60)    /* 7 minutes */
+# define MASTER_RESEED_TIME_INTERVAL             (60 * 60) /* 1 hour */
+# define SLAVE_RESEED_TIME_INTERVAL              (7 * 60)  /* 7 minutes */
 
 /*
  * The number of bytes that constitutes an atomic lump of entropy with respect
  */
 # define DRBG_MAX_LENGTH                         INT32_MAX
 
-/* The default nonce */
-#ifdef CHARSET_EBCDIC
-# define DRBG_DEFAULT_PERS_STRING      { 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, \
-     0x4c, 0x20, 0x4e, 0x49, 0x53, 0x54, 0x20, 0x53, 0x50, 0x20, 0x38, 0x30, \
-     0x30, 0x2d, 0x39, 0x30, 0x41, 0x20, 0x44, 0x52, 0x42, 0x47, 0x00};
-#else
-# define DRBG_DEFAULT_PERS_STRING                "OpenSSL NIST SP 800-90A DRBG"
-#endif
-
-/*
- * Maximum allocation size for RANDOM_POOL buffers
- *
- * The max_len value for the buffer provided to the rand_drbg_get_entropy()
- * callback is currently 2^31 bytes (2 gigabytes), if a derivation function
- * is used. Since this is much too large to be allocated, the rand_pool_new()
- * function chooses more modest values as default pool length, bounded
- * by RAND_POOL_MIN_LENGTH and RAND_POOL_MAX_LENGTH
- *
- * The choice of the RAND_POOL_FACTOR is large enough such that the
- * RAND_POOL can store a random input which has a lousy entropy rate of
- * 8/256 (= 0.03125) bits per byte. This input will be sent through the
- * derivation function which 'compresses' the low quality input into a
- * high quality output.
- *
- * The factor 1.5 below is the pessimistic estimate for the extra amount
- * of entropy required when no get_nonce() callback is defined.
- */
-# define RAND_POOL_FACTOR        256
-# define RAND_POOL_MAX_LENGTH    (RAND_POOL_FACTOR * \
-                                  3 * (RAND_DRBG_STRENGTH / 16))
-/*
- *                             = (RAND_POOL_FACTOR * \
- *                                1.5 * (RAND_DRBG_STRENGTH / 8))
- */
-
-/*
- * Initial allocation minimum.
- *
- * There is a distinction between the secure and normal allocation minimums.
- * Ideally, the secure allocation size should be a power of two.  The normal
- * allocation size doesn't have any such restriction.
- *
- * The secure value is based on 128 bits of secure material, which is 16 bytes.
- * Typically, the DRBGs will set a minimum larger than this so optimal
- * allocation ought to take place (for full quality seed material).
- *
- * The normal value has been chosen by noticing that the rand_drbg_get_nonce
- * function is usually the largest of the built in allocation (twenty four
- * bytes and then appending another sixteen bytes).  This means the buffer ends
- * with 40 bytes.  The value of forty eight is comfortably above this which
- * allows some slack in the platform specific values used.
- */
-# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 16 : 48)
-
 /* DRBG status values */
 typedef enum drbg_status_e {
     DRBG_UNINITIALISED,
@@ -114,7 +58,6 @@ typedef enum drbg_status_e {
     DRBG_ERROR
 } DRBG_STATUS;
 
-
 /* instantiate */
 typedef int (*RAND_DRBG_instantiate_fn)(RAND_DRBG *ctx,
                                         const unsigned char *ent,
@@ -139,82 +82,6 @@ typedef int (*RAND_DRBG_generate_fn)(RAND_DRBG *ctx,
 typedef int (*RAND_DRBG_uninstantiate_fn)(RAND_DRBG *ctx);
 
 
-/*
- * The DRBG methods
- */
-
-typedef struct rand_drbg_method_st {
-    RAND_DRBG_instantiate_fn instantiate;
-    RAND_DRBG_reseed_fn reseed;
-    RAND_DRBG_generate_fn generate;
-    RAND_DRBG_uninstantiate_fn uninstantiate;
-} RAND_DRBG_METHOD;
-
-/* 888 bits from SP800-90Ar1 10.1 table 2 */
-#define HASH_PRNG_MAX_SEEDLEN    (888/8)
-
-typedef struct rand_drbg_hash_st {
-    EVP_MD *md;
-    EVP_MD_CTX *ctx;
-    size_t blocklen;
-    unsigned char V[HASH_PRNG_MAX_SEEDLEN];
-    unsigned char C[HASH_PRNG_MAX_SEEDLEN];
-    /* Temporary value storage: should always exceed max digest length */
-    unsigned char vtmp[HASH_PRNG_MAX_SEEDLEN];
-} RAND_DRBG_HASH;
-
-typedef struct rand_drbg_hmac_st {
-    EVP_MD *md;
-    HMAC_CTX *ctx;
-    size_t blocklen;
-    unsigned char K[EVP_MAX_MD_SIZE];
-    unsigned char V[EVP_MAX_MD_SIZE];
-} RAND_DRBG_HMAC;
-
-/*
- * The state of a DRBG AES-CTR.
- */
-typedef struct rand_drbg_ctr_st {
-    EVP_CIPHER_CTX *ctx_ecb;
-    EVP_CIPHER_CTX *ctx_ctr;
-    EVP_CIPHER_CTX *ctx_df;
-    EVP_CIPHER *cipher_ecb;
-    EVP_CIPHER *cipher_ctr;
-    size_t keylen;
-    unsigned char K[32];
-    unsigned char V[16];
-    /* Temporary block storage used by ctr_df */
-    unsigned char bltmp[16];
-    size_t bltmp_pos;
-    unsigned char KX[48];
-} RAND_DRBG_CTR;
-
-
-/*
- * The 'random pool' acts as a dumb container for collecting random
- * input from various entropy sources. The pool has no knowledge about
- * whether its randomness is fed into a legacy RAND_METHOD via RAND_add()
- * or into a new style RAND_DRBG. It is the callers duty to 1) initialize the
- * random pool, 2) pass it to the polling callbacks, 3) seed the RNG, and
- * 4) cleanup the random pool again.
- *
- * The random pool contains no locking mechanism because its scope and
- * lifetime is intended to be restricted to a single stack frame.
- */
-struct rand_pool_st {
-    unsigned char *buffer;  /* points to the beginning of the random pool */
-    size_t len; /* current number of random bytes contained in the pool */
-
-    int attached;  /* true pool was attached to existing buffer */
-    int secure;    /* 1: allocated on the secure heap, 0: otherwise */
-
-    size_t min_len; /* minimum number of random bytes requested */
-    size_t max_len; /* maximum number of random bytes (allocated buffer size) */
-    size_t alloc_len; /* current number of bytes allocated */
-    size_t entropy; /* current entropy count in bits */
-    size_t entropy_requested; /* requested entropy count in bits */
-};
-
 /*
  * The state of all types of DRBGs, even though we only have CTR mode
  * right now.
@@ -226,104 +93,13 @@ struct rand_drbg_st {
     RAND_DRBG *parent;
     int secure; /* 1: allocated on the secure heap, 0: otherwise */
     int type; /* the nid of the underlying algorithm */
-    /*
-     * Stores the return value of openssl_get_fork_id() as of when we last
-     * reseeded.  The DRBG reseeds automatically whenever drbg->fork_id !=
-     * openssl_get_fork_id().  Used to provide fork-safety and reseed this
-     * DRBG in the child process.
-     */
-    int fork_id;
     unsigned short flags; /* various external flags */
 
-    /*
-     * The random_data is used by RAND_add()/drbg_add() to attach random
-     * data to the global drbg, such that the rand_drbg_get_entropy() callback
-     * can pull it during instantiation and reseeding. This is necessary to
-     * reconcile the different philosophies of the RAND and the RAND_DRBG
-     * with respect to how randomness is added to the RNG during reseeding
-     * (see PR #4328).
-     */
-    struct rand_pool_st *seed_pool;
-
-    /*
-     * Auxiliary pool for additional data.
-     */
-    struct rand_pool_st *adin_pool;
-
-    /*
-     * The following parameters are setup by the per-type "init" function.
-     *
-     * The supported types and their init functions are:
-     *    (1) CTR_DRBG:  drbg_ctr_init().
-     *    (2) HMAC_DRBG: drbg_hmac_init().
-     *    (3) HASH_DRBG: drbg_hash_init().
-     *
-     * The parameters are closely related to the ones described in
-     * section '10.2.1 CTR_DRBG' of [NIST SP 800-90Ar1], with one
-     * crucial difference: In the NIST standard, all counts are given
-     * in bits, whereas in OpenSSL entropy counts are given in bits
-     * and buffer lengths are given in bytes.
-     *
-     * Since this difference has lead to some confusion in the past,
-     * (see [GitHub Issue #2443], formerly [rt.openssl.org #4055])
-     * the 'len' suffix has been added to all buffer sizes for
-     * clarification.
-     */
-
-    int strength;
-    size_t max_request;
-    size_t min_entropylen, max_entropylen;
-    size_t min_noncelen, max_noncelen;
-    size_t max_perslen, max_adinlen;
-
-    /*
-     * Counts the number of generate requests since the last reseed
-     * (Starts at 1). This value is the reseed_counter as defined in
-     * NIST SP 800-90Ar1
-     */
-    unsigned int reseed_gen_counter;
-    /*
-     * Maximum number of generate requests until a reseed is required.
-     * This value is ignored if it is zero.
-     */
-    unsigned int reseed_interval;
-    /* Stores the time when the last reseeding occurred */
-    time_t reseed_time;
-    /*
-     * Specifies the maximum time interval (in seconds) between reseeds.
-     * This value is ignored if it is zero.
-     */
-    time_t reseed_time_interval;
-    /*
-     * Counts the number of reseeds since instantiation.
-     * This value is ignored if it is zero.
-     *
-     * This counter is used only for seed propagation from the <master> DRBG
-     * to its two children, the <public> and <private> DRBG. This feature is
-     * very special and its sole purpose is to ensure that any randomness which
-     * is added by RAND_add() or RAND_seed() will have an immediate effect on
-     * the output of RAND_bytes() resp. RAND_priv_bytes().
-     */
-    TSAN_QUALIFIER unsigned int reseed_prop_counter;
-    unsigned int reseed_next_counter;
-
-    size_t seedlen;
-    DRBG_STATUS state;
-
-#ifndef FIPS_MODULE
     /* Application data, mainly used in the KATs. */
     CRYPTO_EX_DATA ex_data;
-#endif
-
-    /* Implementation specific data */
-    union {
-        RAND_DRBG_CTR ctr;
-        RAND_DRBG_HASH hash;
-        RAND_DRBG_HMAC hmac;
-    } data;
 
-    /* Implementation specific methods */
-    RAND_DRBG_METHOD *meth;
+    /* Implementation */
+    EVP_RAND_CTX *rand;
 
     /* Callback functions.  See comments in rand_lib.c */
     RAND_DRBG_get_entropy_fn get_entropy;
@@ -341,16 +117,6 @@ extern RAND_METHOD rand_meth;
 int rand_drbg_restart(RAND_DRBG *drbg,
                       const unsigned char *buffer, size_t len, size_t entropy);
 size_t rand_drbg_seedlen(RAND_DRBG *drbg);
-/* locking api */
-int rand_drbg_lock(RAND_DRBG *drbg);
-int rand_drbg_unlock(RAND_DRBG *drbg);
-int rand_drbg_enable_locking(RAND_DRBG *drbg);
-
-
-/* initializes the DRBG implementation */
-int drbg_ctr_init(RAND_DRBG *drbg);
-int drbg_hash_init(RAND_DRBG *drbg);
-int drbg_hmac_init(RAND_DRBG *drbg);
 
 /*
  * Entropy call back for the FIPS 140-2 section 4.9.2 Conditional Tests.
index 29f7238c1aac36d8f4632caf80f4eecb20473d55..00f62e523ee8dfc63da87d3f46443acaaa91a8bd 100644 (file)
@@ -3,5 +3,5 @@
 SOURCE[../../libfips.a]=drbg.c
 SOURCE[../../libnonfips.a]=drbg.c
 
-# Missing: drbg_hmac.c crngt.c
-SOURCE[../../libimplementations.a]=test_rng.c drbg_hash.c
+# Missing: drbg_hmac.c
+SOURCE[../../libimplementations.a]=test_rng.c drbg_hash.c crngt.c
diff --git a/providers/implementations/rands/crngt.c b/providers/implementations/rands/crngt.c
new file mode 100644 (file)
index 0000000..2680f7b
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Implementation of the FIPS 140-2 section 4.9.2 Conditional Tests.
+ */
+
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/core_numbers.h>
+#include <openssl/params.h>
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "internal/cryptlib.h"
+#include "prov/rand_pool.h"
+#include "drbg_local.h"
+#include "seeding/seeding.h"
+
+typedef struct crng_test_global_st {
+    unsigned char crngt_prev[EVP_MAX_MD_SIZE];
+    RAND_POOL *crngt_pool;
+} CRNG_TEST_GLOBAL;
+
+static int crngt_get_entropy(OPENSSL_CTX *ctx, RAND_POOL *pool,
+                             unsigned char *buf, unsigned char *md,
+                             unsigned int *md_size)
+{
+    int r;
+    size_t n;
+    unsigned char *p;
+    EVP_MD *fmd;
+
+    if (pool == NULL)
+        return 0;
+
+    n = prov_pool_acquire_entropy(pool);
+    if (n >= CRNGT_BUFSIZ) {
+        fmd = EVP_MD_fetch(ctx, "SHA256", "");
+        if (fmd == NULL)
+            return 0;
+        p = rand_pool_detach(pool);
+        r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL);
+        if (r != 0)
+            memcpy(buf, p, CRNGT_BUFSIZ);
+        rand_pool_reattach(pool, p);
+        EVP_MD_free(fmd);
+        return r;
+    }
+    return 0;
+}
+
+static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
+{
+    CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
+
+    rand_pool_free(crngt_glob->crngt_pool);
+    OPENSSL_free(crngt_glob);
+}
+
+static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx)
+{
+    unsigned char buf[CRNGT_BUFSIZ];
+    CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
+
+    if (crngt_glob == NULL)
+        return NULL;
+
+    if ((crngt_glob->crngt_pool
+         = rand_pool_new(0, 1, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
+        OPENSSL_free(crngt_glob);
+        return NULL;
+    }
+    if (crngt_get_entropy(ctx, crngt_glob->crngt_pool, buf,
+                          crngt_glob->crngt_prev, NULL)) {
+        OPENSSL_cleanse(buf, sizeof(buf));
+        return crngt_glob;
+    }
+    rand_pool_free(crngt_glob->crngt_pool);
+    OPENSSL_free(crngt_glob);
+    return NULL;
+}
+
+static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = {
+    rand_crng_ossl_ctx_new,
+    rand_crng_ossl_ctx_free,
+};
+
+size_t prov_crngt_get_entropy(PROV_DRBG *drbg,
+                              unsigned char **pout,
+                              int entropy, size_t min_len, size_t max_len,
+                              int prediction_resistance)
+{
+    unsigned char buf[CRNGT_BUFSIZ], md[EVP_MAX_MD_SIZE];
+    unsigned int sz;
+    RAND_POOL *pool;
+    size_t q, r = 0, s, t = 0;
+    int attempts = 3;
+    OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(drbg->provctx);
+    CRNG_TEST_GLOBAL *crngt_glob
+        = openssl_ctx_get_data(libctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
+                               &rand_crng_ossl_ctx_method);
+
+    if (crngt_glob == NULL)
+        return 0;
+
+    if ((pool = rand_pool_new(entropy, 1, min_len, max_len)) == NULL)
+        return 0;
+
+    while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
+        s = q > sizeof(buf) ? sizeof(buf) : q;
+        if (!crngt_get_entropy(libctx, crngt_glob->crngt_pool, buf, md,
+                               &sz)
+            || memcmp(crngt_glob->crngt_prev, md, sz) == 0
+            || !rand_pool_add(pool, buf, s, s * 8))
+            goto err;
+        memcpy(crngt_glob->crngt_prev, md, sz);
+        t += s;
+        attempts++;
+    }
+    r = t;
+    *pout = rand_pool_detach(pool);
+err:
+    OPENSSL_cleanse(buf, sizeof(buf));
+    rand_pool_free(pool);
+    return r;
+}
+
+void prov_crngt_cleanup_entropy(PROV_DRBG *drbg,
+                                unsigned char *out, size_t outlen)
+{
+    OPENSSL_secure_clear_free(out, outlen);
+}
diff --git a/providers/implementations/rands/rand_crng_test.c b/providers/implementations/rands/rand_crng_test.c
deleted file mode 100644 (file)
index b348b40..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Implementation of the FIPS 140-2 section 4.9.2 Conditional Tests.
- */
-
-#include <string.h>
-#include <openssl/evp.h>
-#include "crypto/rand.h"
-#include "internal/thread_once.h"
-#include "internal/cryptlib.h"
-#include "crypto/rand_pool.h"
-#include "drbg_local.h"
-#include "crypto/rand_pool.h"
-#include "seeding/seeding.h"
-
-typedef struct crng_test_global_st {
-    unsigned char crngt_prev[EVP_MAX_MD_SIZE];
-    RAND_POOL *crngt_pool;
-} CRNG_TEST_GLOBAL;
-
-static int crngt_get_entropy(OPENSSL_CTX *ctx, RAND_POOL *pool,
-                             unsigned char *buf, unsigned char *md,
-                             unsigned int *md_size)
-{
-    int r;
-    size_t n;
-    unsigned char *p;
-
-    if (pool == NULL)
-        return 0;
-
-    n = prov_pool_acquire_entropy(pool);
-    if (n >= CRNGT_BUFSIZ) {
-        EVP_MD *fmd = EVP_MD_fetch(ctx, "SHA256", "");
-        if (fmd == NULL)
-            return 0;
-        p = rand_pool_detach(pool);
-        r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL);
-        if (r != 0)
-            memcpy(buf, p, CRNGT_BUFSIZ);
-        rand_pool_reattach(pool, p);
-        EVP_MD_free(fmd);
-        return r;
-    }
-    return 0;
-}
-
-static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
-{
-    CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
-
-    rand_pool_free(crngt_glob->crngt_pool);
-    OPENSSL_free(crngt_glob);
-}
-
-static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx)
-{
-    unsigned char buf[CRNGT_BUFSIZ];
-    CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
-
-    if (crngt_glob == NULL)
-        return NULL;
-
-    if ((crngt_glob->crngt_pool
-         = rand_pool_new(0, 1, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
-        OPENSSL_free(crngt_glob);
-        return NULL;
-    }
-    if (crngt_get_entropy(ctx, crngt_glob->crngt_pool, buf,
-                          crngt_glob->crngt_prev, NULL)) {
-        OPENSSL_cleanse(buf, sizeof(buf));
-        return crngt_glob;
-    }
-    rand_pool_free(crngt_glob->crngt_pool);
-    OPENSSL_free(crngt_glob);
-    return NULL;
-}
-
-static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = {
-    rand_crng_ossl_ctx_new,
-    rand_crng_ossl_ctx_free,
-};
-
-int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx,
-                              RAND_POOL *pool,
-                              unsigned char *buf,
-                              unsigned char *md,
-                              unsigned int *md_size)
-{
-    int r;
-    size_t n;
-    unsigned char *p;
-
-    if (pool == NULL)
-        return 0;
-
-    n = rand_pool_acquire_entropy(pool);
-    if (n >= CRNGT_BUFSIZ) {
-        EVP_MD *fmd = EVP_MD_fetch(ctx, "SHA256", "");
-        if (fmd == NULL)
-            return 0;
-        p = rand_pool_detach(pool);
-        r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL);
-        if (r != 0)
-            memcpy(buf, p, CRNGT_BUFSIZ);
-        rand_pool_reattach(pool, p);
-        EVP_MD_free(fmd);
-        return r;
-    }
-    return 0;
-}
-
-size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
-                              unsigned char **pout,
-                              int entropy, size_t min_len, size_t max_len,
-                              int prediction_resistance)
-{
-    unsigned char buf[CRNGT_BUFSIZ], md[EVP_MAX_MD_SIZE];
-    unsigned int sz;
-    RAND_POOL *pool;
-    size_t q, r = 0, s, t = 0;
-    int attempts = 3;
-    CRNG_TEST_GLOBAL *crngt_glob
-        = openssl_ctx_get_data(drbg->libctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
-                               &rand_crng_ossl_ctx_method);
-
-    if (crngt_glob == NULL)
-        return 0;
-
-    if ((pool = rand_pool_new(entropy, 1, min_len, max_len)) == NULL)
-        return 0;
-
-    while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
-        s = q > sizeof(buf) ? sizeof(buf) : q;
-        if (!crngt_get_entropy(drbg->libctx, crngt_glob->crngt_pool, buf, md,
-                               &sz)
-            || memcmp(crngt_glob->crngt_prev, md, sz) == 0
-            || !rand_pool_add(pool, buf, s, s * 8))
-            goto err;
-        memcpy(crngt_glob->crngt_prev, md, sz);
-        t += s;
-        attempts++;
-    }
-    r = t;
-    *pout = rand_pool_detach(pool);
-err:
-    OPENSSL_cleanse(buf, sizeof(buf));
-    rand_pool_free(pool);
-    return r;
-}
-
-void rand_crngt_cleanup_entropy(RAND_DRBG *drbg,
-                                unsigned char *out, size_t outlen)
-{
-    OPENSSL_secure_clear_free(out, outlen);
-}
-
-#if 0
-const OSSL_DISPATCH crngt_functions[] = {
-    { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))crngt_new },
-    { OSSL_FUNC_RAND_FREECTX, (void(*)(void))crngt_free },
-    { OSSL_FUNC_RAND_INSTANTIATE, (void(*)(void))crngt_instantiate },
-    { OSSL_FUNC_RAND_UNINSTANTIATE, (void(*)(void))crngt_uninstantiate },
-    { OSSL_FUNC_RAND_GENERATE, (void(*)(void))crngt_generate },
-    { OSSL_FUNC_RAND_RESEED, (void(*)(void))crngt_reseed },
-    { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))drbg_enable_locking },
-    { OSSL_FUNC_RAND_LOCK, (void(*)(void))drbg_lock },
-    { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))drbg_unlock },
-    { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
-      (void(*)(void))crngt_settable_ctx_params },
-    { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))crngt_set_ctx_params },
-    { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
-      (void(*)(void))crngt_gettable_ctx_params },
-    { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))crngt_get_ctx_params },
-    { 0, NULL }
-};
-#endif