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>
This commit is contained in:
Steven Valdez 2018-01-22 15:20:31 -05:00 committed by CQ bot account: commit-bot@chromium.org
parent 3c034b2cf3
commit 7e5dd25d47
21 changed files with 524 additions and 1079 deletions

View File

@ -593,9 +593,7 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl);
#define DTLS1_VERSION 0xfeff #define DTLS1_VERSION 0xfeff
#define DTLS1_2_VERSION 0xfefd #define DTLS1_2_VERSION 0xfefd
#define TLS1_3_DRAFT22_VERSION 0x7f16
#define TLS1_3_DRAFT23_VERSION 0x7f17 #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 // 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 // |version|. If |version| is zero, the default minimum version is used. It
@ -3304,8 +3302,6 @@ OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl);
enum tls13_variant_t { enum tls13_variant_t {
tls13_default = 0, 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 // SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the

View File

@ -213,15 +213,13 @@ extern "C" {
// ExtensionType values from draft-ietf-tls-tls13-18 // ExtensionType values from draft-ietf-tls-tls13-18
#define TLSEXT_TYPE_supported_groups 10 #define TLSEXT_TYPE_supported_groups 10
#define TLSEXT_TYPE_old_key_share 40
#define TLSEXT_TYPE_pre_shared_key 41 #define TLSEXT_TYPE_pre_shared_key 41
#define TLSEXT_TYPE_early_data 42 #define TLSEXT_TYPE_early_data 42
#define TLSEXT_TYPE_supported_versions 43 #define TLSEXT_TYPE_supported_versions 43
#define TLSEXT_TYPE_cookie 44 #define TLSEXT_TYPE_cookie 44
#define TLSEXT_TYPE_psk_key_exchange_modes 45 #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_certificate_authorities 47
#define TLSEXT_TYPE_new_key_share 51 #define TLSEXT_TYPE_key_share 51
// ExtensionType value from RFC5746 // ExtensionType value from RFC5746
#define TLSEXT_TYPE_renegotiate 0xff01 #define TLSEXT_TYPE_renegotiate 0xff01

View File

@ -493,8 +493,7 @@ static enum ssl_hs_wait_t do_enter_early_data(SSL_HANDSHAKE *hs) {
} }
ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->session->ssl_version); ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->session->ssl_version);
if (ssl_is_draft22(ssl->session->ssl_version) && if (!ssl->method->add_change_cipher_spec(ssl)) {
!ssl->method->add_change_cipher_spec(ssl)) {
return ssl_hs_error; return ssl_hs_error;
} }

View File

@ -392,18 +392,6 @@ bool ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
// call this function before the version is determined. // call this function before the version is determined.
uint16_t ssl_protocol_version(const SSL *ssl); 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. // Cipher suites.
} // namespace bssl } // namespace bssl

View File

@ -304,14 +304,6 @@ ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span<uint8_t> *out,
const bool is_early_data_read = ssl->server && SSL_in_early_data(ssl); const bool is_early_data_read = ssl->server && SSL_in_early_data(ssl);
if (type == SSL3_RT_HANDSHAKE) { 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 // Post-handshake data prior to TLS 1.3 is always renegotiation, which we
// never accept as a server. Otherwise |ssl3_get_message| will send // never accept as a server. Otherwise |ssl3_get_message| will send
// |SSL_R_EXCESSIVE_MESSAGE_SIZE|. // |SSL_R_EXCESSIVE_MESSAGE_SIZE|.
@ -332,16 +324,6 @@ ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span<uint8_t> *out,
return ssl_open_record_discard; 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) { if (type != SSL3_RT_APPLICATION_DATA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
*out_alert = SSL_AD_UNEXPECTED_MESSAGE; *out_alert = SSL_AD_UNEXPECTED_MESSAGE;

View File

@ -2618,7 +2618,7 @@ TEST(SSLTest, SetVersion) {
// TLS1_3_DRAFT_VERSION is not an API-level version. // TLS1_3_DRAFT_VERSION is not an API-level version.
EXPECT_FALSE( 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(); ERR_clear_error();
ctx.reset(SSL_CTX_new(DTLS_method())); ctx.reset(SSL_CTX_new(DTLS_method()));

View File

@ -34,9 +34,7 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
*out = version; *out = version;
return true; return true;
case TLS1_3_DRAFT22_VERSION:
case TLS1_3_DRAFT23_VERSION: case TLS1_3_DRAFT23_VERSION:
case TLS1_3_EXPERIMENT2_VERSION:
*out = TLS1_3_VERSION; *out = TLS1_3_VERSION;
return true; return true;
@ -59,8 +57,6 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
static const uint16_t kTLSVersions[] = { static const uint16_t kTLSVersions[] = {
TLS1_3_DRAFT23_VERSION, TLS1_3_DRAFT23_VERSION,
TLS1_3_DRAFT22_VERSION,
TLS1_3_EXPERIMENT2_VERSION,
TLS1_2_VERSION, TLS1_2_VERSION,
TLS1_1_VERSION, TLS1_1_VERSION,
TLS1_VERSION, TLS1_VERSION,
@ -103,9 +99,7 @@ static bool method_supports_version(const SSL_PROTOCOL_METHOD *method,
static const char *ssl_version_to_string(uint16_t version) { static const char *ssl_version_to_string(uint16_t version) {
switch (version) { switch (version) {
case TLS1_3_DRAFT22_VERSION:
case TLS1_3_DRAFT23_VERSION: case TLS1_3_DRAFT23_VERSION:
case TLS1_3_EXPERIMENT2_VERSION:
return "TLSv1.3"; return "TLSv1.3";
case TLS1_2_VERSION: case TLS1_2_VERSION:
@ -134,9 +128,7 @@ static const char *ssl_version_to_string(uint16_t version) {
static uint16_t wire_version_to_api(uint16_t version) { static uint16_t wire_version_to_api(uint16_t version) {
switch (version) { switch (version) {
// Report TLS 1.3 draft versions as TLS 1.3 in the public API. // 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_DRAFT23_VERSION:
case TLS1_3_EXPERIMENT2_VERSION:
return TLS1_3_VERSION; return TLS1_3_VERSION;
default: default:
return version; return version;
@ -147,13 +139,11 @@ static uint16_t wire_version_to_api(uint16_t version) {
// particular, it picks an arbitrary TLS 1.3 representative. This should only be // particular, it picks an arbitrary TLS 1.3 representative. This should only be
// used in context where that does not matter. // used in context where that does not matter.
static bool api_version_to_wire(uint16_t *out, uint16_t version) { static bool api_version_to_wire(uint16_t *out, uint16_t version) {
if (version == TLS1_3_DRAFT22_VERSION || if (version == TLS1_3_DRAFT23_VERSION) {
version == TLS1_3_DRAFT23_VERSION ||
version == TLS1_3_EXPERIMENT2_VERSION) {
return false; return false;
} }
if (version == TLS1_3_VERSION) { if (version == TLS1_3_VERSION) {
version = TLS1_3_DRAFT22_VERSION; version = TLS1_3_DRAFT23_VERSION;
} }
// Check it is a real protocol version. // Check it is a real protocol version.
@ -304,12 +294,10 @@ bool ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) {
return false; 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 || 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 && (ssl->tls13_variant == tls13_default &&
version == TLS1_3_DRAFT23_VERSION)) { version == TLS1_3_DRAFT23_VERSION)) {
return true; return true;
@ -368,18 +356,6 @@ bool ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
return false; 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 } // namespace bssl
using namespace bssl; using namespace bssl;

View File

@ -551,10 +551,6 @@ static bool forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
return true; 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, static bool ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) { CBS *contents) {
// This extension from the client is handled elsewhere. // This extension from the client is handled elsewhere.
@ -1821,7 +1817,6 @@ static bool ext_pre_shared_key_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
// selected cipher in HelloRetryRequest does not match. This avoids performing // selected cipher in HelloRetryRequest does not match. This avoids performing
// the transcript hash transformation for multiple hashes. // the transcript hash transformation for multiple hashes.
if (hs->received_hello_retry_request && if (hs->received_hello_retry_request &&
ssl_is_draft22(ssl->version) &&
ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) { ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) {
return true; return true;
} }
@ -2091,9 +2086,7 @@ static bool ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
} }
CBB contents, kse_bytes; CBB contents, kse_bytes;
if (!CBB_add_u16(out, ssl_is_draft23_variant(ssl->tls13_variant) if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
? TLSEXT_TYPE_new_key_share
: TLSEXT_TYPE_old_key_share) ||
!CBB_add_u16_length_prefixed(out, &contents) || !CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &kse_bytes)) { !CBB_add_u16_length_prefixed(&contents, &kse_bytes)) {
return false; return false;
@ -2250,9 +2243,7 @@ bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
uint16_t group_id; uint16_t group_id;
CBB kse_bytes, public_key; CBB kse_bytes, public_key;
if (!tls1_get_shared_group(hs, &group_id) || if (!tls1_get_shared_group(hs, &group_id) ||
!CBB_add_u16(out, ssl_is_draft23(hs->ssl->version) !CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
? TLSEXT_TYPE_new_key_share
: TLSEXT_TYPE_old_key_share) ||
!CBB_add_u16_length_prefixed(out, &kse_bytes) || !CBB_add_u16_length_prefixed(out, &kse_bytes) ||
!CBB_add_u16(&kse_bytes, group_id) || !CBB_add_u16(&kse_bytes, group_id) ||
!CBB_add_u16_length_prefixed(&kse_bytes, &public_key) || !CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
@ -2760,16 +2751,7 @@ static const struct tls_extension kExtensions[] = {
ext_ec_point_add_serverhello, ext_ec_point_add_serverhello,
}, },
{ {
TLSEXT_TYPE_old_key_share, TLSEXT_TYPE_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,
NULL, NULL,
ext_key_share_add_clienthello, ext_key_share_add_clienthello,
forbid_parse_serverhello, forbid_parse_serverhello,

View File

@ -33,21 +33,15 @@ const (
// A draft version of TLS 1.3 that is sent over the wire for the current draft. // A draft version of TLS 1.3 that is sent over the wire for the current draft.
const ( const (
tls13Experiment2Version = 0x7e02 tls13Draft23Version = 0x7f17
tls13Draft22Version = 0x7f16
tls13Draft23Version = 0x7f17
) )
const ( const (
TLS13Draft23 = 0 TLS13Draft23 = 0
TLS13Experiment2 = 1
TLS13Draft22 = 2
) )
var allTLSWireVersions = []uint16{ var allTLSWireVersions = []uint16{
tls13Draft23Version, tls13Draft23Version,
tls13Draft22Version,
tls13Experiment2Version,
VersionTLS12, VersionTLS12,
VersionTLS11, VersionTLS11,
VersionTLS10, VersionTLS10,
@ -125,7 +119,6 @@ const (
extensionTokenBinding uint16 = 24 extensionTokenBinding uint16 = 24
extensionQUICTransportParams uint16 = 26 extensionQUICTransportParams uint16 = 26
extensionSessionTicket uint16 = 35 extensionSessionTicket uint16 = 35
extensionOldKeyShare uint16 = 40 // draft-ietf-tls-tls13-16
extensionPreSharedKey uint16 = 41 // draft-ietf-tls-tls13-16 extensionPreSharedKey uint16 = 41 // draft-ietf-tls-tls13-16
extensionEarlyData uint16 = 42 // draft-ietf-tls-tls13-16 extensionEarlyData uint16 = 42 // draft-ietf-tls-tls13-16
extensionSupportedVersions uint16 = 43 // draft-ietf-tls-tls13-16 extensionSupportedVersions uint16 = 43 // draft-ietf-tls-tls13-16
@ -133,7 +126,7 @@ const (
extensionPSKKeyExchangeModes uint16 = 45 // draft-ietf-tls-tls13-18 extensionPSKKeyExchangeModes uint16 = 45 // draft-ietf-tls-tls13-18
extensionTicketEarlyDataInfo uint16 = 46 // draft-ietf-tls-tls13-18 extensionTicketEarlyDataInfo uint16 = 46 // draft-ietf-tls-tls13-18
extensionCertificateAuthorities uint16 = 47 // draft-ietf-tls-tls13-21 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 extensionCustom uint16 = 1234 // not IANA assigned
extensionNextProtoNeg uint16 = 13172 // not IANA assigned extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01 extensionRenegotiationInfo uint16 = 0xff01
@ -1670,7 +1663,7 @@ func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
switch vers { switch vers {
case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12: case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
return vers, true return vers, true
case tls13Draft23Version, tls13Draft22Version, tls13Experiment2Version: case tls13Draft23Version:
return VersionTLS13, true return VersionTLS13, true
} }
} }
@ -1678,21 +1671,11 @@ func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
return 0, false 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, // isSupportedVersion checks if the specified wire version is acceptable. If so,
// it returns true and the corresponding protocol version. Otherwise, it returns // it returns true and the corresponding protocol version. Otherwise, it returns
// false. // false.
func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) { func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) {
if (c.TLS13Variant != TLS13Experiment2 && wireVers == tls13Experiment2Version) || if c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version {
(c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version) ||
(c.TLS13Variant != TLS13Draft22 && wireVers == tls13Draft22Version) {
return 0, false return 0, false
} }

View File

@ -1566,9 +1566,7 @@ func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMs
earlyALPN: c.clientProtocol, 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) cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
_, ok := c.config.ClientSessionCache.Get(cacheKey) _, ok := c.config.ClientSessionCache.Get(cacheKey)
@ -1860,16 +1858,13 @@ func (c *Conn) exportKeyingMaterialTLS13(length int, secret, label, context []by
if cipherSuite == nil { if cipherSuite == nil {
cipherSuite = c.earlyCipherSuite cipherSuite = c.earlyCipherSuite
} }
if isDraft22(c.wireVersion) { hash := cipherSuite.hash()
hash := cipherSuite.hash() exporterKeyingLabel := []byte("exporter")
exporterKeyingLabel := []byte("exporter") contextHash := hash.New()
contextHash := hash.New() contextHash.Write(context)
contextHash.Write(context) exporterContext := hash.New().Sum(nil)
exporterContext := hash.New().Sum(nil) derivedSecret := hkdfExpandLabel(cipherSuite.hash(), secret, label, exporterContext, hash.Size())
derivedSecret := hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, secret, label, exporterContext, hash.Size()) return hkdfExpandLabel(cipherSuite.hash(), derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length)
return hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length)
}
return hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, secret, label, context, length)
} }
// ExportKeyingMaterial exports keying material from the current connection // ExportKeyingMaterial exports keying material from the current connection
@ -1954,13 +1949,10 @@ func (c *Conn) SendNewSessionTicket(nonce []byte) error {
duplicateEarlyDataExtension: c.config.Bugs.DuplicateTicketEarlyData, duplicateEarlyDataExtension: c.config.Bugs.DuplicateTicketEarlyData,
customExtension: c.config.Bugs.CustomTicketExtension, customExtension: c.config.Bugs.CustomTicketExtension,
ticketAgeAdd: ticketAgeAdd, ticketAgeAdd: ticketAgeAdd,
ticketNonce: nonce,
maxEarlyDataSize: c.config.MaxEarlyDataSize, maxEarlyDataSize: c.config.MaxEarlyDataSize,
} }
if isDraft22(c.wireVersion) {
m.ticketNonce = nonce
}
if c.config.Bugs.SendTicketLifetime != 0 { if c.config.Bugs.SendTicketLifetime != 0 {
m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second) m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second)
} }
@ -1968,7 +1960,7 @@ func (c *Conn) SendNewSessionTicket(nonce []byte) error {
state := sessionState{ state := sessionState{
vers: c.vers, vers: c.vers,
cipherSuite: c.cipherSuite.id, cipherSuite: c.cipherSuite.id,
masterSecret: c.resumptionSecret, masterSecret: deriveSessionPSK(c.cipherSuite, c.wireVersion, c.resumptionSecret, nonce),
certificates: peerCertificatesRaw, certificates: peerCertificatesRaw,
ticketCreationTime: c.config.time(), ticketCreationTime: c.config.time(),
ticketExpiration: c.config.time().Add(time.Duration(m.ticketLifetime) * time.Second), ticketExpiration: c.config.time().Add(time.Duration(m.ticketLifetime) * time.Second),
@ -1976,10 +1968,6 @@ func (c *Conn) SendNewSessionTicket(nonce []byte) error {
earlyALPN: []byte(c.clientProtocol), earlyALPN: []byte(c.clientProtocol),
} }
if isDraft22(c.wireVersion) {
state.masterSecret = deriveSessionPSK(c.cipherSuite, c.wireVersion, c.resumptionSecret, nonce)
}
if !c.config.Bugs.SendEmptySessionTicket { if !c.config.Bugs.SendEmptySessionTicket {
var err error var err error
m.ticket, err = c.encryptTicket(&state) m.ticket, err = c.encryptTicket(&state)

View File

@ -162,11 +162,6 @@ func (c *Conn) clientHandshake() error {
if maxVersion >= VersionTLS13 { if maxVersion >= VersionTLS13 {
keyShares = make(map[CurveID]ecdhCurve) keyShares = make(map[CurveID]ecdhCurve)
hello.hasKeyShares = true hello.hasKeyShares = true
if c.config.TLS13Variant == TLS13Draft23 {
hello.keyShareExtension = extensionNewKeyShare
} else {
hello.keyShareExtension = extensionOldKeyShare
}
hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
curvesToSend := c.config.defaultCurves() curvesToSend := c.config.defaultCurves()
for _, curveID := range hello.supportedCurves { for _, curveID := range hello.supportedCurves {
@ -385,7 +380,7 @@ NextCipherSuite:
// set. Fill in an arbitrary TLS 1.3 version to compute // set. Fill in an arbitrary TLS 1.3 version to compute
// the binder. // the binder.
if session.vers < VersionTLS13 { if session.vers < VersionTLS13 {
version = tls13Draft22Version version = tls13Draft23Version
} }
generatePSKBinders(version, hello, pskCipherSuite, session.masterSecret, []byte{}, []byte{}, c.config) generatePSKBinders(version, hello, pskCipherSuite, session.masterSecret, []byte{}, []byte{}, c.config)
} }
@ -422,7 +417,7 @@ NextCipherSuite:
finishedHash.addEntropy(session.masterSecret) finishedHash.addEntropy(session.masterSecret)
finishedHash.Write(helloBytes) finishedHash.Write(helloBytes)
if !c.config.Bugs.SkipChangeCipherSpec && isDraft22(session.wireVersion) { if !c.config.Bugs.SkipChangeCipherSpec {
c.wireVersion = session.wireVersion c.wireVersion = session.wireVersion
c.vers = VersionTLS13 c.vers = VersionTLS13
c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
@ -430,14 +425,8 @@ NextCipherSuite:
c.vers = 0 c.vers = 0
} }
var earlyTrafficSecret []byte earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
if isDraft22(session.wireVersion) { c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel)
earlyTrafficSecret = finishedHash.deriveSecret(earlyTrafficLabelDraft22)
c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabelDraft22)
} else {
earlyTrafficSecret = finishedHash.deriveSecret(earlyTrafficLabel)
c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel)
}
c.useOutTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret) c.useOutTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret)
for _, earlyData := range c.config.Bugs.SendEarlyData { for _, earlyData := range c.config.Bugs.SendEarlyData {
@ -498,7 +487,7 @@ NextCipherSuite:
c.vers = serverVersion c.vers = serverVersion
c.haveVers = true c.haveVers = true
if isDraft22(c.wireVersion) { if c.vers >= VersionTLS13 {
// The first server message must be followed by a ChangeCipherSpec. // The first server message must be followed by a ChangeCipherSpec.
c.expectTLS13ChangeCipherSpec = true c.expectTLS13ChangeCipherSpec = true
} }
@ -506,12 +495,10 @@ NextCipherSuite:
helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg) helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
var secondHelloBytes []byte var secondHelloBytes []byte
if haveHelloRetryRequest { if haveHelloRetryRequest {
if isDraft22(c.wireVersion) { // Explicitly read the ChangeCipherSpec now; it should
// Explicitly read the ChangeCipherSpec now; it should // be attached to the first flight, not the second flight.
// be attached to the first flight, not the second flight. if err := c.readTLS13ChangeCipherSpec(); err != nil {
if err := c.readTLS13ChangeCipherSpec(); err != nil { return err
return err
}
} }
c.out.resetCipher() c.out.resetCipher()
@ -639,11 +626,9 @@ NextCipherSuite:
hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1) hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
if haveHelloRetryRequest { if haveHelloRetryRequest {
if isDraft22(c.wireVersion) { err = hs.finishedHash.UpdateForHelloRetryRequest()
err = hs.finishedHash.UpdateForHelloRetryRequest() if err != nil {
if err != nil { return err
return err
}
} }
hs.writeServerHash(helloRetryRequest.marshal()) hs.writeServerHash(helloRetryRequest.marshal())
hs.writeClientHash(secondHelloBytes) hs.writeClientHash(secondHelloBytes)
@ -740,12 +725,6 @@ NextCipherSuite:
func (hs *clientHandshakeState) doTLS13Handshake() error { func (hs *clientHandshakeState) doTLS13Handshake() error {
c := hs.c 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) { if !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
return errors.New("tls: session IDs did not match.") return errors.New("tls: session IDs did not match.")
} }
@ -802,17 +781,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
hs.finishedHash.addEntropy(zeroSecret) 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 // Derive handshake traffic keys and switch read key to handshake
// traffic key. // traffic key.
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientLabel) clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret); err != nil { if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret); err != nil {
return err return err
} }
@ -949,18 +921,9 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
hs.finishedHash.nextSecret() hs.finishedHash.nextSecret()
hs.finishedHash.addEntropy(zeroSecret) hs.finishedHash.addEntropy(zeroSecret)
clientLabel = clientApplicationTrafficLabel clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
serverLabel = serverApplicationTrafficLabel serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
exportLabel := exporterLabel c.exporterSecret = hs.finishedHash.deriveSecret(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)
// Switch to application data keys on read. In particular, any alerts // Switch to application data keys on read. In particular, any alerts
// from the client certificate are read over these keys. // from the client certificate are read over these keys.
@ -1004,14 +967,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
helloRequest := new(helloRequestMsg) helloRequest := new(helloRequestMsg)
c.writeRecord(recordTypeHandshake, helloRequest.marshal()) c.writeRecord(recordTypeHandshake, helloRequest.marshal())
} }
if isDraft22(c.wireVersion) { endOfEarlyData := new(endOfEarlyDataMsg)
endOfEarlyData := new(endOfEarlyDataMsg) endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData
endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal())
c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal()) hs.writeClientHash(endOfEarlyData.marshal())
hs.writeClientHash(endOfEarlyData.marshal())
} else {
c.sendAlert(alertEndOfEarlyData)
}
} }
if !c.config.Bugs.SkipChangeCipherSpec && !hs.hello.hasEarlyData { if !c.config.Bugs.SkipChangeCipherSpec && !hs.hello.hasEarlyData {
@ -1109,13 +1068,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
// Switch to application data keys. // Switch to application data keys.
c.useOutTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret) c.useOutTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret)
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
resumeLabel := resumptionLabel
if isDraft22(c.wireVersion) {
resumeLabel = resumptionLabelDraft22
}
c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel)
for _, ticket := range deferredTickets { for _, ticket := range deferredTickets {
if err := c.processTLS13NewSessionTicket(ticket, hs.suite); err != nil { if err := c.processTLS13NewSessionTicket(ticket, hs.suite); err != nil {
return err return err
@ -1887,11 +1840,7 @@ func generatePSKBinders(version uint16, hello *clientHelloMsg, pskCipherSuite *c
helloBytes := hello.marshal() helloBytes := hello.marshal()
binderSize := len(hello.pskBinders)*(binderLen+1) + 2 binderSize := len(hello.pskBinders)*(binderLen+1) + 2
truncatedHello := helloBytes[:len(helloBytes)-binderSize] truncatedHello := helloBytes[:len(helloBytes)-binderSize]
binderLabel := resumptionPSKBinderLabel binder := computePSKBinder(psk, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
if isDraft22(version) {
binderLabel = resumptionPSKBinderLabelDraft22
}
binder := computePSKBinder(psk, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
if config.Bugs.SendShortPSKBinder { if config.Bugs.SendShortPSKBinder {
binder = binder[:binderLen] binder = binder[:binderLen]
} }

View File

@ -265,7 +265,6 @@ type clientHelloMsg struct {
supportedCurves []CurveID supportedCurves []CurveID
supportedPoints []uint8 supportedPoints []uint8
hasKeyShares bool hasKeyShares bool
keyShareExtension uint16
keyShares []keyShareEntry keyShares []keyShareEntry
trailingKeyShareData bool trailingKeyShareData bool
pskIdentities []pskIdentity pskIdentities []pskIdentity
@ -453,7 +452,7 @@ func (m *clientHelloMsg) marshal() []byte {
supportedPoints.addBytes(m.supportedPoints) supportedPoints.addBytes(m.supportedPoints)
} }
if m.hasKeyShares { if m.hasKeyShares {
extensions.addU16(m.keyShareExtension) extensions.addU16(extensionKeyShare)
keyShareList := extensions.addU16LengthPrefixed() keyShareList := extensions.addU16LengthPrefixed()
keyShares := keyShareList.addU16LengthPrefixed() keyShares := keyShareList.addU16LengthPrefixed()
@ -740,12 +739,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
// http://tools.ietf.org/html/rfc5077#section-3.2 // http://tools.ietf.org/html/rfc5077#section-3.2
m.ticketSupported = true m.ticketSupported = true
m.sessionTicket = []byte(body) m.sessionTicket = []byte(body)
case extensionOldKeyShare, extensionNewKeyShare: case extensionKeyShare:
// We assume the client only supports one of draft-22 or draft-23.
if m.keyShareExtension != 0 {
return false
}
m.keyShareExtension = extension
// draft-ietf-tls-tls13 section 6.3.2.3 // draft-ietf-tls-tls13 section 6.3.2.3
var keyShares byteReader var keyShares byteReader
if !body.readU16LengthPrefixed(&keyShares) || len(body) != 0 { if !body.readU16LengthPrefixed(&keyShares) || len(body) != 0 {
@ -951,11 +945,7 @@ func (m *serverHelloMsg) marshal() []byte {
if vers >= VersionTLS13 { if vers >= VersionTLS13 {
if m.hasKeyShare { if m.hasKeyShare {
if isDraft23(m.vers) { extensions.addU16(extensionKeyShare)
extensions.addU16(extensionNewKeyShare)
} else {
extensions.addU16(extensionOldKeyShare)
}
keyShare := extensions.addU16LengthPrefixed() keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group)) keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed() keyExchange := keyShare.addU16LengthPrefixed()
@ -1058,10 +1048,6 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
} }
if vers >= VersionTLS13 { if vers >= VersionTLS13 {
extensionKeyShare := extensionOldKeyShare
if isDraft23(m.vers) {
extensionKeyShare = extensionNewKeyShare
}
for len(extensions) > 0 { for len(extensions) > 0 {
var extension uint16 var extension uint16
var body byteReader var body byteReader
@ -1252,7 +1238,7 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) {
} }
} }
if m.hasKeyShare { if m.hasKeyShare {
extensions.addU16(extensionOldKeyShare) extensions.addU16(extensionKeyShare)
keyShare := extensions.addU16LengthPrefixed() keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group)) keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed() keyExchange := keyShare.addU16LengthPrefixed()
@ -1425,26 +1411,15 @@ func (m *helloRetryRequestMsg) marshal() []byte {
} }
retryRequestMsg := newByteBuilder() retryRequestMsg := newByteBuilder()
if isDraft22(m.vers) { retryRequestMsg.addU8(typeServerHello)
retryRequestMsg.addU8(typeServerHello)
} else {
retryRequestMsg.addU8(typeHelloRetryRequest)
}
retryRequest := retryRequestMsg.addU24LengthPrefixed() 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() extensions := retryRequest.addU16LengthPrefixed()
count := 1 count := 1
@ -1453,17 +1428,11 @@ func (m *helloRetryRequestMsg) marshal() []byte {
} }
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
if isDraft22(m.vers) { extensions.addU16(extensionSupportedVersions)
extensions.addU16(extensionSupportedVersions) extensions.addU16(2) // Length
extensions.addU16(2) // Length extensions.addU16(m.vers)
extensions.addU16(m.vers)
}
if m.hasSelectedGroup { if m.hasSelectedGroup {
if isDraft23(m.vers) { extensions.addU16(extensionKeyShare)
extensions.addU16(extensionNewKeyShare)
} else {
extensions.addU16(extensionOldKeyShare)
}
extensions.addU16(2) // length extensions.addU16(2) // length
extensions.addU16(uint16(m.selectedGroup)) extensions.addU16(uint16(m.selectedGroup))
} }
@ -1499,7 +1468,7 @@ func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
compressionMethod != 0 { compressionMethod != 0 {
return false return false
} }
} else if isDraft22(m.vers) && !reader.readU16(&m.cipherSuite) { } else if !reader.readU16(&m.cipherSuite) {
return false return false
} }
var extensions byteReader var extensions byteReader
@ -1524,10 +1493,6 @@ func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
default: default:
} }
} }
extensionKeyShare := extensionOldKeyShare
if isDraft23(m.vers) {
extensionKeyShare = extensionNewKeyShare
}
for len(extensions) > 0 { for len(extensions) > 0 {
var extension uint16 var extension uint16
var body byteReader var body byteReader
@ -1883,37 +1848,21 @@ func (m *certificateRequestMsg) marshal() []byte {
requestContext := body.addU8LengthPrefixed() requestContext := body.addU8LengthPrefixed()
requestContext.addBytes(m.requestContext) requestContext.addBytes(m.requestContext)
extensions := newByteBuilder() extensions := newByteBuilder()
if isDraft22(m.vers) { extensions = body.addU16LengthPrefixed()
extensions = body.addU16LengthPrefixed() if m.hasSignatureAlgorithm {
if m.hasSignatureAlgorithm { extensions.addU16(extensionSignatureAlgorithms)
extensions.addU16(extensionSignatureAlgorithms) signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed() for _, sigAlg := range m.signatureAlgorithms {
for _, sigAlg := range m.signatureAlgorithms { signatureAlgorithms.addU16(uint16(sigAlg))
signatureAlgorithms.addU16(uint16(sigAlg))
}
} }
if len(m.certificateAuthorities) > 0 { }
extensions.addU16(extensionCertificateAuthorities) if len(m.certificateAuthorities) > 0 {
certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed() extensions.addU16(extensionCertificateAuthorities)
for _, ca := range m.certificateAuthorities { certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
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()
for _, ca := range m.certificateAuthorities { for _, ca := range m.certificateAuthorities {
caEntry := certificateAuthorities.addU16LengthPrefixed() caEntry := certificateAuthorities.addU16LengthPrefixed()
caEntry.addBytes(ca) caEntry.addBytes(ca)
} }
extensions = body.addU16LengthPrefixed()
} }
if m.customExtension > 0 { if m.customExtension > 0 {
@ -1961,7 +1910,7 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
m.raw = data m.raw = data
reader := byteReader(data[4:]) reader := byteReader(data[4:])
if isDraft22(m.vers) { if m.hasRequestContext {
var extensions byteReader var extensions byteReader
if !reader.readU8LengthPrefixedBytes(&m.requestContext) || if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
!reader.readU16LengthPrefixed(&extensions) || !reader.readU16LengthPrefixed(&extensions) ||
@ -1987,16 +1936,6 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
m.hasCAExtension = true 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 { } else {
if !reader.readU8LengthPrefixedBytes(&m.certificateTypes) { if !reader.readU8LengthPrefixedBytes(&m.certificateTypes) {
return false return false
@ -2114,9 +2053,7 @@ func (m *newSessionTicketMsg) marshal() []byte {
body.addU32(m.ticketLifetime) body.addU32(m.ticketLifetime)
if version >= VersionTLS13 { if version >= VersionTLS13 {
body.addU32(m.ticketAgeAdd) body.addU32(m.ticketAgeAdd)
if isDraft22(m.vers) { body.addU8LengthPrefixed().addBytes(m.ticketNonce)
body.addU8LengthPrefixed().addBytes(m.ticketNonce)
}
} }
ticket := body.addU16LengthPrefixed() ticket := body.addU16LengthPrefixed()
@ -2125,14 +2062,10 @@ func (m *newSessionTicketMsg) marshal() []byte {
if version >= VersionTLS13 { if version >= VersionTLS13 {
extensions := body.addU16LengthPrefixed() extensions := body.addU16LengthPrefixed()
if m.maxEarlyDataSize > 0 { if m.maxEarlyDataSize > 0 {
extID := extensionTicketEarlyDataInfo extensions.addU16(extensionEarlyData)
if isDraft22(m.vers) {
extID = extensionEarlyData
}
extensions.addU16(extID)
extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize) extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
if m.duplicateEarlyDataExtension { if m.duplicateEarlyDataExtension {
extensions.addU16(extID) extensions.addU16(extensionEarlyData)
extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize) extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
} }
} }
@ -2166,15 +2099,13 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
} }
m.ticketAgeAdd = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) m.ticketAgeAdd = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
data = data[4:] data = data[4:]
if isDraft22(m.vers) { nonceLen := int(data[0])
nonceLen := int(data[0]) data = data[1:]
data = data[1:] if len(data) < nonceLen {
if len(data) < nonceLen { return false
return false
}
m.ticketNonce = data[:nonceLen]
data = data[nonceLen:]
} }
m.ticketNonce = data[:nonceLen]
data = data[nonceLen:]
} }
if len(data) < 2 { if len(data) < 2 {
@ -2204,11 +2135,6 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
return false return false
} }
extID := extensionTicketEarlyDataInfo
if isDraft22(m.vers) {
extID = extensionEarlyData
}
for len(data) != 0 { for len(data) != 0 {
if len(data) < 4 { if len(data) < 4 {
return false return false
@ -2221,7 +2147,7 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
} }
switch extension { switch extension {
case extID: case extensionEarlyData:
if length != 4 { if length != 4 {
return false return false
} }

View File

@ -280,14 +280,6 @@ func (hs *serverHandshakeState) readClientHello() error {
} }
} }
// 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 config.Bugs.ExpectNoTLS12Session {
if len(hs.clientHello.sessionId) > 0 && c.vers >= VersionTLS13 { if len(hs.clientHello.sessionId) > 0 && c.vers >= VersionTLS13 {
return fmt.Errorf("tls: client offered an unexpected session ID") return fmt.Errorf("tls: client offered an unexpected session ID")
@ -370,11 +362,8 @@ func (hs *serverHandshakeState) doTLS13Handshake() error {
c := hs.c c := hs.c
config := c.config config := c.config
// We've read the ClientHello, so the next record in draft 22 must be // We've read the ClientHello, so the next record must be preceded with ChangeCipherSpec.
// preceded with ChangeCipherSpec. c.expectTLS13ChangeCipherSpec = true
if isDraft22(c.wireVersion) {
c.expectTLS13ChangeCipherSpec = true
}
hs.hello = &serverHelloMsg{ hs.hello = &serverHelloMsg{
isDTLS: c.isDTLS, isDTLS: c.isDTLS,
@ -597,10 +586,8 @@ ResendHelloRetryRequest:
} }
if sendHelloRetryRequest { if sendHelloRetryRequest {
if isDraft22(c.wireVersion) { if err := hs.finishedHash.UpdateForHelloRetryRequest(); err != nil {
if err := hs.finishedHash.UpdateForHelloRetryRequest(); err != nil { return err
return err
}
} }
oldClientHelloBytes := hs.clientHello.marshal() oldClientHelloBytes := hs.clientHello.marshal()
@ -608,7 +595,7 @@ ResendHelloRetryRequest:
c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal()) c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
c.flushHandshake() c.flushHandshake()
if !c.config.Bugs.SkipChangeCipherSpec && isDraft22(c.wireVersion) { if !c.config.Bugs.SkipChangeCipherSpec {
c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
} }
@ -666,7 +653,7 @@ ResendHelloRetryRequest:
// PSK binders and obfuscated ticket age are both updated in the // PSK binders and obfuscated ticket age are both updated in the
// second ClientHello. // second ClientHello.
if isDraft22(c.wireVersion) && len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) { if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
newClientHelloCopy.pskIdentities = oldClientHelloCopy.pskIdentities newClientHelloCopy.pskIdentities = oldClientHelloCopy.pskIdentities
} else { } else {
if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) { if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
@ -706,14 +693,8 @@ ResendHelloRetryRequest:
} }
} }
if encryptedExtensions.extensions.hasEarlyData { if encryptedExtensions.extensions.hasEarlyData {
var earlyTrafficSecret []byte earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel)
if isDraft22(c.wireVersion) { c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel)
earlyTrafficSecret = hs.finishedHash.deriveSecret(earlyTrafficLabelDraft22)
c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabelDraft22)
} else {
earlyTrafficSecret = hs.finishedHash.deriveSecret(earlyTrafficLabel)
c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel)
}
if err := c.useInTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret); err != nil { if err := c.useInTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret); err != nil {
return err return err
@ -829,18 +810,11 @@ ResendHelloRetryRequest:
c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
} }
clientLabel := clientHandshakeTrafficLabel
serverLabel := serverHandshakeTrafficLabel
if isDraft22(c.wireVersion) {
clientLabel = clientHandshakeTrafficLabelDraft22
serverLabel = serverHandshakeTrafficLabelDraft22
}
// Switch to handshake traffic keys. // Switch to handshake traffic keys.
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
c.useOutTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret) c.useOutTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret)
// Derive handshake traffic read key, but don't switch yet. // Derive handshake traffic read key, but don't switch yet.
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientLabel) clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
// Send EncryptedExtensions. // Send EncryptedExtensions.
hs.writeServerHash(encryptedExtensions.marshal()) hs.writeServerHash(encryptedExtensions.marshal())
@ -977,18 +951,9 @@ ResendHelloRetryRequest:
hs.finishedHash.nextSecret() hs.finishedHash.nextSecret()
hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret()) hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
clientLabel = clientApplicationTrafficLabel clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
serverLabel = serverApplicationTrafficLabel serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
exportLabel := exporterLabel c.exporterSecret = hs.finishedHash.deriveSecret(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)
// Switch to application data keys on write. In particular, any alerts // Switch to application data keys on write. In particular, any alerts
// from the client certificate are sent over these keys. // from the client certificate are sent over these keys.
@ -1003,31 +968,17 @@ ResendHelloRetryRequest:
// Read end_of_early_data. // Read end_of_early_data.
if encryptedExtensions.extensions.hasEarlyData { if encryptedExtensions.extensions.hasEarlyData {
if isDraft22(c.wireVersion) { msg, err := c.readHandshake()
msg, err := c.readHandshake() if err != nil {
if err != nil { return err
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
}
} }
}
if !isDraft22(c.wireVersion) && !hs.clientHello.hasEarlyData { endOfEarlyData, ok := msg.(*endOfEarlyDataMsg)
// Early versions of the middlebox hacks inserted if !ok {
// ChangeCipherSpec differently on 0-RTT and 2-RTT handshakes. c.sendAlert(alertUnexpectedMessage)
c.expectTLS13ChangeCipherSpec = true return unexpectedMessageError(endOfEarlyData, msg)
}
hs.writeClientHash(endOfEarlyData.marshal())
} }
// Switch input stream to handshake traffic keys. // Switch input stream to handshake traffic keys.
@ -1142,13 +1093,7 @@ ResendHelloRetryRequest:
} }
c.cipherSuite = hs.suite c.cipherSuite = hs.suite
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
resumeLabel := resumptionLabel
if isDraft22(c.wireVersion) {
resumeLabel = resumptionLabelDraft22
}
c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel)
// TODO(davidben): Allow configuring the number of tickets sent for // TODO(davidben): Allow configuring the number of tickets sent for
// testing. // testing.
@ -2172,11 +2117,7 @@ func verifyPSKBinder(version uint16, clientHello *clientHelloMsg, sessionState *
return errors.New("tls: Unknown cipher suite for PSK in session") return errors.New("tls: Unknown cipher suite for PSK in session")
} }
binderLabel := resumptionPSKBinderLabel binder := computePSKBinder(sessionState.masterSecret, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
if isDraft22(version) {
binderLabel = resumptionPSKBinderLabelDraft22
}
binder := computePSKBinder(sessionState.masterSecret, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
if !bytes.Equal(binder, binderToVerify) { if !bytes.Equal(binder, binderToVerify) {
return errors.New("tls: PSK binder does not verify") return errors.New("tls: PSK binder does not verify")
} }

View File

@ -328,7 +328,7 @@ func (h finishedHash) clientSum(baseKey []byte) []byte {
return out 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 := hmac.New(h.hash.New, clientFinishedKey)
finishedHMAC.Write(h.appendContextHashes(nil)) finishedHMAC.Write(h.appendContextHashes(nil))
return finishedHMAC.Sum(nil) return finishedHMAC.Sum(nil)
@ -347,7 +347,7 @@ func (h finishedHash) serverSum(baseKey []byte) []byte {
return out 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 := hmac.New(h.hash.New, serverFinishedKey)
finishedHMAC.Write(h.appendContextHashes(nil)) finishedHMAC.Write(h.appendContextHashes(nil))
return finishedHMAC.Sum(nil) return finishedHMAC.Sum(nil)
@ -396,24 +396,17 @@ func (h *finishedHash) addEntropy(ikm []byte) {
} }
func (h *finishedHash) nextSecret() { func (h *finishedHash) nextSecret() {
if isDraft22(h.wireVersion) { h.secret = hkdfExpandLabel(h.hash, h.secret, []byte("derived"), h.hash.New().Sum(nil), h.hash.Size())
derivedLabel := []byte("derived")
h.secret = hkdfExpandLabel(h.hash, h.wireVersion, h.secret, derivedLabel, h.hash.New().Sum(nil), h.hash.Size())
}
} }
// hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined // hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined
// in section 7.1 of draft-ietf-tls-tls13-16. // 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 { if len(label) > 255 || len(hashValue) > 255 {
panic("hkdfExpandLabel: label or hashValue too long") panic("hkdfExpandLabel: label or hashValue too long")
} }
versionLabel := []byte("TLS 1.3, ") versionLabel := []byte("tls13 ")
if isDraft22(version) {
versionLabel = []byte("tls13 ")
}
hkdfLabel := make([]byte, 3+len(versionLabel)+len(label)+1+len(hashValue)) hkdfLabel := make([]byte, 3+len(versionLabel)+len(label)+1+len(hashValue))
x := hkdfLabel x := hkdfLabel
x[0] = byte(length >> 8) x[0] = byte(length >> 8)
@ -438,29 +431,17 @@ func (h *finishedHash) appendContextHashes(b []byte) []byte {
// The following are labels for traffic secret derivation in TLS 1.3. // The following are labels for traffic secret derivation in TLS 1.3.
var ( var (
externalPSKBinderLabel = []byte("external psk binder key") externalPSKBinderLabel = []byte("ext binder")
resumptionPSKBinderLabel = []byte("resumption psk binder key") resumptionPSKBinderLabel = []byte("res binder")
earlyTrafficLabel = []byte("client early traffic secret") earlyTrafficLabel = []byte("c e traffic")
clientHandshakeTrafficLabel = []byte("client handshake traffic secret") clientHandshakeTrafficLabel = []byte("c hs traffic")
serverHandshakeTrafficLabel = []byte("server handshake traffic secret") serverHandshakeTrafficLabel = []byte("s hs traffic")
clientApplicationTrafficLabel = []byte("client application traffic secret") clientApplicationTrafficLabel = []byte("c ap traffic")
serverApplicationTrafficLabel = []byte("server application traffic secret") serverApplicationTrafficLabel = []byte("s ap traffic")
applicationTrafficLabel = []byte("application traffic secret") applicationTrafficLabel = []byte("traffic upd")
earlyExporterLabel = []byte("early exporter master secret") earlyExporterLabel = []byte("e exp master")
exporterLabel = []byte("exporter master secret") exporterLabel = []byte("exp master")
resumptionLabel = []byte("resumption master secret") resumptionLabel = []byte("res master")
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")
resumptionPSKLabel = []byte("resumption") resumptionPSKLabel = []byte("resumption")
) )
@ -468,7 +449,7 @@ var (
// deriveSecret implements TLS 1.3's Derive-Secret function, as defined in // deriveSecret implements TLS 1.3's Derive-Secret function, as defined in
// section 7.1 of draft ietf-tls-tls13-16. // section 7.1 of draft ietf-tls-tls13-16.
func (h *finishedHash) deriveSecret(label []byte) []byte { 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. // The following are context strings for CertificateVerify in TLS 1.3.
@ -507,18 +488,14 @@ var (
// deriveTrafficAEAD derives traffic keys and constructs an AEAD given a traffic // deriveTrafficAEAD derives traffic keys and constructs an AEAD given a traffic
// secret. // secret.
func deriveTrafficAEAD(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) interface{} { func deriveTrafficAEAD(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) interface{} {
key := hkdfExpandLabel(suite.hash(), version, secret, keyTLS13, nil, suite.keyLen) key := hkdfExpandLabel(suite.hash(), secret, keyTLS13, nil, suite.keyLen)
iv := hkdfExpandLabel(suite.hash(), version, secret, ivTLS13, nil, suite.ivLen(version)) iv := hkdfExpandLabel(suite.hash(), secret, ivTLS13, nil, suite.ivLen(version))
return suite.aead(version, key, iv) return suite.aead(version, key, iv)
} }
func updateTrafficSecret(hash crypto.Hash, version uint16, secret []byte) []byte { func updateTrafficSecret(hash crypto.Hash, version uint16, secret []byte) []byte {
trafficLabel := applicationTrafficLabel return hkdfExpandLabel(hash, secret, applicationTrafficLabel, nil, hash.Size())
if isDraft22(version) {
trafficLabel = applicationTrafficLabelDraft22
}
return hkdfExpandLabel(hash, version, secret, trafficLabel, nil, hash.Size())
} }
func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cipherSuite, clientHello, helloRetryRequest, truncatedHello []byte) []byte { func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cipherSuite, clientHello, helloRetryRequest, truncatedHello []byte) []byte {
@ -526,7 +503,7 @@ func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cip
finishedHash.addEntropy(psk) finishedHash.addEntropy(psk)
binderKey := finishedHash.deriveSecret(label) binderKey := finishedHash.deriveSecret(label)
finishedHash.Write(clientHello) finishedHash.Write(clientHello)
if isDraft22(version) && len(helloRetryRequest) != 0 { if len(helloRetryRequest) != 0 {
finishedHash.UpdateForHelloRetryRequest() finishedHash.UpdateForHelloRetryRequest()
} }
finishedHash.Write(helloRetryRequest) finishedHash.Write(helloRetryRequest)
@ -536,5 +513,5 @@ func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cip
func deriveSessionPSK(suite *cipherSuite, version uint16, masterSecret []byte, nonce []byte) []byte { func deriveSessionPSK(suite *cipherSuite, version uint16, masterSecret []byte, nonce []byte) []byte {
hash := suite.hash() hash := suite.hash()
return hkdfExpandLabel(hash, version, masterSecret, resumptionPSKLabel, nonce, hash.Size()) return hkdfExpandLabel(hash, masterSecret, resumptionPSKLabel, nonce, hash.Size())
} }

View File

@ -1371,13 +1371,6 @@ var tlsVersions = []tlsVersion{
hasDTLS: true, hasDTLS: true,
versionDTLS: VersionDTLS12, versionDTLS: VersionDTLS12,
}, },
{
name: "TLS13Draft22",
version: VersionTLS13,
excludeFlag: "-no-tls13",
versionWire: tls13Draft22Version,
tls13Variant: TLS13Draft22,
},
{ {
name: "TLS13Draft23", name: "TLS13Draft23",
version: VersionTLS13, version: VersionTLS13,
@ -1385,13 +1378,6 @@ var tlsVersions = []tlsVersion{
versionWire: tls13Draft23Version, versionWire: tls13Draft23Version,
tls13Variant: TLS13Draft23, tls13Variant: TLS13Draft23,
}, },
{
name: "TLS13Experiment2",
version: VersionTLS13,
excludeFlag: "-no-tls13",
versionWire: tls13Experiment2Version,
tls13Variant: TLS13Experiment2,
},
} }
func allVersions(protocol protocol) []tlsVersion { func allVersions(protocol protocol) []tlsVersion {
@ -2854,20 +2840,20 @@ read alert 1 0
}, },
{ {
testType: clientTest, testType: clientTest,
name: "TLS13Draft22-InvalidCompressionMethod", name: "TLS13Draft23-InvalidCompressionMethod",
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{ Bugs: ProtocolBugs{
SendCompressionMethod: 1, SendCompressionMethod: 1,
}, },
}, },
tls13Variant: TLS13Draft22, tls13Variant: TLS13Draft23,
shouldFail: true, shouldFail: true,
expectedError: ":DECODE_ERROR:", expectedError: ":DECODE_ERROR:",
}, },
{ {
testType: clientTest, testType: clientTest,
name: "TLS13Draft22-HRR-InvalidCompressionMethod", name: "TLS13Draft23-HRR-InvalidCompressionMethod",
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
CurvePreferences: []CurveID{CurveP384}, CurvePreferences: []CurveID{CurveP384},
@ -2875,7 +2861,7 @@ read alert 1 0
SendCompressionMethod: 1, SendCompressionMethod: 1,
}, },
}, },
tls13Variant: TLS13Draft22, tls13Variant: TLS13Draft23,
shouldFail: true, shouldFail: true,
expectedError: ":DECODE_ERROR:", expectedError: ":DECODE_ERROR:",
expectedLocalError: "remote error: error decoding message", expectedLocalError: "remote error: error decoding message",
@ -3968,7 +3954,7 @@ func addClientAuthTests() {
// Test that an empty client CA list doesn't send a CA extension. // Test that an empty client CA list doesn't send a CA extension.
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
testType: serverTest, testType: serverTest,
name: "TLS13Draft22-Empty-Client-CA-List", name: "TLS13Draft23-Empty-Client-CA-List",
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
Certificates: []Certificate{rsaCertificate}, Certificates: []Certificate{rsaCertificate},
@ -3976,7 +3962,7 @@ func addClientAuthTests() {
ExpectNoCertificateAuthoritiesExtension: true, ExpectNoCertificateAuthoritiesExtension: true,
}, },
}, },
tls13Variant: TLS13Draft22, tls13Variant: TLS13Draft23,
flags: []string{ flags: []string{
"-require-any-client-certificate", "-require-any-client-certificate",
"-use-client-ca-list", "<EMPTY>", "-use-client-ca-list", "<EMPTY>",
@ -4334,7 +4320,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
}) })
tests = append(tests, testCase{ tests = append(tests, testCase{
name: "TLS13Draft22-HelloRetryRequest-Client", name: "TLS13Draft23-HelloRetryRequest-Client",
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
MinVersion: VersionTLS13, MinVersion: VersionTLS13,
@ -4345,21 +4331,21 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
ExpectMissingKeyShare: true, ExpectMissingKeyShare: true,
}, },
}, },
tls13Variant: TLS13Draft22, tls13Variant: TLS13Draft23,
// Cover HelloRetryRequest during an ECDHE-PSK resumption. // Cover HelloRetryRequest during an ECDHE-PSK resumption.
resumeSession: true, resumeSession: true,
}) })
tests = append(tests, testCase{ tests = append(tests, testCase{
testType: serverTest, testType: serverTest,
name: "TLS13Draft22-HelloRetryRequest-Server", name: "TLS13Draft23-HelloRetryRequest-Server",
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
MinVersion: VersionTLS13, MinVersion: VersionTLS13,
// Require a HelloRetryRequest for every curve. // Require a HelloRetryRequest for every curve.
DefaultCurves: []CurveID{}, DefaultCurves: []CurveID{},
}, },
tls13Variant: TLS13Draft22, tls13Variant: TLS13Draft23,
// Cover HelloRetryRequest during an ECDHE-PSK resumption. // Cover HelloRetryRequest during an ECDHE-PSK resumption.
resumeSession: true, resumeSession: true,
}) })
@ -7903,14 +7889,14 @@ func addRenegotiationTests() {
}, },
}) })
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
name: "Renegotiate-Client-TLS13Draft22", name: "Renegotiate-Client-TLS13Draft23",
config: Config{ config: Config{
MaxVersion: VersionTLS12, MaxVersion: VersionTLS12,
Bugs: ProtocolBugs{ Bugs: ProtocolBugs{
FailIfResumeOnRenego: true, FailIfResumeOnRenego: true,
}, },
}, },
tls13Variant: TLS13Draft22, tls13Variant: TLS13Draft23,
renegotiate: 1, renegotiate: 1,
// Test renegotiation after both an initial and resumption // Test renegotiation after both an initial and resumption
// handshake. // handshake.
@ -11717,7 +11703,7 @@ func makePerMessageTests() []perMessageTest {
messageType: typeEndOfEarlyData, messageType: typeEndOfEarlyData,
test: testCase{ test: testCase{
testType: serverTest, testType: serverTest,
name: "TLS13Draft22-EndOfEarlyData", name: "TLS13Draft23-EndOfEarlyData",
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
}, },
@ -11728,7 +11714,7 @@ func makePerMessageTests() []perMessageTest {
ExpectEarlyDataAccepted: true, ExpectEarlyDataAccepted: true,
}, },
}, },
tls13Variant: TLS13Draft22, tls13Variant: TLS13Draft23,
resumeSession: true, resumeSession: true,
flags: []string{"-enable-early-data"}, flags: []string{"-enable-early-data"},
}, },
@ -12275,50 +12261,48 @@ func addTLS13HandshakeTests() {
expectedError: ":WRONG_CURVE:", expectedError: ":WRONG_CURVE:",
}) })
if isDraft22(version.versionWire) { testCases = append(testCases, testCase{
testCases = append(testCases, testCase{ name: "HelloRetryRequest-CipherChange-" + name,
name: "HelloRetryRequest-CipherChange-" + name, config: Config{
config: Config{ MaxVersion: VersionTLS13,
MaxVersion: VersionTLS13, // P-384 requires HelloRetryRequest in BoringSSL.
// P-384 requires HelloRetryRequest in BoringSSL. CurvePreferences: []CurveID{CurveP384},
CurvePreferences: []CurveID{CurveP384}, Bugs: ProtocolBugs{
Bugs: ProtocolBugs{ SendCipherSuite: TLS_AES_128_GCM_SHA256,
SendCipherSuite: TLS_AES_128_GCM_SHA256, SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
},
}, },
tls13Variant: variant, },
shouldFail: true, tls13Variant: variant,
expectedError: ":WRONG_CIPHER_RETURNED:", shouldFail: true,
}) expectedError: ":WRONG_CIPHER_RETURNED:",
})
// Test that the client does not offer a PSK in the second ClientHello if the // Test that the client does not offer a PSK in the second ClientHello if the
// HelloRetryRequest is incompatible with it. // HelloRetryRequest is incompatible with it.
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
testType: clientTest, testType: clientTest,
name: "HelloRetryRequest-NonResumableCipher-" + name, name: "HelloRetryRequest-NonResumableCipher-" + name,
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
CipherSuites: []uint16{ CipherSuites: []uint16{
TLS_AES_128_GCM_SHA256, TLS_AES_128_GCM_SHA256,
},
}, },
resumeConfig: &Config{ },
MaxVersion: VersionTLS13, resumeConfig: &Config{
// P-384 requires HelloRetryRequest in BoringSSL. MaxVersion: VersionTLS13,
CurvePreferences: []CurveID{CurveP384}, // P-384 requires HelloRetryRequest in BoringSSL.
Bugs: ProtocolBugs{ CurvePreferences: []CurveID{CurveP384},
ExpectNoTLS13PSKAfterHRR: true, Bugs: ProtocolBugs{
}, ExpectNoTLS13PSKAfterHRR: true,
CipherSuites: []uint16{
TLS_AES_256_GCM_SHA384,
},
}, },
tls13Variant: variant, CipherSuites: []uint16{
resumeSession: true, TLS_AES_256_GCM_SHA384,
expectResumeRejected: true, },
}) },
} tls13Variant: variant,
resumeSession: true,
expectResumeRejected: true,
})
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
name: "DisabledCurve-HelloRetryRequest-" + name, name: "DisabledCurve-HelloRetryRequest-" + name,
@ -12562,43 +12546,41 @@ func addTLS13HandshakeTests() {
expectedError: ":DECODE_ERROR:", expectedError: ":DECODE_ERROR:",
}) })
if isDraft22(version.versionWire) { testCases = append(testCases, testCase{
testCases = append(testCases, testCase{ name: "UnknownExtensionInCertificateRequest-" + name,
name: "UnknownExtensionInCertificateRequest-" + name, config: Config{
config: Config{ MaxVersion: VersionTLS13,
MaxVersion: VersionTLS13, MinVersion: VersionTLS13,
MinVersion: VersionTLS13, ClientAuth: RequireAnyClientCert,
ClientAuth: RequireAnyClientCert, Bugs: ProtocolBugs{
Bugs: ProtocolBugs{ SendCustomCertificateRequest: 0x1212,
SendCustomCertificateRequest: 0x1212,
},
}, },
tls13Variant: variant, },
flags: []string{ tls13Variant: variant,
"-cert-file", path.Join(*resourceDir, rsaCertificateFile), flags: []string{
"-key-file", path.Join(*resourceDir, rsaKeyFile), "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
}, "-key-file", path.Join(*resourceDir, rsaKeyFile),
}) },
})
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
name: "MissingSignatureAlgorithmsInCertificateRequest-" + name, name: "MissingSignatureAlgorithmsInCertificateRequest-" + name,
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
MinVersion: VersionTLS13, MinVersion: VersionTLS13,
ClientAuth: RequireAnyClientCert, ClientAuth: RequireAnyClientCert,
Bugs: ProtocolBugs{ Bugs: ProtocolBugs{
OmitCertificateRequestAlgorithms: true, OmitCertificateRequestAlgorithms: true,
},
}, },
tls13Variant: variant, },
flags: []string{ tls13Variant: variant,
"-cert-file", path.Join(*resourceDir, rsaCertificateFile), flags: []string{
"-key-file", path.Join(*resourceDir, rsaKeyFile), "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
}, "-key-file", path.Join(*resourceDir, rsaKeyFile),
shouldFail: true, },
expectedError: ":DECODE_ERROR:", shouldFail: true,
}) expectedError: ":DECODE_ERROR:",
} })
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
testType: serverTest, testType: serverTest,
@ -12795,73 +12777,71 @@ func addTLS13HandshakeTests() {
expectedError: ":UNEXPECTED_EXTENSION:", expectedError: ":UNEXPECTED_EXTENSION:",
}) })
if isDraft22(version.versionWire) { testCases = append(testCases, testCase{
testCases = append(testCases, testCase{ testType: clientTest,
testType: clientTest, name: "SkipChangeCipherSpec-Client-" + name,
name: "SkipChangeCipherSpec-Client-" + name, config: Config{
config: Config{ MaxVersion: VersionTLS13,
MaxVersion: VersionTLS13, Bugs: ProtocolBugs{
Bugs: ProtocolBugs{ SkipChangeCipherSpec: true,
SkipChangeCipherSpec: true,
},
}, },
tls13Variant: variant, },
}) tls13Variant: variant,
})
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
testType: serverTest, testType: serverTest,
name: "SkipChangeCipherSpec-Server-" + name, name: "SkipChangeCipherSpec-Server-" + name,
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{ Bugs: ProtocolBugs{
SkipChangeCipherSpec: true, SkipChangeCipherSpec: true,
},
}, },
tls13Variant: variant, },
}) tls13Variant: variant,
})
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
testType: clientTest, testType: clientTest,
name: "TooManyChangeCipherSpec-Client-" + name, name: "TooManyChangeCipherSpec-Client-" + name,
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{ Bugs: ProtocolBugs{
SendExtraChangeCipherSpec: 33, SendExtraChangeCipherSpec: 33,
},
}, },
tls13Variant: variant, },
shouldFail: true, tls13Variant: variant,
expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", shouldFail: true,
}) expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
})
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
testType: serverTest, testType: serverTest,
name: "TooManyChangeCipherSpec-Server-" + name, name: "TooManyChangeCipherSpec-Server-" + name,
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{ Bugs: ProtocolBugs{
SendExtraChangeCipherSpec: 33, SendExtraChangeCipherSpec: 33,
},
}, },
tls13Variant: variant, },
shouldFail: true, tls13Variant: variant,
expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", shouldFail: true,
}) expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
})
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
name: "SendPostHandshakeChangeCipherSpec-" + name, name: "SendPostHandshakeChangeCipherSpec-" + name,
config: Config{ config: Config{
MaxVersion: VersionTLS13, MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{ Bugs: ProtocolBugs{
SendPostHandshakeChangeCipherSpec: true, SendPostHandshakeChangeCipherSpec: true,
},
}, },
tls13Variant: variant, },
shouldFail: true, tls13Variant: variant,
expectedError: ":UNEXPECTED_RECORD:", shouldFail: true,
expectedLocalError: "remote error: unexpected message", expectedError: ":UNEXPECTED_RECORD:",
}) expectedLocalError: "remote error: unexpected message",
} })
fooString := "foo" fooString := "foo"
barString := "bar" barString := "bar"
@ -13243,13 +13223,6 @@ func addTLS13HandshakeTests() {
expectedError: ":BAD_DECRYPT:", 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{ testCases = append(testCases, testCase{
testType: serverTest, testType: serverTest,
name: "EarlyData-UnexpectedHandshake-Server-" + name, name: "EarlyData-UnexpectedHandshake-Server-" + name,
@ -13267,7 +13240,7 @@ func addTLS13HandshakeTests() {
tls13Variant: variant, tls13Variant: variant,
resumeSession: true, resumeSession: true,
shouldFail: true, shouldFail: true,
expectedError: expectedError, expectedError: ":UNEXPECTED_MESSAGE:",
expectedLocalError: "remote error: unexpected message", expectedLocalError: "remote error: unexpected message",
flags: []string{ flags: []string{
"-enable-early-data", "-enable-early-data",
@ -13346,32 +13319,30 @@ func addTLS13HandshakeTests() {
expectedLocalError: "remote error: error decrypting message", expectedLocalError: "remote error: error decrypting message",
}) })
if isDraft22(version.versionWire) { testCases = append(testCases, testCase{
testCases = append(testCases, testCase{ testType: serverTest,
testType: serverTest, name: "Server-NonEmptyEndOfEarlyData-" + name,
name: "Server-NonEmptyEndOfEarlyData-" + name, config: Config{
config: Config{ MaxVersion: VersionTLS13,
MaxVersion: VersionTLS13, },
resumeConfig: &Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendEarlyData: [][]byte{{1, 2, 3, 4}},
ExpectEarlyDataAccepted: true,
NonEmptyEndOfEarlyData: true,
}, },
resumeConfig: &Config{ },
MaxVersion: VersionTLS13, resumeSession: true,
Bugs: ProtocolBugs{ flags: []string{
SendEarlyData: [][]byte{{1, 2, 3, 4}}, "-enable-early-data",
ExpectEarlyDataAccepted: true, "-expect-ticket-supports-early-data",
NonEmptyEndOfEarlyData: true, "-expect-accept-early-data",
}, },
}, tls13Variant: variant,
resumeSession: true, shouldFail: true,
flags: []string{ expectedError: ":DECODE_ERROR:",
"-enable-early-data", })
"-expect-ticket-supports-early-data",
"-expect-accept-early-data",
},
tls13Variant: variant,
shouldFail: true,
expectedError: ":DECODE_ERROR:",
})
}
testCases = append(testCases, testCase{ testCases = append(testCases, testCase{
testType: serverTest, testType: serverTest,

View File

@ -58,88 +58,63 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
return ssl_hs_read_message; return ssl_hs_read_message;
} }
CBS extensions; // Queue up a ChangeCipherSpec for whenever we next send something. This
uint16_t cipher_suite = 0; // will be before the second ClientHello. If we offered early data, this was
if (ssl_is_draft22(ssl->version)) { // already done.
// Queue up a ChangeCipherSpec for whenever we next send something. This if (!hs->early_data_offered &&
// will be before the second ClientHello. If we offered early data, this was !ssl->method->add_change_cipher_spec(ssl)) {
// already done. return ssl_hs_error;
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;
}
} }
if (ssl_is_draft22(ssl->version)) { if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite); return ssl_hs_error;
// 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; 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) || if (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
!hs->transcript.UpdateForHelloRetryRequest()) { hs->tls13_state = state_read_server_hello;
return ssl_hs_error; 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; bool have_cookie, have_key_share, have_supported_versions;
CBS cookie, key_share, supported_versions; CBS cookie, key_share, supported_versions;
SSL_EXTENSION_TYPE ext_types[] = { SSL_EXTENSION_TYPE ext_types[] = {
{ssl_is_draft23(ssl->version) ? (uint16_t)TLSEXT_TYPE_new_key_share {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
: (uint16_t)TLSEXT_TYPE_old_key_share,
&have_key_share, &key_share},
{TLSEXT_TYPE_cookie, &have_cookie, &cookie}, {TLSEXT_TYPE_cookie, &have_cookie, &cookie},
{TLSEXT_TYPE_supported_versions, &have_supported_versions, {TLSEXT_TYPE_supported_versions, &have_supported_versions,
&supported_versions}, &supported_versions},
@ -153,11 +128,6 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
return ssl_hs_error; 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) { if (!have_cookie && !have_key_share) {
OPENSSL_PUT_ERROR(SSL, SSL_R_EMPTY_HELLO_RETRY_REQUEST); OPENSSL_PUT_ERROR(SSL, SSL_R_EMPTY_HELLO_RETRY_REQUEST);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@ -274,8 +244,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
} }
// Forbid a second HelloRetryRequest. // Forbid a second HelloRetryRequest.
if (ssl_is_draft22(ssl->version) && if (CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
return ssl_hs_error; return ssl_hs_error;
@ -295,8 +264,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
} }
// Check that the cipher matches the one in the HelloRetryRequest. // Check that the cipher matches the one in the HelloRetryRequest.
if (ssl_is_draft22(ssl->version) && if (hs->received_hello_retry_request &&
hs->received_hello_retry_request &&
hs->new_cipher != cipher) { hs->new_cipher != cipher) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@ -308,9 +276,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
have_supported_versions = false; have_supported_versions = false;
CBS key_share, pre_shared_key, supported_versions; CBS key_share, pre_shared_key, supported_versions;
SSL_EXTENSION_TYPE ext_types[] = { SSL_EXTENSION_TYPE ext_types[] = {
{ssl_is_draft23(ssl->version) ? (uint16_t)TLSEXT_TYPE_new_key_share {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
: (uint16_t)TLSEXT_TYPE_old_key_share,
&have_key_share, &key_share},
{TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key}, {TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key},
{TLSEXT_TYPE_supported_versions, &have_supported_versions, {TLSEXT_TYPE_supported_versions, &have_supported_versions,
&supported_versions}, &supported_versions},
@ -416,13 +382,6 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
} }
if (!hs->early_data_offered) { 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 // If not sending early data, set client traffic keys now so that alerts are
// encrypted. // encrypted.
if (!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret, if (!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
@ -515,75 +474,45 @@ static enum ssl_hs_wait_t do_read_certificate_request(SSL_HANDSHAKE *hs) {
} }
if (ssl_is_draft22(ssl->version)) { bool have_sigalgs = false, have_ca = false;
bool have_sigalgs = false, have_ca = false; CBS sigalgs, ca;
CBS sigalgs, ca; const SSL_EXTENSION_TYPE ext_types[] = {
const SSL_EXTENSION_TYPE ext_types[] = { {TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs},
{TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs}, {TLSEXT_TYPE_certificate_authorities, &have_ca, &ca},
{TLSEXT_TYPE_certificate_authorities, &have_ca, &ca}, };
};
CBS body = msg.body, context, extensions, supported_signature_algorithms; CBS body = msg.body, context, extensions, supported_signature_algorithms;
uint8_t alert = SSL_AD_DECODE_ERROR; uint8_t alert = SSL_AD_DECODE_ERROR;
if (!CBS_get_u8_length_prefixed(&body, &context) || if (!CBS_get_u8_length_prefixed(&body, &context) ||
// The request context is always empty during the handshake. // The request context is always empty during the handshake.
CBS_len(&context) != 0 || CBS_len(&context) != 0 ||
!CBS_get_u16_length_prefixed(&body, &extensions) || !CBS_get_u16_length_prefixed(&body, &extensions) ||
CBS_len(&body) != 0 || CBS_len(&body) != 0 ||
!ssl_parse_extensions(&extensions, &alert, ext_types, !ssl_parse_extensions(&extensions, &alert, ext_types,
OPENSSL_ARRAY_SIZE(ext_types), OPENSSL_ARRAY_SIZE(ext_types),
1 /* accept unknown */) || 1 /* accept unknown */) ||
(have_ca && CBS_len(&ca) == 0) || (have_ca && CBS_len(&ca) == 0) ||
!have_sigalgs || !have_sigalgs ||
!CBS_get_u16_length_prefixed(&sigalgs, !CBS_get_u16_length_prefixed(&sigalgs,
&supported_signature_algorithms) || &supported_signature_algorithms) ||
CBS_len(&supported_signature_algorithms) == 0 || CBS_len(&supported_signature_algorithms) == 0 ||
!tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) { !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert); ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error; return ssl_hs_error;
} }
if (have_ca) { if (have_ca) {
hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &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 (!hs->ca_names) { if (!hs->ca_names) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert); ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error; return ssl_hs_error;
} }
} else {
// Ignore extensions. hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null());
CBS extensions; if (!hs->ca_names) {
if (!CBS_get_u16_length_prefixed(&body, &extensions) || OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
CBS_len(&body) != 0) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error; return ssl_hs_error;
} }
} }
@ -670,19 +599,12 @@ static enum ssl_hs_wait_t do_send_end_of_early_data(SSL_HANDSHAKE *hs) {
if (ssl->s3->early_data_accepted) { if (ssl->s3->early_data_accepted) {
hs->can_early_write = false; hs->can_early_write = false;
if (ssl_is_draft22(ssl->version)) { ScopedCBB cbb;
ScopedCBB cbb; CBB body;
CBB body; if (!ssl->method->init_message(ssl, cbb.get(), &body,
if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_END_OF_EARLY_DATA) ||
SSL3_MT_END_OF_EARLY_DATA) || !ssl_add_message_cbb(ssl, cbb.get())) {
!ssl_add_message_cbb(ssl, cbb.get())) { return ssl_hs_error;
return ssl_hs_error;
}
} else {
if (!ssl->method->add_alert(ssl, SSL3_AL_WARNING,
TLS1_AD_END_OF_EARLY_DATA)) {
return ssl_hs_error;
}
} }
} }
@ -909,8 +831,7 @@ int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg) {
CBS body = msg.body, ticket_nonce, ticket, extensions; CBS body = msg.body, ticket_nonce, ticket, extensions;
if (!CBS_get_u32(&body, &server_timeout) || if (!CBS_get_u32(&body, &server_timeout) ||
!CBS_get_u32(&body, &session->ticket_age_add) || !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_get_u16_length_prefixed(&body, &ticket) ||
!CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen) || !CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen) ||
!CBS_get_u16_length_prefixed(&body, &extensions) || !CBS_get_u16_length_prefixed(&body, &extensions) ||
@ -933,11 +854,8 @@ int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg) {
// Parse out the extensions. // Parse out the extensions.
bool have_early_data_info = false; bool have_early_data_info = false;
CBS early_data_info; 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[] = { 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; uint8_t alert = SSL_AD_DECODE_ERROR;

View File

@ -66,13 +66,11 @@ int tls13_init_early_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *psk,
psk_len, hs->secret, hs->hash_len); psk_len, hs->secret, hs->hash_len);
} }
static int hkdf_expand_label(uint8_t *out, uint16_t version, static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
const EVP_MD *digest, const uint8_t *secret, const uint8_t *secret, size_t secret_len,
size_t secret_len, const char *label, const char *label, size_t label_len,
size_t label_len, const uint8_t *hash, const uint8_t *hash, size_t hash_len, size_t len) {
size_t hash_len, size_t len) { static const char kTLS13LabelVersion[] = "tls13 ";
const char *kTLS13LabelVersion =
ssl_is_draft22(version) ? "tls13 " : "TLS 1.3, ";
ScopedCBB cbb; ScopedCBB cbb;
CBB child; CBB child;
@ -101,23 +99,18 @@ static const char kTLS13LabelDerived[] = "derived";
int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in, int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
size_t len) { 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 (!hkdf_expand_label(hs->secret, hs->transcript.Digest(), hs->secret,
if (ssl_is_draft22(ssl->version)) { hs->hash_len, kTLS13LabelDerived,
uint8_t derive_context[EVP_MAX_MD_SIZE]; strlen(kTLS13LabelDerived), derive_context,
unsigned derive_context_len; derive_context_len, hs->hash_len)) {
if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len, return 0;
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;
}
} }
return HKDF_extract(hs->secret, &hs->hash_len, hs->transcript.Digest(), in, return HKDF_extract(hs->secret, &hs->hash_len, hs->transcript.Digest(), in,
@ -135,10 +128,9 @@ static int derive_secret(SSL_HANDSHAKE *hs, uint8_t *out, size_t len,
return 0; return 0;
} }
return hkdf_expand_label(out, SSL_get_session(hs->ssl)->ssl_version, return hkdf_expand_label(out, hs->transcript.Digest(), hs->secret,
hs->transcript.Digest(), hs->secret, hs->hash_len, hs->hash_len, label, label_len, context_hash,
label, label_len, context_hash, context_hash_len, context_hash_len, len);
len);
} }
int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction, int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
@ -165,16 +157,16 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
// Derive the key. // Derive the key.
size_t key_len = EVP_AEAD_key_length(aead); size_t key_len = EVP_AEAD_key_length(aead);
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH]; uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
if (!hkdf_expand_label(key, session->ssl_version, digest, traffic_secret, if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, "key",
traffic_secret_len, "key", 3, NULL, 0, key_len)) { 3, NULL, 0, key_len)) {
return 0; return 0;
} }
// Derive the IV. // Derive the IV.
size_t iv_len = EVP_AEAD_nonce_length(aead); size_t iv_len = EVP_AEAD_nonce_length(aead);
uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH]; uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
if (!hkdf_expand_label(iv, session->ssl_version, digest, traffic_secret, if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, "iv",
traffic_secret_len, "iv", 2, NULL, 0, iv_len)) { 2, NULL, 0, iv_len)) {
return 0; return 0;
} }
@ -210,45 +202,26 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
return 1; return 1;
} }
static const char kTLS13LabelExporter[] = "exporter master secret";
static const char kTLS13LabelEarlyExporter[] = "early exporter master secret";
static const char kTLS13LabelClientEarlyTraffic[] = static const char kTLS13LabelExporter[] = "exp master";
"client early traffic secret"; static const char kTLS13LabelEarlyExporter[] = "e exp master";
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 kTLS13Draft22LabelExporter[] = "exp master"; static const char kTLS13LabelClientEarlyTraffic[] = "c e traffic";
static const char kTLS13Draft22LabelEarlyExporter[] = "e exp master"; static const char kTLS13LabelClientHandshakeTraffic[] = "c hs traffic";
static const char kTLS13LabelServerHandshakeTraffic[] = "s hs traffic";
static const char kTLS13Draft22LabelClientEarlyTraffic[] = "c e traffic"; static const char kTLS13LabelClientApplicationTraffic[] = "c ap traffic";
static const char kTLS13Draft22LabelClientHandshakeTraffic[] = "c hs traffic"; static const char kTLS13LabelServerApplicationTraffic[] = "s ap traffic";
static const char kTLS13Draft22LabelServerHandshakeTraffic[] = "s hs traffic";
static const char kTLS13Draft22LabelClientApplicationTraffic[] = "c ap traffic";
static const char kTLS13Draft22LabelServerApplicationTraffic[] = "s ap traffic";
int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) { int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl; 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, 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", !ssl_log_secret(ssl, "CLIENT_EARLY_TRAFFIC_SECRET",
hs->early_traffic_secret, hs->hash_len) || hs->early_traffic_secret, hs->hash_len) ||
!derive_secret(hs, ssl->s3->early_exporter_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; return 0;
} }
ssl->s3->early_exporter_secret_len = hs->hash_len; ssl->s3->early_exporter_secret_len = hs->hash_len;
@ -257,18 +230,14 @@ int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) {
int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) { int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl; 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, 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", ssl_log_secret(ssl, "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
hs->client_handshake_secret, hs->hash_len) && hs->client_handshake_secret, hs->hash_len) &&
derive_secret(hs, hs->server_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", ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
hs->server_handshake_secret, hs->hash_len); hs->server_handshake_secret, hs->hash_len);
} }
@ -276,32 +245,23 @@ int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) {
int tls13_derive_application_secrets(SSL_HANDSHAKE *hs) { int tls13_derive_application_secrets(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl; SSL *const ssl = hs->ssl;
ssl->s3->exporter_secret_len = hs->hash_len; 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, 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", ssl_log_secret(ssl, "CLIENT_TRAFFIC_SECRET_0",
hs->client_traffic_secret_0, hs->hash_len) && hs->client_traffic_secret_0, hs->hash_len) &&
derive_secret(hs, hs->server_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", ssl_log_secret(ssl, "SERVER_TRAFFIC_SECRET_0",
hs->server_traffic_secret_0, hs->hash_len) && hs->server_traffic_secret_0, hs->hash_len) &&
derive_secret(hs, ssl->s3->exporter_secret, 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, ssl_log_secret(ssl, "EXPORTER_SECRET", ssl->s3->exporter_secret,
hs->hash_len); hs->hash_len);
} }
static const char kTLS13LabelApplicationTraffic[] = static const char kTLS13LabelApplicationTraffic[] = "traffic upd";
"application traffic secret";
static const char kTLS13Draft22LabelApplicationTraffic[] = "traffic upd";
int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) { int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
uint8_t *secret; uint8_t *secret;
@ -314,35 +274,27 @@ int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
secret_len = ssl->s3->write_traffic_secret_len; 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)); const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl));
if (!hkdf_expand_label(secret, ssl->version, digest, secret, secret_len, if (!hkdf_expand_label(
traffic_label, strlen(traffic_label), NULL, 0, secret, digest, secret, secret_len, kTLS13LabelApplicationTraffic,
secret_len)) { strlen(kTLS13LabelApplicationTraffic), NULL, 0, secret_len)) {
return 0; return 0;
} }
return tls13_set_traffic_key(ssl, direction, secret, secret_len); return tls13_set_traffic_key(ssl, direction, secret, secret_len);
} }
static const char kTLS13LabelResumption[] = "resumption master secret"; static const char kTLS13LabelResumption[] = "res master";
static const char kTLS13Draft22LabelResumption[] = "res master";
int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs) { int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs) {
if (hs->hash_len > SSL_MAX_MASTER_KEY_LENGTH) { if (hs->hash_len > SSL_MAX_MASTER_KEY_LENGTH) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0; return 0;
} }
const char *resumption_label = ssl_is_draft22(hs->ssl->version)
? kTLS13Draft22LabelResumption
: kTLS13LabelResumption;
hs->new_session->master_key_length = hs->hash_len; hs->new_session->master_key_length = hs->hash_len;
return derive_secret(hs, hs->new_session->master_key, return derive_secret(hs, hs->new_session->master_key,
hs->new_session->master_key_length, resumption_label, hs->new_session->master_key_length,
strlen(resumption_label)); kTLS13LabelResumption, strlen(kTLS13LabelResumption));
} }
static const char kTLS13LabelFinished[] = "finished"; static const char kTLS13LabelFinished[] = "finished";
@ -355,9 +307,8 @@ static int tls13_verify_data(const EVP_MD *digest, uint16_t version,
uint8_t *context, size_t context_len) { uint8_t *context, size_t context_len) {
uint8_t key[EVP_MAX_MD_SIZE]; uint8_t key[EVP_MAX_MD_SIZE];
unsigned len; unsigned len;
if (!hkdf_expand_label(key, version, digest, secret, hash_len, if (!hkdf_expand_label(key, digest, secret, hash_len, kTLS13LabelFinished,
kTLS13LabelFinished, strlen(kTLS13LabelFinished), NULL, strlen(kTLS13LabelFinished), NULL, 0, hash_len) ||
0, hash_len) ||
HMAC(digest, key, hash_len, context, context_len, out, &len) == NULL) { HMAC(digest, key, hash_len, context, context_len, out, &len) == NULL) {
return 0; return 0;
} }
@ -388,14 +339,9 @@ int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len,
static const char kTLS13LabelResumptionPSK[] = "resumption"; static const char kTLS13LabelResumptionPSK[] = "resumption";
bool tls13_derive_session_psk(SSL_SESSION *session, Span<const uint8_t> nonce) { 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); const EVP_MD *digest = ssl_session_get_digest(session);
return hkdf_expand_label(session->master_key, session->ssl_version, digest, return hkdf_expand_label(session->master_key, digest, session->master_key,
session->master_key, session->master_key_length, session->master_key_length, kTLS13LabelResumptionPSK,
kTLS13LabelResumptionPSK,
strlen(kTLS13LabelResumptionPSK), nonce.data(), strlen(kTLS13LabelResumptionPSK), nonce.data(),
nonce.size(), session->master_key_length); nonce.size(), session->master_key_length);
} }
@ -412,14 +358,6 @@ int tls13_export_keying_material(SSL *ssl, Span<uint8_t> out,
return 0; 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)); const EVP_MD *digest = ssl_session_get_digest(SSL_get_session(ssl));
uint8_t hash[EVP_MAX_MD_SIZE]; uint8_t hash[EVP_MAX_MD_SIZE];
@ -432,18 +370,16 @@ int tls13_export_keying_material(SSL *ssl, Span<uint8_t> out,
nullptr) && nullptr) &&
EVP_Digest(nullptr, 0, export_context, &export_context_len, digest, EVP_Digest(nullptr, 0, export_context, &export_context_len, digest,
nullptr) && nullptr) &&
hkdf_expand_label(derived_secret, version, digest, secret.data(), hkdf_expand_label(derived_secret, digest, secret.data(), secret.size(),
secret.size(), label.data(), label.size(), label.data(), label.size(), export_context,
export_context, export_context_len, export_context_len, derived_secret_len) &&
derived_secret_len) && hkdf_expand_label(out.data(), digest, derived_secret,
hkdf_expand_label(out.data(), version, digest, derived_secret,
derived_secret_len, kTLS13LabelExportKeying, derived_secret_len, kTLS13LabelExportKeying,
strlen(kTLS13LabelExportKeying), hash, hash_len, strlen(kTLS13LabelExportKeying), hash, hash_len,
out.size()); out.size());
} }
static const char kTLS13LabelPSKBinder[] = "resumption psk binder key"; static const char kTLS13LabelPSKBinder[] = "res binder";
static const char kTLS13Draft22LabelPSKBinder[] = "res binder";
static int tls13_psk_binder(uint8_t *out, uint16_t version, static int tls13_psk_binder(uint8_t *out, uint16_t version,
const EVP_MD *digest, uint8_t *psk, size_t psk_len, const EVP_MD *digest, uint8_t *psk, size_t psk_len,
@ -461,15 +397,12 @@ static int tls13_psk_binder(uint8_t *out, uint16_t version,
NULL, 0)) { NULL, 0)) {
return 0; return 0;
} }
const char *binder_label = ssl_is_draft22(version)
? kTLS13Draft22LabelPSKBinder
: kTLS13LabelPSKBinder;
uint8_t binder_key[EVP_MAX_MD_SIZE] = {0}; uint8_t binder_key[EVP_MAX_MD_SIZE] = {0};
size_t len; size_t len;
if (!hkdf_expand_label(binder_key, version, digest, early_secret, hash_len, if (!hkdf_expand_label(binder_key, digest, early_secret, hash_len,
binder_label, strlen(binder_label), binder_context, kTLS13LabelPSKBinder, strlen(kTLS13LabelPSKBinder),
binder_context_len, hash_len) || binder_context, binder_context_len, hash_len) ||
!tls13_verify_data(digest, version, out, &len, binder_key, hash_len, !tls13_verify_data(digest, version, out, &len, binder_key, hash_len,
context, context_len)) { context, context_len)) {
return 0; return 0;

View File

@ -63,15 +63,10 @@ static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, bool *out_need_retry,
SSL *const ssl = hs->ssl; SSL *const ssl = hs->ssl;
*out_need_retry = false; *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. // We only support connections that include an ECDHE key exchange.
CBS key_share; CBS key_share;
if (!ssl_client_hello_get_extension(client_hello, &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); OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
return 0; return 0;
@ -187,9 +182,8 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) {
SSL3_MT_NEW_SESSION_TICKET) || SSL3_MT_NEW_SESSION_TICKET) ||
!CBB_add_u32(&body, session->timeout) || !CBB_add_u32(&body, session->timeout) ||
!CBB_add_u32(&body, session->ticket_age_add) || !CBB_add_u32(&body, session->ticket_age_add) ||
(ssl_is_draft22(ssl->version) && !CBB_add_u8_length_prefixed(&body, &nonce_cbb) ||
(!CBB_add_u8_length_prefixed(&body, &nonce_cbb) || !CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)) ||
!CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)))) ||
!CBB_add_u16_length_prefixed(&body, &ticket) || !CBB_add_u16_length_prefixed(&body, &ticket) ||
!tls13_derive_session_psk(session.get(), nonce) || !tls13_derive_session_psk(session.get(), nonce) ||
!ssl_encrypt_ticket(ssl, &ticket, session.get()) || !ssl_encrypt_ticket(ssl, &ticket, session.get()) ||
@ -199,9 +193,7 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) {
if (ssl->cert->enable_early_data) { if (ssl->cert->enable_early_data) {
CBB early_data_info; CBB early_data_info;
if (!CBB_add_u16(&extensions, ssl_is_draft22(ssl->version) if (!CBB_add_u16(&extensions, TLSEXT_TYPE_early_data) ||
? TLSEXT_TYPE_early_data
: TLSEXT_TYPE_ticket_early_data_info) ||
!CBB_add_u16_length_prefixed(&extensions, &early_data_info) || !CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
!CBB_add_u32(&early_data_info, session->ticket_max_early_data) || !CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
!CBB_flush(&extensions)) { !CBB_flush(&extensions)) {
@ -479,8 +471,7 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
ssl->s3->early_data_accepted = false; ssl->s3->early_data_accepted = false;
ssl->s3->skip_early_data = true; ssl->s3->skip_early_data = true;
ssl->method->next_message(ssl); ssl->method->next_message(ssl);
if (ssl_is_draft22(ssl->version) && if (!hs->transcript.UpdateForHelloRetryRequest()) {
!hs->transcript.UpdateForHelloRetryRequest()) {
return ssl_hs_error; return ssl_hs_error;
} }
hs->tls13_state = state_send_hello_retry_request; hs->tls13_state = state_send_hello_retry_request;
@ -498,52 +489,30 @@ static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl; SSL *const ssl = hs->ssl;
if (ssl_is_draft22(ssl->version)) { ScopedCBB cbb;
ScopedCBB cbb; CBB body, session_id, extensions;
CBB body, session_id, extensions; uint16_t group_id;
uint16_t group_id; if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
if (!ssl->method->init_message(ssl, cbb.get(), &body, !CBB_add_u16(&body, TLS1_2_VERSION) ||
SSL3_MT_SERVER_HELLO) || !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) ||
!CBB_add_u16(&body, TLS1_2_VERSION) || !CBB_add_u8_length_prefixed(&body, &session_id) ||
!CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) || !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
!CBB_add_u8_length_prefixed(&body, &session_id) || !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
!CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || !CBB_add_u8(&body, 0 /* no compression */) ||
!CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) || !tls1_get_shared_group(hs, &group_id) ||
!CBB_add_u8(&body, 0 /* no compression */) || !CBB_add_u16_length_prefixed(&body, &extensions) ||
!tls1_get_shared_group(hs, &group_id) || !CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) ||
!CBB_add_u16_length_prefixed(&body, &extensions) || !CBB_add_u16(&extensions, 2 /* length */) ||
!CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) || !CBB_add_u16(&extensions, ssl->version) ||
!CBB_add_u16(&extensions, 2 /* length */) || !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
!CBB_add_u16(&extensions, ssl->version) || !CBB_add_u16(&extensions, 2 /* length */) ||
!CBB_add_u16(&extensions, ssl_is_draft23(ssl->version) !CBB_add_u16(&extensions, group_id) ||
? TLSEXT_TYPE_new_key_share !ssl_add_message_cbb(ssl, cbb.get())) {
: TLSEXT_TYPE_old_key_share) || return ssl_hs_error;
!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)) { if (!ssl->method->add_change_cipher_spec(ssl)) {
return ssl_hs_error; 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;
}
} }
hs->sent_hello_retry_request = true; hs->sent_hello_retry_request = true;
@ -608,7 +577,7 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
return ssl_hs_error; 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)) { !ssl->method->add_change_cipher_spec(ssl)) {
return ssl_hs_error; return ssl_hs_error;
} }
@ -640,48 +609,34 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
// Send a CertificateRequest, if necessary. // Send a CertificateRequest, if necessary.
if (hs->cert_request) { if (hs->cert_request) {
if (ssl_is_draft22(ssl->version)) { CBB cert_request_extensions, sigalg_contents, sigalgs_cbb;
CBB cert_request_extensions, sigalg_contents, sigalgs_cbb; if (!ssl->method->init_message(ssl, cbb.get(), &body,
if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE_REQUEST) ||
SSL3_MT_CERTIFICATE_REQUEST) || !CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */) || !CBB_add_u16_length_prefixed(&body, &cert_request_extensions) ||
!CBB_add_u16_length_prefixed(&body, &cert_request_extensions) || !CBB_add_u16(&cert_request_extensions,
!CBB_add_u16(&cert_request_extensions, TLSEXT_TYPE_signature_algorithms) ||
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, !CBB_add_u16_length_prefixed(&cert_request_extensions,
&sigalg_contents) || &ca_contents) ||
!CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) || !ssl_add_client_CA_list(ssl, &ca_contents) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) { !CBB_flush(&cert_request_extensions)) {
return ssl_hs_error; return ssl_hs_error;
} }
}
if (ssl_has_client_CAs(ssl)) { if (!ssl_add_message_cbb(ssl, cbb.get())) {
CBB ca_contents; return ssl_hs_error;
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;
}
} }
} }
@ -738,13 +693,11 @@ static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
// the wire sooner and also avoids triggering a write on |SSL_read| when // the wire sooner and also avoids triggering a write on |SSL_read| when
// processing the client Finished. This requires computing the client // processing the client Finished. This requires computing the client
// Finished early. See draft-ietf-tls-tls13-18, section 4.5.1. // 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,
static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0, 0, 0};
0, 0}; if (!hs->transcript.Update(kEndOfEarlyData)) {
if (!hs->transcript.Update(kEndOfEarlyData)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return ssl_hs_error;
return ssl_hs_error;
}
} }
size_t finished_len; size_t finished_len;
@ -801,22 +754,20 @@ static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) {
// If early data was not accepted, the EndOfEarlyData and ChangeCipherSpec // If early data was not accepted, the EndOfEarlyData and ChangeCipherSpec
// message will be in the discarded early data. // message will be in the discarded early data.
if (hs->ssl->s3->early_data_accepted) { if (hs->ssl->s3->early_data_accepted) {
if (ssl_is_draft22(ssl->version)) { SSLMessage msg;
SSLMessage msg; if (!ssl->method->get_message(ssl, &msg)) {
if (!ssl->method->get_message(ssl, &msg)) { return ssl_hs_read_message;
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 (!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, if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,

View File

@ -356,15 +356,6 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type,
} }
if (type == SSL3_RT_ALERT) { 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); return ssl_process_alert(ssl, out_alert, *out);
} }

View File

@ -332,12 +332,8 @@ static bool DoConnection(SSL_CTX *ctx,
} }
static bool GetTLS13Variant(tls13_variant_t *out, const std::string &in) { static bool GetTLS13Variant(tls13_variant_t *out, const std::string &in) {
if (in == "draft22") { if (in == "draft23") {
*out = tls13_draft22; *out = tls13_default;
return true;
}
if (in == "experiment2") {
*out = tls13_experiment2;
return true; return true;
} }
return false; return false;

View File

@ -308,7 +308,7 @@ bool Server(const std::vector<std::string> &args) {
} }
if (args_map.count("-tls13-variant") != 0) { 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) { if (args_map.count("-debug") != 0) {