From 89728451234ae39a001098157d43633d7eb3f3db Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Thu, 12 Sep 2024 12:38:51 -0400 Subject: [PATCH] vtls/rustls: support strong CSRNG data Now that the curl rustls vtls backend is using rustls 0.14 we can address the weak random situation by using `rustls_default_crypto_provider_random()` to provide a `Curl_ssl` `random` callback that fills the provided buffer with cryptographically secure random data. The mentions in `docs/` about weak RNG when using rustls are removed as they are no longer applicable. Closes #14889 --- docs/EXPERIMENTAL.md | 1 - docs/RUSTLS.md | 15 --------------- lib/rand.c | 6 +++--- lib/rand.h | 5 ----- lib/vtls/rustls.c | 38 ++++++++++++++++++++++++-------------- 5 files changed, 27 insertions(+), 38 deletions(-) diff --git a/docs/EXPERIMENTAL.md b/docs/EXPERIMENTAL.md index b1e3710ed7..7a9de9a810 100644 --- a/docs/EXPERIMENTAL.md +++ b/docs/EXPERIMENTAL.md @@ -56,7 +56,6 @@ Graduation requirements: Graduation requirements: - a reasonable expectation of a stable API going forward. -- a sufficient approach to avoid using weak random numbers ### WebSocket diff --git a/docs/RUSTLS.md b/docs/RUSTLS.md index e91a090a7c..47af01a534 100644 --- a/docs/RUSTLS.md +++ b/docs/RUSTLS.md @@ -34,18 +34,3 @@ See the [rustls-ffi README] for more information on cryptography providers and their build/platform requirements. [rustls-ffi README]: https://github.com/rustls/rustls-ffi/blob/main/README.md#cryptography-provide - -## Randomness - -Every TLS libcurl curl supports - *except* Rustls - provides a function for -curl to extract cryptographically safe random numbers with. - -When you build curl with Rustls, curl uses its own internal attempts to get a -decent random value: - -1. Windows specific APIs -2. arc4random - -If neither of those are present, then curl using Rustls falls back to **weak -pseudo-random values**, and thus weakening several curl authentication -implementations. diff --git a/lib/rand.c b/lib/rand.c index 3c1b88db73..63aebdc8f9 100644 --- a/lib/rand.c +++ b/lib/rand.c @@ -100,9 +100,9 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length) } #endif -#if !defined(USE_SSL) || defined(USE_RUSTLS) +#if !defined(USE_SSL) /* ---- possibly non-cryptographic version following ---- */ -CURLcode Curl_weak_random(struct Curl_easy *data, +static CURLcode weak_random(struct Curl_easy *data, unsigned char *entropy, size_t length) /* always 4, size of int */ { @@ -151,7 +151,7 @@ CURLcode Curl_weak_random(struct Curl_easy *data, #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) +#define _random(x,y,z) weak_random(x,y,z) #endif static CURLcode randit(struct Curl_easy *data, unsigned int *rnd, diff --git a/lib/rand.h b/lib/rand.h index 7810a903a7..2ba60e7297 100644 --- a/lib/rand.h +++ b/lib/rand.h @@ -36,11 +36,6 @@ 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 241d2cc540..02ed4ec45a 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -216,15 +216,15 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data, } rresult = rustls_connection_read(rconn, - (uint8_t *)plainbuf + plain_bytes_copied, - plainlen - plain_bytes_copied, - &n); + (uint8_t *)plainbuf + plain_bytes_copied, + plainlen - plain_bytes_copied, + &n); if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) { backend->data_in_pending = FALSE; } else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) { failf(data, "rustls: peer closed TCP connection " - "without first closing TLS connection"); + "without first closing TLS connection"); *err = CURLE_RECV_ERROR; nread = -1; goto out; @@ -449,7 +449,7 @@ cr_get_selected_ciphers(struct Curl_easy *data, for(j = 0; j < default_len; j++) { entry = rustls_default_crypto_provider_ciphersuites_get(j); if(rustls_supported_ciphersuite_protocol_version(entry) != - RUSTLS_TLS_VERSION_TLSV1_3) + RUSTLS_TLS_VERSION_TLSV1_3) continue; selected[count++] = entry; @@ -606,10 +606,10 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, } result = rustls_crypto_provider_builder_new_from_default( - &custom_provider_builder); + &custom_provider_builder); if(result != RUSTLS_RESULT_OK) { failf(data, - "rustls: failed to create crypto provider builder from default"); + "rustls: failed to create crypto provider builder from default"); return CURLE_SSL_ENGINE_INITFAILED; } @@ -620,9 +620,9 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, cipher_suites_len); if(result != RUSTLS_RESULT_OK) { failf(data, - "rustls: failed to set ciphersuites for crypto provider builder"); - rustls_crypto_provider_builder_free(custom_provider_builder); - return CURLE_SSL_ENGINE_INITFAILED; + "rustls: failed to set ciphersuites for crypto provider builder"); + rustls_crypto_provider_builder_free(custom_provider_builder); + return CURLE_SSL_ENGINE_INITFAILED; } result = rustls_crypto_provider_builder_build( @@ -634,9 +634,9 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, } result = rustls_client_config_builder_new_custom(custom_provider, - tls_versions, - tls_versions_len, - &config_builder); + tls_versions, + tls_versions_len, + &config_builder); free(cipher_suites); if(result != RUSTLS_RESULT_OK) { failf(data, "rustls: failed to create client config"); @@ -1056,6 +1056,16 @@ static size_t cr_version(char *buffer, size_t size) return msnprintf(buffer, size, "%.*s", (int)ver.len, ver.data); } +static CURLcode +cr_random(struct Curl_easy *data, unsigned char *entropy, size_t length) +{ + rustls_result rresult = 0; + (void)data; + rresult = + rustls_default_crypto_provider_random(entropy, length); + return map_error(rresult); +} + const struct Curl_ssl Curl_ssl_rustls = { { CURLSSLBACKEND_RUSTLS, "rustls" }, SSLSUPP_CAINFO_BLOB | /* supports */ @@ -1070,7 +1080,7 @@ const struct Curl_ssl Curl_ssl_rustls = { Curl_none_check_cxn, /* check_cxn */ cr_shutdown, /* shutdown */ cr_data_pending, /* data_pending */ - Curl_weak_random, /* random */ + cr_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ cr_connect_blocking, /* connect */ cr_connect_nonblocking, /* connect_nonblocking */ -- 2.47.2