From d76b648584dc231d27b74d1f8d1b106707826557 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 31 Aug 2024 23:37:00 +0200 Subject: [PATCH] rand: only provide weak random when needed builds without TLS and builds using rustls Closes #14749 --- lib/rand.c | 102 +++++++++++++++++++++++++------------------- lib/rand.h | 5 +++ lib/vtls/rustls.c | 3 +- lib/vtls/vtls.c | 20 ++++----- lib/vtls/vtls_int.h | 2 - 5 files changed, 73 insertions(+), 59 deletions(-) diff --git a/lib/rand.c b/lib/rand.c index de96fc93ef..3c1b88db73 100644 --- a/lib/rand.c +++ b/lib/rand.c @@ -100,17 +100,70 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length) } #endif +#if !defined(USE_SSL) || defined(USE_RUSTLS) +/* ---- possibly non-cryptographic version following ---- */ +CURLcode Curl_weak_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) /* always 4, size of int */ +{ + unsigned int r; + DEBUGASSERT(length == sizeof(int)); + + /* Trying cryptographically secure functions first */ +#ifdef _WIN32 + (void)data; + { + CURLcode result = Curl_win32_random(entropy, length); + if(result != CURLE_NOT_BUILT_IN) + return result; + } +#endif + +#if defined(HAVE_ARC4RANDOM) + (void)data; + r = (unsigned int)arc4random(); + memcpy(entropy, &r, length); +#else + infof(data, "WARNING: using weak random seed"); + { + static unsigned int randseed; + static bool seeded = FALSE; + unsigned int rnd; + if(!seeded) { + struct curltime now = Curl_now(); + randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + seeded = TRUE; + } + + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + rnd = (r << 16) | ((r >> 16) & 0xFFFF); + memcpy(entropy, &rnd, length); + } +#endif + return CURLE_OK; +} +#endif + +#ifdef USE_SSL +#define _random(x,y,z) Curl_ssl_random(x,y,z) +#else +#define _random(x,y,z) Curl_weak_random(x,y,z) +#endif + static CURLcode randit(struct Curl_easy *data, unsigned int *rnd, bool env_override) { - CURLcode result = CURLE_OK; - static unsigned int randseed; - static bool seeded = FALSE; - #ifdef DEBUGBUILD if(env_override) { char *force_entropy = getenv("CURL_ENTROPY"); if(force_entropy) { + static unsigned int randseed; + static bool seeded = FALSE; + if(!seeded) { unsigned int seed = 0; size_t elen = strlen(force_entropy); @@ -131,46 +184,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd, #endif /* data may be NULL! */ - result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd)); - if(result != CURLE_NOT_BUILT_IN) - /* only if there is no random function in the TLS backend do the non crypto - version, otherwise return result */ - return result; - - /* ---- non-cryptographic version following ---- */ - -#ifdef _WIN32 - if(!seeded) { - result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd)); - if(result != CURLE_NOT_BUILT_IN) - return result; - } -#endif - -#if defined(HAVE_ARC4RANDOM) && !defined(USE_OPENSSL) - if(!seeded) { - *rnd = (unsigned int)arc4random(); - return CURLE_OK; - } -#endif - - if(!seeded) { - struct curltime now = Curl_now(); - infof(data, "WARNING: using weak random seed"); - randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; - randseed = randseed * 1103515245 + 12345; - randseed = randseed * 1103515245 + 12345; - randseed = randseed * 1103515245 + 12345; - seeded = TRUE; - } - - { - unsigned int r; - /* Return an unsigned 32-bit pseudo-random number. */ - r = randseed = randseed * 1103515245 + 12345; - *rnd = (r << 16) | ((r >> 16) & 0xFFFF); - } - return CURLE_OK; + return _random(data, (unsigned char *)rnd, sizeof(*rnd)); } /* diff --git a/lib/rand.h b/lib/rand.h index 2ba60e7297..7810a903a7 100644 --- a/lib/rand.h +++ b/lib/rand.h @@ -36,6 +36,11 @@ CURLcode Curl_rand_bytes(struct Curl_easy *data, #define Curl_rand(a,b,c) Curl_rand_bytes((a), (b), (c)) #endif +/* ---- non-cryptographic version following ---- */ +CURLcode Curl_weak_random(struct Curl_easy *data, + unsigned char *rnd, + size_t length); + /* * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random * hexadecimal digits PLUS a null-terminating byte. It must be an odd number diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index 96cd8dfa59..be1f666cc1 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -42,6 +42,7 @@ #include "multiif.h" #include "connect.h" /* for the connect timeout */ #include "cipher_suite.h" +#include "rand.h" struct rustls_ssl_backend_data { @@ -1037,7 +1038,7 @@ const struct Curl_ssl Curl_ssl_rustls = { Curl_none_check_cxn, /* check_cxn */ cr_shutdown, /* shutdown */ cr_data_pending, /* data_pending */ - Curl_none_random, /* random */ + Curl_weak_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ cr_connect_blocking, /* connect */ cr_connect_nonblocking, /* connect_nonblocking */ diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 2860a9dc0c..0620220fe8 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -71,6 +71,7 @@ #include "connect.h" #include "select.h" #include "strdup.h" +#include "rand.h" /* The last #include files should be: */ #include "curl_memory.h" @@ -919,11 +920,16 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, return result; } +/* get 32 bits of random */ CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *entropy, size_t length) { - return Curl_ssl->random(data, entropy, length); + DEBUGASSERT(length == sizeof(int)); + if(Curl_ssl->random) + return Curl_ssl->random(data, entropy, length); + else + return CURLE_NOT_BUILT_IN; } /* @@ -1193,16 +1199,6 @@ int Curl_none_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data) return -1; } -CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM, - unsigned char *entropy UNUSED_PARAM, - size_t length UNUSED_PARAM) -{ - (void)data; - (void)entropy; - (void)length; - return CURLE_NOT_BUILT_IN; -} - void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM) { (void)data; @@ -1329,7 +1325,7 @@ static const struct Curl_ssl Curl_ssl_multi = { Curl_none_check_cxn, /* check_cxn */ Curl_none_shutdown, /* shutdown */ Curl_none_data_pending, /* data_pending */ - Curl_none_random, /* random */ + NULL, /* random */ Curl_none_cert_status_request, /* cert_status_request */ multissl_connect, /* connect */ multissl_connect_nonblocking, /* connect_nonblocking */ diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h index 7f32e8c38e..836bfad708 100644 --- a/lib/vtls/vtls_int.h +++ b/lib/vtls/vtls_int.h @@ -171,8 +171,6 @@ void Curl_none_cleanup(void); CURLcode Curl_none_shutdown(struct Curl_cfilter *cf, struct Curl_easy *data, bool send_shutdown, bool *done); int Curl_none_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data); -CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy, - size_t length); void Curl_none_close_all(struct Curl_easy *data); void Curl_none_session_free(void *ptr); bool Curl_none_data_pending(struct Curl_cfilter *cf,