Implement all TLS ciphers with stateful AEADs.

The EVP_CIPHER codepath should no longer be used with TLS. It still exists for
DTLS and SSLv3. The AEAD construction in TLS does not allow for
variable-overhead AEADs, so stateful AEADs do not include the length in the ad
parameter. Rather the AEADs internally append the unpadded length once it is
known. EVP_aead_rc4_md5_tls is modified to account for this.

Tests are added (and RC4-MD5's regenerated) for each of the new AEADs. The
cipher tests are all moved into crypto/cipher/test because there's now a lot of
them and they clutter the directory listing.

In ssl/, the stateful AEAD logic is also modified to account for stateful AEADs
with a fixed IV component, and for AEADs which use a random nonce (for the
explicit-IV CBC mode ciphers).

The new implementation fixes a bug/quirk in stateless CBC mode ciphers where
the fixed IV portion of the keyblock was generated regardless. This is at the
end, so it's only relevant for EAP-TLS which generates a MSK from the end of
the key block.

Change-Id: I2d8b8aa11deb43bde2fd733f4f90b5d5b8cb1334
Reviewed-on: https://boringssl-review.googlesource.com/2692
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index e4c2a2b..5869cdf 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -267,8 +267,7 @@
       return NULL;
     }
     /* TODO(davidben): EVP_AEAD does not work in DTLS yet. */
-    if (ciph->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD ||
-        ciph->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) {
+    if (ciph->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) {
       return NULL;
     }
   }
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index ef4e024..913f84b 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -160,11 +160,6 @@
 
 #define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers) / sizeof(SSL_CIPHER))
 
-/* FIXED_NONCE_LEN is a macro that results in the correct value to set the
- * fixed nonce length in SSL_CIPHER.algorithms2. It's the inverse of
- * SSL_CIPHER_AEAD_FIXED_NONCE_LEN. */
-#define FIXED_NONCE_LEN(x) ((x / 2) << 24)
-
 /* list of available SSLv3 ciphers (sorted by id) */
 const SSL_CIPHER ssl3_ciphers[] = {
     /* The RSA ciphers */
@@ -172,8 +167,7 @@
     {
      1, SSL3_TXT_RSA_RC4_128_MD5, SSL3_CK_RSA_RC4_128_MD5, SSL_kRSA, SSL_aRSA,
      SSL_RC4, SSL_MD5, SSL_SSLV3, SSL_MEDIUM,
-     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF | SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD,
-     128, 128,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF, 128, 128,
     },
 
     /* Cipher 05 */
@@ -322,7 +316,6 @@
      TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, SSL_kRSA, SSL_aRSA, SSL_AES128GCM,
      SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      128, 128,
     },
@@ -333,7 +326,6 @@
      TLS1_CK_RSA_WITH_AES_256_GCM_SHA384, SSL_kRSA, SSL_aRSA, SSL_AES256GCM,
      SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      256, 256,
     },
@@ -344,7 +336,6 @@
      TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kEDH, SSL_aRSA, SSL_AES128GCM,
      SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      128, 128,
     },
@@ -355,7 +346,6 @@
      TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384, SSL_kEDH, SSL_aRSA, SSL_AES256GCM,
      SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      256, 256,
     },
@@ -366,7 +356,6 @@
      TLS1_CK_ADH_WITH_AES_128_GCM_SHA256, SSL_kEDH, SSL_aNULL, SSL_AES128GCM,
      SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      128, 128,
     },
@@ -377,7 +366,6 @@
      TLS1_CK_ADH_WITH_AES_256_GCM_SHA384, SSL_kEDH, SSL_aNULL, SSL_AES256GCM,
      SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      256, 256,
     },
@@ -496,7 +484,6 @@
      TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_kEECDH, SSL_aECDSA,
      SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      128, 128,
     },
@@ -507,7 +494,6 @@
      TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, SSL_kEECDH, SSL_aECDSA,
      SSL_AES256GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      256, 256,
     },
@@ -518,7 +504,6 @@
      TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_kEECDH, SSL_aRSA,
      SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      128, 128,
     },
@@ -529,7 +514,6 @@
      TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, SSL_kEECDH, SSL_aRSA,
      SSL_AES256GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      256, 256,
     },
@@ -543,7 +527,6 @@
      TLS1_CK_ECDHE_PSK_WITH_AES_128_GCM_SHA256, SSL_kEECDH, SSL_aPSK,
      SSL_AES128GCM, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
      SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(4) |
          SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
      128, 128,
     },
@@ -552,8 +535,7 @@
      1, TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
      TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, SSL_kEECDH, SSL_aRSA,
      SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
-     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(0),
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD,
      256, 0,
     },
 
@@ -561,8 +543,7 @@
      1, TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
      TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, SSL_kEECDH, SSL_aECDSA,
      SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
-     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(0),
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD,
      256, 0,
     },
 
@@ -570,8 +551,7 @@
      1, TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
      TLS1_CK_DHE_RSA_CHACHA20_POLY1305, SSL_kEDH, SSL_aRSA,
      SSL_CHACHA20POLY1305, SSL_AEAD, SSL_TLSV1_2, SSL_HIGH,
-     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD |
-         FIXED_NONCE_LEN(0),
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256 | SSL_CIPHER_ALGORITHM2_AEAD,
      256, 0,
     },
 };
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index fb8c047..d5f9c68 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -142,8 +142,10 @@
 #include <assert.h>
 
 #include <openssl/engine.h>
+#include <openssl/md5.h>
 #include <openssl/mem.h>
 #include <openssl/obj.h>
+#include <openssl/sha.h>
 
 #include "ssl_locl.h"
 
@@ -241,49 +243,109 @@
      {0, SSL_TXT_FIPS, 0, 0, 0, 0, 0, 0, SSL_FIPS, 0, 0, 0},
 };
 
-/* ssl_cipher_get_evp_aead sets |*aead| to point to the correct EVP_AEAD object
- * for |s->cipher|. It returns 1 on success and 0 on error. */
-int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead) {
-  const SSL_CIPHER *c = s->cipher;
+int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
+                            size_t *out_mac_secret_len,
+                            size_t *out_fixed_iv_len,
+                            const SSL_CIPHER *cipher, uint16_t version) {
+  *out_aead = NULL;
+  *out_mac_secret_len = 0;
+  *out_fixed_iv_len = 0;
 
-  *aead = NULL;
-
-  if (c == NULL) {
-    return 0;
-  }
-
-  if ((c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) == 0 &&
-      (c->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) == 0) {
-    return 0;
-  }
-
-  switch (c->algorithm_enc) {
+  switch (cipher->algorithm_enc) {
     case SSL_AES128GCM:
-      *aead = EVP_aead_aes_128_gcm();
+      *out_aead = EVP_aead_aes_128_gcm();
+      *out_fixed_iv_len = 4;
       return 1;
 
     case SSL_AES256GCM:
-      *aead = EVP_aead_aes_256_gcm();
+      *out_aead = EVP_aead_aes_256_gcm();
+      *out_fixed_iv_len = 4;
       return 1;
 
     case SSL_CHACHA20POLY1305:
-      *aead = EVP_aead_chacha20_poly1305();
+      *out_aead = EVP_aead_chacha20_poly1305();
+      *out_fixed_iv_len = 0;
       return 1;
 
     case SSL_RC4:
-      if (c->algorithm_mac != SSL_MD5) {
-        return 0;
+      switch (cipher->algorithm_mac) {
+        case SSL_MD5:
+          *out_aead = EVP_aead_rc4_md5_tls();
+          *out_mac_secret_len = MD5_DIGEST_LENGTH;
+          return 1;
+        case SSL_SHA1:
+          *out_aead = EVP_aead_rc4_sha1_tls();
+          *out_mac_secret_len = SHA_DIGEST_LENGTH;
+          return 1;
+        default:
+          return 0;
       }
-      *aead = EVP_aead_rc4_md5_tls();
-      return 1;
-  }
 
-  return 0;
+    case SSL_AES128:
+      switch (cipher->algorithm_mac) {
+        case SSL_SHA1:
+          if (version <= TLS1_VERSION) {
+            *out_aead = EVP_aead_aes_128_cbc_sha1_tls_implicit_iv();
+            *out_fixed_iv_len = 16;
+          } else {
+            *out_aead = EVP_aead_aes_128_cbc_sha1_tls();
+          }
+          *out_mac_secret_len = SHA_DIGEST_LENGTH;
+          return 1;
+        case SSL_SHA256:
+          *out_aead = EVP_aead_aes_128_cbc_sha256_tls();
+          *out_mac_secret_len = SHA256_DIGEST_LENGTH;
+          return 1;
+        default:
+          return 0;
+      }
+
+    case SSL_AES256:
+      switch (cipher->algorithm_mac) {
+        case SSL_SHA1:
+          if (version <= TLS1_VERSION) {
+            *out_aead = EVP_aead_aes_256_cbc_sha1_tls_implicit_iv();
+            *out_fixed_iv_len = 16;
+          } else {
+            *out_aead = EVP_aead_aes_256_cbc_sha1_tls();
+          }
+          *out_mac_secret_len = SHA_DIGEST_LENGTH;
+          return 1;
+        case SSL_SHA256:
+          *out_aead = EVP_aead_aes_256_cbc_sha256_tls();
+          *out_mac_secret_len = SHA256_DIGEST_LENGTH;
+          return 1;
+        case SSL_SHA384:
+          *out_aead = EVP_aead_aes_256_cbc_sha384_tls();
+          *out_mac_secret_len = SHA384_DIGEST_LENGTH;
+          return 1;
+        default:
+          return 0;
+      }
+
+    case SSL_3DES:
+      switch (cipher->algorithm_mac) {
+        case SSL_SHA1:
+          if (version <= TLS1_VERSION) {
+            *out_aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv();
+            *out_fixed_iv_len = 8;
+          } else {
+            *out_aead = EVP_aead_des_ede3_cbc_sha1_tls();
+          }
+          *out_mac_secret_len = SHA_DIGEST_LENGTH;
+          return 1;
+        default:
+          return 0;
+      }
+
+    default:
+      return 0;
+  }
 }
 
 int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
                        const EVP_MD **md, int *mac_pkey_type,
-                       int *mac_secret_size) {
+                       size_t *mac_secret_size) {
   const SSL_CIPHER *c;
 
   c = s->cipher;
@@ -347,7 +409,7 @@
 }
 
 int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md,
-                       int *mac_pkey_type, int *mac_secret_size) {
+                       int *mac_pkey_type, size_t *mac_secret_size) {
   const SSL_CIPHER *c;
 
   c = s->cipher;
diff --git a/ssl/ssl_error.c b/ssl/ssl_error.c
index 2f06460..a0a5ac7 100644
--- a/ssl/ssl_error.c
+++ b/ssl/ssl_error.c
@@ -207,6 +207,7 @@
   {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_change_cipher_state_aead, 0), "tls1_change_cipher_state_aead"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_change_cipher_state_cipher, 0), "tls1_change_cipher_state_cipher"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_check_duplicate_extensions, 0), "tls1_check_duplicate_extensions"},
+  {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_enc, 0), "tls1_enc"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_export_keying_material, 0), "tls1_export_keying_material"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_get_server_supplemental_data, 0), "tls1_get_server_supplemental_data"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_tls1_heartbeat, 0), "tls1_heartbeat"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 0118aa5..9e5af76 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3165,6 +3165,27 @@
   }
 }
 
+uint16_t ssl3_version_from_wire(SSL *s, uint16_t wire_version) {
+  if (!SSL_IS_DTLS(s)) {
+    return wire_version;
+  }
+
+  uint16_t tls_version = ~wire_version;
+  uint16_t version = tls_version + 0x0201;
+  /* If either component overflowed, clamp it so comparisons still work. */
+  if ((version >> 8) < (tls_version >> 8)) {
+    version = 0xff00 | (version & 0xff);
+  }
+  if ((version & 0xff) < (tls_version & 0xff)) {
+    version = (version & 0xff00) | 0xff;
+  }
+  /* DTLS 1.0 maps to TLS 1.1, not TLS 1.0. */
+  if (version == TLS1_VERSION) {
+    version = TLS1_1_VERSION;
+  }
+  return version;
+}
+
 /* Allocates new EVP_MD_CTX and sets pointer to it into given pointer vairable,
  * freeing  EVP_MD_CTX previously stored in that variable, if any. If EVP_MD
  * pointer is passed, initializes ctx with this md Returns newly allocated
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 0364097..4cb95ca 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -363,22 +363,12 @@
  * indicates that the cipher is implemented via an EVP_AEAD. */
 #define SSL_CIPHER_ALGORITHM2_AEAD (1 << 23)
 
-/* SSL_CIPHER_AEAD_FIXED_NONCE_LEN returns the number of bytes of fixed nonce
- * for an SSL_CIPHER* with the SSL_CIPHER_ALGORITHM2_AEAD flag. */
-#define SSL_CIPHER_AEAD_FIXED_NONCE_LEN(ssl_cipher) \
-  (((ssl_cipher->algorithm2 >> 24) & 0xf) * 2)
-
 /* SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD is a flag in
  * SSL_CIPHER.algorithm2 which indicates that the variable part of the nonce is
  * included as a prefix of the record. (AES-GCM, for example, does with with an
  * 8-byte variable nonce.) */
 #define SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD (1<<22)
 
-/* SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD is a flag in SSL_CIPHER.algorithm2 which
- * indicates that the AEAD is stateful and so doesn't take an nonce. This is
- * only true of legacy cipher suites. */
-#define SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD (1<<28)
-
 /* Cipher strength information. */
 #define SSL_MEDIUM 0x00000001L
 #define SSL_HIGH 0x00000002L
@@ -643,6 +633,13 @@
   /* variable_nonce_included_in_record is non-zero if the variable nonce
    * for a record is included as a prefix before the ciphertext. */
   char variable_nonce_included_in_record;
+  /* random_variable_nonce is non-zero if the variable nonce is
+   * randomly generated, rather than derived from the sequence
+   * number. */
+  char random_variable_nonce;
+  /* omit_length_in_ad is non-zero if the length should be omitted in the
+   * AEAD's ad parameter. */
+  char omit_length_in_ad;
 };
 
 extern const SSL_CIPHER ssl3_ciphers[];
@@ -681,12 +678,22 @@
 struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_from_ciphers(
     STACK_OF(SSL_CIPHER) * ciphers);
 struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *s);
-int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead);
+
+/* ssl_cipher_get_evp_aead sets |*out_aead| to point to the correct EVP_AEAD
+* object for |cipher| protocol version |version|. It sets |*out_mac_secret_len|
+* and |*out_fixed_iv_len| to the MAC key length and fixed IV length,
+* respectively. The MAC key length is zero except for legacy block and stream
+* ciphers. It returns 1 on success and 0 on error. */
+int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
+                            size_t *out_mac_secret_len,
+                            size_t *out_fixed_iv_len,
+                            const SSL_CIPHER *cipher, uint16_t version);
+
 int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
                        const EVP_MD **md, int *mac_pkey_type,
-                       int *mac_secret_size);
+                       size_t *mac_secret_size);
 int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md,
-                       int *mac_pkey_type, int *mac_secret_size);
+                       int *mac_pkey_type, size_t *mac_secret_size);
 int ssl_get_handshake_digest(int i, long *mask, const EVP_MD **md);
 int ssl_cipher_get_cert_index(const SSL_CIPHER *c);
 int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher);
@@ -999,6 +1006,15 @@
  * version for |s| and zero otherwise. */
 int ssl3_is_version_enabled(SSL *s, uint16_t version);
 
+/* ssl3_version_from_wire maps |wire_version| to a protocol version. For
+ * SSLv3/TLS, the version is returned as-is. For DTLS, the corresponding TLS
+ * version is used. Note that this mapping is not injective but preserves
+ * comparisons.
+ *
+ * TODO(davidben): To normalize some DTLS-specific code, move away from using
+ * the wire version except at API boundaries. */
+uint16_t ssl3_version_from_wire(SSL *s, uint16_t wire_version);
+
 EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
 void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
 int ssl_add_serverhello_renegotiate_ext(SSL *s, uint8_t *p, int *len,
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index dd8ccb0..dac3fca 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -330,10 +330,9 @@
                                          unsigned mac_secret_len) {
   const EVP_AEAD *aead = s->s3->tmp.new_aead;
   SSL_AEAD_CTX *aead_ctx;
-  /* mac_key_and_key is used to merge the MAC and cipher keys for an AEAD which
-   * simulates pre-AEAD cipher suites. It needs to be large enough to cope with
-   * the largest pair of keys. */
-  uint8_t mac_key_and_key[32 /* HMAC(SHA256) */ + 32 /* AES-256 */];
+  /* merged_key is used to merge the MAC, cipher, and IV keys for an AEAD which
+   * simulates pre-AEAD cipher suites. */
+  uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];
 
   if (is_read) {
     tls1_cleanup_enc_ctx(&s->enc_read_ctx);
@@ -346,15 +345,17 @@
   if (mac_secret_len > 0) {
     /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
      * suites). */
-    if (mac_secret_len + key_len > sizeof(mac_key_and_key)) {
+    if (mac_secret_len + key_len + iv_len > sizeof(merged_key)) {
       OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead,
                         ERR_R_INTERNAL_ERROR);
       return 0;
     }
-    memcpy(mac_key_and_key, mac_secret, mac_secret_len);
-    memcpy(mac_key_and_key + mac_secret_len, key, key_len);
-    key = mac_key_and_key;
+    memcpy(merged_key, mac_secret, mac_secret_len);
+    memcpy(merged_key + mac_secret_len, key, key_len);
+    memcpy(merged_key + mac_secret_len + key_len, iv, iv_len);
+    key = merged_key;
     key_len += mac_secret_len;
+    key_len += iv_len;
   }
 
   if (is_read) {
@@ -381,21 +382,28 @@
     return 0;
   }
 
-  if (iv_len > sizeof(aead_ctx->fixed_nonce)) {
-    OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
+  if (mac_secret_len == 0) {
+    /* For a real AEAD, the IV is the fixed part of the nonce. */
+    if (iv_len > sizeof(aead_ctx->fixed_nonce)) {
+      OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
+      return 0;
+    }
 
-  memcpy(aead_ctx->fixed_nonce, iv, iv_len);
-  aead_ctx->fixed_nonce_len = iv_len;
-  aead_ctx->variable_nonce_len = 8; /* correct for all true AEADs so far. */
-  if (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) {
-    aead_ctx->variable_nonce_len = 0;
-  }
-
-  aead_ctx->variable_nonce_included_in_record =
+    memcpy(aead_ctx->fixed_nonce, iv, iv_len);
+    aead_ctx->fixed_nonce_len = iv_len;
+    aead_ctx->variable_nonce_included_in_record =
       (s->s3->tmp.new_cipher->algorithm2 &
        SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0;
+    aead_ctx->random_variable_nonce = 0;
+    aead_ctx->omit_length_in_ad = 0;
+  } else {
+    aead_ctx->fixed_nonce_len = 0;
+    aead_ctx->variable_nonce_included_in_record = 1;
+    aead_ctx->random_variable_nonce = 1;
+    aead_ctx->omit_length_in_ad = 1;
+  }
+  aead_ctx->variable_nonce_len = s->s3->tmp.new_variable_iv_len;
+
   if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len !=
       EVP_AEAD_nonce_length(aead)) {
     OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
@@ -524,7 +532,7 @@
   const uint8_t *client_write_iv, *server_write_iv, *iv;
   const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc;
   const EVP_AEAD *aead = s->s3->tmp.new_aead;
-  unsigned key_len, iv_len, mac_secret_len;
+  size_t key_len, iv_len, mac_secret_len;
   const uint8_t *key_data;
 
   /* Reset sequence number to zero. */
@@ -532,22 +540,23 @@
     memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8);
   }
 
-  mac_secret_len = s->s3->tmp.new_mac_secret_size;
+  mac_secret_len = s->s3->tmp.new_mac_secret_len;
+  iv_len = s->s3->tmp.new_fixed_iv_len;
 
   if (aead != NULL) {
     key_len = EVP_AEAD_key_length(aead);
-    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites)
-     * the key length reported by |EVP_AEAD_key_length| will include the MAC
-     * key bytes. */
-    if (key_len < mac_secret_len) {
-      OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
-      return 0;
+    if (mac_secret_len > 0) {
+      /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites)
+       * the key length reported by |EVP_AEAD_key_length| will include the MAC
+       * and IV key bytes. */
+      if (key_len < mac_secret_len + iv_len) {
+        OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
+        return 0;
+      }
+      key_len -= mac_secret_len + iv_len;
     }
-    key_len -= mac_secret_len;
-    iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->s3->tmp.new_cipher);
   } else {
     key_len = EVP_CIPHER_key_length(cipher);
-    iv_len = EVP_CIPHER_iv_length(cipher);
   }
 
   key_data = s->s3->tmp.key_block;
@@ -601,53 +610,68 @@
   const EVP_MD *hash = NULL;
   const EVP_AEAD *aead = NULL;
   int num;
-  int mac_type = NID_undef, mac_secret_size = 0;
+  int mac_type = NID_undef;
   int ret = 0;
-  unsigned key_len, iv_len;
+  size_t mac_secret_len, fixed_iv_len, variable_iv_len, key_len;
 
 
   if (s->s3->tmp.key_block_length != 0) {
     return 1;
   }
 
-  if (s->session->cipher &&
-      ((s->session->cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) ||
-       (s->session->cipher->algorithm2 &
-        SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD))) {
-    if (!ssl_cipher_get_evp_aead(s->session, &aead)) {
+  if (s->session->cipher == NULL) {
+    goto cipher_unavailable_err;
+  }
+
+  /* TODO(davidben): Make DTLS record-layer code EVP_AEAD-aware. */
+  if (!SSL_IS_DTLS(s)) {
+    if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
+                                 s->session->cipher,
+                                 ssl3_version_from_wire(s, s->version))) {
       goto cipher_unavailable_err;
     }
     key_len = EVP_AEAD_key_length(aead);
-    iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
-    if ((s->session->cipher->algorithm2 &
-         SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) &&
-        !ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size)) {
-      goto cipher_unavailable_err;
+    variable_iv_len = EVP_AEAD_nonce_length(aead);
+    if (mac_secret_len > 0) {
+      /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites)
+       * the key length reported by |EVP_AEAD_key_length| will include the MAC
+       * key bytes and initial implicit IV. */
+      if (key_len < mac_secret_len + fixed_iv_len) {
+        OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_INTERNAL_ERROR);
+        return 0;
+      }
+      key_len -= mac_secret_len + fixed_iv_len;
+    } else {
+      /* The nonce is split into a fixed portion and a variable portion. */
+      if (variable_iv_len < fixed_iv_len) {
+        OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_INTERNAL_ERROR);
+        return 0;
+      }
+      variable_iv_len -= fixed_iv_len;
     }
-    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites)
-     * the key length reported by |EVP_AEAD_key_length| will include the MAC
-     * key bytes. */
-    if (key_len < (size_t)mac_secret_size) {
-      OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
-      return 0;
-    }
-    key_len -= mac_secret_size;
   } else {
     if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type,
-                            &mac_secret_size)) {
+                            &mac_secret_len)) {
       goto cipher_unavailable_err;
     }
     key_len = EVP_CIPHER_key_length(c);
-    iv_len = EVP_CIPHER_iv_length(c);
+    fixed_iv_len = EVP_CIPHER_iv_length(c);
+    variable_iv_len = 0;
   }
 
+  assert(mac_secret_len < 256);
+  assert(fixed_iv_len < 256);
+  assert(variable_iv_len < 256);
+
   s->s3->tmp.new_aead = aead;
   s->s3->tmp.new_sym_enc = c;
   s->s3->tmp.new_hash = hash;
   s->s3->tmp.new_mac_pkey_type = mac_type;
-  s->s3->tmp.new_mac_secret_size = mac_secret_size;
+  s->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
+  s->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;
+  s->s3->tmp.new_variable_iv_len = (uint8_t)variable_iv_len;
 
-  num = key_len + mac_secret_size + iv_len;
+  num = key_len + mac_secret_len + fixed_iv_len;
   num *= 2;
 
   ssl3_cleanup_key_block(s);
@@ -714,9 +738,9 @@
   }
 
   if (aead) {
-    uint8_t ad[13], *seq, *in, *out, nonce[16];
+    uint8_t ad[13], *seq, *in, *out, nonce[EVP_AEAD_MAX_NONCE_LENGTH];
     unsigned nonce_used;
-    size_t n;
+    size_t n, ad_len;
 
     seq = send ? s->s3->write_sequence : s->s3->read_sequence;
 
@@ -740,8 +764,8 @@
     ad[9] = (uint8_t)(s->version >> 8);
     ad[10] = (uint8_t)(s->version);
 
-    if (aead->fixed_nonce_len + aead->variable_nonce_len > sizeof(nonce) ||
-        aead->variable_nonce_len > 8) {
+    if (aead->fixed_nonce_len + aead->variable_nonce_len > sizeof(nonce)) {
+      OPENSSL_PUT_ERROR(SSL, tls1_enc, ERR_R_INTERNAL_ERROR);
       return -1; /* internal error - should never happen. */
     }
 
@@ -754,12 +778,21 @@
       in = rec->input;
       out = rec->data;
 
-      /* When sending we use the sequence number as the variable part of the
-       * nonce. */
-      if (aead->variable_nonce_len > 8) {
-        return -1;
+      uint8_t *variable_nonce = nonce + nonce_used;
+      if (aead->random_variable_nonce) {
+        assert(aead->variable_nonce_included_in_record);
+        if (!RAND_bytes(nonce + nonce_used, aead->variable_nonce_len)) {
+          return -1;
+        }
+      } else {
+        /* When sending we use the sequence number as the variable part of the
+         * nonce. */
+        if (aead->variable_nonce_len != 8) {
+          OPENSSL_PUT_ERROR(SSL, tls1_enc, ERR_R_INTERNAL_ERROR);
+          return -1;
+        }
+        memcpy(nonce + nonce_used, ad, aead->variable_nonce_len);
       }
-      memcpy(nonce + nonce_used, ad, aead->variable_nonce_len);
       nonce_used += aead->variable_nonce_len;
 
       /* in do_ssl3_write, rec->input is moved forward by variable_nonce_len in
@@ -767,17 +800,21 @@
        * sequence number bytes into place without overwriting any of the
        * plaintext. */
       if (aead->variable_nonce_included_in_record) {
-        memcpy(out, ad, aead->variable_nonce_len);
+        memcpy(out, variable_nonce, aead->variable_nonce_len);
         len -= aead->variable_nonce_len;
         eivlen = aead->variable_nonce_len;
       }
 
-      ad[11] = len >> 8;
-      ad[12] = len & 0xff;
+      if (aead->omit_length_in_ad) {
+        ad_len = 11;
+      } else {
+        ad[11] = len >> 8;
+        ad[12] = len & 0xff;
+        ad_len = 13;
+      }
 
       if (!EVP_AEAD_CTX_seal(&aead->ctx, out + eivlen, &n, len + aead->tag_len,
-                             nonce, nonce_used, in + eivlen, len, ad,
-                             sizeof(ad))) {
+                             nonce, nonce_used, in + eivlen, len, ad, ad_len)) {
         return -1;
       }
 
@@ -789,6 +826,7 @@
       size_t len = rec->length;
 
       if (rec->data != rec->input) {
+        OPENSSL_PUT_ERROR(SSL, tls1_enc, ERR_R_INTERNAL_ERROR);
         return -1; /* internal error - should never happen. */
       }
       out = in = rec->input;
@@ -807,16 +845,21 @@
         out += aead->variable_nonce_len;
       }
 
-      if (len < aead->tag_len) {
-        return 0;
+      if (aead->omit_length_in_ad) {
+        ad_len = 11;
+      } else {
+        if (len < aead->tag_len) {
+          return 0;
+        }
+        size_t plaintext_len = len - aead->tag_len;
+
+        ad[11] = plaintext_len >> 8;
+        ad[12] = plaintext_len & 0xff;
+        ad_len = 13;
       }
-      len -= aead->tag_len;
 
-      ad[11] = len >> 8;
-      ad[12] = len & 0xff;
-
-      if (!EVP_AEAD_CTX_open(&aead->ctx, out, &n, len, nonce, nonce_used, in,
-                             len + aead->tag_len, ad, sizeof(ad))) {
+      if (!EVP_AEAD_CTX_open(&aead->ctx, out, &n, rec->length, nonce, nonce_used, in,
+                             len, ad, ad_len)) {
         return -1;
       }