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>kris/onging/CECPQ3_patch15
@@ -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 | ||||
@@ -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 | ||||
@@ -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) && | |||||
!ssl->method->add_change_cipher_spec(ssl)) { | |||||
if (!ssl->method->add_change_cipher_spec(ssl)) { | |||||
return ssl_hs_error; | return ssl_hs_error; | ||||
} | } | ||||
@@ -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 | ||||
@@ -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; | ||||
@@ -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())); | ||||
@@ -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 || | |||||
version == TLS1_3_DRAFT23_VERSION || | |||||
version == TLS1_3_EXPERIMENT2_VERSION) { | |||||
if (version == TLS1_3_DRAFT23_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; | ||||
@@ -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) | |||||
? TLSEXT_TYPE_new_key_share | |||||
: TLSEXT_TYPE_old_key_share) || | |||||
if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) || | |||||
!CBB_add_u16_length_prefixed(out, &contents) || | !CBB_add_u16_length_prefixed(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) | |||||
? TLSEXT_TYPE_new_key_share | |||||
: TLSEXT_TYPE_old_key_share) || | |||||
!CBB_add_u16(out, TLSEXT_TYPE_key_share) || | |||||
!CBB_add_u16_length_prefixed(out, &kse_bytes) || | !CBB_add_u16_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, | |||||
// This is added by TLSEXT_TYPE_new_key_share's callback. | |||||
NULL, | |||||
dont_add_clienthello, | |||||
forbid_parse_serverhello, | |||||
ignore_parse_clienthello, | |||||
dont_add_serverhello, | |||||
}, | |||||
{ | |||||
TLSEXT_TYPE_new_key_share, | |||||
TLSEXT_TYPE_key_share, | |||||
NULL, | NULL, | ||||
ext_key_share_add_clienthello, | ext_key_share_add_clienthello, | ||||
forbid_parse_serverhello, | forbid_parse_serverhello, | ||||
@@ -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 | |||||
tls13Draft22Version = 0x7f16 | |||||
tls13Draft23Version = 0x7f17 | |||||
tls13Draft23Version = 0x7f17 | |||||
) | ) | ||||
const ( | const ( | ||||
TLS13Draft23 = 0 | |||||
TLS13Experiment2 = 1 | |||||
TLS13Draft22 = 2 | |||||
TLS13Draft23 = 0 | |||||
) | ) | ||||
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) || | |||||
(c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version) || | |||||
(c.TLS13Variant != TLS13Draft22 && wireVers == tls13Draft22Version) { | |||||
if c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version { | |||||
return 0, false | return 0, false | ||||
} | } | ||||
@@ -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() | |||||
exporterKeyingLabel := []byte("exporter") | |||||
contextHash := hash.New() | |||||
contextHash.Write(context) | |||||
exporterContext := hash.New().Sum(nil) | |||||
derivedSecret := hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, secret, label, exporterContext, hash.Size()) | |||||
return hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length) | |||||
} | |||||
return hkdfExpandLabel(cipherSuite.hash(), c.wireVersion, secret, label, context, length) | |||||
hash := cipherSuite.hash() | |||||
exporterKeyingLabel := []byte("exporter") | |||||
contextHash := hash.New() | |||||
contextHash.Write(context) | |||||
exporterContext := hash.New().Sum(nil) | |||||
derivedSecret := hkdfExpandLabel(cipherSuite.hash(), secret, label, exporterContext, hash.Size()) | |||||
return hkdfExpandLabel(cipherSuite.hash(), derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length) | |||||
} | } | ||||
// ExportKeyingMaterial exports keying material from the current connection | // 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) | ||||
@@ -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 | |||||
if isDraft22(session.wireVersion) { | |||||
earlyTrafficSecret = finishedHash.deriveSecret(earlyTrafficLabelDraft22) | |||||
c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabelDraft22) | |||||
} else { | |||||
earlyTrafficSecret = finishedHash.deriveSecret(earlyTrafficLabel) | |||||
c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel) | |||||
} | |||||
earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel) | |||||
c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel) | |||||
c.useOutTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret) | 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 | |||||
// be attached to the first flight, not the second flight. | |||||
if err := c.readTLS13ChangeCipherSpec(); err != nil { | |||||
return err | |||||
} | |||||
// Explicitly read the ChangeCipherSpec now; it should | |||||
// be attached to the first flight, not the second flight. | |||||
if err := c.readTLS13ChangeCipherSpec(); err != nil { | |||||
return err | |||||
} | } | ||||
c.out.resetCipher() | 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() | |||||
if err != nil { | |||||
return err | |||||
} | |||||
err = hs.finishedHash.UpdateForHelloRetryRequest() | |||||
if err != nil { | |||||
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) | |||||
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) | |||||
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel) | |||||
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel) | |||||
if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret); err != nil { | 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 | |||||
serverLabel = serverApplicationTrafficLabel | |||||
exportLabel := exporterLabel | |||||
if isDraft22(c.wireVersion) { | |||||
clientLabel = clientApplicationTrafficLabelDraft22 | |||||
serverLabel = serverApplicationTrafficLabelDraft22 | |||||
exportLabel = exporterLabelDraft22 | |||||
} | |||||
clientTrafficSecret := hs.finishedHash.deriveSecret(clientLabel) | |||||
serverTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) | |||||
c.exporterSecret = hs.finishedHash.deriveSecret(exportLabel) | |||||
clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel) | |||||
serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel) | |||||
c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel) | |||||
// Switch to application data keys on read. In particular, any alerts | // 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.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData | |||||
c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal()) | |||||
hs.writeClientHash(endOfEarlyData.marshal()) | |||||
} else { | |||||
c.sendAlert(alertEndOfEarlyData) | |||||
} | |||||
endOfEarlyData := new(endOfEarlyDataMsg) | |||||
endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData | |||||
c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal()) | |||||
hs.writeClientHash(endOfEarlyData.marshal()) | |||||
} | } | ||||
if !c.config.Bugs.SkipChangeCipherSpec && !hs.hello.hasEarlyData { | 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) | ||||
resumeLabel := resumptionLabel | |||||
if isDraft22(c.wireVersion) { | |||||
resumeLabel = resumptionLabelDraft22 | |||||
} | |||||
c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel) | |||||
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel) | |||||
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 | |||||
if isDraft22(version) { | |||||
binderLabel = resumptionPSKBinderLabelDraft22 | |||||
} | |||||
binder := computePSKBinder(psk, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello) | |||||
binder := computePSKBinder(psk, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello) | |||||
if config.Bugs.SendShortPSKBinder { | if config.Bugs.SendShortPSKBinder { | ||||
binder = binder[:binderLen] | binder = binder[:binderLen] | ||||
} | } | ||||
@@ -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: | |||||
// We assume the client only supports one of draft-22 or draft-23. | |||||
if m.keyShareExtension != 0 { | |||||
return false | |||||
} | |||||
m.keyShareExtension = extension | |||||
case extensionKeyShare: | |||||
// draft-ietf-tls-tls13 section 6.3.2.3 | // 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(extensionNewKeyShare) | |||||
} else { | |||||
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() | ||||
@@ -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) | |||||
} else { | |||||
retryRequestMsg.addU8(typeHelloRetryRequest) | |||||
} | |||||
retryRequestMsg.addU8(typeServerHello) | |||||
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(2) // Length | |||||
extensions.addU16(m.vers) | |||||
} | |||||
extensions.addU16(extensionSupportedVersions) | |||||
extensions.addU16(2) // Length | |||||
extensions.addU16(m.vers) | |||||
if m.hasSelectedGroup { | if m.hasSelectedGroup { | ||||
if isDraft23(m.vers) { | |||||
extensions.addU16(extensionNewKeyShare) | |||||
} else { | |||||
extensions.addU16(extensionOldKeyShare) | |||||
} | |||||
extensions.addU16(extensionKeyShare) | |||||
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() | |||||
if m.hasSignatureAlgorithm { | |||||
extensions.addU16(extensionSignatureAlgorithms) | |||||
signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed() | |||||
for _, sigAlg := range m.signatureAlgorithms { | |||||
signatureAlgorithms.addU16(uint16(sigAlg)) | |||||
} | |||||
} | |||||
if len(m.certificateAuthorities) > 0 { | |||||
extensions.addU16(extensionCertificateAuthorities) | |||||
certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed() | |||||
for _, ca := range m.certificateAuthorities { | |||||
caEntry := certificateAuthorities.addU16LengthPrefixed() | |||||
caEntry.addBytes(ca) | |||||
} | |||||
} | |||||
} else { | |||||
if m.hasSignatureAlgorithm { | |||||
signatureAlgorithms := body.addU16LengthPrefixed() | |||||
for _, sigAlg := range m.signatureAlgorithms { | |||||
signatureAlgorithms.addU16(uint16(sigAlg)) | |||||
} | |||||
extensions = body.addU16LengthPrefixed() | |||||
if m.hasSignatureAlgorithm { | |||||
extensions.addU16(extensionSignatureAlgorithms) | |||||
signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed() | |||||
for _, sigAlg := range m.signatureAlgorithms { | |||||
signatureAlgorithms.addU16(uint16(sigAlg)) | |||||
} | } | ||||
certificateAuthorities := body.addU16LengthPrefixed() | |||||
} | |||||
if len(m.certificateAuthorities) > 0 { | |||||
extensions.addU16(extensionCertificateAuthorities) | |||||
certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed() | |||||
for _, ca := range m.certificateAuthorities { | 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 | |||||
if isDraft22(m.vers) { | |||||
extID = extensionEarlyData | |||||
} | |||||
extensions.addU16(extID) | |||||
extensions.addU16(extensionEarlyData) | |||||
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]) | |||||
data = data[1:] | |||||
if len(data) < nonceLen { | |||||
return false | |||||
} | |||||
m.ticketNonce = data[:nonceLen] | |||||
data = data[nonceLen:] | |||||
nonceLen := int(data[0]) | |||||
data = data[1:] | |||||
if len(data) < nonceLen { | |||||
return false | |||||
} | } | ||||
m.ticketNonce = data[:nonceLen] | |||||
data = data[nonceLen:] | |||||
} | } | ||||
if len(data) < 2 { | 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 | ||||
} | } | ||||
@@ -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 | |||||
// preceded with ChangeCipherSpec. | |||||
if isDraft22(c.wireVersion) { | |||||
c.expectTLS13ChangeCipherSpec = true | |||||
} | |||||
// We've read the ClientHello, so the next record must be preceded with ChangeCipherSpec. | |||||
c.expectTLS13ChangeCipherSpec = true | |||||
hs.hello = &serverHelloMsg{ | 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 { | |||||
return err | |||||
} | |||||
if err := hs.finishedHash.UpdateForHelloRetryRequest(); err != nil { | |||||
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 | |||||
if isDraft22(c.wireVersion) { | |||||
earlyTrafficSecret = hs.finishedHash.deriveSecret(earlyTrafficLabelDraft22) | |||||
c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabelDraft22) | |||||
} else { | |||||
earlyTrafficSecret = hs.finishedHash.deriveSecret(earlyTrafficLabel) | |||||
c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel) | |||||
} | |||||
earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel) | |||||
c.earlyExporterSecret = hs.finishedHash.deriveSecret(earlyExporterLabel) | |||||
if err := c.useInTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret); err != nil { | 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 | |||||
serverLabel = serverApplicationTrafficLabel | |||||
exportLabel := exporterLabel | |||||
if isDraft22(c.wireVersion) { | |||||
clientLabel = clientApplicationTrafficLabelDraft22 | |||||
serverLabel = serverApplicationTrafficLabelDraft22 | |||||
exportLabel = exporterLabelDraft22 | |||||
} | |||||
clientTrafficSecret := hs.finishedHash.deriveSecret(clientLabel) | |||||
serverTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) | |||||
c.exporterSecret = hs.finishedHash.deriveSecret(exportLabel) | |||||
clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel) | |||||
serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel) | |||||
c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel) | |||||
// Switch to application data keys on write. In particular, any alerts | // 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() | |||||
if err != nil { | |||||
return err | |||||
} | |||||
msg, err := c.readHandshake() | |||||
if err != nil { | |||||
return err | |||||
} | |||||
endOfEarlyData, ok := msg.(*endOfEarlyDataMsg) | |||||
if !ok { | |||||
c.sendAlert(alertUnexpectedMessage) | |||||
return unexpectedMessageError(endOfEarlyData, msg) | |||||
} | |||||
hs.writeClientHash(endOfEarlyData.marshal()) | |||||
} else { | |||||
if err := c.readRecord(recordTypeAlert); err != errEndOfEarlyDataAlert { | |||||
if err == nil { | |||||
panic("readRecord(recordTypeAlert) returned nil") | |||||
} | |||||
return err | |||||
} | |||||
endOfEarlyData, ok := msg.(*endOfEarlyDataMsg) | |||||
if !ok { | |||||
c.sendAlert(alertUnexpectedMessage) | |||||
return unexpectedMessageError(endOfEarlyData, msg) | |||||
} | } | ||||
} | |||||
if !isDraft22(c.wireVersion) && !hs.clientHello.hasEarlyData { | |||||
// Early versions of the middlebox hacks inserted | |||||
// ChangeCipherSpec differently on 0-RTT and 2-RTT handshakes. | |||||
c.expectTLS13ChangeCipherSpec = true | |||||
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 | ||||
resumeLabel := resumptionLabel | |||||
if isDraft22(c.wireVersion) { | |||||
resumeLabel = resumptionLabelDraft22 | |||||
} | |||||
c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel) | |||||
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel) | |||||
// TODO(davidben): Allow configuring the number of tickets sent for | // 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 | |||||
if isDraft22(version) { | |||||
binderLabel = resumptionPSKBinderLabelDraft22 | |||||
} | |||||
binder := computePSKBinder(sessionState.masterSecret, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello) | |||||
binder := computePSKBinder(sessionState.masterSecret, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello) | |||||
if !bytes.Equal(binder, binderToVerify) { | if !bytes.Equal(binder, binderToVerify) { | ||||
return errors.New("tls: PSK binder does not verify") | return errors.New("tls: PSK binder does not verify") | ||||
} | } | ||||
@@ -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) { | |||||
derivedLabel := []byte("derived") | |||||
h.secret = hkdfExpandLabel(h.hash, h.wireVersion, h.secret, derivedLabel, h.hash.New().Sum(nil), h.hash.Size()) | |||||
} | |||||
h.secret = hkdfExpandLabel(h.hash, h.secret, []byte("derived"), h.hash.New().Sum(nil), h.hash.Size()) | |||||
} | } | ||||
// hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined | // 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, ") | |||||
if isDraft22(version) { | |||||
versionLabel = []byte("tls13 ") | |||||
} | |||||
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") | |||||
resumptionPSKBinderLabel = []byte("resumption psk binder key") | |||||
earlyTrafficLabel = []byte("client early traffic secret") | |||||
clientHandshakeTrafficLabel = []byte("client handshake traffic secret") | |||||
serverHandshakeTrafficLabel = []byte("server handshake traffic secret") | |||||
clientApplicationTrafficLabel = []byte("client application traffic secret") | |||||
serverApplicationTrafficLabel = []byte("server application traffic secret") | |||||
applicationTrafficLabel = []byte("application traffic secret") | |||||
earlyExporterLabel = []byte("early exporter master secret") | |||||
exporterLabel = []byte("exporter master secret") | |||||
resumptionLabel = []byte("resumption master secret") | |||||
externalPSKBinderLabelDraft22 = []byte("ext binder") | |||||
resumptionPSKBinderLabelDraft22 = []byte("res binder") | |||||
earlyTrafficLabelDraft22 = []byte("c e traffic") | |||||
clientHandshakeTrafficLabelDraft22 = []byte("c hs traffic") | |||||
serverHandshakeTrafficLabelDraft22 = []byte("s hs traffic") | |||||
clientApplicationTrafficLabelDraft22 = []byte("c ap traffic") | |||||
serverApplicationTrafficLabelDraft22 = []byte("s ap traffic") | |||||
applicationTrafficLabelDraft22 = []byte("traffic upd") | |||||
earlyExporterLabelDraft22 = []byte("e exp master") | |||||
exporterLabelDraft22 = []byte("exp master") | |||||
resumptionLabelDraft22 = []byte("res master") | |||||
externalPSKBinderLabel = []byte("ext binder") | |||||
resumptionPSKBinderLabel = []byte("res binder") | |||||
earlyTrafficLabel = []byte("c e traffic") | |||||
clientHandshakeTrafficLabel = []byte("c hs traffic") | |||||
serverHandshakeTrafficLabel = []byte("s hs traffic") | |||||
clientApplicationTrafficLabel = []byte("c ap traffic") | |||||
serverApplicationTrafficLabel = []byte("s ap traffic") | |||||
applicationTrafficLabel = []byte("traffic upd") | |||||
earlyExporterLabel = []byte("e exp master") | |||||
exporterLabel = []byte("exp master") | |||||
resumptionLabel = []byte("res master") | |||||
resumptionPSKLabel = []byte("resumption") | 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) | |||||
iv := hkdfExpandLabel(suite.hash(), version, secret, ivTLS13, nil, suite.ivLen(version)) | |||||
key := hkdfExpandLabel(suite.hash(), secret, keyTLS13, nil, suite.keyLen) | |||||
iv := hkdfExpandLabel(suite.hash(), secret, ivTLS13, nil, suite.ivLen(version)) | |||||
return suite.aead(version, key, iv) | 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 | |||||
if isDraft22(version) { | |||||
trafficLabel = applicationTrafficLabelDraft22 | |||||
} | |||||
return hkdfExpandLabel(hash, version, secret, trafficLabel, nil, hash.Size()) | |||||
return hkdfExpandLabel(hash, secret, applicationTrafficLabel, nil, hash.Size()) | |||||
} | } | ||||
func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cipherSuite, clientHello, helloRetryRequest, truncatedHello []byte) []byte { | 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()) | |||||
} | } |
@@ -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{ | |||||
name: "HelloRetryRequest-CipherChange-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
// P-384 requires HelloRetryRequest in BoringSSL. | |||||
CurvePreferences: []CurveID{CurveP384}, | |||||
Bugs: ProtocolBugs{ | |||||
SendCipherSuite: TLS_AES_128_GCM_SHA256, | |||||
SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256, | |||||
}, | |||||
testCases = append(testCases, testCase{ | |||||
name: "HelloRetryRequest-CipherChange-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
// P-384 requires HelloRetryRequest in BoringSSL. | |||||
CurvePreferences: []CurveID{CurveP384}, | |||||
Bugs: ProtocolBugs{ | |||||
SendCipherSuite: TLS_AES_128_GCM_SHA256, | |||||
SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256, | |||||
}, | }, | ||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":WRONG_CIPHER_RETURNED:", | |||||
}) | |||||
}, | |||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":WRONG_CIPHER_RETURNED:", | |||||
}) | |||||
// Test that the client does not offer a PSK in the second ClientHello if the | |||||
// HelloRetryRequest is incompatible with it. | |||||
testCases = append(testCases, testCase{ | |||||
testType: clientTest, | |||||
name: "HelloRetryRequest-NonResumableCipher-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
CipherSuites: []uint16{ | |||||
TLS_AES_128_GCM_SHA256, | |||||
}, | |||||
// Test that the client does not offer a PSK in the second ClientHello if the | |||||
// HelloRetryRequest is incompatible with it. | |||||
testCases = append(testCases, testCase{ | |||||
testType: clientTest, | |||||
name: "HelloRetryRequest-NonResumableCipher-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
CipherSuites: []uint16{ | |||||
TLS_AES_128_GCM_SHA256, | |||||
}, | }, | ||||
resumeConfig: &Config{ | |||||
MaxVersion: VersionTLS13, | |||||
// P-384 requires HelloRetryRequest in BoringSSL. | |||||
CurvePreferences: []CurveID{CurveP384}, | |||||
Bugs: ProtocolBugs{ | |||||
ExpectNoTLS13PSKAfterHRR: true, | |||||
}, | |||||
CipherSuites: []uint16{ | |||||
TLS_AES_256_GCM_SHA384, | |||||
}, | |||||
}, | |||||
resumeConfig: &Config{ | |||||
MaxVersion: VersionTLS13, | |||||
// P-384 requires HelloRetryRequest in BoringSSL. | |||||
CurvePreferences: []CurveID{CurveP384}, | |||||
Bugs: ProtocolBugs{ | |||||
ExpectNoTLS13PSKAfterHRR: true, | |||||
}, | }, | ||||
tls13Variant: variant, | |||||
resumeSession: true, | |||||
expectResumeRejected: true, | |||||
}) | |||||
} | |||||
CipherSuites: []uint16{ | |||||
TLS_AES_256_GCM_SHA384, | |||||
}, | |||||
}, | |||||
tls13Variant: variant, | |||||
resumeSession: true, | |||||
expectResumeRejected: true, | |||||
}) | |||||
testCases = append(testCases, testCase{ | 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{ | |||||
name: "UnknownExtensionInCertificateRequest-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
MinVersion: VersionTLS13, | |||||
ClientAuth: RequireAnyClientCert, | |||||
Bugs: ProtocolBugs{ | |||||
SendCustomCertificateRequest: 0x1212, | |||||
}, | |||||
}, | |||||
tls13Variant: variant, | |||||
flags: []string{ | |||||
"-cert-file", path.Join(*resourceDir, rsaCertificateFile), | |||||
"-key-file", path.Join(*resourceDir, rsaKeyFile), | |||||
testCases = append(testCases, testCase{ | |||||
name: "UnknownExtensionInCertificateRequest-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
MinVersion: VersionTLS13, | |||||
ClientAuth: RequireAnyClientCert, | |||||
Bugs: ProtocolBugs{ | |||||
SendCustomCertificateRequest: 0x1212, | |||||
}, | }, | ||||
}) | |||||
}, | |||||
tls13Variant: variant, | |||||
flags: []string{ | |||||
"-cert-file", path.Join(*resourceDir, rsaCertificateFile), | |||||
"-key-file", path.Join(*resourceDir, rsaKeyFile), | |||||
}, | |||||
}) | |||||
testCases = append(testCases, testCase{ | |||||
name: "MissingSignatureAlgorithmsInCertificateRequest-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
MinVersion: VersionTLS13, | |||||
ClientAuth: RequireAnyClientCert, | |||||
Bugs: ProtocolBugs{ | |||||
OmitCertificateRequestAlgorithms: true, | |||||
}, | |||||
}, | |||||
tls13Variant: variant, | |||||
flags: []string{ | |||||
"-cert-file", path.Join(*resourceDir, rsaCertificateFile), | |||||
"-key-file", path.Join(*resourceDir, rsaKeyFile), | |||||
testCases = append(testCases, testCase{ | |||||
name: "MissingSignatureAlgorithmsInCertificateRequest-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
MinVersion: VersionTLS13, | |||||
ClientAuth: RequireAnyClientCert, | |||||
Bugs: ProtocolBugs{ | |||||
OmitCertificateRequestAlgorithms: true, | |||||
}, | }, | ||||
shouldFail: true, | |||||
expectedError: ":DECODE_ERROR:", | |||||
}) | |||||
} | |||||
}, | |||||
tls13Variant: variant, | |||||
flags: []string{ | |||||
"-cert-file", path.Join(*resourceDir, rsaCertificateFile), | |||||
"-key-file", path.Join(*resourceDir, rsaKeyFile), | |||||
}, | |||||
shouldFail: true, | |||||
expectedError: ":DECODE_ERROR:", | |||||
}) | |||||
testCases = append(testCases, testCase{ | 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{ | |||||
testType: clientTest, | |||||
name: "SkipChangeCipherSpec-Client-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SkipChangeCipherSpec: true, | |||||
}, | |||||
testCases = append(testCases, testCase{ | |||||
testType: clientTest, | |||||
name: "SkipChangeCipherSpec-Client-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SkipChangeCipherSpec: true, | |||||
}, | }, | ||||
tls13Variant: variant, | |||||
}) | |||||
}, | |||||
tls13Variant: variant, | |||||
}) | |||||
testCases = append(testCases, testCase{ | |||||
testType: serverTest, | |||||
name: "SkipChangeCipherSpec-Server-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SkipChangeCipherSpec: true, | |||||
}, | |||||
testCases = append(testCases, testCase{ | |||||
testType: serverTest, | |||||
name: "SkipChangeCipherSpec-Server-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SkipChangeCipherSpec: true, | |||||
}, | }, | ||||
tls13Variant: variant, | |||||
}) | |||||
}, | |||||
tls13Variant: variant, | |||||
}) | |||||
testCases = append(testCases, testCase{ | |||||
testType: clientTest, | |||||
name: "TooManyChangeCipherSpec-Client-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SendExtraChangeCipherSpec: 33, | |||||
}, | |||||
testCases = append(testCases, testCase{ | |||||
testType: clientTest, | |||||
name: "TooManyChangeCipherSpec-Client-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SendExtraChangeCipherSpec: 33, | |||||
}, | }, | ||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", | |||||
}) | |||||
}, | |||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", | |||||
}) | |||||
testCases = append(testCases, testCase{ | |||||
testType: serverTest, | |||||
name: "TooManyChangeCipherSpec-Server-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SendExtraChangeCipherSpec: 33, | |||||
}, | |||||
testCases = append(testCases, testCase{ | |||||
testType: serverTest, | |||||
name: "TooManyChangeCipherSpec-Server-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SendExtraChangeCipherSpec: 33, | |||||
}, | }, | ||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", | |||||
}) | |||||
}, | |||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", | |||||
}) | |||||
testCases = append(testCases, testCase{ | |||||
name: "SendPostHandshakeChangeCipherSpec-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SendPostHandshakeChangeCipherSpec: true, | |||||
}, | |||||
testCases = append(testCases, testCase{ | |||||
name: "SendPostHandshakeChangeCipherSpec-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SendPostHandshakeChangeCipherSpec: true, | |||||
}, | }, | ||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":UNEXPECTED_RECORD:", | |||||
expectedLocalError: "remote error: unexpected message", | |||||
}) | |||||
} | |||||
}, | |||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":UNEXPECTED_RECORD:", | |||||
expectedLocalError: "remote error: unexpected message", | |||||
}) | |||||
fooString := "foo" | 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{ | |||||
testType: serverTest, | |||||
name: "Server-NonEmptyEndOfEarlyData-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
}, | |||||
resumeConfig: &Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SendEarlyData: [][]byte{{1, 2, 3, 4}}, | |||||
ExpectEarlyDataAccepted: true, | |||||
NonEmptyEndOfEarlyData: true, | |||||
}, | |||||
}, | |||||
resumeSession: true, | |||||
flags: []string{ | |||||
"-enable-early-data", | |||||
"-expect-ticket-supports-early-data", | |||||
"-expect-accept-early-data", | |||||
testCases = append(testCases, testCase{ | |||||
testType: serverTest, | |||||
name: "Server-NonEmptyEndOfEarlyData-" + name, | |||||
config: Config{ | |||||
MaxVersion: VersionTLS13, | |||||
}, | |||||
resumeConfig: &Config{ | |||||
MaxVersion: VersionTLS13, | |||||
Bugs: ProtocolBugs{ | |||||
SendEarlyData: [][]byte{{1, 2, 3, 4}}, | |||||
ExpectEarlyDataAccepted: true, | |||||
NonEmptyEndOfEarlyData: true, | |||||
}, | }, | ||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":DECODE_ERROR:", | |||||
}) | |||||
} | |||||
}, | |||||
resumeSession: true, | |||||
flags: []string{ | |||||
"-enable-early-data", | |||||
"-expect-ticket-supports-early-data", | |||||
"-expect-accept-early-data", | |||||
}, | |||||
tls13Variant: variant, | |||||
shouldFail: true, | |||||
expectedError: ":DECODE_ERROR:", | |||||
}) | |||||
testCases = append(testCases, testCase{ | testCases = append(testCases, testCase{ | ||||
testType: serverTest, | testType: serverTest, | ||||
@@ -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; | |||||
uint16_t cipher_suite = 0; | |||||
if (ssl_is_draft22(ssl->version)) { | |||||
// Queue up a ChangeCipherSpec for whenever we next send something. This | |||||
// will be before the second ClientHello. If we offered early data, this was | |||||
// already done. | |||||
if (!hs->early_data_offered && | |||||
!ssl->method->add_change_cipher_spec(ssl)) { | |||||
return ssl_hs_error; | |||||
} | |||||
if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { | |||||
return ssl_hs_error; | |||||
} | |||||
// Queue up a ChangeCipherSpec for whenever we next send something. This | |||||
// will be before the second ClientHello. If we offered early data, this was | |||||
// already done. | |||||
if (!hs->early_data_offered && | |||||
!ssl->method->add_change_cipher_spec(ssl)) { | |||||
return ssl_hs_error; | |||||
} | |||||
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 (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) { | |||||
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, 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; | |||||
} | |||||
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 (!CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { | |||||
hs->tls13_state = state_read_server_hello; | |||||
return ssl_hs_ok; | |||||
} | } | ||||
if (ssl_is_draft22(ssl->version)) { | |||||
const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite); | |||||
// Check if the cipher is a TLS 1.3 cipher. | |||||
if (cipher == NULL || | |||||
SSL_CIPHER_get_min_version(cipher) > ssl_protocol_version(ssl) || | |||||
SSL_CIPHER_get_max_version(cipher) < ssl_protocol_version(ssl)) { | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); | |||||
return ssl_hs_error; | |||||
} | |||||
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; | |||||
hs->new_cipher = cipher; | |||||
if (!hs->transcript.InitHash(ssl_protocol_version(ssl), hs->new_cipher) || | |||||
!hs->transcript.UpdateForHelloRetryRequest()) { | |||||
return ssl_hs_error; | |||||
} | |||||
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 | |||||
: (uint16_t)TLSEXT_TYPE_old_key_share, | |||||
&have_key_share, &key_share}, | |||||
{TLSEXT_TYPE_key_share, &have_key_share, &key_share}, | |||||
{TLSEXT_TYPE_cookie, &have_cookie, &cookie}, | {TLSEXT_TYPE_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) && | |||||
CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { | |||||
if (CBS_mem_equal(&server_random, kHelloRetryRequest, SSL3_RANDOM_SIZE)) { | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); | 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) && | |||||
hs->received_hello_retry_request && | |||||
if (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 | |||||
: (uint16_t)TLSEXT_TYPE_old_key_share, | |||||
&have_key_share, &key_share}, | |||||
{TLSEXT_TYPE_key_share, &have_key_share, &key_share}, | |||||
{TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key}, | {TLSEXT_TYPE_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; | |||||
CBS sigalgs, ca; | |||||
const SSL_EXTENSION_TYPE ext_types[] = { | |||||
{TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs}, | |||||
{TLSEXT_TYPE_certificate_authorities, &have_ca, &ca}, | |||||
}; | |||||
CBS body = msg.body, context, extensions, supported_signature_algorithms; | |||||
uint8_t alert = SSL_AD_DECODE_ERROR; | |||||
if (!CBS_get_u8_length_prefixed(&body, &context) || | |||||
// The request context is always empty during the handshake. | |||||
CBS_len(&context) != 0 || | |||||
!CBS_get_u16_length_prefixed(&body, &extensions) || | |||||
CBS_len(&body) != 0 || | |||||
!ssl_parse_extensions(&extensions, &alert, ext_types, | |||||
OPENSSL_ARRAY_SIZE(ext_types), | |||||
1 /* accept unknown */) || | |||||
(have_ca && CBS_len(&ca) == 0) || | |||||
!have_sigalgs || | |||||
!CBS_get_u16_length_prefixed(&sigalgs, | |||||
&supported_signature_algorithms) || | |||||
CBS_len(&supported_signature_algorithms) == 0 || | |||||
!tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) { | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, alert); | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||||
return ssl_hs_error; | |||||
} | |||||
bool have_sigalgs = false, have_ca = false; | |||||
CBS sigalgs, ca; | |||||
const SSL_EXTENSION_TYPE ext_types[] = { | |||||
{TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs}, | |||||
{TLSEXT_TYPE_certificate_authorities, &have_ca, &ca}, | |||||
}; | |||||
if (have_ca) { | |||||
hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca); | |||||
if (!hs->ca_names) { | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, alert); | |||||
return ssl_hs_error; | |||||
} | |||||
} else { | |||||
hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null()); | |||||
if (!hs->ca_names) { | |||||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); | |||||
return ssl_hs_error; | |||||
} | |||||
} | |||||
} else { | |||||
CBS body = msg.body, context, supported_signature_algorithms; | |||||
if (!CBS_get_u8_length_prefixed(&body, &context) || | |||||
// The request context is always empty during the handshake. | |||||
CBS_len(&context) != 0 || | |||||
!CBS_get_u16_length_prefixed(&body, &supported_signature_algorithms) || | |||||
CBS_len(&supported_signature_algorithms) == 0 || | |||||
!tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) { | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||||
return ssl_hs_error; | |||||
} | |||||
CBS body = msg.body, context, extensions, supported_signature_algorithms; | |||||
uint8_t alert = SSL_AD_DECODE_ERROR; | |||||
if (!CBS_get_u8_length_prefixed(&body, &context) || | |||||
// The request context is always empty during the handshake. | |||||
CBS_len(&context) != 0 || | |||||
!CBS_get_u16_length_prefixed(&body, &extensions) || | |||||
CBS_len(&body) != 0 || | |||||
!ssl_parse_extensions(&extensions, &alert, ext_types, | |||||
OPENSSL_ARRAY_SIZE(ext_types), | |||||
1 /* accept unknown */) || | |||||
(have_ca && CBS_len(&ca) == 0) || | |||||
!have_sigalgs || | |||||
!CBS_get_u16_length_prefixed(&sigalgs, | |||||
&supported_signature_algorithms) || | |||||
CBS_len(&supported_signature_algorithms) == 0 || | |||||
!tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) { | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, alert); | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||||
return ssl_hs_error; | |||||
} | |||||
uint8_t alert = SSL_AD_DECODE_ERROR; | |||||
hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &body); | |||||
if (have_ca) { | |||||
hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca); | |||||
if (!hs->ca_names) { | 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; | ||||
} | } | ||||
// Ignore extensions. | |||||
CBS extensions; | |||||
if (!CBS_get_u16_length_prefixed(&body, &extensions) || | |||||
CBS_len(&body) != 0) { | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||||
} else { | |||||
hs->ca_names.reset(sk_CRYPTO_BUFFER_new_null()); | |||||
if (!hs->ca_names) { | |||||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); | |||||
return ssl_hs_error; | 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; | |||||
CBB body; | |||||
if (!ssl->method->init_message(ssl, cbb.get(), &body, | |||||
SSL3_MT_END_OF_EARLY_DATA) || | |||||
!ssl_add_message_cbb(ssl, cbb.get())) { | |||||
return ssl_hs_error; | |||||
} | |||||
} else { | |||||
if (!ssl->method->add_alert(ssl, SSL3_AL_WARNING, | |||||
TLS1_AD_END_OF_EARLY_DATA)) { | |||||
return ssl_hs_error; | |||||
} | |||||
ScopedCBB cbb; | |||||
CBB body; | |||||
if (!ssl->method->init_message(ssl, cbb.get(), &body, | |||||
SSL3_MT_END_OF_EARLY_DATA) || | |||||
!ssl_add_message_cbb(ssl, cbb.get())) { | |||||
return ssl_hs_error; | |||||
} | } | ||||
} | } | ||||
@@ -909,8 +831,7 @@ 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; | ||||
@@ -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, | |||||
const EVP_MD *digest, const uint8_t *secret, | |||||
size_t secret_len, const char *label, | |||||
size_t label_len, const uint8_t *hash, | |||||
size_t hash_len, size_t len) { | |||||
const char *kTLS13LabelVersion = | |||||
ssl_is_draft22(version) ? "tls13 " : "TLS 1.3, "; | |||||
static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest, | |||||
const uint8_t *secret, size_t secret_len, | |||||
const char *label, size_t label_len, | |||||
const uint8_t *hash, size_t hash_len, size_t len) { | |||||
static const char kTLS13LabelVersion[] = "tls13 "; | |||||
ScopedCBB cbb; | 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; | |||||
// Draft 18 does not include the extra Derive-Secret step. | |||||
if (ssl_is_draft22(ssl->version)) { | |||||
uint8_t derive_context[EVP_MAX_MD_SIZE]; | |||||
unsigned derive_context_len; | |||||
if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len, | |||||
hs->transcript.Digest(), nullptr)) { | |||||
return 0; | |||||
} | |||||
uint8_t derive_context[EVP_MAX_MD_SIZE]; | |||||
unsigned derive_context_len; | |||||
if (!EVP_Digest(nullptr, 0, derive_context, &derive_context_len, | |||||
hs->transcript.Digest(), nullptr)) { | |||||
return 0; | |||||
} | |||||
if (!hkdf_expand_label(hs->secret, ssl->version, hs->transcript.Digest(), | |||||
hs->secret, hs->hash_len, kTLS13LabelDerived, | |||||
strlen(kTLS13LabelDerived), derive_context, | |||||
derive_context_len, hs->hash_len)) { | |||||
return 0; | |||||
} | |||||
if (!hkdf_expand_label(hs->secret, hs->transcript.Digest(), hs->secret, | |||||
hs->hash_len, kTLS13LabelDerived, | |||||
strlen(kTLS13LabelDerived), derive_context, | |||||
derive_context_len, hs->hash_len)) { | |||||
return 0; | |||||
} | } | ||||
return HKDF_extract(hs->secret, &hs->hash_len, hs->transcript.Digest(), in, | 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, | |||||
hs->transcript.Digest(), hs->secret, hs->hash_len, | |||||
label, label_len, context_hash, context_hash_len, | |||||
len); | |||||
return hkdf_expand_label(out, hs->transcript.Digest(), hs->secret, | |||||
hs->hash_len, label, label_len, context_hash, | |||||
context_hash_len, len); | |||||
} | } | ||||
int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction, | 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, | |||||
traffic_secret_len, "key", 3, NULL, 0, key_len)) { | |||||
if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, "key", | |||||
3, NULL, 0, key_len)) { | |||||
return 0; | 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, | |||||
traffic_secret_len, "iv", 2, NULL, 0, iv_len)) { | |||||
if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, "iv", | |||||
2, NULL, 0, iv_len)) { | |||||
return 0; | 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[] = | |||||
"client early traffic secret"; | |||||
static const char kTLS13LabelClientHandshakeTraffic[] = | |||||
"client handshake traffic secret"; | |||||
static const char kTLS13LabelServerHandshakeTraffic[] = | |||||
"server handshake traffic secret"; | |||||
static const char kTLS13LabelClientApplicationTraffic[] = | |||||
"client application traffic secret"; | |||||
static const char kTLS13LabelServerApplicationTraffic[] = | |||||
"server application traffic secret"; | |||||
static const char kTLS13Draft22LabelExporter[] = "exp master"; | |||||
static const char kTLS13Draft22LabelEarlyExporter[] = "e exp master"; | |||||
static const char kTLS13Draft22LabelClientEarlyTraffic[] = "c e traffic"; | |||||
static const char kTLS13Draft22LabelClientHandshakeTraffic[] = "c hs traffic"; | |||||
static const char kTLS13Draft22LabelServerHandshakeTraffic[] = "s hs traffic"; | |||||
static const char kTLS13Draft22LabelClientApplicationTraffic[] = "c ap traffic"; | |||||
static const char kTLS13Draft22LabelServerApplicationTraffic[] = "s ap traffic"; | |||||
static const char kTLS13LabelExporter[] = "exp master"; | |||||
static const char kTLS13LabelEarlyExporter[] = "e exp master"; | |||||
static const char kTLS13LabelClientEarlyTraffic[] = "c e traffic"; | |||||
static const char kTLS13LabelClientHandshakeTraffic[] = "c hs traffic"; | |||||
static const char kTLS13LabelServerHandshakeTraffic[] = "s hs traffic"; | |||||
static const char kTLS13LabelClientApplicationTraffic[] = "c ap traffic"; | |||||
static const char kTLS13LabelServerApplicationTraffic[] = "s ap traffic"; | |||||
int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) { | 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[] = | |||||
"application traffic secret"; | |||||
static const char kTLS13Draft22LabelApplicationTraffic[] = "traffic upd"; | |||||
static const char kTLS13LabelApplicationTraffic[] = "traffic upd"; | |||||
int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) { | 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, | |||||
traffic_label, strlen(traffic_label), NULL, 0, | |||||
secret_len)) { | |||||
if (!hkdf_expand_label( | |||||
secret, digest, secret, secret_len, kTLS13LabelApplicationTraffic, | |||||
strlen(kTLS13LabelApplicationTraffic), NULL, 0, secret_len)) { | |||||
return 0; | return 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 kTLS13Draft22LabelResumption[] = "res master"; | |||||
static const char kTLS13LabelResumption[] = "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, | |||||
strlen(resumption_label)); | |||||
hs->new_session->master_key_length, | |||||
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, | |||||
kTLS13LabelFinished, strlen(kTLS13LabelFinished), NULL, | |||||
0, hash_len) || | |||||
if (!hkdf_expand_label(key, digest, secret, hash_len, kTLS13LabelFinished, | |||||
strlen(kTLS13LabelFinished), NULL, 0, hash_len) || | |||||
HMAC(digest, key, hash_len, context, context_len, out, &len) == NULL) { | 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, | |||||
session->master_key, session->master_key_length, | |||||
kTLS13LabelResumptionPSK, | |||||
return hkdf_expand_label(session->master_key, digest, session->master_key, | |||||
session->master_key_length, kTLS13LabelResumptionPSK, | |||||
strlen(kTLS13LabelResumptionPSK), nonce.data(), | 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(), | |||||
secret.size(), label.data(), label.size(), | |||||
export_context, export_context_len, | |||||
derived_secret_len) && | |||||
hkdf_expand_label(out.data(), version, digest, derived_secret, | |||||
hkdf_expand_label(derived_secret, digest, secret.data(), secret.size(), | |||||
label.data(), label.size(), export_context, | |||||
export_context_len, derived_secret_len) && | |||||
hkdf_expand_label(out.data(), digest, derived_secret, | |||||
derived_secret_len, kTLS13LabelExportKeying, | 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 kTLS13Draft22LabelPSKBinder[] = "res binder"; | |||||
static const char kTLS13LabelPSKBinder[] = "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, | |||||
binder_label, strlen(binder_label), binder_context, | |||||
binder_context_len, hash_len) || | |||||
if (!hkdf_expand_label(binder_key, digest, early_secret, hash_len, | |||||
kTLS13LabelPSKBinder, strlen(kTLS13LabelPSKBinder), | |||||
binder_context, binder_context_len, hash_len) || | |||||
!tls13_verify_data(digest, version, out, &len, binder_key, hash_len, | !tls13_verify_data(digest, version, out, &len, binder_key, hash_len, | ||||
context, context_len)) { | context, context_len)) { | ||||
return 0; | return 0; | ||||
@@ -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_bytes(&nonce_cbb, nonce, sizeof(nonce)))) || | |||||
!CBB_add_u8_length_prefixed(&body, &nonce_cbb) || | |||||
!CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)) || | |||||
!CBB_add_u16_length_prefixed(&body, &ticket) || | !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) | |||||
? TLSEXT_TYPE_early_data | |||||
: TLSEXT_TYPE_ticket_early_data_info) || | |||||
if (!CBB_add_u16(&extensions, TLSEXT_TYPE_early_data) || | |||||
!CBB_add_u16_length_prefixed(&extensions, &early_data_info) || | !CBB_add_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) && | |||||
!hs->transcript.UpdateForHelloRetryRequest()) { | |||||
if (!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; | |||||
CBB body, session_id, extensions; | |||||
uint16_t group_id; | |||||
if (!ssl->method->init_message(ssl, cbb.get(), &body, | |||||
SSL3_MT_SERVER_HELLO) || | |||||
!CBB_add_u16(&body, TLS1_2_VERSION) || | |||||
!CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) || | |||||
!CBB_add_u8_length_prefixed(&body, &session_id) || | |||||
!CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || | |||||
!CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) || | |||||
!CBB_add_u8(&body, 0 /* no compression */) || | |||||
!tls1_get_shared_group(hs, &group_id) || | |||||
!CBB_add_u16_length_prefixed(&body, &extensions) || | |||||
!CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) || | |||||
!CBB_add_u16(&extensions, 2 /* length */) || | |||||
!CBB_add_u16(&extensions, ssl->version) || | |||||
!CBB_add_u16(&extensions, ssl_is_draft23(ssl->version) | |||||
? TLSEXT_TYPE_new_key_share | |||||
: TLSEXT_TYPE_old_key_share) || | |||||
!CBB_add_u16(&extensions, 2 /* length */) || | |||||
!CBB_add_u16(&extensions, group_id) || | |||||
!ssl_add_message_cbb(ssl, cbb.get())) { | |||||
return ssl_hs_error; | |||||
} | |||||
ScopedCBB cbb; | |||||
CBB body, session_id, extensions; | |||||
uint16_t group_id; | |||||
if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) || | |||||
!CBB_add_u16(&body, TLS1_2_VERSION) || | |||||
!CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) || | |||||
!CBB_add_u8_length_prefixed(&body, &session_id) || | |||||
!CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || | |||||
!CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) || | |||||
!CBB_add_u8(&body, 0 /* no compression */) || | |||||
!tls1_get_shared_group(hs, &group_id) || | |||||
!CBB_add_u16_length_prefixed(&body, &extensions) || | |||||
!CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) || | |||||
!CBB_add_u16(&extensions, 2 /* length */) || | |||||
!CBB_add_u16(&extensions, ssl->version) || | |||||
!CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) || | |||||
!CBB_add_u16(&extensions, 2 /* length */) || | |||||
!CBB_add_u16(&extensions, group_id) || | |||||
!ssl_add_message_cbb(ssl, cbb.get())) { | |||||
return ssl_hs_error; | |||||
} | |||||
if (!ssl->method->add_change_cipher_spec(ssl)) { | |||||
return ssl_hs_error; | |||||
} | |||||
} else { | |||||
ScopedCBB cbb; | |||||
CBB body, extensions; | |||||
uint16_t group_id; | |||||
if (!ssl->method->init_message(ssl, cbb.get(), &body, | |||||
SSL3_MT_HELLO_RETRY_REQUEST) || | |||||
!CBB_add_u16(&body, ssl->version) || | |||||
(ssl_is_draft22(ssl->version) && | |||||
!CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher))) || | |||||
!tls1_get_shared_group(hs, &group_id) || | |||||
!CBB_add_u16_length_prefixed(&body, &extensions) || | |||||
!CBB_add_u16(&extensions, TLSEXT_TYPE_old_key_share) || | |||||
!CBB_add_u16(&extensions, 2 /* length */) || | |||||
!CBB_add_u16(&extensions, group_id) || | |||||
!ssl_add_message_cbb(ssl, cbb.get())) { | |||||
return ssl_hs_error; | |||||
} | |||||
if (!ssl->method->add_change_cipher_spec(ssl)) { | |||||
return ssl_hs_error; | |||||
} | } | ||||
hs->sent_hello_retry_request = true; | 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; | |||||
if (!ssl->method->init_message(ssl, cbb.get(), &body, | |||||
SSL3_MT_CERTIFICATE_REQUEST) || | |||||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */) || | |||||
!CBB_add_u16_length_prefixed(&body, &cert_request_extensions) || | |||||
!CBB_add_u16(&cert_request_extensions, | |||||
TLSEXT_TYPE_signature_algorithms) || | |||||
CBB cert_request_extensions, sigalg_contents, sigalgs_cbb; | |||||
if (!ssl->method->init_message(ssl, cbb.get(), &body, | |||||
SSL3_MT_CERTIFICATE_REQUEST) || | |||||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */) || | |||||
!CBB_add_u16_length_prefixed(&body, &cert_request_extensions) || | |||||
!CBB_add_u16(&cert_request_extensions, | |||||
TLSEXT_TYPE_signature_algorithms) || | |||||
!CBB_add_u16_length_prefixed(&cert_request_extensions, | |||||
&sigalg_contents) || | |||||
!CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) || | |||||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) { | |||||
return ssl_hs_error; | |||||
} | |||||
if (ssl_has_client_CAs(ssl)) { | |||||
CBB ca_contents; | |||||
if (!CBB_add_u16(&cert_request_extensions, | |||||
TLSEXT_TYPE_certificate_authorities) || | |||||
!CBB_add_u16_length_prefixed(&cert_request_extensions, | !CBB_add_u16_length_prefixed(&cert_request_extensions, | ||||
&sigalg_contents) || | |||||
!CBB_add_u16_length_prefixed(&sigalg_contents, &sigalgs_cbb) || | |||||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) { | |||||
&ca_contents) || | |||||
!ssl_add_client_CA_list(ssl, &ca_contents) || | |||||
!CBB_flush(&cert_request_extensions)) { | |||||
return ssl_hs_error; | return ssl_hs_error; | ||||
} | } | ||||
} | |||||
if (ssl_has_client_CAs(ssl)) { | |||||
CBB ca_contents; | |||||
if (!CBB_add_u16(&cert_request_extensions, | |||||
TLSEXT_TYPE_certificate_authorities) || | |||||
!CBB_add_u16_length_prefixed(&cert_request_extensions, | |||||
&ca_contents) || | |||||
!ssl_add_client_CA_list(ssl, &ca_contents) || | |||||
!CBB_flush(&cert_request_extensions)) { | |||||
return ssl_hs_error; | |||||
} | |||||
} | |||||
if (!ssl_add_message_cbb(ssl, cbb.get())) { | |||||
return ssl_hs_error; | |||||
} | |||||
} else { | |||||
CBB sigalgs_cbb; | |||||
if (!ssl->method->init_message(ssl, cbb.get(), &body, | |||||
SSL3_MT_CERTIFICATE_REQUEST) || | |||||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */) || | |||||
!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) || | |||||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb) || | |||||
!ssl_add_client_CA_list(ssl, &body) || | |||||
!CBB_add_u16(&body, 0 /* empty certificate_extensions. */) || | |||||
!ssl_add_message_cbb(ssl, cbb.get())) { | |||||
return ssl_hs_error; | |||||
} | |||||
if (!ssl_add_message_cbb(ssl, cbb.get())) { | |||||
return ssl_hs_error; | |||||
} | } | ||||
} | } | ||||
@@ -738,13 +693,11 @@ 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, | |||||
0, 0}; | |||||
if (!hs->transcript.Update(kEndOfEarlyData)) { | |||||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||||
return ssl_hs_error; | |||||
} | |||||
static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0, | |||||
0, 0}; | |||||
if (!hs->transcript.Update(kEndOfEarlyData)) { | |||||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||||
return ssl_hs_error; | |||||
} | } | ||||
size_t finished_len; | 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; | |||||
if (!ssl->method->get_message(ssl, &msg)) { | |||||
return ssl_hs_read_message; | |||||
} | |||||
if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) { | |||||
return ssl_hs_error; | |||||
} | |||||
if (CBS_len(&msg.body) != 0) { | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||||
return ssl_hs_error; | |||||
} | |||||
ssl->method->next_message(ssl); | |||||
SSLMessage msg; | |||||
if (!ssl->method->get_message(ssl, &msg)) { | |||||
return ssl_hs_read_message; | |||||
} | } | ||||
if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) { | |||||
return ssl_hs_error; | |||||
} | |||||
if (CBS_len(&msg.body) != 0) { | |||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||||
return ssl_hs_error; | |||||
} | |||||
ssl->method->next_message(ssl); | |||||
} | } | ||||
} | } | ||||
if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret, | if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret, | ||||
@@ -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); | ||||
} | } | ||||
@@ -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") { | |||||
*out = tls13_draft22; | |||||
return true; | |||||
} | |||||
if (in == "experiment2") { | |||||
*out = tls13_experiment2; | |||||
if (in == "draft23") { | |||||
*out = tls13_default; | |||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
@@ -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) { | ||||