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>
fips-20230428
Bob Beck 2 years ago committed by Boringssl LUCI CQ
parent 94235101d2
commit 8cacbd93b8
  1. 12
      include/openssl/ssl.h
  2. 17
      ssl/encrypted_client_hello.cc
  3. 8
      ssl/handshake_client.cc
  4. 33
      ssl/internal.h
  5. 9
      ssl/s3_both.cc
  6. 5
      ssl/ssl_cipher.cc
  7. 37
      ssl/ssl_lib.cc
  8. 6
      ssl/test/bssl_shim.cc
  9. 7
      ssl/tls13_server.cc

@ -5413,6 +5413,18 @@ OPENSSL_EXPORT bool SSL_get_traffic_secrets(
const SSL *ssl, Span<const uint8_t> *out_read_traffic_secret, const SSL *ssl, Span<const uint8_t> *out_read_traffic_secret,
Span<const uint8_t> *out_write_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 BSSL_NAMESPACE_END

@ -601,8 +601,8 @@ bool ssl_is_valid_ech_config_list(Span<const uint8_t> ech_config_list) {
static bool select_ech_cipher_suite(const EVP_HPKE_KDF **out_kdf, static bool select_ech_cipher_suite(const EVP_HPKE_KDF **out_kdf,
const EVP_HPKE_AEAD **out_aead, const EVP_HPKE_AEAD **out_aead,
Span<const uint8_t> cipher_suites) { Span<const uint8_t> cipher_suites,
const bool has_aes_hardware = EVP_has_aes_hardware(); const bool has_aes_hardware) {
const EVP_HPKE_AEAD *aead = nullptr; const EVP_HPKE_AEAD *aead = nullptr;
CBS cbs = cipher_suites; CBS cbs = cipher_suites;
while (CBS_len(&cbs) != 0) { while (CBS_len(&cbs) != 0) {
@ -660,7 +660,10 @@ bool ssl_select_ech_config(SSL_HANDSHAKE *hs, Span<uint8_t> out_enc,
const EVP_HPKE_AEAD *aead; const EVP_HPKE_AEAD *aead;
if (supported && // if (supported && //
ech_config.kem_id == EVP_HPKE_DHKEM_X25519_HKDF_SHA256 && 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; ScopedCBB info;
static const uint8_t kInfoLabel[] = "tls ech"; // includes trailing NUL static const uint8_t kInfoLabel[] = "tls ech"; // includes trailing NUL
if (!CBB_init(info.get(), sizeof(kInfoLabel) + ech_config.raw.size()) || if (!CBB_init(info.get(), sizeof(kInfoLabel) + ech_config.raw.size()) ||
@ -714,9 +717,11 @@ static bool setup_ech_grease(SSL_HANDSHAKE *hs) {
} }
const uint16_t kdf_id = EVP_HPKE_HKDF_SHA256; const uint16_t kdf_id = EVP_HPKE_HKDF_SHA256;
const EVP_HPKE_AEAD *aead = EVP_has_aes_hardware() const bool has_aes_hw = hs->ssl->config->aes_hw_override
? EVP_hpke_aes_128_gcm() ? hs->ssl->config->aes_hw_override_value
: EVP_hpke_chacha20_poly1305(); : 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), static_assert(ssl_grease_ech_config_id < sizeof(hs->grease_seed),
"hs->grease_seed is too small"); "hs->grease_seed is too small");
uint8_t config_id = hs->grease_seed[ssl_grease_ech_config_id]; uint8_t config_id = hs->grease_seed[ssl_grease_ech_config_id];

@ -239,7 +239,11 @@ static bool ssl_write_client_cipher_list(const SSL_HANDSHAKE *hs, CBB *out,
TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff,
ssl->config->only_fips_cipher_suites_in_tls13); ssl->config->only_fips_cipher_suites_in_tls13);
if (!EVP_has_aes_hardware() && // 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 && // include_chacha20 && //
!CBB_add_u16(&child, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) { !CBB_add_u16(&child, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
return false; return false;
@ -248,7 +252,7 @@ static bool ssl_write_client_cipher_list(const SSL_HANDSHAKE *hs, CBB *out,
!CBB_add_u16(&child, TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff)) { !CBB_add_u16(&child, TLS1_3_CK_AES_256_GCM_SHA384 & 0xffff)) {
return false; return false;
} }
if (EVP_has_aes_hardware() && // if (has_aes_hw && //
include_chacha20 && // include_chacha20 && //
!CBB_add_u16(&child, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) { !CBB_add_u16(&child, TLS1_3_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
return false; return false;

@ -633,9 +633,11 @@ const EVP_MD *ssl_get_handshake_digest(uint16_t version,
// newly-allocated |SSLCipherPreferenceList| containing the result. It returns // newly-allocated |SSLCipherPreferenceList| containing the result. It returns
// true on success and false on failure. If |strict| is true, nonsense will be // 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 // 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, 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| // 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. // values suitable for use with |key| in TLS 1.2 and below.
@ -659,9 +661,12 @@ size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher);
// ssl_choose_tls13_cipher returns an |SSL_CIPHER| corresponding with the best // ssl_choose_tls13_cipher returns an |SSL_CIPHER| corresponding with the best
// available from |cipher_suites| compatible with |version|, |group_id|, and // available from |cipher_suites| compatible with |version|, |group_id|, and
// |only_fips|. It returns NULL if there isn't a compatible cipher. // |only_fips|. It returns NULL if there isn't a compatible cipher. |has_aes_hw|
const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, uint16_t version, // indicates if the choice should be made as if support for AES in hardware
uint16_t group_id, bool only_fips); // 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 // 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 // |only_fips|. (For now there's only a single policy and so the policy argument
@ -3111,6 +3116,15 @@ struct SSL_CONFIG {
// only_fips_cipher_suites_in_tls13 constrains the selection of cipher suites // 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. // in TLS 1.3 such that only FIPS approved ones will be selected.
bool only_fips_cipher_suites_in_tls13 : 1; 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. // From RFC 8446, used in determining PSK modes.
@ -3722,6 +3736,15 @@ struct ssl_ctx_st {
// in TLS 1.3 such that only FIPS approved ones will be selected. // in TLS 1.3 such that only FIPS approved ones will be selected.
bool only_fips_cipher_suites_in_tls13 : 1; 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: 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 *);

@ -663,7 +663,7 @@ void tls_next_message(SSL *ssl) {
// the client. // the client.
class CipherScorer { class CipherScorer {
public: 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; typedef std::tuple<bool, bool> Score;
@ -702,14 +702,15 @@ bool ssl_tls13_cipher_meets_policy(uint16_t cipher_id, bool only_fips) {
} }
} }
const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, uint16_t version, const SSL_CIPHER *ssl_choose_tls13_cipher(CBS cipher_suites, bool has_aes_hw,
uint16_t group_id, bool only_fips) { uint16_t version, uint16_t group_id,
bool only_fips) {
if (CBS_len(&cipher_suites) % 2 != 0) { if (CBS_len(&cipher_suites) % 2 != 0) {
return nullptr; return nullptr;
} }
const SSL_CIPHER *best = nullptr; const SSL_CIPHER *best = nullptr;
CipherScorer scorer; CipherScorer scorer(has_aes_hw);
CipherScorer::Score best_score = scorer.MinScore(); CipherScorer::Score best_score = scorer.MinScore();
while (CBS_len(&cipher_suites) > 0) { while (CBS_len(&cipher_suites) > 0) {

@ -1148,7 +1148,8 @@ static bool ssl_cipher_process_rulestr(const char *rule_str,
} }
bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list, 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. // Return with error if nothing to do.
if (rule_str == NULL || out_cipher_list == NULL) { if (rule_str == NULL || out_cipher_list == NULL) {
return false; return false;
@ -1179,7 +1180,7 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
// CHACHA20 unless there is hardware support for fast and constant-time // 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 // AES_GCM. Of the two CHACHA20 variants, the new one is preferred over the
// old one. // 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, ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1,
false, &head, &tail); false, &head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1,

@ -484,6 +484,17 @@ bool SSL_get_traffic_secrets(const SSL *ssl,
return true; 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 BSSL_NAMESPACE_END
using namespace bssl; using namespace bssl;
@ -525,7 +536,9 @@ ssl_ctx_st::ssl_ctx_st(const SSL_METHOD *ssl_method)
false_start_allowed_without_alpn(false), false_start_allowed_without_alpn(false),
handoff(false), handoff(false),
enable_early_data(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_MUTEX_init(&lock);
CRYPTO_new_ex_data(&ex_data); CRYPTO_new_ex_data(&ex_data);
} }
@ -647,6 +660,8 @@ SSL *SSL_new(SSL_CTX *ctx) {
ssl->config->permute_extensions = ctx->permute_extensions; ssl->config->permute_extensions = ctx->permute_extensions;
ssl->config->only_fips_cipher_suites_in_tls13 = ssl->config->only_fips_cipher_suites_in_tls13 =
ctx->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) || 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(
@ -2026,18 +2041,27 @@ const char *SSL_get_cipher_list(const SSL *ssl, int n) {
} }
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { 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) { 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) { int SSL_set_cipher_list(SSL *ssl, const char *str) {
if (!ssl->config) { if (!ssl->config) {
return 0; 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 */); false /* not strict */);
} }
@ -2045,7 +2069,10 @@ int SSL_set_strict_cipher_list(SSL *ssl, const char *str) {
if (!ssl->config) { if (!ssl->config) {
return 0; 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 */); true /* strict */);
} }

@ -583,16 +583,14 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
} }
uint16_t cipher_id = SSL_CIPHER_get_protocol_id(SSL_get_current_cipher(ssl)); uint16_t cipher_id = SSL_CIPHER_get_protocol_id(SSL_get_current_cipher(ssl));
if (config->expect_cipher_aes != 0 && if (config->expect_cipher_aes != 0 && EVP_has_aes_hardware() &&
EVP_has_aes_hardware() &&
config->expect_cipher_aes != cipher_id) { config->expect_cipher_aes != cipher_id) {
fprintf(stderr, "Cipher ID was %04x, wanted %04x (has AES hardware)\n", fprintf(stderr, "Cipher ID was %04x, wanted %04x (has AES hardware)\n",
cipher_id, config->expect_cipher_aes); cipher_id, config->expect_cipher_aes);
return false; return false;
} }
if (config->expect_cipher_no_aes != 0 && if (config->expect_cipher_no_aes != 0 && !EVP_has_aes_hardware() &&
!EVP_has_aes_hardware() &&
config->expect_cipher_no_aes != cipher_id) { config->expect_cipher_no_aes != cipher_id) {
fprintf(stderr, "Cipher ID was %04x, wanted %04x (no AES hardware)\n", fprintf(stderr, "Cipher ID was %04x, wanted %04x (no AES hardware)\n",
cipher_id, config->expect_cipher_no_aes); cipher_id, config->expect_cipher_no_aes);

@ -116,8 +116,11 @@ static const SSL_CIPHER *choose_tls13_cipher(
const uint16_t version = ssl_protocol_version(ssl); const uint16_t version = ssl_protocol_version(ssl);
return ssl_choose_tls13_cipher(cipher_suites, version, group_id, return ssl_choose_tls13_cipher(
ssl->config->only_fips_cipher_suites_in_tls13); 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) { static bool add_new_session_tickets(SSL_HANDSHAKE *hs, bool *out_sent_tickets) {

Loading…
Cancel
Save