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