Add GREASE for signature_algorithms This adds `SSL_CTX_set_grease_sigalgs_enabled`, which enables adding a GREASE value in signature_algorithms extensions (for a client only, for now). This functionality will be folded into `SSL_CTX_set_grease_enabled` at a later time, once it has been safely deployed. Bug: 526597789 Change-Id: I792304a78706d72f910dbeac6873748c6a6a6964 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/97987 Presubmit-BoringSSL-Verified: boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Lily Chen <chlily@google.com> Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/include/openssl/prefix_symbols.h b/include/openssl/prefix_symbols.h index 703383c..48d5081 100644 --- a/include/openssl/prefix_symbols.h +++ b/include/openssl/prefix_symbols.h
@@ -2018,6 +2018,7 @@ #pragma redefine_extname SSL_CTX_set_ex_data BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_ex_data) #pragma redefine_extname SSL_CTX_set_false_start_allowed_without_alpn BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_false_start_allowed_without_alpn) #pragma redefine_extname SSL_CTX_set_grease_enabled BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_grease_enabled) +#pragma redefine_extname SSL_CTX_set_grease_sigalgs_enabled BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_grease_sigalgs_enabled) #pragma redefine_extname SSL_CTX_set_info_callback BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_info_callback) #pragma redefine_extname SSL_CTX_set_keylog_callback BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_keylog_callback) #pragma redefine_extname SSL_CTX_set_max_cert_list BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_CTX_set_max_cert_list) @@ -5136,6 +5137,7 @@ #define SSL_CTX_set_ex_data BORINGSSL_ADD_PREFIX(SSL_CTX_set_ex_data) #define SSL_CTX_set_false_start_allowed_without_alpn BORINGSSL_ADD_PREFIX(SSL_CTX_set_false_start_allowed_without_alpn) #define SSL_CTX_set_grease_enabled BORINGSSL_ADD_PREFIX(SSL_CTX_set_grease_enabled) +#define SSL_CTX_set_grease_sigalgs_enabled BORINGSSL_ADD_PREFIX(SSL_CTX_set_grease_sigalgs_enabled) #define SSL_CTX_set_info_callback BORINGSSL_ADD_PREFIX(SSL_CTX_set_info_callback) #define SSL_CTX_set_keylog_callback BORINGSSL_ADD_PREFIX(SSL_CTX_set_keylog_callback) #define SSL_CTX_set_max_cert_list BORINGSSL_ADD_PREFIX(SSL_CTX_set_max_cert_list)
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 8c81152..eb4e772 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -5515,6 +5515,16 @@ // GREASE. See RFC 8701. OPENSSL_EXPORT void SSL_CTX_set_grease_enabled(SSL_CTX *ctx, int enabled); +// SSL_CTX_set_grease_sigalgs_enabled configures whether sockets on `ctx` should +// send a GREASE value in signature_algorithms extensions in ClientHello +// messages. See RFC 8701. +// TODO(crbug.com/526597789): Fold this functionality into +// `SSL_CTX_set_grease_enabled` once deployed safely. +// TODO(crbug.com/529360100): signature_algorithms extensions in +// CertificateRequest messages should also be GREASE'd. +OPENSSL_EXPORT void SSL_CTX_set_grease_sigalgs_enabled(SSL_CTX *ctx, + int enabled); + // SSL_CTX_set_permute_extensions configures whether sockets on `ctx` should // permute extensions. For now, this is only implemented for the ClientHello. OPENSSL_EXPORT void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled);
diff --git a/ssl/extensions.cc b/ssl/extensions.cc index 64152ec..1f29be1 100644 --- a/ssl/extensions.cc +++ b/ssl/extensions.cc
@@ -1030,8 +1030,16 @@ CBB contents, sigalgs_cbb; if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_signature_algorithms) || !CBB_add_u16_length_prefixed(out_compressible, &contents) || - !CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb) || - !tls12_add_verify_sigalgs(hs, &sigalgs_cbb) || + !CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb)) { + return false; + } + // Add a fake signature algorithm. See RFC 8701. + if (hs->ssl->ctx->grease_sigalgs_enabled && + !CBB_add_u16(&sigalgs_cbb, + ssl_get_grease_value(hs, ssl_grease_signature_algorithm))) { + return false; + } + if (!tls12_add_verify_sigalgs(hs, &sigalgs_cbb) || !CBB_flush(out_compressible)) { return false; }
diff --git a/ssl/internal.h b/ssl/internal.h index c8d5330..bdd6320 100644 --- a/ssl/internal.h +++ b/ssl/internal.h
@@ -1665,7 +1665,8 @@ ssl_grease_version, ssl_grease_ticket_extension, ssl_grease_ech_config_id, - ssl_grease_last_index = ssl_grease_ech_config_id, + ssl_grease_signature_algorithm, + ssl_grease_last_index = ssl_grease_signature_algorithm, }; enum tls12_server_hs_state_t { @@ -4160,6 +4161,11 @@ // grease_enabled is whether GREASE (RFC 8701) is enabled. bool grease_enabled : 1; + // grease_sigalgs_enabled controls whether GREASE signature algorithms may be + // sent. + // TODO(crbug.com/526597789): Fold into `grease_enabled` once deployed safely. + bool grease_sigalgs_enabled : 1; + // permute_extensions is whether to permute extensions when sending messages. bool permute_extensions : 1;
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc index f5f7df0..fd287f5 100644 --- a/ssl/ssl_lib.cc +++ b/ssl/ssl_lib.cc
@@ -388,6 +388,7 @@ signed_cert_timestamps_enabled(false), channel_id_enabled(false), grease_enabled(false), + grease_sigalgs_enabled(false), permute_extensions(false), allow_unknown_alpn_protos(false), false_start_allowed_without_alpn(false), @@ -3171,6 +3172,10 @@ FromOpaque(ctx)->grease_enabled = !!enabled; } +void SSL_CTX_set_grease_sigalgs_enabled(SSL_CTX *ctx, int enabled) { + FromOpaque(ctx)->grease_sigalgs_enabled = !!enabled; +} + void SSL_CTX_set_permute_extensions(SSL_CTX *ctx, int enabled) { FromOpaque(ctx)->permute_extensions = !!enabled; }
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go index c5e3d6e..ff2a825 100644 --- a/ssl/test/runner/common.go +++ b/ssl/test/runner/common.go
@@ -2745,6 +2745,12 @@ return slices.ContainsFunc(values, isGREASEValue) } +func containsSigAlgsGREASE(values []signatureAlgorithm) bool { + return slices.ContainsFunc(values, func(s signatureAlgorithm) bool { + return isGREASEValue(uint16(s)) + }) +} + func isAllZero(v []byte) bool { for _, b := range v { if b != 0 {
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go index 181c538..0f1fb47 100644 --- a/ssl/test/runner/handshake_server.go +++ b/ssl/test/runner/handshake_server.go
@@ -379,6 +379,10 @@ return fmt.Errorf("tls: client included signature_algorithms before TLS 1.2") } + if config.Bugs.ExpectGREASE && !containsSigAlgsGREASE(hs.clientHello.signatureAlgorithms) { + return fmt.Errorf("tls: no GREASE signature_algorithms value found") + } + // Check the client cipher list is consistent with the version. if clientVersOK && clientVers.protocolVersion() < VersionTLS12 && slices.ContainsFunc(hs.clientHello.cipherSuites, isTLS12Cipher) { return fmt.Errorf("tls: client offered TLS 1.2 cipher before TLS 1.2")
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc index 4f3e790..58f0c01 100644 --- a/ssl/test/test_config.cc +++ b/ssl/test/test_config.cc
@@ -2120,6 +2120,7 @@ if (enable_grease) { SSL_CTX_set_grease_enabled(ssl_ctx.get(), 1); + SSL_CTX_set_grease_sigalgs_enabled(ssl_ctx.get(), 1); } if (permute_extensions) {