[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
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
% ./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
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;
/* 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;
/* 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;
}
/* 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;
{
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;
};
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:
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");
}
}
+ 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];
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);
/* 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)