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) {