Reslice TLS AEAD setup.

This change reslices how the functions that generate the key block and
initialise the TLS AEADs are cut. This makes future changes easier.

Change-Id: I7e0f7327375301bed96f33c195b80156db83ce6d
Reviewed-on: https://boringssl-review.googlesource.com/24845
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/t1_enc.cc b/ssl/t1_enc.cc
index 7f4f10b..d1fb710 100644
--- a/ssl/t1_enc.cc
+++ b/ssl/t1_enc.cc
@@ -239,42 +239,26 @@
   return true;
 }
 
-static bool setup_key_block(SSL_HANDSHAKE *hs) {
-  SSL *const ssl = hs->ssl;
-  if (!hs->key_block.empty()) {
-    return true;
-  }
-
-  size_t mac_secret_len, key_len, fixed_iv_len;
-  Array<uint8_t> key_block;
-  if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &fixed_iv_len,
-                             hs->new_cipher) ||
-      !key_block.Init(2 * (mac_secret_len + key_len + fixed_iv_len)) ||
-      !SSL_generate_key_block(ssl, key_block.data(), key_block.size())) {
-    return false;
-  }
-
-  hs->key_block = std::move(key_block);
-  return true;
-}
-
-int tls1_change_cipher_state(SSL_HANDSHAKE *hs,
-                             evp_aead_direction_t direction) {
-  SSL *const ssl = hs->ssl;
-  // Ensure the key block is set up.
+static int tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction,
+                               Array<uint8_t> *key_block_cache,
+                               const SSL_CIPHER *cipher,
+                               Span<const uint8_t> iv_override) {
   size_t mac_secret_len, key_len, iv_len;
-  if (!setup_key_block(hs) ||
-      !get_key_block_lengths(ssl, &mac_secret_len, &key_len, &iv_len,
-                             hs->new_cipher)) {
+  if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &iv_len, cipher)) {
     return 0;
   }
 
-  if ((mac_secret_len + key_len + iv_len) * 2 != hs->key_block.size()) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
+  // Ensure that |key_block_cache| is set up.
+  const size_t key_block_size = 2 * (mac_secret_len + key_len + iv_len);
+  if (key_block_cache->empty()) {
+    if (!key_block_cache->Init(key_block_size) ||
+        !SSL_generate_key_block(ssl, key_block_cache->data(), key_block_size)) {
+      return 0;
+    }
   }
+  assert(key_block_cache->size() == key_block_size);
 
-  Span<const uint8_t> key_block = hs->key_block;
+  Span<const uint8_t> key_block = *key_block_cache;
   Span<const uint8_t> mac_secret, key, iv;
   if (direction == (ssl->server ? evp_aead_open : evp_aead_seal)) {
     // Use the client write (server read) keys.
@@ -288,9 +272,15 @@
     iv = key_block.subspan(2 * mac_secret_len + 2 * key_len + iv_len, iv_len);
   }
 
-  UniquePtr<SSLAEADContext> aead_ctx =
-      SSLAEADContext::Create(direction, ssl->version, SSL_is_dtls(ssl),
-                             hs->new_cipher, key, mac_secret, iv);
+  if (!iv_override.empty()) {
+    if (iv_override.size() != iv_len) {
+      return 0;
+    }
+    iv = iv_override;
+  }
+
+  UniquePtr<SSLAEADContext> aead_ctx = SSLAEADContext::Create(
+      direction, ssl->version, SSL_is_dtls(ssl), cipher, key, mac_secret, iv);
   if (!aead_ctx) {
     return 0;
   }
@@ -302,6 +292,12 @@
   return ssl->method->set_write_state(ssl, std::move(aead_ctx));
 }
 
+int tls1_change_cipher_state(SSL_HANDSHAKE *hs,
+                             evp_aead_direction_t direction) {
+  return tls1_configure_aead(hs->ssl, direction, &hs->key_block,
+                             hs->new_cipher, {});
+}
+
 int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
                                 Span<const uint8_t> premaster) {
   static const char kMasterSecretLabel[] = "master secret";