Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 /* We need to use some deprecated APIs */
     11 #define OPENSSL_SUPPRESS_DEPRECATED
     12 
     13 #include <string.h>
     14 #include "internal/nelem.h"
     15 #include <openssl/crypto.h>
     16 #include <openssl/err.h>
     17 #include <openssl/rand.h>
     18 #include <openssl/obj_mac.h>
     19 #include <openssl/evp.h>
     20 #include <openssl/aes.h>
     21 #include "../crypto/rand/rand_local.h"
     22 #include "../include/crypto/rand.h"
     23 #include "../include/crypto/evp.h"
     24 #include "../providers/implementations/rands/drbg_local.h"
     25 #include "../crypto/evp/evp_local.h"
     26 
     27 #if defined(_WIN32)
     28 #include <windows.h>
     29 #endif
     30 
     31 #if defined(OPENSSL_SYS_UNIX)
     32 #include <sys/types.h>
     33 #include <sys/wait.h>
     34 #include <unistd.h>
     35 #endif
     36 
     37 #include "testutil.h"
     38 
     39 /*
     40  * DRBG generate wrappers
     41  */
     42 static int gen_bytes(EVP_RAND_CTX *drbg, unsigned char *buf, int num)
     43 {
     44 #ifndef OPENSSL_NO_DEPRECATED_3_0
     45     const RAND_METHOD *meth = RAND_get_rand_method();
     46 
     47     if (meth != NULL && meth != RAND_OpenSSL()) {
     48         if (meth->bytes != NULL)
     49             return meth->bytes(buf, num);
     50         return -1;
     51     }
     52 #endif
     53 
     54     if (drbg != NULL)
     55         return EVP_RAND_generate(drbg, buf, num, 0, 0, NULL, 0);
     56     return 0;
     57 }
     58 
     59 static int rand_bytes(unsigned char *buf, int num)
     60 {
     61     return gen_bytes(RAND_get0_public(NULL), buf, num);
     62 }
     63 
     64 static int rand_priv_bytes(unsigned char *buf, int num)
     65 {
     66     return gen_bytes(RAND_get0_private(NULL), buf, num);
     67 }
     68 
     69 /* size of random output generated in test_drbg_reseed() */
     70 #define RANDOM_SIZE 16
     71 
     72 /*
     73  * DRBG query functions
     74  */
     75 static int state(EVP_RAND_CTX *drbg)
     76 {
     77     return EVP_RAND_get_state(drbg);
     78 }
     79 
     80 static unsigned int query_rand_uint(EVP_RAND_CTX *drbg, const char *name)
     81 {
     82     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
     83     unsigned int n;
     84 
     85     *params = OSSL_PARAM_construct_uint(name, &n);
     86     if (EVP_RAND_CTX_get_params(drbg, params))
     87         return n;
     88     return 0;
     89 }
     90 
     91 #define DRBG_UINT(name)                          \
     92     static unsigned int name(EVP_RAND_CTX *drbg) \
     93     {                                            \
     94         return query_rand_uint(drbg, #name);     \
     95     }
     96 DRBG_UINT(reseed_counter)
     97 
     98 static PROV_DRBG *prov_rand(EVP_RAND_CTX *drbg)
     99 {
    100     return (PROV_DRBG *)drbg->algctx;
    101 }
    102 
    103 static void set_reseed_counter(EVP_RAND_CTX *drbg, unsigned int n)
    104 {
    105     PROV_DRBG *p = prov_rand(drbg);
    106 
    107     p->reseed_counter = n;
    108 }
    109 
    110 static void inc_reseed_counter(EVP_RAND_CTX *drbg)
    111 {
    112     set_reseed_counter(drbg, reseed_counter(drbg) + 1);
    113 }
    114 
    115 static time_t reseed_time(EVP_RAND_CTX *drbg)
    116 {
    117     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
    118     time_t t;
    119 
    120     *params = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME, &t);
    121     if (EVP_RAND_CTX_get_params(drbg, params))
    122         return t;
    123     return 0;
    124 }
    125 
    126 /*
    127  * When building the FIPS module, it isn't possible to disable the continuous
    128  * RNG tests.  Tests that require this are skipped and this means a detection
    129  * mechanism for the FIPS provider being in use.
    130  */
    131 static int using_fips_rng(void)
    132 {
    133     EVP_RAND_CTX *primary = RAND_get0_primary(NULL);
    134     const OSSL_PROVIDER *prov;
    135     const char *name;
    136 
    137     if (!TEST_ptr(primary))
    138         return 0;
    139 
    140     prov = EVP_RAND_get0_provider(EVP_RAND_CTX_get0_rand(primary));
    141     if (!TEST_ptr(prov))
    142         return 0;
    143     name = OSSL_PROVIDER_get0_name(prov);
    144     return strstr(name, "FIPS Provider") != NULL;
    145 }
    146 
    147 /*
    148  * Disable CRNG testing if it is enabled.
    149  * This stub remains to indicate the calling locations where it is necessary.
    150  * Once the RNG infrastructure is able to disable these tests, it should be
    151  * reconstituted.
    152  */
    153 static int disable_crngt(EVP_RAND_CTX *drbg)
    154 {
    155     return 1;
    156 }
    157 
    158 /*
    159  * Generates random output using rand_bytes() and rand_priv_bytes()
    160  * and checks whether the three shared DRBGs were reseeded as
    161  * expected.
    162  *
    163  * |expect_success|: expected outcome (as reported by RAND_status())
    164  * |primary|, |public|, |private|: pointers to the three shared DRBGs
    165  * |public_random|, |private_random|: generated random output
    166  * |expect_xxx_reseed| =
    167  *       1:  it is expected that the specified DRBG is reseeded
    168  *       0:  it is expected that the specified DRBG is not reseeded
    169  *      -1:  don't check whether the specified DRBG was reseeded or not
    170  * |reseed_when|: if nonzero, used instead of time(NULL) to set the
    171  *                |before_reseed| time.
    172  */
    173 static int test_drbg_reseed(int expect_success,
    174     EVP_RAND_CTX *primary,
    175     EVP_RAND_CTX *public,
    176     EVP_RAND_CTX *private,
    177     unsigned char *public_random,
    178     unsigned char *private_random,
    179     int expect_primary_reseed,
    180     int expect_public_reseed,
    181     int expect_private_reseed,
    182     time_t reseed_when)
    183 {
    184     time_t before_reseed, after_reseed;
    185     int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR);
    186     unsigned int primary_reseed, public_reseed, private_reseed;
    187     unsigned char dummy[RANDOM_SIZE];
    188 
    189     if (public_random == NULL)
    190         public_random = dummy;
    191 
    192     if (private_random == NULL)
    193         private_random = dummy;
    194 
    195     /*
    196      * step 1: check preconditions
    197      */
    198 
    199     /* Test whether seed propagation is enabled */
    200     if (!TEST_int_ne(primary_reseed = reseed_counter(primary), 0)
    201         || !TEST_int_ne(public_reseed = reseed_counter(public), 0)
    202         || !TEST_int_ne(private_reseed = reseed_counter(private), 0))
    203         return 0;
    204 
    205     /*
    206      * step 2: generate random output
    207      */
    208 
    209     if (reseed_when == 0)
    210         reseed_when = time(NULL);
    211 
    212     /* Generate random output from the public and private DRBG */
    213     before_reseed = expect_primary_reseed == 1 ? reseed_when : 0;
    214     if (!TEST_int_eq(rand_bytes((unsigned char *)public_random,
    215                          RANDOM_SIZE),
    216             expect_success)
    217         || !TEST_int_eq(rand_priv_bytes((unsigned char *)private_random,
    218                             RANDOM_SIZE),
    219             expect_success))
    220         return 0;
    221     after_reseed = time(NULL);
    222 
    223     /*
    224      * step 3: check postconditions
    225      */
    226 
    227     /* Test whether reseeding succeeded as expected */
    228     if (!TEST_int_eq(state(primary), expected_state)
    229         || !TEST_int_eq(state(public), expected_state)
    230         || !TEST_int_eq(state(private), expected_state))
    231         return 0;
    232 
    233     if (expect_primary_reseed >= 0) {
    234         /* Test whether primary DRBG was reseeded as expected */
    235         if (!TEST_int_ge(reseed_counter(primary), primary_reseed))
    236             return 0;
    237     }
    238 
    239     if (expect_public_reseed >= 0) {
    240         /* Test whether public DRBG was reseeded as expected */
    241         if (!TEST_int_ge(reseed_counter(public), public_reseed)
    242             || !TEST_uint_ge(reseed_counter(public),
    243                 reseed_counter(primary)))
    244             return 0;
    245     }
    246 
    247     if (expect_private_reseed >= 0) {
    248         /* Test whether public DRBG was reseeded as expected */
    249         if (!TEST_int_ge(reseed_counter(private), private_reseed)
    250             || !TEST_uint_ge(reseed_counter(private),
    251                 reseed_counter(primary)))
    252             return 0;
    253     }
    254 
    255     if (expect_success == 1) {
    256         /* Test whether reseed time of primary DRBG is set correctly */
    257         if (!TEST_time_t_le(before_reseed, reseed_time(primary))
    258             || !TEST_time_t_le(reseed_time(primary), after_reseed))
    259             return 0;
    260 
    261         /* Test whether reseed times of child DRBGs are synchronized with primary */
    262         if (!TEST_time_t_ge(reseed_time(public), reseed_time(primary))
    263             || !TEST_time_t_ge(reseed_time(private), reseed_time(primary)))
    264             return 0;
    265     } else {
    266         ERR_clear_error();
    267     }
    268 
    269     return 1;
    270 }
    271 
    272 #if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
    273 /* number of children to fork */
    274 #define DRBG_FORK_COUNT 9
    275 /* two results per child, two for the parent */
    276 #define DRBG_FORK_RESULT_COUNT (2 * (DRBG_FORK_COUNT + 1))
    277 
    278 typedef struct drbg_fork_result_st {
    279 
    280     unsigned char random[RANDOM_SIZE]; /* random output */
    281 
    282     int pindex; /* process index (0: parent, 1,2,3...: children)*/
    283     pid_t pid; /* process id */
    284     int private; /* true if the private drbg was used */
    285     char name[10]; /* 'parent' resp. 'child 1', 'child 2', ... */
    286 } drbg_fork_result;
    287 
    288 /*
    289  * Sort the drbg_fork_result entries in lexicographical order
    290  *
    291  * This simplifies finding duplicate random output and makes
    292  * the printout in case of an error more readable.
    293  */
    294 static int compare_drbg_fork_result(const void *left, const void *right)
    295 {
    296     int result;
    297     const drbg_fork_result *l = left;
    298     const drbg_fork_result *r = right;
    299 
    300     /* separate public and private results */
    301     result = l->private - r->private;
    302 
    303     if (result == 0)
    304         result = memcmp(l->random, r->random, RANDOM_SIZE);
    305 
    306     if (result == 0)
    307         result = l->pindex - r->pindex;
    308 
    309     return result;
    310 }
    311 
    312 /*
    313  * Sort two-byte chunks of random data
    314  *
    315  * Used for finding collisions in two-byte chunks
    316  */
    317 static int compare_rand_chunk(const void *left, const void *right)
    318 {
    319     return memcmp(left, right, 2);
    320 }
    321 
    322 /*
    323  * Test whether primary, public and private DRBG are reseeded
    324  * in the child after forking the process. Collect the random
    325  * output of the public and private DRBG and send it back to
    326  * the parent process.
    327  */
    328 static int test_drbg_reseed_in_child(EVP_RAND_CTX *primary,
    329     EVP_RAND_CTX *public,
    330     EVP_RAND_CTX *private,
    331     drbg_fork_result result[2])
    332 {
    333     int rv = 0, status;
    334     int fd[2];
    335     pid_t pid;
    336     unsigned char random[2 * RANDOM_SIZE];
    337 
    338     if (!TEST_int_ge(pipe(fd), 0))
    339         return 0;
    340 
    341     if (!TEST_int_ge(pid = fork(), 0)) {
    342         close(fd[0]);
    343         close(fd[1]);
    344         return 0;
    345     } else if (pid > 0) {
    346 
    347         /* I'm the parent; close the write end */
    348         close(fd[1]);
    349 
    350         /* wait for children to terminate and collect their random output */
    351         if (TEST_int_eq(waitpid(pid, &status, 0), pid)
    352             && TEST_int_eq(status, 0)
    353             && TEST_true(read(fd[0], &random[0], sizeof(random))
    354                 == sizeof(random))) {
    355 
    356             /* random output of public drbg */
    357             result[0].pid = pid;
    358             result[0].private = 0;
    359             memcpy(result[0].random, &random[0], RANDOM_SIZE);
    360 
    361             /* random output of private drbg */
    362             result[1].pid = pid;
    363             result[1].private = 1;
    364             memcpy(result[1].random, &random[RANDOM_SIZE], RANDOM_SIZE);
    365 
    366             rv = 1;
    367         }
    368 
    369         /* close the read end */
    370         close(fd[0]);
    371 
    372         return rv;
    373 
    374     } else {
    375 
    376         /* I'm the child; close the read end */
    377         close(fd[0]);
    378 
    379         /* check whether all three DRBGs reseed and send output to parent */
    380         if (TEST_true(test_drbg_reseed(1, primary, public, private,
    381                 &random[0], &random[RANDOM_SIZE],
    382                 1, 1, 1, 0))
    383             && TEST_true(write(fd[1], random, sizeof(random))
    384                 == sizeof(random))) {
    385 
    386             rv = 1;
    387         }
    388 
    389         /* close the write end */
    390         close(fd[1]);
    391 
    392         /* convert boolean to exit code */
    393         exit(rv == 0);
    394     }
    395 }
    396 
    397 static int test_rand_reseed_on_fork(EVP_RAND_CTX *primary,
    398     EVP_RAND_CTX *public,
    399     EVP_RAND_CTX *private)
    400 {
    401     unsigned int i;
    402     pid_t pid = getpid();
    403     int verbose = (getenv("V") != NULL);
    404     int success = 1;
    405     int duplicate[2] = { 0, 0 };
    406     unsigned char random[2 * RANDOM_SIZE];
    407     unsigned char sample[DRBG_FORK_RESULT_COUNT * RANDOM_SIZE];
    408     unsigned char *psample = &sample[0];
    409     drbg_fork_result result[DRBG_FORK_RESULT_COUNT];
    410     drbg_fork_result *presult = &result[2];
    411 
    412     memset(&result, 0, sizeof(result));
    413 
    414     for (i = 1; i <= DRBG_FORK_COUNT; ++i) {
    415 
    416         presult[0].pindex = presult[1].pindex = i;
    417 
    418         BIO_snprintf(presult[0].name, sizeof(presult[0].name), "child %d", i);
    419         strcpy(presult[1].name, presult[0].name);
    420 
    421         /* collect the random output of the children */
    422         if (!TEST_true(test_drbg_reseed_in_child(primary,
    423                 public,
    424                 private,
    425                 presult)))
    426             return 0;
    427 
    428         presult += 2;
    429     }
    430 
    431     /* collect the random output of the parent */
    432     if (!TEST_true(test_drbg_reseed(1,
    433             primary, public, private,
    434             &random[0], &random[RANDOM_SIZE],
    435             0, 0, 0, 0)))
    436         return 0;
    437 
    438     strcpy(result[0].name, "parent");
    439     strcpy(result[1].name, "parent");
    440 
    441     /* output of public drbg */
    442     result[0].pid = pid;
    443     result[0].private = 0;
    444     memcpy(result[0].random, &random[0], RANDOM_SIZE);
    445 
    446     /* output of private drbg */
    447     result[1].pid = pid;
    448     result[1].private = 1;
    449     memcpy(result[1].random, &random[RANDOM_SIZE], RANDOM_SIZE);
    450 
    451     /* collect all sampled random data in a single buffer */
    452     for (i = 0; i < DRBG_FORK_RESULT_COUNT; ++i) {
    453         memcpy(psample, &result[i].random[0], RANDOM_SIZE);
    454         psample += RANDOM_SIZE;
    455     }
    456 
    457     /* sort the results... */
    458     qsort(result, DRBG_FORK_RESULT_COUNT, sizeof(drbg_fork_result),
    459         compare_drbg_fork_result);
    460 
    461     /* ...and count duplicate prefixes by looking at the first byte only */
    462     for (i = 1; i < DRBG_FORK_RESULT_COUNT; ++i) {
    463         if (result[i].random[0] == result[i - 1].random[0]) {
    464             /* count public and private duplicates separately */
    465             ++duplicate[result[i].private];
    466         }
    467     }
    468 
    469     if (duplicate[0] >= DRBG_FORK_COUNT - 1) {
    470         /* just too many duplicates to be a coincidence */
    471         TEST_note("ERROR: %d duplicate prefixes in public random output", duplicate[0]);
    472         success = 0;
    473     }
    474 
    475     if (duplicate[1] >= DRBG_FORK_COUNT - 1) {
    476         /* just too many duplicates to be a coincidence */
    477         TEST_note("ERROR: %d duplicate prefixes in private random output", duplicate[1]);
    478         success = 0;
    479     }
    480 
    481     duplicate[0] = 0;
    482 
    483     /* sort the two-byte chunks... */
    484     qsort(sample, sizeof(sample) / 2, 2, compare_rand_chunk);
    485 
    486     /* ...and count duplicate chunks */
    487     for (i = 2, psample = sample + 2; i < sizeof(sample); i += 2, psample += 2) {
    488         if (compare_rand_chunk(psample - 2, psample) == 0)
    489             ++duplicate[0];
    490     }
    491 
    492     if (duplicate[0] >= DRBG_FORK_COUNT - 1) {
    493         /* just too many duplicates to be a coincidence */
    494         TEST_note("ERROR: %d duplicate chunks in random output", duplicate[0]);
    495         success = 0;
    496     }
    497 
    498     if (verbose || !success) {
    499 
    500         for (i = 0; i < DRBG_FORK_RESULT_COUNT; ++i) {
    501             char *rand_hex = OPENSSL_buf2hexstr(result[i].random, RANDOM_SIZE);
    502 
    503             TEST_note("    random: %s, pid: %d (%s, %s)",
    504                 rand_hex,
    505                 result[i].pid,
    506                 result[i].name,
    507                 result[i].private ? "private" : "public");
    508 
    509             OPENSSL_free(rand_hex);
    510         }
    511     }
    512 
    513     return success;
    514 }
    515 
    516 static int test_rand_fork_safety(int i)
    517 {
    518     int success = 1;
    519     unsigned char random[1];
    520     EVP_RAND_CTX *primary, *public, *private;
    521 
    522     /* All three DRBGs should be non-null */
    523     if (!TEST_ptr(primary = RAND_get0_primary(NULL))
    524         || !TEST_ptr(public = RAND_get0_public(NULL))
    525         || !TEST_ptr(private = RAND_get0_private(NULL)))
    526         return 0;
    527 
    528     /* run the actual test */
    529     if (!TEST_true(test_rand_reseed_on_fork(primary, public, private)))
    530         success = 0;
    531 
    532     /* request a single byte from each of the DRBGs before the next run */
    533     if (!TEST_int_gt(RAND_bytes(random, 1), 0) || !TEST_int_gt(RAND_priv_bytes(random, 1), 0))
    534         success = 0;
    535 
    536     return success;
    537 }
    538 #endif
    539 
    540 /*
    541  * Test whether the default rand_method (RAND_OpenSSL()) is
    542  * setup correctly, in particular whether reseeding works
    543  * as designed.
    544  */
    545 static int test_rand_reseed(void)
    546 {
    547     EVP_RAND_CTX *primary, *public, *private;
    548     unsigned char rand_add_buf[256];
    549     int rv = 0;
    550     time_t before_reseed;
    551 
    552     if (using_fips_rng())
    553         return TEST_skip("CRNGT cannot be disabled");
    554 
    555 #ifndef OPENSSL_NO_DEPRECATED_3_0
    556     /* Check whether RAND_OpenSSL() is the default method */
    557     if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
    558         return 0;
    559 #endif
    560 
    561     /* All three DRBGs should be non-null */
    562     if (!TEST_ptr(primary = RAND_get0_primary(NULL))
    563         || !TEST_ptr(public = RAND_get0_public(NULL))
    564         || !TEST_ptr(private = RAND_get0_private(NULL)))
    565         return 0;
    566 
    567     /* There should be three distinct DRBGs, two of them chained to primary */
    568     if (!TEST_ptr_ne(public, private)
    569         || !TEST_ptr_ne(public, primary)
    570         || !TEST_ptr_ne(private, primary)
    571         || !TEST_ptr_eq(prov_rand(public)->parent, prov_rand(primary))
    572         || !TEST_ptr_eq(prov_rand(private)->parent, prov_rand(primary)))
    573         return 0;
    574 
    575     /* Disable CRNG testing for the primary DRBG */
    576     if (!TEST_true(disable_crngt(primary)))
    577         return 0;
    578 
    579     /* uninstantiate the three global DRBGs */
    580     EVP_RAND_uninstantiate(primary);
    581     EVP_RAND_uninstantiate(private);
    582     EVP_RAND_uninstantiate(public);
    583 
    584     /*
    585      * Test initial seeding of shared DRBGs
    586      */
    587     if (!TEST_true(test_drbg_reseed(1,
    588             primary, public, private,
    589             NULL, NULL,
    590             1, 1, 1, 0)))
    591         goto error;
    592 
    593     /*
    594      * Test initial state of shared DRBGs
    595      */
    596     if (!TEST_true(test_drbg_reseed(1,
    597             primary, public, private,
    598             NULL, NULL,
    599             0, 0, 0, 0)))
    600         goto error;
    601 
    602     /*
    603      * Test whether the public and private DRBG are both reseeded when their
    604      * reseed counters differ from the primary's reseed counter.
    605      */
    606     inc_reseed_counter(primary);
    607     if (!TEST_true(test_drbg_reseed(1,
    608             primary, public, private,
    609             NULL, NULL,
    610             0, 1, 1, 0)))
    611         goto error;
    612 
    613     /*
    614      * Test whether the public DRBG is reseeded when its reseed counter differs
    615      * from the primary's reseed counter.
    616      */
    617     inc_reseed_counter(primary);
    618     inc_reseed_counter(private);
    619     if (!TEST_true(test_drbg_reseed(1,
    620             primary, public, private,
    621             NULL, NULL,
    622             0, 1, 0, 0)))
    623         goto error;
    624 
    625     /*
    626      * Test whether the private DRBG is reseeded when its reseed counter differs
    627      * from the primary's reseed counter.
    628      */
    629     inc_reseed_counter(primary);
    630     inc_reseed_counter(public);
    631     if (!TEST_true(test_drbg_reseed(1,
    632             primary, public, private,
    633             NULL, NULL,
    634             0, 0, 1, 0)))
    635         goto error;
    636 
    637     /* fill 'randomness' buffer with some arbitrary data */
    638     memset(rand_add_buf, 'r', sizeof(rand_add_buf));
    639 
    640     /*
    641      * Test whether all three DRBGs are reseeded by RAND_add().
    642      * The before_reseed time has to be measured here and passed into the
    643      * test_drbg_reseed() test, because the primary DRBG gets already reseeded
    644      * in RAND_add(), whence the check for the condition
    645      * before_reseed <= reseed_time(primary) will fail if the time value happens
    646      * to increase between the RAND_add() and the test_drbg_reseed() call.
    647      */
    648     before_reseed = time(NULL);
    649     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
    650     if (!TEST_true(test_drbg_reseed(1,
    651             primary, public, private,
    652             NULL, NULL,
    653             1, 1, 1,
    654             before_reseed)))
    655         goto error;
    656 
    657     rv = 1;
    658 
    659 error:
    660     return rv;
    661 }
    662 
    663 #if defined(OPENSSL_THREADS)
    664 static int multi_thread_rand_bytes_succeeded = 1;
    665 static int multi_thread_rand_priv_bytes_succeeded = 1;
    666 
    667 static int set_reseed_time_interval(EVP_RAND_CTX *drbg, int t)
    668 {
    669     OSSL_PARAM params[2];
    670 
    671     params[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
    672         &t);
    673     params[1] = OSSL_PARAM_construct_end();
    674     return EVP_RAND_CTX_set_params(drbg, params);
    675 }
    676 
    677 static void run_multi_thread_test(void)
    678 {
    679     unsigned char buf[256];
    680     time_t start = time(NULL);
    681     EVP_RAND_CTX *public = NULL, *private = NULL;
    682 
    683     if (!TEST_ptr(public = RAND_get0_public(NULL))
    684         || !TEST_ptr(private = RAND_get0_private(NULL))
    685         || !TEST_true(set_reseed_time_interval(private, 1))
    686         || !TEST_true(set_reseed_time_interval(public, 1))) {
    687         multi_thread_rand_bytes_succeeded = 0;
    688         return;
    689     }
    690 
    691     do {
    692         if (rand_bytes(buf, sizeof(buf)) <= 0)
    693             multi_thread_rand_bytes_succeeded = 0;
    694         if (rand_priv_bytes(buf, sizeof(buf)) <= 0)
    695             multi_thread_rand_priv_bytes_succeeded = 0;
    696     } while (time(NULL) - start < 5);
    697 }
    698 
    699 #if defined(OPENSSL_SYS_WINDOWS)
    700 
    701 typedef HANDLE thread_t;
    702 
    703 static DWORD WINAPI thread_run(LPVOID arg)
    704 {
    705     run_multi_thread_test();
    706     /*
    707      * Because we're linking with a static library, we must stop each
    708      * thread explicitly, or so says OPENSSL_thread_stop(3)
    709      */
    710     OPENSSL_thread_stop();
    711     return 0;
    712 }
    713 
    714 static int run_thread(thread_t *t)
    715 {
    716     *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL);
    717     return *t != NULL;
    718 }
    719 
    720 static int wait_for_thread(thread_t thread)
    721 {
    722     return WaitForSingleObject(thread, INFINITE) == 0;
    723 }
    724 
    725 #else
    726 
    727 typedef pthread_t thread_t;
    728 
    729 static void *thread_run(void *arg)
    730 {
    731     run_multi_thread_test();
    732     /*
    733      * Because we're linking with a static library, we must stop each
    734      * thread explicitly, or so says OPENSSL_thread_stop(3)
    735      */
    736     OPENSSL_thread_stop();
    737     return NULL;
    738 }
    739 
    740 static int run_thread(thread_t *t)
    741 {
    742     return pthread_create(t, NULL, thread_run, NULL) == 0;
    743 }
    744 
    745 static int wait_for_thread(thread_t thread)
    746 {
    747     return pthread_join(thread, NULL) == 0;
    748 }
    749 
    750 #endif
    751 
    752 /*
    753  * The main thread will also run the test, so we'll have THREADS+1 parallel
    754  * tests running
    755  */
    756 #define THREADS 3
    757 
    758 static int test_multi_thread(void)
    759 {
    760     thread_t t[THREADS];
    761     int i;
    762 
    763     for (i = 0; i < THREADS; i++)
    764         run_thread(&t[i]);
    765     run_multi_thread_test();
    766     for (i = 0; i < THREADS; i++)
    767         wait_for_thread(t[i]);
    768 
    769     if (!TEST_true(multi_thread_rand_bytes_succeeded))
    770         return 0;
    771     if (!TEST_true(multi_thread_rand_priv_bytes_succeeded))
    772         return 0;
    773 
    774     return 1;
    775 }
    776 #endif
    777 
    778 static EVP_RAND_CTX *new_drbg(EVP_RAND_CTX *parent)
    779 {
    780     OSSL_PARAM params[2];
    781     EVP_RAND *rand = NULL;
    782     EVP_RAND_CTX *drbg = NULL;
    783 
    784     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
    785         "AES-256-CTR", 0);
    786     params[1] = OSSL_PARAM_construct_end();
    787 
    788     if (!TEST_ptr(rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL))
    789         || !TEST_ptr(drbg = EVP_RAND_CTX_new(rand, parent))
    790         || !TEST_true(EVP_RAND_CTX_set_params(drbg, params))) {
    791         EVP_RAND_CTX_free(drbg);
    792         drbg = NULL;
    793     }
    794     EVP_RAND_free(rand);
    795     return drbg;
    796 }
    797 
    798 static int test_rand_prediction_resistance(void)
    799 {
    800     EVP_RAND_CTX *x = NULL, *y = NULL, *z = NULL;
    801     unsigned char buf1[51], buf2[sizeof(buf1)];
    802     int ret = 0, xreseed, yreseed, zreseed;
    803 
    804     if (using_fips_rng())
    805         return TEST_skip("CRNGT cannot be disabled");
    806 
    807     /* Initialise a three long DRBG chain */
    808     if (!TEST_ptr(x = new_drbg(NULL))
    809         || !TEST_true(disable_crngt(x))
    810         || !TEST_true(EVP_RAND_instantiate(x, 0, 0, NULL, 0, NULL))
    811         || !TEST_ptr(y = new_drbg(x))
    812         || !TEST_true(EVP_RAND_instantiate(y, 0, 0, NULL, 0, NULL))
    813         || !TEST_ptr(z = new_drbg(y))
    814         || !TEST_true(EVP_RAND_instantiate(z, 0, 0, NULL, 0, NULL)))
    815         goto err;
    816 
    817     /*
    818      * During a normal reseed, only the last DRBG in the chain should
    819      * be reseeded.
    820      */
    821     inc_reseed_counter(y);
    822     xreseed = reseed_counter(x);
    823     yreseed = reseed_counter(y);
    824     zreseed = reseed_counter(z);
    825     if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0))
    826         || !TEST_int_eq(reseed_counter(x), xreseed)
    827         || !TEST_int_eq(reseed_counter(y), yreseed)
    828         || !TEST_int_gt(reseed_counter(z), zreseed))
    829         goto err;
    830 
    831     /*
    832      * When prediction resistance is requested, the request should be
    833      * propagated to the primary, so that the entire DRBG chain reseeds.
    834      */
    835     zreseed = reseed_counter(z);
    836     if (!TEST_true(EVP_RAND_reseed(z, 1, NULL, 0, NULL, 0))
    837         || !TEST_int_gt(reseed_counter(x), xreseed)
    838         || !TEST_int_gt(reseed_counter(y), yreseed)
    839         || !TEST_int_gt(reseed_counter(z), zreseed))
    840         goto err;
    841 
    842     /*
    843      * During a normal generate, only the last DRBG should be reseed */
    844     inc_reseed_counter(y);
    845     xreseed = reseed_counter(x);
    846     yreseed = reseed_counter(y);
    847     zreseed = reseed_counter(z);
    848     if (!TEST_true(EVP_RAND_generate(z, buf1, sizeof(buf1), 0, 0, NULL, 0))
    849         || !TEST_int_eq(reseed_counter(x), xreseed)
    850         || !TEST_int_eq(reseed_counter(y), yreseed)
    851         || !TEST_int_gt(reseed_counter(z), zreseed))
    852         goto err;
    853 
    854     /*
    855      * When a prediction resistant generate is requested, the request
    856      * should be propagated to the primary, reseeding the entire DRBG chain.
    857      */
    858     zreseed = reseed_counter(z);
    859     if (!TEST_true(EVP_RAND_generate(z, buf2, sizeof(buf2), 0, 1, NULL, 0))
    860         || !TEST_int_gt(reseed_counter(x), xreseed)
    861         || !TEST_int_gt(reseed_counter(y), yreseed)
    862         || !TEST_int_gt(reseed_counter(z), zreseed)
    863         || !TEST_mem_ne(buf1, sizeof(buf1), buf2, sizeof(buf2)))
    864         goto err;
    865 
    866     /* Verify that a normal reseed still only reseeds the last DRBG */
    867     inc_reseed_counter(y);
    868     xreseed = reseed_counter(x);
    869     yreseed = reseed_counter(y);
    870     zreseed = reseed_counter(z);
    871     if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0))
    872         || !TEST_int_eq(reseed_counter(x), xreseed)
    873         || !TEST_int_eq(reseed_counter(y), yreseed)
    874         || !TEST_int_gt(reseed_counter(z), zreseed))
    875         goto err;
    876 
    877     ret = 1;
    878 err:
    879     EVP_RAND_CTX_free(z);
    880     EVP_RAND_CTX_free(y);
    881     EVP_RAND_CTX_free(x);
    882     return ret;
    883 }
    884 
    885 int setup_tests(void)
    886 {
    887     ADD_TEST(test_rand_reseed);
    888 #if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
    889     ADD_ALL_TESTS(test_rand_fork_safety, RANDOM_SIZE);
    890 #endif
    891     ADD_TEST(test_rand_prediction_resistance);
    892 #if defined(OPENSSL_THREADS)
    893     ADD_TEST(test_multi_thread);
    894 #endif
    895     return 1;
    896 }
    897