Adding TLS 1.3 Record Layer.

In TLS 1.3, the actual record type is hidden within the encrypted data
and the record layer defaults to using a TLS 1.0 {3, 1} record version
for compatibility. Additionally the record layer no longer checks the
minor version of the record layer to maintain compatibility with the
TLS 1.3 spec.

Change-Id: If2c08e48baab170c1658e0715c33929d36c9be3a
Reviewed-on: https://boringssl-review.googlesource.com/8091
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/tls_record.c b/ssl/tls_record.c
index b71da17..45d9940 100644
--- a/ssl/tls_record.c
+++ b/ssl/tls_record.c
@@ -170,17 +170,21 @@
 }
 
 size_t ssl_max_seal_overhead(const SSL *ssl) {
+  size_t ret = SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
   if (SSL_IS_DTLS(ssl)) {
-    return DTLS1_RT_HEADER_LENGTH +
-           SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
+    ret += DTLS1_RT_HEADER_LENGTH;
   } else {
-    size_t ret = SSL3_RT_HEADER_LENGTH +
-                 SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
-    if (ssl_needs_record_splitting(ssl)) {
-      ret *= 2;
-    }
-    return ret;
+    ret += SSL3_RT_HEADER_LENGTH;
   }
+  /* TLS 1.3 needs an extra byte for the encrypted record type. */
+  if (ssl->s3->have_version &&
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    ret += 1;
+  }
+  if (!SSL_IS_DTLS(ssl) && ssl_needs_record_splitting(ssl)) {
+    ret *= 2;
+  }
+  return ret;
 }
 
 enum ssl_open_record_t tls_open_record(
@@ -200,9 +204,9 @@
     return ssl_open_record_partial;
   }
 
-  /* Check the version. */
-  if ((ssl->s3->have_version && version != ssl->version) ||
-      (version >> 8) != SSL3_VERSION_MAJOR) {
+  /* Check that the major version in the record matches. As of TLS 1.3, the
+   * minor version is no longer checked. */
+  if ((version >> 8) != SSL3_VERSION_MAJOR) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
     *out_alert = SSL_AD_PROTOCOL_VERSION;
     return ssl_open_record_error;
@@ -241,6 +245,23 @@
     return ssl_open_record_error;
   }
 
+  /* TLS 1.3 hides the record type inside the encrypted data. */
+  if (ssl->s3->have_version &&
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+      ssl->s3->aead_read_ctx != NULL) {
+    while (plaintext_len != 0 && out[plaintext_len - 1] == 0) {
+      plaintext_len--;
+    }
+
+    if (plaintext_len == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+      *out_alert = SSL_AD_DECRYPT_ERROR;
+      return ssl_open_record_error;
+    }
+    type = out[plaintext_len - 1];
+    plaintext_len--;
+  }
+
   /* Check the plaintext length. */
   if (plaintext_len > SSL3_RT_MAX_PLAIN_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
@@ -284,11 +305,14 @@
 
   out[0] = type;
 
-  /* Some servers hang if initial ClientHello is larger than 256 bytes and
-   * record version number > TLS 1.0. */
-  uint16_t wire_version = ssl->version;
-  if (!ssl->s3->have_version && ssl->version > SSL3_VERSION) {
-    wire_version = TLS1_VERSION;
+  /* The TLS record-layer version number is meaningless and, starting in
+   * TLS 1.3, is frozen at TLS 1.0. But for historical reasons, SSL 3.0
+   * ClientHellos should use SSL 3.0 and pre-TLS-1.3 expects the version
+   * to change after version negotiation. */
+  uint16_t wire_version = TLS1_VERSION;
+  if (ssl->version == SSL3_VERSION ||
+      (ssl->s3->have_version && ssl3_protocol_version(ssl) < TLS1_3_VERSION)) {
+    wire_version = ssl->version;
   }
   out[1] = wire_version >> 8;
   out[2] = wire_version & 0xff;
@@ -322,6 +346,25 @@
 int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
                     uint8_t type, const uint8_t *in, size_t in_len) {
   size_t frag_len = 0;
+
+  /* TLS 1.3 hides the actual record type inside the encrypted data. */
+  if (ssl->s3->have_version &&
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+      ssl->s3->aead_read_ctx != NULL) {
+    size_t padding = SSL3_RT_HEADER_LENGTH + 1;
+
+    if (in_len > in_len + padding || max_out < in_len + padding) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
+      return 0;
+    }
+
+    memmove(out + SSL3_RT_HEADER_LENGTH, in, in_len);
+    out[SSL3_RT_HEADER_LENGTH + in_len] = type;
+    in = out + SSL3_RT_HEADER_LENGTH;
+    type = SSL3_RT_APPLICATION_DATA;
+    in_len++;
+  }
+
   if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 &&
       ssl_needs_record_splitting(ssl)) {
     /* |do_seal_record| will notice if it clobbers |in[0]|, but not if it