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>
chromium-5359
David Benjamin 4 years ago committed by Adam Langley
parent aaecb82c6b
commit d89ec688f2
  1. 30
      include/openssl/ssl.h
  2. 3
      include/openssl/tls1.h
  3. 17
      ssl/handoff.cc
  4. 7
      ssl/handshake_client.cc
  5. 16
      ssl/internal.h
  6. 1
      ssl/s3_lib.cc
  7. 21
      ssl/ssl_lib.cc
  8. 165
      ssl/t1_lib.cc
  9. 12
      ssl/test/bssl_shim.cc
  10. 17
      ssl/test/runner/common.go
  11. 5
      ssl/test/runner/conn.go
  12. 25
      ssl/test/runner/handshake_client.go
  13. 34
      ssl/test/runner/handshake_messages.go
  14. 15
      ssl/test/runner/handshake_server.go
  15. 422
      ssl/test/runner/runner.go
  16. 8
      ssl/test/test_config.cc
  17. 2
      ssl/test/test_config.h
  18. 6
      ssl/tls13_client.cc
  19. 3
      ssl/tls13_server.cc

@ -3019,33 +3019,6 @@ OPENSSL_EXPORT void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(
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 @@ enum ssl_early_data_reason_t BORINGSSL_ENUM_INT {
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.

@ -203,9 +203,6 @@ extern "C" {
// 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

@ -363,8 +363,10 @@ bool SSL_serialize_handback(const SSL *ssl, CBB *out) {
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 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) {
}
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 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) {
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 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) {
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;

@ -768,13 +768,6 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
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) {

@ -1790,12 +1790,6 @@ struct SSL_HANDSHAKE {
// 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 @@ struct SSL3_STATE {
// 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 @@ struct SSL3_STATE {
// 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 @@ struct SSL_CONFIG {
// 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;

@ -177,7 +177,6 @@ SSL3_STATE::SSL3_STATE()
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) {}

@ -1316,8 +1316,6 @@ const char *SSL_early_data_reason_string(enum ssl_early_data_reason_t reason) {
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 @@ size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, size_t max_out) {
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) {

@ -2649,153 +2649,6 @@ static bool ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
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
@ -3437,14 +3290,6 @@ static const struct tls_extension kExtensions[] = {
ext_quic_transport_params_parse_clienthello_legacy,
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,
@ -3829,18 +3674,8 @@ static bool ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs,
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) {

@ -546,18 +546,6 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
}
}
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;

@ -109,7 +109,6 @@ const (
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 @@ type ConnectionState struct {
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 @@ type Config struct {
// 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

@ -83,9 +83,6 @@ type Conn struct {
channelID *ecdsa.PublicKey
tokenBindingNegotiated bool
tokenBindingParam uint8
srtpProtectionProfile uint16
clientVersion uint16
@ -1852,8 +1849,6 @@ func (c *Conn) ConnectionState() ConnectionState {
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

@ -513,8 +513,6 @@ func (hs *clientHandshakeState) createClientHello(innerHello *clientHelloMsg, ec
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 @@ func (hs *clientHandshakeState) processServerExtensions(serverExtensions *server
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")
}

@ -344,8 +344,6 @@ type clientHelloMsg struct {
quicTransportParamsLegacy []byte
duplicateExtension bool
channelIDSupported bool
tokenBindingParams []byte
tokenBindingVersion uint16
extendedMasterSecret bool
srtpProtectionProfiles []uint16
srtpMasterKeyIdentifier string
@ -612,16 +610,6 @@ func (m *clientHelloMsg) marshalBody(hello *byteBuilder, typ clientHelloType) {
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 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
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 @@ type serverExtensions struct {
alpnProtocolEmpty bool
duplicateExtension bool
channelIDRequested bool
tokenBindingParams []byte
tokenBindingVersion uint16
extendedMasterSecret bool
srtpProtectionProfile uint16
srtpMasterKeyIdentifier string
@ -1486,13 +1466,6 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) {
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 @@ func (m *serverExtensions) unmarshal(data byteReader, version uint16) bool {
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

@ -1481,21 +1481,6 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
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 {

@ -518,12 +518,6 @@ type connectionExpectations struct {
// 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 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, tr
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 @@ func addExtensionTests() {
})
}
// 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

@ -200,7 +200,6 @@ const Flag<std::unique_ptr<std::string>> kOptionalStringFlags[] = {
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<std::string> kBase64Flags[] = {
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 @@ bssl::UniquePtr<SSL> TestConfig::NewSSL(
}
}
}
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;

@ -61,8 +61,6 @@ struct TestConfig {
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;

@ -501,9 +501,9 @@ static enum ssl_hs_wait_t do_read_encrypted_extensions(SSL_HANDSHAKE *hs) {
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);

@ -448,9 +448,6 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
} 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;

Loading…
Cancel
Save