feat: Add `set_preserve_tls13_cipher_list` method to `SslContextBuilder` (#97)

* feat: Add set_preserve_tls13_cipher_list method to `SslContextBuilder`

* Update boring/src/ssl/mod.rs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
0x676e67 2025-09-19 18:59:00 +08:00 committed by GitHub
parent 37e0cde8c2
commit 2f94005cf0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 210 additions and 70 deletions

View File

@ -4336,7 +4336,7 @@ index 4dd8841b1..01b19c7a3 100644
#if defined(__cplusplus) #if defined(__cplusplus)
} /* extern C */ } /* extern C */
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 53aa9b453..446e0f539 100644 index 53aa9b453..32465017d 100644
--- a/src/include/openssl/ssl.h --- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h +++ b/src/include/openssl/ssl.h
@@ -718,6 +718,12 @@ OPENSSL_EXPORT int SSL_version(const SSL *ssl); @@ -718,6 +718,12 @@ OPENSSL_EXPORT int SSL_version(const SSL *ssl);
@ -4377,7 +4377,7 @@ index 53aa9b453..446e0f539 100644
// Certificate compression. // Certificate compression.
// //
@@ -4570,6 +4587,51 @@ OPENSSL_EXPORT void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled); @@ -4570,6 +4587,61 @@ OPENSSL_EXPORT void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled);
// permute extensions. For now, this is only implemented for the ClientHello. // permute extensions. For now, this is only implemented for the ClientHello.
OPENSSL_EXPORT void SSL_set_permute_extensions(SSL *ssl, int enabled); OPENSSL_EXPORT void SSL_set_permute_extensions(SSL *ssl, int enabled);
@ -4396,11 +4396,11 @@ index 53aa9b453..446e0f539 100644
+OPENSSL_EXPORT void SSL_CTX_set_record_size_limit(SSL_CTX *ctx, uint16_t limit); +OPENSSL_EXPORT void SSL_CTX_set_record_size_limit(SSL_CTX *ctx, uint16_t limit);
+ +
+// SSL_set_key_shares_limit configures whether sockets on |ssl| should +// SSL_set_key_shares_limit configures whether sockets on |ssl| should
+// send three key shares. +// send key shares limit.
+OPENSSL_EXPORT void SSL_set_key_shares_limit(SSL *ssl, uint8_t limit); +OPENSSL_EXPORT void SSL_set_key_shares_limit(SSL *ssl, uint8_t limit);
+ +
+// SSL_CTX_set_key_shares_limit configures whether sockets on |ctx| should +// SSL_CTX_set_key_shares_limit configures whether sockets on |ctx| should
+// send three key shares. +// send key shares limit.
+OPENSSL_EXPORT void SSL_CTX_set_key_shares_limit(SSL_CTX *ctx, uint8_t limit); +OPENSSL_EXPORT void SSL_CTX_set_key_shares_limit(SSL_CTX *ctx, uint8_t limit);
+ +
+ +
@ -4415,21 +4415,31 @@ index 53aa9b453..446e0f539 100644
+// |SSL_CTX_set_aes_override| but only configures a single |SSL*|. +// |SSL_CTX_set_aes_override| but only configures a single |SSL*|.
+OPENSSL_EXPORT void SSL_set_aes_hw_override(SSL *ssl, int override_value); +OPENSSL_EXPORT void SSL_set_aes_hw_override(SSL *ssl, int override_value);
+ +
+// SSL_CTX_set_prefer_chacha20 configures whether sockets on |ctx| should prefer +// SSL_CTX_set_preserve_tls13_cipher_list configures whether sockets on |ctx| should
+// the ChaCha20 cipher suite over AES. This is only relevant for TLS 1.3 and +// preserve the TLS 1.3 cipher list order, retaining the original cipher suite
+// later, where ChaCha20 is not the default cipher suite. +// preferences. When enabled, it may prefer ChaCha20 over AES based on the
+OPENSSL_EXPORT void SSL_CTX_set_prefer_chacha20(SSL_CTX *ctx, +// configured list. This is only relevant for TLS 1.3 and later, where ChaCha20
+ int prefer_chacha20); +// is not the default cipher suite.
+//
+// Note: This function must be called before |SSL_CTX_set_cipher_list| to take
+// effect.
+OPENSSL_EXPORT void SSL_CTX_set_preserve_tls13_cipher_list(SSL_CTX *ctx,
+ int preserve_tls13_cipher_list);
+ +
+// SSL_set_prefer_chacha20 configures whether sockets on |ssl| should prefer +// SSL_set_preserve_tls13_cipher_list configures whether sockets on |ctx| should
+// the ChaCha20 cipher suite over AES. This is only relevant for TLS 1.3 and +// preserve the TLS 1.3 cipher list order, retaining the original cipher suite
+// later, where ChaCha20 is not the default cipher suite. +// preferences. When enabled, it may prefer ChaCha20 over AES based on the
+OPENSSL_EXPORT void SSL_set_prefer_chacha20(SSL *ssl, int prefer_chacha20); +// configured list. This is only relevant for TLS 1.3 and later, where ChaCha20
+// is not the default cipher suite.
+//
+// Note: This function must be called before |SSL_set_cipher_list| to take
+// effect.
+OPENSSL_EXPORT void SSL_set_preserve_tls13_cipher_list(SSL *ssl, int preserve_tls13_cipher_list);
+ +
// SSL_max_seal_overhead returns the maximum overhead, in bytes, of sealing a // SSL_max_seal_overhead returns the maximum overhead, in bytes, of sealing a
// record with |ssl|. // record with |ssl|.
OPENSSL_EXPORT size_t SSL_max_seal_overhead(const SSL *ssl); OPENSSL_EXPORT size_t SSL_max_seal_overhead(const SSL *ssl);
@@ -4874,6 +4936,10 @@ OPENSSL_EXPORT int SSL_CTX_set1_sigalgs_list(SSL_CTX *ctx, const char *str); @@ -4874,6 +4946,10 @@ OPENSSL_EXPORT int SSL_CTX_set1_sigalgs_list(SSL_CTX *ctx, const char *str);
// more convenient to codesearch for specific algorithm values. // more convenient to codesearch for specific algorithm values.
OPENSSL_EXPORT int SSL_set1_sigalgs_list(SSL *ssl, const char *str); OPENSSL_EXPORT int SSL_set1_sigalgs_list(SSL *ssl, const char *str);
@ -4440,7 +4450,7 @@ index 53aa9b453..446e0f539 100644
#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)(arg))) #define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)(arg)))
#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
#define SSL_SESSION_set_app_data(s, a) \ #define SSL_SESSION_set_app_data(s, a) \
@@ -4926,7 +4992,6 @@ DEFINE_STACK_OF(SSL_COMP) @@ -4926,7 +5002,6 @@ DEFINE_STACK_OF(SSL_COMP)
#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0 #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0
#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0 #define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0
#define SSL_OP_NO_COMPRESSION 0 #define SSL_OP_NO_COMPRESSION 0
@ -4448,7 +4458,7 @@ index 53aa9b453..446e0f539 100644
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
#define SSL_OP_NO_SSLv2 0 #define SSL_OP_NO_SSLv2 0
#define SSL_OP_NO_SSLv3 0 #define SSL_OP_NO_SSLv3 0
@@ -5779,6 +5844,7 @@ BSSL_NAMESPACE_END @@ -5779,6 +5854,7 @@ BSSL_NAMESPACE_END
#define SSL_R_ECH_REJECTED 319 #define SSL_R_ECH_REJECTED 319
#define SSL_R_INVALID_OUTER_EXTENSION 320 #define SSL_R_INVALID_OUTER_EXTENSION 320
#define SSL_R_INCONSISTENT_ECH_NEGOTIATION 321 #define SSL_R_INCONSISTENT_ECH_NEGOTIATION 321
@ -5089,7 +5099,7 @@ index 6e5cc2da1..b1b31f3a7 100644
ticket_age_skew < std::numeric_limits<int32_t>::min()) { ticket_age_skew < std::numeric_limits<int32_t>::min()) {
return false; return false;
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 971ebd0b1..c34c7c677 100644 index 971ebd0b1..3ccda1a78 100644
--- a/src/ssl/handshake_client.cc --- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc +++ b/src/ssl/handshake_client.cc
@@ -158,6 +158,8 @@ @@ -158,6 +158,8 @@
@ -5122,15 +5132,15 @@ index 971ebd0b1..c34c7c677 100644
- TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff, - TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
- ssl->config->tls13_cipher_policy))) { - ssl->config->tls13_cipher_policy))) {
- return false; - return false;
+ if (ssl->config->prefer_chacha20) { + if (ssl->config->preserve_tls13_cipher_list &&
+ if (!ssl_add_tls13_cipher(&child, TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff, + ssl->ctx->tls13_cipher_list != NULL &&
+ ssl->config->tls13_cipher_policy) || + sk_SSL_CIPHER_num(ssl->ctx->tls13_cipher_list->ciphers.get()) >= 1) {
+ !ssl_add_tls13_cipher(&child, + for (size_t i = 0; i < sk_SSL_CIPHER_num(ssl->ctx->tls13_cipher_list->ciphers.get()); i++) {
+ TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff, + const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ssl->ctx->tls13_cipher_list->ciphers.get(), i);
+ ssl->config->tls13_cipher_policy) || + uint16_t cipher_id = SSL_CIPHER_get_protocol_id(cipher);
+ !ssl_add_tls13_cipher(&child, TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff, + if (!ssl_add_tls13_cipher(&child, cipher_id, ssl->config->tls13_cipher_policy)) {
+ ssl->config->tls13_cipher_policy)) { + return false;
+ return false; + }
+ } + }
+ } else { + } else {
+ const bool has_aes_hw = ssl->config->aes_hw_override + const bool has_aes_hw = ssl->config->aes_hw_override
@ -5251,7 +5261,7 @@ index 971ebd0b1..c34c7c677 100644
CBB child; CBB child;
if (!CBB_add_u8_length_prefixed(&body, &child)) { if (!CBB_add_u8_length_prefixed(&body, &child)) {
diff --git a/src/ssl/internal.h b/src/ssl/internal.h diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 1e6da2153..2025dcae0 100644 index 1e6da2153..940cc6c29 100644
--- a/src/ssl/internal.h --- a/src/ssl/internal.h
+++ b/src/ssl/internal.h +++ b/src/ssl/internal.h
@@ -323,6 +323,19 @@ class Array { @@ -323,6 +323,19 @@ class Array {
@ -5332,7 +5342,20 @@ index 1e6da2153..2025dcae0 100644
// Bits for |algorithm_prf| (handshake digest). // Bits for |algorithm_prf| (handshake digest).
#define SSL_HANDSHAKE_MAC_DEFAULT 0x1 #define SSL_HANDSHAKE_MAC_DEFAULT 0x1
@@ -1818,7 +1858,7 @@ struct SSL_HANDSHAKE { @@ -639,6 +679,12 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
const bool has_aes_hw, const char *rule_str,
bool strict);
+// ssl_create_tls13_cipher_list is like |ssl_create_cipher_list| but only
+// supports TLS 1.3 cipher suites.
+bool ssl_create_preserve_tls13_cipher_list(
+ UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
+ const char *rule_str, bool strict);
+
// ssl_cipher_auth_mask_for_key returns the mask of cipher |algorithm_auth|
// values suitable for use with |key| in TLS 1.2 and below.
uint32_t ssl_cipher_auth_mask_for_key(const EVP_PKEY *key);
@@ -1818,7 +1864,7 @@ struct SSL_HANDSHAKE {
// key_shares are the current key exchange instances. The second is only used // key_shares are the current key exchange instances. The second is only used
// as a client if we believe that we should offer two key shares in a // as a client if we believe that we should offer two key shares in a
// ClientHello. // ClientHello.
@ -5341,7 +5364,7 @@ index 1e6da2153..2025dcae0 100644
// transcript is the current handshake transcript. // transcript is the current handshake transcript.
SSLTranscript transcript; SSLTranscript transcript;
@@ -1874,6 +1914,9 @@ struct SSL_HANDSHAKE { @@ -1874,6 +1920,9 @@ struct SSL_HANDSHAKE {
// supports with delegated credentials. // supports with delegated credentials.
Array<uint16_t> peer_delegated_credential_sigalgs; Array<uint16_t> peer_delegated_credential_sigalgs;
@ -5351,7 +5374,7 @@ index 1e6da2153..2025dcae0 100644
// peer_key is the peer's ECDH key for a TLS 1.2 client. // peer_key is the peer's ECDH key for a TLS 1.2 client.
Array<uint8_t> peer_key; Array<uint8_t> peer_key;
@@ -2132,6 +2175,10 @@ bool tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg); @@ -2132,6 +2181,10 @@ bool tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg);
bssl::UniquePtr<SSL_SESSION> tls13_create_session_with_ticket(SSL *ssl, bssl::UniquePtr<SSL_SESSION> tls13_create_session_with_ticket(SSL *ssl,
CBS *body); CBS *body);
@ -5362,7 +5385,7 @@ index 1e6da2153..2025dcae0 100644
// ssl_setup_extension_permutation computes a ClientHello extension permutation // ssl_setup_extension_permutation computes a ClientHello extension permutation
// for |hs|, if applicable. It returns true on success and false on error. // for |hs|, if applicable. It returns true on success and false on error.
bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs); bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs);
@@ -3058,6 +3105,10 @@ struct SSL_CONFIG { @@ -3058,6 +3111,10 @@ struct SSL_CONFIG {
// verify_sigalgs, if not empty, is the set of signature algorithms // verify_sigalgs, if not empty, is the set of signature algorithms
// accepted from the peer in decreasing order of preference. // accepted from the peer in decreasing order of preference.
Array<uint16_t> verify_sigalgs; Array<uint16_t> verify_sigalgs;
@ -5373,7 +5396,7 @@ index 1e6da2153..2025dcae0 100644
// srtp_profiles is the list of configured SRTP protection profiles for // srtp_profiles is the list of configured SRTP protection profiles for
// DTLS-SRTP. // DTLS-SRTP.
@@ -3128,6 +3179,20 @@ struct SSL_CONFIG { @@ -3128,6 +3185,21 @@ struct SSL_CONFIG {
// of support for AES hw. The value is only considered if |aes_hw_override| is // of support for AES hw. The value is only considered if |aes_hw_override| is
// true. // true.
bool aes_hw_override_value : 1; bool aes_hw_override_value : 1;
@ -5388,13 +5411,14 @@ index 1e6da2153..2025dcae0 100644
+ // key_shares_limit is the maximum number of key shares to send. + // key_shares_limit is the maximum number of key shares to send.
+ uint8_t key_shares_limit = 0; + uint8_t key_shares_limit = 0;
+ +
+ // prefer_chacha20 indicates that ChaCha20-Poly1305 ciphers should be + // preserve_tls13_cipher_list indicates that the TLS 1.3 cipher list order should
+ // preferred over AES-GCM ciphers. It is only effective on the client side. + // be preserved, potentially preferring ChaCha20-Poly1305 over AES-GCM ciphers.
+ bool prefer_chacha20 : 1; + // It is only effective on the client side.
+ bool preserve_tls13_cipher_list : 1;
}; };
// From RFC 8446, used in determining PSK modes. // From RFC 8446, used in determining PSK modes.
@@ -3696,6 +3761,10 @@ struct ssl_ctx_st { @@ -3696,6 +3768,10 @@ struct ssl_ctx_st {
// accepted from the peer in decreasing order of preference. // accepted from the peer in decreasing order of preference.
bssl::Array<uint16_t> verify_sigalgs; bssl::Array<uint16_t> verify_sigalgs;
@ -5405,7 +5429,7 @@ index 1e6da2153..2025dcae0 100644
// retain_only_sha256_of_client_certs is true if we should compute the SHA256 // retain_only_sha256_of_client_certs is true if we should compute the SHA256
// hash of the peer's certificate and then discard it to save memory and // hash of the peer's certificate and then discard it to save memory and
// session space. Only effective on the server side. // session space. Only effective on the server side.
@@ -3723,6 +3792,10 @@ struct ssl_ctx_st { @@ -3723,6 +3799,10 @@ struct ssl_ctx_st {
// permute_extensions is whether to permute extensions when sending messages. // permute_extensions is whether to permute extensions when sending messages.
bool permute_extensions : 1; bool permute_extensions : 1;
@ -5416,7 +5440,7 @@ index 1e6da2153..2025dcae0 100644
// allow_unknown_alpn_protos is whether the client allows unsolicited ALPN // allow_unknown_alpn_protos is whether the client allows unsolicited ALPN
// protocols from the peer. // protocols from the peer.
bool allow_unknown_alpn_protos : 1; bool allow_unknown_alpn_protos : 1;
@@ -3748,6 +3821,16 @@ struct ssl_ctx_st { @@ -3748,6 +3828,20 @@ struct ssl_ctx_st {
// |aes_hw_override| is true. // |aes_hw_override| is true.
bool aes_hw_override_value : 1; bool aes_hw_override_value : 1;
@ -5426,15 +5450,19 @@ index 1e6da2153..2025dcae0 100644
+ // key_shares limit is the maximum number of key shares to send. + // key_shares limit is the maximum number of key shares to send.
+ uint8_t key_shares_limit = 0; + uint8_t key_shares_limit = 0;
+ +
+ // prefer_chacha20 indicates that ChaCha20-Poly1305 ciphers should be + // preserve_tls13_cipher_list indicates that the TLS 1.3 cipher list order should
+ // preferred over AES-GCM ciphers. It is only effective on the client side. + // be preserved, potentially preferring ChaCha20-Poly1305 over AES-GCM ciphers.
+ bool prefer_chacha20 : 1; + // It is only effective on the client side.
+ bool preserve_tls13_cipher_list : 1;
+
+ // tls13_cipher_list, if non-null, is the list of ciphers to use in TLS 1.3
+ bssl::UniquePtr<bssl::SSLCipherPreferenceList> tls13_cipher_list;
+ +
private: private:
~ssl_ctx_st(); ~ssl_ctx_st();
friend OPENSSL_EXPORT void SSL_CTX_free(SSL_CTX *); friend OPENSSL_EXPORT void SSL_CTX_free(SSL_CTX *);
diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc
index ebb075351..e272c4fed 100644 index ebb075351..20e3cbc61 100644
--- a/src/ssl/ssl_cipher.cc --- a/src/ssl/ssl_cipher.cc
+++ b/src/ssl/ssl_cipher.cc +++ b/src/ssl/ssl_cipher.cc
@@ -175,26 +175,106 @@ static constexpr SSL_CIPHER kCiphers[] = { @@ -175,26 +175,106 @@ static constexpr SSL_CIPHER kCiphers[] = {
@ -5721,7 +5749,79 @@ index ebb075351..e272c4fed 100644
} else { } else {
return false; return false;
} }
@@ -1152,13 +1344,20 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list, @@ -1129,6 +1321,71 @@ static bool ssl_cipher_process_rulestr(const char *rule_str,
return true;
}
+bool ssl_create_preserve_tls13_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
+ const char *rule_str, bool strict) {
+ if (rule_str == NULL || out_cipher_list == NULL) {
+ return false;
+ }
+
+ // TLS 1.3-only ciphers.
+ static const uint16_t kAESTLS13OnlyCiphers[] = {
+ TLS1_3_CK_AES_128_GCM_SHA256 & 0xffff,
+ TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff,
+ TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
+ };
+
+ // Set up a linked list of ciphers.
+ CIPHER_ORDER co_list[OPENSSL_ARRAY_SIZE(kAESTLS13OnlyCiphers)];
+ for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(co_list); i++) {
+ co_list[i].next = i + 1 < OPENSSL_ARRAY_SIZE(co_list) ? &co_list[i + 1] : nullptr;
+ co_list[i].prev = i == 0 ? nullptr : &co_list[i - 1];
+ co_list[i].active = false; // Do not pre-activate
+ co_list[i].in_group = false;
+ }
+ CIPHER_ORDER *head = &co_list[0];
+ CIPHER_ORDER *tail = &co_list[OPENSSL_ARRAY_SIZE(co_list) - 1];
+
+ // Add TLS 1.3 ciphers to the list (but do not activate yet).
+ size_t num = 0;
+ for (uint16_t id : kAESTLS13OnlyCiphers) {
+ co_list[num++].cipher = SSL_get_cipher_by_value(id);
+ assert(co_list[num - 1].cipher != nullptr);
+ // Removed: co_list[num - 1].active = true;
+ }
+ assert(num == OPENSSL_ARRAY_SIZE(co_list));
+
+ // Apply rule_str to activate and order the ciphers.
+ if (!ssl_cipher_process_rulestr(rule_str, &head, &tail, strict)) {
+ return false;
+ }
+
+ // Allocate new "cipherstack" for the result.
+ UniquePtr<STACK_OF(SSL_CIPHER)> cipherstack(sk_SSL_CIPHER_new_null());
+ Array<bool> in_group_flags;
+ if (cipherstack == nullptr || !in_group_flags.Init(OPENSSL_ARRAY_SIZE(kAESTLS13OnlyCiphers))) {
+ return false;
+ }
+
+ // Add active ciphers to the stack in the order after applying rules.
+ size_t num_in_group_flags = 0;
+ for (CIPHER_ORDER *curr = head; curr != NULL; curr = curr->next) {
+ if (curr->active) {
+ if (!sk_SSL_CIPHER_push(cipherstack.get(), curr->cipher)) {
+ return false;
+ }
+ in_group_flags[num_in_group_flags++] = curr->in_group;
+ }
+ }
+
+ UniquePtr<SSLCipherPreferenceList> pref_list = MakeUnique<SSLCipherPreferenceList>();
+ if (!pref_list || !pref_list->Init(std::move(cipherstack), MakeConstSpan(in_group_flags).subspan(0, num_in_group_flags))) {
+ return false;
+ }
+
+ *out_cipher_list = std::move(pref_list);
+ return true;
+}
+
bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
const bool has_aes_hw, const char *rule_str,
bool strict) {
@@ -1152,13 +1409,20 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 & 0xffff, TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 & 0xffff,
}; };
static const uint16_t kLegacyCiphers[] = { static const uint16_t kLegacyCiphers[] = {
@ -5742,7 +5842,7 @@ index ebb075351..e272c4fed 100644
TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 & 0xffff, TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 & 0xffff,
TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 & 0xffff, TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 & 0xffff,
TLS1_CK_RSA_WITH_AES_128_SHA & 0xffff, TLS1_CK_RSA_WITH_AES_128_SHA & 0xffff,
@@ -1166,6 +1365,12 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list, @@ -1166,6 +1430,12 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
TLS1_CK_RSA_WITH_AES_256_SHA & 0xffff, TLS1_CK_RSA_WITH_AES_256_SHA & 0xffff,
TLS1_CK_PSK_WITH_AES_256_CBC_SHA & 0xffff, TLS1_CK_PSK_WITH_AES_256_CBC_SHA & 0xffff,
SSL3_CK_RSA_DES_192_CBC3_SHA & 0xffff, SSL3_CK_RSA_DES_192_CBC3_SHA & 0xffff,
@ -5755,7 +5855,7 @@ index ebb075351..e272c4fed 100644
}; };
// Set up a linked list of ciphers. // Set up a linked list of ciphers.
@@ -1403,6 +1608,8 @@ int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *cipher) { @@ -1403,6 +1673,8 @@ int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *cipher) {
return NID_sha1; return NID_sha1;
case SSL_SHA256: case SSL_SHA256:
return NID_sha256; return NID_sha256;
@ -5764,7 +5864,7 @@ index ebb075351..e272c4fed 100644
} }
assert(0); assert(0);
return NID_undef; return NID_undef;
@@ -1655,6 +1862,10 @@ const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, @@ -1655,6 +1927,10 @@ const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf,
mac = "SHA256"; mac = "SHA256";
break; break;
@ -6473,7 +6573,7 @@ index 09a9ad380..adf48cf71 100644
return nullptr; return nullptr;
} }
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 838761af5..2707f0150 100644 index 838761af5..830ec8e42 100644
--- a/src/ssl/ssl_lib.cc --- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc +++ b/src/ssl/ssl_lib.cc
@@ -537,7 +537,9 @@ ssl_ctx_st::ssl_ctx_st(const SSL_METHOD *ssl_method) @@ -537,7 +537,9 @@ ssl_ctx_st::ssl_ctx_st(const SSL_METHOD *ssl_method)
@ -6483,7 +6583,7 @@ index 838761af5..2707f0150 100644
- aes_hw_override_value(false) { - aes_hw_override_value(false) {
+ aes_hw_override_value(false), + aes_hw_override_value(false),
+ key_shares_limit(0), + key_shares_limit(0),
+ prefer_chacha20(false) { + preserve_tls13_cipher_list(false) {
CRYPTO_MUTEX_init(&lock); CRYPTO_MUTEX_init(&lock);
CRYPTO_new_ex_data(&ex_data); CRYPTO_new_ex_data(&ex_data);
} }
@ -6492,7 +6592,7 @@ index 838761af5..2707f0150 100644
ssl->config->aes_hw_override_value = ctx->aes_hw_override_value; ssl->config->aes_hw_override_value = ctx->aes_hw_override_value;
ssl->config->tls13_cipher_policy = ctx->tls13_cipher_policy; ssl->config->tls13_cipher_policy = ctx->tls13_cipher_policy;
+ ssl->config->key_shares_limit = ctx->key_shares_limit; + ssl->config->key_shares_limit = ctx->key_shares_limit;
+ ssl->config->prefer_chacha20 = ctx->prefer_chacha20; + ssl->config->preserve_tls13_cipher_list = ctx->preserve_tls13_cipher_list;
if (!ssl->config->supported_group_list.CopyFrom(ctx->supported_group_list) || if (!ssl->config->supported_group_list.CopyFrom(ctx->supported_group_list) ||
!ssl->config->alpn_client_proto_list.CopyFrom( !ssl->config->alpn_client_proto_list.CopyFrom(
@ -6519,11 +6619,35 @@ index 838761af5..2707f0150 100644
+ permute_extensions(false), + permute_extensions(false),
+ key_shares_limit(0), + key_shares_limit(0),
+ alps_use_new_codepoint(false), + alps_use_new_codepoint(false),
+ prefer_chacha20(false) { + preserve_tls13_cipher_list(false) {
assert(ssl); assert(ssl);
} }
@@ -2134,6 +2143,62 @@ void SSL_enable_ocsp_stapling(SSL *ssl) { @@ -2041,6 +2050,11 @@ const char *SSL_get_cipher_list(const SSL *ssl, int n) {
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) {
const bool has_aes_hw = ctx->aes_hw_override ? ctx->aes_hw_override_value
: EVP_has_aes_hardware();
+
+ if (ctx->preserve_tls13_cipher_list) {
+ ssl_create_preserve_tls13_cipher_list(&ctx->tls13_cipher_list, str, false /* not strict */);
+ }
+
return ssl_create_cipher_list(&ctx->cipher_list, has_aes_hw, str,
false /* not strict */);
}
@@ -2048,6 +2062,11 @@ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) {
int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx, const char *str) {
const bool has_aes_hw = ctx->aes_hw_override ? ctx->aes_hw_override_value
: EVP_has_aes_hardware();
+
+ if (ctx->preserve_tls13_cipher_list) {
+ ssl_create_preserve_tls13_cipher_list(&ctx->tls13_cipher_list, str, true /* strict */);
+ }
+
return ssl_create_cipher_list(&ctx->cipher_list, has_aes_hw, str,
true /* strict */);
}
@@ -2134,6 +2153,62 @@ void SSL_enable_ocsp_stapling(SSL *ssl) {
ssl->config->ocsp_stapling_enabled = true; ssl->config->ocsp_stapling_enabled = true;
} }
@ -6567,26 +6691,26 @@ index 838761af5..2707f0150 100644
+ ssl->config->aes_hw_override_value = !!override_value; + ssl->config->aes_hw_override_value = !!override_value;
+} +}
+ +
+void SSL_CTX_set_prefer_chacha20(SSL_CTX *ctx, int prefer_chacha20) { +void SSL_CTX_set_preserve_tls13_cipher_list(SSL_CTX *ctx, int preserve_tls13_cipher_list) {
+ if (!ctx) { + if (!ctx) {
+ return; + return;
+ } + }
+ +
+ ctx->prefer_chacha20 = !!prefer_chacha20; + ctx->preserve_tls13_cipher_list = !!preserve_tls13_cipher_list;
+} +}
+ +
+void SSL_set_prefer_chacha20(SSL *ssl, int prefer_chacha20) { +void SSL_set_preserve_tls13_cipher_list(SSL *ssl, int preserve_tls13_cipher_list) {
+ if (!ssl->config) { + if (!ssl->config) {
+ return; + return;
+ } + }
+ +
+ ssl->config->prefer_chacha20 = !!prefer_chacha20; + ssl->config->preserve_tls13_cipher_list = !!preserve_tls13_cipher_list;
+} +}
+ +
void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out, void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out,
size_t *out_len) { size_t *out_len) {
SSL_SESSION *session = SSL_get_session(ssl); SSL_SESSION *session = SSL_get_session(ssl);
@@ -2327,6 +2392,13 @@ int SSL_has_application_settings(const SSL *ssl) { @@ -2327,6 +2402,13 @@ int SSL_has_application_settings(const SSL *ssl) {
return session && session->has_application_settings; return session && session->has_application_settings;
} }
@ -6600,7 +6724,7 @@ index 838761af5..2707f0150 100644
int SSL_CTX_add_cert_compression_alg(SSL_CTX *ctx, uint16_t alg_id, int SSL_CTX_add_cert_compression_alg(SSL_CTX *ctx, uint16_t alg_id,
ssl_cert_compression_func_t compress, ssl_cert_compression_func_t compress,
ssl_cert_decompression_func_t decompress) { ssl_cert_decompression_func_t decompress) {
@@ -2939,6 +3011,21 @@ void SSL_set_permute_extensions(SSL *ssl, int enabled) { @@ -2939,6 +3021,21 @@ void SSL_set_permute_extensions(SSL *ssl, int enabled) {
ssl->config->permute_extensions = !!enabled; ssl->config->permute_extensions = !!enabled;
} }
@ -6622,7 +6746,7 @@ index 838761af5..2707f0150 100644
int32_t SSL_get_ticket_age_skew(const SSL *ssl) { int32_t SSL_get_ticket_age_skew(const SSL *ssl) {
return ssl->s3->ticket_age_skew; return ssl->s3->ticket_age_skew;
} }
@@ -3151,7 +3238,7 @@ namespace fips202205 { @@ -3151,7 +3248,7 @@ namespace fips202205 {
// Section 3.3.1 // Section 3.3.1
// "The server shall be configured to only use cipher suites that are // "The server shall be configured to only use cipher suites that are
// composed entirely of NIST approved algorithms" // composed entirely of NIST approved algorithms"

View File

@ -279,17 +279,6 @@ impl ConnectConfiguration {
unsafe { ffi::SSL_set_aes_hw_override(self.as_ptr(), enable as _) } unsafe { ffi::SSL_set_aes_hw_override(self.as_ptr(), enable as _) }
} }
/// Sets whether the ChaCha20 preference should be enabled.
///
/// Controls the priority of TLS 1.3 cipher suites. When set to `true`, the client prefers:
/// AES_128_GCM, CHACHA20_POLY1305, then AES_256_GCM. Useful in environments with specific
/// encryption requirements.
#[cfg(not(feature = "fips"))]
#[corresponds(SSL_set_prefer_chacha20)]
pub fn set_prefer_chacha20(&mut self, enable: bool) {
unsafe { ffi::SSL_set_prefer_chacha20(self.as_ptr(), enable as _) }
}
/// Sets application settings flag for ALPS (Application-Layer Protocol Negotiation). /// Sets application settings flag for ALPS (Application-Layer Protocol Negotiation).
#[corresponds(SSL_add_application_settings)] #[corresponds(SSL_add_application_settings)]
pub fn add_application_settings(&mut self, alps: &[u8]) -> Result<(), ErrorStack> { pub fn add_application_settings(&mut self, alps: &[u8]) -> Result<(), ErrorStack> {

View File

@ -1910,15 +1910,42 @@ impl SslContextBuilder {
unsafe { ffi::SSL_CTX_set_aes_hw_override(self.as_ptr(), enable as _) } unsafe { ffi::SSL_CTX_set_aes_hw_override(self.as_ptr(), enable as _) }
} }
/// Sets whether to preserve the TLS 1.3 cipher list as configured by [`Self::set_cipher_list`].
///
/// By default, BoringSSL does not preserve the TLS 1.3 cipher list. When this option is disabled
/// (the default), BoringSSL uses its internal default TLS 1.3 cipher suites in its default order,
/// regardless of what is set via [`Self::set_cipher_list`].
///
/// When enabled, this option ensures that the TLS 1.3 cipher suites explicitly set via
/// [`Self::set_cipher_list`] are retained in their original order, without being reordered or
/// modified by BoringSSL's internal logic. This is useful for maintaining specific cipher suite
/// priorities for TLS 1.3. Note that if [`Self::set_cipher_list`] does not include any TLS 1.3
/// cipher suites, BoringSSL will still fall back to its default TLS 1.3 cipher suites and order.
///
/// This feature isn't available in the certified version of BoringSSL.
///
/// # Note
///
/// This method must be called **before** [`Self::set_cipher_list`] to take effect.
/// If called after [`Self::set_cipher_list`], the setting will be ignored.
///
/// [`Self::set_cipher_list`]: #method.set_cipher_list
#[cfg(not(feature = "fips"))]
#[corresponds(SSL_CTX_set_preserve_tls13_cipher_list)]
pub fn set_preserve_tls13_cipher_list(&mut self, enable: bool) {
unsafe { ffi::SSL_CTX_set_preserve_tls13_cipher_list(self.as_ptr(), enable as _) }
}
/// Sets whether the ChaCha20 preference should be enabled. /// Sets whether the ChaCha20 preference should be enabled.
/// ///
/// Controls the priority of TLS 1.3 cipher suites. When set to `true`, the client prefers: /// Controls the priority of TLS 1.3 cipher suites. When set to `true`, the client prefers:
/// AES_128_GCM, CHACHA20_POLY1305, then AES_256_GCM. Useful in environments with specific /// AES_128_GCM, CHACHA20_POLY1305, then AES_256_GCM. Useful in environments with specific
/// encryption requirements. /// encryption requirements.
#[deprecated(note = "use `set_preserve_tls13_cipher_list` instead")]
#[cfg(not(feature = "fips"))] #[cfg(not(feature = "fips"))]
#[corresponds(SSL_CTX_set_prefer_chacha20)] #[corresponds(SSL_CTX_set_prefer_chacha20)]
pub fn set_prefer_chacha20(&mut self, enable: bool) { pub fn set_prefer_chacha20(&mut self, enable: bool) {
unsafe { ffi::SSL_CTX_set_prefer_chacha20(self.as_ptr(), enable as _) } unsafe { ffi::SSL_CTX_set_preserve_tls13_cipher_list(self.as_ptr(), enable as _) }
} }
/// Sets the indices of the extensions to be permuted. /// Sets the indices of the extensions to be permuted.