Implement TLS 1.3 draft28.

Change-Id: I7298c878bd2c8187dbd25903e397e8f0c2575aa4
Reviewed-on: https://boringssl-review.googlesource.com/26846
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 2cc34cf..d22d396 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -597,6 +597,7 @@
 #define DTLS1_2_VERSION 0xfefd
 
 #define TLS1_3_DRAFT23_VERSION 0x7f17
+#define TLS1_3_DRAFT28_VERSION 0x7f1c
 
 // SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to
 // |version|. If |version| is zero, the default minimum version is used. It
@@ -3310,6 +3311,7 @@
 
 enum tls13_variant_t {
   tls13_default = 0,
+  tls13_draft28 = 1,
 };
 
 // SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the
diff --git a/ssl/internal.h b/ssl/internal.h
index 10716ea..e884b63 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -392,6 +392,10 @@
 // call this function before the version is determined.
 uint16_t ssl_protocol_version(const SSL *ssl);
 
+// ssl_is_draft28 returns whether the version corresponds to a draft28 TLS 1.3
+// variant.
+bool ssl_is_draft28(uint16_t version);
+
 // Cipher suites.
 
 }  // namespace bssl
@@ -694,7 +698,7 @@
   // number of bytes written.
   size_t GetAdditionalData(uint8_t out[13], uint8_t type,
                            uint16_t record_version, const uint8_t seqnum[8],
-                           size_t plaintext_len);
+                           size_t plaintext_len, size_t ciphertext_len);
 
   const SSL_CIPHER *cipher_;
   ScopedEVP_AEAD_CTX ctx_;
@@ -721,6 +725,9 @@
   bool omit_version_in_ad_ : 1;
   // omit_ad_ is true if the AEAD's ad parameter should be omitted.
   bool omit_ad_ : 1;
+  // tls13_ad_ is true if the AEAD's ad parameter should be based on the
+  // TLS 1.3 format.
+  bool tls13_ad_ : 1;
   // xor_fixed_nonce_ is true if the fixed nonce should be XOR'd into the
   // variable nonce rather than prepended.
   bool xor_fixed_nonce_ : 1;
diff --git a/ssl/ssl_aead_ctx.cc b/ssl/ssl_aead_ctx.cc
index 247e889..e6b3ee9 100644
--- a/ssl/ssl_aead_ctx.cc
+++ b/ssl/ssl_aead_ctx.cc
@@ -43,6 +43,7 @@
       omit_length_in_ad_(false),
       omit_version_in_ad_(false),
       omit_ad_(false),
+      tls13_ad_(false),
       xor_fixed_nonce_(false) {
   OPENSSL_memset(fixed_nonce_, 0, sizeof(fixed_nonce_));
 }
@@ -134,7 +135,11 @@
       aead_ctx->xor_fixed_nonce_ = true;
       aead_ctx->variable_nonce_len_ = 8;
       aead_ctx->variable_nonce_included_in_record_ = false;
-      aead_ctx->omit_ad_ = true;
+      if (ssl_is_draft28(version)) {
+        aead_ctx->tls13_ad_ = true;
+      } else {
+        aead_ctx->omit_ad_ = true;
+      }
       assert(fixed_iv.size() >= aead_ctx->variable_nonce_len_);
     }
   } else {
@@ -203,19 +208,26 @@
 size_t SSLAEADContext::GetAdditionalData(uint8_t out[13], uint8_t type,
                                          uint16_t record_version,
                                          const uint8_t seqnum[8],
-                                         size_t plaintext_len) {
+                                         size_t plaintext_len,
+                                         size_t ciphertext_len) {
   if (omit_ad_) {
     return 0;
   }
 
-  OPENSSL_memcpy(out, seqnum, 8);
-  size_t len = 8;
+  size_t len = 0;
+  if (!tls13_ad_) {
+    OPENSSL_memcpy(out, seqnum, 8);
+    len += 8;
+  }
   out[len++] = type;
   if (!omit_version_in_ad_) {
     out[len++] = static_cast<uint8_t>((record_version >> 8));
     out[len++] = static_cast<uint8_t>(record_version);
   }
-  if (!omit_length_in_ad_) {
+  if (tls13_ad_) {
+    out[len++] = static_cast<uint8_t>((ciphertext_len >> 8));
+    out[len++] = static_cast<uint8_t>(ciphertext_len);
+  } else if (!omit_length_in_ad_) {
     out[len++] = static_cast<uint8_t>((plaintext_len >> 8));
     out[len++] = static_cast<uint8_t>(plaintext_len);
   }
@@ -244,8 +256,8 @@
     plaintext_len = in.size() - overhead;
   }
   uint8_t ad[13];
-  size_t ad_len =
-      GetAdditionalData(ad, type, record_version, seqnum, plaintext_len);
+  size_t ad_len = GetAdditionalData(ad, type, record_version, seqnum,
+                                    plaintext_len, in.size());
 
   // Assemble the nonce.
   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
@@ -320,7 +332,8 @@
   }
 
   uint8_t ad[13];
-  size_t ad_len = GetAdditionalData(ad, type, record_version, seqnum, in_len);
+  size_t ad_len = GetAdditionalData(ad, type, record_version, seqnum, in_len,
+                                    in_len + suffix_len);
 
   // Assemble the nonce.
   uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
diff --git a/ssl/ssl_versions.cc b/ssl/ssl_versions.cc
index aeb41d3..73ea26f 100644
--- a/ssl/ssl_versions.cc
+++ b/ssl/ssl_versions.cc
@@ -35,6 +35,7 @@
       return true;
 
     case TLS1_3_DRAFT23_VERSION:
+    case TLS1_3_DRAFT28_VERSION:
       *out = TLS1_3_VERSION;
       return true;
 
@@ -57,6 +58,7 @@
 
 static const uint16_t kTLSVersions[] = {
     TLS1_3_DRAFT23_VERSION,
+    TLS1_3_DRAFT28_VERSION,
     TLS1_2_VERSION,
     TLS1_1_VERSION,
     TLS1_VERSION,
@@ -100,6 +102,7 @@
 static const char *ssl_version_to_string(uint16_t version) {
   switch (version) {
     case TLS1_3_DRAFT23_VERSION:
+    case TLS1_3_DRAFT28_VERSION:
       return "TLSv1.3";
 
     case TLS1_2_VERSION:
@@ -129,6 +132,7 @@
   switch (version) {
     // Report TLS 1.3 draft versions as TLS 1.3 in the public API.
     case TLS1_3_DRAFT23_VERSION:
+    case TLS1_3_DRAFT28_VERSION:
       return TLS1_3_VERSION;
     default:
       return version;
@@ -139,7 +143,8 @@
 // particular, it picks an arbitrary TLS 1.3 representative. This should only be
 // used in context where that does not matter.
 static bool api_version_to_wire(uint16_t *out, uint16_t version) {
-  if (version == TLS1_3_DRAFT23_VERSION) {
+  if (version == TLS1_3_DRAFT23_VERSION ||
+      version == TLS1_3_DRAFT28_VERSION) {
     return false;
   }
   if (version == TLS1_3_VERSION) {
@@ -295,20 +300,15 @@
   }
 
   // This logic is part of the TLS 1.3 variants mechanism used in TLS 1.3
-  // experimentation. Although we currently only have one variant, TLS 1.3 does
-  // not a final stable deployment yet, so leave the logic in place for now.
+  // experimentation. TLS 1.3 variants must match the enabled |tls13_variant|.
   if (protocol_version != TLS1_3_VERSION ||
+      (ssl->tls13_variant == tls13_draft28 &&
+       version == TLS1_3_DRAFT28_VERSION) ||
       (ssl->tls13_variant == tls13_default &&
        version == TLS1_3_DRAFT23_VERSION)) {
     return true;
   }
 
-  // The server, when not configured at |tls13_default|, should additionally
-  // enable all variants.
-  if (ssl->server && ssl->tls13_variant != tls13_default) {
-    return true;
-  }
-
   return false;
 }
 
@@ -356,6 +356,10 @@
   return false;
 }
 
+bool ssl_is_draft28(uint16_t version) {
+  return version == TLS1_3_DRAFT28_VERSION;
+}
+
 }  // namespace bssl
 
 using namespace bssl;
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 16f4dd7..8f354e9 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -34,13 +34,16 @@
 // A draft version of TLS 1.3 that is sent over the wire for the current draft.
 const (
 	tls13Draft23Version = 0x7f17
+	tls13Draft28Version = 0x7f1c
 )
 
 const (
 	TLS13Draft23 = 0
+	TLS13Draft28 = 1
 )
 
 var allTLSWireVersions = []uint16{
+	tls13Draft28Version,
 	tls13Draft23Version,
 	VersionTLS12,
 	VersionTLS11,
@@ -1671,7 +1674,7 @@
 		switch vers {
 		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
 			return vers, true
-		case tls13Draft23Version:
+		case tls13Draft23Version, tls13Draft28Version:
 			return VersionTLS13, true
 		}
 	}
@@ -1679,11 +1682,16 @@
 	return 0, false
 }
 
+func isDraft28(vers uint16) bool {
+	return vers == tls13Draft28Version
+}
+
 // isSupportedVersion checks if the specified wire version is acceptable. If so,
 // it returns true and the corresponding protocol version. Otherwise, it returns
 // false.
 func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) {
-	if c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version {
+	if (c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version) ||
+		(c.TLS13Variant != TLS13Draft28 && wireVers == tls13Draft28Version) {
 		return 0, false
 	}
 
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 79cd06a..9cd61eb 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -448,6 +448,8 @@
 				n := len(payload) - c.Overhead()
 				additionalData[11] = byte(n >> 8)
 				additionalData[12] = byte(n)
+			} else if isDraft28(hc.wireVersion) {
+				additionalData = b.data[:recordHeaderLen]
 			}
 			var err error
 			payload, err = c.Open(payload[:0], nonce, payload, additionalData)
@@ -612,6 +614,12 @@
 				copy(additionalData[8:], b.data[:3])
 				additionalData[11] = byte(payloadLen >> 8)
 				additionalData[12] = byte(payloadLen)
+			} else if isDraft28(hc.wireVersion) {
+				additionalData = make([]byte, 5)
+				copy(additionalData, b.data[:3])
+				n := len(b.data) - recordHeaderLen
+				additionalData[3] = byte(n >> 8)
+				additionalData[4] = byte(n)
 			}
 
 			c.Seal(payload[:0], nonce, payload, additionalData)
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 308f3c6..683fd3a 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -1378,6 +1378,13 @@
 		versionWire:  tls13Draft23Version,
 		tls13Variant: TLS13Draft23,
 	},
+	{
+		name:         "TLS13Draft28",
+		version:      VersionTLS13,
+		excludeFlag:  "-no-tls13",
+		versionWire:  tls13Draft28Version,
+		tls13Variant: TLS13Draft28,
+	},
 }
 
 func allVersions(protocol protocol) []tlsVersion {
@@ -5389,16 +5396,12 @@
 					expectedVersion = runnerVers.version
 				}
 				// When running and shim have different TLS 1.3 variants enabled,
-				// shim clients are expected to fall back to TLS 1.2, while shim
-				// servers support multiple variants.
-				expectedServerVersion := expectedVersion
-				expectedClientVersion := expectedVersion
+				// shim peers are expected to fall back to TLS 1.2.
 				if expectedVersion == VersionTLS13 && runnerVers.tls13Variant != shimVers.tls13Variant {
-					expectedClientVersion = VersionTLS12
-					if shimVers.tls13Variant == TLS13Draft23 {
-						expectedServerVersion = VersionTLS12
-					}
+					expectedVersion = VersionTLS12
 				}
+				expectedClientVersion := expectedVersion
+				expectedServerVersion := expectedVersion
 
 				suffix := shimVers.name + "-" + runnerVers.name
 				if protocol == dtls {
diff --git a/ssl/tls_record.cc b/ssl/tls_record.cc
index 05a3d56..3152e7a 100644
--- a/ssl/tls_record.cc
+++ b/ssl/tls_record.cc
@@ -416,7 +416,7 @@
   out_prefix[4] = ciphertext_len & 0xff;
 
   if (!ssl->s3->aead_write_ctx->SealScatter(
-          out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, type,
+          out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, out_prefix[0],
           record_version, ssl->s3->write_sequence, in, in_len, extra_in,
           extra_in_len) ||
       !ssl_record_sequence_update(ssl->s3->write_sequence, 8)) {
diff --git a/tool/client.cc b/tool/client.cc
index 4162698..bdb5de7 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -336,6 +336,10 @@
     *out = tls13_default;
     return true;
   }
+  if (in == "draft28") {
+    *out = tls13_draft28;
+    return true;
+  }
   return false;
 }
 
diff --git a/tool/server.cc b/tool/server.cc
index 896aa86..23a47e9 100644
--- a/tool/server.cc
+++ b/tool/server.cc
@@ -308,7 +308,7 @@
   }
 
   if (args_map.count("-tls13-variant") != 0) {
-    SSL_CTX_set_tls13_variant(ctx.get(), tls13_default);
+    SSL_CTX_set_tls13_variant(ctx.get(), tls13_draft28);
   }
 
   if (args_map.count("-debug") != 0) {