diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 909960dea8..47dd1cc41e 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -54,7 +54,7 @@ env: # unhandled quictls-version: 3.1.4+quic # renovate: datasource=github-tags depName=rustls/rustls-ffi versioning=semver registryUrl=https://github.com - rustls-version: 0.13.0 + rustls-version: 0.14.0 jobs: linux: diff --git a/docs/RUSTLS.md b/docs/RUSTLS.md index 893fd21348..e91a090a7c 100644 --- a/docs/RUSTLS.md +++ b/docs/RUSTLS.md @@ -9,7 +9,7 @@ SPDX-License-Identifier: curl [Rustls is a TLS backend written in Rust](https://docs.rs/rustls/). Curl can be built to use it as an alternative to OpenSSL or other TLS backends. We use the [rustls-ffi C bindings](https://github.com/rustls/rustls-ffi/). This -version of curl depends on version v0.13.0 of rustls-ffi. +version of curl depends on version v0.14.0 of rustls-ffi. # Building with Rustls @@ -17,7 +17,7 @@ First, [install Rust](https://rustup.rs/). Next, check out, build, and install the appropriate version of rustls-ffi: - % git clone https://github.com/rustls/rustls-ffi -b v0.13.0 + % git clone https://github.com/rustls/rustls-ffi -b v0.14.0 % cd rustls-ffi % make % make DESTDIR=${HOME}/rustls-ffi-built/ install @@ -30,6 +30,11 @@ Now configure and build curl with Rustls: % ./configure --with-rustls=${HOME}/rustls-ffi-built % make +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 diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index e887fbecf2..848bd973cd 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -436,7 +436,7 @@ cr_get_selected_ciphers(struct Curl_easy *data, size_t *selected_size) { size_t supported_len = *selected_size; - size_t default_len = rustls_default_ciphersuites_len(); + size_t default_len = rustls_default_crypto_provider_ciphersuites_len(); const struct rustls_supported_ciphersuite *entry; const char *ciphers = ciphers12; size_t count = 0, default13_count = 0, i, j; @@ -448,7 +448,7 @@ cr_get_selected_ciphers(struct Curl_easy *data, /* Add default TLSv1.3 ciphers to selection */ for(j = 0; j < default_len; j++) { struct rustls_str s; - entry = rustls_default_ciphersuites_get_entry(j); + entry = rustls_default_crypto_provider_ciphersuites_get(j); s = rustls_supported_ciphersuite_get_name(entry); if(s.len < 5 || strncmp(s.data, "TLS13", 5) != 0) continue; @@ -471,7 +471,7 @@ add_ciphers: /* Check if cipher is supported */ if(id) { for(i = 0; i < supported_len; i++) { - entry = rustls_all_ciphersuites_get_entry(i); + entry = rustls_default_crypto_provider_ciphersuites_get(i); if(rustls_supported_ciphersuite_get_suite(entry) == id) break; } @@ -506,7 +506,7 @@ add_ciphers: /* Add default TLSv1.2 ciphers to selection */ for(j = 0; j < default_len; j++) { struct rustls_str s; - entry = rustls_default_ciphersuites_get_entry(j); + entry = rustls_default_crypto_provider_ciphersuites_get(j); s = rustls_supported_ciphersuite_get_name(entry); if(s.len >= 5 && strncmp(s.data, "TLS13", 5) == 0) continue; @@ -529,6 +529,8 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, { struct ssl_connect_data *connssl = cf->ctx; struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); + struct rustls_crypto_provider_builder *custom_provider_builder = NULL; + const struct rustls_crypto_provider *custom_provider = NULL; struct rustls_connection *rconn = NULL; struct rustls_client_config_builder *config_builder = NULL; const struct rustls_root_cert_store *roots = NULL; @@ -554,7 +556,8 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, }; size_t tls_versions_len = 2; const struct rustls_supported_ciphersuite **cipher_suites; - size_t cipher_suites_len = rustls_default_ciphersuites_len(); + size_t cipher_suites_len = + rustls_default_crypto_provider_ciphersuites_len(); switch(conn_config->version) { case CURL_SSLVERSION_DEFAULT: @@ -604,11 +607,38 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, return CURLE_SSL_CIPHER; } - result = rustls_client_config_builder_new_custom(cipher_suites, - cipher_suites_len, - tls_versions, - tls_versions_len, - &config_builder); + result = rustls_crypto_provider_builder_new_from_default( + &custom_provider_builder); + if(result != RUSTLS_RESULT_OK) { + failf(data, + "rustls: failed to create crypto provider builder from default"); + return CURLE_SSL_ENGINE_INITFAILED; + } + + result = + rustls_crypto_provider_builder_set_cipher_suites( + custom_provider_builder, + cipher_suites, + 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; + } + + result = rustls_crypto_provider_builder_build( + custom_provider_builder, &custom_provider); + if(result != RUSTLS_RESULT_OK) { + failf(data, "rustls: failed to build custom crypto provider"); + rustls_crypto_provider_builder_free(custom_provider_builder); + return CURLE_SSL_ENGINE_INITFAILED; + } + + result = rustls_client_config_builder_new_custom(custom_provider, + tls_versions, + tls_versions_len, + &config_builder); free(cipher_suites); if(result != RUSTLS_RESULT_OK) { failf(data, "rustls: failed to create client config"); @@ -616,6 +646,9 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, } } + rustls_crypto_provider_builder_free(custom_provider_builder); + rustls_crypto_provider_free(custom_provider); + if(connssl->alpn) { struct alpn_proto_buf proto; rustls_slice_bytes alpn[ALPN_ENTRIES_MAX]; @@ -710,7 +743,15 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, rustls_server_cert_verifier_free(server_cert_verifier); } - backend->config = rustls_client_config_builder_build(config_builder); + result = rustls_client_config_builder_build( + config_builder, + &backend->config); + if(result != RUSTLS_RESULT_OK) { + failf(data, "rustls: failed to build client config"); + rustls_client_config_free(backend->config); + return CURLE_SSL_ENGINE_INITFAILED; + } + DEBUGASSERT(rconn == NULL); result = rustls_client_connection_new(backend->config, connssl->peer.hostname, &rconn); @@ -806,10 +847,7 @@ cr_connect_common(struct Curl_cfilter *cf, /* REALLY Done with the handshake. */ { uint16_t proto = rustls_connection_get_protocol_version(rconn); - const rustls_supported_ciphersuite *rcipher = - rustls_connection_get_negotiated_ciphersuite(rconn); - uint16_t cipher = rcipher ? - rustls_supported_ciphersuite_get_suite(rcipher) : 0; + uint16_t cipher = rustls_connection_get_negotiated_ciphersuite(rconn); char buf[64] = ""; const char *ver = "TLS version unknown"; if(proto == RUSTLS_TLS_VERSION_TLSV1_3)