X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Frand%2Frand_lib.c;h=8c28550a7606b125dee5fec5d2236e578ccf89d0;hb=32cf5baeae21774db04af2ad2d74567a617c6fec;hp=4503215e1d7976e6ba884b917dbdf4941c74a9a0;hpb=651d0aff98d28e2db146afa1790e9e22f3ef22db;p=oweals%2Fopenssl.git diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 4503215e1d..8c28550a76 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -57,48 +57,212 @@ */ #include -#include "cryptlib.h" -#include #include -#include "rand.h" +#include "cryptlib.h" +#include + +#ifndef OPENSSL_NO_ENGINE +#include +#endif + +#ifdef OPENSSL_FIPS +#include +#include +#endif + +#ifndef OPENSSL_NO_ENGINE +/* non-NULL if default_RAND_meth is ENGINE-provided */ +static ENGINE *funct_ref =NULL; +#endif +static const RAND_METHOD *default_RAND_meth = NULL; + +int RAND_set_rand_method(const RAND_METHOD *meth) + { +#ifndef OPENSSL_NO_ENGINE + if(funct_ref) + { + ENGINE_finish(funct_ref); + funct_ref = NULL; + } +#endif + default_RAND_meth = meth; + return 1; + } -#ifdef NO_RAND -static RAND_METHOD *rand_meth=NULL; -#else -extern RAND_METHOD rand_ssleay_meth; -static RAND_METHOD *rand_meth= &rand_ssleay_meth; +const RAND_METHOD *RAND_get_rand_method(void) + { + if (!default_RAND_meth) + { +#ifndef OPENSSL_NO_ENGINE + ENGINE *e = ENGINE_get_default_RAND(); + if(e) + { + default_RAND_meth = ENGINE_get_RAND(e); + if(!default_RAND_meth) + { + ENGINE_finish(e); + e = NULL; + } + } + if(e) + funct_ref = e; + else +#endif + default_RAND_meth = RAND_SSLeay(); + } + return default_RAND_meth; + } + +#ifndef OPENSSL_NO_ENGINE +int RAND_set_rand_engine(ENGINE *engine) + { + const RAND_METHOD *tmp_meth = NULL; + if(engine) + { + if(!ENGINE_init(engine)) + return 0; + tmp_meth = ENGINE_get_RAND(engine); + if(!tmp_meth) + { + ENGINE_finish(engine); + return 0; + } + } + /* This function releases any prior ENGINE so call it first */ + RAND_set_rand_method(tmp_meth); + funct_ref = engine; + return 1; + } #endif -void RAND_set_rand_method(meth) -RAND_METHOD *meth; +void RAND_cleanup(void) { - rand_meth=meth; + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->cleanup) + meth->cleanup(); + RAND_set_rand_method(NULL); } -RAND_METHOD *RAND_get_rand_method() +void RAND_seed(const void *buf, int num) { - return(rand_meth); + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->seed) + meth->seed(buf,num); } -void RAND_cleanup() +void RAND_add(const void *buf, int num, double entropy) { - if (rand_meth != NULL) - rand_meth->cleanup(); + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->add) + meth->add(buf,num,entropy); } -void RAND_seed(buf,num) -unsigned char *buf; -int num; +int RAND_bytes(unsigned char *buf, int num) { - if (rand_meth != NULL) - rand_meth->seed(buf,num); + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->bytes) + return meth->bytes(buf,num); + return(-1); } -void RAND_bytes(buf,num) -unsigned char *buf; -int num; +int RAND_pseudo_bytes(unsigned char *buf, int num) { - if (rand_meth != NULL) - rand_meth->bytes(buf,num); + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->pseudorand) + return meth->pseudorand(buf,num); + return(-1); } +int RAND_status(void) + { + const RAND_METHOD *meth = RAND_get_rand_method(); + if (meth && meth->status) + return meth->status(); + return 0; + } + +#ifdef OPENSSL_FIPS + +/* FIPS DRBG initialisation code. This sets up the DRBG for use by the + * rest of OpenSSL. + */ + +/* Entropy gatherer: use standard OpenSSL PRNG to seed (this will gather + * entropy internally through RAND_poll(). + */ + +static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout, + int entropy, size_t min_len, size_t max_len) + { + /* Round up request to multiple of block size */ + min_len = ((min_len + 19) / 20) * 20; + *pout = OPENSSL_malloc(min_len); + if (!*pout) + return 0; + if (RAND_SSLeay()->bytes(*pout, min_len) <= 0) + { + OPENSSL_free(*pout); + *pout = NULL; + return 0; + } + return min_len; + } + +static void drbg_free_entropy(DRBG_CTX *ctx, unsigned char *out, size_t olen) + { + OPENSSL_cleanse(out, olen); + OPENSSL_free(out); + } + +/* Set "additional input" when generating random data. This uses the + * current PID, a time value and a counter. + */ + +static size_t drbg_get_adin(DRBG_CTX *ctx, unsigned char **pout) + { + /* Use of static variables is OK as this happens under a lock */ + static unsigned char buf[16]; + static unsigned long counter; + FIPS_get_timevec(buf, &counter); + *pout = buf; + return sizeof(buf); + } + +/* RAND_add() and RAND_seed() pass through to OpenSSL PRNG so it is + * correctly seeded by RAND_poll(). + */ + +static int drbg_rand_add(DRBG_CTX *ctx, const void *in, int inlen, + double entropy) + { + return RAND_SSLeay()->add(in, inlen, entropy); + } + +static int drbg_rand_seed(DRBG_CTX *ctx, const void *in, int inlen) + { + return RAND_SSLeay()->seed(in, inlen); + } + +int RAND_init_fips(void) + { + DRBG_CTX *dctx; + size_t plen; + unsigned char pers[32], *p; + dctx = FIPS_get_default_drbg(); + FIPS_drbg_init(dctx, NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF); + FIPS_drbg_set_callbacks(dctx, + drbg_get_entropy, drbg_free_entropy, 20, + drbg_get_entropy, drbg_free_entropy); + FIPS_drbg_set_rand_callbacks(dctx, drbg_get_adin, 0, + drbg_rand_seed, drbg_rand_add); + /* Personalisation string: a string followed by date time vector */ + strcpy((char *)pers, "OpenSSL DRBG2.0"); + plen = drbg_get_adin(dctx, &p); + memcpy(pers + 16, p, plen); + + FIPS_drbg_instantiate(dctx, pers, sizeof(pers)); + FIPS_rand_set_method(FIPS_drbg_method()); + return 1; + } + +#endif