Remove draft tokbind implementation.

We didn't end up deploying this. We also never implemented the final
RFC, so what we do have isn't useful for someone who wishes to deploy
it anyway.

Update-Note: Token binding APIs are removed.
Change-Id: Iecea7c3dcf9d3e2644a3b7afaf61511310b45d5f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47584
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 7a356f7..0d3d944 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -3019,33 +3019,6 @@
     SSL *ssl, EVP_PKEY **out_pkey);
 
 
-// Token Binding.
-//
-// See draft-ietf-tokbind-protocol-16.
-
-// SSL_set_token_binding_params sets |params| as the Token Binding Key
-// parameters (section 3 of draft-ietf-tokbind-protocol-16) to negotiate on the
-// connection. If this function is not called, or if |len| is 0, then this
-// endpoint will not attempt to negotiate Token Binding. |params| are provided
-// in preference order, with the more preferred parameters at the beginning of
-// the list. This function returns 1 on success and 0 on failure.
-OPENSSL_EXPORT int SSL_set_token_binding_params(SSL *ssl, const uint8_t *params,
-                                                size_t len);
-
-// SSL_is_token_binding_negotiated returns 1 if Token Binding was negotiated
-// on this connection and 0 otherwise. On a server, it is possible for this
-// function to return 1 when the client's view of the connection is that Token
-// Binding was not negotiated. This occurs when the server indicates a version
-// of Token Binding less than the client's minimum version.
-OPENSSL_EXPORT int SSL_is_token_binding_negotiated(const SSL *ssl);
-
-// SSL_get_negotiated_token_binding_param returns the TokenBindingKeyParameters
-// enum value that was negotiated. It is only valid to call this function if
-// SSL_is_token_binding_negotiated returned 1, otherwise this function returns
-// an undefined value.
-OPENSSL_EXPORT uint8_t SSL_get_negotiated_token_binding_param(const SSL *ssl);
-
-
 // DTLS-SRTP.
 //
 // See RFC 5764.
@@ -3570,8 +3543,7 @@
   ssl_early_data_alpn_mismatch = 9,
   // The connection negotiated Channel ID, which is incompatible with 0-RTT.
   ssl_early_data_channel_id = 10,
-  // The connection negotiated token binding, which is incompatible with 0-RTT.
-  ssl_early_data_token_binding = 11,
+  // Value 11 is reserved. (It has historically |ssl_early_data_token_binding|.)
   // The client and server ticket age were too far apart.
   ssl_early_data_ticket_age_skew = 12,
   // QUIC parameters differ between this connection and the original.
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 93a5a56..75dea96 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -203,9 +203,6 @@
 // ExtensionType value from RFC7627
 #define TLSEXT_TYPE_extended_master_secret 23
 
-// ExtensionType value from draft-ietf-tokbind-negotiation-10
-#define TLSEXT_TYPE_token_binding 24
-
 // ExtensionType value from draft-ietf-quic-tls. Drafts 00 through 32 use
 // 0xffa5 which is part of the Private Use section of the registry, and it
 // collides with TLS-LTS and, based on scans, something else too (though this
diff --git a/ssl/handoff.cc b/ssl/handoff.cc
index aededdb..3ac29c6 100644
--- a/ssl/handoff.cc
+++ b/ssl/handoff.cc
@@ -363,8 +363,10 @@
           hostname_len) ||
       !CBB_add_asn1_octet_string(&seq, s3->channel_id,
                                  sizeof(s3->channel_id)) ||
-      !CBB_add_asn1_bool(&seq, ssl->s3->token_binding_negotiated) ||
-      !CBB_add_asn1_uint64(&seq, ssl->s3->negotiated_token_binding_param) ||
+      // These two fields were historically |token_binding_negotiated| and
+      // |negotiated_token_binding_param|.
+      !CBB_add_asn1_bool(&seq, 0) ||
+      !CBB_add_asn1_uint64(&seq, 0) ||
       !CBB_add_asn1_bool(&seq, s3->hs->next_proto_neg_seen) ||
       !CBB_add_asn1_bool(&seq, s3->hs->cert_request) ||
       !CBB_add_asn1_bool(&seq, s3->hs->extended_master_secret) ||
@@ -443,12 +445,12 @@
   }
 
   SSL3_STATE *const s3 = ssl->s3;
-  uint64_t handback_version, negotiated_token_binding_param, cipher, type_u64;
+  uint64_t handback_version, unused_token_binding_param, cipher, type_u64;
 
   CBS seq, read_seq, write_seq, server_rand, client_rand, read_iv, write_iv,
       next_proto, alpn, hostname, channel_id, transcript, key_share;
   int session_reused, channel_id_valid, cert_request, extended_master_secret,
-      ticket_expected, token_binding_negotiated, next_proto_neg_seen;
+      ticket_expected, unused_token_binding, next_proto_neg_seen;
   SSL_SESSION *session = nullptr;
 
   CBS handback_cbs(handback);
@@ -499,8 +501,8 @@
       CBS_len(&channel_id) != sizeof(s3->channel_id) ||
       !CBS_copy_bytes(&channel_id, s3->channel_id,
                       sizeof(s3->channel_id)) ||
-      !CBS_get_asn1_bool(&seq, &token_binding_negotiated) ||
-      !CBS_get_asn1_uint64(&seq, &negotiated_token_binding_param) ||
+      !CBS_get_asn1_bool(&seq, &unused_token_binding) ||
+      !CBS_get_asn1_uint64(&seq, &unused_token_binding_param) ||
       !CBS_get_asn1_bool(&seq, &next_proto_neg_seen) ||
       !CBS_get_asn1_bool(&seq, &cert_request) ||
       !CBS_get_asn1_bool(&seq, &extended_master_secret) ||
@@ -629,9 +631,6 @@
     s3->hostname.reset(hostname_str);
   }
 
-  s3->token_binding_negotiated = token_binding_negotiated;
-  s3->negotiated_token_binding_param =
-      static_cast<uint8_t>(negotiated_token_binding_param);
   hs->next_proto_neg_seen = next_proto_neg_seen;
   hs->wait = ssl_hs_flush;
   hs->extended_master_secret = extended_master_secret;
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index 1a14c11..b12113b 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -768,13 +768,6 @@
     return ssl_hs_error;
   }
 
-  if (ssl->s3->token_binding_negotiated &&
-      (!hs->extended_master_secret || !ssl->s3->send_connection_binding)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI);
-    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
-    return ssl_hs_error;
-  }
-
   ssl->method->next_message(ssl);
 
   if (ssl->session != NULL) {
diff --git a/ssl/internal.h b/ssl/internal.h
index a753329..bfd2ab6 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1790,12 +1790,6 @@
   // peer_key is the peer's ECDH key for a TLS 1.2 client.
   Array<uint8_t> peer_key;
 
-  // negotiated_token_binding_version is used by a server to store the
-  // on-the-wire encoding of the Token Binding protocol version to advertise in
-  // the ServerHello/EncryptedExtensions if the Token Binding extension is to be
-  // sent.
-  uint16_t negotiated_token_binding_version;
-
   // cert_compression_alg_id, for a server, contains the negotiated certificate
   // compression algorithm for this client. It is only valid if
   // |cert_compression_negotiated| is true.
@@ -2535,10 +2529,6 @@
   // key_update_count is the number of consecutive KeyUpdates received.
   uint8_t key_update_count = 0;
 
-  // The negotiated Token Binding key parameter. Only valid if
-  // |token_binding_negotiated| is set.
-  uint8_t negotiated_token_binding_param = 0;
-
   // skip_early_data instructs the record layer to skip unexpected early data
   // messages when 0RTT is rejected.
   bool skip_early_data : 1;
@@ -2587,9 +2577,6 @@
   // early_data_accepted is true if early data was accepted by the server.
   bool early_data_accepted : 1;
 
-  // token_binding_negotiated is set if Token Binding was negotiated.
-  bool token_binding_negotiated : 1;
-
   // alert_dispatch is true there is an alert in |send_alert| to be sent.
   bool alert_dispatch : 1;
 
@@ -2883,9 +2870,6 @@
   // along with their corresponding ALPS values.
   GrowableArray<ALPSConfig> alps_configs;
 
-  // Contains a list of supported Token Binding key parameters.
-  Array<uint8_t> token_binding_params;
-
   // Contains the QUIC transport params that this endpoint will send.
   Array<uint8_t> quic_transport_params;
 
diff --git a/ssl/s3_lib.cc b/ssl/s3_lib.cc
index 3e12492..fa73d34 100644
--- a/ssl/s3_lib.cc
+++ b/ssl/s3_lib.cc
@@ -177,7 +177,6 @@
       key_update_pending(false),
       wpend_pending(false),
       early_data_accepted(false),
-      token_binding_negotiated(false),
       alert_dispatch(false),
       renegotiate_pending(false),
       used_hello_retry_request(false) {}
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 5f3614a..97eeb12 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -1316,8 +1316,6 @@
       return "alpn_mismatch";
     case ssl_early_data_channel_id:
       return "channel_id";
-    case ssl_early_data_token_binding:
-      return "token_binding";
     case ssl_early_data_ticket_age_skew:
       return "ticket_age_skew";
     case ssl_early_data_quic_parameter_mismatch:
@@ -2465,25 +2463,6 @@
   return 64;
 }
 
-int SSL_set_token_binding_params(SSL *ssl, const uint8_t *params, size_t len) {
-  if (!ssl->config) {
-    return 0;
-  }
-  if (len > 256) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-    return 0;
-  }
-  return ssl->config->token_binding_params.CopyFrom(MakeConstSpan(params, len));
-}
-
-int SSL_is_token_binding_negotiated(const SSL *ssl) {
-  return ssl->s3->token_binding_negotiated;
-}
-
-uint8_t SSL_get_negotiated_token_binding_param(const SSL *ssl) {
-  return ssl->s3->negotiated_token_binding_param;
-}
-
 size_t SSL_get0_certificate_types(const SSL *ssl, const uint8_t **out_types) {
   Span<const uint8_t> types;
   if (!ssl->server && ssl->s3->hs != nullptr) {
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index 689d75b..0a7ffb0 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -2649,153 +2649,6 @@
   return true;
 }
 
-// Token Binding
-//
-// https://tools.ietf.org/html/draft-ietf-tokbind-negotiation-10
-
-// The Token Binding version number currently matches the draft number of
-// draft-ietf-tokbind-protocol, and when published as an RFC it will be 0x0100.
-// Since there are no wire changes to the protocol from draft 13 through the
-// current draft (16), this implementation supports all versions in that range.
-static uint16_t kTokenBindingMaxVersion = 16;
-static uint16_t kTokenBindingMinVersion = 13;
-
-static bool ext_token_binding_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
-  SSL *const ssl = hs->ssl;
-  if (hs->config->token_binding_params.empty() || SSL_is_dtls(ssl)) {
-    return true;
-  }
-
-  CBB contents, params;
-  if (!CBB_add_u16(out, TLSEXT_TYPE_token_binding) ||
-      !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_u16(&contents, kTokenBindingMaxVersion) ||
-      !CBB_add_u8_length_prefixed(&contents, &params) ||
-      !CBB_add_bytes(&params, hs->config->token_binding_params.data(),
-                     hs->config->token_binding_params.size()) ||
-      !CBB_flush(out)) {
-    return false;
-  }
-
-  return true;
-}
-
-static bool ext_token_binding_parse_serverhello(SSL_HANDSHAKE *hs,
-                                                uint8_t *out_alert,
-                                                CBS *contents) {
-  SSL *const ssl = hs->ssl;
-  if (contents == nullptr) {
-    return true;
-  }
-
-  CBS params_list;
-  uint16_t version;
-  uint8_t param;
-  if (!CBS_get_u16(contents, &version) ||
-      !CBS_get_u8_length_prefixed(contents, &params_list) ||
-      !CBS_get_u8(&params_list, &param) ||
-      CBS_len(&params_list) > 0 ||
-      CBS_len(contents) > 0) {
-    *out_alert = SSL_AD_DECODE_ERROR;
-    return false;
-  }
-
-  // The server-negotiated version must be less than or equal to our version.
-  if (version > kTokenBindingMaxVersion) {
-    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
-    return false;
-  }
-
-  // If the server-selected version is less than what we support, then Token
-  // Binding wasn't negotiated (but the extension was parsed successfully).
-  if (version < kTokenBindingMinVersion) {
-    return true;
-  }
-
-  for (uint8_t config_param : hs->config->token_binding_params) {
-    if (param == config_param) {
-      ssl->s3->negotiated_token_binding_param = param;
-      ssl->s3->token_binding_negotiated = true;
-      return true;
-    }
-  }
-
-  *out_alert = SSL_AD_ILLEGAL_PARAMETER;
-  return false;
-}
-
-// select_tb_param looks for the first token binding param in
-// |hs->ssl->token_binding_params| that is also in |params| and puts it in
-// |hs->ssl->negotiated_token_binding_param|. It returns true if a token binding
-// param is found, and false otherwise.
-static bool select_tb_param(SSL_HANDSHAKE *hs,
-                            Span<const uint8_t> peer_params) {
-  for (uint8_t tb_param : hs->config->token_binding_params) {
-    for (uint8_t peer_param : peer_params) {
-      if (tb_param == peer_param) {
-        hs->ssl->s3->negotiated_token_binding_param = tb_param;
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-static bool ext_token_binding_parse_clienthello(SSL_HANDSHAKE *hs,
-                                                uint8_t *out_alert,
-                                                CBS *contents) {
-  SSL *const ssl = hs->ssl;
-  if (contents == nullptr || hs->config->token_binding_params.empty()) {
-    return true;
-  }
-
-  CBS params;
-  uint16_t version;
-  if (!CBS_get_u16(contents, &version) ||
-      !CBS_get_u8_length_prefixed(contents, &params) ||
-      CBS_len(&params) == 0 ||
-      CBS_len(contents) > 0) {
-    *out_alert = SSL_AD_DECODE_ERROR;
-    return false;
-  }
-
-  // If the client-selected version is less than what we support, then Token
-  // Binding wasn't negotiated (but the extension was parsed successfully).
-  if (version < kTokenBindingMinVersion) {
-    return true;
-  }
-
-  // If the client-selected version is higher than we support, use our max
-  // version. Otherwise, use the client's version.
-  hs->negotiated_token_binding_version =
-      std::min(version, kTokenBindingMaxVersion);
-  if (!select_tb_param(hs, params)) {
-    return true;
-  }
-
-  ssl->s3->token_binding_negotiated = true;
-  return true;
-}
-
-static bool ext_token_binding_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
-  SSL *const ssl = hs->ssl;
-
-  if (!ssl->s3->token_binding_negotiated) {
-    return true;
-  }
-
-  CBB contents, params;
-  if (!CBB_add_u16(out, TLSEXT_TYPE_token_binding) ||
-      !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_u16(&contents, hs->negotiated_token_binding_version) ||
-      !CBB_add_u8_length_prefixed(&contents, &params) ||
-      !CBB_add_u8(&params, ssl->s3->negotiated_token_binding_param) ||
-      !CBB_flush(out)) {
-    return false;
-  }
-
-  return true;
-}
 
 // QUIC Transport Parameters
 
@@ -3438,14 +3291,6 @@
     ext_quic_transport_params_add_serverhello_legacy,
   },
   {
-    TLSEXT_TYPE_token_binding,
-    NULL,
-    ext_token_binding_add_clienthello,
-    ext_token_binding_parse_serverhello,
-    ext_token_binding_parse_clienthello,
-    ext_token_binding_add_serverhello,
-  },
-  {
     TLSEXT_TYPE_cert_compression,
     NULL,
     cert_compression_add_clienthello,
@@ -3829,18 +3674,8 @@
 
 static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-
-  if (ssl->s3->token_binding_negotiated &&
-      !(SSL_get_secure_renegotiation_support(ssl) &&
-        SSL_get_extms_support(ssl))) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI);
-    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
-    return false;
-  }
-
   int ret = SSL_TLSEXT_ERR_NOACK;
   int al = SSL_AD_UNRECOGNIZED_NAME;
-
   if (ssl->ctx->servername_callback != 0) {
     ret = ssl->ctx->servername_callback(ssl, &al, ssl->ctx->servername_arg);
   } else if (ssl->session_ctx->servername_callback != 0) {
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 9438c1f..d4b5626 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -546,18 +546,6 @@
     }
   }
 
-  if (config->expect_token_binding_param != -1) {
-    if (!SSL_is_token_binding_negotiated(ssl)) {
-      fprintf(stderr, "no Token Binding negotiated\n");
-      return false;
-    }
-    if (SSL_get_negotiated_token_binding_param(ssl) !=
-        static_cast<uint8_t>(config->expect_token_binding_param)) {
-      fprintf(stderr, "Token Binding param mismatch\n");
-      return false;
-    }
-  }
-
   if (config->expect_extended_master_secret && !SSL_get_extms_support(ssl)) {
     fprintf(stderr, "No EMS for connection when expected\n");
     return false;
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 9ca2b34..13c077b 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -109,7 +109,6 @@
 	extensionSignedCertificateTimestamp uint16 = 18
 	extensionPadding                    uint16 = 21
 	extensionExtendedMasterSecret       uint16 = 23
-	extensionTokenBinding               uint16 = 24
 	extensionCompressedCertAlgs         uint16 = 27
 	extensionSessionTicket              uint16 = 35
 	extensionPreSharedKey               uint16 = 41
@@ -258,8 +257,6 @@
 	VerifiedChains             [][]*x509.Certificate // verified chains built from PeerCertificates
 	OCSPResponse               []byte                // stapled OCSP response from the peer, if any
 	ChannelID                  *ecdsa.PublicKey      // the channel ID for this connection
-	TokenBindingNegotiated     bool                  // whether Token Binding was negotiated
-	TokenBindingParam          uint8                 // the negotiated Token Binding key parameter
 	SRTPProtectionProfile      uint16                // the negotiated DTLS-SRTP protection profile
 	TLSUnique                  []byte                // the tls-unique channel binding
 	SCTList                    []byte                // signed certificate timestamp list
@@ -521,20 +518,6 @@
 	// returned in the ConnectionState.
 	RequestChannelID bool
 
-	// TokenBindingParams contains a list of TokenBindingKeyParameters
-	// (draft-ietf-tokbind-protocol-16) to attempt to negotiate. If
-	// nil, Token Binding will not be negotiated.
-	TokenBindingParams []byte
-
-	// TokenBindingVersion contains the serialized ProtocolVersion to
-	// use when negotiating Token Binding.
-	TokenBindingVersion uint16
-
-	// ExpectTokenBindingParams is checked by a server that the client
-	// sent ExpectTokenBindingParams as its list of Token Binding
-	// paramters.
-	ExpectTokenBindingParams []byte
-
 	// PreSharedKey, if not nil, is the pre-shared key to use with
 	// the PSK cipher suites.
 	PreSharedKey []byte
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 4932a0b..ad77b66 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -83,9 +83,6 @@
 
 	channelID *ecdsa.PublicKey
 
-	tokenBindingNegotiated bool
-	tokenBindingParam      uint8
-
 	srtpProtectionProfile uint16
 
 	clientVersion uint16
@@ -1852,8 +1849,6 @@
 		state.OCSPResponse = c.ocspResponse
 		state.ServerName = c.serverName
 		state.ChannelID = c.channelID
-		state.TokenBindingNegotiated = c.tokenBindingNegotiated
-		state.TokenBindingParam = c.tokenBindingParam
 		state.SRTPProtectionProfile = c.srtpProtectionProfile
 		state.TLSUnique = c.firstFinished[:]
 		state.SCTList = c.sctList
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index b58a313..17aa9c6 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -513,8 +513,6 @@
 		quicTransportParamsLegacy: quicTransportParamsLegacy,
 		duplicateExtension:        c.config.Bugs.DuplicateExtension,
 		channelIDSupported:        c.config.ChannelID != nil,
-		tokenBindingParams:        c.config.TokenBindingParams,
-		tokenBindingVersion:       c.config.TokenBindingVersion,
 		extendedMasterSecret:      maxVersion >= VersionTLS10,
 		srtpProtectionProfiles:    c.config.SRTPProtectionProfiles,
 		srtpMasterKeyIdentifier:   c.config.Bugs.SRTPMasterKeyIdentifer,
@@ -1924,29 +1922,6 @@
 		return errors.New("server advertised unrequested Channel ID extension")
 	}
 
-	if len(serverExtensions.tokenBindingParams) == 1 {
-		found := false
-		for _, p := range c.config.TokenBindingParams {
-			if p == serverExtensions.tokenBindingParams[0] {
-				c.tokenBindingParam = p
-				found = true
-				break
-			}
-		}
-		if !found {
-			return errors.New("tls: server advertised unsupported Token Binding key param")
-		}
-		if serverExtensions.tokenBindingVersion > c.config.TokenBindingVersion {
-			return errors.New("tls: server's Token Binding version is too new")
-		}
-		if c.vers < VersionTLS13 {
-			if !serverExtensions.extendedMasterSecret || serverExtensions.secureRenegotiation == nil {
-				return errors.New("server sent Token Binding without EMS or RI")
-			}
-		}
-		c.tokenBindingNegotiated = true
-	}
-
 	if serverExtensions.extendedMasterSecret && c.vers >= VersionTLS13 {
 		return errors.New("tls: server advertised extended master secret over TLS 1.3")
 	}
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 9156f80..15c92c8 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -344,8 +344,6 @@
 	quicTransportParamsLegacy []byte
 	duplicateExtension        bool
 	channelIDSupported        bool
-	tokenBindingParams        []byte
-	tokenBindingVersion       uint16
 	extendedMasterSecret      bool
 	srtpProtectionProfiles    []uint16
 	srtpMasterKeyIdentifier   string
@@ -612,16 +610,6 @@
 	if m.channelIDSupported {
 		extensions = append(extensions, extension{id: extensionChannelID})
 	}
-	if m.tokenBindingParams != nil {
-		tokbindExtension := newByteBuilder()
-		tokbindExtension.addU16(m.tokenBindingVersion)
-		tokbindParams := tokbindExtension.addU8LengthPrefixed()
-		tokbindParams.addBytes(m.tokenBindingParams)
-		extensions = append(extensions, extension{
-			id:   extensionTokenBinding,
-			body: tokbindExtension.finish(),
-		})
-	}
 	if m.duplicateExtension {
 		// Add a duplicate bogus extension at the beginning and end.
 		extensions = append(extensions, extension{id: extensionDuplicate})
@@ -1073,12 +1061,6 @@
 				return false
 			}
 			m.channelIDSupported = true
-		case extensionTokenBinding:
-			if !body.readU16(&m.tokenBindingVersion) ||
-				!body.readU8LengthPrefixedBytes(&m.tokenBindingParams) ||
-				len(body) != 0 {
-				return false
-			}
 		case extensionExtendedMasterSecret:
 			if len(body) != 0 {
 				return false
@@ -1420,8 +1402,6 @@
 	alpnProtocolEmpty         bool
 	duplicateExtension        bool
 	channelIDRequested        bool
-	tokenBindingParams        []byte
-	tokenBindingVersion       uint16
 	extendedMasterSecret      bool
 	srtpProtectionProfile     uint16
 	srtpMasterKeyIdentifier   string
@@ -1486,13 +1466,6 @@
 		extensions.addU16(extensionChannelID)
 		extensions.addU16(0)
 	}
-	if m.tokenBindingParams != nil {
-		extensions.addU16(extensionTokenBinding)
-		tokbindExtension := extensions.addU16LengthPrefixed()
-		tokbindExtension.addU16(m.tokenBindingVersion)
-		tokbindParams := tokbindExtension.addU8LengthPrefixed()
-		tokbindParams.addBytes(m.tokenBindingParams)
-	}
 	if m.duplicateExtension {
 		// Add a duplicate bogus extension at the beginning and end.
 		extensions.addU16(extensionDuplicate)
@@ -1643,13 +1616,6 @@
 				return false
 			}
 			m.channelIDRequested = true
-		case extensionTokenBinding:
-			if !body.readU16(&m.tokenBindingVersion) ||
-				!body.readU8LengthPrefixedBytes(&m.tokenBindingParams) ||
-				len(m.tokenBindingParams) != 1 ||
-				len(body) != 0 {
-				return false
-			}
 		case extensionExtendedMasterSecret:
 			if len(body) != 0 {
 				return false
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index ecc4078..a1a248c 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -1481,21 +1481,6 @@
 		serverExtensions.channelIDRequested = true
 	}
 
-	if config.TokenBindingParams != nil {
-		if !bytes.Equal(config.ExpectTokenBindingParams, hs.clientHello.tokenBindingParams) {
-			return errors.New("client did not send expected token binding params")
-		}
-
-		// For testing, blindly send whatever is set in config, even if
-		// it is invalid.
-		serverExtensions.tokenBindingParams = config.TokenBindingParams
-		serverExtensions.tokenBindingVersion = config.TokenBindingVersion
-	}
-
-	if c.vers < VersionTLS13 && len(hs.clientHello.tokenBindingParams) > 0 && (!hs.clientHello.extendedMasterSecret || hs.clientHello.secureRenegotiation == nil) {
-		return errors.New("client sent Token Binding without EMS and/or RI")
-	}
-
 	if hs.clientHello.srtpProtectionProfiles != nil {
 	SRTPLoop:
 		for _, p1 := range c.config.SRTPProtectionProfiles {
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index f802585..0f7c628 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -518,12 +518,6 @@
 	// channelID controls whether the connection should have negotiated a
 	// Channel ID with channelIDKey.
 	channelID bool
-	// tokenBinding controls whether the connection should have negotiated Token
-	// Binding.
-	tokenBinding bool
-	// tokenBindingParam is the Token Binding parameter that should have been
-	// negotiated (if tokenBinding is true).
-	tokenBindingParam uint8
 	// nextProto controls whether the connection should negotiate a next
 	// protocol via NPN or ALPN.
 	nextProto string
@@ -907,17 +901,6 @@
 		return fmt.Errorf("channel ID unexpectedly negotiated")
 	}
 
-	if expectations.tokenBinding {
-		if !connState.TokenBindingNegotiated {
-			return errors.New("no Token Binding negotiated")
-		}
-		if connState.TokenBindingParam != expectations.tokenBindingParam {
-			return fmt.Errorf("expected param %02x, but got %02x", expectations.tokenBindingParam, connState.TokenBindingParam)
-		}
-	} else if connState.TokenBindingNegotiated {
-		return errors.New("Token Binding unexpectedly negotiated")
-	}
-
 	if expected := expectations.nextProto; expected != "" {
 		if actual := connState.NegotiatedProtocol; actual != expected {
 			return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
@@ -7697,411 +7680,6 @@
 				})
 			}
 
-			// Test Token Binding.
-			if protocol != dtls {
-				const maxTokenBindingVersion = 16
-				const minTokenBindingVersion = 13
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TokenBinding-Server-" + suffix,
-
-					config: Config{
-						MinVersion:          ver.version,
-						MaxVersion:          ver.version,
-						TokenBindingParams:  []byte{0, 1, 2},
-						TokenBindingVersion: maxTokenBindingVersion,
-					},
-					expectations: connectionExpectations{
-						tokenBinding:      true,
-						tokenBindingParam: 2,
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-						"-expect-token-binding-param",
-						"2",
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TokenBinding-Server-UnsupportedParam-" + suffix,
-
-					config: Config{
-						MinVersion:          ver.version,
-						MaxVersion:          ver.version,
-						TokenBindingParams:  []byte{3},
-						TokenBindingVersion: maxTokenBindingVersion,
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TokenBinding-Server-OldVersion-" + suffix,
-
-					config: Config{
-						MinVersion:          ver.version,
-						MaxVersion:          ver.version,
-						TokenBindingParams:  []byte{0, 1, 2},
-						TokenBindingVersion: minTokenBindingVersion - 1,
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TokenBinding-Server-NewVersion-" + suffix,
-
-					config: Config{
-						MinVersion:          ver.version,
-						MaxVersion:          ver.version,
-						TokenBindingParams:  []byte{0, 1, 2},
-						TokenBindingVersion: maxTokenBindingVersion + 1,
-					},
-					expectations: connectionExpectations{
-						tokenBinding:      true,
-						tokenBindingParam: 2,
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-						"-expect-token-binding-param",
-						"2",
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TokenBinding-Server-NoParams-" + suffix,
-
-					config: Config{
-						MinVersion:          ver.version,
-						MaxVersion:          ver.version,
-						TokenBindingParams:  []byte{},
-						TokenBindingVersion: maxTokenBindingVersion,
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-					},
-					shouldFail:    true,
-					expectedError: ":ERROR_PARSING_EXTENSION:",
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: serverTest,
-					name:     "TokenBinding-Server-RepeatedParam" + suffix,
-
-					config: Config{
-						MinVersion:          ver.version,
-						MaxVersion:          ver.version,
-						TokenBindingParams:  []byte{0, 1, 2, 2},
-						TokenBindingVersion: maxTokenBindingVersion,
-					},
-					expectations: connectionExpectations{
-						tokenBinding:      true,
-						tokenBindingParam: 2,
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-						"-expect-token-binding-param",
-						"2",
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "TokenBinding-Client-" + suffix,
-
-					config: Config{
-						MinVersion:               ver.version,
-						MaxVersion:               ver.version,
-						TokenBindingParams:       []byte{2},
-						TokenBindingVersion:      maxTokenBindingVersion,
-						ExpectTokenBindingParams: []byte{0, 1, 2},
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
-						"-expect-token-binding-param",
-						"2",
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "TokenBinding-Client-Unexpected-" + suffix,
-
-					config: Config{
-						MinVersion:          ver.version,
-						MaxVersion:          ver.version,
-						TokenBindingParams:  []byte{2},
-						TokenBindingVersion: maxTokenBindingVersion,
-					},
-					shouldFail:    true,
-					expectedError: ":UNEXPECTED_EXTENSION:",
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "TokenBinding-Client-ExtraParams-" + suffix,
-
-					config: Config{
-						MinVersion:               ver.version,
-						MaxVersion:               ver.version,
-						TokenBindingParams:       []byte{2, 1},
-						TokenBindingVersion:      maxTokenBindingVersion,
-						ExpectTokenBindingParams: []byte{0, 1, 2},
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
-						"-expect-token-binding-param",
-						"2",
-					},
-					shouldFail:    true,
-					expectedError: ":ERROR_PARSING_EXTENSION:",
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "TokenBinding-Client-NoParams-" + suffix,
-
-					config: Config{
-						MinVersion:               ver.version,
-						MaxVersion:               ver.version,
-						TokenBindingParams:       []byte{},
-						TokenBindingVersion:      maxTokenBindingVersion,
-						ExpectTokenBindingParams: []byte{0, 1, 2},
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
-						"-expect-token-binding-param",
-						"2",
-					},
-					shouldFail:    true,
-					expectedError: ":ERROR_PARSING_EXTENSION:",
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "TokenBinding-Client-WrongParam-" + suffix,
-
-					config: Config{
-						MinVersion:               ver.version,
-						MaxVersion:               ver.version,
-						TokenBindingParams:       []byte{3},
-						TokenBindingVersion:      maxTokenBindingVersion,
-						ExpectTokenBindingParams: []byte{0, 1, 2},
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
-						"-expect-token-binding-param",
-						"2",
-					},
-					shouldFail:    true,
-					expectedError: ":ERROR_PARSING_EXTENSION:",
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "TokenBinding-Client-OldVersion-" + suffix,
-
-					config: Config{
-						MinVersion:               ver.version,
-						MaxVersion:               ver.version,
-						TokenBindingParams:       []byte{2},
-						TokenBindingVersion:      minTokenBindingVersion - 1,
-						ExpectTokenBindingParams: []byte{0, 1, 2},
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "TokenBinding-Client-MinVersion-" + suffix,
-
-					config: Config{
-						MinVersion:               ver.version,
-						MaxVersion:               ver.version,
-						TokenBindingParams:       []byte{2},
-						TokenBindingVersion:      minTokenBindingVersion,
-						ExpectTokenBindingParams: []byte{0, 1, 2},
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
-						"-expect-token-binding-param",
-						"2",
-					},
-				})
-				testCases = append(testCases, testCase{
-					protocol: protocol,
-					testType: clientTest,
-					name:     "TokenBinding-Client-VersionTooNew-" + suffix,
-
-					config: Config{
-						MinVersion:               ver.version,
-						MaxVersion:               ver.version,
-						TokenBindingParams:       []byte{2},
-						TokenBindingVersion:      maxTokenBindingVersion + 1,
-						ExpectTokenBindingParams: []byte{0, 1, 2},
-					},
-					flags: []string{
-						"-token-binding-params",
-						base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
-					},
-					shouldFail:    true,
-					expectedError: "ERROR_PARSING_EXTENSION",
-				})
-				if ver.version < VersionTLS13 {
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: clientTest,
-						name:     "TokenBinding-Client-NoEMS-" + suffix,
-
-						config: Config{
-							MinVersion:               ver.version,
-							MaxVersion:               ver.version,
-							TokenBindingParams:       []byte{2},
-							TokenBindingVersion:      maxTokenBindingVersion,
-							ExpectTokenBindingParams: []byte{2, 1, 0},
-							Bugs: ProtocolBugs{
-								NoExtendedMasterSecret: true,
-							},
-						},
-						flags: []string{
-							"-token-binding-params",
-							base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-						},
-						shouldFail:    true,
-						expectedError: ":NEGOTIATED_TB_WITHOUT_EMS_OR_RI:",
-					})
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: serverTest,
-						name:     "TokenBinding-Server-NoEMS-" + suffix,
-
-						config: Config{
-							MinVersion:          ver.version,
-							MaxVersion:          ver.version,
-							TokenBindingParams:  []byte{0, 1, 2},
-							TokenBindingVersion: maxTokenBindingVersion,
-							Bugs: ProtocolBugs{
-								NoExtendedMasterSecret: true,
-							},
-						},
-						flags: []string{
-							"-token-binding-params",
-							base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-						},
-						shouldFail:    true,
-						expectedError: ":NEGOTIATED_TB_WITHOUT_EMS_OR_RI:",
-					})
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: clientTest,
-						name:     "TokenBinding-Client-NoRI-" + suffix,
-
-						config: Config{
-							MinVersion:               ver.version,
-							MaxVersion:               ver.version,
-							TokenBindingParams:       []byte{2},
-							TokenBindingVersion:      maxTokenBindingVersion,
-							ExpectTokenBindingParams: []byte{2, 1, 0},
-							Bugs: ProtocolBugs{
-								NoRenegotiationInfo: true,
-							},
-						},
-						flags: []string{
-							"-token-binding-params",
-							base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-						},
-						shouldFail:    true,
-						expectedError: ":NEGOTIATED_TB_WITHOUT_EMS_OR_RI:",
-					})
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: serverTest,
-						name:     "TokenBinding-Server-NoRI-" + suffix,
-
-						config: Config{
-							MinVersion:          ver.version,
-							MaxVersion:          ver.version,
-							TokenBindingParams:  []byte{0, 1, 2},
-							TokenBindingVersion: maxTokenBindingVersion,
-							Bugs: ProtocolBugs{
-								NoRenegotiationInfo: true,
-							},
-						},
-						flags: []string{
-							"-token-binding-params",
-							base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-						},
-						shouldFail:    true,
-						expectedError: ":NEGOTIATED_TB_WITHOUT_EMS_OR_RI:",
-					})
-				} else {
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: clientTest,
-						name:     "TokenBinding-WithEarlyDataFails-" + suffix,
-						config: Config{
-							MinVersion:               ver.version,
-							MaxVersion:               ver.version,
-							TokenBindingParams:       []byte{2},
-							TokenBindingVersion:      maxTokenBindingVersion,
-							ExpectTokenBindingParams: []byte{2, 1, 0},
-						},
-						resumeSession: true,
-						earlyData:     true,
-						flags: []string{
-							"-token-binding-params",
-							base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-						},
-						shouldFail:    true,
-						expectedError: ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
-					})
-					testCases = append(testCases, testCase{
-						protocol: protocol,
-						testType: serverTest,
-						name:     "TokenBinding-EarlyDataRejected-" + suffix,
-						config: Config{
-							MinVersion:          ver.version,
-							MaxVersion:          ver.version,
-							TokenBindingParams:  []byte{0, 1, 2},
-							TokenBindingVersion: maxTokenBindingVersion,
-						},
-						resumeSession:           true,
-						earlyData:               true,
-						expectEarlyDataRejected: true,
-						expectations: connectionExpectations{
-							tokenBinding:      true,
-							tokenBindingParam: 2,
-						},
-						flags: []string{
-							"-token-binding-params",
-							base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
-							"-on-retry-expect-early-data-reason", "token_binding",
-						},
-					})
-				}
-			}
-
 			// Test QUIC transport params
 			if protocol == quic {
 				// Client sends params
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index e933f0f..47fac65 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -200,7 +200,6 @@
 const Flag<std::string> kBase64Flags[] = {
     {"-expect-certificate-types", &TestConfig::expect_certificate_types},
     {"-expect-channel-id", &TestConfig::expect_channel_id},
-    {"-token-binding-params", &TestConfig::send_token_binding_params},
     {"-expect-ocsp-response", &TestConfig::expect_ocsp_response},
     {"-expect-signed-cert-timestamps",
      &TestConfig::expect_signed_cert_timestamps},
@@ -215,7 +214,6 @@
 const Flag<int> kIntFlags[] = {
     {"-port", &TestConfig::port},
     {"-resume-count", &TestConfig::resume_count},
-    {"-expect-token-binding-param", &TestConfig::expect_token_binding_param},
     {"-min-version", &TestConfig::min_version},
     {"-max-version", &TestConfig::max_version},
     {"-expect-version", &TestConfig::expect_version},
@@ -1738,12 +1736,6 @@
       }
     }
   }
-  if (!send_token_binding_params.empty()) {
-    SSL_set_token_binding_params(
-        ssl.get(),
-        reinterpret_cast<const uint8_t *>(send_token_binding_params.data()),
-        send_token_binding_params.length());
-  }
   if (!host_name.empty() &&
       !SSL_set_tlsext_host_name(ssl.get(), host_name.c_str())) {
     return nullptr;
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index f4ddba2..4a65abf 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -61,8 +61,6 @@
   std::string expect_channel_id;
   bool enable_channel_id = false;
   std::string send_channel_id;
-  int expect_token_binding_param = -1;
-  std::string send_token_binding_params;
   bool shim_writes_first = false;
   std::string host_name;
   std::string advertise_alpn;
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc
index 0fd6567..b4d56ea 100644
--- a/ssl/tls13_client.cc
+++ b/ssl/tls13_client.cc
@@ -501,9 +501,9 @@
       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
       return ssl_hs_error;
     }
-    // Channel ID and Token Binding are incompatible with 0-RTT. The ALPS
-    // extension should be negotiated implicitly.
-    if (ssl->s3->channel_id_valid || ssl->s3->token_binding_negotiated ||
+    // Channel ID is incompatible with 0-RTT. The ALPS extension should be
+    // negotiated implicitly.
+    if (ssl->s3->channel_id_valid ||
         hs->new_session->has_application_settings) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION_ON_EARLY_DATA);
       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index ba7b4cf..f3f4853 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -448,9 +448,6 @@
   } else if (ssl->s3->channel_id_valid) {
     // Channel ID is incompatible with 0-RTT.
     ssl->s3->early_data_reason = ssl_early_data_channel_id;
-  } else if (ssl->s3->token_binding_negotiated) {
-    // Token Binding is incompatible with 0-RTT.
-    ssl->s3->early_data_reason = ssl_early_data_token_binding;
   } else if (MakeConstSpan(ssl->s3->alpn_selected) != session->early_alpn) {
     // The negotiated ALPN must match the one in the ticket.
     ssl->s3->early_data_reason = ssl_early_data_alpn_mismatch;