diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index 5d3d0f2fd718fe92ae6e7ae9a8f8afd43ae1ea27..5e6bdceb1ed77c45fad3f7c6e4171c74650655aa 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -534,6 +534,28 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, return 1; } +/* + * Generates |outlen| random bytes and stores them in |out|. It will + * using the given |drbg| to generate the bytes. + * + * Requires that drbg->lock is already locked for write, if non-null. + * + * Returns 1 on success 0 on failure. + */ +int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen) +{ + unsigned char *additional = NULL; + size_t additional_len; + size_t ret; + + additional_len = rand_drbg_get_additional_data(&additional, drbg->max_adinlen); + ret = RAND_DRBG_generate(drbg, out, outlen, 0, additional, additional_len); + if (additional_len != 0) + OPENSSL_secure_clear_free(additional, additional_len); + + return ret; +} + /* * Set the RAND_DRBG callbacks for obtaining entropy and nonce. * diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index 5f859d537693554e341ebbbc5b6b3740129d526e..e3c0b76cde5843ace5d0579684c3f6a56fea81d5 100644 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -215,6 +215,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg, int entropy, size_t min_len, size_t max_len); void rand_drbg_cleanup_entropy(RAND_DRBG *drbg, unsigned char *out, size_t outlen); +size_t rand_drbg_get_additional_data(unsigned char **pout, size_t max_len); /* DRBG helpers */ int rand_drbg_restart(RAND_DRBG *drbg, diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 07f54276d3727696aae43cb7c6ba87fe029fcf1d..3824d93317bf6fda4d44937e2ce69ff919e08910 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -15,6 +15,12 @@ #include #include "internal/thread_once.h" #include "rand_lcl.h" +#ifdef OPENSSL_SYS_UNIX +# include +# include +# include +#endif +#include "e_os.h" #ifndef OPENSSL_NO_ENGINE /* non-NULL if default_RAND_meth is ENGINE-provided */ @@ -187,6 +193,74 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg, return ret; } +/* + * Generate additional data that can be used for the drbg. The data does + * not need to contain entropy, but it's useful if it contains at least + * some bits that are unpredictable. + * + * Returns 0 on failure. + * + * On success it allocates a buffer at |*pout| and returns the length of + * the data. The buffer should get freed using OPENSSL_secure_clear_free(). + */ +size_t rand_drbg_get_additional_data(unsigned char **pout, size_t max_len) +{ + RAND_POOL *pool; + CRYPTO_THREAD_ID thread_id; + size_t len; +#ifdef OPENSSL_SYS_UNIX + pid_t pid; + struct timespec ts; +#elif defined(OPENSSL_SYS_WIN32) + DWORD pid; + FILETIME ft; + LARGE_INTEGER pc; +#endif + uint32_t tsc = 0; + + pool = RAND_POOL_new(0, 0, max_len); + if (pool == NULL) + return 0; + +#ifdef OPENSSL_SYS_UNIX + pid = getpid(); + RAND_POOL_add(pool, (unsigned char *)&pid, sizeof(pid), 0); +#elif defined(OPENSSL_SYS_WIN32) + pid = GetCurrentProcessId(); + RAND_POOL_add(pool, (unsigned char *)&pid, sizeof(pid), 0); +#endif + + thread_id = CRYPTO_THREAD_get_current_id(); + if (thread_id != 0) + RAND_POOL_add(pool, (unsigned char *)&thread_id, sizeof(thread_id), 0); + +#ifdef OPENSSL_CPUID_OBJ + tsc = OPENSSL_rdtsc(); + if (tsc != 0) + RAND_POOL_add(pool, (unsigned char *)&tsc, sizeof(tsc), 0); +#endif + +#ifdef OPENSSL_SYS_UNIX + if (tsc == 0 && clock_gettime(CLOCK_MONOTONIC, &ts) == 0) + RAND_POOL_add(pool, (unsigned char *)&ts, sizeof(ts), 0); + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) + RAND_POOL_add(pool, (unsigned char *)&ts, sizeof(ts), 0); +#elif defined(OPENSSL_SYS_WIN32) + if (tsc == 0 && QueryPerformanceCounter(&pc) != 0) + RAND_POOL_add(pool, (unsigned char *)&pc, sizeof(pc), 0); + GetSystemTimeAsFileTime(&ft); + RAND_POOL_add(pool, (unsigned char *)&ft, sizeof(ft), 0); +#endif + + /* TODO: Use RDSEED? */ + + len = RAND_POOL_length(pool); + if (len != 0) + *pout = RAND_POOL_detach(pool); + RAND_POOL_free(pool); + + return len; +} /* * Implements the cleanup_entropy() callback (see RAND_DRBG_set_callbacks()) diff --git a/include/internal/rand.h b/include/internal/rand.h index 2f9a8015bee79b689fd60e55f25f010c5cd4f566..9fdd0973fe82110e30e304439d51c98292584e73 100644 --- a/include/internal/rand.h +++ b/include/internal/rand.h @@ -42,6 +42,8 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg, int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, int prediction_resistance, const unsigned char *adin, size_t adinlen); +int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen); + int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval); int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval); diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index f68031e57167d8dc295ac9b7dfdbbb611d5a923c..270d4de593e80cad3d0810f70bd112961f9dd35e 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -5267,9 +5267,11 @@ int ssl_randbytes(SSL *s, unsigned char *rnd, size_t size) * serialization of SSL accesses for the needed concurrency protection * here. */ - return RAND_DRBG_generate(s->drbg, rnd, size, 0, NULL, 0); + return RAND_DRBG_bytes(s->drbg, rnd, size); } - return RAND_bytes(rnd, (int)size); + if (size > INT_MAX) + return 0; + return RAND_bytes(rnd, size); } __owur unsigned int ssl_get_max_send_fragment(const SSL *ssl) diff --git a/util/libcrypto.num b/util/libcrypto.num index 3e7d28e167a943eae21b4d1a32b8bca13d2293f4..536a3d24eeef81c97efaa6eef0947d4027239b3a 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4501,3 +4501,4 @@ ADMISSION_SYNTAX_new 4441 1_1_1 EXIST::FUNCTION: EVP_sha512_256 4442 1_1_1 EXIST::FUNCTION: EVP_sha512_224 4443 1_1_1 EXIST::FUNCTION: OCSP_basic_sign_ctx 4444 1_1_1 EXIST::FUNCTION:OCSP +RAND_DRBG_bytes 4445 1_1_1 EXIST::FUNCTION: