Add functions to allow the mocking of AES hw support for testing.
Bug: 586
Change-Id: I5bc8e6df3a5a14e6b218f41181d06406e835f9c1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/58605
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index b4d669a..68253bd 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -5413,6 +5413,18 @@
const SSL *ssl, Span<const uint8_t> *out_read_traffic_secret,
Span<const uint8_t> *out_write_traffic_secret);
+// SSL_CTX_set_aes_hw_override_for_testing sets |override_value| to
+// override checking for aes hardware support for testing. If |override_value|
+// is set to true, the library will behave as if aes hardware support is
+// present. If it is set to false, the library will behave as if aes hardware
+// support is not present.
+OPENSSL_EXPORT void SSL_CTX_set_aes_hw_override_for_testing(
+ SSL_CTX *ctx, bool override_value);
+
+// SSL_set_aes_hw_override_for_testing acts the same as
+// |SSL_CTX_set_aes_override_for_testing| but only configures a single |SSL*|.
+OPENSSL_EXPORT void SSL_set_aes_hw_override_for_testing(SSL *ssl,
+ bool override_value);
BSSL_NAMESPACE_END
diff --git a/ssl/encrypted_client_hello.cc b/ssl/encrypted_client_hello.cc
index 8d35f18..a5492e9 100644
--- a/ssl/encrypted_client_hello.cc
+++ b/ssl/encrypted_client_hello.cc
@@ -601,8 +601,8 @@
static bool select_ech_cipher_suite(const EVP_HPKE_KDF **out_kdf,
const EVP_HPKE_AEAD **out_aead,
- Span<const uint8_t> cipher_suites) {
- const bool has_aes_hardware = EVP_has_aes_hardware();
+ Span<const uint8_t> cipher_suites,
+ const bool has_aes_hardware) {
const EVP_HPKE_AEAD *aead = nullptr;
CBS cbs = cipher_suites;
while (CBS_len(&cbs) != 0) {
@@ -660,7 +660,10 @@
const EVP_HPKE_AEAD *aead;
if (supported && //
ech_config.kem_id == EVP_HPKE_DHKEM_X25519_HKDF_SHA256 &&
- select_ech_cipher_suite(&kdf, &aead, ech_config.cipher_suites)) {
+ select_ech_cipher_suite(&kdf, &aead, ech_config.cipher_suites,
+ hs->ssl->config->aes_hw_override
+ ? hs->ssl->config->aes_hw_override_value
+ : EVP_has_aes_hardware())) {
ScopedCBB info;
static const uint8_t kInfoLabel[] = "tls ech"; // includes trailing NUL
if (!CBB_init(info.get(), sizeof(kInfoLabel) + ech_config.raw.size()) ||
@@ -714,9 +717,11 @@
}
const uint16_t kdf_id = EVP_HPKE_HKDF_SHA256;
- const EVP_HPKE_AEAD *aead = EVP_has_aes_hardware()
- ? EVP_hpke_aes_128_gcm()
- : EVP_hpke_chacha20_poly1305();
+ const bool has_aes_hw = hs->ssl->config->aes_hw_override
+ ? hs->ssl->config->aes_hw_override_value
+ : EVP_has_aes_hardware();
+ const EVP_HPKE_AEAD *aead =
+ has_aes_hw ? EVP_hpke_aes_128_gcm() : EVP_hpke_chacha20_poly1305();
static_assert(ssl_grease_ech_config_id < sizeof(hs->grease_seed),
"hs->grease_seed is too small");
uint8_t config_id = hs->grease_seed[ssl_grease_ech_config_id];
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index 3e63019..7fe2a2b 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -239,8 +239,12 @@
TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
ssl->config->only_fips_cipher_suites_in_tls13);
- if (!EVP_has_aes_hardware() && //
- include_chacha20 && //
+ const bool has_aes_hw = ssl->config->aes_hw_override
+ ? ssl->config->aes_hw_override_value
+ : EVP_has_aes_hardware();
+
+ if (!has_aes_hw && //
+ include_chacha20 && //
!CBB_add_u16(&child, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
return false;
}
@@ -248,8 +252,8 @@
!CBB_add_u16(&child, TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff)) {
return false;
}
- if (EVP_has_aes_hardware() && //
- include_chacha20 && //
+ if (has_aes_hw && //
+ include_chacha20 && //
!CBB_add_u16(&child, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
return false;
}
diff --git a/ssl/internal.h b/ssl/internal.h
index b4d853a..15ad6c2 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -633,9 +633,11 @@
// newly-allocated |SSLCipherPreferenceList| containing the result. It returns
// true on success and false on failure. If |strict| is true, nonsense will be
// rejected. If false, nonsense will be silently ignored. An empty result is
-// considered an error regardless of |strict|.
+// considered an error regardless of |strict|. |has_aes_hw| indicates if the
+// list should be ordered based on having support for AES in hardware or not.
bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
- const char *rule_str, bool strict);
+ const bool has_aes_hw, 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.
@@ -659,9 +661,12 @@
// ssl_choose_tls13_cipher returns an |SSL_CIPHER| corresponding with the best
// available from |cipher_suites| compatible with |version|, |group_id|, and
-// |only_fips|. It returns NULL if there isn't a compatible cipher.
-const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, uint16_t version,
- uint16_t group_id, bool only_fips);
+// |only_fips|. It returns NULL if there isn't a compatible cipher. |has_aes_hw|
+// indicates if the choice should be made as if support for AES in hardware
+// is available.
+const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, bool has_aes_hw,
+ uint16_t version, uint16_t group_id,
+ bool only_fips);
// ssl_tls13_cipher_meets_policy returns true if |cipher_id| is acceptable given
// |only_fips|. (For now there's only a single policy and so the policy argument
@@ -3111,6 +3116,15 @@
// only_fips_cipher_suites_in_tls13 constrains the selection of cipher suites
// in TLS 1.3 such that only FIPS approved ones will be selected.
bool only_fips_cipher_suites_in_tls13 : 1;
+
+ // aes_hw_override if set indicates we should override checking for aes
+ // hardware support, and use the value in aes_hw_override_value instead.
+ bool aes_hw_override : 1;
+
+ // aes_hw_override_value is used for testing to indicate the support or lack
+ // of support for AES hw. The value is only considered if |aes_hw_override| is
+ // true.
+ bool aes_hw_override_value : 1;
};
// From RFC 8446, used in determining PSK modes.
@@ -3722,6 +3736,15 @@
// in TLS 1.3 such that only FIPS approved ones will be selected.
bool only_fips_cipher_suites_in_tls13 : 1;
+ // aes_hw_override if set indicates we should override checking for AES
+ // hardware support, and use the value in aes_hw_override_value instead.
+ bool aes_hw_override : 1;
+
+ // aes_hw_override_value is used for testing to indicate the support or lack
+ // of support for AES hardware. The value is only considered if
+ // |aes_hw_override| is true.
+ bool aes_hw_override_value : 1;
+
private:
~ssl_ctx_st();
friend OPENSSL_EXPORT void SSL_CTX_free(SSL_CTX *);
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index eb9da0d..f8352f3 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -663,7 +663,7 @@
// the client.
class CipherScorer {
public:
- CipherScorer() : aes_is_fine_(EVP_has_aes_hardware()) {}
+ CipherScorer(bool has_aes_hw) : aes_is_fine_(has_aes_hw) {}
typedef std::tuple<bool, bool> Score;
@@ -702,14 +702,15 @@
}
}
-const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, uint16_t version,
- uint16_t group_id, bool only_fips) {
+const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, bool has_aes_hw,
+ uint16_t version, uint16_t group_id,
+ bool only_fips) {
if (CBS_len(&cipher_suites) % 2 != 0) {
return nullptr;
}
const SSL_CIPHER *best = nullptr;
- CipherScorer scorer;
+ CipherScorer scorer(has_aes_hw);
CipherScorer::Score best_score = scorer.MinScore();
while (CBS_len(&cipher_suites) > 0) {
diff --git a/ssl/ssl_cipher.cc b/ssl/ssl_cipher.cc
index b08eb20..73564b3 100644
--- a/ssl/ssl_cipher.cc
+++ b/ssl/ssl_cipher.cc
@@ -1148,7 +1148,8 @@
}
bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
- const char *rule_str, bool strict) {
+ const bool has_aes_hw, const char *rule_str,
+ bool strict) {
// Return with error if nothing to do.
if (rule_str == NULL || out_cipher_list == NULL) {
return false;
@@ -1179,7 +1180,7 @@
// CHACHA20 unless there is hardware support for fast and constant-time
// AES_GCM. Of the two CHACHA20 variants, the new one is preferred over the
// old one.
- if (EVP_has_aes_hardware()) {
+ if (has_aes_hw) {
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1,
false, &head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1,
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 86e8eb3..c035825 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -484,6 +484,17 @@
return true;
}
+void SSL_CTX_set_aes_hw_override_for_testing(SSL_CTX *ctx,
+ bool override_value) {
+ ctx->aes_hw_override = true;
+ ctx->aes_hw_override_value = override_value;
+}
+
+void SSL_set_aes_hw_override_for_testing(SSL *ssl, bool override_value) {
+ ssl->config->aes_hw_override = true;
+ ssl->config->aes_hw_override_value = override_value;
+}
+
BSSL_NAMESPACE_END
using namespace bssl;
@@ -525,7 +536,9 @@
false_start_allowed_without_alpn(false),
handoff(false),
enable_early_data(false),
- only_fips_cipher_suites_in_tls13(false) {
+ only_fips_cipher_suites_in_tls13(false),
+ aes_hw_override(false),
+ aes_hw_override_value(false) {
CRYPTO_MUTEX_init(&lock);
CRYPTO_new_ex_data(&ex_data);
}
@@ -647,6 +660,8 @@
ssl->config->permute_extensions = ctx->permute_extensions;
ssl->config->only_fips_cipher_suites_in_tls13 =
ctx->only_fips_cipher_suites_in_tls13;
+ ssl->config->aes_hw_override = ctx->aes_hw_override;
+ ssl->config->aes_hw_override_value = ctx->aes_hw_override_value;
if (!ssl->config->supported_group_list.CopyFrom(ctx->supported_group_list) ||
!ssl->config->alpn_client_proto_list.CopyFrom(
@@ -2026,18 +2041,27 @@
}
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) {
- return ssl_create_cipher_list(&ctx->cipher_list, str, false /* not strict */);
+ const bool has_aes_hw = ctx->aes_hw_override ? ctx->aes_hw_override_value
+ : EVP_has_aes_hardware();
+ return ssl_create_cipher_list(&ctx->cipher_list, has_aes_hw, str,
+ false /* not strict */);
}
int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx, const char *str) {
- return ssl_create_cipher_list(&ctx->cipher_list, str, true /* strict */);
+ const bool has_aes_hw = ctx->aes_hw_override ? ctx->aes_hw_override_value
+ : EVP_has_aes_hardware();
+ return ssl_create_cipher_list(&ctx->cipher_list, has_aes_hw, str,
+ true /* strict */);
}
int SSL_set_cipher_list(SSL *ssl, const char *str) {
if (!ssl->config) {
return 0;
}
- return ssl_create_cipher_list(&ssl->config->cipher_list, str,
+ const bool has_aes_hw = ssl->config->aes_hw_override
+ ? ssl->config->aes_hw_override_value
+ : EVP_has_aes_hardware();
+ return ssl_create_cipher_list(&ssl->config->cipher_list, has_aes_hw, str,
false /* not strict */);
}
@@ -2045,7 +2069,10 @@
if (!ssl->config) {
return 0;
}
- return ssl_create_cipher_list(&ssl->config->cipher_list, str,
+ const bool has_aes_hw = ssl->config->aes_hw_override
+ ? ssl->config->aes_hw_override_value
+ : EVP_has_aes_hardware();
+ return ssl_create_cipher_list(&ssl->config->cipher_list, has_aes_hw, str,
true /* strict */);
}
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 684c254..c64bb16 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -583,16 +583,14 @@
}
uint16_t cipher_id = SSL_CIPHER_get_protocol_id(SSL_get_current_cipher(ssl));
- if (config->expect_cipher_aes != 0 &&
- EVP_has_aes_hardware() &&
+ if (config->expect_cipher_aes != 0 && EVP_has_aes_hardware() &&
config->expect_cipher_aes != cipher_id) {
fprintf(stderr, "Cipher ID was %04x, wanted %04x (has AES hardware)\n",
cipher_id, config->expect_cipher_aes);
return false;
}
- if (config->expect_cipher_no_aes != 0 &&
- !EVP_has_aes_hardware() &&
+ if (config->expect_cipher_no_aes != 0 && !EVP_has_aes_hardware() &&
config->expect_cipher_no_aes != cipher_id) {
fprintf(stderr, "Cipher ID was %04x, wanted %04x (no AES hardware)\n",
cipher_id, config->expect_cipher_no_aes);
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index 0bbe97f..c97e3f5 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -116,8 +116,11 @@
const uint16_t version = ssl_protocol_version(ssl);
- return ssl_choose_tls13_cipher(cipher_suites, version, group_id,
- ssl->config->only_fips_cipher_suites_in_tls13);
+ return ssl_choose_tls13_cipher(
+ cipher_suites,
+ ssl->config->aes_hw_override ? ssl->config->aes_hw_override_value
+ : EVP_has_aes_hardware(),
+ version, group_id, ssl->config->only_fips_cipher_suites_in_tls13);
}
static bool add_new_session_tickets(SSL_HANDSHAKE *hs, bool *out_sent_tickets) {