Commit 1f985276 authored by Bernd Edlinger's avatar Bernd Edlinger Committed by Dr. Matthias St. Pierre
Browse files

Fix data race in RAND_DRBG_generate



Fixes #7394

Reviewed-by: default avatarPaul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/7399)

(cherry picked from commit a83dc59afa2e0207180d7218efed19b20d48de95)
parent d597a9a8
Loading
Loading
Loading
Loading
+25 −16
Original line number Diff line number Diff line
@@ -316,6 +316,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
        max_entropylen += drbg->max_noncelen;
    }

    drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
    if (drbg->reseed_next_counter) {
        drbg->reseed_next_counter++;
        if(!drbg->reseed_next_counter)
            drbg->reseed_next_counter = 1;
    }

    if (drbg->get_entropy != NULL)
        entropylen = drbg->get_entropy(drbg, &entropy, min_entropy,
                                       min_entropylen, max_entropylen, 0);
@@ -343,12 +350,7 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
    drbg->state = DRBG_READY;
    drbg->reseed_gen_counter = 0;
    drbg->reseed_time = time(NULL);
    if (drbg->reseed_prop_counter > 0) {
        if (drbg->parent == NULL)
            drbg->reseed_prop_counter++;
        else
            drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
    }
    tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);

 end:
    if (entropy != NULL && drbg->cleanup_entropy != NULL)
@@ -423,6 +425,14 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
    }

    drbg->state = DRBG_ERROR;

    drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
    if (drbg->reseed_next_counter) {
        drbg->reseed_next_counter++;
        if(!drbg->reseed_next_counter)
            drbg->reseed_next_counter = 1;
    }

    if (drbg->get_entropy != NULL)
        entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
                                       drbg->min_entropylen,
@@ -440,12 +450,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
    drbg->state = DRBG_READY;
    drbg->reseed_gen_counter = 0;
    drbg->reseed_time = time(NULL);
    if (drbg->reseed_prop_counter > 0) {
        if (drbg->parent == NULL)
            drbg->reseed_prop_counter++;
        else
            drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
    }
    tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);

 end:
    if (entropy != NULL && drbg->cleanup_entropy != NULL)
@@ -616,8 +621,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
            || now - drbg->reseed_time >= drbg->reseed_time_interval)
            reseed_required = 1;
    }
    if (drbg->reseed_prop_counter > 0 && drbg->parent != NULL) {
        if (drbg->reseed_prop_counter != drbg->parent->reseed_prop_counter)
    if (drbg->parent != NULL) {
        unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter);
        if (reseed_counter > 0
                && tsan_load(&drbg->parent->reseed_prop_counter)
                   != reseed_counter)
            reseed_required = 1;
    }

@@ -689,7 +697,8 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
                            RAND_DRBG_get_nonce_fn get_nonce,
                            RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
{
    if (drbg->state != DRBG_UNINITIALISED)
    if (drbg->state != DRBG_UNINITIALISED
            || drbg->parent != NULL)
        return 0;
    drbg->get_entropy = get_entropy;
    drbg->cleanup_entropy = cleanup_entropy;
@@ -866,7 +875,7 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent)
        goto err;

    /* enable seed propagation */
    drbg->reseed_prop_counter = 1;
    tsan_store(&drbg->reseed_prop_counter, 1);

    /*
     * Ignore instantiation error to support just-in-time instantiation.
+3 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
# include <openssl/hmac.h>
# include <openssl/ec.h>
# include <openssl/rand_drbg.h>
# include "internal/tsan_assist.h"

# include "internal/numbers.h"

@@ -231,7 +232,8 @@ struct rand_drbg_st {
     * is added by RAND_add() or RAND_seed() will have an immediate effect on
     * the output of RAND_bytes() resp. RAND_priv_bytes().
     */
    unsigned int reseed_prop_counter;
    TSAN_QUALIFIER unsigned int reseed_prop_counter;
    unsigned int reseed_next_counter;

    size_t seedlen;
    DRBG_STATUS state;
+2 −0
Original line number Diff line number Diff line
@@ -174,6 +174,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
                                   prediction_resistance,
                                   NULL, 0) != 0)
                bytes = bytes_needed;
            drbg->reseed_next_counter
                = tsan_load(&drbg->parent->reseed_prop_counter);
            rand_drbg_unlock(drbg->parent);

            rand_pool_add_end(pool, bytes, 8 * bytes);