Simplify SSLAEADContext::Create slightly
The AEAD and non-AEAD cases got a bit jumbled together.
Change-Id: I38044af403673ff16a79414f5a3660afed357ad6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/71747
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/ssl/ssl_aead_ctx.cc b/ssl/ssl_aead_ctx.cc
index 9a4da85..4f25d43 100644
--- a/ssl/ssl_aead_ctx.cc
+++ b/ssl/ssl_aead_ctx.cc
@@ -68,26 +68,60 @@
return nullptr;
}
+ UniquePtr<SSLAEADContext> aead_ctx = MakeUnique<SSLAEADContext>(cipher);
+ if (!aead_ctx) {
+ return nullptr;
+ }
+
uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];
- if (!mac_key.empty()) {
- // This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
- // suites).
- if (mac_key.size() + enc_key.size() + fixed_iv.size() >
- sizeof(merged_key)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return nullptr;
+ assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH);
+ static_assert(EVP_AEAD_MAX_NONCE_LENGTH < 256,
+ "variable_nonce_len doesn't fit in uint8_t");
+ aead_ctx->variable_nonce_len_ = (uint8_t)EVP_AEAD_nonce_length(aead);
+ if (mac_key.empty()) {
+ // This is an actual AEAD.
+ assert(fixed_iv.size() <= sizeof(aead_ctx->fixed_nonce_));
+ OPENSSL_memcpy(aead_ctx->fixed_nonce_, fixed_iv.data(), fixed_iv.size());
+ aead_ctx->fixed_nonce_len_ = fixed_iv.size();
+
+ if (protocol_version >= TLS1_3_VERSION ||
+ cipher->algorithm_enc & SSL_CHACHA20POLY1305) {
+ // TLS 1.3, and TLS 1.2 ChaCha20-Poly1305, XOR the fixed IV with the
+ // sequence number to form the nonce.
+ aead_ctx->xor_fixed_nonce_ = true;
+ aead_ctx->variable_nonce_len_ = 8;
+ assert(fixed_iv.size() >= aead_ctx->variable_nonce_len_);
+ } else {
+ // TLS 1.2 AES-GCM prepends the fixed IV to an explicit nonce.
+ assert(fixed_iv.size() <= aead_ctx->variable_nonce_len_);
+ assert(cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM));
+ aead_ctx->variable_nonce_len_ -= fixed_iv.size();
+ aead_ctx->variable_nonce_included_in_record_ = true;
}
+
+ // Starting TLS 1.3, the AAD is the whole record header.
+ if (protocol_version >= TLS1_3_VERSION) {
+ aead_ctx->ad_is_header_ = true;
+ }
+ } else {
+ // This is a CBC cipher suite that implements the |EVP_AEAD| interface. The
+ // |EVP_AEAD| takes the MAC key, encryption key, and fixed IV concatenated
+ // as its input key.
+ assert(protocol_version < TLS1_3_VERSION);
+ BSSL_CHECK(mac_key.size() + enc_key.size() + fixed_iv.size() <=
+ sizeof(merged_key));
OPENSSL_memcpy(merged_key, mac_key.data(), mac_key.size());
OPENSSL_memcpy(merged_key + mac_key.size(), enc_key.data(), enc_key.size());
OPENSSL_memcpy(merged_key + mac_key.size() + enc_key.size(),
fixed_iv.data(), fixed_iv.size());
enc_key = MakeConstSpan(merged_key,
enc_key.size() + mac_key.size() + fixed_iv.size());
- }
- UniquePtr<SSLAEADContext> aead_ctx = MakeUnique<SSLAEADContext>(cipher);
- if (!aead_ctx) {
- return nullptr;
+ // The |EVP_AEAD|'s per-encryption nonce, if any, is actually the CBC IV. It
+ // must be generated randomly and prepended to the record.
+ aead_ctx->variable_nonce_included_in_record_ = true;
+ aead_ctx->random_variable_nonce_ = true;
+ aead_ctx->omit_length_in_ad_ = true;
}
if (!EVP_AEAD_CTX_init_with_direction(
@@ -96,46 +130,6 @@
return nullptr;
}
- assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH);
- static_assert(EVP_AEAD_MAX_NONCE_LENGTH < 256,
- "variable_nonce_len doesn't fit in uint8_t");
- aead_ctx->variable_nonce_len_ = (uint8_t)EVP_AEAD_nonce_length(aead);
- if (mac_key.empty()) {
- assert(fixed_iv.size() <= sizeof(aead_ctx->fixed_nonce_));
- OPENSSL_memcpy(aead_ctx->fixed_nonce_, fixed_iv.data(), fixed_iv.size());
- aead_ctx->fixed_nonce_len_ = fixed_iv.size();
-
- if (cipher->algorithm_enc & SSL_CHACHA20POLY1305) {
- // The fixed nonce into the actual nonce (the sequence number).
- aead_ctx->xor_fixed_nonce_ = true;
- aead_ctx->variable_nonce_len_ = 8;
- } else {
- // The fixed IV is prepended to the nonce.
- assert(fixed_iv.size() <= aead_ctx->variable_nonce_len_);
- aead_ctx->variable_nonce_len_ -= fixed_iv.size();
- }
-
- // AES-GCM uses an explicit nonce.
- if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) {
- aead_ctx->variable_nonce_included_in_record_ = true;
- }
-
- // The TLS 1.3 construction XORs the fixed nonce into the sequence number
- // and omits the additional data.
- if (protocol_version >= TLS1_3_VERSION) {
- aead_ctx->xor_fixed_nonce_ = true;
- aead_ctx->variable_nonce_len_ = 8;
- aead_ctx->variable_nonce_included_in_record_ = false;
- aead_ctx->ad_is_header_ = true;
- assert(fixed_iv.size() >= aead_ctx->variable_nonce_len_);
- }
- } else {
- assert(protocol_version < TLS1_3_VERSION);
- aead_ctx->variable_nonce_included_in_record_ = true;
- aead_ctx->random_variable_nonce_ = true;
- aead_ctx->omit_length_in_ad_ = true;
- }
-
return aead_ctx;
}