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
This commit is contained in:
parent
6d9b40d6a4
commit
8972845123
@ -56,7 +56,6 @@ Graduation requirements:
|
|||||||
Graduation requirements:
|
Graduation requirements:
|
||||||
|
|
||||||
- a reasonable expectation of a stable API going forward.
|
- a reasonable expectation of a stable API going forward.
|
||||||
- a sufficient approach to avoid using weak random numbers
|
|
||||||
|
|
||||||
### WebSocket
|
### WebSocket
|
||||||
|
|
||||||
|
|||||||
@ -34,18 +34,3 @@ See the [rustls-ffi README] for more information on cryptography providers and
|
|||||||
their build/platform requirements.
|
their build/platform requirements.
|
||||||
|
|
||||||
[rustls-ffi README]: https://github.com/rustls/rustls-ffi/blob/main/README.md#cryptography-provide
|
[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.
|
|
||||||
|
|||||||
@ -100,9 +100,9 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(USE_SSL) || defined(USE_RUSTLS)
|
#if !defined(USE_SSL)
|
||||||
/* ---- possibly non-cryptographic version following ---- */
|
/* ---- possibly non-cryptographic version following ---- */
|
||||||
CURLcode Curl_weak_random(struct Curl_easy *data,
|
static CURLcode weak_random(struct Curl_easy *data,
|
||||||
unsigned char *entropy,
|
unsigned char *entropy,
|
||||||
size_t length) /* always 4, size of int */
|
size_t length) /* always 4, size of int */
|
||||||
{
|
{
|
||||||
@ -151,7 +151,7 @@ CURLcode Curl_weak_random(struct Curl_easy *data,
|
|||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
#define _random(x,y,z) Curl_ssl_random(x,y,z)
|
#define _random(x,y,z) Curl_ssl_random(x,y,z)
|
||||||
#else
|
#else
|
||||||
#define _random(x,y,z) Curl_weak_random(x,y,z)
|
#define _random(x,y,z) weak_random(x,y,z)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static CURLcode randit(struct Curl_easy *data, unsigned int *rnd,
|
static CURLcode randit(struct Curl_easy *data, unsigned int *rnd,
|
||||||
|
|||||||
@ -36,11 +36,6 @@ CURLcode Curl_rand_bytes(struct Curl_easy *data,
|
|||||||
#define Curl_rand(a,b,c) Curl_rand_bytes((a), (b), (c))
|
#define Curl_rand(a,b,c) Curl_rand_bytes((a), (b), (c))
|
||||||
#endif
|
#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
|
* 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
|
* hexadecimal digits PLUS a null-terminating byte. It must be an odd number
|
||||||
|
|||||||
@ -216,15 +216,15 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rresult = rustls_connection_read(rconn,
|
rresult = rustls_connection_read(rconn,
|
||||||
(uint8_t *)plainbuf + plain_bytes_copied,
|
(uint8_t *)plainbuf + plain_bytes_copied,
|
||||||
plainlen - plain_bytes_copied,
|
plainlen - plain_bytes_copied,
|
||||||
&n);
|
&n);
|
||||||
if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
|
if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
|
||||||
backend->data_in_pending = FALSE;
|
backend->data_in_pending = FALSE;
|
||||||
}
|
}
|
||||||
else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) {
|
else if(rresult == RUSTLS_RESULT_UNEXPECTED_EOF) {
|
||||||
failf(data, "rustls: peer closed TCP connection "
|
failf(data, "rustls: peer closed TCP connection "
|
||||||
"without first closing TLS connection");
|
"without first closing TLS connection");
|
||||||
*err = CURLE_RECV_ERROR;
|
*err = CURLE_RECV_ERROR;
|
||||||
nread = -1;
|
nread = -1;
|
||||||
goto out;
|
goto out;
|
||||||
@ -449,7 +449,7 @@ cr_get_selected_ciphers(struct Curl_easy *data,
|
|||||||
for(j = 0; j < default_len; j++) {
|
for(j = 0; j < default_len; j++) {
|
||||||
entry = rustls_default_crypto_provider_ciphersuites_get(j);
|
entry = rustls_default_crypto_provider_ciphersuites_get(j);
|
||||||
if(rustls_supported_ciphersuite_protocol_version(entry) !=
|
if(rustls_supported_ciphersuite_protocol_version(entry) !=
|
||||||
RUSTLS_TLS_VERSION_TLSV1_3)
|
RUSTLS_TLS_VERSION_TLSV1_3)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
selected[count++] = entry;
|
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(
|
result = rustls_crypto_provider_builder_new_from_default(
|
||||||
&custom_provider_builder);
|
&custom_provider_builder);
|
||||||
if(result != RUSTLS_RESULT_OK) {
|
if(result != RUSTLS_RESULT_OK) {
|
||||||
failf(data,
|
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;
|
return CURLE_SSL_ENGINE_INITFAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,9 +620,9 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||||||
cipher_suites_len);
|
cipher_suites_len);
|
||||||
if(result != RUSTLS_RESULT_OK) {
|
if(result != RUSTLS_RESULT_OK) {
|
||||||
failf(data,
|
failf(data,
|
||||||
"rustls: failed to set ciphersuites for crypto provider builder");
|
"rustls: failed to set ciphersuites for crypto provider builder");
|
||||||
rustls_crypto_provider_builder_free(custom_provider_builder);
|
rustls_crypto_provider_builder_free(custom_provider_builder);
|
||||||
return CURLE_SSL_ENGINE_INITFAILED;
|
return CURLE_SSL_ENGINE_INITFAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = rustls_crypto_provider_builder_build(
|
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,
|
result = rustls_client_config_builder_new_custom(custom_provider,
|
||||||
tls_versions,
|
tls_versions,
|
||||||
tls_versions_len,
|
tls_versions_len,
|
||||||
&config_builder);
|
&config_builder);
|
||||||
free(cipher_suites);
|
free(cipher_suites);
|
||||||
if(result != RUSTLS_RESULT_OK) {
|
if(result != RUSTLS_RESULT_OK) {
|
||||||
failf(data, "rustls: failed to create client config");
|
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);
|
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 = {
|
const struct Curl_ssl Curl_ssl_rustls = {
|
||||||
{ CURLSSLBACKEND_RUSTLS, "rustls" },
|
{ CURLSSLBACKEND_RUSTLS, "rustls" },
|
||||||
SSLSUPP_CAINFO_BLOB | /* supports */
|
SSLSUPP_CAINFO_BLOB | /* supports */
|
||||||
@ -1070,7 +1080,7 @@ const struct Curl_ssl Curl_ssl_rustls = {
|
|||||||
Curl_none_check_cxn, /* check_cxn */
|
Curl_none_check_cxn, /* check_cxn */
|
||||||
cr_shutdown, /* shutdown */
|
cr_shutdown, /* shutdown */
|
||||||
cr_data_pending, /* data_pending */
|
cr_data_pending, /* data_pending */
|
||||||
Curl_weak_random, /* random */
|
cr_random, /* random */
|
||||||
Curl_none_cert_status_request, /* cert_status_request */
|
Curl_none_cert_status_request, /* cert_status_request */
|
||||||
cr_connect_blocking, /* connect */
|
cr_connect_blocking, /* connect */
|
||||||
cr_connect_nonblocking, /* connect_nonblocking */
|
cr_connect_nonblocking, /* connect_nonblocking */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user