supported with wolfSSL and the other macros did not set a minimum, but
restricted the TLS version to only the specified one.
+rustls support added in 8.10.0.
+
# %AVAILABILITY%
# RETURN VALUE
***************************************************************************/
#include "curl_setup.h"
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
+ defined(USE_BEARSSL) || defined(USE_RUSTLS)
#include "cipher_suite.h"
#include "curl_printf.h"
#include "strcase.h"
/* !checksrc! disable COMMANOSPACE all */
static const struct cs_entry cs_list [] = {
+ /* TLS 1.3 ciphers */
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_RUSTLS)
+ CS_ENTRY(0x1301, TLS,AES,128,GCM,SHA256,,,),
+ CS_ENTRY(0x1302, TLS,AES,256,GCM,SHA384,,,),
+ CS_ENTRY(0x1303, TLS,CHACHA20,POLY1305,SHA256,,,,),
+ CS_ENTRY(0x1304, TLS,AES,128,CCM,SHA256,,,),
+ CS_ENTRY(0x1305, TLS,AES,128,CCM,8,SHA256,,),
+#endif
+ /* TLS 1.2 ciphers */
+ CS_ENTRY(0xC02B, TLS,ECDHE,ECDSA,WITH,AES,128,GCM,SHA256),
+ CS_ENTRY(0xC02B, ECDHE,ECDSA,AES128,GCM,SHA256,,,),
+ CS_ENTRY(0xC02C, TLS,ECDHE,ECDSA,WITH,AES,256,GCM,SHA384),
+ CS_ENTRY(0xC02C, ECDHE,ECDSA,AES256,GCM,SHA384,,,),
+ CS_ENTRY(0xC02F, TLS,ECDHE,RSA,WITH,AES,128,GCM,SHA256),
+ CS_ENTRY(0xC02F, ECDHE,RSA,AES128,GCM,SHA256,,,),
+ CS_ENTRY(0xC030, TLS,ECDHE,RSA,WITH,AES,256,GCM,SHA384),
+ CS_ENTRY(0xC030, ECDHE,RSA,AES256,GCM,SHA384,,,),
+ CS_ENTRY(0xCCA8, TLS,ECDHE,RSA,WITH,CHACHA20,POLY1305,SHA256,),
+ CS_ENTRY(0xCCA8, ECDHE,RSA,CHACHA20,POLY1305,,,,),
+ CS_ENTRY(0xCCA9, TLS,ECDHE,ECDSA,WITH,CHACHA20,POLY1305,SHA256,),
+ CS_ENTRY(0xCCA9, ECDHE,ECDSA,CHACHA20,POLY1305,,,,),
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
CS_ENTRY(0x002F, TLS,RSA,WITH,AES,128,CBC,SHA,),
CS_ENTRY(0x002F, AES128,SHA,,,,,,),
CS_ENTRY(0x0035, TLS,RSA,WITH,AES,256,CBC,SHA,),
CS_ENTRY(0xC029, ECDH,RSA,AES128,SHA256,,,,),
CS_ENTRY(0xC02A, TLS,ECDH,RSA,WITH,AES,256,CBC,SHA384),
CS_ENTRY(0xC02A, ECDH,RSA,AES256,SHA384,,,,),
- CS_ENTRY(0xC02B, TLS,ECDHE,ECDSA,WITH,AES,128,GCM,SHA256),
- CS_ENTRY(0xC02B, ECDHE,ECDSA,AES128,GCM,SHA256,,,),
- CS_ENTRY(0xC02C, TLS,ECDHE,ECDSA,WITH,AES,256,GCM,SHA384),
- CS_ENTRY(0xC02C, ECDHE,ECDSA,AES256,GCM,SHA384,,,),
CS_ENTRY(0xC02D, TLS,ECDH,ECDSA,WITH,AES,128,GCM,SHA256),
CS_ENTRY(0xC02D, ECDH,ECDSA,AES128,GCM,SHA256,,,),
CS_ENTRY(0xC02E, TLS,ECDH,ECDSA,WITH,AES,256,GCM,SHA384),
CS_ENTRY(0xC02E, ECDH,ECDSA,AES256,GCM,SHA384,,,),
- CS_ENTRY(0xC02F, TLS,ECDHE,RSA,WITH,AES,128,GCM,SHA256),
- CS_ENTRY(0xC02F, ECDHE,RSA,AES128,GCM,SHA256,,,),
- CS_ENTRY(0xC030, TLS,ECDHE,RSA,WITH,AES,256,GCM,SHA384),
- CS_ENTRY(0xC030, ECDHE,RSA,AES256,GCM,SHA384,,,),
CS_ENTRY(0xC031, TLS,ECDH,RSA,WITH,AES,128,GCM,SHA256),
CS_ENTRY(0xC031, ECDH,RSA,AES128,GCM,SHA256,,,),
CS_ENTRY(0xC032, TLS,ECDH,RSA,WITH,AES,256,GCM,SHA384),
CS_ENTRY(0xC032, ECDH,RSA,AES256,GCM,SHA384,,,),
- CS_ENTRY(0xCCA8, TLS,ECDHE,RSA,WITH,CHACHA20,POLY1305,SHA256,),
- CS_ENTRY(0xCCA8, ECDHE,RSA,CHACHA20,POLY1305,,,,),
- CS_ENTRY(0xCCA9, TLS,ECDHE,ECDSA,WITH,CHACHA20,POLY1305,SHA256,),
- CS_ENTRY(0xCCA9, ECDHE,ECDSA,CHACHA20,POLY1305,,,,),
+#endif
#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS)
CS_ENTRY(0x0001, TLS,RSA,WITH,NULL,MD5,,,),
CS_ENTRY(0x0001, NULL,MD5,,,,,,),
CS_ENTRY(0x00B8, RSA,PSK,NULL,SHA256,,,,),
CS_ENTRY(0x00B9, TLS,RSA,PSK,WITH,NULL,SHA384,,),
CS_ENTRY(0x00B9, RSA,PSK,NULL,SHA384,,,,),
- CS_ENTRY(0x1301, TLS,AES,128,GCM,SHA256,,,),
- CS_ENTRY(0x1302, TLS,AES,256,GCM,SHA384,,,),
- CS_ENTRY(0x1303, TLS,CHACHA20,POLY1305,SHA256,,,,),
- CS_ENTRY(0x1304, TLS,AES,128,CCM,SHA256,,,),
- CS_ENTRY(0x1305, TLS,AES,128,CCM,8,SHA256,,),
CS_ENTRY(0xC001, TLS,ECDH,ECDSA,WITH,NULL,SHA,,),
CS_ENTRY(0xC001, ECDH,ECDSA,NULL,SHA,,,,),
CS_ENTRY(0xC006, TLS,ECDHE,ECDSA,WITH,NULL,SHA,,),
}
#endif /* defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) */
+ defined(USE_BEARSSL) || defined(USE_RUSTLS) */
#include "curl_setup.h"
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
+ defined(USE_BEARSSL) || defined(USE_RUSTLS)
#include <stdint.h>
/* Lookup IANA id for cipher suite string, returns 0 if not recognized */
bool prefer_rfc);
#endif /* defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) */
+ defined(USE_BEARSSL) || defined(USE_RUSTLS) */
#endif /* HEADER_CURL_CIPHER_SUITE_H */
#include "strerror.h"
#include "multiif.h"
#include "connect.h" /* for the connect timeout */
+#include "cipher_suite.h"
struct rustls_ssl_backend_data
{
return fclose(f) == 0;
}
+static void
+cr_get_selected_ciphers(struct Curl_easy *data,
+ const char *ciphers12,
+ const char *ciphers13,
+ const struct rustls_supported_ciphersuite **selected,
+ size_t *selected_size)
+{
+ size_t supported_len = *selected_size;
+ size_t default_len = rustls_default_ciphersuites_len();
+ const struct rustls_supported_ciphersuite *entry;
+ const char *ciphers = ciphers12;
+ size_t count = 0, default13_count = 0, i, j;
+ const char *ptr, *end;
+
+ DEBUGASSERT(default_len <= supported_len);
+
+ if(!ciphers13) {
+ /* 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);
+ s = rustls_supported_ciphersuite_get_name(entry);
+ if(s.len < 5 || strncmp(s.data, "TLS13", 5) != 0)
+ continue;
+
+ selected[count++] = entry;
+ }
+
+ default13_count = count;
+
+ if(!ciphers)
+ ciphers = "";
+ }
+ else
+ ciphers = ciphers13;
+
+add_ciphers:
+ for(ptr = ciphers; ptr[0] != '\0' && count < supported_len; ptr = end) {
+ uint16_t id = Curl_cipher_suite_walk_str(&ptr, &end);
+
+ /* Check if cipher is supported */
+ if(id) {
+ for(i = 0; i < supported_len; i++) {
+ entry = rustls_all_ciphersuites_get_entry(i);
+ if(rustls_supported_ciphersuite_get_suite(entry) == id)
+ break;
+ }
+ if(i == supported_len)
+ id = 0;
+ }
+ if(!id) {
+ if(ptr[0] != '\0')
+ infof(data, "rustls: unknown cipher in list: \"%.*s\"",
+ (int) (end - ptr), ptr);
+ continue;
+ }
+
+ /* No duplicates allowed (so selected cannot overflow) */
+ for(i = 0; i < count && selected[i] != entry; i++);
+ if(i < count) {
+ if(i >= default13_count)
+ infof(data, "rustls: duplicate cipher in list: \"%.*s\"",
+ (int) (end - ptr), ptr);
+ continue;
+ }
+
+ selected[count++] = entry;
+ }
+
+ if(ciphers == ciphers13 && ciphers12) {
+ ciphers = ciphers12;
+ goto add_ciphers;
+ }
+
+ if(!ciphers12) {
+ /* 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);
+ s = rustls_supported_ciphersuite_get_name(entry);
+ if(s.len < 5 || strncmp(s.data, "TLS13", 5) == 0)
+ continue;
+
+ /* No duplicates allowed (so selected cannot overflow) */
+ for(i = 0; i < count && selected[i] != entry; i++);
+ if(i < count)
+ continue;
+
+ selected[count++] = entry;
+ }
+ }
+
+ *selected_size = count;
+}
+
static CURLcode
cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
struct rustls_ssl_backend_data *const backend)
DEBUGASSERT(backend);
rconn = backend->conn;
- config_builder = rustls_client_config_builder_new();
+ {
+ uint16_t tls_versions[2] = {
+ RUSTLS_TLS_VERSION_TLSV1_2,
+ RUSTLS_TLS_VERSION_TLSV1_3,
+ };
+ size_t tls_versions_len = 2;
+ const struct rustls_supported_ciphersuite **cipher_suites;
+ size_t cipher_suites_len = rustls_default_ciphersuites_len();
+
+ switch(conn_config->version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_1:
+ case CURL_SSLVERSION_TLSv1_2:
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3;
+ tls_versions_len = 1;
+ break;
+ default:
+ failf(data, "rustls: unrecognized minimum TLS version value");
+ return CURLE_SSL_ENGINE_INITFAILED;
+ }
+
+ switch(conn_config->version_max) {
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ case CURL_SSLVERSION_MAX_NONE:
+ case CURL_SSLVERSION_MAX_TLSv1_3:
+ break;
+ case CURL_SSLVERSION_MAX_TLSv1_2:
+ if(tls_versions[0] == RUSTLS_TLS_VERSION_TLSV1_2) {
+ tls_versions_len = 1;
+ break;
+ }
+ FALLTHROUGH();
+ case CURL_SSLVERSION_MAX_TLSv1_1:
+ case CURL_SSLVERSION_MAX_TLSv1_0:
+ default:
+ failf(data, "rustls: unsupported maximum TLS version value");
+ return CURLE_SSL_ENGINE_INITFAILED;
+ }
+
+ cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len));
+ if(!cipher_suites)
+ return CURLE_OUT_OF_MEMORY;
+
+ cr_get_selected_ciphers(data,
+ conn_config->cipher_list,
+ conn_config->cipher_list13,
+ cipher_suites, &cipher_suites_len);
+ if(cipher_suites_len == 0) {
+ failf(data, "rustls: no supported cipher in list");
+ free(cipher_suites);
+ return CURLE_SSL_CIPHER;
+ }
+
+ result = rustls_client_config_builder_new_custom(cipher_suites,
+ cipher_suites_len,
+ tls_versions,
+ tls_versions_len,
+ &config_builder);
+ free(cipher_suites);
+ if(result != RUSTLS_RESULT_OK) {
+ failf(data, "rustls: failed to create client config");
+ return CURLE_SSL_ENGINE_INITFAILED;
+ }
+ }
+
if(connssl->alpn) {
struct alpn_proto_buf proto;
rustls_slice_bytes alpn[ALPN_ENTRIES_MAX];
*/
connssl->io_need = CURL_SSL_IO_NEED_NONE;
if(!rustls_connection_is_handshaking(rconn)) {
- infof(data, "Done handshaking");
/* rustls claims it is no longer handshaking *before* it has
* send its FINISHED message off. We attempt to let it write
* one more time. Oh my.
return tmperr;
}
/* 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;
+ char buf[64] = "";
+ const char *ver = "TLS version unknown";
+ if(proto == RUSTLS_TLS_VERSION_TLSV1_3)
+ ver = "TLSv1.3";
+ if(proto == RUSTLS_TLS_VERSION_TLSV1_2)
+ ver = "TLSv1.2";
+ Curl_cipher_suite_get_str(cipher, buf, sizeof(buf), true);
+ infof(data, "rustls: handshake complete, %s, cipher: %s",
+ ver, buf);
+ }
connssl->state = ssl_connection_complete;
*done = TRUE;
return CURLE_OK;
const struct Curl_ssl Curl_ssl_rustls = {
{ CURLSSLBACKEND_RUSTLS, "rustls" },
SSLSUPP_CAINFO_BLOB | /* supports */
- SSLSUPP_HTTPS_PROXY,
+ SSLSUPP_HTTPS_PROXY |
+ SSLSUPP_CIPHER_LIST |
+ SSLSUPP_TLS13_CIPHERSUITES,
sizeof(struct rustls_ssl_backend_data),
Curl_none_init, /* init */
extra_args = []
if env.curl_uses_lib('gnutls'):
pytest.skip('GnuTLS does not support setting ciphers by name')
- if env.curl_uses_lib('rustls-ffi'):
- pytest.skip('rustls-ffi does not support setting ciphers')
if ciphers[0] & 0xFF00 == 0x1300:
# test setting TLSv1.3 ciphers
if env.curl_uses_lib('bearssl'):
{
}
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
+ defined(USE_BEARSSL) || defined(USE_RUSTLS)
struct test_cs_entry {
uint16_t id;
const char *openssl;
};
static const struct test_cs_entry test_cs_list[] = {
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_RUSTLS)
+ { 0x1301, "TLS_AES_128_GCM_SHA256",
+ NULL },
+ { 0x1302, "TLS_AES_256_GCM_SHA384",
+ NULL },
+ { 0x1303, "TLS_CHACHA20_POLY1305_SHA256",
+ NULL },
+ { 0x1304, "TLS_AES_128_CCM_SHA256",
+ NULL },
+ { 0x1305, "TLS_AES_128_CCM_8_SHA256",
+ NULL },
+#endif
+ { 0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ "ECDHE-ECDSA-AES128-GCM-SHA256" },
+ { 0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ "ECDHE-ECDSA-AES256-GCM-SHA384" },
+ { 0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ "ECDHE-RSA-AES128-GCM-SHA256" },
+ { 0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ "ECDHE-RSA-AES256-GCM-SHA384" },
+ { 0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ "ECDHE-RSA-CHACHA20-POLY1305" },
+ { 0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ "ECDHE-ECDSA-CHACHA20-POLY1305" },
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
{ 0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA",
"AES128-SHA" },
{ 0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA",
"ECDH-RSA-AES128-SHA256" },
{ 0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
"ECDH-RSA-AES256-SHA384" },
- { 0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
- "ECDHE-ECDSA-AES128-GCM-SHA256" },
- { 0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
- "ECDHE-ECDSA-AES256-GCM-SHA384" },
{ 0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
"ECDH-ECDSA-AES128-GCM-SHA256" },
{ 0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
"ECDH-ECDSA-AES256-GCM-SHA384" },
- { 0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
- "ECDHE-RSA-AES128-GCM-SHA256" },
- { 0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
- "ECDHE-RSA-AES256-GCM-SHA384" },
{ 0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
"ECDH-RSA-AES128-GCM-SHA256" },
{ 0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
"ECDH-RSA-AES256-GCM-SHA384" },
- { 0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
- "ECDHE-RSA-CHACHA20-POLY1305" },
- { 0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
- "ECDHE-ECDSA-CHACHA20-POLY1305" },
+#endif
#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS)
{ 0x0001, "TLS_RSA_WITH_NULL_MD5",
"NULL-MD5" },
"RSA-PSK-NULL-SHA256" },
{ 0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384",
"RSA-PSK-NULL-SHA384" },
- { 0x1301, "TLS_AES_128_GCM_SHA256",
- NULL },
- { 0x1302, "TLS_AES_256_GCM_SHA384",
- NULL },
- { 0x1303, "TLS_CHACHA20_POLY1305_SHA256",
- NULL },
- { 0x1304, "TLS_AES_128_CCM_SHA256",
- NULL },
- { 0x1305, "TLS_AES_128_CCM_8_SHA256",
- NULL },
{ 0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA",
"ECDH-ECDSA-NULL-SHA" },
{ 0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA",
const char *str;
};
static const struct test_str_entry test_str_list[] = {
-#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS)
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_RUSTLS)
{ 0x1301, "TLS_AES_128_GCM_SHA256"},
{ 0x1302, "TLS_AES_256_GCM_SHA384"},
{ 0x1303, "TLS_CHACHA20_POLY1305_SHA256"},
#else
{ 0x0000, "DHE-RSA-CHACHA20-POLY1305"},
#endif
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
{ 0xC023, "ECDHE-ECDSA-AES128-SHA256" },
{ 0xC027, "ECDHE-RSA-AES128-SHA256" },
{ 0xC009, "ECDHE-ECDSA-AES128-SHA" },
{ 0xC028, "ECDHE-RSA-AES256-SHA384" },
{ 0xC00A, "ECDHE-ECDSA-AES256-SHA" },
{ 0xC014, "ECDHE-RSA-AES256-SHA" },
+#else
+ { 0x0000, "ECDHE-ECDSA-AES128-SHA256" },
+ { 0x0000, "ECDHE-RSA-AES128-SHA256" },
+ { 0x0000, "ECDHE-ECDSA-AES128-SHA" },
+ { 0x0000, "ECDHE-RSA-AES128-SHA" },
+ { 0x0000, "ECDHE-ECDSA-AES256-SHA384" },
+ { 0x0000, "ECDHE-RSA-AES256-SHA384" },
+ { 0x0000, "ECDHE-ECDSA-AES256-SHA" },
+ { 0x0000, "ECDHE-RSA-AES256-SHA" },
+#endif
#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS)
{ 0x0067, "DHE-RSA-AES128-SHA256" },
{ 0x006B, "DHE-RSA-AES256-SHA256" },
{ 0x0000, "DHE-RSA-AES128-SHA256" },
{ 0x0000, "DHE-RSA-AES256-SHA256" },
#endif
+#if defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || defined(USE_BEARSSL)
{ 0x009C, "AES128-GCM-SHA256" },
{ 0x009D, "AES256-GCM-SHA384" },
{ 0x003C, "AES128-SHA256" },
{ 0x003D, "AES256-SHA256" },
{ 0x002F, "AES128-SHA" },
{ 0x0035, "AES256-SHA" },
+#else
+ { 0x0000, "AES128-GCM-SHA256" },
+ { 0x0000, "AES256-GCM-SHA384" },
+ { 0x0000, "AES128-SHA256" },
+ { 0x0000, "AES256-SHA256" },
+ { 0x0000, "AES128-SHA" },
+ { 0x0000, "AES256-SHA" },
+#endif
#if defined(USE_SECTRANSP) || defined(USE_BEARSSL)
{ 0x000A, "DES-CBC3-SHA" },
#else
UNITTEST_STOP
#endif /* defined(USE_SECTRANSP) || defined(USE_MBEDTLS) || \
- defined(USE_BEARSSL) */
+ defined(USE_BEARSSL) || defined(USE_RUSTLS) */