Remove draft22 and experiment2.

Change-Id: I2486dc810ea842c534015fc04917712daa26cfde
Update-Note: Now that tls13_experiment2 is gone, the server should remove the set_tls13_variant call. To avoid further churn, we'll make the server default for future variants to be what we'd like to deploy.
Reviewed-on: https://boringssl-review.googlesource.com/25104
Commit-Queue: Steven Valdez <svaldez@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 a6c2880..17709bc 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -593,9 +593,7 @@
 #define DTLS1_VERSION 0xfeff
 #define DTLS1_2_VERSION 0xfefd
 
-#define TLS1_3_DRAFT22_VERSION 0x7f16
 #define TLS1_3_DRAFT23_VERSION 0x7f17
-#define TLS1_3_EXPERIMENT2_VERSION 0x7e02
 
 // 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
@@ -3304,8 +3302,6 @@
 
 enum tls13_variant_t {
   tls13_default = 0,
-  tls13_experiment2 = 1,
-  tls13_draft22 = 2,
 };
 
 // SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 105ab8e..3424f3d 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -213,15 +213,13 @@
 
 // ExtensionType values from draft-ietf-tls-tls13-18
 #define TLSEXT_TYPE_supported_groups 10
-#define TLSEXT_TYPE_old_key_share 40
 #define TLSEXT_TYPE_pre_shared_key 41
 #define TLSEXT_TYPE_early_data 42
 #define TLSEXT_TYPE_supported_versions 43
 #define TLSEXT_TYPE_cookie 44
 #define TLSEXT_TYPE_psk_key_exchange_modes 45
-#define TLSEXT_TYPE_ticket_early_data_info 46
 #define TLSEXT_TYPE_certificate_authorities 47
-#define TLSEXT_TYPE_new_key_share 51
+#define TLSEXT_TYPE_key_share 51
 
 // ExtensionType value from RFC5746
 #define TLSEXT_TYPE_renegotiate 0xff01
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index 1f91adb..e8dd0d3 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -493,8 +493,7 @@
   }
 
   ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->session->ssl_version);
-  if (ssl_is_draft22(ssl->session->ssl_version) &&
-      !ssl->method->add_change_cipher_spec(ssl)) {
+  if (!ssl->method->add_change_cipher_spec(ssl)) {
     return ssl_hs_error;
   }
 
diff --git a/ssl/internal.h b/ssl/internal.h
index af4eaae..f2b2f6d 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -392,18 +392,6 @@
 // call this function before the version is determined.
 uint16_t ssl_protocol_version(const SSL *ssl);
 
-// ssl_is_draft22 returns whether the version corresponds to a draft22 TLS 1.3
-// variant.
-bool ssl_is_draft22(uint16_t version);
-
-// ssl_is_draft23 returns whether the version corresponds to a draft23 TLS 1.3
-// variant.
-bool ssl_is_draft23(uint16_t version);
-
-// ssl_is_draft23_variant returns whether the variant corresponds to a
-// draft23 TLS 1.3 variant.
- bool ssl_is_draft23_variant(enum tls13_variant_t variant);
-
 // Cipher suites.
 
 }  // namespace bssl
diff --git a/ssl/s3_pkt.cc b/ssl/s3_pkt.cc
index e14d551..5eb68f6 100644
--- a/ssl/s3_pkt.cc
+++ b/ssl/s3_pkt.cc
@@ -304,14 +304,6 @@
   const bool is_early_data_read = ssl->server && SSL_in_early_data(ssl);
 
   if (type == SSL3_RT_HANDSHAKE) {
-    // If reading 0-RTT data, reject handshake data. 0-RTT data is terminated
-    // by an alert.
-    if (!ssl_is_draft22(ssl->version) && is_early_data_read) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
-      *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
-      return ssl_open_record_error;
-    }
-
     // Post-handshake data prior to TLS 1.3 is always renegotiation, which we
     // never accept as a server. Otherwise |ssl3_get_message| will send
     // |SSL_R_EXCESSIVE_MESSAGE_SIZE|.
@@ -332,16 +324,6 @@
     return ssl_open_record_discard;
   }
 
-  // Handle the end_of_early_data alert.
-  static const uint8_t kEndOfEarlyData[2] = {SSL3_AL_WARNING,
-                                             TLS1_AD_END_OF_EARLY_DATA};
-  if (!ssl_is_draft22(ssl->version) && is_early_data_read &&
-      type == SSL3_RT_ALERT && body == kEndOfEarlyData) {
-    // Stop accepting early data.
-    ssl->s3->hs->can_early_read = false;
-    return ssl_open_record_discard;
-  }
-
   if (type != SSL3_RT_APPLICATION_DATA) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
     *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index 6c4282e..b2042ea 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -2618,7 +2618,7 @@
 
   // TLS1_3_DRAFT_VERSION is not an API-level version.
   EXPECT_FALSE(
-      SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_DRAFT22_VERSION));
+      SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_DRAFT23_VERSION));
   ERR_clear_error();
 
   ctx.reset(SSL_CTX_new(DTLS_method()));
diff --git a/ssl/ssl_versions.cc b/ssl/ssl_versions.cc
index 15012dc..aeb41d3 100644
--- a/ssl/ssl_versions.cc
+++ b/ssl/ssl_versions.cc
@@ -34,9 +34,7 @@
       *out = version;
       return true;
 
-    case TLS1_3_DRAFT22_VERSION:
     case TLS1_3_DRAFT23_VERSION:
-    case TLS1_3_EXPERIMENT2_VERSION:
       *out = TLS1_3_VERSION;
       return true;
 
@@ -59,8 +57,6 @@
 
 static const uint16_t kTLSVersions[] = {
     TLS1_3_DRAFT23_VERSION,
-    TLS1_3_DRAFT22_VERSION,
-    TLS1_3_EXPERIMENT2_VERSION,
     TLS1_2_VERSION,
     TLS1_1_VERSION,
     TLS1_VERSION,
@@ -103,9 +99,7 @@
 
 static const char *ssl_version_to_string(uint16_t version) {
   switch (version) {
-    case TLS1_3_DRAFT22_VERSION:
     case TLS1_3_DRAFT23_VERSION:
-    case TLS1_3_EXPERIMENT2_VERSION:
       return "TLSv1.3";
 
     case TLS1_2_VERSION:
@@ -134,9 +128,7 @@
 static uint16_t wire_version_to_api(uint16_t version) {
   switch (version) {
     // Report TLS 1.3 draft versions as TLS 1.3 in the public API.
-    case TLS1_3_DRAFT22_VERSION:
     case TLS1_3_DRAFT23_VERSION:
-    case TLS1_3_EXPERIMENT2_VERSION:
       return TLS1_3_VERSION;
     default:
       return version;
@@ -147,13 +139,11 @@
 // 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_DRAFT22_VERSION ||
-      version == TLS1_3_DRAFT23_VERSION ||
-      version == TLS1_3_EXPERIMENT2_VERSION) {
+  if (version == TLS1_3_DRAFT23_VERSION) {
     return false;
   }
   if (version == TLS1_3_VERSION) {
-    version = TLS1_3_DRAFT22_VERSION;
+    version = TLS1_3_DRAFT23_VERSION;
   }
 
   // Check it is a real protocol version.
@@ -304,12 +294,10 @@
     return false;
   }
 
-  // TLS 1.3 variants must additionally match |tls13_variant|.
+  // 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.
   if (protocol_version != TLS1_3_VERSION ||
-      (ssl->tls13_variant == tls13_experiment2 &&
-       version == TLS1_3_EXPERIMENT2_VERSION) ||
-      (ssl->tls13_variant == tls13_draft22 &&
-       version == TLS1_3_DRAFT22_VERSION) ||
       (ssl->tls13_variant == tls13_default &&
        version == TLS1_3_DRAFT23_VERSION)) {
     return true;
@@ -368,18 +356,6 @@
   return false;
 }
 
-bool ssl_is_draft22(uint16_t version) {
-  return version == TLS1_3_DRAFT22_VERSION || version == TLS1_3_DRAFT23_VERSION;
-}
-
-bool ssl_is_draft23(uint16_t version) {
-  return version == TLS1_3_DRAFT23_VERSION;
-}
-
-bool ssl_is_draft23_variant(tls13_variant_t variant) {
-  return variant == tls13_default;
-}
-
 }  // namespace bssl
 
 using namespace bssl;
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index d972949..02ed22b 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -551,10 +551,6 @@
   return true;
 }
 
-static bool dont_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
-  return true;
-}
-
 static bool ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                     CBS *contents) {
   // This extension from the client is handled elsewhere.
@@ -1821,7 +1817,6 @@
   // selected cipher in HelloRetryRequest does not match. This avoids performing
   // the transcript hash transformation for multiple hashes.
   if (hs->received_hello_retry_request &&
-      ssl_is_draft22(ssl->version) &&
       ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) {
     return true;
   }
@@ -2091,9 +2086,7 @@
   }
 
   CBB contents, kse_bytes;
-  if (!CBB_add_u16(out, ssl_is_draft23_variant(ssl->tls13_variant)
-                            ? TLSEXT_TYPE_new_key_share
-                            : TLSEXT_TYPE_old_key_share) ||
+  if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
       !CBB_add_u16_length_prefixed(&contents, &kse_bytes)) {
     return false;
@@ -2250,9 +2243,7 @@
   uint16_t group_id;
   CBB kse_bytes, public_key;
   if (!tls1_get_shared_group(hs, &group_id) ||
-      !CBB_add_u16(out, ssl_is_draft23(hs->ssl->version)
-                            ? TLSEXT_TYPE_new_key_share
-                            : TLSEXT_TYPE_old_key_share) ||
+      !CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
       !CBB_add_u16_length_prefixed(out, &kse_bytes) ||
       !CBB_add_u16(&kse_bytes, group_id) ||
       !CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
@@ -2760,16 +2751,7 @@
     ext_ec_point_add_serverhello,
   },
   {
-    TLSEXT_TYPE_old_key_share,
-    // This is added by TLSEXT_TYPE_new_key_share's callback.
-    NULL,
-    dont_add_clienthello,
-    forbid_parse_serverhello,
-    ignore_parse_clienthello,
-    dont_add_serverhello,
-  },
-  {
-    TLSEXT_TYPE_new_key_share,
+    TLSEXT_TYPE_key_share,
     NULL,
     ext_key_share_add_clienthello,
     forbid_parse_serverhello,
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index dcf8afe..fef5129 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -33,21 +33,15 @@
 
 // A draft version of TLS 1.3 that is sent over the wire for the current draft.
 const (
-	tls13Experiment2Version = 0x7e02
-	tls13Draft22Version     = 0x7f16
-	tls13Draft23Version     = 0x7f17
+	tls13Draft23Version = 0x7f17
 )
 
 const (
-	TLS13Draft23     = 0
-	TLS13Experiment2 = 1
-	TLS13Draft22     = 2
+	TLS13Draft23 = 0
 )
 
 var allTLSWireVersions = []uint16{
 	tls13Draft23Version,
-	tls13Draft22Version,
-	tls13Experiment2Version,
 	VersionTLS12,
 	VersionTLS11,
 	VersionTLS10,
@@ -125,7 +119,6 @@
 	extensionTokenBinding               uint16 = 24
 	extensionQUICTransportParams        uint16 = 26
 	extensionSessionTicket              uint16 = 35
-	extensionOldKeyShare                uint16 = 40    // draft-ietf-tls-tls13-16
 	extensionPreSharedKey               uint16 = 41    // draft-ietf-tls-tls13-16
 	extensionEarlyData                  uint16 = 42    // draft-ietf-tls-tls13-16
 	extensionSupportedVersions          uint16 = 43    // draft-ietf-tls-tls13-16
@@ -133,7 +126,7 @@
 	extensionPSKKeyExchangeModes        uint16 = 45    // draft-ietf-tls-tls13-18
 	extensionTicketEarlyDataInfo        uint16 = 46    // draft-ietf-tls-tls13-18
 	extensionCertificateAuthorities     uint16 = 47    // draft-ietf-tls-tls13-21
-	extensionNewKeyShare                uint16 = 51    // draft-ietf-tls-tls13-23
+	extensionKeyShare                   uint16 = 51    // draft-ietf-tls-tls13-23
 	extensionCustom                     uint16 = 1234  // not IANA assigned
 	extensionNextProtoNeg               uint16 = 13172 // not IANA assigned
 	extensionRenegotiationInfo          uint16 = 0xff01
@@ -1670,7 +1663,7 @@
 		switch vers {
 		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
 			return vers, true
-		case tls13Draft23Version, tls13Draft22Version, tls13Experiment2Version:
+		case tls13Draft23Version:
 			return VersionTLS13, true
 		}
 	}
@@ -1678,21 +1671,11 @@
 	return 0, false
 }
 
-func isDraft22(vers uint16) bool {
-	return vers == tls13Draft22Version || vers == tls13Draft23Version
-}
-
-func isDraft23(vers uint16) bool {
-	return vers == tls13Draft23Version
-}
-
 // 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 != TLS13Experiment2 && wireVers == tls13Experiment2Version) ||
-		(c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version) ||
-		(c.TLS13Variant != TLS13Draft22 && wireVers == tls13Draft22Version) {
+	if c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version {
 		return 0, false
 	}
 
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 1bf4c5e..79cd06a 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -1566,9 +1566,7 @@
 		earlyALPN:          c.clientProtocol,
 	}
 
-	if isDraft22(c.wireVersion) {
-		session.masterSecret = deriveSessionPSK(cipherSuite, c.wireVersion, c.resumptionSecret, newSessionTicket.ticketNonce)
-	}
+	session.masterSecret = deriveSessionPSK(cipherSuite, c.wireVersion, c.resumptionSecret, newSessionTicket.ticketNonce)
 
 	cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
 	_, ok := c.config.ClientSessionCache.Get(cacheKey)
@@ -1860,16 +1858,13 @@
 	if cipherSuite == nil {
 		cipherSuite = c.earlyCipherSuite
 	}
-	if isDraft22(c.wireVersion) {
-		hash := cipherSuite.hash()
-		exporterKeyingLabel := []byte("exporter")
-		contextHash := hash.New()
-		contextHash.Write(context)
-		exporterContext := hash.New().Sum(nil)
-		derivedSecret := hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, secret, label, exporterContext, hash.Size())
-		return hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length)
-	}
-	return hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, secret, label, context, length)
+	hash := cipherSuite.hash()
+	exporterKeyingLabel := []byte("exporter")
+	contextHash := hash.New()
+	contextHash.Write(context)
+	exporterContext := hash.New().Sum(nil)
+	derivedSecret := hkdfExpandLabel(cipherSuite.hash(), secret, label, exporterContext, hash.Size())
+	return hkdfExpandLabel(cipherSuite.hash(), derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length)
 }
 
 // ExportKeyingMaterial exports keying material from the current connection
@@ -1954,13 +1949,10 @@
 		duplicateEarlyDataExtension: c.config.Bugs.DuplicateTicketEarlyData,
 		customExtension:             c.config.Bugs.CustomTicketExtension,
 		ticketAgeAdd:                ticketAgeAdd,
+		ticketNonce:                 nonce,
 		maxEarlyDataSize:            c.config.MaxEarlyDataSize,
 	}
 
-	if isDraft22(c.wireVersion) {
-		m.ticketNonce = nonce
-	}
-
 	if c.config.Bugs.SendTicketLifetime != 0 {
 		m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second)
 	}
@@ -1968,7 +1960,7 @@
 	state := sessionState{
 		vers:               c.vers,
 		cipherSuite:        c.cipherSuite.id,
-		masterSecret:       c.resumptionSecret,
+		masterSecret:       deriveSessionPSK(c.cipherSuite, c.wireVersion, c.resumptionSecret, nonce),
 		certificates:       peerCertificatesRaw,
 		ticketCreationTime: c.config.time(),
 		ticketExpiration:   c.config.time().Add(time.Duration(m.ticketLifetime) * time.Second),
@@ -1976,10 +1968,6 @@
 		earlyALPN:          []byte(c.clientProtocol),
 	}
 
-	if isDraft22(c.wireVersion) {
-		state.masterSecret = deriveSessionPSK(c.cipherSuite, c.wireVersion, c.resumptionSecret, nonce)
-	}
-
 	if !c.config.Bugs.SendEmptySessionTicket {
 		var err error
 		m.ticket, err = c.encryptTicket(&state)
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index b2abc40..1140269 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -162,11 +162,6 @@
 	if maxVersion >= VersionTLS13 {
 		keyShares = make(map[CurveID]ecdhCurve)
 		hello.hasKeyShares = true
-		if c.config.TLS13Variant == TLS13Draft23 {
-			hello.keyShareExtension = extensionNewKeyShare
-		} else {
-			hello.keyShareExtension = extensionOldKeyShare
-		}
 		hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
 		curvesToSend := c.config.defaultCurves()
 		for _, curveID := range hello.supportedCurves {
@@ -385,7 +380,7 @@
 			// set. Fill in an arbitrary TLS 1.3 version to compute
 			// the binder.
 			if session.vers < VersionTLS13 {
-				version = tls13Draft22Version
+				version = tls13Draft23Version
 			}
 			generatePSKBinders(version, hello, pskCipherSuite, session.masterSecret, []byte{}, []byte{}, c.config)
 		}
@@ -422,7 +417,7 @@
 		finishedHash.addEntropy(session.masterSecret)
 		finishedHash.Write(helloBytes)
 
-		if !c.config.Bugs.SkipChangeCipherSpec && isDraft22(session.wireVersion) {
+		if !c.config.Bugs.SkipChangeCipherSpec {
 			c.wireVersion = session.wireVersion
 			c.vers = VersionTLS13
 			c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
@@ -430,14 +425,8 @@
 			c.vers = 0
 		}
 
-		var earlyTrafficSecret []byte
-		if isDraft22(session.wireVersion) {
-			earlyTrafficSecret = finishedHash.deriveSecret(earlyTrafficLabelDraft22)
-			c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabelDraft22)
-		} else {
-			earlyTrafficSecret = finishedHash.deriveSecret(earlyTrafficLabel)
-			c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel)
-		}
+		earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
+		c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel)
 
 		c.useOutTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret)
 		for _, earlyData := range c.config.Bugs.SendEarlyData {
@@ -498,7 +487,7 @@
 	c.vers = serverVersion
 	c.haveVers = true
 
-	if isDraft22(c.wireVersion) {
+	if c.vers >= VersionTLS13 {
 		// The first server message must be followed by a ChangeCipherSpec.
 		c.expectTLS13ChangeCipherSpec = true
 	}
@@ -506,12 +495,10 @@
 	helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
 	var secondHelloBytes []byte
 	if haveHelloRetryRequest {
-		if isDraft22(c.wireVersion) {
-			// Explicitly read the ChangeCipherSpec now; it should
-			// be attached to the first flight, not the second flight.
-			if err := c.readTLS13ChangeCipherSpec(); err != nil {
-				return err
-			}
+		// Explicitly read the ChangeCipherSpec now; it should
+		// be attached to the first flight, not the second flight.
+		if err := c.readTLS13ChangeCipherSpec(); err != nil {
+			return err
 		}
 
 		c.out.resetCipher()
@@ -639,11 +626,9 @@
 
 	hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
 	if haveHelloRetryRequest {
-		if isDraft22(c.wireVersion) {
-			err = hs.finishedHash.UpdateForHelloRetryRequest()
-			if err != nil {
-				return err
-			}
+		err = hs.finishedHash.UpdateForHelloRetryRequest()
+		if err != nil {
+			return err
 		}
 		hs.writeServerHash(helloRetryRequest.marshal())
 		hs.writeClientHash(secondHelloBytes)
@@ -740,12 +725,6 @@
 func (hs *clientHandshakeState) doTLS13Handshake() error {
 	c := hs.c
 
-	if !isDraft22(c.wireVersion) {
-		// Early versions of the middlebox hacks inserted
-		// ChangeCipherSpec differently on 0-RTT and 2-RTT handshakes.
-		c.expectTLS13ChangeCipherSpec = true
-	}
-
 	if !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
 		return errors.New("tls: session IDs did not match.")
 	}
@@ -802,17 +781,10 @@
 		hs.finishedHash.addEntropy(zeroSecret)
 	}
 
-	clientLabel := clientHandshakeTrafficLabel
-	serverLabel := serverHandshakeTrafficLabel
-	if isDraft22(c.wireVersion) {
-		clientLabel = clientHandshakeTrafficLabelDraft22
-		serverLabel = serverHandshakeTrafficLabelDraft22
-	}
-
 	// Derive handshake traffic keys and switch read key to handshake
 	// traffic key.
-	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientLabel)
-	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel)
+	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
+	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
 	if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret); err != nil {
 		return err
 	}
@@ -949,18 +921,9 @@
 	hs.finishedHash.nextSecret()
 	hs.finishedHash.addEntropy(zeroSecret)
 
-	clientLabel = clientApplicationTrafficLabel
-	serverLabel = serverApplicationTrafficLabel
-	exportLabel := exporterLabel
-	if isDraft22(c.wireVersion) {
-		clientLabel = clientApplicationTrafficLabelDraft22
-		serverLabel = serverApplicationTrafficLabelDraft22
-		exportLabel = exporterLabelDraft22
-	}
-
-	clientTrafficSecret := hs.finishedHash.deriveSecret(clientLabel)
-	serverTrafficSecret := hs.finishedHash.deriveSecret(serverLabel)
-	c.exporterSecret = hs.finishedHash.deriveSecret(exportLabel)
+	clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
+	serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
+	c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
 
 	// Switch to application data keys on read. In particular, any alerts
 	// from the client certificate are read over these keys.
@@ -1004,14 +967,10 @@
 			helloRequest := new(helloRequestMsg)
 			c.writeRecord(recordTypeHandshake, helloRequest.marshal())
 		}
-		if isDraft22(c.wireVersion) {
-			endOfEarlyData := new(endOfEarlyDataMsg)
-			endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData
-			c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal())
-			hs.writeClientHash(endOfEarlyData.marshal())
-		} else {
-			c.sendAlert(alertEndOfEarlyData)
-		}
+		endOfEarlyData := new(endOfEarlyDataMsg)
+		endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData
+		c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal())
+		hs.writeClientHash(endOfEarlyData.marshal())
 	}
 
 	if !c.config.Bugs.SkipChangeCipherSpec && !hs.hello.hasEarlyData {
@@ -1109,13 +1068,7 @@
 
 	// Switch to application data keys.
 	c.useOutTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret)
-
-	resumeLabel := resumptionLabel
-	if isDraft22(c.wireVersion) {
-		resumeLabel = resumptionLabelDraft22
-	}
-
-	c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel)
+	c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
 	for _, ticket := range deferredTickets {
 		if err := c.processTLS13NewSessionTicket(ticket, hs.suite); err != nil {
 			return err
@@ -1887,11 +1840,7 @@
 	helloBytes := hello.marshal()
 	binderSize := len(hello.pskBinders)*(binderLen+1) + 2
 	truncatedHello := helloBytes[:len(helloBytes)-binderSize]
-	binderLabel := resumptionPSKBinderLabel
-	if isDraft22(version) {
-		binderLabel = resumptionPSKBinderLabelDraft22
-	}
-	binder := computePSKBinder(psk, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
+	binder := computePSKBinder(psk, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
 	if config.Bugs.SendShortPSKBinder {
 		binder = binder[:binderLen]
 	}
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 2f1f765..b19506d 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -265,7 +265,6 @@
 	supportedCurves         []CurveID
 	supportedPoints         []uint8
 	hasKeyShares            bool
-	keyShareExtension       uint16
 	keyShares               []keyShareEntry
 	trailingKeyShareData    bool
 	pskIdentities           []pskIdentity
@@ -453,7 +452,7 @@
 		supportedPoints.addBytes(m.supportedPoints)
 	}
 	if m.hasKeyShares {
-		extensions.addU16(m.keyShareExtension)
+		extensions.addU16(extensionKeyShare)
 		keyShareList := extensions.addU16LengthPrefixed()
 
 		keyShares := keyShareList.addU16LengthPrefixed()
@@ -740,12 +739,7 @@
 			// http://tools.ietf.org/html/rfc5077#section-3.2
 			m.ticketSupported = true
 			m.sessionTicket = []byte(body)
-		case extensionOldKeyShare, extensionNewKeyShare:
-			// We assume the client only supports one of draft-22 or draft-23.
-			if m.keyShareExtension != 0 {
-				return false
-			}
-			m.keyShareExtension = extension
+		case extensionKeyShare:
 			// draft-ietf-tls-tls13 section 6.3.2.3
 			var keyShares byteReader
 			if !body.readU16LengthPrefixed(&keyShares) || len(body) != 0 {
@@ -951,11 +945,7 @@
 
 	if vers >= VersionTLS13 {
 		if m.hasKeyShare {
-			if isDraft23(m.vers) {
-				extensions.addU16(extensionNewKeyShare)
-			} else {
-				extensions.addU16(extensionOldKeyShare)
-			}
+			extensions.addU16(extensionKeyShare)
 			keyShare := extensions.addU16LengthPrefixed()
 			keyShare.addU16(uint16(m.keyShare.group))
 			keyExchange := keyShare.addU16LengthPrefixed()
@@ -1058,10 +1048,6 @@
 	}
 
 	if vers >= VersionTLS13 {
-		extensionKeyShare := extensionOldKeyShare
-		if isDraft23(m.vers) {
-			extensionKeyShare = extensionNewKeyShare
-		}
 		for len(extensions) > 0 {
 			var extension uint16
 			var body byteReader
@@ -1252,7 +1238,7 @@
 		}
 	}
 	if m.hasKeyShare {
-		extensions.addU16(extensionOldKeyShare)
+		extensions.addU16(extensionKeyShare)
 		keyShare := extensions.addU16LengthPrefixed()
 		keyShare.addU16(uint16(m.keyShare.group))
 		keyExchange := keyShare.addU16LengthPrefixed()
@@ -1425,26 +1411,15 @@
 	}
 
 	retryRequestMsg := newByteBuilder()
-	if isDraft22(m.vers) {
-		retryRequestMsg.addU8(typeServerHello)
-	} else {
-		retryRequestMsg.addU8(typeHelloRetryRequest)
-	}
+	retryRequestMsg.addU8(typeServerHello)
 	retryRequest := retryRequestMsg.addU24LengthPrefixed()
+	retryRequest.addU16(VersionTLS12)
+	retryRequest.addBytes(tls13HelloRetryRequest)
+	sessionId := retryRequest.addU8LengthPrefixed()
+	sessionId.addBytes(m.sessionId)
+	retryRequest.addU16(m.cipherSuite)
+	retryRequest.addU8(m.compressionMethod)
 
-	if isDraft22(m.vers) {
-		retryRequest.addU16(VersionTLS12)
-		retryRequest.addBytes(tls13HelloRetryRequest)
-		sessionId := retryRequest.addU8LengthPrefixed()
-		sessionId.addBytes(m.sessionId)
-		retryRequest.addU16(m.cipherSuite)
-		retryRequest.addU8(m.compressionMethod)
-	} else {
-		retryRequest.addU16(m.vers)
-		if isDraft22(m.vers) {
-			retryRequest.addU16(m.cipherSuite)
-		}
-	}
 	extensions := retryRequest.addU16LengthPrefixed()
 
 	count := 1
@@ -1453,17 +1428,11 @@
 	}
 
 	for i := 0; i < count; i++ {
-		if isDraft22(m.vers) {
-			extensions.addU16(extensionSupportedVersions)
-			extensions.addU16(2) // Length
-			extensions.addU16(m.vers)
-		}
+		extensions.addU16(extensionSupportedVersions)
+		extensions.addU16(2) // Length
+		extensions.addU16(m.vers)
 		if m.hasSelectedGroup {
-			if isDraft23(m.vers) {
-				extensions.addU16(extensionNewKeyShare)
-			} else {
-				extensions.addU16(extensionOldKeyShare)
-			}
+			extensions.addU16(extensionKeyShare)
 			extensions.addU16(2) // length
 			extensions.addU16(uint16(m.selectedGroup))
 		}
@@ -1499,7 +1468,7 @@
 			compressionMethod != 0 {
 			return false
 		}
-	} else if isDraft22(m.vers) && !reader.readU16(&m.cipherSuite) {
+	} else if !reader.readU16(&m.cipherSuite) {
 		return false
 	}
 	var extensions byteReader
@@ -1524,10 +1493,6 @@
 		default:
 		}
 	}
-	extensionKeyShare := extensionOldKeyShare
-	if isDraft23(m.vers) {
-		extensionKeyShare = extensionNewKeyShare
-	}
 	for len(extensions) > 0 {
 		var extension uint16
 		var body byteReader
@@ -1883,37 +1848,21 @@
 		requestContext := body.addU8LengthPrefixed()
 		requestContext.addBytes(m.requestContext)
 		extensions := newByteBuilder()
-		if isDraft22(m.vers) {
-			extensions = body.addU16LengthPrefixed()
-			if m.hasSignatureAlgorithm {
-				extensions.addU16(extensionSignatureAlgorithms)
-				signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
-				for _, sigAlg := range m.signatureAlgorithms {
-					signatureAlgorithms.addU16(uint16(sigAlg))
-				}
+		extensions = body.addU16LengthPrefixed()
+		if m.hasSignatureAlgorithm {
+			extensions.addU16(extensionSignatureAlgorithms)
+			signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
+			for _, sigAlg := range m.signatureAlgorithms {
+				signatureAlgorithms.addU16(uint16(sigAlg))
 			}
-			if len(m.certificateAuthorities) > 0 {
-				extensions.addU16(extensionCertificateAuthorities)
-				certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
-				for _, ca := range m.certificateAuthorities {
-					caEntry := certificateAuthorities.addU16LengthPrefixed()
-					caEntry.addBytes(ca)
-				}
-			}
-		} else {
-			if m.hasSignatureAlgorithm {
-				signatureAlgorithms := body.addU16LengthPrefixed()
-				for _, sigAlg := range m.signatureAlgorithms {
-					signatureAlgorithms.addU16(uint16(sigAlg))
-				}
-			}
-
-			certificateAuthorities := body.addU16LengthPrefixed()
+		}
+		if len(m.certificateAuthorities) > 0 {
+			extensions.addU16(extensionCertificateAuthorities)
+			certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
 			for _, ca := range m.certificateAuthorities {
 				caEntry := certificateAuthorities.addU16LengthPrefixed()
 				caEntry.addBytes(ca)
 			}
-			extensions = body.addU16LengthPrefixed()
 		}
 
 		if m.customExtension > 0 {
@@ -1961,7 +1910,7 @@
 	m.raw = data
 	reader := byteReader(data[4:])
 
-	if isDraft22(m.vers) {
+	if m.hasRequestContext {
 		var extensions byteReader
 		if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
 			!reader.readU16LengthPrefixed(&extensions) ||
@@ -1987,16 +1936,6 @@
 				m.hasCAExtension = true
 			}
 		}
-	} else if m.hasRequestContext {
-		var extensions byteReader
-		if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
-			!parseSignatureAlgorithms(&reader, &m.signatureAlgorithms) ||
-			!parseCAs(&reader, &m.certificateAuthorities) ||
-			!reader.readU16LengthPrefixed(&extensions) ||
-			len(reader) != 0 {
-			return false
-		}
-		// Ignore certificate extensions.
 	} else {
 		if !reader.readU8LengthPrefixedBytes(&m.certificateTypes) {
 			return false
@@ -2114,9 +2053,7 @@
 	body.addU32(m.ticketLifetime)
 	if version >= VersionTLS13 {
 		body.addU32(m.ticketAgeAdd)
-		if isDraft22(m.vers) {
-			body.addU8LengthPrefixed().addBytes(m.ticketNonce)
-		}
+		body.addU8LengthPrefixed().addBytes(m.ticketNonce)
 	}
 
 	ticket := body.addU16LengthPrefixed()
@@ -2125,14 +2062,10 @@
 	if version >= VersionTLS13 {
 		extensions := body.addU16LengthPrefixed()
 		if m.maxEarlyDataSize > 0 {
-			extID := extensionTicketEarlyDataInfo
-			if isDraft22(m.vers) {
-				extID = extensionEarlyData
-			}
-			extensions.addU16(extID)
+			extensions.addU16(extensionEarlyData)
 			extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
 			if m.duplicateEarlyDataExtension {
-				extensions.addU16(extID)
+				extensions.addU16(extensionEarlyData)
 				extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
 			}
 		}
@@ -2166,15 +2099,13 @@
 		}
 		m.ticketAgeAdd = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
 		data = data[4:]
-		if isDraft22(m.vers) {
-			nonceLen := int(data[0])
-			data = data[1:]
-			if len(data) < nonceLen {
-				return false
-			}
-			m.ticketNonce = data[:nonceLen]
-			data = data[nonceLen:]
+		nonceLen := int(data[0])
+		data = data[1:]
+		if len(data) < nonceLen {
+			return false
 		}
+		m.ticketNonce = data[:nonceLen]
+		data = data[nonceLen:]
 	}
 
 	if len(data) < 2 {
@@ -2204,11 +2135,6 @@
 			return false
 		}
 
-		extID := extensionTicketEarlyDataInfo
-		if isDraft22(m.vers) {
-			extID = extensionEarlyData
-		}
-
 		for len(data) != 0 {
 			if len(data) < 4 {
 				return false
@@ -2221,7 +2147,7 @@
 			}
 
 			switch extension {
-			case extID:
+			case extensionEarlyData:
 				if length != 4 {
 					return false
 				}
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 7944377..caa66ed 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -280,14 +280,6 @@
 		}
 	}
 
-	// Check that we received the expected version of the key_share extension.
-	if c.vers >= VersionTLS13 {
-		if (isDraft23(c.wireVersion) && hs.clientHello.keyShareExtension != extensionNewKeyShare) ||
-			(!isDraft23(c.wireVersion) && hs.clientHello.keyShareExtension != extensionOldKeyShare) {
-			return fmt.Errorf("tls: client offered wrong key_share extension")
-		}
-	}
-
 	if config.Bugs.ExpectNoTLS12Session {
 		if len(hs.clientHello.sessionId) > 0 && c.vers >= VersionTLS13 {
 			return fmt.Errorf("tls: client offered an unexpected session ID")
@@ -370,11 +362,8 @@
 	c := hs.c
 	config := c.config
 
-	// We've read the ClientHello, so the next record in draft 22 must be
-	// preceded with ChangeCipherSpec.
-	if isDraft22(c.wireVersion) {
-		c.expectTLS13ChangeCipherSpec = true
-	}
+	// We've read the ClientHello, so the next record must be preceded with ChangeCipherSpec.
+	c.expectTLS13ChangeCipherSpec = true
 
 	hs.hello = &serverHelloMsg{
 		isDTLS:                c.isDTLS,
@@ -597,10 +586,8 @@
 	}
 
 	if sendHelloRetryRequest {
-		if isDraft22(c.wireVersion) {
-			if err := hs.finishedHash.UpdateForHelloRetryRequest(); err != nil {
-				return err
-			}
+		if err := hs.finishedHash.UpdateForHelloRetryRequest(); err != nil {
+			return err
 		}
 
 		oldClientHelloBytes := hs.clientHello.marshal()
@@ -608,7 +595,7 @@
 		c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
 		c.flushHandshake()
 
-		if !c.config.Bugs.SkipChangeCipherSpec && isDraft22(c.wireVersion) {
+		if !c.config.Bugs.SkipChangeCipherSpec {
 			c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
 		}
 
@@ -666,7 +653,7 @@
 
 		// PSK binders and obfuscated ticket age are both updated in the
 		// second ClientHello.
-		if isDraft22(c.wireVersion) && len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
+		if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
 			newClientHelloCopy.pskIdentities = oldClientHelloCopy.pskIdentities
 		} else {
 			if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
@@ -706,14 +693,8 @@
 			}
 		}
 		if encryptedExtensions.extensions.hasEarlyData {
-			var earlyTrafficSecret []byte
-			if isDraft22(c.wireVersion) {
-				earlyTrafficSecret = hs.finishedHash.deriveSecret(earlyTrafficLabelDraft22)
-				c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabelDraft22)
-			} else {
-				earlyTrafficSecret = hs.finishedHash.deriveSecret(earlyTrafficLabel)
-				c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel)
-			}
+			earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel)
+			c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel)
 
 			if err := c.useInTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret); err != nil {
 				return err
@@ -829,18 +810,11 @@
 		c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
 	}
 
-	clientLabel := clientHandshakeTrafficLabel
-	serverLabel := serverHandshakeTrafficLabel
-	if isDraft22(c.wireVersion) {
-		clientLabel = clientHandshakeTrafficLabelDraft22
-		serverLabel = serverHandshakeTrafficLabelDraft22
-	}
-
 	// Switch to handshake traffic keys.
-	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel)
+	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
 	c.useOutTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret)
 	// Derive handshake traffic read key, but don't switch yet.
-	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientLabel)
+	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
 
 	// Send EncryptedExtensions.
 	hs.writeServerHash(encryptedExtensions.marshal())
@@ -977,18 +951,9 @@
 	hs.finishedHash.nextSecret()
 	hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
 
-	clientLabel = clientApplicationTrafficLabel
-	serverLabel = serverApplicationTrafficLabel
-	exportLabel := exporterLabel
-	if isDraft22(c.wireVersion) {
-		clientLabel = clientApplicationTrafficLabelDraft22
-		serverLabel = serverApplicationTrafficLabelDraft22
-		exportLabel = exporterLabelDraft22
-	}
-
-	clientTrafficSecret := hs.finishedHash.deriveSecret(clientLabel)
-	serverTrafficSecret := hs.finishedHash.deriveSecret(serverLabel)
-	c.exporterSecret = hs.finishedHash.deriveSecret(exportLabel)
+	clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
+	serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
+	c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
 
 	// Switch to application data keys on write. In particular, any alerts
 	// from the client certificate are sent over these keys.
@@ -1003,31 +968,17 @@
 
 	// Read end_of_early_data.
 	if encryptedExtensions.extensions.hasEarlyData {
-		if isDraft22(c.wireVersion) {
-			msg, err := c.readHandshake()
-			if err != nil {
-				return err
-			}
-
-			endOfEarlyData, ok := msg.(*endOfEarlyDataMsg)
-			if !ok {
-				c.sendAlert(alertUnexpectedMessage)
-				return unexpectedMessageError(endOfEarlyData, msg)
-			}
-			hs.writeClientHash(endOfEarlyData.marshal())
-		} else {
-			if err := c.readRecord(recordTypeAlert); err != errEndOfEarlyDataAlert {
-				if err == nil {
-					panic("readRecord(recordTypeAlert) returned nil")
-				}
-				return err
-			}
+		msg, err := c.readHandshake()
+		if err != nil {
+			return err
 		}
-	}
-	if !isDraft22(c.wireVersion) && !hs.clientHello.hasEarlyData {
-		// Early versions of the middlebox hacks inserted
-		// ChangeCipherSpec differently on 0-RTT and 2-RTT handshakes.
-		c.expectTLS13ChangeCipherSpec = true
+
+		endOfEarlyData, ok := msg.(*endOfEarlyDataMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(endOfEarlyData, msg)
+		}
+		hs.writeClientHash(endOfEarlyData.marshal())
 	}
 
 	// Switch input stream to handshake traffic keys.
@@ -1142,13 +1093,7 @@
 	}
 
 	c.cipherSuite = hs.suite
-
-	resumeLabel := resumptionLabel
-	if isDraft22(c.wireVersion) {
-		resumeLabel = resumptionLabelDraft22
-	}
-
-	c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel)
+	c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
 
 	// TODO(davidben): Allow configuring the number of tickets sent for
 	// testing.
@@ -2172,11 +2117,7 @@
 		return errors.New("tls: Unknown cipher suite for PSK in session")
 	}
 
-	binderLabel := resumptionPSKBinderLabel
-	if isDraft22(version) {
-		binderLabel = resumptionPSKBinderLabelDraft22
-	}
-	binder := computePSKBinder(sessionState.masterSecret, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
+	binder := computePSKBinder(sessionState.masterSecret, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
 	if !bytes.Equal(binder, binderToVerify) {
 		return errors.New("tls: PSK binder does not verify")
 	}
diff --git a/ssl/test/runner/prf.go b/ssl/test/runner/prf.go
index 62c98b7..8c2da0d 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -328,7 +328,7 @@
 		return out
 	}
 
-	clientFinishedKey := hkdfExpandLabel(h.hash, h.wireVersion, baseKey, finishedLabel, nil, h.hash.Size())
+	clientFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
 	finishedHMAC := hmac.New(h.hash.New, clientFinishedKey)
 	finishedHMAC.Write(h.appendContextHashes(nil))
 	return finishedHMAC.Sum(nil)
@@ -347,7 +347,7 @@
 		return out
 	}
 
-	serverFinishedKey := hkdfExpandLabel(h.hash, h.wireVersion, baseKey, finishedLabel, nil, h.hash.Size())
+	serverFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
 	finishedHMAC := hmac.New(h.hash.New, serverFinishedKey)
 	finishedHMAC.Write(h.appendContextHashes(nil))
 	return finishedHMAC.Sum(nil)
@@ -396,24 +396,17 @@
 }
 
 func (h *finishedHash) nextSecret() {
-	if isDraft22(h.wireVersion) {
-		derivedLabel := []byte("derived")
-		h.secret = hkdfExpandLabel(h.hash, h.wireVersion, h.secret, derivedLabel, h.hash.New().Sum(nil), h.hash.Size())
-	}
+	h.secret = hkdfExpandLabel(h.hash, h.secret, []byte("derived"), h.hash.New().Sum(nil), h.hash.Size())
 }
 
 // hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined
 // in section 7.1 of draft-ietf-tls-tls13-16.
-func hkdfExpandLabel(hash crypto.Hash, version uint16, secret, label, hashValue []byte, length int) []byte {
+func hkdfExpandLabel(hash crypto.Hash, secret, label, hashValue []byte, length int) []byte {
 	if len(label) > 255 || len(hashValue) > 255 {
 		panic("hkdfExpandLabel: label or hashValue too long")
 	}
 
-	versionLabel := []byte("TLS 1.3, ")
-	if isDraft22(version) {
-		versionLabel = []byte("tls13 ")
-	}
-
+	versionLabel := []byte("tls13 ")
 	hkdfLabel := make([]byte, 3+len(versionLabel)+len(label)+1+len(hashValue))
 	x := hkdfLabel
 	x[0] = byte(length >> 8)
@@ -438,29 +431,17 @@
 
 // The following are labels for traffic secret derivation in TLS 1.3.
 var (
-	externalPSKBinderLabel        = []byte("external psk binder key")
-	resumptionPSKBinderLabel      = []byte("resumption psk binder key")
-	earlyTrafficLabel             = []byte("client early traffic secret")
-	clientHandshakeTrafficLabel   = []byte("client handshake traffic secret")
-	serverHandshakeTrafficLabel   = []byte("server handshake traffic secret")
-	clientApplicationTrafficLabel = []byte("client application traffic secret")
-	serverApplicationTrafficLabel = []byte("server application traffic secret")
-	applicationTrafficLabel       = []byte("application traffic secret")
-	earlyExporterLabel            = []byte("early exporter master secret")
-	exporterLabel                 = []byte("exporter master secret")
-	resumptionLabel               = []byte("resumption master secret")
-
-	externalPSKBinderLabelDraft22        = []byte("ext binder")
-	resumptionPSKBinderLabelDraft22      = []byte("res binder")
-	earlyTrafficLabelDraft22             = []byte("c e traffic")
-	clientHandshakeTrafficLabelDraft22   = []byte("c hs traffic")
-	serverHandshakeTrafficLabelDraft22   = []byte("s hs traffic")
-	clientApplicationTrafficLabelDraft22 = []byte("c ap traffic")
-	serverApplicationTrafficLabelDraft22 = []byte("s ap traffic")
-	applicationTrafficLabelDraft22       = []byte("traffic upd")
-	earlyExporterLabelDraft22            = []byte("e exp master")
-	exporterLabelDraft22                 = []byte("exp master")
-	resumptionLabelDraft22               = []byte("res master")
+	externalPSKBinderLabel        = []byte("ext binder")
+	resumptionPSKBinderLabel      = []byte("res binder")
+	earlyTrafficLabel             = []byte("c e traffic")
+	clientHandshakeTrafficLabel   = []byte("c hs traffic")
+	serverHandshakeTrafficLabel   = []byte("s hs traffic")
+	clientApplicationTrafficLabel = []byte("c ap traffic")
+	serverApplicationTrafficLabel = []byte("s ap traffic")
+	applicationTrafficLabel       = []byte("traffic upd")
+	earlyExporterLabel            = []byte("e exp master")
+	exporterLabel                 = []byte("exp master")
+	resumptionLabel               = []byte("res master")
 
 	resumptionPSKLabel = []byte("resumption")
 )
@@ -468,7 +449,7 @@
 // deriveSecret implements TLS 1.3's Derive-Secret function, as defined in
 // section 7.1 of draft ietf-tls-tls13-16.
 func (h *finishedHash) deriveSecret(label []byte) []byte {
-	return hkdfExpandLabel(h.hash, h.wireVersion, h.secret, label, h.appendContextHashes(nil), h.hash.Size())
+	return hkdfExpandLabel(h.hash, h.secret, label, h.appendContextHashes(nil), h.hash.Size())
 }
 
 // The following are context strings for CertificateVerify in TLS 1.3.
@@ -507,18 +488,14 @@
 // deriveTrafficAEAD derives traffic keys and constructs an AEAD given a traffic
 // secret.
 func deriveTrafficAEAD(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) interface{} {
-	key := hkdfExpandLabel(suite.hash(), version, secret, keyTLS13, nil, suite.keyLen)
-	iv := hkdfExpandLabel(suite.hash(), version, secret, ivTLS13, nil, suite.ivLen(version))
+	key := hkdfExpandLabel(suite.hash(), secret, keyTLS13, nil, suite.keyLen)
+	iv := hkdfExpandLabel(suite.hash(), secret, ivTLS13, nil, suite.ivLen(version))
 
 	return suite.aead(version, key, iv)
 }
 
 func updateTrafficSecret(hash crypto.Hash, version uint16, secret []byte) []byte {
-	trafficLabel := applicationTrafficLabel
-	if isDraft22(version) {
-		trafficLabel = applicationTrafficLabelDraft22
-	}
-	return hkdfExpandLabel(hash, version, secret, trafficLabel, nil, hash.Size())
+	return hkdfExpandLabel(hash, secret, applicationTrafficLabel, nil, hash.Size())
 }
 
 func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cipherSuite, clientHello, helloRetryRequest, truncatedHello []byte) []byte {
@@ -526,7 +503,7 @@
 	finishedHash.addEntropy(psk)
 	binderKey := finishedHash.deriveSecret(label)
 	finishedHash.Write(clientHello)
-	if isDraft22(version) && len(helloRetryRequest) != 0 {
+	if len(helloRetryRequest) != 0 {
 		finishedHash.UpdateForHelloRetryRequest()
 	}
 	finishedHash.Write(helloRetryRequest)
@@ -536,5 +513,5 @@
 
 func deriveSessionPSK(suite *cipherSuite, version uint16, masterSecret []byte, nonce []byte) []byte {
 	hash := suite.hash()
-	return hkdfExpandLabel(hash, version, masterSecret, resumptionPSKLabel, nonce, hash.Size())
+	return hkdfExpandLabel(hash, masterSecret, resumptionPSKLabel, nonce, hash.Size())
 }
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 68848ea..b782514 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -1372,26 +1372,12 @@
 		versionDTLS: VersionDTLS12,
 	},
 	{
-		name:         "TLS13Draft22",
-		version:      VersionTLS13,
-		excludeFlag:  "-no-tls13",
-		versionWire:  tls13Draft22Version,
-		tls13Variant: TLS13Draft22,
-	},
-	{
 		name:         "TLS13Draft23",
 		version:      VersionTLS13,
 		excludeFlag:  "-no-tls13",
 		versionWire:  tls13Draft23Version,
 		tls13Variant: TLS13Draft23,
 	},
-	{
-		name:         "TLS13Experiment2",
-		version:      VersionTLS13,
-		excludeFlag:  "-no-tls13",
-		versionWire:  tls13Experiment2Version,
-		tls13Variant: TLS13Experiment2,
-	},
 }
 
 func allVersions(protocol protocol) []tlsVersion {
@@ -2854,20 +2840,20 @@
 		},
 		{
 			testType: clientTest,
-			name:     "TLS13Draft22-InvalidCompressionMethod",
+			name:     "TLS13Draft23-InvalidCompressionMethod",
 			config: Config{
 				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
 					SendCompressionMethod: 1,
 				},
 			},
-			tls13Variant:  TLS13Draft22,
+			tls13Variant:  TLS13Draft23,
 			shouldFail:    true,
 			expectedError: ":DECODE_ERROR:",
 		},
 		{
 			testType: clientTest,
-			name:     "TLS13Draft22-HRR-InvalidCompressionMethod",
+			name:     "TLS13Draft23-HRR-InvalidCompressionMethod",
 			config: Config{
 				MaxVersion:       VersionTLS13,
 				CurvePreferences: []CurveID{CurveP384},
@@ -2875,7 +2861,7 @@
 					SendCompressionMethod: 1,
 				},
 			},
-			tls13Variant:       TLS13Draft22,
+			tls13Variant:       TLS13Draft23,
 			shouldFail:         true,
 			expectedError:      ":DECODE_ERROR:",
 			expectedLocalError: "remote error: error decoding message",
@@ -3968,7 +3954,7 @@
 	// Test that an empty client CA list doesn't send a CA extension.
 	testCases = append(testCases, testCase{
 		testType: serverTest,
-		name:     "TLS13Draft22-Empty-Client-CA-List",
+		name:     "TLS13Draft23-Empty-Client-CA-List",
 		config: Config{
 			MaxVersion:   VersionTLS13,
 			Certificates: []Certificate{rsaCertificate},
@@ -3976,7 +3962,7 @@
 				ExpectNoCertificateAuthoritiesExtension: true,
 			},
 		},
-		tls13Variant: TLS13Draft22,
+		tls13Variant: TLS13Draft23,
 		flags: []string{
 			"-require-any-client-certificate",
 			"-use-client-ca-list", "<EMPTY>",
@@ -4334,7 +4320,7 @@
 		})
 
 		tests = append(tests, testCase{
-			name: "TLS13Draft22-HelloRetryRequest-Client",
+			name: "TLS13Draft23-HelloRetryRequest-Client",
 			config: Config{
 				MaxVersion: VersionTLS13,
 				MinVersion: VersionTLS13,
@@ -4345,21 +4331,21 @@
 					ExpectMissingKeyShare: true,
 				},
 			},
-			tls13Variant: TLS13Draft22,
+			tls13Variant: TLS13Draft23,
 			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
 			resumeSession: true,
 		})
 
 		tests = append(tests, testCase{
 			testType: serverTest,
-			name:     "TLS13Draft22-HelloRetryRequest-Server",
+			name:     "TLS13Draft23-HelloRetryRequest-Server",
 			config: Config{
 				MaxVersion: VersionTLS13,
 				MinVersion: VersionTLS13,
 				// Require a HelloRetryRequest for every curve.
 				DefaultCurves: []CurveID{},
 			},
-			tls13Variant: TLS13Draft22,
+			tls13Variant: TLS13Draft23,
 			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
 			resumeSession: true,
 		})
@@ -7903,14 +7889,14 @@
 		},
 	})
 	testCases = append(testCases, testCase{
-		name: "Renegotiate-Client-TLS13Draft22",
+		name: "Renegotiate-Client-TLS13Draft23",
 		config: Config{
 			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				FailIfResumeOnRenego: true,
 			},
 		},
-		tls13Variant: TLS13Draft22,
+		tls13Variant: TLS13Draft23,
 		renegotiate:  1,
 		// Test renegotiation after both an initial and resumption
 		// handshake.
@@ -11717,7 +11703,7 @@
 		messageType: typeEndOfEarlyData,
 		test: testCase{
 			testType: serverTest,
-			name:     "TLS13Draft22-EndOfEarlyData",
+			name:     "TLS13Draft23-EndOfEarlyData",
 			config: Config{
 				MaxVersion: VersionTLS13,
 			},
@@ -11728,7 +11714,7 @@
 					ExpectEarlyDataAccepted: true,
 				},
 			},
-			tls13Variant:  TLS13Draft22,
+			tls13Variant:  TLS13Draft23,
 			resumeSession: true,
 			flags:         []string{"-enable-early-data"},
 		},
@@ -12275,50 +12261,48 @@
 			expectedError: ":WRONG_CURVE:",
 		})
 
-		if isDraft22(version.versionWire) {
-			testCases = append(testCases, testCase{
-				name: "HelloRetryRequest-CipherChange-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					// P-384 requires HelloRetryRequest in BoringSSL.
-					CurvePreferences: []CurveID{CurveP384},
-					Bugs: ProtocolBugs{
-						SendCipherSuite:                  TLS_AES_128_GCM_SHA256,
-						SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
-					},
+		testCases = append(testCases, testCase{
+			name: "HelloRetryRequest-CipherChange-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				// P-384 requires HelloRetryRequest in BoringSSL.
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					SendCipherSuite:                  TLS_AES_128_GCM_SHA256,
+					SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
 				},
-				tls13Variant:  variant,
-				shouldFail:    true,
-				expectedError: ":WRONG_CIPHER_RETURNED:",
-			})
+			},
+			tls13Variant:  variant,
+			shouldFail:    true,
+			expectedError: ":WRONG_CIPHER_RETURNED:",
+		})
 
-			// Test that the client does not offer a PSK in the second ClientHello if the
-			// HelloRetryRequest is incompatible with it.
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "HelloRetryRequest-NonResumableCipher-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					CipherSuites: []uint16{
-						TLS_AES_128_GCM_SHA256,
-					},
+		// Test that the client does not offer a PSK in the second ClientHello if the
+		// HelloRetryRequest is incompatible with it.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "HelloRetryRequest-NonResumableCipher-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				CipherSuites: []uint16{
+					TLS_AES_128_GCM_SHA256,
 				},
-				resumeConfig: &Config{
-					MaxVersion: VersionTLS13,
-					// P-384 requires HelloRetryRequest in BoringSSL.
-					CurvePreferences: []CurveID{CurveP384},
-					Bugs: ProtocolBugs{
-						ExpectNoTLS13PSKAfterHRR: true,
-					},
-					CipherSuites: []uint16{
-						TLS_AES_256_GCM_SHA384,
-					},
+			},
+			resumeConfig: &Config{
+				MaxVersion: VersionTLS13,
+				// P-384 requires HelloRetryRequest in BoringSSL.
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					ExpectNoTLS13PSKAfterHRR: true,
 				},
-				tls13Variant:         variant,
-				resumeSession:        true,
-				expectResumeRejected: true,
-			})
-		}
+				CipherSuites: []uint16{
+					TLS_AES_256_GCM_SHA384,
+				},
+			},
+			tls13Variant:         variant,
+			resumeSession:        true,
+			expectResumeRejected: true,
+		})
 
 		testCases = append(testCases, testCase{
 			name: "DisabledCurve-HelloRetryRequest-" + name,
@@ -12562,43 +12546,41 @@
 			expectedError: ":DECODE_ERROR:",
 		})
 
-		if isDraft22(version.versionWire) {
-			testCases = append(testCases, testCase{
-				name: "UnknownExtensionInCertificateRequest-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					MinVersion: VersionTLS13,
-					ClientAuth: RequireAnyClientCert,
-					Bugs: ProtocolBugs{
-						SendCustomCertificateRequest: 0x1212,
-					},
+		testCases = append(testCases, testCase{
+			name: "UnknownExtensionInCertificateRequest-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				ClientAuth: RequireAnyClientCert,
+				Bugs: ProtocolBugs{
+					SendCustomCertificateRequest: 0x1212,
 				},
-				tls13Variant: variant,
-				flags: []string{
-					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-					"-key-file", path.Join(*resourceDir, rsaKeyFile),
-				},
-			})
+			},
+			tls13Variant: variant,
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			},
+		})
 
-			testCases = append(testCases, testCase{
-				name: "MissingSignatureAlgorithmsInCertificateRequest-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					MinVersion: VersionTLS13,
-					ClientAuth: RequireAnyClientCert,
-					Bugs: ProtocolBugs{
-						OmitCertificateRequestAlgorithms: true,
-					},
+		testCases = append(testCases, testCase{
+			name: "MissingSignatureAlgorithmsInCertificateRequest-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				ClientAuth: RequireAnyClientCert,
+				Bugs: ProtocolBugs{
+					OmitCertificateRequestAlgorithms: true,
 				},
-				tls13Variant: variant,
-				flags: []string{
-					"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-					"-key-file", path.Join(*resourceDir, rsaKeyFile),
-				},
-				shouldFail:    true,
-				expectedError: ":DECODE_ERROR:",
-			})
-		}
+			},
+			tls13Variant: variant,
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			},
+			shouldFail:    true,
+			expectedError: ":DECODE_ERROR:",
+		})
 
 		testCases = append(testCases, testCase{
 			testType: serverTest,
@@ -12795,73 +12777,71 @@
 			expectedError: ":UNEXPECTED_EXTENSION:",
 		})
 
-		if isDraft22(version.versionWire) {
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "SkipChangeCipherSpec-Client-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						SkipChangeCipherSpec: true,
-					},
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "SkipChangeCipherSpec-Client-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SkipChangeCipherSpec: true,
 				},
-				tls13Variant: variant,
-			})
+			},
+			tls13Variant: variant,
+		})
 
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     "SkipChangeCipherSpec-Server-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						SkipChangeCipherSpec: true,
-					},
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "SkipChangeCipherSpec-Server-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SkipChangeCipherSpec: true,
 				},
-				tls13Variant: variant,
-			})
+			},
+			tls13Variant: variant,
+		})
 
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "TooManyChangeCipherSpec-Client-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						SendExtraChangeCipherSpec: 33,
-					},
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "TooManyChangeCipherSpec-Client-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendExtraChangeCipherSpec: 33,
 				},
-				tls13Variant:  variant,
-				shouldFail:    true,
-				expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
-			})
+			},
+			tls13Variant:  variant,
+			shouldFail:    true,
+			expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
+		})
 
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     "TooManyChangeCipherSpec-Server-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						SendExtraChangeCipherSpec: 33,
-					},
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "TooManyChangeCipherSpec-Server-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendExtraChangeCipherSpec: 33,
 				},
-				tls13Variant:  variant,
-				shouldFail:    true,
-				expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
-			})
+			},
+			tls13Variant:  variant,
+			shouldFail:    true,
+			expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
+		})
 
-			testCases = append(testCases, testCase{
-				name: "SendPostHandshakeChangeCipherSpec-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						SendPostHandshakeChangeCipherSpec: true,
-					},
+		testCases = append(testCases, testCase{
+			name: "SendPostHandshakeChangeCipherSpec-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendPostHandshakeChangeCipherSpec: true,
 				},
-				tls13Variant:       variant,
-				shouldFail:         true,
-				expectedError:      ":UNEXPECTED_RECORD:",
-				expectedLocalError: "remote error: unexpected message",
-			})
-		}
+			},
+			tls13Variant:       variant,
+			shouldFail:         true,
+			expectedError:      ":UNEXPECTED_RECORD:",
+			expectedLocalError: "remote error: unexpected message",
+		})
 
 		fooString := "foo"
 		barString := "bar"
@@ -13243,13 +13223,6 @@
 			expectedError:      ":BAD_DECRYPT:",
 		})
 
-		expectedError := ":UNEXPECTED_RECORD:"
-		if isDraft22(version.versionWire) {
-			// In draft-21 and up, early data is expected to be
-			// terminated by a handshake message, though we test
-			// with the wrong one.
-			expectedError = ":UNEXPECTED_MESSAGE:"
-		}
 		testCases = append(testCases, testCase{
 			testType: serverTest,
 			name:     "EarlyData-UnexpectedHandshake-Server-" + name,
@@ -13267,7 +13240,7 @@
 			tls13Variant:       variant,
 			resumeSession:      true,
 			shouldFail:         true,
-			expectedError:      expectedError,
+			expectedError:      ":UNEXPECTED_MESSAGE:",
 			expectedLocalError: "remote error: unexpected message",
 			flags: []string{
 				"-enable-early-data",
@@ -13346,32 +13319,30 @@
 			expectedLocalError: "remote error: error decrypting message",
 		})
 
-		if isDraft22(version.versionWire) {
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     "Server-NonEmptyEndOfEarlyData-" + name,
-				config: Config{
-					MaxVersion: VersionTLS13,
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "Server-NonEmptyEndOfEarlyData-" + name,
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			resumeConfig: &Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+					ExpectEarlyDataAccepted: true,
+					NonEmptyEndOfEarlyData:  true,
 				},
-				resumeConfig: &Config{
-					MaxVersion: VersionTLS13,
-					Bugs: ProtocolBugs{
-						SendEarlyData:           [][]byte{{1, 2, 3, 4}},
-						ExpectEarlyDataAccepted: true,
-						NonEmptyEndOfEarlyData:  true,
-					},
-				},
-				resumeSession: true,
-				flags: []string{
-					"-enable-early-data",
-					"-expect-ticket-supports-early-data",
-					"-expect-accept-early-data",
-				},
-				tls13Variant:  variant,
-				shouldFail:    true,
-				expectedError: ":DECODE_ERROR:",
-			})
-		}
+			},
+			resumeSession: true,
+			flags: []string{
+				"-enable-early-data",
+				"-expect-ticket-supports-early-data",
+				"-expect-accept-early-data",
+			},
+			tls13Variant:  variant,
+			shouldFail:    true,
+			expectedError: ":DECODE_ERROR:",
+		})
 
 		testCases = append(testCases, testCase{
 			testType: serverTest,
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc
index f013afd..aa05456 100644
--- a/ssl/tls13_client.cc
+++ b/ssl/tls13_client.cc
@@ -58,88 +58,63 @@
     return ssl_hs_read_message;
   }
 
-  CBS extensions;
-  uint16_t cipher_suite = 0;
-  if (ssl_is_draft22(ssl->version)) {
-    // Queue up a ChangeCipherSpec for whenever we next send something. This
-    // will be before the second ClientHello. If we offered early data, this was
-    // already done.
-    if (!hs->early_data_offered &&
-        !ssl->method->add_change_cipher_spec(ssl)) {
-      return ssl_hs_error;
-    }
-
-    if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
-      return ssl_hs_error;
-    }
-
-    CBS body = msg.body, server_random, session_id;
-    uint16_t server_version;
-    uint8_t compression_method;
-    if (!CBS_get_u16(&body, &server_version) ||
-        !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) ||
-        !CBS_get_u8_length_prefixed(&body, &session_id) ||
-        !CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len) ||
-        !CBS_get_u16(&body, &cipher_suite) ||
-        !CBS_get_u8(&body, &compression_method) ||
-        compression_method != 0 ||
-        !CBS_get_u16_length_prefixed(&body, &extensions) ||
-        CBS_len(&extensions) == 0 ||
-        CBS_len(&body) != 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      return ssl_hs_error;
-    }
-
-    if (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
-      hs->tls13_state = state_read_server_hello;
-      return ssl_hs_ok;
-    }
-  } else {
-    if (msg.type != SSL3_MT_HELLO_RETRY_REQUEST) {
-      hs->tls13_state = state_read_server_hello;
-      return ssl_hs_ok;
-    }
-
-    CBS body = msg.body;
-    uint16_t server_version;
-    if (!CBS_get_u16(&body, &server_version) ||
-        (ssl_is_draft22(ssl->version) &&
-         !CBS_get_u16(&body, &cipher_suite)) ||
-        !CBS_get_u16_length_prefixed(&body, &extensions) ||
-        CBS_len(&body) != 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      return ssl_hs_error;
-    }
+  // Queue up a ChangeCipherSpec for whenever we next send something. This
+  // will be before the second ClientHello. If we offered early data, this was
+  // already done.
+  if (!hs->early_data_offered &&
+      !ssl->method->add_change_cipher_spec(ssl)) {
+    return ssl_hs_error;
   }
 
-  if (ssl_is_draft22(ssl->version)) {
-    const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
-    // Check if the cipher is a TLS 1.3 cipher.
-    if (cipher == NULL ||
-        SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) ||
-        SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
-      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-      return ssl_hs_error;
-    }
+  if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
+    return ssl_hs_error;
+  }
 
-    hs->new_cipher = cipher;
+  CBS body = msg.body, extensions, server_random, session_id;
+  uint16_t server_version, cipher_suite;
+  uint8_t compression_method;
+  if (!CBS_get_u16(&body, &server_version) ||
+      !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) ||
+      !CBS_get_u8_length_prefixed(&body, &session_id) ||
+      !CBS_mem_equal(&session_id, hs->session_id, hs->session_id_len) ||
+      !CBS_get_u16(&body, &cipher_suite) ||
+      !CBS_get_u8(&body, &compression_method) ||
+      compression_method != 0 ||
+      !CBS_get_u16_length_prefixed(&body, &extensions) ||
+      CBS_len(&extensions) == 0 ||
+      CBS_len(&body) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return ssl_hs_error;
+  }
 
-    if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher) ||
-        !hs->transcript.UpdateForHelloRetryRequest()) {
-      return ssl_hs_error;
-    }
+  if (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
+    hs->tls13_state = state_read_server_hello;
+    return ssl_hs_ok;
+  }
+
+  const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
+  // Check if the cipher is a TLS 1.3 cipher.
+  if (cipher == NULL ||
+      SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) ||
+      SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
+    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return ssl_hs_error;
+  }
+
+  hs->new_cipher = cipher;
+
+  if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher) ||
+      !hs->transcript.UpdateForHelloRetryRequest()) {
+    return ssl_hs_error;
   }
 
 
   bool have_cookie, have_key_share, have_supported_versions;
   CBS cookie, key_share, supported_versions;
   SSL_EXTENSION_TYPE ext_types[] = {
-      {ssl_is_draft23(ssl->version) ? (uint16_t)TLSEXT_TYPE_new_key_share
-                                    : (uint16_t)TLSEXT_TYPE_old_key_share,
-       &have_key_share, &key_share},
+      {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
       {TLSEXT_TYPE_cookie, &have_cookie, &cookie},
       {TLSEXT_TYPE_supported_versions, &have_supported_versions,
        &supported_versions},
@@ -153,11 +128,6 @@
     return ssl_hs_error;
   }
 
-  if (!ssl_is_draft22(ssl->version) && have_supported_versions) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
-    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
-    return ssl_hs_error;
-  }
   if (!have_cookie && !have_key_share) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_EMPTY_HELLO_RETRY_REQUEST);
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@@ -274,8 +244,7 @@
   }
 
   // Forbid a second HelloRetryRequest.
-  if (ssl_is_draft22(ssl->version) &&
-      CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
+  if (CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
     return ssl_hs_error;
@@ -295,8 +264,7 @@
   }
 
   // Check that the cipher matches the one in the HelloRetryRequest.
-  if (ssl_is_draft22(ssl->version) &&
-      hs->received_hello_retry_request &&
+  if (hs->received_hello_retry_request &&
       hs->new_cipher != cipher) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@@ -308,9 +276,7 @@
        have_supported_versions = false;
   CBS key_share, pre_shared_key, supported_versions;
   SSL_EXTENSION_TYPE ext_types[] = {
-      {ssl_is_draft23(ssl->version) ? (uint16_t)TLSEXT_TYPE_new_key_share
-                                    : (uint16_t)TLSEXT_TYPE_old_key_share,
-       &have_key_share, &key_share},
+      {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
       {TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key},
       {TLSEXT_TYPE_supported_versions, &have_supported_versions,
        &supported_versions},
@@ -416,13 +382,6 @@
   }
 
   if (!hs->early_data_offered) {
-    // Earlier versions of the resumption experiment added ChangeCipherSpec just
-    // before the Finished flight.
-    if (!ssl_is_draft22(ssl->version) &&
-        !ssl->method->add_change_cipher_spec(ssl)) {
-      return ssl_hs_error;
-    }
-
     // If not sending early data, set client traffic keys now so that alerts are
     // encrypted.
     if (!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
@@ -515,75 +474,45 @@
   }
 
 
-  if (ssl_is_draft22(ssl->version)) {
-    bool have_sigalgs = false, have_ca = false;
-    CBS sigalgs, ca;
-    const SSL_EXTENSION_TYPE ext_types[] = {
-      {TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs},
-      {TLSEXT_TYPE_certificate_authorities, &have_ca, &ca},
-    };
+  bool have_sigalgs = false, have_ca = false;
+  CBS sigalgs, ca;
+  const SSL_EXTENSION_TYPE ext_types[] = {
+    {TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs},
+    {TLSEXT_TYPE_certificate_authorities, &have_ca, &ca},
+  };
 
-    CBS body = msg.body, context, extensions, supported_signature_algorithms;
-    uint8_t alert = SSL_AD_DECODE_ERROR;
-    if (!CBS_get_u8_length_prefixed(&body, &context) ||
-        // The request context is always empty during the handshake.
-        CBS_len(&context) != 0 ||
-        !CBS_get_u16_length_prefixed(&body, &extensions) ||
-        CBS_len(&body) != 0 ||
-        !ssl_parse_extensions(&extensions, &alert, ext_types,
-                              OPENSSL_ARRAY_SIZE(ext_types),
-                              1 /* accept unknown */) ||
-        (have_ca && CBS_len(&ca) == 0) ||
-        !have_sigalgs ||
-        !CBS_get_u16_length_prefixed(&sigalgs,
-                                     &supported_signature_algorithms) ||
-        CBS_len(&supported_signature_algorithms) == 0 ||
-        !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
-      ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      return ssl_hs_error;
-    }
+  CBS body = msg.body, context, extensions, supported_signature_algorithms;
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  if (!CBS_get_u8_length_prefixed(&body, &context) ||
+      // The request context is always empty during the handshake.
+      CBS_len(&context) != 0 ||
+      !CBS_get_u16_length_prefixed(&body, &extensions) ||
+      CBS_len(&body) != 0 ||
+      !ssl_parse_extensions(&extensions, &alert, ext_types,
+                            OPENSSL_ARRAY_SIZE(ext_types),
+                            1 /* accept unknown */) ||
+      (have_ca && CBS_len(&ca) == 0) ||
+      !have_sigalgs ||
+      !CBS_get_u16_length_prefixed(&sigalgs,
+                                   &supported_signature_algorithms) ||
+      CBS_len(&supported_signature_algorithms) == 0 ||
+      !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
+    ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return ssl_hs_error;
+  }
 
-    if (have_ca) {
-      hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca);
-      if (!hs->ca_names) {
-        ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
-        return ssl_hs_error;
-      }
-    } else {
-      hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null());
-      if (!hs->ca_names) {
-        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        return ssl_hs_error;
-      }
-    }
-  } else {
-    CBS body = msg.body, context, supported_signature_algorithms;
-    if (!CBS_get_u8_length_prefixed(&body, &context) ||
-        // The request context is always empty during the handshake.
-        CBS_len(&context) != 0 ||
-        !CBS_get_u16_length_prefixed(&body, &supported_signature_algorithms) ||
-        CBS_len(&supported_signature_algorithms) == 0 ||
-        !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
-      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      return ssl_hs_error;
-    }
-
-    uint8_t alert = SSL_AD_DECODE_ERROR;
-    hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &body);
+  if (have_ca) {
+    hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca);
     if (!hs->ca_names) {
       ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
       return ssl_hs_error;
     }
-
-    // Ignore extensions.
-    CBS extensions;
-    if (!CBS_get_u16_length_prefixed(&body, &extensions) ||
-        CBS_len(&body) != 0) {
-      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+  } else {
+    hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null());
+    if (!hs->ca_names) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
       return ssl_hs_error;
     }
   }
@@ -670,19 +599,12 @@
 
   if (ssl->s3->early_data_accepted) {
     hs->can_early_write = false;
-    if (ssl_is_draft22(ssl->version)) {
-      ScopedCBB cbb;
-      CBB body;
-      if (!ssl->method->init_message(ssl, cbb.get(), &body,
-                                     SSL3_MT_END_OF_EARLY_DATA) ||
-          !ssl_add_message_cbb(ssl, cbb.get())) {
-        return ssl_hs_error;
-      }
-    } else {
-      if (!ssl->method->add_alert(ssl, SSL3_AL_WARNING,
-                                  TLS1_AD_END_OF_EARLY_DATA)) {
-        return ssl_hs_error;
-      }
+    ScopedCBB cbb;
+    CBB body;
+    if (!ssl->method->init_message(ssl, cbb.get(), &body,
+                                   SSL3_MT_END_OF_EARLY_DATA) ||
+        !ssl_add_message_cbb(ssl, cbb.get())) {
+      return ssl_hs_error;
     }
   }
 
@@ -909,8 +831,7 @@
   CBS body = msg.body, ticket_nonce, ticket, extensions;
   if (!CBS_get_u32(&body, &server_timeout) ||
       !CBS_get_u32(&body, &session->ticket_age_add) ||
-      (ssl_is_draft22(ssl->version) &&
-       !CBS_get_u8_length_prefixed(&body, &ticket_nonce)) ||
+      !CBS_get_u8_length_prefixed(&body, &ticket_nonce) ||
       !CBS_get_u16_length_prefixed(&body, &ticket) ||
       !CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen) ||
       !CBS_get_u16_length_prefixed(&body, &extensions) ||
@@ -933,11 +854,8 @@
   // Parse out the extensions.
   bool have_early_data_info = false;
   CBS early_data_info;
-  uint16_t ext_id = ssl_is_draft22(ssl->version)
-                        ? TLSEXT_TYPE_early_data
-                        : TLSEXT_TYPE_ticket_early_data_info;
   const SSL_EXTENSION_TYPE ext_types[] = {
-      {ext_id, &have_early_data_info, &early_data_info},
+      {TLSEXT_TYPE_early_data, &have_early_data_info, &early_data_info},
   };
 
   uint8_t alert = SSL_AD_DECODE_ERROR;
diff --git a/ssl/tls13_enc.cc b/ssl/tls13_enc.cc
index 1bf820e..cc7afb8 100644
--- a/ssl/tls13_enc.cc
+++ b/ssl/tls13_enc.cc
@@ -66,13 +66,11 @@
                       psk_len, hs->secret, hs->hash_len);
 }
 
-static int hkdf_expand_label(uint8_t *out, uint16_t version,
-                             const EVP_MD *digest, const uint8_t *secret,
-                             size_t secret_len, const char *label,
-                             size_t label_len, const uint8_t *hash,
-                             size_t hash_len, size_t len) {
-  const char *kTLS13LabelVersion =
-      ssl_is_draft22(version) ? "tls13 " : "TLS 1.3, ";
+static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
+                             const uint8_t *secret, size_t secret_len,
+                             const char *label, size_t label_len,
+                             const uint8_t *hash, size_t hash_len, size_t len) {
+  static const char kTLS13LabelVersion[] = "tls13 ";
 
   ScopedCBB cbb;
   CBB child;
@@ -101,23 +99,18 @@
 
 int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
                                size_t len) {
-  SSL *const ssl = hs->ssl;
+  uint8_t derive_context[EVP_MAX_MD_SIZE];
+  unsigned derive_context_len;
+  if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len,
+                  hs->transcript.Digest(), nullptr)) {
+    return 0;
+  }
 
-  // Draft 18 does not include the extra Derive-Secret step.
-  if (ssl_is_draft22(ssl->version)) {
-    uint8_t derive_context[EVP_MAX_MD_SIZE];
-    unsigned derive_context_len;
-    if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len,
-                    hs->transcript.Digest(), nullptr)) {
-      return 0;
-    }
-
-    if (!hkdf_expand_label(hs->secret, ssl->version, hs->transcript.Digest(),
-                           hs->secret, hs->hash_len, kTLS13LabelDerived,
-                           strlen(kTLS13LabelDerived), derive_context,
-                           derive_context_len, hs->hash_len)) {
-      return 0;
-    }
+  if (!hkdf_expand_label(hs->secret, hs->transcript.Digest(), hs->secret,
+                         hs->hash_len, kTLS13LabelDerived,
+                         strlen(kTLS13LabelDerived), derive_context,
+                         derive_context_len, hs->hash_len)) {
+    return 0;
   }
 
   return HKDF_extract(hs->secret, &hs->hash_len, hs->transcript.Digest(), in,
@@ -135,10 +128,9 @@
     return 0;
   }
 
-  return hkdf_expand_label(out, SSL_get_session(hs->ssl)->ssl_version,
-                           hs->transcript.Digest(), hs->secret, hs->hash_len,
-                           label, label_len, context_hash, context_hash_len,
-                           len);
+  return hkdf_expand_label(out, hs->transcript.Digest(), hs->secret,
+                           hs->hash_len, label, label_len, context_hash,
+                           context_hash_len, len);
 }
 
 int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
@@ -165,16 +157,16 @@
   // Derive the key.
   size_t key_len = EVP_AEAD_key_length(aead);
   uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
-  if (!hkdf_expand_label(key, session->ssl_version, digest, traffic_secret,
-                         traffic_secret_len, "key", 3, NULL, 0, key_len)) {
+  if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, "key",
+                         3, NULL, 0, key_len)) {
     return 0;
   }
 
   // Derive the IV.
   size_t iv_len = EVP_AEAD_nonce_length(aead);
   uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
-  if (!hkdf_expand_label(iv, session->ssl_version, digest, traffic_secret,
-                         traffic_secret_len, "iv", 2, NULL, 0, iv_len)) {
+  if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, "iv",
+                         2, NULL, 0, iv_len)) {
     return 0;
   }
 
@@ -210,45 +202,26 @@
   return 1;
 }
 
-static const char kTLS13LabelExporter[] = "exporter master secret";
-static const char kTLS13LabelEarlyExporter[] = "early exporter master secret";
 
-static const char kTLS13LabelClientEarlyTraffic[] =
-    "client early traffic secret";
-static const char kTLS13LabelClientHandshakeTraffic[] =
-    "client handshake traffic secret";
-static const char kTLS13LabelServerHandshakeTraffic[] =
-    "server handshake traffic secret";
-static const char kTLS13LabelClientApplicationTraffic[] =
-    "client application traffic secret";
-static const char kTLS13LabelServerApplicationTraffic[] =
-    "server application traffic secret";
+static const char kTLS13LabelExporter[] = "exp master";
+static const char kTLS13LabelEarlyExporter[] = "e exp master";
 
-static const char kTLS13Draft22LabelExporter[] = "exp master";
-static const char kTLS13Draft22LabelEarlyExporter[] = "e exp master";
-
-static const char kTLS13Draft22LabelClientEarlyTraffic[] = "c e traffic";
-static const char kTLS13Draft22LabelClientHandshakeTraffic[] = "c hs traffic";
-static const char kTLS13Draft22LabelServerHandshakeTraffic[] = "s hs traffic";
-static const char kTLS13Draft22LabelClientApplicationTraffic[] = "c ap traffic";
-static const char kTLS13Draft22LabelServerApplicationTraffic[] = "s ap traffic";
+static const char kTLS13LabelClientEarlyTraffic[] = "c e traffic";
+static const char kTLS13LabelClientHandshakeTraffic[] = "c hs traffic";
+static const char kTLS13LabelServerHandshakeTraffic[] = "s hs traffic";
+static const char kTLS13LabelClientApplicationTraffic[] = "c ap traffic";
+static const char kTLS13LabelServerApplicationTraffic[] = "s ap traffic";
 
 int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  uint16_t version = SSL_get_session(ssl)->ssl_version;
-
-  const char *early_traffic_label = ssl_is_draft22(version)
-                                        ? kTLS13Draft22LabelClientEarlyTraffic
-                                        : kTLS13LabelClientEarlyTraffic;
-  const char *early_exporter_label = ssl_is_draft22(version)
-                                         ? kTLS13Draft22LabelEarlyExporter
-                                         : kTLS13LabelEarlyExporter;
   if (!derive_secret(hs, hs->early_traffic_secret, hs->hash_len,
-                     early_traffic_label, strlen(early_traffic_label)) ||
+                     kTLS13LabelClientEarlyTraffic,
+                     strlen(kTLS13LabelClientEarlyTraffic)) ||
       !ssl_log_secret(ssl, "CLIENT_EARLY_TRAFFIC_SECRET",
                       hs->early_traffic_secret, hs->hash_len) ||
       !derive_secret(hs, ssl->s3->early_exporter_secret, hs->hash_len,
-                     early_exporter_label, strlen(early_exporter_label))) {
+                     kTLS13LabelEarlyExporter,
+                     strlen(kTLS13LabelEarlyExporter))) {
     return 0;
   }
   ssl->s3->early_exporter_secret_len = hs->hash_len;
@@ -257,18 +230,14 @@
 
 int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  const char *client_label = ssl_is_draft22(ssl->version)
-                                 ? kTLS13Draft22LabelClientHandshakeTraffic
-                                 : kTLS13LabelClientHandshakeTraffic;
-  const char *server_label = ssl_is_draft22(ssl->version)
-                                 ? kTLS13Draft22LabelServerHandshakeTraffic
-                                 : kTLS13LabelServerHandshakeTraffic;
   return derive_secret(hs, hs->client_handshake_secret, hs->hash_len,
-                       client_label, strlen(client_label)) &&
+                       kTLS13LabelClientHandshakeTraffic,
+                       strlen(kTLS13LabelClientHandshakeTraffic)) &&
          ssl_log_secret(ssl, "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
                         hs->client_handshake_secret, hs->hash_len) &&
          derive_secret(hs, hs->server_handshake_secret, hs->hash_len,
-                       server_label, strlen(server_label)) &&
+                       kTLS13LabelServerHandshakeTraffic,
+                       strlen(kTLS13LabelServerHandshakeTraffic)) &&
          ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
                         hs->server_handshake_secret, hs->hash_len);
 }
@@ -276,32 +245,23 @@
 int tls13_derive_application_secrets(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
   ssl->s3->exporter_secret_len = hs->hash_len;
-  const char *client_label = ssl_is_draft22(ssl->version)
-                                 ? kTLS13Draft22LabelClientApplicationTraffic
-                                 : kTLS13LabelClientApplicationTraffic;
-  const char *server_label = ssl_is_draft22(ssl->version)
-                                 ? kTLS13Draft22LabelServerApplicationTraffic
-                                 : kTLS13LabelServerApplicationTraffic;
-  const char *exporter_label = ssl_is_draft22(ssl->version)
-                                   ? kTLS13Draft22LabelExporter
-                                   : kTLS13LabelExporter;
   return derive_secret(hs, hs->client_traffic_secret_0, hs->hash_len,
-                       client_label, strlen(client_label)) &&
+                       kTLS13LabelClientApplicationTraffic,
+                       strlen(kTLS13LabelClientApplicationTraffic)) &&
          ssl_log_secret(ssl, "CLIENT_TRAFFIC_SECRET_0",
                         hs->client_traffic_secret_0, hs->hash_len) &&
          derive_secret(hs, hs->server_traffic_secret_0, hs->hash_len,
-                       server_label, strlen(server_label)) &&
+                       kTLS13LabelServerApplicationTraffic,
+                       strlen(kTLS13LabelServerApplicationTraffic)) &&
          ssl_log_secret(ssl, "SERVER_TRAFFIC_SECRET_0",
                         hs->server_traffic_secret_0, hs->hash_len) &&
          derive_secret(hs, ssl->s3->exporter_secret, hs->hash_len,
-                       exporter_label, strlen(exporter_label)) &&
+                       kTLS13LabelExporter, strlen(kTLS13LabelExporter)) &&
          ssl_log_secret(ssl, "EXPORTER_SECRET", ssl->s3->exporter_secret,
                         hs->hash_len);
 }
 
-static const char kTLS13LabelApplicationTraffic[] =
-    "application traffic secret";
-static const char kTLS13Draft22LabelApplicationTraffic[] = "traffic upd";
+static const char kTLS13LabelApplicationTraffic[] = "traffic upd";
 
 int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
   uint8_t *secret;
@@ -314,35 +274,27 @@
     secret_len = ssl->s3->write_traffic_secret_len;
   }
 
-  const char *traffic_label = ssl_is_draft22(ssl->version)
-                                  ? kTLS13Draft22LabelApplicationTraffic
-                                  : kTLS13LabelApplicationTraffic;
-
   const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl));
-  if (!hkdf_expand_label(secret, ssl->version, digest, secret, secret_len,
-                         traffic_label, strlen(traffic_label), NULL, 0,
-                         secret_len)) {
+  if (!hkdf_expand_label(
+          secret, digest, secret, secret_len, kTLS13LabelApplicationTraffic,
+          strlen(kTLS13LabelApplicationTraffic), NULL, 0, secret_len)) {
     return 0;
   }
 
   return tls13_set_traffic_key(ssl, direction, secret, secret_len);
 }
 
-static const char kTLS13LabelResumption[] = "resumption master secret";
-static const char kTLS13Draft22LabelResumption[] = "res master";
+static const char kTLS13LabelResumption[] = "res master";
 
 int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs) {
   if (hs->hash_len > SSL_MAX_MASTER_KEY_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return 0;
   }
-  const char *resumption_label = ssl_is_draft22(hs->ssl->version)
-                                     ? kTLS13Draft22LabelResumption
-                                     : kTLS13LabelResumption;
   hs->new_session->master_key_length = hs->hash_len;
   return derive_secret(hs, hs->new_session->master_key,
-                       hs->new_session->master_key_length, resumption_label,
-                       strlen(resumption_label));
+                       hs->new_session->master_key_length,
+                       kTLS13LabelResumption, strlen(kTLS13LabelResumption));
 }
 
 static const char kTLS13LabelFinished[] = "finished";
@@ -355,9 +307,8 @@
                              uint8_t *context, size_t context_len) {
   uint8_t key[EVP_MAX_MD_SIZE];
   unsigned len;
-  if (!hkdf_expand_label(key, version, digest, secret, hash_len,
-                         kTLS13LabelFinished, strlen(kTLS13LabelFinished), NULL,
-                         0, hash_len) ||
+  if (!hkdf_expand_label(key, digest, secret, hash_len, kTLS13LabelFinished,
+                         strlen(kTLS13LabelFinished), NULL, 0, hash_len) ||
       HMAC(digest, key, hash_len, context, context_len, out, &len) == NULL) {
     return 0;
   }
@@ -388,14 +339,9 @@
 static const char kTLS13LabelResumptionPSK[] = "resumption";
 
 bool tls13_derive_session_psk(SSL_SESSION *session, Span<const uint8_t> nonce) {
-  if (!ssl_is_draft22(session->ssl_version)) {
-    return true;
-  }
-
   const EVP_MD *digest = ssl_session_get_digest(session);
-  return hkdf_expand_label(session->master_key, session->ssl_version, digest,
-                           session->master_key, session->master_key_length,
-                           kTLS13LabelResumptionPSK,
+  return hkdf_expand_label(session->master_key, digest, session->master_key,
+                           session->master_key_length, kTLS13LabelResumptionPSK,
                            strlen(kTLS13LabelResumptionPSK), nonce.data(),
                            nonce.size(), session->master_key_length);
 }
@@ -412,14 +358,6 @@
     return 0;
   }
 
-  uint16_t version = SSL_get_session(ssl)->ssl_version;
-  if (!ssl_is_draft22(version)) {
-    const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl));
-    return hkdf_expand_label(out.data(), version, digest, secret.data(),
-                             secret.size(), label.data(), label.size(),
-                             context.data(), context.size(), out.size());
-  }
-
   const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl));
 
   uint8_t hash[EVP_MAX_MD_SIZE];
@@ -432,18 +370,16 @@
                     nullptr) &&
          EVP_Digest(nullptr, 0, export_context, &export_context_len, digest,
                     nullptr) &&
-         hkdf_expand_label(derived_secret, version, digest, secret.data(),
-                           secret.size(), label.data(), label.size(),
-                           export_context, export_context_len,
-                           derived_secret_len) &&
-         hkdf_expand_label(out.data(), version, digest, derived_secret,
+         hkdf_expand_label(derived_secret, digest, secret.data(), secret.size(),
+                           label.data(), label.size(), export_context,
+                           export_context_len, derived_secret_len) &&
+         hkdf_expand_label(out.data(), digest, derived_secret,
                            derived_secret_len, kTLS13LabelExportKeying,
                            strlen(kTLS13LabelExportKeying), hash, hash_len,
                            out.size());
 }
 
-static const char kTLS13LabelPSKBinder[] = "resumption psk binder key";
-static const char kTLS13Draft22LabelPSKBinder[] = "res binder";
+static const char kTLS13LabelPSKBinder[] = "res binder";
 
 static int tls13_psk_binder(uint8_t *out, uint16_t version,
                             const EVP_MD *digest, uint8_t *psk, size_t psk_len,
@@ -461,15 +397,12 @@
                     NULL, 0)) {
     return 0;
   }
-  const char *binder_label = ssl_is_draft22(version)
-                                 ? kTLS13Draft22LabelPSKBinder
-                                 : kTLS13LabelPSKBinder;
 
   uint8_t binder_key[EVP_MAX_MD_SIZE] = {0};
   size_t len;
-  if (!hkdf_expand_label(binder_key, version, digest, early_secret, hash_len,
-                         binder_label, strlen(binder_label), binder_context,
-                         binder_context_len, hash_len) ||
+  if (!hkdf_expand_label(binder_key, digest, early_secret, hash_len,
+                         kTLS13LabelPSKBinder, strlen(kTLS13LabelPSKBinder),
+                         binder_context, binder_context_len, hash_len) ||
       !tls13_verify_data(digest, version, out, &len, binder_key, hash_len,
                          context, context_len)) {
     return 0;
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index a6a3a0a..3bd6786 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -63,15 +63,10 @@
   SSL *const ssl = hs->ssl;
   *out_need_retry = false;
 
-  uint16_t key_share_ext = TLSEXT_TYPE_old_key_share;
-  if (ssl_is_draft23(ssl->version)) {
-    key_share_ext = TLSEXT_TYPE_new_key_share;
-  }
-
   // We only support connections that include an ECDHE key exchange.
   CBS key_share;
   if (!ssl_client_hello_get_extension(client_hello, &key_share,
-                                      key_share_ext)) {
+                                      TLSEXT_TYPE_key_share)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
     return 0;
@@ -187,9 +182,8 @@
                                    SSL3_MT_NEW_SESSION_TICKET) ||
         !CBB_add_u32(&body, session->timeout) ||
         !CBB_add_u32(&body, session->ticket_age_add) ||
-        (ssl_is_draft22(ssl->version) &&
-         (!CBB_add_u8_length_prefixed(&body, &nonce_cbb) ||
-          !CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)))) ||
+        !CBB_add_u8_length_prefixed(&body, &nonce_cbb) ||
+        !CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)) ||
         !CBB_add_u16_length_prefixed(&body, &ticket) ||
         !tls13_derive_session_psk(session.get(), nonce) ||
         !ssl_encrypt_ticket(ssl, &ticket, session.get()) ||
@@ -199,9 +193,7 @@
 
     if (ssl->cert->enable_early_data) {
       CBB early_data_info;
-      if (!CBB_add_u16(&extensions, ssl_is_draft22(ssl->version)
-                                        ? TLSEXT_TYPE_early_data
-                                        : TLSEXT_TYPE_ticket_early_data_info) ||
+      if (!CBB_add_u16(&extensions, TLSEXT_TYPE_early_data) ||
           !CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
           !CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
           !CBB_flush(&extensions)) {
@@ -479,8 +471,7 @@
       ssl->s3->early_data_accepted = false;
       ssl->s3->skip_early_data = true;
       ssl->method->next_message(ssl);
-      if (ssl_is_draft22(ssl->version) &&
-          !hs->transcript.UpdateForHelloRetryRequest()) {
+      if (!hs->transcript.UpdateForHelloRetryRequest()) {
         return ssl_hs_error;
       }
       hs->tls13_state = state_send_hello_retry_request;
@@ -498,52 +489,30 @@
   SSL *const ssl = hs->ssl;
 
 
-  if (ssl_is_draft22(ssl->version)) {
-    ScopedCBB cbb;
-    CBB body, session_id, extensions;
-    uint16_t group_id;
-    if (!ssl->method->init_message(ssl, cbb.get(), &body,
-                                   SSL3_MT_SERVER_HELLO) ||
-        !CBB_add_u16(&body, TLS1_2_VERSION) ||
-        !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) ||
-        !CBB_add_u8_length_prefixed(&body, &session_id) ||
-        !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
-        !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
-        !CBB_add_u8(&body, 0 /* no compression */) ||
-        !tls1_get_shared_group(hs, &group_id) ||
-        !CBB_add_u16_length_prefixed(&body, &extensions) ||
-        !CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) ||
-        !CBB_add_u16(&extensions, 2 /* length */) ||
-        !CBB_add_u16(&extensions, ssl->version) ||
-        !CBB_add_u16(&extensions, ssl_is_draft23(ssl->version)
-                                      ? TLSEXT_TYPE_new_key_share
-                                      : TLSEXT_TYPE_old_key_share) ||
-        !CBB_add_u16(&extensions, 2 /* length */) ||
-        !CBB_add_u16(&extensions, group_id) ||
-        !ssl_add_message_cbb(ssl, cbb.get())) {
-      return ssl_hs_error;
-    }
+  ScopedCBB cbb;
+  CBB body, session_id, extensions;
+  uint16_t group_id;
+  if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
+      !CBB_add_u16(&body, TLS1_2_VERSION) ||
+      !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) ||
+      !CBB_add_u8_length_prefixed(&body, &session_id) ||
+      !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
+      !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
+      !CBB_add_u8(&body, 0 /* no compression */) ||
+      !tls1_get_shared_group(hs, &group_id) ||
+      !CBB_add_u16_length_prefixed(&body, &extensions) ||
+      !CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) ||
+      !CBB_add_u16(&extensions, 2 /* length */) ||
+      !CBB_add_u16(&extensions, ssl->version) ||
+      !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
+      !CBB_add_u16(&extensions, 2 /* length */) ||
+      !CBB_add_u16(&extensions, group_id) ||
+      !ssl_add_message_cbb(ssl, cbb.get())) {
+    return ssl_hs_error;
+  }
 
-    if (!ssl->method->add_change_cipher_spec(ssl)) {
-      return ssl_hs_error;
-    }
-  } else {
-    ScopedCBB cbb;
-    CBB body, extensions;
-    uint16_t group_id;
-    if (!ssl->method->init_message(ssl, cbb.get(), &body,
-                                   SSL3_MT_HELLO_RETRY_REQUEST) ||
-        !CBB_add_u16(&body, ssl->version) ||
-        (ssl_is_draft22(ssl->version) &&
-         !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher))) ||
-        !tls1_get_shared_group(hs, &group_id) ||
-        !CBB_add_u16_length_prefixed(&body, &extensions) ||
-        !CBB_add_u16(&extensions, TLSEXT_TYPE_old_key_share) ||
-        !CBB_add_u16(&extensions, 2 /* length */) ||
-        !CBB_add_u16(&extensions, group_id) ||
-        !ssl_add_message_cbb(ssl, cbb.get())) {
-      return ssl_hs_error;
-    }
+  if (!ssl->method->add_change_cipher_spec(ssl)) {
+    return ssl_hs_error;
   }
 
   hs->sent_hello_retry_request = true;
@@ -608,7 +577,7 @@
     return ssl_hs_error;
   }
 
-  if ((!ssl_is_draft22(ssl->version) || !hs->sent_hello_retry_request) &&
+  if (!hs->sent_hello_retry_request &&
       !ssl->method->add_change_cipher_spec(ssl)) {
     return ssl_hs_error;
   }
@@ -640,48 +609,34 @@
 
   // Send a CertificateRequest, if necessary.
   if (hs->cert_request) {
-    if (ssl_is_draft22(ssl->version)) {
-      CBB cert_request_extensions, sigalg_contents, sigalgs_cbb;
-      if (!ssl->method->init_message(ssl, cbb.get(), &body,
-                                     SSL3_MT_CERTIFICATE_REQUEST) ||
-          !CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
-          !CBB_add_u16_length_prefixed(&body, &cert_request_extensions) ||
-          !CBB_add_u16(&cert_request_extensions,
-                       TLSEXT_TYPE_signature_algorithms) ||
+    CBB cert_request_extensions, sigalg_contents, sigalgs_cbb;
+    if (!ssl->method->init_message(ssl, cbb.get(), &body,
+                                   SSL3_MT_CERTIFICATE_REQUEST) ||
+        !CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
+        !CBB_add_u16_length_prefixed(&body, &cert_request_extensions) ||
+        !CBB_add_u16(&cert_request_extensions,
+                     TLSEXT_TYPE_signature_algorithms) ||
+        !CBB_add_u16_length_prefixed(&cert_request_extensions,
+                                     &sigalg_contents) ||
+        !CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) ||
+        !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) {
+      return ssl_hs_error;
+    }
+
+    if (ssl_has_client_CAs(ssl)) {
+      CBB ca_contents;
+      if (!CBB_add_u16(&cert_request_extensions,
+                       TLSEXT_TYPE_certificate_authorities) ||
           !CBB_add_u16_length_prefixed(&cert_request_extensions,
-                                       &sigalg_contents) ||
-          !CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) ||
-          !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) {
+                                       &ca_contents) ||
+          !ssl_add_client_CA_list(ssl, &ca_contents) ||
+          !CBB_flush(&cert_request_extensions)) {
         return ssl_hs_error;
       }
+    }
 
-      if (ssl_has_client_CAs(ssl)) {
-        CBB ca_contents;
-        if (!CBB_add_u16(&cert_request_extensions,
-                         TLSEXT_TYPE_certificate_authorities) ||
-            !CBB_add_u16_length_prefixed(&cert_request_extensions,
-                                         &ca_contents) ||
-            !ssl_add_client_CA_list(ssl, &ca_contents) ||
-            !CBB_flush(&cert_request_extensions)) {
-          return ssl_hs_error;
-        }
-      }
-
-      if (!ssl_add_message_cbb(ssl, cbb.get())) {
-        return ssl_hs_error;
-      }
-    } else {
-      CBB sigalgs_cbb;
-      if (!ssl->method->init_message(ssl, cbb.get(), &body,
-                                     SSL3_MT_CERTIFICATE_REQUEST) ||
-          !CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
-          !CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
-          !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb) ||
-          !ssl_add_client_CA_list(ssl, &body) ||
-          !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
-          !ssl_add_message_cbb(ssl, cbb.get())) {
-        return ssl_hs_error;
-      }
+    if (!ssl_add_message_cbb(ssl, cbb.get())) {
+      return ssl_hs_error;
     }
   }
 
@@ -738,13 +693,11 @@
     // the wire sooner and also avoids triggering a write on |SSL_read| when
     // processing the client Finished. This requires computing the client
     // Finished early. See draft-ietf-tls-tls13-18, section 4.5.1.
-    if (ssl_is_draft22(ssl->version)) {
-      static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0,
-                                                 0, 0};
-      if (!hs->transcript.Update(kEndOfEarlyData)) {
-        OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-        return ssl_hs_error;
-      }
+    static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0,
+                                               0, 0};
+    if (!hs->transcript.Update(kEndOfEarlyData)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return ssl_hs_error;
     }
 
     size_t finished_len;
@@ -801,22 +754,20 @@
     // If early data was not accepted, the EndOfEarlyData and ChangeCipherSpec
     // message will be in the discarded early data.
     if (hs->ssl->s3->early_data_accepted) {
-      if (ssl_is_draft22(ssl->version)) {
-        SSLMessage msg;
-        if (!ssl->method->get_message(ssl, &msg)) {
-          return ssl_hs_read_message;
-        }
-
-        if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) {
-          return ssl_hs_error;
-        }
-        if (CBS_len(&msg.body) != 0) {
-          ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-          OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-          return ssl_hs_error;
-        }
-        ssl->method->next_message(ssl);
+      SSLMessage msg;
+      if (!ssl->method->get_message(ssl, &msg)) {
+        return ssl_hs_read_message;
       }
+
+      if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) {
+        return ssl_hs_error;
+      }
+      if (CBS_len(&msg.body) != 0) {
+        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+        return ssl_hs_error;
+      }
+      ssl->method->next_message(ssl);
     }
   }
   if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
diff --git a/ssl/tls_record.cc b/ssl/tls_record.cc
index 3d34951..05a3d56 100644
--- a/ssl/tls_record.cc
+++ b/ssl/tls_record.cc
@@ -356,15 +356,6 @@
   }
 
   if (type == SSL3_RT_ALERT) {
-    // Return end_of_early_data alerts as-is for the caller to process.
-    if (!ssl_is_draft22(ssl->version) &&
-        out->size() == 2 &&
-        (*out)[0] == SSL3_AL_WARNING &&
-        (*out)[1] == TLS1_AD_END_OF_EARLY_DATA) {
-      *out_type = type;
-      return ssl_open_record_success;
-    }
-
     return ssl_process_alert(ssl, out_alert, *out);
   }
 
diff --git a/tool/client.cc b/tool/client.cc
index de1a8ca..4162698 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -332,12 +332,8 @@
 }
 
 static bool GetTLS13Variant(tls13_variant_t *out, const std::string &in) {
-  if (in == "draft22") {
-    *out = tls13_draft22;
-    return true;
-  }
-  if (in == "experiment2") {
-    *out = tls13_experiment2;
+  if (in == "draft23") {
+    *out = tls13_default;
     return true;
   }
   return false;
diff --git a/tool/server.cc b/tool/server.cc
index 37235a7..896aa86 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_experiment2);
+    SSL_CTX_set_tls13_variant(ctx.get(), tls13_default);
   }
 
   if (args_map.count("-debug") != 0) {