external/boringssl: Sync to c3889634a1aa52575c5d26497696238208fbd0f5.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/41c10e2b5f37edce8b9f292f7f3bacb7e30e25c4..c3889634a1aa52575c5d26497696238208fbd0f5
Test: atest CtsLibcoreTestCases
Change-Id: Ia1c2941ccf58a9e0d736b3409a2d13c21603a205
diff --git a/src/ssl/CMakeLists.txt b/src/ssl/CMakeLists.txt
index d6c1294..dc89dca 100644
--- a/src/ssl/CMakeLists.txt
+++ b/src/ssl/CMakeLists.txt
@@ -52,12 +52,11 @@
ssl_test.cc
$<TARGET_OBJECTS:boringssl_gtest_main>
- $<TARGET_OBJECTS:test_support>
)
add_dependencies(ssl_test global_target)
-target_link_libraries(ssl_test ssl crypto boringssl_gtest)
+target_link_libraries(ssl_test test_support_lib boringssl_gtest ssl crypto)
if(WIN32)
target_link_libraries(ssl_test ws2_32)
endif()
diff --git a/src/ssl/handshake.cc b/src/ssl/handshake.cc
index 058a793..89be48f 100644
--- a/src/ssl/handshake.cc
+++ b/src/ssl/handshake.cc
@@ -135,6 +135,7 @@
cert_request(false),
certificate_status_expected(false),
ocsp_stapling_requested(false),
+ delegated_credential_requested(false),
should_ack_sni(false),
in_false_start(false),
in_early_data(false),
@@ -544,7 +545,7 @@
case ssl_hs_read_server_hello:
case ssl_hs_read_message:
case ssl_hs_read_change_cipher_spec: {
- if (ssl->ctx->quic_method) {
+ if (ssl->quic_method) {
hs->wait = ssl_hs_ok;
// The change cipher spec is omitted in QUIC.
if (hs->wait != ssl_hs_read_change_cipher_spec) {
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 0274dc2..b0de670 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -416,8 +416,6 @@
return ssl_hs_error;
}
- // Initialize a random session ID for the experimental TLS 1.3 variant
- // requiring a session id.
if (ssl->session != nullptr &&
!ssl->s3->initial_handshake_complete &&
ssl->session->session_id_length > 0) {
@@ -425,6 +423,7 @@
OPENSSL_memcpy(hs->session_id, ssl->session->session_id,
hs->session_id_len);
} else if (hs->max_version >= TLS1_3_VERSION) {
+ // Initialize a random session ID.
hs->session_id_len = sizeof(hs->session_id);
if (!RAND_bytes(hs->session_id, hs->session_id_len)) {
return ssl_hs_error;
@@ -1219,7 +1218,7 @@
}
}
- if (!ssl_has_certificate(hs->config)) {
+ if (!ssl_has_certificate(hs)) {
// Without a client certificate, the handshake buffer may be released.
hs->transcript.FreeBuffer();
}
@@ -1249,6 +1248,27 @@
Array<uint8_t> pms;
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
+ if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+ CRYPTO_BUFFER *leaf =
+ sk_CRYPTO_BUFFER_value(hs->new_session->certs.get(), 0);
+ CBS leaf_cbs;
+ CBS_init(&leaf_cbs, CRYPTO_BUFFER_data(leaf), CRYPTO_BUFFER_len(leaf));
+
+ // Check the key usage matches the cipher suite. We do this unconditionally
+ // for non-RSA certificates. In particular, it's needed to distinguish ECDH
+ // certificates, which we do not support, from ECDSA certificates.
+ // Historically, we have not checked RSA key usages, so it is controlled by
+ // a flag for now. See https://crbug.com/795089.
+ ssl_key_usage_t intended_use = (alg_k & SSL_kRSA)
+ ? key_usage_encipherment
+ : key_usage_digital_signature;
+ if (ssl->config->enforce_rsa_key_usage ||
+ EVP_PKEY_id(hs->peer_pubkey.get()) != EVP_PKEY_RSA) {
+ if (!ssl_cert_check_key_usage(&leaf_cbs, intended_use)) {
+ return ssl_hs_error;
+ }
+ }
+ }
// If using a PSK key exchange, prepare the pre-shared key.
unsigned psk_len = 0;
@@ -1386,12 +1406,12 @@
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!hs->cert_request || !ssl_has_certificate(hs->config)) {
+ if (!hs->cert_request || !ssl_has_certificate(hs)) {
hs->state = state_send_client_finished;
return ssl_hs_ok;
}
- assert(ssl_has_private_key(hs->config));
+ assert(ssl_has_private_key(hs));
ScopedCBB cbb;
CBB body, child;
if (!ssl->method->init_message(ssl, cbb.get(), &body,
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index 8b3b942..cb4e9d1 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -303,7 +303,7 @@
uint32_t mask_k = 0;
uint32_t mask_a = 0;
- if (ssl_has_certificate(hs->config)) {
+ if (ssl_has_certificate(hs)) {
mask_a |= ssl_cipher_auth_mask_for_key(hs->local_pubkey.get());
if (EVP_PKEY_id(hs->local_pubkey.get()) == EVP_PKEY_RSA) {
mask_k |= SSL_kRSA;
@@ -402,8 +402,7 @@
}
// is_probably_jdk11_with_tls13 returns whether |client_hello| was probably sent
-// from a JDK 11 client (11.0.1 or earlier) with both TLS 1.3 and a prior
-// version enabled.
+// from a JDK 11 client with both TLS 1.3 and a prior version enabled.
static bool is_probably_jdk11_with_tls13(const SSL_CLIENT_HELLO *client_hello) {
// JDK 11 ClientHellos contain a number of unusual properties which should
// limit false positives.
@@ -868,7 +867,7 @@
ScopedCBB cbb;
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
- if (!ssl_has_certificate(hs->config)) {
+ if (!ssl_has_certificate(hs)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
return ssl_hs_error;
}
@@ -974,7 +973,7 @@
// Add a signature.
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
- if (!ssl_has_private_key(hs->config)) {
+ if (!ssl_has_private_key(hs)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
@@ -1226,6 +1225,8 @@
return ssl_hs_error;
}
+ CONSTTIME_SECRET(decrypt_buf.data(), decrypt_len);
+
// Prepare a random premaster, to be used on invalid padding. See RFC 5246,
// section 7.4.7.1.
if (!premaster_secret.Init(SSL_MAX_MASTER_KEY_LENGTH) ||
@@ -1348,6 +1349,8 @@
return ssl_hs_error;
}
hs->new_session->extended_master_secret = hs->extended_master_secret;
+ CONSTTIME_DECLASSIFY(hs->new_session->master_key,
+ hs->new_session->master_key_length);
ssl->method->next_message(ssl);
hs->state = state12_read_client_certificate_verify;
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index bbce7ec..0df9a5f 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -359,8 +359,7 @@
// Protocol versions.
//
-// Due to DTLS's historical wire version differences and to support multiple
-// variants of the same protocol during development, we maintain two notions of
+// Due to DTLS's historical wire version differences, we maintain two notions of
// version.
//
// The "version" or "wire version" is the actual 16-bit value that appears on
@@ -369,9 +368,8 @@
// versions are opaque values and may not be compared numerically.
//
// The "protocol version" identifies the high-level handshake variant being
-// used. DTLS versions map to the corresponding TLS versions. Draft TLS 1.3
-// variants all map to TLS 1.3. Protocol versions are sequential and may be
-// compared numerically.
+// used. DTLS versions map to the corresponding TLS versions. Protocol versions
+// are sequential and may be compared numerically.
// ssl_protocol_version_from_wire sets |*out| to the protocol version
// corresponding to wire version |version| and returns true. If |version| is not
@@ -408,10 +406,6 @@
// call this function before the version is determined.
uint16_t ssl_protocol_version(const SSL *ssl);
-// ssl_is_draft28 returns whether the version corresponds to a draft28 TLS 1.3
-// variant.
-bool ssl_is_draft28(uint16_t version);
-
// Cipher suites.
BSSL_NAMESPACE_END
@@ -785,8 +779,6 @@
// omit_length_in_ad_ is true if the length should be omitted in the
// AEAD's ad parameter.
bool omit_length_in_ad_ : 1;
- // omit_ad_ is true if the AEAD's ad parameter should be omitted.
- bool omit_ad_ : 1;
// ad_is_header_ is true if the AEAD's ad parameter is the record header.
bool ad_is_header_ : 1;
};
@@ -919,8 +911,8 @@
// Private key operations.
-// ssl_has_private_key returns whether |cfg| has a private key configured.
-bool ssl_has_private_key(const SSL_CONFIG *cfg);
+// ssl_has_private_key returns whether |hs| has a private key configured.
+bool ssl_has_private_key(const SSL_HANDSHAKE *hs);
// ssl_private_key_* perform the corresponding operation on
// |SSL_PRIVATE_KEY_METHOD|. If there is a custom private key configured, they
@@ -1173,7 +1165,7 @@
// ssl_has_certificate returns whether a certificate and private key are
// configured.
-bool ssl_has_certificate(const SSL_CONFIG *cfg);
+bool ssl_has_certificate(const SSL_HANDSHAKE *hs);
// ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
// by a TLS Certificate message. On success, it advances |cbs| and returns
@@ -1197,11 +1189,15 @@
// an empty certificate list. It returns true on success and false on error.
bool ssl_add_cert_chain(SSL_HANDSHAKE *hs, CBB *cbb);
-// ssl_cert_check_digital_signature_key_usage parses the DER-encoded, X.509
-// certificate in |in| and returns true if doesn't specify a key usage or, if it
-// does, if it includes digitalSignature. Otherwise it pushes to the error queue
-// and returns false.
-bool ssl_cert_check_digital_signature_key_usage(const CBS *in);
+enum ssl_key_usage_t {
+ key_usage_digital_signature = 0,
+ key_usage_encipherment = 2,
+};
+
+// ssl_cert_check_key_usage parses the DER-encoded, X.509 certificate in |in|
+// and returns true if doesn't specify a key usage or, if it does, if it
+// includes |bit|. Otherwise it pushes to the error queue and returns false.
+bool ssl_cert_check_key_usage(const CBS *in, enum ssl_key_usage_t bit);
// ssl_cert_parse_pubkey extracts the public key from the DER-encoded, X.509
// certificate in |in|. It returns an allocated |EVP_PKEY| or else returns
@@ -1299,8 +1295,7 @@
// tls13_derive_session_psk calculates the PSK for this session based on the
// resumption master secret and |nonce|. It returns true on success, and false
// on failure.
-bool tls13_derive_session_psk(SSL_SESSION *session, Span<const uint8_t> nonce,
- bool use_quic);
+bool tls13_derive_session_psk(SSL_SESSION *session, Span<const uint8_t> nonce);
// tls13_write_psk_binder calculates the PSK binder value and replaces the last
// bytes of |msg| with the resulting value. It returns true on success, and
@@ -1379,6 +1374,46 @@
handback_after_handshake,
};
+
+// Delegated credentials.
+
+// This structure stores a delegated credential (DC) as defined by
+// draft-ietf-tls-subcerts-03.
+struct DC {
+ static constexpr bool kAllowUniquePtr = true;
+ ~DC();
+
+ // Dup returns a copy of this DC and takes references to |raw| and |pkey|.
+ UniquePtr<DC> Dup();
+
+ // Parse parses the delegated credential stored in |in|. If successful it
+ // returns the parsed structure, otherwise it returns |nullptr| and sets
+ // |*out_alert|.
+ static UniquePtr<DC> Parse(CRYPTO_BUFFER *in, uint8_t *out_alert);
+
+ // raw is the delegated credential encoded as specified in draft-ietf-tls-
+ // subcerts-02.
+ UniquePtr<CRYPTO_BUFFER> raw;
+
+ // expected_cert_verify_algorithm is the signature scheme of the DC public
+ // key.
+ uint16_t expected_cert_verify_algorithm = 0;
+
+ // pkey is the public key parsed from |public_key|.
+ UniquePtr<EVP_PKEY> pkey;
+
+ private:
+ friend DC* New<DC>();
+ DC();
+};
+
+// ssl_signing_with_dc returns true if the peer has indicated support for
+// delegated credentials and this host has sent a delegated credential in
+// response. If this is true then we've committed to using the DC in the
+// handshake.
+bool ssl_signing_with_dc(const SSL_HANDSHAKE *hs);
+
+
struct SSL_HANDSHAKE {
explicit SSL_HANDSHAKE(SSL *ssl);
~SSL_HANDSHAKE();
@@ -1550,6 +1585,10 @@
// ocsp_stapling_requested is true if a client requested OCSP stapling.
bool ocsp_stapling_requested : 1;
+ // delegated_credential_requested is true if the peer indicated support for
+ // the delegated credential extension.
+ bool delegated_credential_requested : 1;
+
// should_ack_sni is used by a server and indicates that the SNI extension
// should be echoed in the ServerHello.
bool should_ack_sni : 1;
@@ -1614,8 +1653,7 @@
// record layer.
uint16_t early_data_written = 0;
- // session_id is the session ID in the ClientHello, used for the experimental
- // TLS 1.3 variant.
+ // session_id is the session ID in the ClientHello.
uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH] = {0};
uint8_t session_id_len = 0;
@@ -1649,6 +1687,11 @@
const char *tls13_client_handshake_state(SSL_HANDSHAKE *hs);
const char *tls13_server_handshake_state(SSL_HANDSHAKE *hs);
+// tls13_add_key_update queues a KeyUpdate message on |ssl|. The
+// |update_requested| argument must be one of |SSL_KEY_UPDATE_REQUESTED| or
+// |SSL_KEY_UPDATE_NOT_REQUESTED|.
+bool tls13_add_key_update(SSL *ssl, int update_requested);
+
// tls13_post_handshake processes a post-handshake message. It returns true on
// success and false on failure.
bool tls13_post_handshake(SSL *ssl, const SSLMessage &msg);
@@ -1791,6 +1834,15 @@
// supported. It returns true on success and false on error.
bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out);
+// tls1_get_peer_verify_algorithms returns the signature schemes for which the
+// peer indicated support.
+//
+// NOTE: The related function |SSL_get0_peer_verify_algorithms| only has
+// well-defined behavior during the callbacks set by |SSL_CTX_set_cert_cb| and
+// |SSL_CTX_set_client_cert_cb|, or when the handshake is paused because of
+// them.
+Span<const uint16_t> tls1_get_peer_verify_algorithms(const SSL_HANDSHAKE *hs);
+
// tls12_add_verify_sigalgs adds the signature algorithms acceptable for the
// peer signature to |out|. It returns true on success and false on error. If
// |for_certs| is true, the potentially more restrictive list of algorithms for
@@ -1884,6 +1936,19 @@
// ticket key. Only sessions with a matching value will be accepted.
uint8_t sid_ctx_length = 0;
uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH] = {0};
+
+ // Delegated credentials.
+
+ // dc is the delegated credential to send to the peer (if requested).
+ UniquePtr<DC> dc = nullptr;
+
+ // dc_privatekey is used instead of |privatekey| or |key_method| to
+ // authenticate the host if a delegated credential is used in the handshake.
+ UniquePtr<EVP_PKEY> dc_privatekey = nullptr;
+
+ // dc_key_method, if not NULL, is used instead of |dc_privatekey| to
+ // authenticate the host.
+ const SSL_PRIVATE_KEY_METHOD *dc_key_method = nullptr;
};
// |SSL_PROTOCOL_METHOD| abstracts between TLS and DTLS.
@@ -2049,7 +2114,7 @@
DEFINE_LHASH_OF(SSL_SESSION)
-DEFINE_NAMED_STACK_OF(CertCompressionAlg, bssl::CertCompressionAlg);
+DEFINE_NAMED_STACK_OF(CertCompressionAlg, bssl::CertCompressionAlg)
BSSL_NAMESPACE_BEGIN
@@ -2479,6 +2544,11 @@
// advertise support.
bool channel_id_enabled : 1;
+ // If enforce_rsa_key_usage is true, the handshake will fail if the
+ // keyUsage extension is present and incompatible with the TLS usage.
+ // This field is not read until after certificate verification.
+ bool enforce_rsa_key_usage : 1;
+
// retain_only_sha256_of_client_certs is true if we should compute the SHA256
// hash of the peer's certificate and then discard it to save memory and
// session space. Only effective on the server side.
@@ -2506,10 +2576,6 @@
// From RFC 8446, used in determining PSK modes.
#define SSL_PSK_DHE_KE 0x1
-// From RFC 8446, used in determining whether to respond with a KeyUpdate.
-#define SSL_KEY_UPDATE_NOT_REQUESTED 0
-#define SSL_KEY_UPDATE_REQUESTED 1
-
// kMaxEarlyDataAccepted is the advertised number of plaintext bytes of early
// data that will be accepted. This value should be slightly below
// kMaxEarlyDataSkipped in tls_record.c, which is measured in ciphertext.
@@ -2834,10 +2900,6 @@
// quic_method is the method table corresponding to the QUIC hooks.
const SSL_QUIC_METHOD *quic_method = nullptr;
- // tls13_variant is the variant of TLS 1.3 we are using for this
- // configuration.
- tls13_variant_t tls13_variant = tls13_rfc;
-
bssl::UniquePtr<bssl::SSLCipherPreferenceList> cipher_list;
X509_STORE *cert_store = nullptr;
@@ -3163,10 +3225,6 @@
// second.
unsigned initial_timeout_duration_ms = 1000;
- // tls13_variant is the variant of TLS 1.3 we are using for this
- // configuration.
- tls13_variant_t tls13_variant = tls13_rfc;
-
// session is the configured session to be offered by the client. This session
// is immutable.
bssl::UniquePtr<SSL_SESSION> session;
@@ -3187,6 +3245,9 @@
uint32_t max_cert_list = 0;
bssl::UniquePtr<char> hostname;
+ // quic_method is the method table corresponding to the QUIC hooks.
+ const SSL_QUIC_METHOD *quic_method = nullptr;
+
// renegotiate_mode controls how peer renegotiation attempts are handled.
ssl_renegotiate_mode_t renegotiate_mode = ssl_renegotiate_never;
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index f835dc2..aec6cae 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -188,14 +188,12 @@
// unnecessary encryption overhead, notably in TLS 1.3 where we send several
// encrypted messages in a row. For now, we do not do this for the null
// cipher. The benefit is smaller and there is a risk of breaking buggy
- // implementations. Additionally, we tie this to draft-28 as a sanity check,
- // on the off chance middleboxes have fixated on sizes.
+ // implementations.
//
// TODO(davidben): See if we can do this uniformly.
Span<const uint8_t> rest = msg;
- if (ssl->ctx->quic_method == nullptr &&
- (ssl->s3->aead_write_ctx->is_null_cipher() ||
- ssl->version == TLS1_3_DRAFT23_VERSION)) {
+ if (ssl->quic_method == nullptr &&
+ ssl->s3->aead_write_ctx->is_null_cipher()) {
while (!rest.empty()) {
Span<const uint8_t> chunk = rest.subspan(0, ssl->max_send_fragment);
rest = rest.subspan(chunk.size());
@@ -250,9 +248,9 @@
auto data =
MakeConstSpan(reinterpret_cast<const uint8_t *>(pending_hs_data->data),
pending_hs_data->length);
- if (ssl->ctx->quic_method) {
- if (!ssl->ctx->quic_method->add_handshake_data(ssl, ssl->s3->write_level,
- data.data(), data.size())) {
+ if (ssl->quic_method) {
+ if (!ssl->quic_method->add_handshake_data(ssl, ssl->s3->write_level,
+ data.data(), data.size())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
return false;
}
@@ -269,7 +267,7 @@
return false;
}
- if (!ssl->ctx->quic_method &&
+ if (!ssl->quic_method &&
!add_record_to_flight(ssl, SSL3_RT_CHANGE_CIPHER_SPEC,
kChangeCipherSpec)) {
return false;
@@ -285,13 +283,13 @@
return -1;
}
- if (ssl->ctx->quic_method) {
+ if (ssl->quic_method) {
if (ssl->s3->write_shutdown != ssl_shutdown_none) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
return -1;
}
- if (!ssl->ctx->quic_method->flush_flight(ssl)) {
+ if (!ssl->quic_method->flush_flight(ssl)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
return -1;
}
diff --git a/src/ssl/s3_pkt.cc b/src/ssl/s3_pkt.cc
index f0ae8a2..abc6798 100644
--- a/src/ssl/s3_pkt.cc
+++ b/src/ssl/s3_pkt.cc
@@ -232,25 +232,29 @@
return -1;
}
- if (len == 0) {
- return 0;
- }
-
if (!tls_flush_pending_hs_data(ssl)) {
return -1;
}
+
size_t flight_len = 0;
if (ssl->s3->pending_flight != nullptr) {
flight_len =
ssl->s3->pending_flight->length - ssl->s3->pending_flight_offset;
}
- size_t max_out = len + SSL_max_seal_overhead(ssl);
- if (max_out < len || max_out + flight_len < max_out) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
- return -1;
+ size_t max_out = flight_len;
+ if (len > 0) {
+ const size_t max_ciphertext_len = len + SSL_max_seal_overhead(ssl);
+ if (max_ciphertext_len < len || max_out + max_ciphertext_len < max_out) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+ return -1;
+ }
+ max_out += max_ciphertext_len;
}
- max_out += flight_len;
+
+ if (max_out == 0) {
+ return 0;
+ }
if (!buf->EnsureCap(flight_len + ssl_seal_align_prefix_len(ssl), max_out)) {
return -1;
@@ -270,12 +274,14 @@
buf->DidWrite(flight_len);
}
- size_t ciphertext_len;
- if (!tls_seal_record(ssl, buf->remaining().data(), &ciphertext_len,
- buf->remaining().size(), type, in, len)) {
- return -1;
+ if (len > 0) {
+ size_t ciphertext_len;
+ if (!tls_seal_record(ssl, buf->remaining().data(), &ciphertext_len,
+ buf->remaining().size(), type, in, len)) {
+ return -1;
+ }
+ buf->DidWrite(ciphertext_len);
}
- buf->DidWrite(ciphertext_len);
// Now that we've made progress on the connection, uncork KeyUpdate
// acknowledgments.
@@ -404,9 +410,9 @@
}
int ssl3_dispatch_alert(SSL *ssl) {
- if (ssl->ctx->quic_method) {
- if (!ssl->ctx->quic_method->send_alert(ssl, ssl->s3->write_level,
- ssl->s3->send_alert[1])) {
+ if (ssl->quic_method) {
+ if (!ssl->quic_method->send_alert(ssl, ssl->s3->write_level,
+ ssl->s3->send_alert[1])) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
return 0;
}
diff --git a/src/ssl/ssl_aead_ctx.cc b/src/ssl/ssl_aead_ctx.cc
index f01b57d..0bad266 100644
--- a/src/ssl/ssl_aead_ctx.cc
+++ b/src/ssl/ssl_aead_ctx.cc
@@ -42,7 +42,6 @@
random_variable_nonce_(false),
xor_fixed_nonce_(false),
omit_length_in_ad_(false),
- omit_ad_(false),
ad_is_header_(false) {
OPENSSL_memset(fixed_nonce_, 0, sizeof(fixed_nonce_));
}
@@ -134,11 +133,7 @@
aead_ctx->xor_fixed_nonce_ = true;
aead_ctx->variable_nonce_len_ = 8;
aead_ctx->variable_nonce_included_in_record_ = false;
- if (ssl_is_draft28(version)) {
- aead_ctx->ad_is_header_ = true;
- } else {
- aead_ctx->omit_ad_ = true;
- }
+ aead_ctx->ad_is_header_ = true;
assert(fixed_iv.size() >= aead_ctx->variable_nonce_len_);
}
} else {
@@ -231,10 +226,6 @@
return header;
}
- if (omit_ad_) {
- return {};
- }
-
OPENSSL_memcpy(storage, seqnum, 8);
size_t len = 8;
storage[len++] = type;
diff --git a/src/ssl/ssl_cert.cc b/src/ssl/ssl_cert.cc
index 37d6501..1b01e7f 100644
--- a/src/ssl/ssl_cert.cc
+++ b/src/ssl/ssl_cert.cc
@@ -180,6 +180,16 @@
ret->sid_ctx_length = cert->sid_ctx_length;
OPENSSL_memcpy(ret->sid_ctx, cert->sid_ctx, sizeof(ret->sid_ctx));
+ if (cert->dc) {
+ ret->dc = cert->dc->Dup();
+ if (!ret->dc) {
+ return nullptr;
+ }
+ }
+
+ ret->dc_privatekey = UpRef(cert->dc_privatekey);
+ ret->dc_key_method = cert->dc_key_method;
+
return ret;
}
@@ -194,6 +204,10 @@
cert->chain.reset();
cert->privatekey.reset();
cert->key_method = nullptr;
+
+ cert->dc.reset();
+ cert->dc_privatekey.reset();
+ cert->dc_key_method = nullptr;
}
static void ssl_cert_set_cert_cb(CERT *cert, int (*cb)(SSL *ssl, void *arg),
@@ -232,7 +246,7 @@
// An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
// certificates, so sanity-check the key usage extension.
if (pubkey->type == EVP_PKEY_EC &&
- !ssl_cert_check_digital_signature_key_usage(&cert_cbs)) {
+ !ssl_cert_check_key_usage(&cert_cbs, key_usage_digital_signature)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
return leaf_cert_and_privkey_error;
}
@@ -324,10 +338,10 @@
return true;
}
-bool ssl_has_certificate(const SSL_CONFIG *cfg) {
- return cfg->cert->chain != nullptr &&
- sk_CRYPTO_BUFFER_value(cfg->cert->chain.get(), 0) != nullptr &&
- ssl_has_private_key(cfg);
+bool ssl_has_certificate(const SSL_HANDSHAKE *hs) {
+ return hs->config->cert->chain != nullptr &&
+ sk_CRYPTO_BUFFER_value(hs->config->cert->chain.get(), 0) != nullptr &&
+ ssl_has_private_key(hs);
}
bool ssl_parse_cert_chain(uint8_t *out_alert,
@@ -395,7 +409,7 @@
}
bool ssl_add_cert_chain(SSL_HANDSHAKE *hs, CBB *cbb) {
- if (!ssl_has_certificate(hs->config)) {
+ if (!ssl_has_certificate(hs)) {
return CBB_add_u24(cbb, 0);
}
@@ -526,7 +540,7 @@
return ssl_compare_public_and_private_key(pubkey.get(), privkey);
}
-bool ssl_cert_check_digital_signature_key_usage(const CBS *in) {
+bool ssl_cert_check_key_usage(const CBS *in, enum ssl_key_usage_t bit) {
CBS buf = *in;
CBS tbs_cert, outer_extensions;
@@ -592,8 +606,8 @@
return false;
}
- if (!CBS_asn1_bitstring_has_bit(&bit_string, 0)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+ if (!CBS_asn1_bitstring_has_bit(&bit_string, bit)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_KEY_USAGE_BIT_INCORRECT);
return false;
}
@@ -696,20 +710,6 @@
return false;
}
- // Check key usages for all key types but RSA. This is needed to distinguish
- // ECDH certificates, which we do not support, from ECDSA certificates. In
- // principle, we should check RSA key usages based on cipher, but this breaks
- // buggy antivirus deployments. Other key types are always used for signing.
- //
- // TODO(davidben): Get more recent data on RSA key usages.
- if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) {
- CBS leaf_cbs;
- CBS_init(&leaf_cbs, CRYPTO_BUFFER_data(leaf), CRYPTO_BUFFER_len(leaf));
- if (!ssl_cert_check_digital_signature_key_usage(&leaf_cbs)) {
- return false;
- }
- }
-
if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
// Check the key's group and point format are acceptable.
EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
@@ -728,7 +728,7 @@
bool ssl_on_certificate_selected(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_has_certificate(hs->config)) {
+ if (!ssl_has_certificate(hs)) {
// Nothing to do.
return true;
}
@@ -741,10 +741,143 @@
CRYPTO_BUFFER_init_CBS(
sk_CRYPTO_BUFFER_value(hs->config->cert->chain.get(), 0), &leaf);
- hs->local_pubkey = ssl_cert_parse_pubkey(&leaf);
+ if (ssl_signing_with_dc(hs)) {
+ hs->local_pubkey = UpRef(hs->config->cert->dc->pkey);
+ } else {
+ hs->local_pubkey = ssl_cert_parse_pubkey(&leaf);
+ }
return hs->local_pubkey != NULL;
}
+
+// Delegated credentials.
+
+DC::DC() = default;
+DC::~DC() = default;
+
+UniquePtr<DC> DC::Dup() {
+ bssl::UniquePtr<DC> ret = MakeUnique<DC>();
+ if (!ret) {
+ return nullptr;
+ }
+
+ ret->raw = UpRef(raw);
+ ret->expected_cert_verify_algorithm = expected_cert_verify_algorithm;
+ ret->pkey = UpRef(pkey);
+ return ret;
+}
+
+// static
+UniquePtr<DC> DC::Parse(CRYPTO_BUFFER *in, uint8_t *out_alert) {
+ UniquePtr<DC> dc = MakeUnique<DC>();
+ if (!dc) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return nullptr;
+ }
+
+ dc->raw = UpRef(in);
+
+ CBS pubkey, deleg, sig;
+ uint32_t valid_time;
+ uint16_t algorithm;
+ CRYPTO_BUFFER_init_CBS(dc->raw.get(), &deleg);
+ if (!CBS_get_u32(&deleg, &valid_time) ||
+ !CBS_get_u16(&deleg, &dc->expected_cert_verify_algorithm) ||
+ !CBS_get_u24_length_prefixed(&deleg, &pubkey) ||
+ !CBS_get_u16(&deleg, &algorithm) ||
+ !CBS_get_u16_length_prefixed(&deleg, &sig) ||
+ CBS_len(&deleg) != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return nullptr;
+ }
+
+ dc->pkey.reset(EVP_parse_public_key(&pubkey));
+ if (dc->pkey == nullptr) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return nullptr;
+ }
+
+ return dc;
+}
+
+// ssl_can_serve_dc returns true if the host has configured a DC that it can
+// serve in the handshake. Specifically, it checks that a DC has been
+// configured, that the DC protocol version is the same as the negotiated
+// protocol version, and that the DC signature algorithm is supported by the
+// peer.
+static bool ssl_can_serve_dc(const SSL_HANDSHAKE *hs) {
+ // Check that a DC has been configured.
+ const CERT *cert = hs->config->cert.get();
+ if (cert->dc == nullptr ||
+ cert->dc->raw == nullptr ||
+ (cert->dc_privatekey == nullptr && cert->dc_key_method == nullptr)) {
+ return false;
+ }
+
+ // Check that 1.3 or higher has been negotiated.
+ const DC *dc = cert->dc.get();
+ assert(hs->ssl->s3->have_version);
+ if (ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
+ return false;
+ }
+
+ // Check that the DC signature algorithm is supported by the peer.
+ Span<const uint16_t> peer_sigalgs = tls1_get_peer_verify_algorithms(hs);
+ bool sigalg_found = false;
+ for (uint16_t peer_sigalg : peer_sigalgs) {
+ if (dc->expected_cert_verify_algorithm == peer_sigalg) {
+ sigalg_found = true;
+ break;
+ }
+ }
+
+ return sigalg_found;
+}
+
+bool ssl_signing_with_dc(const SSL_HANDSHAKE *hs) {
+ // As of draft-ietf-tls-subcert-03, only the server may use delegated
+ // credentials to authenticate itself.
+ return hs->ssl->server &&
+ hs->delegated_credential_requested &&
+ ssl_can_serve_dc(hs);
+}
+
+static int cert_set_dc(CERT *cert, CRYPTO_BUFFER *const raw, EVP_PKEY *privkey,
+ const SSL_PRIVATE_KEY_METHOD *key_method) {
+ if (privkey == nullptr && key_method == nullptr) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (privkey != nullptr && key_method != nullptr) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD);
+ return 0;
+ }
+
+ uint8_t alert;
+ UniquePtr<DC> dc = DC::Parse(raw, &alert);
+ if (dc == nullptr) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_DELEGATED_CREDENTIAL);
+ return 0;
+ }
+
+ if (privkey) {
+ // Check that the public and private keys match.
+ if (!ssl_compare_public_and_private_key(dc->pkey.get(), privkey)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_AND_PRIVATE_KEY_MISMATCH);
+ return 0;
+ }
+ }
+
+ cert->dc = std::move(dc);
+ cert->dc_privatekey = UpRef(privkey);
+ cert->dc_key_method = key_method;
+
+ return 1;
+}
+
BSSL_NAMESPACE_END
using namespace bssl;
@@ -870,3 +1003,12 @@
ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl->config.get());
ssl->config->client_CA.reset(name_list);
}
+
+int SSL_set1_delegated_credential(SSL *ssl, CRYPTO_BUFFER *dc, EVP_PKEY *pkey,
+ const SSL_PRIVATE_KEY_METHOD *key_method) {
+ if (!ssl->config) {
+ return 0;
+ }
+
+ return cert_set_dc(ssl->config->cert.get(), dc, pkey, key_method);
+}
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
index 108ea6a..78d2aa1 100644
--- a/src/ssl/ssl_key_share.cc
+++ b/src/ssl/ssl_key_share.cc
@@ -220,11 +220,12 @@
X25519_keypair(x25519_public_key, x25519_private_key_);
uint8_t hrss_entropy[HRSS_GENERATE_KEY_BYTES];
+ HRSS_public_key hrss_public_key;
RAND_bytes(hrss_entropy, sizeof(hrss_entropy));
- HRSS_generate_key(&hrss_public_key_, &hrss_private_key_, hrss_entropy);
+ HRSS_generate_key(&hrss_public_key, &hrss_private_key_, hrss_entropy);
uint8_t hrss_public_key_bytes[HRSS_PUBLIC_KEY_BYTES];
- HRSS_marshal_public_key(hrss_public_key_bytes, &hrss_public_key_);
+ HRSS_marshal_public_key(hrss_public_key_bytes, &hrss_public_key);
if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
!CBB_add_bytes(out, hrss_public_key_bytes,
@@ -233,7 +234,7 @@
}
return true;
- };
+ }
bool Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
@@ -287,16 +288,15 @@
return false;
}
- HRSS_decap(secret.data() + 32, &hrss_public_key_, &hrss_private_key_,
- peer_key.data() + 32, peer_key.size() - 32);
+ HRSS_decap(secret.data() + 32, &hrss_private_key_, peer_key.data() + 32,
+ peer_key.size() - 32);
*out_secret = std::move(secret);
return true;
- };
+ }
private:
uint8_t x25519_private_key_[32];
- HRSS_public_key hrss_public_key_;
HRSS_private_key hrss_private_key_;
};
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index ceeba89..a4f2044 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -640,7 +640,6 @@
max_send_fragment(ctx_arg->max_send_fragment),
msg_callback(ctx_arg->msg_callback),
msg_callback_arg(ctx_arg->msg_callback_arg),
- tls13_variant(ctx_arg->tls13_variant),
ctx(UpRef(ctx_arg)),
session_ctx(UpRef(ctx_arg)),
options(ctx->options),
@@ -715,6 +714,7 @@
ssl->config->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled;
ssl->config->handoff = ctx->handoff;
ssl->config->ignore_tls13_downgrade = ctx->ignore_tls13_downgrade;
+ ssl->quic_method = ctx->quic_method;
if (!ssl->method->ssl_new(ssl.get()) ||
!ssl->ctx->x509_method->ssl_new(ssl->s3->hs.get())) {
@@ -729,6 +729,7 @@
signed_cert_timestamps_enabled(false),
ocsp_stapling_enabled(false),
channel_id_enabled(false),
+ enforce_rsa_key_usage(false),
retain_only_sha256_of_client_certs(false),
handoff(false),
shed_handshake_config(false),
@@ -851,7 +852,7 @@
int SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level,
const uint8_t *data, size_t len) {
- if (ssl->ctx->quic_method == nullptr) {
+ if (ssl->quic_method == nullptr) {
OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
@@ -1078,7 +1079,7 @@
}
int SSL_peek(SSL *ssl, void *buf, int num) {
- if (ssl->ctx->quic_method != nullptr) {
+ if (ssl->quic_method != nullptr) {
OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
@@ -1099,7 +1100,7 @@
int SSL_write(SSL *ssl, const void *buf, int num) {
ssl_reset_error_state(ssl);
- if (ssl->ctx->quic_method != nullptr) {
+ if (ssl->quic_method != nullptr) {
OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
@@ -1135,6 +1136,37 @@
return ret;
}
+int SSL_key_update(SSL *ssl, int request_type) {
+ ssl_reset_error_state(ssl);
+
+ if (ssl->do_handshake == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
+ return 0;
+ }
+
+ if (ssl->ctx->quic_method != nullptr) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ if (!ssl->s3->initial_handshake_complete) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_NOT_COMPLETE);
+ return 0;
+ }
+
+ if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
+ return 0;
+ }
+
+ if (!ssl->s3->key_update_pending &&
+ !tls13_add_key_update(ssl, request_type)) {
+ return 0;
+ }
+
+ return 1;
+}
+
int SSL_shutdown(SSL *ssl) {
ssl_reset_error_state(ssl);
@@ -1230,14 +1262,6 @@
ctx->enable_early_data = !!enabled;
}
-void SSL_CTX_set_tls13_variant(SSL_CTX *ctx, enum tls13_variant_t variant) {
- ctx->tls13_variant = variant;
-}
-
-void SSL_set_tls13_variant(SSL *ssl, enum tls13_variant_t variant) {
- ssl->tls13_variant = variant;
-}
-
void SSL_set_early_data_enabled(SSL *ssl, int enabled) {
ssl->enable_early_data = !!enabled;
}
@@ -1320,7 +1344,7 @@
return SSL_ERROR_HANDBACK;
case SSL_READING: {
- if (ssl->ctx->quic_method) {
+ if (ssl->quic_method) {
return SSL_ERROR_WANT_READ;
}
BIO *bio = SSL_get_rbio(ssl);
@@ -2437,6 +2461,14 @@
return 1;
}
+int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method) {
+ if (ssl->method->is_dtls) {
+ return 0;
+ }
+ ssl->quic_method = quic_method;
+ return 1;
+}
+
int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
CRYPTO_EX_dup *dup_unused, CRYPTO_EX_free *free_func) {
int index;
@@ -2666,6 +2698,13 @@
ctx->reverify_on_resume = !!enabled;
}
+void SSL_set_enforce_rsa_key_usage(SSL *ssl, int enabled) {
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->enforce_rsa_key_usage = !!enabled;
+}
+
void SSL_set_renegotiate_mode(SSL *ssl, enum ssl_renegotiate_mode_t mode) {
ssl->renegotiate_mode = mode;
diff --git a/src/ssl/ssl_privkey.cc b/src/ssl/ssl_privkey.cc
index e716c9a..1ddb1b1 100644
--- a/src/ssl/ssl_privkey.cc
+++ b/src/ssl/ssl_privkey.cc
@@ -133,8 +133,14 @@
return NULL;
}
-bool ssl_has_private_key(const SSL_CONFIG *cfg) {
- return cfg->cert->privatekey != nullptr || cfg->cert->key_method != nullptr;
+bool ssl_has_private_key(const SSL_HANDSHAKE *hs) {
+ if (hs->config->cert->privatekey != nullptr ||
+ hs->config->cert->key_method != nullptr ||
+ ssl_signing_with_dc(hs)) {
+ return true;
+ }
+
+ return false;
}
static bool pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
@@ -195,13 +201,20 @@
SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
uint16_t sigalg, Span<const uint8_t> in) {
SSL *const ssl = hs->ssl;
- if (hs->config->cert->key_method != NULL) {
+ const SSL_PRIVATE_KEY_METHOD *key_method = hs->config->cert->key_method;
+ EVP_PKEY *privatekey = hs->config->cert->privatekey.get();
+ if (ssl_signing_with_dc(hs)) {
+ key_method = hs->config->cert->dc_key_method;
+ privatekey = hs->config->cert->dc_privatekey.get();
+ }
+
+ if (key_method != NULL) {
enum ssl_private_key_result_t ret;
if (hs->pending_private_key_op) {
- ret = hs->config->cert->key_method->complete(ssl, out, out_len, max_out);
+ ret = key_method->complete(ssl, out, out_len, max_out);
} else {
- ret = hs->config->cert->key_method->sign(ssl, out, out_len, max_out,
- sigalg, in.data(), in.size());
+ ret = key_method->sign(ssl, out, out_len, max_out,
+ sigalg, in.data(), in.size());
}
if (ret == ssl_private_key_failure) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED);
@@ -212,8 +225,7 @@
*out_len = max_out;
ScopedEVP_MD_CTX ctx;
- if (!setup_ctx(ssl, ctx.get(), hs->config->cert->privatekey.get(), sigalg,
- false /* sign */) ||
+ if (!setup_ctx(ssl, ctx.get(), privatekey, sigalg, false /* sign */) ||
!EVP_DigestSign(ctx.get(), out, out_len, in.data(), in.size())) {
return ssl_private_key_failure;
}
@@ -552,6 +564,10 @@
}
static bool sigalgs_unique(Span<const uint16_t> in_sigalgs) {
+ if (in_sigalgs.size() < 2) {
+ return true;
+ }
+
Array<uint16_t> sigalgs;
if (!sigalgs.CopyFrom(in_sigalgs)) {
return false;
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 8d01c03..f3f7923 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -2628,11 +2628,6 @@
// SSL 3.0 is not available.
EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION));
- // TLS1_3_DRAFT_VERSION is not an API-level version.
- EXPECT_FALSE(
- SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_DRAFT23_VERSION));
- ERR_clear_error();
-
ctx.reset(SSL_CTX_new(DTLS_method()));
ASSERT_TRUE(ctx);
@@ -4358,6 +4353,35 @@
EXPECT_EQ(1u, server->config->supported_group_list.size());
}
+TEST(SSLTest, ZeroSizedWiteFlushesHandshakeMessages) {
+ // If there are pending handshake mesages, an |SSL_write| of zero bytes should
+ // flush them.
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+ EXPECT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION));
+ EXPECT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_3_VERSION));
+ bssl::UniquePtr<X509> cert = GetTestCertificate();
+ bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+ ASSERT_TRUE(cert);
+ ASSERT_TRUE(key);
+ ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+ ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
+
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+ EXPECT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION));
+ EXPECT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_3_VERSION));
+
+ bssl::UniquePtr<SSL> client, server;
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get()));
+
+ BIO *client_wbio = SSL_get_wbio(client.get());
+ EXPECT_EQ(0u, BIO_wpending(client_wbio));
+ EXPECT_TRUE(SSL_key_update(client.get(), SSL_KEY_UPDATE_NOT_REQUESTED));
+ EXPECT_EQ(0u, BIO_wpending(client_wbio));
+ EXPECT_EQ(0, SSL_write(client.get(), nullptr, 0));
+ EXPECT_NE(0u, BIO_wpending(client_wbio));
+}
+
TEST_P(SSLVersionTest, VerifyBeforeCertRequest) {
// Configure the server to request client certificates.
SSL_CTX_set_custom_verify(
diff --git a/src/ssl/ssl_versions.cc b/src/ssl/ssl_versions.cc
index 8616967..e6dbc8d 100644
--- a/src/ssl/ssl_versions.cc
+++ b/src/ssl/ssl_versions.cc
@@ -34,11 +34,6 @@
*out = version;
return true;
- case TLS1_3_DRAFT23_VERSION:
- case TLS1_3_DRAFT28_VERSION:
- *out = TLS1_3_VERSION;
- return true;
-
case DTLS1_VERSION:
// DTLS 1.0 is analogous to TLS 1.1, not TLS 1.0.
*out = TLS1_1_VERSION;
@@ -58,8 +53,6 @@
static const uint16_t kTLSVersions[] = {
TLS1_3_VERSION,
- TLS1_3_DRAFT28_VERSION,
- TLS1_3_DRAFT23_VERSION,
TLS1_2_VERSION,
TLS1_1_VERSION,
TLS1_VERSION,
@@ -95,14 +88,10 @@
}
// The following functions map between API versions and wire versions. The
-// public API works on wire versions, except that TLS 1.3 draft versions all
-// appear as TLS 1.3. This will get collapsed back down when TLS 1.3 is
-// finalized.
+// public API works on wire versions.
static const char *ssl_version_to_string(uint16_t version) {
switch (version) {
- case TLS1_3_DRAFT23_VERSION:
- case TLS1_3_DRAFT28_VERSION:
case TLS1_3_VERSION:
return "TLSv1.3";
@@ -127,26 +116,11 @@
}
static uint16_t wire_version_to_api(uint16_t version) {
- switch (version) {
- // Report TLS 1.3 draft versions as TLS 1.3 in the public API.
- case TLS1_3_DRAFT23_VERSION:
- case TLS1_3_DRAFT28_VERSION:
- case TLS1_3_VERSION:
- return TLS1_3_VERSION;
- default:
- return version;
- }
+ return version;
}
-// api_version_to_wire maps |version| to some representative wire version. In
-// particular, it picks an arbitrary TLS 1.3 representative. This should only be
-// used in context where that does not matter.
+// api_version_to_wire maps |version| to some representative wire version.
static bool api_version_to_wire(uint16_t *out, uint16_t version) {
- if (version == TLS1_3_DRAFT23_VERSION ||
- version == TLS1_3_DRAFT28_VERSION) {
- return false;
- }
-
// Check it is a real protocol version.
uint16_t unused;
if (!ssl_protocol_version_from_wire(&unused, version)) {
@@ -218,7 +192,7 @@
uint16_t max_version = hs->config->conf_max_version;
// QUIC requires TLS 1.3.
- if (hs->ssl->ctx->quic_method && min_version < TLS1_3_VERSION) {
+ if (hs->ssl->quic_method && min_version < TLS1_3_VERSION) {
min_version = TLS1_3_VERSION;
}
@@ -299,21 +273,6 @@
return false;
}
- // If the TLS 1.3 variant is set to |tls13_default|, all variants are enabled,
- // otherwise only the matching version is enabled.
- if (protocol_version == TLS1_3_VERSION) {
- switch (ssl->tls13_variant) {
- case tls13_draft23:
- return version == TLS1_3_DRAFT23_VERSION;
- case tls13_draft28:
- return version == TLS1_3_DRAFT28_VERSION;
- case tls13_rfc:
- return version == TLS1_3_VERSION;
- case tls13_all:
- return true;
- }
- }
-
return true;
}
@@ -373,10 +332,6 @@
return false;
}
-bool ssl_is_draft28(uint16_t version) {
- return version == TLS1_3_DRAFT28_VERSION || version == TLS1_3_VERSION;
-}
-
BSSL_NAMESPACE_END
using namespace bssl;
diff --git a/src/ssl/ssl_x509.cc b/src/ssl/ssl_x509.cc
index eb3a38b..841482f 100644
--- a/src/ssl/ssl_x509.cc
+++ b/src/ssl/ssl_x509.cc
@@ -448,7 +448,7 @@
// Only build a chain if there are no intermediates configured and the feature
// isn't disabled.
if ((hs->ssl->mode & SSL_MODE_NO_AUTO_CHAIN) ||
- !ssl_has_certificate(hs->config) || hs->config->cert->chain == NULL ||
+ !ssl_has_certificate(hs) || hs->config->cert->chain == NULL ||
sk_CRYPTO_BUFFER_num(hs->config->cert->chain.get()) > 1) {
return 1;
}
@@ -1223,7 +1223,8 @@
assert(ssl->config);
return -1;
}
- if (ssl_has_certificate(ssl->config.get()) ||
+
+ if (ssl_has_certificate(ssl->s3->hs.get()) ||
ssl->ctx->client_cert_cb == NULL) {
return 1;
}
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 5e65f81..3a08fe6 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -292,23 +292,10 @@
SSL_CURVE_SECP384R1,
};
-// TLS 1.3 servers will pick CECPQ2 if offered by a client, but it's not enabled
-// by default for clients.
-static const uint16_t kDefaultGroupsServer[] = {
- // CECPQ2 is not yet enabled by default.
- // SSL_CURVE_CECPQ2,
- SSL_CURVE_X25519,
- SSL_CURVE_SECP256R1,
- SSL_CURVE_SECP384R1,
-};;
-
Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) {
if (!hs->config->supported_group_list.empty()) {
return hs->config->supported_group_list;
}
- if (hs->ssl->server) {
- return Span<const uint16_t>(kDefaultGroupsServer);
- }
return Span<const uint16_t>(kDefaultGroups);
}
@@ -2715,6 +2702,36 @@
return true;
}
+// Delegated credentials.
+//
+// https://tools.ietf.org/html/draft-ietf-tls-subcerts
+
+static bool ext_delegated_credential_add_clienthello(SSL_HANDSHAKE *hs,
+ CBB *out) {
+ return true;
+}
+
+static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
+ CBS *contents) {
+ assert(TLSEXT_TYPE_delegated_credential == 0xff02);
+ // TODO: Check that the extension is empty.
+ //
+ // As of draft-02, the client sends an empty extension in order indicate
+ // support for delegated credentials. This could change, however, since the
+ // spec is not yet finalized. This assertion is here to remind us to enforce
+ // this check once the extension ID is assigned.
+
+ if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
+ // Don't use delegated credentials unless we're negotiating TLS 1.3 or
+ // higher.
+ return true;
+ }
+
+ hs->delegated_credential_requested = true;
+ return true;
+}
+
// Certificate compression
static bool cert_compression_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
@@ -3003,6 +3020,14 @@
cert_compression_parse_clienthello,
cert_compression_add_serverhello,
},
+ {
+ TLSEXT_TYPE_delegated_credential,
+ NULL,
+ ext_delegated_credential_add_clienthello,
+ forbid_parse_serverhello,
+ ext_delegated_credential_parse_clienthello,
+ dont_add_serverhello,
+ },
};
#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
@@ -3629,6 +3654,7 @@
bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) {
SSL *const ssl = hs->ssl;
CERT *cert = hs->config->cert.get();
+ DC *dc = cert->dc.get();
// Before TLS 1.2, the signature algorithm isn't negotiated as part of the
// handshake.
@@ -3641,19 +3667,13 @@
}
Span<const uint16_t> sigalgs = kSignSignatureAlgorithms;
- if (!cert->sigalgs.empty()) {
+ if (ssl_signing_with_dc(hs)) {
+ sigalgs = MakeConstSpan(&dc->expected_cert_verify_algorithm, 1);
+ } else if (!cert->sigalgs.empty()) {
sigalgs = cert->sigalgs;
}
- Span<const uint16_t> peer_sigalgs = hs->peer_sigalgs;
- if (peer_sigalgs.empty() && ssl_protocol_version(ssl) < TLS1_3_VERSION) {
- // If the client didn't specify any signature_algorithms extension then
- // we can assume that it supports SHA1. See
- // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
- static const uint16_t kDefaultPeerAlgorithms[] = {SSL_SIGN_RSA_PKCS1_SHA1,
- SSL_SIGN_ECDSA_SHA1};
- peer_sigalgs = kDefaultPeerAlgorithms;
- }
+ Span<const uint16_t> peer_sigalgs = tls1_get_peer_verify_algorithms(hs);
for (uint16_t sigalg : sigalgs) {
// SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal value and should never be
@@ -3675,6 +3695,19 @@
return false;
}
+Span<const uint16_t> tls1_get_peer_verify_algorithms(const SSL_HANDSHAKE *hs) {
+ Span<const uint16_t> peer_sigalgs = hs->peer_sigalgs;
+ if (peer_sigalgs.empty() && ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
+ // If the client didn't specify any signature_algorithms extension then
+ // we can assume that it supports SHA1. See
+ // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+ static const uint16_t kDefaultPeerAlgorithms[] = {SSL_SIGN_RSA_PKCS1_SHA1,
+ SSL_SIGN_ECDSA_SHA1};
+ peer_sigalgs = kDefaultPeerAlgorithms;
+ }
+ return peer_sigalgs;
+}
+
bool tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
SSL *const ssl = hs->ssl;
// A Channel ID handshake message is structured to contain multiple
diff --git a/src/ssl/test/CMakeLists.txt b/src/ssl/test/CMakeLists.txt
index d86464c..ebc16f1 100644
--- a/src/ssl/test/CMakeLists.txt
+++ b/src/ssl/test/CMakeLists.txt
@@ -10,13 +10,11 @@
settings_writer.cc
test_config.cc
test_state.cc
-
- $<TARGET_OBJECTS:test_support>
)
add_dependencies(bssl_shim global_target)
-target_link_libraries(bssl_shim ssl crypto)
+target_link_libraries(bssl_shim test_support_lib ssl crypto)
if(UNIX AND NOT APPLE AND NOT ANDROID)
add_executable(
@@ -29,13 +27,11 @@
settings_writer.cc
test_config.cc
test_state.cc
-
- $<TARGET_OBJECTS:test_support>
)
add_dependencies(handshaker global_target)
- target_link_libraries(handshaker ssl crypto)
+ target_link_libraries(handshaker test_support_lib ssl crypto)
else()
# Declare a dummy target for run_tests to depend on.
add_custom_target(handshaker)
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 77ed796..62db076 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -981,6 +981,12 @@
pending_initial_write = false;
}
+ if (config->key_update &&
+ !SSL_key_update(ssl, SSL_KEY_UPDATE_NOT_REQUESTED)) {
+ fprintf(stderr, "SSL_key_update failed.\n");
+ return false;
+ }
+
for (int i = 0; i < n; i++) {
buf[i] ^= 0xff;
}
diff --git a/src/ssl/test/fuzzer.h b/src/ssl/test/fuzzer.h
index 1ca970d..f714d5d 100644
--- a/src/ssl/test/fuzzer.h
+++ b/src/ssl/test/fuzzer.h
@@ -414,6 +414,13 @@
return false;
}
+ static const int kCurves[] = {NID_CECPQ2, NID_X25519, NID_X9_62_prime256v1,
+ NID_secp384r1, NID_secp521r1};
+ if (!SSL_CTX_set1_curves(ctx_.get(), kCurves,
+ OPENSSL_ARRAY_SIZE(kCurves))) {
+ return false;
+ }
+
SSL_CTX_set_early_data_enabled(ctx_.get(), 1);
SSL_CTX_set_next_proto_select_cb(ctx_.get(), NPNSelectCallback, nullptr);
@@ -489,16 +496,6 @@
SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, nullptr);
break;
- case kTLS13Variant: {
- uint8_t variant;
- if (!CBS_get_u8(cbs, &variant)) {
- return nullptr;
- }
- SSL_set_tls13_variant(ssl.get(),
- static_cast<tls13_variant_t>(variant));
- break;
- }
-
case kHandoffTag: {
CBS handoff;
if (!CBS_get_u24_length_prefixed(cbs, &handoff)) {
diff --git a/src/ssl/test/fuzzer_tags.h b/src/ssl/test/fuzzer_tags.h
index c21aca3..eb9991d 100644
--- a/src/ssl/test/fuzzer_tags.h
+++ b/src/ssl/test/fuzzer_tags.h
@@ -39,13 +39,10 @@
// certificates.
static const uint16_t kRequestClientCert = 2;
-// kTLS13Variant is followed by a u8 denoting the TLS 1.3 variant to configure.
-static const uint16_t kTLS13Variant = 3;
-
// kHandoffTag is followed by the output of |SSL_serialize_handoff|.
-static const uint16_t kHandoffTag = 4;
+static const uint16_t kHandoffTag = 3;
// kHandbackTag is followed by te output of |SSL_serialize_handback|.
-static const uint16_t kHandbackTag = 5;
+static const uint16_t kHandbackTag = 4;
#endif // HEADER_SSL_TEST_FUZZER_TAGS
diff --git a/src/ssl/test/runner/cipher_suites.go b/src/ssl/test/runner/cipher_suites.go
index 3246f0b..e827c52 100644
--- a/src/ssl/test/runner/cipher_suites.go
+++ b/src/ssl/test/runner/cipher_suites.go
@@ -33,7 +33,7 @@
// This method may not be called if the server doesn't send a
// ServerKeyExchange message.
- processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
+ processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, crypto.PublicKey, *serverKeyExchangeMsg) error
generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
// peerSignatureAlgorithm returns the signature algorithm used by the
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index d99518c..bbcacf5 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -32,23 +32,8 @@
VersionDTLS12 = 0xfefd
)
-// A draft version of TLS 1.3 that is sent over the wire for the current draft.
-const (
- tls13Draft23Version = 0x7f17
- tls13Draft28Version = 0x7f1c
-)
-
-const (
- TLS13RFC = 0
- TLS13Draft23 = 1
- TLS13Draft28 = 2
- TLS13All = 3
-)
-
var allTLSWireVersions = []uint16{
VersionTLS13,
- tls13Draft28Version,
- tls13Draft23Version,
VersionTLS12,
VersionTLS11,
VersionTLS10,
@@ -140,6 +125,7 @@
extensionRenegotiationInfo uint16 = 0xff01
extensionQUICTransportParams uint16 = 0xffa5 // draft-ietf-quic-tls-13
extensionChannelID uint16 = 30032 // not IANA assigned
+ extensionDelegatedCredentials uint16 = 0xff02 // not IANA assigned
)
// TLS signaling cipher suite values
@@ -447,9 +433,6 @@
// which is currently TLS 1.2.
MaxVersion uint16
- // TLS13Variant is the variant of TLS 1.3 to use.
- TLS13Variant int
-
// CurvePreferences contains the elliptic curves that will be used in
// an ECDHE handshake, in preference order. If empty, the default will
// be used.
@@ -1531,10 +1514,6 @@
// specified number of plaintext bytes per record.
ExpectPackedEncryptedHandshake int
- // ForbidHandshakePacking, if true, requires the peer place a record
- // boundary after every handshake message.
- ForbidHandshakePacking bool
-
// SendTicketLifetime, if non-zero, is the ticket lifetime to send in
// NewSessionTicket messages.
SendTicketLifetime time.Duration
@@ -1658,6 +1637,18 @@
// ExpectKeyShares, if not nil, lists (in order) the curves that a ClientHello
// should have key shares for.
ExpectedKeyShares []CurveID
+
+ // ExpectDelegatedCredentials, if true, requires that the handshake present
+ // delegated credentials.
+ ExpectDelegatedCredentials bool
+
+ // FailIfDelegatedCredentials, if true, causes a handshake failure if the
+ // server returns delegated credentials.
+ FailIfDelegatedCredentials bool
+
+ // DisableDelegatedCredentials, if true, disables client support for delegated
+ // credentials.
+ DisableDelegatedCredentials bool
}
func (c *Config) serverInit() {
@@ -1770,18 +1761,12 @@
switch vers {
case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13:
return vers, true
- case tls13Draft23Version, tls13Draft28Version:
- return VersionTLS13, true
}
}
return 0, false
}
-func isDraft28(vers uint16) bool {
- return vers == tls13Draft28Version || vers == VersionTLS13
-}
-
// isSupportedVersion checks if the specified wire version is acceptable. If so,
// it returns true and the corresponding protocol version. Otherwise, it returns
// false.
@@ -1790,26 +1775,6 @@
if !ok || c.minVersion(isDTLS) > vers || vers > c.maxVersion(isDTLS) {
return 0, false
}
- if vers == VersionTLS13 {
- switch c.TLS13Variant {
- case TLS13Draft23:
- if wireVers != tls13Draft23Version {
- return 0, false
- }
- case TLS13Draft28:
- if wireVers != tls13Draft28Version {
- return 0, false
- }
- case TLS13RFC:
- if wireVers != VersionTLS13 {
- return 0, false
- }
- case TLS13All:
- // Allow all of them.
- default:
- panic(c.TLS13Variant)
- }
- }
return vers, true
}
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index b6b6ffa..8a3ed5d 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -106,6 +106,7 @@
pendingFragments [][]byte // pending outgoing handshake fragments.
pendingPacket []byte // pending outgoing packet.
+ keyUpdateSeen bool
keyUpdateRequested bool
seenOneByteRecord bool
@@ -453,7 +454,7 @@
n := len(payload) - c.Overhead()
additionalData[11] = byte(n >> 8)
additionalData[12] = byte(n)
- } else if isDraft28(hc.wireVersion) {
+ } else {
additionalData = b.data[:recordHeaderLen]
}
var err error
@@ -619,7 +620,7 @@
copy(additionalData[8:], b.data[:3])
additionalData[11] = byte(payloadLen >> 8)
additionalData[12] = byte(payloadLen)
- } else if isDraft28(hc.wireVersion) {
+ } else {
additionalData = make([]byte, 5)
copy(additionalData, b.data[:3])
n := len(b.data) - recordHeaderLen
@@ -1321,9 +1322,6 @@
return nil, err
}
}
- if c.hand.Len() > 4+n && c.config.Bugs.ForbidHandshakePacking {
- return nil, errors.New("tls: forbidden trailing data after a handshake message")
- }
return c.hand.Next(4 + n), nil
}
@@ -1635,6 +1633,8 @@
}
if keyUpdate, ok := msg.(*keyUpdateMsg); ok {
+ c.keyUpdateSeen = true
+
if c.config.Bugs.RejectUnsolicitedKeyUpdate {
return errors.New("tls: unexpected KeyUpdate message")
}
@@ -1665,7 +1665,7 @@
keyUpdate, ok := msg.(*keyUpdateMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
- return errors.New("tls: unexpected message when reading KeyUpdate")
+ return fmt.Errorf("tls: unexpected message (%T) when reading KeyUpdate", msg)
}
if keyUpdate.keyUpdateRequest != keyUpdateNotRequested {
@@ -1708,13 +1708,12 @@
// Soft error, like EAGAIN
return 0, err
}
- if c.hand.Len() > 0 {
+ for c.hand.Len() > 0 {
// We received handshake bytes, indicating a
// post-handshake message.
if err := c.handlePostHandshakeMessage(); err != nil {
return 0, err
}
- continue
}
}
if err := c.in.err; err != nil {
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 5234462..45dc75d 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -32,6 +32,8 @@
masterSecret []byte
session *ClientSessionState
finishedBytes []byte
+ peerPublicKey crypto.PublicKey
+ skxAlgo signatureAlgorithm
}
func mapClientHelloVersion(vers uint16, isDTLS bool) uint16 {
@@ -126,6 +128,7 @@
pskBinderFirst: c.config.Bugs.PSKBinderFirst,
omitExtensions: c.config.Bugs.OmitExtensions,
emptyExtensions: c.config.Bugs.EmptyExtensions,
+ delegatedCredentials: !c.config.Bugs.DisableDelegatedCredentials,
}
if maxVersion >= VersionTLS13 {
@@ -424,10 +427,9 @@
if len(hello.pskIdentities) > 0 {
version := session.wireVersion
// We may have a pre-1.3 session if SendBothTickets is
- // set. Fill in an arbitrary TLS 1.3 version to compute
- // the binder.
+ // set.
if session.vers < VersionTLS13 {
- version = tls13Draft23Version
+ version = VersionTLS13
}
generatePSKBinders(version, hello, pskCipherSuite, session.masterSecret, []byte{}, []byte{}, c.config)
}
@@ -979,7 +981,6 @@
if err := hs.verifyCertificates(certMsg); err != nil {
return err
}
- leaf := c.peerCertificates[0]
c.ocspResponse = certMsg.certificates[0].ocspResponse
c.sctList = certMsg.certificates[0].sctList
@@ -995,7 +996,7 @@
c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
- err = verifyMessage(c.vers, getCertificatePublicKey(leaf), c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
+ err = verifyMessage(c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
if err != nil {
return err
}
@@ -1234,7 +1235,7 @@
skx, ok := msg.(*serverKeyExchangeMsg)
if ok {
hs.writeServerHash(skx.marshal())
- err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
+ err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, hs.peerPublicKey, skx)
if err != nil {
c.sendAlert(alertUnexpectedMessage)
return err
@@ -1378,6 +1379,23 @@
return nil
}
+// delegatedCredentialSignedMessage returns the bytes that are signed in order
+// to authenticate a delegated credential.
+func delegatedCredentialSignedMessage(credBytes []byte, algorithm signatureAlgorithm, leafDER []byte) []byte {
+ // https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
+ ret := make([]byte, 64, 128)
+ for i := range ret {
+ ret[i] = 0x20
+ }
+
+ ret = append(ret, []byte("TLS, server delegated credentials\x00")...)
+ ret = append(ret, leafDER...)
+ ret = append(ret, byte(algorithm>>8), byte(algorithm))
+ ret = append(ret, credBytes...)
+
+ return ret
+}
+
func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
c := hs.c
@@ -1386,6 +1404,7 @@
return errors.New("tls: no certificates sent")
}
+ var dc *delegatedCredential
certs := make([]*x509.Certificate, len(certMsg.certificates))
for i, certEntry := range certMsg.certificates {
cert, err := x509.ParseCertificate(certEntry.data)
@@ -1394,6 +1413,22 @@
return errors.New("tls: failed to parse certificate from server: " + err.Error())
}
certs[i] = cert
+
+ if certEntry.delegatedCredential != nil {
+ if c.config.Bugs.FailIfDelegatedCredentials {
+ c.sendAlert(alertIllegalParameter)
+ return errors.New("tls: unexpected delegated credential")
+ }
+ if i != 0 {
+ c.sendAlert(alertIllegalParameter)
+ return errors.New("tls: non-leaf certificate has a delegated credential")
+ }
+ if c.config.Bugs.DisableDelegatedCredentials {
+ c.sendAlert(alertIllegalParameter)
+ return errors.New("tls: server sent delegated credential without it being requested")
+ }
+ dc = certEntry.delegatedCredential
+ }
}
if !c.config.InsecureSkipVerify {
@@ -1418,16 +1453,45 @@
}
}
- publicKey := getCertificatePublicKey(certs[0])
- switch publicKey.(type) {
+ leafPublicKey := getCertificatePublicKey(certs[0])
+ switch leafPublicKey.(type) {
case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
break
default:
c.sendAlert(alertUnsupportedCertificate)
- return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", publicKey)
+ return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leafPublicKey)
}
c.peerCertificates = certs
+
+ if dc != nil {
+ // Note that this doesn't check a) the delegated credential temporal
+ // validity nor b) that the certificate has the special OID asserted.
+ hs.skxAlgo = dc.expectedCertVerifyAlgo
+
+ var err error
+ if hs.peerPublicKey, err = x509.ParsePKIXPublicKey(dc.pkixPublicKey); err != nil {
+ c.sendAlert(alertBadCertificate)
+ return errors.New("tls: failed to parse public key from delegated credential: " + err.Error())
+ }
+
+ verifier, err := getSigner(c.vers, hs.peerPublicKey, c.config, dc.algorithm, true)
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return errors.New("tls: failed to get verifier for delegated credential: " + err.Error())
+ }
+
+ if err := verifier.verifyMessage(leafPublicKey, delegatedCredentialSignedMessage(dc.signedBytes, dc.algorithm, certs[0].Raw), dc.signature); err != nil {
+ c.sendAlert(alertBadCertificate)
+ return errors.New("tls: failed to verify delegated credential: " + err.Error())
+ }
+ } else if c.config.Bugs.ExpectDelegatedCredentials {
+ c.sendAlert(alertInternalError)
+ return errors.New("tls: delegated credentials missing")
+ } else {
+ hs.peerPublicKey = leafPublicKey
+ }
+
return nil
}
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 823c6c8..f12ca1a 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -297,6 +297,7 @@
emptyExtensions bool
pad int
compressedCertAlgs []uint16
+ delegatedCredentials bool
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -350,7 +351,8 @@
m.omitExtensions == m1.omitExtensions &&
m.emptyExtensions == m1.emptyExtensions &&
m.pad == m1.pad &&
- eqUint16s(m.compressedCertAlgs, m1.compressedCertAlgs)
+ eqUint16s(m.compressedCertAlgs, m1.compressedCertAlgs) &&
+ m.delegatedCredentials == m1.delegatedCredentials
}
func (m *clientHelloMsg) marshalKeyShares(bb *byteBuilder) {
@@ -592,6 +594,10 @@
algIDs.addU16(v)
}
}
+ if m.delegatedCredentials {
+ extensions.addU16(extensionDelegatedCredentials)
+ extensions.addU16(0) // Length is always 0
+ }
// The PSK extension must be last. See https://tools.ietf.org/html/rfc8446#section-4.2.11
if len(m.pskIdentities) > 0 && !m.pskBinderFirst {
extensions.addU16(extensionPreSharedKey)
@@ -717,6 +723,7 @@
m.alpnProtocols = nil
m.extendedMasterSecret = false
m.customExtension = ""
+ m.delegatedCredentials = false
if len(reader) == 0 {
// ClientHello is optionally followed by extension data
@@ -947,6 +954,11 @@
return false
}
}
+ case extensionDelegatedCredentials:
+ if len(body) != 0 {
+ return false
+ }
+ m.delegatedCredentials = true
}
if isGREASEValue(extension) {
@@ -1602,6 +1614,17 @@
sctList []byte
duplicateExtensions bool
extraExtension []byte
+ delegatedCredential *delegatedCredential
+}
+
+type delegatedCredential struct {
+ // https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
+ signedBytes []byte
+ lifetimeSecs uint32
+ expectedCertVerifyAlgo signatureAlgorithm
+ pkixPublicKey []byte
+ algorithm signatureAlgorithm
+ signature []byte
}
type certificateMsg struct {
@@ -1700,6 +1723,29 @@
}
case extensionSignedCertificateTimestamp:
cert.sctList = []byte(body)
+ case extensionDelegatedCredentials:
+ // https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
+ if cert.delegatedCredential != nil {
+ return false
+ }
+
+ dc := new(delegatedCredential)
+ origBody := body
+ var expectedCertVerifyAlgo, algorithm uint16
+
+ if !body.readU32(&dc.lifetimeSecs) ||
+ !body.readU16(&expectedCertVerifyAlgo) ||
+ !body.readU24LengthPrefixedBytes(&dc.pkixPublicKey) ||
+ !body.readU16(&algorithm) ||
+ !body.readU16LengthPrefixedBytes(&dc.signature) ||
+ len(body) != 0 {
+ return false
+ }
+
+ dc.expectedCertVerifyAlgo = signatureAlgorithm(expectedCertVerifyAlgo)
+ dc.algorithm = signatureAlgorithm(algorithm)
+ dc.signedBytes = []byte(origBody)[:4+2+3+len(dc.pkixPublicKey)]
+ cert.delegatedCredential = dc
default:
return false
}
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 5486342..d2ef9b4 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -881,10 +881,10 @@
data: certData,
}
if i == 0 {
- if hs.clientHello.ocspStapling {
+ if hs.clientHello.ocspStapling && !c.config.Bugs.NoOCSPStapling {
cert.ocspResponse = hs.cert.OCSPStaple
}
- if hs.clientHello.sctListSupported {
+ if hs.clientHello.sctListSupported && !c.config.Bugs.NoSignedCertificateTimestamps {
cert.sctList = hs.cert.SignedCertificateTimestampList
}
cert.duplicateExtensions = config.Bugs.SendDuplicateCertExtensions
@@ -1577,11 +1577,11 @@
c := hs.c
isPSK := hs.suite.flags&suitePSK != 0
- if !isPSK && hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
+ if !isPSK && hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 && !c.config.Bugs.NoOCSPStapling {
hs.hello.extensions.ocspStapling = true
}
- if hs.clientHello.sctListSupported && len(hs.cert.SignedCertificateTimestampList) > 0 {
+ if hs.clientHello.sctListSupported && len(hs.cert.SignedCertificateTimestampList) > 0 && !c.config.Bugs.NoSignedCertificateTimestamps {
hs.hello.extensions.sctList = hs.cert.SignedCertificateTimestampList
}
diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go
index f40552d..13e78bc 100644
--- a/src/ssl/test/runner/key_agreement.go
+++ b/src/ssl/test/runner/key_agreement.go
@@ -5,6 +5,7 @@
package runner
import (
+ "crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
@@ -133,7 +134,7 @@
return preMasterSecret, nil
}
-func (ka *rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+func (ka *rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, key crypto.PublicKey, skx *serverKeyExchangeMsg) error {
return errors.New("tls: unexpected ServerKeyExchange")
}
@@ -456,7 +457,7 @@
// to authenticate the ServerKeyExchange parameters.
type keyAgreementAuthentication interface {
signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error)
- verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error
+ verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, key crypto.PublicKey, params []byte, sig []byte) error
}
// nilKeyAgreementAuthentication does not authenticate the key
@@ -469,7 +470,7 @@
return skx, nil
}
-func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
+func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, key crypto.PublicKey, params []byte, sig []byte) error {
return nil
}
@@ -529,9 +530,8 @@
return skx, nil
}
-func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
+func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, publicKey crypto.PublicKey, params []byte, sig []byte) error {
// The peer's key must match the cipher type.
- publicKey := getCertificatePublicKey(cert)
switch ka.keyType {
case keyTypeECDSA:
_, edsaOk := publicKey.(*ecdsa.PublicKey)
@@ -646,7 +646,7 @@
return ka.curve.finish(ckx.ciphertext[1:])
}
-func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, key crypto.PublicKey, skx *serverKeyExchangeMsg) error {
if len(skx.key) < 4 {
return errServerKeyExchange
}
@@ -671,7 +671,7 @@
// Check the signature.
serverECDHParams := skx.key[:4+publicLen]
sig := skx.key[4+publicLen:]
- return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
+ return ka.auth.verifyParameters(config, clientHello, serverHello, key, serverECDHParams, sig)
}
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
@@ -722,7 +722,7 @@
return nil, nil
}
-func (ka *nilKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+func (ka *nilKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, key crypto.PublicKey, skx *serverKeyExchangeMsg) error {
if len(skx.key) != 0 {
return errServerKeyExchange
}
@@ -820,7 +820,7 @@
return makePSKPremaster(otherSecret, config.PreSharedKey), nil
}
-func (ka *pskKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+func (ka *pskKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, key crypto.PublicKey, skx *serverKeyExchangeMsg) error {
if len(skx.key) < 2 {
return errServerKeyExchange
}
@@ -833,7 +833,7 @@
// Process the remainder of the ServerKeyExchange.
newSkx := new(serverKeyExchangeMsg)
newSkx.key = skx.key[2+identityLen:]
- return ka.base.processServerKeyExchange(config, clientHello, serverHello, cert, newSkx)
+ return ka.base.processServerKeyExchange(config, clientHello, serverHello, key, newSkx)
}
func (ka *pskKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index b5cc0a7..8461bd8 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -16,9 +16,11 @@
import (
"bytes"
+ "crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
+ "crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
@@ -246,6 +248,143 @@
garbageCertificate.PrivateKey = rsaCertificate.PrivateKey
}
+// delegatedCredentialConfig specifies the shape of a delegated credential, not
+// including the keys themselves.
+type delegatedCredentialConfig struct {
+ // lifetime is the amount of time, from the notBefore of the parent
+ // certificate, that the delegated credential is valid for. If zero, then 24
+ // hours is assumed.
+ lifetime time.Duration
+ // expectedAlgo is the signature scheme that should be used with this
+ // delegated credential. If zero, ECDSA with P-256 is assumed.
+ expectedAlgo signatureAlgorithm
+ // tlsVersion is the version of TLS that should be used with this delegated
+ // credential. If zero, TLS 1.3 is assumed.
+ tlsVersion uint16
+ // algo is the signature algorithm that the delegated credential itself is
+ // signed with. Cannot be zero.
+ algo signatureAlgorithm
+}
+
+func loadRSAPrivateKey(filename string) (priv *rsa.PrivateKey, privPKCS8 []byte, err error) {
+ pemPath := path.Join(*resourceDir, filename)
+ pemBytes, err := ioutil.ReadFile(pemPath)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return nil, nil, fmt.Errorf("no PEM block found in %q", pemPath)
+ }
+ privPKCS8 = block.Bytes
+
+ parsed, err := x509.ParsePKCS8PrivateKey(privPKCS8)
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to parse PKCS#8 key from %q", pemPath)
+ }
+
+ priv, ok := parsed.(*rsa.PrivateKey)
+ if !ok {
+ return nil, nil, fmt.Errorf("found %T in %q rather than an RSA private key", parsed, pemPath)
+ }
+
+ return priv, privPKCS8, nil
+}
+
+func createDelegatedCredential(config delegatedCredentialConfig, parentDER []byte, parentPriv crypto.PrivateKey) (dc, privPKCS8 []uint8, err error) {
+ expectedAlgo := config.expectedAlgo
+ if expectedAlgo == signatureAlgorithm(0) {
+ expectedAlgo = signatureECDSAWithP256AndSHA256
+ }
+
+ var pub crypto.PublicKey
+
+ switch expectedAlgo {
+ case signatureRSAPKCS1WithMD5, signatureRSAPKCS1WithSHA1, signatureRSAPKCS1WithSHA256, signatureRSAPKCS1WithSHA384, signatureRSAPKCS1WithSHA512, signatureRSAPSSWithSHA256, signatureRSAPSSWithSHA384, signatureRSAPSSWithSHA512:
+ // RSA keys are expensive to generate so load from disk instead.
+ var priv *rsa.PrivateKey
+ if priv, privPKCS8, err = loadRSAPrivateKey(rsaKeyFile); err != nil {
+ return nil, nil, err
+ }
+
+ pub = &priv.PublicKey
+
+ case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256, signatureECDSAWithP384AndSHA384, signatureECDSAWithP521AndSHA512:
+ var curve elliptic.Curve
+ switch expectedAlgo {
+ case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256:
+ curve = elliptic.P256()
+ case signatureECDSAWithP384AndSHA384:
+ curve = elliptic.P384()
+ case signatureECDSAWithP521AndSHA512:
+ curve = elliptic.P521()
+ default:
+ panic("internal error")
+ }
+
+ priv, err := ecdsa.GenerateKey(curve, rand.Reader)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if privPKCS8, err = x509.MarshalPKCS8PrivateKey(priv); err != nil {
+ return nil, nil, err
+ }
+
+ pub = &priv.PublicKey
+
+ default:
+ return nil, nil, fmt.Errorf("unsupported expected signature algorithm: %x", expectedAlgo)
+ }
+
+ lifetime := config.lifetime
+ if lifetime == 0 {
+ lifetime = 24 * time.Hour
+ }
+ lifetimeSecs := int64(lifetime.Seconds())
+ if lifetimeSecs > 1<<32 {
+ return nil, nil, fmt.Errorf("lifetime %s is too long to be expressed", lifetime)
+ }
+ tlsVersion := config.tlsVersion
+ if tlsVersion == 0 {
+ tlsVersion = VersionTLS13
+ }
+
+ if tlsVersion < VersionTLS13 {
+ return nil, nil, fmt.Errorf("delegated credentials require TLS 1.3")
+ }
+
+ // https://tools.ietf.org/html/draft-ietf-tls-subcerts-03#section-3
+ dc = append(dc, byte(lifetimeSecs>>24), byte(lifetimeSecs>>16), byte(lifetimeSecs>>8), byte(lifetimeSecs))
+ dc = append(dc, byte(expectedAlgo>>8), byte(expectedAlgo))
+
+ pubBytes, err := x509.MarshalPKIXPublicKey(pub)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ dc = append(dc, byte(len(pubBytes)>>16), byte(len(pubBytes)>>8), byte(len(pubBytes)))
+ dc = append(dc, pubBytes...)
+
+ var dummyConfig Config
+ parentSigner, err := getSigner(tlsVersion, parentPriv, &dummyConfig, config.algo, false /* not for verification */)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ parentSignature, err := parentSigner.signMessage(parentPriv, &dummyConfig, delegatedCredentialSignedMessage(dc, config.algo, parentDER))
+ if err != nil {
+ return nil, nil, err
+ }
+
+ dc = append(dc, byte(config.algo>>8), byte(config.algo))
+ dc = append(dc, byte(len(parentSignature)>>8), byte(len(parentSignature)))
+ dc = append(dc, parentSignature...)
+
+ return dc, privPKCS8, nil
+}
+
func getRunnerCertificate(t testCert) Certificate {
for _, cert := range testCerts {
if cert.id == t {
@@ -473,6 +612,11 @@
sendKeyUpdates int
// keyUpdateRequest is the KeyUpdateRequest value to send in KeyUpdate messages.
keyUpdateRequest byte
+ // expectUnsolicitedKeyUpdate makes the test expect a one or more KeyUpdate
+ // messages while reading data from the shim. Don't use this in combination
+ // with any of the fields that send a KeyUpdate otherwise any received
+ // KeyUpdate might not be as unsolicited as expected.
+ expectUnsolicitedKeyUpdate bool
// expectMessageDropped, if true, means the test message is expected to
// be dropped by the client rather than echoed back.
expectMessageDropped bool
@@ -484,10 +628,6 @@
// resumeShimPrefix is the prefix that the shim will send to the server on a
// resumption.
resumeShimPrefix string
- // tls13Variant, if non-zero, causes both runner and shim to be
- // configured with the specified TLS 1.3 variant. This is a convenience
- // option for configuring both concurrently.
- tls13Variant int
// expectedQUICTransportParams contains the QUIC transport
// parameters that are expected to be sent by the peer.
expectedQUICTransportParams []byte
@@ -567,9 +707,6 @@
if *deterministic {
config.Time = func() time.Time { return time.Unix(1234, 1234) }
}
- if test.tls13Variant != 0 {
- config.TLS13Variant = test.tls13Variant
- }
conn = &timeoutConn{conn, *idleTimeout}
@@ -951,6 +1088,10 @@
return fmt.Errorf("bad reply contents at byte %d; got %q and wanted %q", i, buf, testMessage)
}
}
+
+ if seen := tlsConn.keyUpdateSeen; seen != test.expectUnsolicitedKeyUpdate {
+ return fmt.Errorf("keyUpdateSeen (%t) != expectUnsolicitedKeyUpdate", seen)
+ }
}
return nil
@@ -1063,20 +1204,6 @@
if test.config.MaxVersion == 0 && test.config.MinVersion == 0 && test.expectedVersion == 0 {
panic(fmt.Sprintf("The name of test %q suggests that it's version specific, but min/max version in the Config is %x/%x. One of them should probably be %x", test.name, test.config.MinVersion, test.config.MaxVersion, ver.version))
}
-
- if ver.tls13Variant != 0 {
- var foundFlag bool
- for _, flag := range test.flags {
- if flag == "-tls13-variant" {
- foundFlag = true
- break
- }
- }
- if !foundFlag && test.config.TLS13Variant != ver.tls13Variant && test.tls13Variant != ver.tls13Variant {
- panic(fmt.Sprintf("The name of test %q suggests that uses an experimental TLS 1.3 variant, but neither the shim nor the runner configures it", test.name))
- }
- }
-
}
listener, err := net.ListenTCP("tcp", &net.TCPAddr{IP: net.IPv6loopback})
@@ -1165,10 +1292,6 @@
flags = append(flags, "-tls-unique")
}
- if test.tls13Variant != 0 {
- flags = append(flags, "-tls13-variant", strconv.Itoa(test.tls13Variant))
- }
-
flags = append(flags, "-handshaker-path", *handshakerPath)
var transcriptPrefix string
@@ -1376,8 +1499,7 @@
// versionWire, if non-zero, is the wire representation of the
// version. Otherwise the wire version is the protocol version or
// versionDTLS.
- versionWire uint16
- tls13Variant int
+ versionWire uint16
}
func (vers tlsVersion) shimFlag(protocol protocol) string {
@@ -1420,25 +1542,10 @@
versionDTLS: VersionDTLS12,
},
{
- name: "TLS13",
- version: VersionTLS13,
- excludeFlag: "-no-tls13",
- versionWire: VersionTLS13,
- tls13Variant: TLS13RFC,
- },
- {
- name: "TLS13Draft23",
- version: VersionTLS13,
- excludeFlag: "-no-tls13",
- versionWire: tls13Draft23Version,
- tls13Variant: TLS13Draft23,
- },
- {
- name: "TLS13Draft28",
- version: VersionTLS13,
- excludeFlag: "-no-tls13",
- versionWire: tls13Draft28Version,
- tls13Variant: TLS13Draft28,
+ name: "TLS13",
+ version: VersionTLS13,
+ excludeFlag: "-no-tls13",
+ versionWire: VersionTLS13,
},
}
@@ -1456,23 +1563,6 @@
return ret
}
-func allShimVersions(protocol protocol) []tlsVersion {
- if protocol == dtls {
- return allVersions(protocol)
- }
- tls13Default := tlsVersion{
- name: "TLS13All",
- version: VersionTLS13,
- excludeFlag: "-no-tls13",
- versionWire: 0,
- tls13Variant: TLS13All,
- }
-
- var shimVersions []tlsVersion
- shimVersions = append(shimVersions, allVersions(protocol)...)
- return append(shimVersions, tls13Default)
-}
-
type testCipherSuite struct {
name string
id uint16
@@ -2826,7 +2916,7 @@
expectedError: ":WRONG_VERSION_NUMBER:",
},
{
- name: "KeyUpdate-Client",
+ name: "KeyUpdate-ToClient",
config: Config{
MaxVersion: VersionTLS13,
},
@@ -2835,7 +2925,7 @@
},
{
testType: serverTest,
- name: "KeyUpdate-Server",
+ name: "KeyUpdate-ToServer",
config: Config{
MaxVersion: VersionTLS13,
},
@@ -2843,6 +2933,23 @@
keyUpdateRequest: keyUpdateNotRequested,
},
{
+ name: "KeyUpdate-FromClient",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ expectUnsolicitedKeyUpdate: true,
+ flags: []string{"-key-update"},
+ },
+ {
+ testType: serverTest,
+ name: "KeyUpdate-FromServer",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ expectUnsolicitedKeyUpdate: true,
+ flags: []string{"-key-update"},
+ },
+ {
name: "KeyUpdate-InvalidRequestMode",
config: Config{
MaxVersion: VersionTLS13,
@@ -2959,20 +3066,19 @@
},
{
testType: clientTest,
- name: "TLS13Draft23-InvalidCompressionMethod",
+ name: "TLS13-InvalidCompressionMethod",
config: Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendCompressionMethod: 1,
},
},
- tls13Variant: TLS13Draft23,
shouldFail: true,
expectedError: ":DECODE_ERROR:",
},
{
testType: clientTest,
- name: "TLS13Draft23-HRR-InvalidCompressionMethod",
+ name: "TLS13-HRR-InvalidCompressionMethod",
config: Config{
MaxVersion: VersionTLS13,
CurvePreferences: []CurveID{CurveP384},
@@ -2980,7 +3086,6 @@
SendCompressionMethod: 1,
},
},
- tls13Variant: TLS13Draft23,
shouldFail: true,
expectedError: ":DECODE_ERROR:",
expectedLocalError: "remote error: error decoding message",
@@ -3069,8 +3174,7 @@
ExpectPackedEncryptedHandshake: 512,
},
},
- tls13Variant: TLS13Draft28,
- messageLen: 1024,
+ messageLen: 1024,
flags: []string{
"-max-send-fragment", "512",
"-read-size", "1024",
@@ -3098,30 +3202,15 @@
expectedLocalError: "local error: record overflow",
},
{
- // Test that handshake data is not packed in TLS 1.3
- // draft-23.
+ // Test that handshake data is tightly packed in TLS 1.3.
testType: serverTest,
- name: "ForbidHandshakePacking-TLS13Draft23",
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ForbidHandshakePacking: true,
- },
- },
- tls13Variant: TLS13Draft23,
- },
- {
- // Test that handshake data is tightly packed in TLS 1.3
- // draft-28.
- testType: serverTest,
- name: "PackedEncryptedHandshake-TLS13Draft28",
+ name: "PackedEncryptedHandshake-TLS13",
config: Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
ExpectPackedEncryptedHandshake: 16384,
},
},
- tls13Variant: TLS13Draft28,
},
{
// Test that DTLS can handle multiple application data
@@ -3280,7 +3369,6 @@
AdvertiseAllConfiguredCiphers: true,
},
},
- tls13Variant: ver.tls13Variant,
certFile: certFile,
keyFile: keyFile,
flags: flags,
@@ -3306,7 +3394,6 @@
SendCipherSuite: sendCipherSuite,
},
},
- tls13Variant: ver.tls13Variant,
flags: flags,
resumeSession: true,
shouldFail: shouldFail,
@@ -3330,9 +3417,8 @@
PreSharedKey: []byte(psk),
PreSharedKeyIdentity: pskIdentity,
},
- tls13Variant: ver.tls13Variant,
- flags: flags,
- messageLen: maxPlaintext,
+ flags: flags,
+ messageLen: maxPlaintext,
})
// Test bad records for all ciphers. Bad records are fatal in TLS
@@ -3354,7 +3440,6 @@
PreSharedKey: []byte(psk),
PreSharedKeyIdentity: pskIdentity,
},
- tls13Variant: ver.tls13Variant,
flags: flags,
damageFirstWrite: true,
messageLen: maxPlaintext,
@@ -3828,7 +3913,6 @@
ClientAuth: RequireAnyClientCert,
ClientCAs: certPool,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
"-key-file", path.Join(*resourceDir, rsaKeyFile),
@@ -3842,8 +3926,7 @@
MaxVersion: ver.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: ver.tls13Variant,
- flags: []string{"-require-any-client-certificate"},
+ flags: []string{"-require-any-client-certificate"},
})
testCases = append(testCases, testCase{
testType: serverTest,
@@ -3853,8 +3936,7 @@
MaxVersion: ver.version,
Certificates: []Certificate{ecdsaP256Certificate},
},
- tls13Variant: ver.tls13Variant,
- flags: []string{"-require-any-client-certificate"},
+ flags: []string{"-require-any-client-certificate"},
})
testCases = append(testCases, testCase{
testType: clientTest,
@@ -3865,7 +3947,6 @@
ClientAuth: RequireAnyClientCert,
ClientCAs: certPool,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
@@ -3879,7 +3960,6 @@
MaxVersion: ver.version,
ClientAuth: RequireAnyClientCert,
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedLocalError: "client didn't provide a certificate",
})
@@ -3893,7 +3973,6 @@
MinVersion: ver.version,
MaxVersion: ver.version,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-expect-verify-result",
},
@@ -3909,7 +3988,6 @@
MinVersion: ver.version,
MaxVersion: ver.version,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-expect-verify-result",
"-verify-peer",
@@ -3931,7 +4009,6 @@
MaxVersion: ver.version,
},
flags: []string{"-require-any-client-certificate"},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
expectedLocalError: certificateRequired,
@@ -3949,7 +4026,6 @@
},
// Setting SSL_VERIFY_PEER allows anonymous clients.
flags: []string{"-verify-peer"},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":UNEXPECTED_MESSAGE:",
})
@@ -3965,7 +4041,6 @@
"-enable-channel-id",
"-verify-peer-if-no-obc",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
expectedLocalError: certificateRequired,
@@ -3980,7 +4055,6 @@
ChannelID: channelIDKey,
},
expectChannelID: true,
- tls13Variant: ver.tls13Variant,
flags: []string{
"-enable-channel-id",
"-verify-peer-if-no-obc",
@@ -3998,7 +4072,6 @@
ExpectCertificateReqNames: caNames,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-require-any-client-certificate",
"-use-client-ca-list", encodeDERValues(caNames),
@@ -4015,7 +4088,6 @@
ClientAuth: RequireAnyClientCert,
ClientCAs: certPool,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
"-key-file", path.Join(*resourceDir, rsaKeyFile),
@@ -4081,7 +4153,7 @@
// Test that an empty client CA list doesn't send a CA extension.
testCases = append(testCases, testCase{
testType: serverTest,
- name: "TLS13Draft23-Empty-Client-CA-List",
+ name: "TLS13-Empty-Client-CA-List",
config: Config{
MaxVersion: VersionTLS13,
Certificates: []Certificate{rsaCertificate},
@@ -4089,7 +4161,6 @@
ExpectNoCertificateAuthoritiesExtension: true,
},
},
- tls13Variant: TLS13Draft23,
flags: []string{
"-require-any-client-certificate",
"-use-client-ca-list", "<EMPTY>",
@@ -4134,8 +4205,7 @@
RequireExtendedMasterSecret: with,
},
},
- tls13Variant: ver.tls13Variant,
- flags: flags,
+ flags: flags,
})
}
}
@@ -4442,37 +4512,6 @@
})
tests = append(tests, testCase{
- name: "TLS13Draft23-HelloRetryRequest-Client",
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- // P-384 requires a HelloRetryRequest against BoringSSL's default
- // configuration. Assert this with ExpectMissingKeyShare.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- ExpectMissingKeyShare: true,
- },
- },
- tls13Variant: TLS13Draft23,
- // Cover HelloRetryRequest during an ECDHE-PSK resumption.
- resumeSession: true,
- })
-
- tests = append(tests, testCase{
- testType: serverTest,
- name: "TLS13Draft23-HelloRetryRequest-Server",
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- // Require a HelloRetryRequest for every curve.
- DefaultCurves: []CurveID{},
- },
- tls13Variant: TLS13Draft23,
- // Cover HelloRetryRequest during an ECDHE-PSK resumption.
- resumeSession: true,
- })
-
- tests = append(tests, testCase{
testType: clientTest,
name: "TLS13-EarlyData-TooMuchData-Client",
config: Config{
@@ -4829,7 +4868,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
flags: []string{
"-enable-ocsp-stapling",
"-expect-ocsp-response",
@@ -4844,7 +4882,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
expectedOCSPResponse: testOCSPResponse,
flags: []string{
"-ocsp-response",
@@ -4862,7 +4899,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: vers.tls13Variant,
flags: []string{
"-enable-ocsp-stapling",
"-use-ocsp-callback",
@@ -4881,7 +4917,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: vers.tls13Variant,
flags: []string{
"-enable-ocsp-stapling",
"-use-ocsp-callback",
@@ -4902,7 +4937,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{certNoStaple},
},
- tls13Variant: vers.tls13Variant,
flags: []string{
"-enable-ocsp-stapling",
"-use-ocsp-callback",
@@ -4921,7 +4955,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
expectedOCSPResponse: testOCSPResponse,
flags: []string{
"-use-ocsp-callback",
@@ -4941,7 +4974,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
expectedOCSPResponse: []byte{},
flags: []string{
"-use-ocsp-callback",
@@ -4959,7 +4991,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
flags: []string{
"-use-ocsp-callback",
"-fail-ocsp-callback",
@@ -5002,7 +5033,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: vers.tls13Variant,
flags: append([]string{"-expect-verify-result"}, flags...),
resumeSession: true,
})
@@ -5013,7 +5043,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: vers.tls13Variant,
flags: append([]string{"-verify-fail"}, flags...),
shouldFail: true,
expectedError: ":CERTIFICATE_VERIFY_FAILED:",
@@ -5026,7 +5055,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: vers.tls13Variant,
flags: append([]string{"-on-resume-verify-fail"}, flags...),
resumeSession: true,
})
@@ -5038,7 +5066,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: vers.tls13Variant,
flags: append([]string{
"-on-resume-verify-fail",
"-reverify-on-resume",
@@ -5054,7 +5081,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: vers.tls13Variant,
flags: append([]string{
"-reverify-on-resume",
}, flags...),
@@ -5073,7 +5099,6 @@
MaxEarlyDataSize: 16384,
SessionTicketsDisabled: true,
},
- tls13Variant: vers.tls13Variant,
resumeSession: true,
expectResumeRejected: true,
flags: append([]string{
@@ -5100,7 +5125,6 @@
AlwaysRejectEarlyData: true,
},
},
- tls13Variant: vers.tls13Variant,
resumeSession: true,
expectResumeRejected: false,
flags: append([]string{
@@ -5123,7 +5147,6 @@
MaxEarlyDataSize: 16384,
SessionTicketsDisabled: true,
},
- tls13Variant: vers.tls13Variant,
resumeSession: true,
expectResumeRejected: true,
shouldFail: true,
@@ -5153,7 +5176,6 @@
AlwaysRejectEarlyData: true,
},
},
- tls13Variant: vers.tls13Variant,
resumeSession: true,
expectResumeRejected: false,
shouldFail: true,
@@ -5182,7 +5204,6 @@
ExpectEarlyData: [][]byte{[]byte("hello")},
},
},
- tls13Variant: vers.tls13Variant,
resumeSession: true,
expectResumeRejected: false,
flags: append([]string{
@@ -5206,7 +5227,6 @@
ExpectEarlyData: [][]byte{[]byte("hello")},
},
},
- tls13Variant: vers.tls13Variant,
resumeSession: true,
shouldFail: true,
expectedError: ":CERTIFICATE_VERIFY_FAILED:",
@@ -5232,7 +5252,6 @@
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: vers.tls13Variant,
flags: []string{
"-verify-fail",
"-expect-verify-result",
@@ -5404,7 +5423,6 @@
MaxVersion: ver.version,
RequestChannelID: true,
},
- tls13Variant: ver.tls13Variant,
flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
resumeSession: true,
expectChannelID: true,
@@ -5418,7 +5436,6 @@
MaxVersion: ver.version,
ChannelID: channelIDKey,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-expect-channel-id",
base64.StdEncoding.EncodeToString(channelIDBytes),
@@ -5437,7 +5454,6 @@
InvalidChannelIDSignature: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{"-enable-channel-id"},
shouldFail: true,
expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:",
@@ -5759,7 +5775,7 @@
func addVersionNegotiationTests() {
for _, protocol := range []protocol{tls, dtls} {
- for _, shimVers := range allShimVersions(protocol) {
+ for _, shimVers := range allVersions(protocol) {
// Assemble flags to disable all newer versions on the shim.
var flags []string
for _, vers := range allVersions(protocol) {
@@ -5770,11 +5786,6 @@
flags2 := []string{"-max-version", shimVers.shimFlag(protocol)}
- if shimVers.tls13Variant != 0 {
- flags = append(flags, "-tls13-variant", strconv.Itoa(shimVers.tls13Variant))
- flags2 = append(flags2, "-tls13-variant", strconv.Itoa(shimVers.tls13Variant))
- }
-
// Test configuring the runner's maximum version.
for _, runnerVers := range allVersions(protocol) {
expectedVersion := shimVers.version
@@ -5782,12 +5793,6 @@
expectedVersion = runnerVers.version
}
- if expectedVersion == VersionTLS13 && runnerVers.tls13Variant != shimVers.tls13Variant {
- if shimVers.tls13Variant != TLS13All {
- expectedVersion = VersionTLS12
- }
- }
-
suffix := shimVers.name + "-" + runnerVers.name
if protocol == dtls {
suffix += "-DTLS"
@@ -5810,8 +5815,7 @@
testType: clientTest,
name: "VersionNegotiation-Client-" + suffix,
config: Config{
- MaxVersion: runnerVers.version,
- TLS13Variant: runnerVers.tls13Variant,
+ MaxVersion: runnerVers.version,
Bugs: ProtocolBugs{
ExpectInitialRecordVersion: clientVers,
},
@@ -5824,8 +5828,7 @@
testType: clientTest,
name: "VersionNegotiation-Client2-" + suffix,
config: Config{
- MaxVersion: runnerVers.version,
- TLS13Variant: runnerVers.tls13Variant,
+ MaxVersion: runnerVers.version,
Bugs: ProtocolBugs{
ExpectInitialRecordVersion: clientVers,
},
@@ -5839,8 +5842,7 @@
testType: serverTest,
name: "VersionNegotiation-Server-" + suffix,
config: Config{
- MaxVersion: runnerVers.version,
- TLS13Variant: runnerVers.tls13Variant,
+ MaxVersion: runnerVers.version,
Bugs: ProtocolBugs{
ExpectInitialRecordVersion: serverVers,
},
@@ -5853,8 +5855,7 @@
testType: serverTest,
name: "VersionNegotiation-Server2-" + suffix,
config: Config{
- MaxVersion: runnerVers.version,
- TLS13Variant: runnerVers.tls13Variant,
+ MaxVersion: runnerVers.version,
Bugs: ProtocolBugs{
ExpectInitialRecordVersion: serverVers,
},
@@ -5883,14 +5884,12 @@
testType: serverTest,
name: "VersionNegotiationExtension-" + suffix,
config: Config{
- TLS13Variant: vers.tls13Variant,
Bugs: ProtocolBugs{
SendSupportedVersions: []uint16{0x1111, vers.wire(protocol), 0x2222},
IgnoreTLS13DowngradeRandom: true,
},
},
expectedVersion: vers.version,
- flags: []string{"-tls13-variant", strconv.Itoa(vers.tls13Variant)},
})
}
}
@@ -6114,7 +6113,6 @@
NegotiateVersion: test.version,
},
},
- tls13Variant: TLS13RFC,
expectedVersion: test.version,
shouldFail: true,
expectedError: ":TLS13_DOWNGRADE:",
@@ -6130,7 +6128,6 @@
NegotiateVersion: test.version,
},
},
- tls13Variant: TLS13RFC,
expectedVersion: test.version,
flags: []string{
"-ignore-tls13-downgrade",
@@ -6147,37 +6144,12 @@
SendSupportedVersions: []uint16{test.version},
},
},
- tls13Variant: TLS13RFC,
expectedVersion: test.version,
shouldFail: true,
expectedLocalError: test.clientShimError,
})
}
- // Test that the draft TLS 1.3 variants don't trigger the downgrade logic.
- testCases = append(testCases, testCase{
- name: "Downgrade-Draft-Client",
- config: Config{
- Bugs: ProtocolBugs{
- NegotiateVersion: VersionTLS12,
- SendTLS13DowngradeRandom: true,
- },
- },
- tls13Variant: TLS13Draft28,
- expectedVersion: VersionTLS12,
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Downgrade-Draft-Server",
- config: Config{
- Bugs: ProtocolBugs{
- CheckTLS13DowngradeRandom: true,
- },
- },
- tls13Variant: TLS13Draft28,
- expectedVersion: VersionTLS13,
- })
-
// Test that False Start is disabled when the downgrade logic triggers.
testCases = append(testCases, testCase{
name: "Downgrade-FalseStart",
@@ -6189,7 +6161,6 @@
AlertBeforeFalseStartTest: alertAccessDenied,
},
},
- tls13Variant: TLS13RFC,
expectedVersion: VersionTLS12,
flags: []string{
"-false-start",
@@ -6202,29 +6173,6 @@
expectedLocalError: "tls: peer did not false start: EOF",
})
- // Test that draft TLS 1.3 versions do not trigger disabling False Start.
- testCases = append(testCases, testCase{
- name: "Downgrade-FalseStart-Draft",
- config: Config{
- MaxVersion: VersionTLS13,
- TLS13Variant: TLS13RFC,
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- },
- },
- expectedVersion: VersionTLS12,
- flags: []string{
- "-false-start",
- "-advertise-alpn", "\x03foo",
- "-expect-alpn", "foo",
- "-ignore-tls13-downgrade",
- "-tls13-variant", strconv.Itoa(TLS13Draft28),
- "-max-version", strconv.Itoa(VersionTLS13),
- },
- shimWritesFirst: true,
- })
-
// SSL 3.0 support has been removed. Test that the shim does not
// support it.
testCases = append(testCases, testCase{
@@ -6279,22 +6227,7 @@
flags2 := []string{"-min-version", shimVers.shimFlag(protocol)}
- if shimVers.tls13Variant != 0 {
- flags = append(flags, "-tls13-variant", strconv.Itoa(shimVers.tls13Variant))
- flags2 = append(flags2, "-tls13-variant", strconv.Itoa(shimVers.tls13Variant))
- }
-
for _, runnerVers := range allVersions(protocol) {
- // Different TLS 1.3 variants are incompatible with each other and don't
- // produce consistent minimum versions.
- //
- // TODO(davidben): Fold these tests (the main value is in the
- // NegotiateVersion bug) into addVersionNegotiationTests and test based
- // on intended shim behavior, not the shim + runner combination.
- if shimVers.tls13Variant != runnerVers.tls13Variant {
- continue
- }
-
suffix := shimVers.name + "-" + runnerVers.name
if protocol == dtls {
suffix += "-DTLS"
@@ -6316,8 +6249,7 @@
testType: clientTest,
name: "MinimumVersion-Client-" + suffix,
config: Config{
- MaxVersion: runnerVers.version,
- TLS13Variant: runnerVers.tls13Variant,
+ MaxVersion: runnerVers.version,
Bugs: ProtocolBugs{
// Ensure the server does not decline to
// select a version (versions extension) or
@@ -6337,8 +6269,7 @@
testType: clientTest,
name: "MinimumVersion-Client2-" + suffix,
config: Config{
- MaxVersion: runnerVers.version,
- TLS13Variant: runnerVers.tls13Variant,
+ MaxVersion: runnerVers.version,
Bugs: ProtocolBugs{
// Ensure the server does not decline to
// select a version (versions extension) or
@@ -6359,8 +6290,7 @@
testType: serverTest,
name: "MinimumVersion-Server-" + suffix,
config: Config{
- MaxVersion: runnerVers.version,
- TLS13Variant: runnerVers.tls13Variant,
+ MaxVersion: runnerVers.version,
},
flags: flags,
expectedVersion: expectedVersion,
@@ -6373,8 +6303,7 @@
testType: serverTest,
name: "MinimumVersion-Server2-" + suffix,
config: Config{
- MaxVersion: runnerVers.version,
- TLS13Variant: runnerVers.tls13Variant,
+ MaxVersion: runnerVers.version,
},
flags: flags2,
expectedVersion: expectedVersion,
@@ -6404,7 +6333,6 @@
DuplicateExtension: true,
},
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedLocalError: "remote error: error decoding message",
})
@@ -6417,7 +6345,6 @@
DuplicateExtension: true,
},
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedLocalError: "remote error: error decoding message",
})
@@ -6432,8 +6359,7 @@
ExpectServerName: "example.com",
},
},
- tls13Variant: ver.tls13Variant,
- flags: []string{"-host-name", "example.com"},
+ flags: []string{"-host-name", "example.com"},
})
testCases = append(testCases, testCase{
testType: clientTest,
@@ -6445,7 +6371,6 @@
},
},
flags: []string{"-host-name", "example.com"},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedLocalError: "tls: unexpected server name",
})
@@ -6458,7 +6383,6 @@
ExpectServerName: "missing.com",
},
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedLocalError: "tls: unexpected server name",
})
@@ -6471,7 +6395,6 @@
SendServerNameAck: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{"-host-name", "example.com"},
resumeSession: true,
})
@@ -6484,7 +6407,6 @@
SendServerNameAck: true,
},
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":UNEXPECTED_EXTENSION:",
expectedLocalError: "remote error: unsupported extension",
@@ -6496,7 +6418,6 @@
MaxVersion: ver.version,
ServerName: "example.com",
},
- tls13Variant: ver.tls13Variant,
flags: []string{"-expect-server-name", "example.com"},
resumeSession: true,
})
@@ -6513,7 +6434,6 @@
"-advertise-alpn", "\x03foo\x03bar\x03baz",
"-expect-alpn", "foo",
},
- tls13Variant: ver.tls13Variant,
expectedNextProto: "foo",
expectedNextProtoType: alpn,
resumeSession: true,
@@ -6530,7 +6450,6 @@
flags: []string{
"-advertise-alpn", "\x03foo\x03bar",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":INVALID_ALPN_PROTOCOL:",
expectedLocalError: "remote error: illegal parameter",
@@ -6549,7 +6468,6 @@
"-allow-unknown-alpn-protos",
"-expect-alpn", "baz",
},
- tls13Variant: ver.tls13Variant,
})
testCases = append(testCases, testCase{
testType: serverTest,
@@ -6562,7 +6480,6 @@
"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
"-select-alpn", "foo",
},
- tls13Variant: ver.tls13Variant,
expectedNextProto: "foo",
expectedNextProtoType: alpn,
resumeSession: true,
@@ -6575,7 +6492,6 @@
NextProtos: []string{"foo", "bar", "baz"},
},
flags: []string{"-decline-alpn"},
- tls13Variant: ver.tls13Variant,
expectNoNextProto: true,
resumeSession: true,
})
@@ -6592,7 +6508,6 @@
"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
"-select-empty-alpn",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedLocalError: "remote error: internal error",
expectedError: ":INVALID_ALPN_PROTOCOL:",
@@ -6614,7 +6529,6 @@
"-select-alpn", "foo",
"-async",
},
- tls13Variant: ver.tls13Variant,
expectedNextProto: "foo",
expectedNextProtoType: alpn,
resumeSession: true,
@@ -6636,7 +6550,6 @@
flags: []string{
"-advertise-alpn", "\x03foo",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":PARSE_TLSEXT:",
})
@@ -6652,7 +6565,6 @@
flags: []string{
"-select-alpn", "foo",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":PARSE_TLSEXT:",
})
@@ -6672,7 +6584,6 @@
"-select-alpn", "foo",
"-advertise-npn", "\x03foo\x03bar\x03baz",
},
- tls13Variant: ver.tls13Variant,
expectedNextProto: "foo",
expectedNextProtoType: alpn,
resumeSession: true,
@@ -6692,7 +6603,6 @@
"-select-alpn", "foo",
"-advertise-npn", "\x03foo\x03bar\x03baz",
},
- tls13Variant: ver.tls13Variant,
expectedNextProto: "foo",
expectedNextProtoType: alpn,
resumeSession: true,
@@ -6712,7 +6622,6 @@
"-advertise-alpn", "\x03foo",
"-select-next-proto", "foo",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
})
@@ -6730,7 +6639,6 @@
"-advertise-alpn", "\x03foo",
"-select-next-proto", "foo",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
})
@@ -6752,7 +6660,6 @@
},
expectTokenBinding: true,
expectedTokenBindingParam: 2,
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -6770,7 +6677,6 @@
TokenBindingParams: []byte{3},
TokenBindingVersion: maxTokenBindingVersion,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -6786,7 +6692,6 @@
TokenBindingParams: []byte{0, 1, 2},
TokenBindingVersion: minTokenBindingVersion - 1,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -6804,7 +6709,6 @@
},
expectTokenBinding: true,
expectedTokenBindingParam: 2,
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -6822,7 +6726,6 @@
TokenBindingParams: []byte{},
TokenBindingVersion: maxTokenBindingVersion,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -6842,7 +6745,6 @@
},
expectTokenBinding: true,
expectedTokenBindingParam: 2,
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -6861,7 +6763,6 @@
TokenBindingVersion: maxTokenBindingVersion,
ExpectTokenBindingParams: []byte{0, 1, 2},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
@@ -6879,7 +6780,6 @@
TokenBindingParams: []byte{2},
TokenBindingVersion: maxTokenBindingVersion,
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":UNEXPECTED_EXTENSION:",
})
@@ -6900,7 +6800,6 @@
"-expected-token-binding-param",
"2",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":ERROR_PARSING_EXTENSION:",
})
@@ -6921,7 +6820,6 @@
"-expected-token-binding-param",
"2",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":ERROR_PARSING_EXTENSION:",
})
@@ -6942,7 +6840,6 @@
"-expected-token-binding-param",
"2",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":ERROR_PARSING_EXTENSION:",
})
@@ -6961,7 +6858,6 @@
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
},
- tls13Variant: ver.tls13Variant,
})
testCases = append(testCases, testCase{
testType: clientTest,
@@ -6980,7 +6876,6 @@
"-expected-token-binding-param",
"2",
},
- tls13Variant: ver.tls13Variant,
})
testCases = append(testCases, testCase{
testType: clientTest,
@@ -6997,7 +6892,6 @@
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{0, 1, 2}),
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: "ERROR_PARSING_EXTENSION",
})
@@ -7016,7 +6910,6 @@
NoExtendedMasterSecret: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -7037,7 +6930,6 @@
NoExtendedMasterSecret: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -7059,7 +6951,6 @@
NoRenegotiationInfo: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -7080,7 +6971,6 @@
NoRenegotiationInfo: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-token-binding-params",
base64.StdEncoding.EncodeToString([]byte{2, 1, 0}),
@@ -7101,7 +6991,6 @@
MaxEarlyDataSize: 16384,
},
resumeSession: true,
- tls13Variant: ver.tls13Variant,
flags: []string{
"-enable-early-data",
"-expect-ticket-supports-early-data",
@@ -7124,7 +7013,6 @@
resumeSession: true,
expectTokenBinding: true,
expectedTokenBindingParam: 2,
- tls13Variant: ver.tls13Variant,
flags: []string{
"-enable-early-data",
"-expect-ticket-supports-early-data",
@@ -7145,7 +7033,6 @@
MaxVersion: ver.version,
QUICTransportParams: []byte{1, 2},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{3, 4}),
@@ -7163,7 +7050,6 @@
MaxVersion: ver.version,
QUICTransportParams: []byte{1, 2},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{3, 4}),
@@ -7180,7 +7066,6 @@
MinVersion: ver.version,
MaxVersion: ver.version,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-max-version",
strconv.Itoa(int(ver.version)),
@@ -7196,7 +7081,6 @@
MaxVersion: ver.version,
QUICTransportParams: []byte{1, 2},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{3, 4}),
@@ -7212,7 +7096,6 @@
MaxVersion: ver.version,
QUICTransportParams: []byte{1, 2},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-expected-quic-transport-params",
base64.StdEncoding.EncodeToString([]byte{1, 2}),
@@ -7249,7 +7132,6 @@
},
},
},
- tls13Variant: ver.tls13Variant,
resumeSession: true,
expectResumeRejected: true,
})
@@ -7260,7 +7142,6 @@
config: Config{
MaxVersion: ver.version,
},
- tls13Variant: ver.tls13Variant,
resumeSession: true,
flags: []string{"-use-ticket-callback"},
})
@@ -7273,7 +7154,6 @@
ExpectNewTicket: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{"-use-ticket-callback", "-renew-ticket"},
resumeSession: true,
})
@@ -7293,7 +7173,6 @@
},
},
},
- tls13Variant: ver.tls13Variant,
resumeSession: true,
expectResumeRejected: true,
flags: []string{
@@ -7449,7 +7328,6 @@
"-expect-signed-cert-timestamps",
base64.StdEncoding.EncodeToString(testSCTList),
},
- tls13Variant: ver.tls13Variant,
resumeSession: true,
})
@@ -7472,7 +7350,6 @@
"-expect-signed-cert-timestamps",
base64.StdEncoding.EncodeToString(testSCTList),
},
- tls13Variant: ver.tls13Variant,
resumeSession: true,
})
@@ -7486,7 +7363,6 @@
"-signed-cert-timestamps",
base64.StdEncoding.EncodeToString(testSCTList),
},
- tls13Variant: ver.tls13Variant,
expectedSCTList: testSCTList,
resumeSession: true,
})
@@ -7505,7 +7381,6 @@
flags: []string{
"-enable-signed-cert-timestamps",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":ERROR_PARSING_EXTENSION:",
})
@@ -7524,7 +7399,6 @@
flags: []string{
"-enable-signed-cert-timestamps",
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":ERROR_PARSING_EXTENSION:",
})
@@ -7540,7 +7414,6 @@
NoSignedCertificateTimestamps: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-ocsp-response",
base64.StdEncoding.EncodeToString(testOCSPResponse),
@@ -7809,29 +7682,19 @@
suffix += "-DTLS"
}
- // We can't resume across TLS 1.3 variants and error out earlier in the
- // session resumption.
- if sessionVers.tls13Variant != resumeVers.tls13Variant {
- continue
- }
-
if sessionVers.version == resumeVers.version {
testCases = append(testCases, testCase{
protocol: protocol,
name: "Resume-Client" + suffix,
resumeSession: true,
config: Config{
- MaxVersion: sessionVers.version,
- TLS13Variant: sessionVers.tls13Variant,
+ MaxVersion: sessionVers.version,
Bugs: ProtocolBugs{
ExpectNoTLS13PSK: sessionVers.version < VersionTLS13,
},
},
expectedVersion: sessionVers.version,
expectedResumeVersion: resumeVers.version,
- flags: []string{
- "-tls13-variant", strconv.Itoa(sessionVers.tls13Variant),
- },
})
} else {
testCases = append(testCases, testCase{
@@ -7839,13 +7702,11 @@
name: "Resume-Client-Mismatch" + suffix,
resumeSession: true,
config: Config{
- MaxVersion: sessionVers.version,
- TLS13Variant: sessionVers.tls13Variant,
+ MaxVersion: sessionVers.version,
},
expectedVersion: sessionVers.version,
resumeConfig: &Config{
- MaxVersion: resumeVers.version,
- TLS13Variant: resumeVers.tls13Variant,
+ MaxVersion: resumeVers.version,
Bugs: ProtocolBugs{
AcceptAnySession: true,
},
@@ -7853,10 +7714,6 @@
expectedResumeVersion: resumeVers.version,
shouldFail: true,
expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
- flags: []string{
- "-on-initial-tls13-variant", strconv.Itoa(sessionVers.tls13Variant),
- "-on-resume-tls13-variant", strconv.Itoa(resumeVers.tls13Variant),
- },
})
}
@@ -7865,21 +7722,15 @@
name: "Resume-Client-NoResume" + suffix,
resumeSession: true,
config: Config{
- MaxVersion: sessionVers.version,
- TLS13Variant: sessionVers.tls13Variant,
+ MaxVersion: sessionVers.version,
},
expectedVersion: sessionVers.version,
resumeConfig: &Config{
- MaxVersion: resumeVers.version,
- TLS13Variant: resumeVers.tls13Variant,
+ MaxVersion: resumeVers.version,
},
newSessionsOnResume: true,
expectResumeRejected: true,
expectedResumeVersion: resumeVers.version,
- flags: []string{
- "-on-initial-tls13-variant", strconv.Itoa(sessionVers.tls13Variant),
- "-on-resume-tls13-variant", strconv.Itoa(resumeVers.tls13Variant),
- },
})
testCases = append(testCases, testCase{
@@ -7888,23 +7739,17 @@
name: "Resume-Server" + suffix,
resumeSession: true,
config: Config{
- MaxVersion: sessionVers.version,
- TLS13Variant: sessionVers.tls13Variant,
+ MaxVersion: sessionVers.version,
},
expectedVersion: sessionVers.version,
expectResumeRejected: sessionVers != resumeVers,
resumeConfig: &Config{
- MaxVersion: resumeVers.version,
- TLS13Variant: resumeVers.tls13Variant,
+ MaxVersion: resumeVers.version,
Bugs: ProtocolBugs{
SendBothTickets: true,
},
},
expectedResumeVersion: resumeVers.version,
- flags: []string{
- "-on-initial-tls13-variant", strconv.Itoa(sessionVers.tls13Variant),
- "-on-resume-tls13-variant", strconv.Itoa(resumeVers.tls13Variant),
- },
})
// Repeat the test using session IDs, rather than tickets.
@@ -8352,15 +8197,14 @@
},
})
testCases = append(testCases, testCase{
- name: "Renegotiate-Client-TLS13Draft23",
+ name: "Renegotiate-Client-TLS12",
config: Config{
MaxVersion: VersionTLS12,
Bugs: ProtocolBugs{
FailIfResumeOnRenego: true,
},
},
- tls13Variant: TLS13Draft23,
- renegotiate: 1,
+ renegotiate: 1,
// Test renegotiation after both an initial and resumption
// handshake.
resumeSession: true,
@@ -8970,7 +8814,6 @@
"-enable-all-curves",
"-enable-ed25519",
},
- tls13Variant: ver.tls13Variant,
shouldFail: shouldSignFail,
expectedError: signError,
expectedLocalError: signLocalError,
@@ -8993,7 +8836,6 @@
IgnorePeerSignatureAlgorithmPreferences: shouldVerifyFail,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-require-any-client-certificate",
"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)),
@@ -9020,7 +8862,6 @@
fakeSigAlg2,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
@@ -9049,7 +8890,6 @@
IgnorePeerSignatureAlgorithmPreferences: shouldVerifyFail,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)),
"-enable-all-curves",
@@ -9077,7 +8917,6 @@
InvalidSignature: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-require-any-client-certificate",
"-enable-all-curves",
@@ -9100,7 +8939,6 @@
InvalidSignature: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-enable-all-curves",
"-enable-ed25519",
@@ -9118,7 +8956,6 @@
ClientAuth: RequireAnyClientCert,
VerifySignatureAlgorithms: allAlgorithms,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
@@ -9137,7 +8974,6 @@
CipherSuites: signingCiphers,
VerifySignatureAlgorithms: allAlgorithms,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
@@ -9167,7 +9003,6 @@
signatureECDSAWithP256AndSHA256,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
"-key-file", path.Join(*resourceDir, rsaKeyFile),
@@ -9188,7 +9023,6 @@
signatureECDSAWithP256AndSHA256,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
"-key-file", path.Join(*resourceDir, rsaKeyFile),
@@ -10006,7 +9840,6 @@
ExpectRSAPSSSupport: expect,
},
},
- tls13Variant: ver.tls13Variant,
flags: flags,
shouldFail: shouldFail,
expectedLocalError: localError,
@@ -10025,7 +9858,6 @@
ExpectRSAPSSSupport: expect,
},
},
- tls13Variant: ver.tls13Variant,
flags: serverFlags,
shouldFail: shouldFail,
expectedLocalError: localError,
@@ -10253,7 +10085,6 @@
// Test the exporter in both initial and resumption
// handshakes.
resumeSession: true,
- tls13Variant: vers.tls13Variant,
exportKeyingMaterial: 1024,
exportLabel: "label",
exportContext: "context",
@@ -10264,7 +10095,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
exportKeyingMaterial: 1024,
})
testCases = append(testCases, testCase{
@@ -10272,7 +10102,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
exportKeyingMaterial: 1024,
useExportContext: true,
})
@@ -10281,7 +10110,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
exportKeyingMaterial: 1,
exportLabel: "label",
exportContext: "context",
@@ -10298,7 +10126,6 @@
MaxEarlyDataSize: 16384,
},
resumeSession: true,
- tls13Variant: vers.tls13Variant,
flags: []string{
"-enable-early-data",
"-expect-ticket-supports-early-data",
@@ -10330,7 +10157,6 @@
},
},
resumeSession: true,
- tls13Variant: vers.tls13Variant,
flags: []string{
"-enable-early-data",
"-expect-ticket-supports-early-data",
@@ -10355,7 +10181,6 @@
MaxEarlyDataSize: 16384,
},
resumeSession: true,
- tls13Variant: vers.tls13Variant,
exportEarlyKeyingMaterial: 1024,
exportLabel: "label",
exportContext: "context",
@@ -10376,7 +10201,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
flags: []string{"-export-early-keying-material", "1024"},
shouldFail: true,
expectedError: ":EARLY_DATA_NOT_IN_USE:",
@@ -10387,7 +10211,6 @@
MaxVersion: vers.version,
},
resumeSession: true,
- tls13Variant: vers.tls13Variant,
flags: []string{"-on-resume-export-early-keying-material", "1024"},
shouldFail: true,
expectedError: ":EARLY_DATA_NOT_IN_USE:",
@@ -10405,7 +10228,6 @@
},
},
resumeSession: true,
- tls13Variant: vers.tls13Variant,
flags: []string{
"-enable-early-data",
"-expect-ticket-supports-early-data",
@@ -10427,7 +10249,6 @@
ExpectEarlyDataAccepted: true,
},
},
- tls13Variant: vers.tls13Variant,
resumeSession: true,
exportKeyingMaterial: 1024,
exportLabel: "label",
@@ -10447,7 +10268,6 @@
ExpectEarlyDataAccepted: true,
},
},
- tls13Variant: vers.tls13Variant,
resumeSession: true,
exportEarlyKeyingMaterial: 1024,
exportLabel: "label",
@@ -10463,7 +10283,6 @@
config: Config{
MaxVersion: vers.version,
},
- tls13Variant: vers.tls13Variant,
flags: []string{"-export-early-keying-material", "1024"},
shouldFail: true,
expectedError: ":EARLY_DATA_NOT_IN_USE:",
@@ -10475,7 +10294,6 @@
MaxVersion: vers.version,
},
resumeSession: true,
- tls13Variant: vers.tls13Variant,
flags: []string{"-on-resume-export-early-keying-material", "1024"},
shouldFail: true,
expectedError: ":EARLY_DATA_NOT_IN_USE:",
@@ -10488,7 +10306,6 @@
MaxVersion: vers.version,
},
resumeSession: true,
- tls13Variant: vers.tls13Variant,
exportEarlyKeyingMaterial: 1024,
exportLabel: "label",
exportContext: "context",
@@ -10502,7 +10319,6 @@
MaxVersion: vers.version,
},
resumeSession: true,
- tls13Variant: vers.tls13Variant,
exportEarlyKeyingMaterial: 1024,
exportLabel: "label",
exportContext: "context",
@@ -10788,7 +10604,6 @@
},
CurvePreferences: []CurveID{curve.id},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-enable-all-curves",
"-expect-curve-id", strconv.Itoa(int(curve.id)),
@@ -10807,7 +10622,6 @@
},
CurvePreferences: []CurveID{curve.id},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-enable-all-curves",
"-expect-curve-id", strconv.Itoa(int(curve.id)),
@@ -10830,7 +10644,6 @@
SendCompressedCoordinates: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{"-enable-all-curves"},
shouldFail: true,
expectedError: ":BAD_ECPOINT:",
@@ -10850,7 +10663,6 @@
SendCompressedCoordinates: true,
},
},
- tls13Variant: ver.tls13Variant,
flags: []string{"-enable-all-curves"},
shouldFail: true,
expectedError: ":BAD_ECPOINT:",
@@ -11613,7 +11425,6 @@
},
},
resumeSession: useStatefulResumption,
- tls13Variant: ver.tls13Variant,
flags: []string{"-no-ticket"},
})
@@ -11625,7 +11436,6 @@
MinVersion: ver.version,
MaxVersion: ver.version,
},
- tls13Variant: ver.tls13Variant,
resumeSession: true,
expectResumeRejected: true,
// Set SSL_OP_NO_TICKET on the second connection, after the first
@@ -12255,7 +12065,7 @@
messageType: typeEndOfEarlyData,
test: testCase{
testType: serverTest,
- name: "TLS13Draft23-EndOfEarlyData",
+ name: "TLS13-EndOfEarlyData",
config: Config{
MaxVersion: VersionTLS13,
},
@@ -12266,7 +12076,6 @@
ExpectEarlyDataAccepted: true,
},
},
- tls13Variant: TLS13Draft23,
resumeSession: true,
flags: []string{"-enable-early-data"},
},
@@ -12345,1637 +12154,1539 @@
}
func addTLS13HandshakeTests() {
- for _, version := range allVersions(tls) {
- if version.version != VersionTLS13 {
- continue
- }
- name := version.name
- variant := version.tls13Variant
-
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "NegotiatePSKResumption-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- NegotiatePSKResumption: true,
- },
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "NegotiatePSKResumption-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ NegotiatePSKResumption: true,
},
- tls13Variant: variant,
- resumeSession: true,
- shouldFail: true,
- expectedError: ":MISSING_KEY_SHARE:",
- })
+ },
+ resumeSession: true,
+ shouldFail: true,
+ expectedError: ":MISSING_KEY_SHARE:",
+ })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "MissingKeyShare-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- MissingKeyShare: true,
- },
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "MissingKeyShare-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ MissingKeyShare: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":MISSING_KEY_SHARE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":MISSING_KEY_SHARE:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "MissingKeyShare-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- MissingKeyShare: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "MissingKeyShare-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ MissingKeyShare: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":MISSING_KEY_SHARE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":MISSING_KEY_SHARE:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "DuplicateKeyShares-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- DuplicateKeyShares: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "DuplicateKeyShares-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ DuplicateKeyShares: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DUPLICATE_KEY_SHARE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":DUPLICATE_KEY_SHARE:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 4,
},
- tls13Variant: variant,
- })
+ },
+ })
- // Test that enabling a TLS 1.3 variant does not interfere with
- // TLS 1.2 session ID resumption.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ResumeTLS12SessionID-" + name,
- config: Config{
- MaxVersion: VersionTLS12,
- SessionTicketsDisabled: true,
- },
- tls13Variant: variant,
- resumeSession: true,
- })
+ // Test that enabling TLS 1.3 does not interfere with TLS 1.2 session ID
+ // resumption.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ResumeTLS12SessionID-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ SessionTicketsDisabled: true,
+ },
+ resumeSession: true,
+ })
- // Test that the client correctly handles a TLS 1.3 ServerHello which echoes
- // a TLS 1.2 session ID.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TLS12SessionID-" + name,
- config: Config{
- MaxVersion: VersionTLS12,
- SessionTicketsDisabled: true,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
+ // Test that the client correctly handles a TLS 1.3 ServerHello which echoes
+ // a TLS 1.2 session ID.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS12SessionID-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ SessionTicketsDisabled: true,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ },
+ resumeSession: true,
+ expectResumeRejected: true,
+ })
+
+ // Test that the server correctly echoes back session IDs of
+ // various lengths. The first test additionally asserts that
+ // BoringSSL always sends the ChangeCipherSpec messages for
+ // compatibility mode, rather than negotiating it based on the
+ // ClientHello.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EmptySessionID-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: []byte{},
},
- tls13Variant: variant,
- resumeSession: true,
- expectResumeRejected: true,
- })
+ },
+ })
- // Test that the server correctly echoes back session IDs of
- // various lengths. The first test additionally asserts that
- // BoringSSL always sends the ChangeCipherSpec messages for
- // compatibility mode, rather than negotiating it based on the
- // ClientHello.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EmptySessionID-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendClientHelloSessionID: []byte{},
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ShortSessionID-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: make([]byte, 16),
},
- tls13Variant: variant,
- })
+ },
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ShortSessionID-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendClientHelloSessionID: make([]byte, 16),
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "FullSessionID-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: make([]byte, 32),
},
- tls13Variant: variant,
- })
+ },
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "FullSessionID-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendClientHelloSessionID: make([]byte, 32),
- },
+ // Test that the client sends a fake session ID in TLS 1.3.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13SessionID-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectClientHelloSessionID: true,
},
- tls13Variant: variant,
- })
+ },
+ })
- // Test that the client sends a fake session ID in TLS 1.3.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TLS13SessionID-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ExpectClientHelloSessionID: true,
- },
+ // Test that the client omits the fake session ID when the max version is TLS 1.2 and below.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS12NoSessionID-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectNoTLS12Session: true,
},
- tls13Variant: variant,
- })
+ },
+ flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+ })
- // Test that the client omits the fake session ID when the max version is TLS 1.2 and below.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "TLS12NoSessionID-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ExpectNoTLS12Session: true,
- },
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
},
- tls13Variant: variant,
- flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-accept-early-data",
+ "-on-resume-shim-writes-first",
+ },
+ })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-Reject-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ AlwaysRejectEarlyData: true,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-accept-early-data",
- "-on-resume-shim-writes-first",
- },
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-reject-early-data",
+ "-on-resume-shim-writes-first",
+ },
+ })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-Reject-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- AlwaysRejectEarlyData: true,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-reject-early-data",
- "-on-resume-shim-writes-first",
- },
- })
+ },
+ messageCount: 2,
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-accept-early-data",
+ },
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
- },
- },
- tls13Variant: variant,
- messageCount: 2,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-accept-early-data",
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-FirstTicket-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ UseFirstSessionTicket: true,
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
},
- })
+ },
+ messageCount: 2,
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-accept-early-data",
+ },
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-FirstTicket-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- UseFirstSessionTicket: true,
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
- },
- },
- tls13Variant: variant,
- messageCount: 2,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-accept-early-data",
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-OmitEarlyDataExtension-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 4,
+ OmitEarlyDataExtension: true,
},
- })
+ },
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-OmitEarlyDataExtension-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
- OmitEarlyDataExtension: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-TooMuchData-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 16384 + 1,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-TooMuchData-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 16384 + 1,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-Interleaved-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 4,
+ InterleaveEarlyData: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-Interleaved-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
- InterleaveEarlyData: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-EarlyDataInTLS12-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 4,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-EarlyDataInTLS12-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-HRR-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 4,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
- })
+ DefaultCurves: []CurveID{},
+ },
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-HRR-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
- },
- DefaultCurves: []CurveID{},
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-HRR-Interleaved-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 4,
+ InterleaveEarlyData: true,
},
- tls13Variant: variant,
- })
+ DefaultCurves: []CurveID{},
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-HRR-Interleaved-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 4,
- InterleaveEarlyData: true,
- },
- DefaultCurves: []CurveID{},
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-HRR-TooMuchData-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendFakeEarlyDataLength: 16384 + 1,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- })
+ DefaultCurves: []CurveID{},
+ },
+ shouldFail: true,
+ expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-HRR-TooMuchData-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendFakeEarlyDataLength: 16384 + 1,
- },
- DefaultCurves: []CurveID{},
+ // Test that skipping early data looking for cleartext correctly
+ // processes an alert record.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-HRR-FatalAlert-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyAlert: true,
+ SendFakeEarlyDataLength: 4,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
- })
+ DefaultCurves: []CurveID{},
+ },
+ shouldFail: true,
+ expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
+ })
- // Test that skipping early data looking for cleartext correctly
- // processes an alert record.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-HRR-FatalAlert-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyAlert: true,
- SendFakeEarlyDataLength: 4,
- },
- DefaultCurves: []CurveID{},
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-SecondClientHelloEarlyData-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataOnSecondClientHello: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
- })
+ DefaultCurves: []CurveID{},
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: bad record MAC",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SkipEarlyData-SecondClientHelloEarlyData-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyDataOnSecondClientHello: true,
- },
- DefaultCurves: []CurveID{},
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EmptyEncryptedExtensions-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ EmptyEncryptedExtensions: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedLocalError: "remote error: bad record MAC",
- })
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: error decoding message",
+ })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EmptyEncryptedExtensions-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- EmptyEncryptedExtensions: true,
- },
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EncryptedExtensionsWithKeyShare-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ EncryptedExtensionsWithKeyShare: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedLocalError: "remote error: error decoding message",
- })
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: unsupported extension",
+ })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EncryptedExtensionsWithKeyShare-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- EncryptedExtensionsWithKeyShare: true,
- },
- },
- tls13Variant: variant,
- shouldFail: true,
- expectedLocalError: "remote error: unsupported extension",
- })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SendHelloRetryRequest-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // Require a HelloRetryRequest for every curve.
+ DefaultCurves: []CurveID{},
+ CurvePreferences: []CurveID{CurveX25519},
+ },
+ expectedCurveID: CurveX25519,
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SendHelloRetryRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // Require a HelloRetryRequest for every curve.
- DefaultCurves: []CurveID{},
- },
- tls13Variant: variant,
- expectedCurveID: CurveX25519,
- })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SendHelloRetryRequest-2-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ DefaultCurves: []CurveID{CurveP384},
+ CurvePreferences: []CurveID{CurveX25519, CurveP384},
+ },
+ // Although the ClientHello did not predict our preferred curve,
+ // we always select it whether it is predicted or not.
+ expectedCurveID: CurveX25519,
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SendHelloRetryRequest-2-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- DefaultCurves: []CurveID{CurveP384},
+ testCases = append(testCases, testCase{
+ name: "UnknownCurve-HelloRetryRequest-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ SendHelloRetryRequestCurve: bogusCurve,
},
- tls13Variant: variant,
- // Although the ClientHello did not predict our preferred curve,
- // we always select it whether it is predicted or not.
- expectedCurveID: CurveX25519,
- })
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ })
- testCases = append(testCases, testCase{
- name: "UnknownCurve-HelloRetryRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- SendHelloRetryRequestCurve: bogusCurve,
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-CipherChange-TLS13",
+ 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_CURVE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CIPHER_RETURNED:",
+ })
- 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,
- },
+ // 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-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
},
- 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,
- },
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ ExpectNoTLS13PSKAfterHRR: true,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- ExpectNoTLS13PSKAfterHRR: true,
- },
- CipherSuites: []uint16{
- TLS_AES_256_GCM_SHA384,
- },
+ CipherSuites: []uint16{
+ TLS_AES_256_GCM_SHA384,
},
- tls13Variant: variant,
- resumeSession: true,
- expectResumeRejected: true,
- })
+ },
+ resumeSession: true,
+ expectResumeRejected: true,
+ })
- testCases = append(testCases, testCase{
- name: "DisabledCurve-HelloRetryRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- CurvePreferences: []CurveID{CurveP256},
- Bugs: ProtocolBugs{
- IgnorePeerCurvePreferences: true,
- },
+ testCases = append(testCases, testCase{
+ name: "DisabledCurve-HelloRetryRequest-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CurvePreferences: []CurveID{CurveP256},
+ Bugs: ProtocolBugs{
+ IgnorePeerCurvePreferences: true,
},
- tls13Variant: variant,
- flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- })
+ },
+ flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ })
- testCases = append(testCases, testCase{
- name: "UnnecessaryHelloRetryRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- CurvePreferences: []CurveID{CurveX25519},
- Bugs: ProtocolBugs{
- SendHelloRetryRequestCurve: CurveX25519,
- },
+ testCases = append(testCases, testCase{
+ name: "UnnecessaryHelloRetryRequest-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CurvePreferences: []CurveID{CurveX25519},
+ Bugs: ProtocolBugs{
+ SendHelloRetryRequestCurve: CurveX25519,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ })
- testCases = append(testCases, testCase{
- name: "SecondHelloRetryRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- SecondHelloRetryRequest: true,
- },
+ testCases = append(testCases, testCase{
+ name: "SecondHelloRetryRequest-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ SecondHelloRetryRequest: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequest-Empty-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- AlwaysSendHelloRetryRequest: true,
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-Empty-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ AlwaysSendHelloRetryRequest: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":EMPTY_HELLO_RETRY_REQUEST:",
- expectedLocalError: "remote error: illegal parameter",
- })
+ },
+ shouldFail: true,
+ expectedError: ":EMPTY_HELLO_RETRY_REQUEST:",
+ expectedLocalError: "remote error: illegal parameter",
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequest-DuplicateCurve-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires a HelloRetryRequest against BoringSSL's default
- // configuration. Assert this ExpectMissingKeyShare.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- ExpectMissingKeyShare: true,
- DuplicateHelloRetryRequestExtensions: true,
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-DuplicateCurve-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires a HelloRetryRequest against BoringSSL's default
+ // configuration. Assert this ExpectMissingKeyShare.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ ExpectMissingKeyShare: true,
+ DuplicateHelloRetryRequestExtensions: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DUPLICATE_EXTENSION:",
- expectedLocalError: "remote error: illegal parameter",
- })
+ },
+ shouldFail: true,
+ expectedError: ":DUPLICATE_EXTENSION:",
+ expectedLocalError: "remote error: illegal parameter",
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequest-Cookie-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendHelloRetryRequestCookie: []byte("cookie"),
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-Cookie-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendHelloRetryRequestCookie: []byte("cookie"),
},
- tls13Variant: variant,
- })
+ },
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequest-DuplicateCookie-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendHelloRetryRequestCookie: []byte("cookie"),
- DuplicateHelloRetryRequestExtensions: true,
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-DuplicateCookie-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendHelloRetryRequestCookie: []byte("cookie"),
+ DuplicateHelloRetryRequestExtensions: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DUPLICATE_EXTENSION:",
- expectedLocalError: "remote error: illegal parameter",
- })
+ },
+ shouldFail: true,
+ expectedError: ":DUPLICATE_EXTENSION:",
+ expectedLocalError: "remote error: illegal parameter",
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequest-EmptyCookie-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendHelloRetryRequestCookie: []byte{},
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-EmptyCookie-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendHelloRetryRequestCookie: []byte{},
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequest-Cookie-Curve-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- SendHelloRetryRequestCookie: []byte("cookie"),
- ExpectMissingKeyShare: true,
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-Cookie-Curve-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ SendHelloRetryRequestCookie: []byte("cookie"),
+ ExpectMissingKeyShare: true,
},
- tls13Variant: variant,
- })
+ },
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequest-Unknown-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- CustomHelloRetryRequestExtension: "extension",
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequest-Unknown-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ CustomHelloRetryRequestExtension: "extension",
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":UNEXPECTED_EXTENSION:",
- expectedLocalError: "remote error: unsupported extension",
- })
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION:",
+ expectedLocalError: "remote error: unsupported extension",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SecondClientHelloMissingKeyShare-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- DefaultCurves: []CurveID{},
- Bugs: ProtocolBugs{
- SecondClientHelloMissingKeyShare: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SecondClientHelloMissingKeyShare-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ DefaultCurves: []CurveID{},
+ Bugs: ProtocolBugs{
+ SecondClientHelloMissingKeyShare: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":MISSING_KEY_SHARE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":MISSING_KEY_SHARE:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SecondClientHelloWrongCurve-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- DefaultCurves: []CurveID{},
- Bugs: ProtocolBugs{
- MisinterpretHelloRetryRequestCurve: CurveP521,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SecondClientHelloWrongCurve-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ DefaultCurves: []CurveID{},
+ Bugs: ProtocolBugs{
+ MisinterpretHelloRetryRequestCurve: CurveP521,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequestVersionMismatch-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- SendServerHelloVersion: 0x0305,
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequestVersionMismatch-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ SendServerHelloVersion: 0x0305,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":WRONG_VERSION_NUMBER:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_VERSION_NUMBER:",
+ })
- testCases = append(testCases, testCase{
- name: "HelloRetryRequestCurveMismatch-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- // Send P-384 (correct) in the HelloRetryRequest.
- SendHelloRetryRequestCurve: CurveP384,
- // But send P-256 in the ServerHello.
- SendCurve: CurveP256,
- },
+ testCases = append(testCases, testCase{
+ name: "HelloRetryRequestCurveMismatch-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ // Send P-384 (correct) in the HelloRetryRequest.
+ SendHelloRetryRequestCurve: CurveP384,
+ // But send P-256 in the ServerHello.
+ SendCurve: CurveP256,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ })
- // Test the server selecting a curve that requires a HelloRetryRequest
- // without sending it.
- testCases = append(testCases, testCase{
- name: "SkipHelloRetryRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- SkipHelloRetryRequest: true,
- },
+ // Test the server selecting a curve that requires a HelloRetryRequest
+ // without sending it.
+ testCases = append(testCases, testCase{
+ name: "SkipHelloRetryRequest-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ SkipHelloRetryRequest: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CURVE:",
+ })
- // Test that the supported_versions extension is enforced in the
- // second ServerHello. Note we only enforce this starting draft 28.
- if isDraft28(version.versionWire) {
- testCases = append(testCases, testCase{
- name: "SecondServerHelloNoVersion-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- OmitServerSupportedVersionExtension: true,
- },
- },
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
- })
- testCases = append(testCases, testCase{
- name: "SecondServerHelloWrongVersion-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- // P-384 requires HelloRetryRequest in BoringSSL.
- CurvePreferences: []CurveID{CurveP384},
- Bugs: ProtocolBugs{
- SendServerSupportedVersionExtension: 0x1234,
- },
- },
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
- })
- }
-
- testCases = append(testCases, testCase{
- name: "RequestContextInHandshake-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- ClientAuth: RequireAnyClientCert,
- Bugs: ProtocolBugs{
- SendRequestContext: []byte("request context"),
- },
+ testCases = append(testCases, testCase{
+ name: "SecondServerHelloNoVersion-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ OmitServerSupportedVersionExtension: true,
},
- tls13Variant: variant,
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ },
+ shouldFail: true,
+ expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
+ })
+ testCases = append(testCases, testCase{
+ name: "SecondServerHelloWrongVersion-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ // P-384 requires HelloRetryRequest in BoringSSL.
+ CurvePreferences: []CurveID{CurveP384},
+ Bugs: ProtocolBugs{
+ SendServerSupportedVersionExtension: 0x1234,
},
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
+ })
- testCases = append(testCases, testCase{
- name: "UnknownExtensionInCertificateRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- ClientAuth: RequireAnyClientCert,
- Bugs: ProtocolBugs{
- SendCustomCertificateRequest: 0x1212,
- },
+ testCases = append(testCases, testCase{
+ name: "RequestContextInHandshake-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ ClientAuth: RequireAnyClientCert,
+ Bugs: ProtocolBugs{
+ SendRequestContext: []byte("request context"),
},
- tls13Variant: variant,
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ },
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ },
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ })
+
+ testCases = append(testCases, testCase{
+ name: "UnknownExtensionInCertificateRequest-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ ClientAuth: RequireAnyClientCert,
+ Bugs: ProtocolBugs{
+ SendCustomCertificateRequest: 0x1212,
},
- })
+ },
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ },
+ })
- testCases = append(testCases, testCase{
- name: "MissingSignatureAlgorithmsInCertificateRequest-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- ClientAuth: RequireAnyClientCert,
- Bugs: ProtocolBugs{
- OmitCertificateRequestAlgorithms: true,
- },
+ testCases = append(testCases, testCase{
+ name: "MissingSignatureAlgorithmsInCertificateRequest-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ ClientAuth: RequireAnyClientCert,
+ Bugs: ProtocolBugs{
+ OmitCertificateRequestAlgorithms: true,
},
- tls13Variant: variant,
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- })
+ },
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaKeyFile),
+ },
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TrailingKeyShareData-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- TrailingKeyShareData: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TrailingKeyShareData-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ TrailingKeyShareData: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ })
- testCases = append(testCases, testCase{
- name: "AlwaysSelectPSKIdentity-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- AlwaysSelectPSKIdentity: true,
- },
+ testCases = append(testCases, testCase{
+ name: "AlwaysSelectPSKIdentity-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ AlwaysSelectPSKIdentity: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":UNEXPECTED_EXTENSION:",
- })
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION:",
+ })
- testCases = append(testCases, testCase{
- name: "InvalidPSKIdentity-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SelectPSKIdentityOnResume: 1,
- },
+ testCases = append(testCases, testCase{
+ name: "InvalidPSKIdentity-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SelectPSKIdentityOnResume: 1,
},
- tls13Variant: variant,
- resumeSession: true,
- shouldFail: true,
- expectedError: ":PSK_IDENTITY_NOT_FOUND:",
- })
+ },
+ resumeSession: true,
+ shouldFail: true,
+ expectedError: ":PSK_IDENTITY_NOT_FOUND:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ExtraPSKIdentity-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ExtraPSKIdentity: true,
- SendExtraPSKBinder: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ExtraPSKIdentity-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExtraPSKIdentity: true,
+ SendExtraPSKBinder: true,
},
- tls13Variant: variant,
- resumeSession: true,
- })
+ },
+ resumeSession: true,
+ })
- // Test that unknown NewSessionTicket extensions are tolerated.
- testCases = append(testCases, testCase{
- name: "CustomTicketExtension-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- CustomTicketExtension: "1234",
- },
+ // Test that unknown NewSessionTicket extensions are tolerated.
+ testCases = append(testCases, testCase{
+ name: "CustomTicketExtension-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ CustomTicketExtension: "1234",
},
- tls13Variant: variant,
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-RejectTicket-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Certificates: []Certificate{rsaCertificate},
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Certificates: []Certificate{ecdsaP256Certificate},
- SessionTicketsDisabled: true,
- },
- tls13Variant: variant,
- resumeSession: true,
- expectResumeRejected: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-reject-early-data",
- "-on-resume-shim-writes-first",
- "-on-initial-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-on-resume-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-on-retry-expect-peer-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
- // Session tickets are disabled, so the runner will not send a ticket.
- "-on-retry-expect-no-session",
- },
- })
+ },
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-RejectTicket-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Certificates: []Certificate{rsaCertificate},
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Certificates: []Certificate{ecdsaP256Certificate},
+ SessionTicketsDisabled: true,
+ },
+ resumeSession: true,
+ expectResumeRejected: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-reject-early-data",
+ "-on-resume-shim-writes-first",
+ "-on-initial-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-on-resume-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-on-retry-expect-peer-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+ // Session tickets are disabled, so the runner will not send a ticket.
+ "-on-retry-expect-no-session",
+ },
+ })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-HRR-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-HRR-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-reject-early-data",
- },
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-reject-early-data",
+ },
+ })
- // The client must check the server does not send the early_data
- // extension while rejecting the session.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyDataWithoutResume-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
+ // The client must check the server does not send the early_data
+ // extension while rejecting the session.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyDataWithoutResume-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ SessionTicketsDisabled: true,
+ Bugs: ProtocolBugs{
+ SendEarlyDataExtension: true,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- SessionTicketsDisabled: true,
- Bugs: ProtocolBugs{
- SendEarlyDataExtension: true,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_EXTENSION:",
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION:",
+ })
- // The client must fail with a dedicated error code if the server
- // responds with TLS 1.2 when offering 0-RTT.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyDataVersionDowngrade-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS12,
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- },
- shouldFail: true,
- expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
- })
+ // The client must fail with a dedicated error code if the server
+ // responds with TLS 1.2 when offering 0-RTT.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyDataVersionDowngrade-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS12,
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
+ })
- // Test that the client rejects an (unsolicited) early_data extension if
- // the server sent an HRR.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ServerAcceptsEarlyDataOnHRR-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
+ // Test that the client rejects an (unsolicited) early_data extension if
+ // the server sent an HRR.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerAcceptsEarlyDataOnHRR-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
+ SendEarlyDataExtension: true,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
- SendEarlyDataExtension: true,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-reject-early-data",
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_EXTENSION:",
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-reject-early-data",
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION:",
+ })
- 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-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
},
- 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-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SkipChangeCipherSpec: true,
},
- 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-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendExtraChangeCipherSpec: 33,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
- })
+ },
+ 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-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendExtraChangeCipherSpec: 33,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
- })
+ },
+ 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-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendPostHandshakeChangeCipherSpec: true,
},
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- expectedLocalError: "remote error: unexpected message",
- })
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ expectedLocalError: "remote error: unexpected message",
+ })
- fooString := "foo"
- barString := "bar"
+ fooString := "foo"
+ barString := "bar"
- // Test that the client reports the correct ALPN after a 0-RTT reject
- // that changed it.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-ALPNMismatch-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- ALPNProtocol: &fooString,
- },
+ // Test that the client reports the correct ALPN after a 0-RTT reject
+ // that changed it.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-ALPNMismatch-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ ALPNProtocol: &fooString,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- ALPNProtocol: &barString,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-advertise-alpn", "\x03foo\x03bar",
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-reject-early-data",
- "-on-initial-expect-alpn", "foo",
- "-on-resume-expect-alpn", "foo",
- "-on-retry-expect-alpn", "bar",
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ ALPNProtocol: &barString,
},
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-advertise-alpn", "\x03foo\x03bar",
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-reject-early-data",
+ "-on-initial-expect-alpn", "foo",
+ "-on-resume-expect-alpn", "foo",
+ "-on-retry-expect-alpn", "bar",
+ },
+ })
- // Test that the client reports the correct ALPN after a 0-RTT reject if
- // ALPN was omitted from the first connection.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-ALPNOmitted1-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- NextProtos: []string{"foo"},
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-advertise-alpn", "\x03foo\x03bar",
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-reject-early-data",
- "-on-initial-expect-alpn", "",
- "-on-resume-expect-alpn", "",
- "-on-retry-expect-alpn", "foo",
- "-on-resume-shim-writes-first",
- },
- })
+ // Test that the client reports the correct ALPN after a 0-RTT reject if
+ // ALPN was omitted from the first connection.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-ALPNOmitted1-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ NextProtos: []string{"foo"},
+ },
+ resumeSession: true,
+ flags: []string{
+ "-advertise-alpn", "\x03foo\x03bar",
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-reject-early-data",
+ "-on-initial-expect-alpn", "",
+ "-on-resume-expect-alpn", "",
+ "-on-retry-expect-alpn", "foo",
+ "-on-resume-shim-writes-first",
+ },
+ })
+
+ // Test that the client reports the correct ALPN after a 0-RTT reject if
+ // ALPN was omitted from the second connection.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-ALPNOmitted2-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ NextProtos: []string{"foo"},
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeSession: true,
+ flags: []string{
+ "-advertise-alpn", "\x03foo\x03bar",
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-reject-early-data",
+ "-on-initial-expect-alpn", "foo",
+ "-on-resume-expect-alpn", "foo",
+ "-on-retry-expect-alpn", "",
+ "-on-resume-shim-writes-first",
+ },
+ })
- // Test that the client reports the correct ALPN after a 0-RTT reject if
- // ALPN was omitted from the second connection.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-ALPNOmitted2-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- NextProtos: []string{"foo"},
+ // Test that the client enforces ALPN match on 0-RTT accept.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-BadALPNMismatch-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ ALPNProtocol: &fooString,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-advertise-alpn", "\x03foo\x03bar",
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-reject-early-data",
- "-on-initial-expect-alpn", "foo",
- "-on-resume-expect-alpn", "foo",
- "-on-retry-expect-alpn", "",
- "-on-resume-shim-writes-first",
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ AlwaysAcceptEarlyData: true,
+ ALPNProtocol: &barString,
},
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-advertise-alpn", "\x03foo\x03bar",
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-on-initial-expect-alpn", "foo",
+ "-on-resume-expect-alpn", "foo",
+ "-on-retry-expect-alpn", "bar",
+ },
+ shouldFail: true,
+ expectedError: ":ALPN_MISMATCH_ON_EARLY_DATA:",
+ })
- // Test that the client enforces ALPN match on 0-RTT accept.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-BadALPNMismatch-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- ALPNProtocol: &fooString,
- },
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- AlwaysAcceptEarlyData: true,
- ALPNProtocol: &barString,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-advertise-alpn", "\x03foo\x03bar",
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-on-initial-expect-alpn", "foo",
- "-on-resume-expect-alpn", "foo",
- "-on-retry-expect-alpn", "bar",
- },
- shouldFail: true,
- expectedError: ":ALPN_MISMATCH_ON_EARLY_DATA:",
- })
+ // Test that the client does not offer early data if it is incompatible
+ // with ALPN preferences.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-ALPNPreferenceChanged-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ NextProtos: []string{"foo", "bar"},
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-no-offer-early-data",
+ "-on-initial-advertise-alpn", "\x03foo",
+ "-on-resume-advertise-alpn", "\x03bar",
+ "-on-initial-expect-alpn", "foo",
+ "-on-resume-expect-alpn", "bar",
+ },
+ })
- // Test that the client does not offer early data if it is incompatible
- // with ALPN preferences.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-ALPNPreferenceChanged-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- NextProtos: []string{"foo", "bar"},
+ // Test that the server correctly rejects 0-RTT when the previous
+ // session did not allow early data on resumption.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-NonZeroRTTSession-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: false,
},
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-no-offer-early-data",
- "-on-initial-advertise-alpn", "\x03foo",
- "-on-resume-advertise-alpn", "\x03bar",
- "-on-initial-expect-alpn", "foo",
- "-on-resume-expect-alpn", "bar",
- },
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-on-resume-enable-early-data",
+ "-expect-reject-early-data",
+ },
+ })
- // Test that the server correctly rejects 0-RTT when the previous
- // session did not allow early data on resumption.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-NonZeroRTTSession-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
+ // Test that we reject early data where ALPN is omitted from the first
+ // connection.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-ALPNOmitted1-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ NextProtos: []string{},
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: false,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: false,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-on-resume-enable-early-data",
- "-expect-reject-early-data",
- },
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-on-initial-select-alpn", "",
+ "-on-resume-select-alpn", "foo",
+ },
+ })
- // Test that we reject early data where ALPN is omitted from the first
- // connection.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-ALPNOmitted1-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- NextProtos: []string{},
+ // Test that we reject early data where ALPN is omitted from the second
+ // connection.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-ALPNOmitted2-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ NextProtos: []string{"foo"},
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ NextProtos: []string{},
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: false,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: false,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-on-initial-select-alpn", "",
- "-on-resume-select-alpn", "foo",
- },
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-on-initial-select-alpn", "foo",
+ "-on-resume-select-alpn", "",
+ },
+ })
- // Test that we reject early data where ALPN is omitted from the second
- // connection.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-ALPNOmitted2-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- NextProtos: []string{"foo"},
+ // Test that we reject early data with mismatched ALPN.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-ALPNMismatch-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ NextProtos: []string{"foo"},
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ NextProtos: []string{"bar"},
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: false,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- NextProtos: []string{},
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: false,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-on-initial-select-alpn", "foo",
- "-on-resume-select-alpn", "",
- },
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-on-initial-select-alpn", "foo",
+ "-on-resume-select-alpn", "bar",
+ },
+ })
- // Test that we reject early data with mismatched ALPN.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-ALPNMismatch-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- NextProtos: []string{"foo"},
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- NextProtos: []string{"bar"},
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: false,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-on-initial-select-alpn", "foo",
- "-on-resume-select-alpn", "bar",
- },
- })
+ // Test that the client offering 0-RTT and Channel ID forbids the server
+ // from accepting both.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyDataChannelID-AcceptBoth-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ RequestChannelID: true,
+ },
+ resumeSession: true,
+ expectChannelID: true,
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
+ },
+ })
- // Test that the client offering 0-RTT and Channel ID forbids the server
- // from accepting both.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyDataChannelID-AcceptBoth-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- RequestChannelID: true,
+ // Test that the client offering Channel ID and 0-RTT allows the server
+ // to decline 0-RTT.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyDataChannelID-AcceptChannelID-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ RequestChannelID: true,
+ Bugs: ProtocolBugs{
+ AlwaysRejectEarlyData: true,
},
- tls13Variant: variant,
- resumeSession: true,
- expectChannelID: true,
- shouldFail: true,
- expectedError: ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
- },
- })
+ },
+ resumeSession: true,
+ expectChannelID: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
+ "-expect-reject-early-data",
+ },
+ })
- // Test that the client offering Channel ID and 0-RTT allows the server
- // to decline 0-RTT.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyDataChannelID-AcceptChannelID-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- RequestChannelID: true,
- Bugs: ProtocolBugs{
- AlwaysRejectEarlyData: true,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- expectChannelID: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
- "-expect-reject-early-data",
- },
- })
+ // Test that the client offering Channel ID and 0-RTT allows the server
+ // to decline Channel ID.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyDataChannelID-AcceptEarlyData-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
+ "-expect-accept-early-data",
+ },
+ })
- // Test that the client offering Channel ID and 0-RTT allows the server
- // to decline Channel ID.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyDataChannelID-AcceptEarlyData-Client-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
- "-expect-accept-early-data",
+ // Test that the server supporting Channel ID and 0-RTT declines 0-RTT
+ // if it would negotiate Channel ID.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyDataChannelID-OfferBoth-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ ChannelID: channelIDKey,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: false,
},
- })
+ },
+ resumeSession: true,
+ expectChannelID: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-reject-early-data",
+ "-expect-channel-id",
+ base64.StdEncoding.EncodeToString(channelIDBytes),
+ },
+ })
- // Test that the server supporting Channel ID and 0-RTT declines 0-RTT
- // if it would negotiate Channel ID.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyDataChannelID-OfferBoth-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- ChannelID: channelIDKey,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: false,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- expectChannelID: true,
- flags: []string{
- "-enable-early-data",
- "-expect-reject-early-data",
- "-expect-channel-id",
- base64.StdEncoding.EncodeToString(channelIDBytes),
+ // Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
+ // if not offered Channel ID.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyDataChannelID-OfferEarlyData-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
},
- })
+ },
+ resumeSession: true,
+ expectChannelID: false,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-accept-early-data",
+ "-enable-channel-id",
+ },
+ })
- // Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
- // if not offered Channel ID.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyDataChannelID-OfferEarlyData-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- expectChannelID: false,
- flags: []string{
- "-enable-early-data",
- "-expect-accept-early-data",
- "-enable-channel-id",
+ // Test that the server rejects 0-RTT streams without end_of_early_data.
+ // The subsequent records should fail to decrypt.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-SkipEndOfEarlyData-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ SkipEndOfEarlyData: true,
},
- })
+ },
+ resumeSession: true,
+ flags: []string{"-enable-early-data"},
+ shouldFail: true,
+ expectedLocalError: "remote error: bad record MAC",
+ expectedError: ":BAD_DECRYPT:",
+ })
- // Test that the server rejects 0-RTT streams without end_of_early_data.
- // The subsequent records should fail to decrypt.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-SkipEndOfEarlyData-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- SkipEndOfEarlyData: true,
- },
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-UnexpectedHandshake-Server-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ SendStrayEarlyHandshake: true,
+ ExpectEarlyDataAccepted: true,
},
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{"-enable-early-data"},
- shouldFail: true,
- expectedLocalError: "remote error: bad record MAC",
- expectedError: ":BAD_DECRYPT:",
- })
+ },
+ resumeSession: true,
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ expectedLocalError: "remote error: unexpected message",
+ flags: []string{
+ "-enable-early-data",
+ },
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-UnexpectedHandshake-Server-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- SendStrayEarlyHandshake: true,
- ExpectEarlyDataAccepted: true,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- expectedLocalError: "remote error: unexpected message",
- flags: []string{
- "-enable-early-data",
- },
- })
+ // Test that the client reports TLS 1.3 as the version while sending
+ // early data.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-Client-VersionAPI-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-accept-early-data",
+ "-expect-version", strconv.Itoa(VersionTLS13),
+ },
+ })
- // Test that the client reports TLS 1.3 as the version while sending
- // early data.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-Client-VersionAPI-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
+ // Test that client and server both notice handshake errors after data
+ // has started flowing.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "EarlyData-Client-BadFinished-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ BadFinished: true,
},
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-accept-early-data",
- "-expect-version", strconv.Itoa(VersionTLS13),
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-accept-early-data",
+ },
+ shouldFail: true,
+ expectedError: ":DIGEST_CHECK_FAILED:",
+ expectedLocalError: "remote error: error decrypting message",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "EarlyData-Server-BadFinished-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
+ BadFinished: true,
},
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-accept-early-data",
+ },
+ shouldFail: true,
+ expectedError: ":DIGEST_CHECK_FAILED:",
+ expectedLocalError: "remote error: error decrypting message",
+ })
- // Test that client and server both notice handshake errors after data
- // has started flowing.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "EarlyData-Client-BadFinished-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- MaxEarlyDataSize: 16384,
- Bugs: ProtocolBugs{
- BadFinished: true,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-accept-early-data",
- },
- shouldFail: true,
- expectedError: ":DIGEST_CHECK_FAILED:",
- expectedLocalError: "remote error: error decrypting message",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "EarlyData-Server-BadFinished-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
- },
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
- BadFinished: true,
- },
- },
- tls13Variant: variant,
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-accept-early-data",
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Server-NonEmptyEndOfEarlyData-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ NonEmptyEndOfEarlyData: true,
},
- shouldFail: true,
- expectedError: ":DIGEST_CHECK_FAILED:",
- expectedLocalError: "remote error: error decrypting message",
- })
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-ticket-supports-early-data",
+ "-expect-accept-early-data",
+ },
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Server-NonEmptyEndOfEarlyData-" + name,
- config: Config{
- MaxVersion: VersionTLS13,
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ServerSkipCertificateVerify-TLS13",
+ config: Config{
+ MinVersion: VersionTLS13,
+ MaxVersion: VersionTLS13,
+ Certificates: []Certificate{rsaChainCertificate},
+ Bugs: ProtocolBugs{
+ SkipCertificateVerify: true,
},
- resumeConfig: &Config{
- MaxVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- SendEarlyData: [][]byte{{1, 2, 3, 4}},
- ExpectEarlyDataAccepted: true,
- NonEmptyEndOfEarlyData: true,
- },
+ },
+ expectPeerCertificate: &rsaChainCertificate,
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaChainKeyFile),
+ "-require-any-client-certificate",
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ expectedLocalError: "remote error: unexpected message",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ClientSkipCertificateVerify-TLS13",
+ config: Config{
+ MinVersion: VersionTLS13,
+ MaxVersion: VersionTLS13,
+ Certificates: []Certificate{rsaChainCertificate},
+ Bugs: ProtocolBugs{
+ SkipCertificateVerify: true,
},
- resumeSession: true,
- flags: []string{
- "-enable-early-data",
- "-expect-ticket-supports-early-data",
- "-expect-accept-early-data",
- },
- tls13Variant: variant,
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- })
+ },
+ expectPeerCertificate: &rsaChainCertificate,
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaChainKeyFile),
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ expectedLocalError: "remote error: unexpected message",
+ })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ServerSkipCertificateVerify-" + name,
- config: Config{
- MinVersion: VersionTLS13,
- MaxVersion: VersionTLS13,
- Certificates: []Certificate{rsaChainCertificate},
- Bugs: ProtocolBugs{
- SkipCertificateVerify: true,
- },
- },
- tls13Variant: variant,
- expectPeerCertificate: &rsaChainCertificate,
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaChainKeyFile),
- "-require-any-client-certificate",
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- expectedLocalError: "remote error: unexpected message",
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ClientSkipCertificateVerify-" + name,
- config: Config{
- MinVersion: VersionTLS13,
- MaxVersion: VersionTLS13,
- Certificates: []Certificate{rsaChainCertificate},
- Bugs: ProtocolBugs{
- SkipCertificateVerify: true,
- },
- },
- tls13Variant: variant,
- expectPeerCertificate: &rsaChainCertificate,
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaChainKeyFile),
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- expectedLocalError: "remote error: unexpected message",
- })
- }
}
func addTLS13CipherPreferenceTests() {
@@ -13990,6 +13701,7 @@
TLS_CHACHA20_POLY1305_SHA256,
TLS_AES_128_GCM_SHA256,
},
+ CurvePreferences: []CurveID{CurveX25519},
},
flags: []string{
"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
@@ -14006,6 +13718,7 @@
TLS_AES_128_GCM_SHA256,
TLS_CHACHA20_POLY1305_SHA256,
},
+ CurvePreferences: []CurveID{CurveX25519},
},
flags: []string{
"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
@@ -14029,7 +13742,7 @@
},
})
- // Test that CECPQ2 cannot be used with TLS_AES_128_GCM_SHA256.
+ // CECPQ2 prefers 256-bit ciphers but will use AES-128 if there's nothing else.
testCases = append(testCases, testCase{
testType: serverTest,
name: "TLS13-CipherPreference-CECPQ2-AES128Only",
@@ -14042,9 +13755,39 @@
flags: []string{
"-curves", strconv.Itoa(int(CurveCECPQ2)),
},
- shouldFail: true,
- expectedError: ":NO_SHARED_CIPHER:",
- expectedLocalError: "remote error: handshake failure",
+ })
+ // When a 256-bit cipher is offered, even if not in first place, it should be
+ // picked.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-CipherPreference-CECPQ2-AES256Preferred",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
+ TLS_AES_256_GCM_SHA384,
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveCECPQ2)),
+ },
+ expectedCipher: TLS_AES_256_GCM_SHA384,
+ })
+ // ... but when CECPQ2 isn't being used, the client's preference controls.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-CipherPreference-CECPQ2-AES128PreferredOtherwise",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ CipherSuites: []uint16{
+ TLS_AES_128_GCM_SHA256,
+ TLS_AES_256_GCM_SHA384,
+ },
+ },
+ flags: []string{
+ "-curves", strconv.Itoa(int(CurveX25519)),
+ },
+ expectedCipher: TLS_AES_128_GCM_SHA256,
})
// Test that CECPQ2 continues to honor AES vs ChaCha20 logic.
@@ -14166,7 +13909,6 @@
SendRecordVersion: 0x03ff,
},
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":WRONG_VERSION_NUMBER:",
})
@@ -14183,7 +13925,6 @@
SendInitialRecordVersion: 0x03ff,
},
},
- tls13Variant: ver.tls13Variant,
})
// Test that garbage ClientHello record versions are rejected.
@@ -14197,7 +13938,6 @@
SendInitialRecordVersion: 0xffff,
},
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":WRONG_VERSION_NUMBER:",
})
@@ -14217,7 +13957,6 @@
Certificates: []Certificate{rsaChainCertificate},
ClientAuth: RequireAnyClientCert,
},
- tls13Variant: ver.tls13Variant,
expectPeerCertificate: &rsaChainCertificate,
flags: []string{
"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
@@ -14234,7 +13973,6 @@
MaxVersion: ver.version,
Certificates: []Certificate{rsaChainCertificate},
},
- tls13Variant: ver.tls13Variant,
expectPeerCertificate: &rsaChainCertificate,
flags: []string{
"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
@@ -14253,7 +13991,6 @@
MaxVersion: ver.version,
Certificates: []Certificate{garbageCertificate},
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
expectedError: ":CANNOT_PARSE_LEAF_CERT:",
expectedLocalError: "remote error: error decoding message",
@@ -14267,7 +14004,6 @@
MaxVersion: ver.version,
Certificates: []Certificate{garbageCertificate},
},
- tls13Variant: ver.tls13Variant,
flags: []string{"-require-any-client-certificate"},
shouldFail: true,
expectedError: ":CANNOT_PARSE_LEAF_CERT:",
@@ -14288,7 +14024,6 @@
MinVersion: ver.version,
MaxVersion: ver.version,
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-on-initial-retain-only-sha256-client-cert",
"-on-resume-retain-only-sha256-client-cert",
@@ -14306,7 +14041,6 @@
MaxVersion: ver.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-verify-peer",
"-on-initial-retain-only-sha256-client-cert",
@@ -14328,7 +14062,6 @@
MaxVersion: ver.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-verify-peer",
"-on-initial-retain-only-sha256-client-cert",
@@ -14349,7 +14082,6 @@
MaxVersion: ver.version,
Certificates: []Certificate{rsaCertificate},
},
- tls13Variant: ver.tls13Variant,
flags: []string{
"-verify-peer",
"-on-resume-retain-only-sha256-client-cert",
@@ -14412,13 +14144,182 @@
MaxVersion: ver.version,
Certificates: []Certificate{cert},
},
- tls13Variant: ver.tls13Variant,
shouldFail: true,
- expectedError: ":ECC_CERT_NOT_FOR_SIGNING:",
+ expectedError: ":KEY_USAGE_BIT_INCORRECT:",
})
}
}
+func addRSAKeyUsageTests() {
+ priv := rsaCertificate.PrivateKey.(*rsa.PrivateKey)
+
+ serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+ serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+ if err != nil {
+ panic(err)
+ }
+
+ dsTemplate := x509.Certificate{
+ SerialNumber: serialNumber,
+ Subject: pkix.Name{
+ Organization: []string{"Acme Co"},
+ },
+ NotBefore: time.Now(),
+ NotAfter: time.Now(),
+
+ KeyUsage: x509.KeyUsageDigitalSignature,
+ BasicConstraintsValid: true,
+ }
+
+ encTemplate := x509.Certificate{
+ SerialNumber: serialNumber,
+ Subject: pkix.Name{
+ Organization: []string{"Acme Co"},
+ },
+ NotBefore: time.Now(),
+ NotAfter: time.Now(),
+
+ KeyUsage: x509.KeyUsageKeyEncipherment,
+ BasicConstraintsValid: true,
+ }
+
+ dsDerBytes, err := x509.CreateCertificate(rand.Reader, &dsTemplate, &dsTemplate, &priv.PublicKey, priv)
+ if err != nil {
+ panic(err)
+ }
+
+ encDerBytes, err := x509.CreateCertificate(rand.Reader, &encTemplate, &encTemplate, &priv.PublicKey, priv)
+ if err != nil {
+ panic(err)
+ }
+
+ dsCert := Certificate{
+ Certificate: [][]byte{dsDerBytes},
+ PrivateKey: priv,
+ }
+
+ encCert := Certificate{
+ Certificate: [][]byte{encDerBytes},
+ PrivateKey: priv,
+ }
+
+ dsSuites := []uint16{
+ TLS_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ }
+ encSuites := []uint16{
+ TLS_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_RSA_WITH_AES_128_CBC_SHA,
+ }
+
+ for _, ver := range tlsVersions {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "RSAKeyUsage-WantSignature-GotEncipherment-" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{encCert},
+ CipherSuites: dsSuites,
+ },
+ shouldFail: true,
+ expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+ flags: []string{
+ "-enforce-rsa-key-usage",
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "RSAKeyUsage-WantSignature-GotSignature-" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{dsCert},
+ CipherSuites: dsSuites,
+ },
+ flags: []string{
+ "-enforce-rsa-key-usage",
+ },
+ })
+
+ // TLS 1.3 removes the encipherment suites.
+ if ver.version < VersionTLS13 {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "RSAKeyUsage-WantEncipherment-GotEncipherment" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{encCert},
+ CipherSuites: encSuites,
+ },
+ flags: []string{
+ "-enforce-rsa-key-usage",
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "RSAKeyUsage-WantEncipherment-GotSignature-" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{dsCert},
+ CipherSuites: encSuites,
+ },
+ shouldFail: true,
+ expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+ flags: []string{
+ "-enforce-rsa-key-usage",
+ },
+ })
+
+ // In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "RSAKeyUsage-WantSignature-GotEncipherment-Unenforced" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{dsCert},
+ CipherSuites: encSuites,
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "RSAKeyUsage-WantEncipherment-GotSignature-Unenforced" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{encCert},
+ CipherSuites: dsSuites,
+ },
+ })
+
+ }
+
+ if ver.version >= VersionTLS13 {
+ // In 1.3 and above, we enforce keyUsage even without the flag.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "RSAKeyUsage-WantSignature-GotEncipherment-Enforced" + ver.name,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{encCert},
+ CipherSuites: dsSuites,
+ },
+ shouldFail: true,
+ expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+ })
+
+ }
+ }
+}
+
func addExtraHandshakeTests() {
// An extra SSL_do_handshake is normally a no-op. These tests use -async
// to ensure there is no transport I/O.
@@ -14588,8 +14489,10 @@
OmitExtensions: true,
// Disable all ServerHello extensions so
// OmitExtensions works.
- NoExtendedMasterSecret: true,
- NoRenegotiationInfo: true,
+ NoExtendedMasterSecret: true,
+ NoRenegotiationInfo: true,
+ NoOCSPStapling: true,
+ NoSignedCertificateTimestamps: true,
},
},
})
@@ -14605,8 +14508,10 @@
EmptyExtensions: true,
// Disable all ServerHello extensions so
// EmptyExtensions works.
- NoExtendedMasterSecret: true,
- NoRenegotiationInfo: true,
+ NoExtendedMasterSecret: true,
+ NoRenegotiationInfo: true,
+ NoOCSPStapling: true,
+ NoSignedCertificateTimestamps: true,
},
},
})
@@ -14666,9 +14571,8 @@
// Duplicate compression algorithms is an error, even if nothing is
// configured.
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "DuplicateCertCompressionExt-" + ver.name,
- tls13Variant: ver.tls13Variant,
+ testType: serverTest,
+ name: "DuplicateCertCompressionExt-" + ver.name,
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14683,10 +14587,9 @@
// With compression algorithms configured, an duplicate values should still
// be an error.
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "DuplicateCertCompressionExt2-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: serverTest,
+ name: "DuplicateCertCompressionExt2-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14714,10 +14617,9 @@
}
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "CertCompressionExpands-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: serverTest,
+ name: "CertCompressionExpands-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14729,10 +14631,9 @@
})
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "CertCompressionShrinks-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: serverTest,
+ name: "CertCompressionShrinks-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14746,10 +14647,9 @@
// With both algorithms configured, the server should pick its most
// preferable. (Which is expandingAlgId.)
testCases = append(testCases, testCase{
- testType: serverTest,
- name: "CertCompressionPriority-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: serverTest,
+ name: "CertCompressionPriority-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14764,10 +14664,9 @@
})
testCases = append(testCases, testCase{
- testType: clientTest,
- name: "CertCompressionExpandsClient-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: clientTest,
+ name: "CertCompressionExpandsClient-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14781,10 +14680,9 @@
})
testCases = append(testCases, testCase{
- testType: clientTest,
- name: "CertCompressionShrinksClient-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: clientTest,
+ name: "CertCompressionShrinksClient-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14798,10 +14696,9 @@
})
testCases = append(testCases, testCase{
- testType: clientTest,
- name: "CertCompressionBadAlgIdClient-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: clientTest,
+ name: "CertCompressionBadAlgIdClient-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14818,10 +14715,9 @@
})
testCases = append(testCases, testCase{
- testType: clientTest,
- name: "CertCompressionTooSmallClient-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: clientTest,
+ name: "CertCompressionTooSmallClient-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -14838,10 +14734,9 @@
})
testCases = append(testCases, testCase{
- testType: clientTest,
- name: "CertCompressionTooLargeClient-" + ver.name,
- tls13Variant: ver.tls13Variant,
- flags: []string{"-install-cert-compression-algs"},
+ testType: clientTest,
+ name: "CertCompressionTooLargeClient-" + ver.name,
+ flags: []string{"-install-cert-compression-algs"},
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -15015,6 +14910,109 @@
}
}
+func addDelegatedCredentialTests() {
+ certPath := path.Join(*resourceDir, rsaCertificateFile)
+ pemBytes, err := ioutil.ReadFile(certPath)
+ if err != nil {
+ panic(err)
+ }
+
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ panic(fmt.Sprintf("no PEM block found in %q", certPath))
+ }
+ parentDER := block.Bytes
+
+ rsaPriv, _, err := loadRSAPrivateKey(rsaKeyFile)
+ if err != nil {
+ panic(err)
+ }
+
+ ecdsaDC, ecdsaPKCS8, err := createDelegatedCredential(delegatedCredentialConfig{
+ algo: signatureRSAPSSWithSHA256,
+ }, parentDER, rsaPriv)
+ if err != nil {
+ panic(err)
+ }
+ ecdsaFlagValue := fmt.Sprintf("%x,%x", ecdsaDC, ecdsaPKCS8)
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "DelegatedCredentials-NoClientSupport",
+ config: Config{
+ MinVersion: VersionTLS13,
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ DisableDelegatedCredentials: true,
+ },
+ },
+ flags: []string{
+ "-delegated-credential", ecdsaFlagValue,
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "DelegatedCredentials-Basic",
+ config: Config{
+ MinVersion: VersionTLS13,
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectDelegatedCredentials: true,
+ },
+ },
+ flags: []string{
+ "-delegated-credential", ecdsaFlagValue,
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "DelegatedCredentials-SigAlgoMissing",
+ config: Config{
+ MinVersion: VersionTLS13,
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ FailIfDelegatedCredentials: true,
+ },
+ // If the client doesn't support the delegated credential signature
+ // algorithm then the handshake should complete without using delegated
+ // credentials.
+ VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
+ },
+ flags: []string{
+ "-delegated-credential", ecdsaFlagValue,
+ },
+ })
+
+ // This flag value has mismatched public and private keys which should cause a
+ // configuration error in the shim.
+ _, badTLSVersionPKCS8, err := createDelegatedCredential(delegatedCredentialConfig{
+ algo: signatureRSAPSSWithSHA256,
+ tlsVersion: 0x1234,
+ }, parentDER, rsaPriv)
+ if err != nil {
+ panic(err)
+ }
+ mismatchFlagValue := fmt.Sprintf("%x,%x", ecdsaDC, badTLSVersionPKCS8)
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "DelegatedCredentials-KeyMismatch",
+ config: Config{
+ MinVersion: VersionTLS13,
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ FailIfDelegatedCredentials: true,
+ },
+ },
+ flags: []string{
+ "-delegated-credential", mismatchFlagValue,
+ },
+ shouldFail: true,
+ expectedError: ":KEY_VALUES_MISMATCH:",
+ })
+}
+
func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
defer wg.Done()
@@ -15146,10 +15144,12 @@
addCertificateTests()
addRetainOnlySHA256ClientCertTests()
addECDSAKeyUsageTests()
+ addRSAKeyUsageTests()
addExtraHandshakeTests()
addOmitExtensionsTests()
addCertCompressionTests()
addJDK11WorkaroundTests()
+ addDelegatedCredentialTests()
testCases = append(testCases, convertToSplitHandshakeTests(testCases)...)
diff --git a/src/ssl/test/settings_writer.cc b/src/ssl/test/settings_writer.cc
index 66025f6..fe8d42e 100644
--- a/src/ssl/test/settings_writer.cc
+++ b/src/ssl/test/settings_writer.cc
@@ -59,12 +59,6 @@
return false;
}
- if (config->tls13_variant != 0 &&
- (!CBB_add_u16(cbb_.get(), kTLS13Variant) ||
- !CBB_add_u8(cbb_.get(), static_cast<uint8_t>(config->tls13_variant)))) {
- return false;
- }
-
return true;
}
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index bed0501..70e061b 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -145,9 +145,11 @@
{ "-is-handshaker-supported", &TestConfig::is_handshaker_supported },
{ "-handshaker-resume", &TestConfig::handshaker_resume },
{ "-reverify-on-resume", &TestConfig::reverify_on_resume },
+ { "-enforce-rsa-key-usage", &TestConfig::enforce_rsa_key_usage },
{ "-jdk11-workaround", &TestConfig::jdk11_workaround },
{ "-server-preference", &TestConfig::server_preference },
{ "-export-traffic-secrets", &TestConfig::export_traffic_secrets },
+ { "-key-update", &TestConfig::key_update },
};
const Flag<std::string> kStringFlags[] = {
@@ -176,6 +178,7 @@
{ "-expect-client-ca-list", &TestConfig::expected_client_ca_list },
{ "-expect-msg-callback", &TestConfig::expect_msg_callback },
{ "-handshaker-path", &TestConfig::handshaker_path },
+ { "-delegated-credential", &TestConfig::delegated_credential },
};
const Flag<std::string> kBase64Flags[] = {
@@ -217,7 +220,6 @@
{ "-max-send-fragment", &TestConfig::max_send_fragment },
{ "-read-size", &TestConfig::read_size },
{ "-expect-ticket-age-skew", &TestConfig::expect_ticket_age_skew },
- { "-tls13-variant", &TestConfig::tls13_variant },
};
const Flag<std::vector<int>> kIntVectorFlags[] = {
@@ -1246,9 +1248,6 @@
SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
}
- SSL_CTX_set_tls13_variant(ssl_ctx.get(),
- static_cast<enum tls13_variant_t>(tls13_variant));
-
if (allow_unknown_alpn_protos) {
SSL_CTX_set_allow_unknown_alpn_protos(ssl_ctx.get(), 1);
}
@@ -1503,6 +1502,9 @@
if (reverify_on_resume) {
SSL_CTX_set_reverify_on_resume(ssl_ctx, 1);
}
+ if (enforce_rsa_key_usage) {
+ SSL_set_enforce_rsa_key_usage(ssl.get(), 1);
+ }
if (no_tls13) {
SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_3);
}
@@ -1673,5 +1675,40 @@
}
}
+ if (!delegated_credential.empty()) {
+ std::string::size_type comma = delegated_credential.find(',');
+ if (comma == std::string::npos) {
+ fprintf(stderr, "failed to find comma in delegated credential argument");
+ return nullptr;
+ }
+
+ const std::string dc_hex = delegated_credential.substr(0, comma);
+ const std::string pkcs8_hex = delegated_credential.substr(comma + 1);
+ std::string dc, pkcs8;
+ if (!HexDecode(&dc, dc_hex) || !HexDecode(&pkcs8, pkcs8_hex)) {
+ fprintf(stderr, "failed to hex decode delegated credential argument");
+ return nullptr;
+ }
+
+ CBS dc_cbs(bssl::Span<const uint8_t>(
+ reinterpret_cast<const uint8_t *>(dc.data()), dc.size()));
+ CBS pkcs8_cbs(bssl::Span<const uint8_t>(
+ reinterpret_cast<const uint8_t *>(pkcs8.data()), pkcs8.size()));
+
+ bssl::UniquePtr<EVP_PKEY> priv(EVP_parse_private_key(&pkcs8_cbs));
+ if (!priv) {
+ fprintf(stderr, "failed to parse delegated credential private key");
+ return nullptr;
+ }
+
+ bssl::UniquePtr<CRYPTO_BUFFER> dc_buf(
+ CRYPTO_BUFFER_new_from_CBS(&dc_cbs, nullptr));
+ if (!SSL_set1_delegated_credential(ssl.get(), dc_buf.get(),
+ priv.get(), nullptr)) {
+ fprintf(stderr, "SSL_set1_delegated_credential failed.\n");
+ return nullptr;
+ }
+ }
+
return ssl;
}
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 0d0753e..9221d6f 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -104,7 +104,6 @@
bool use_ticket_callback = false;
bool renew_ticket = false;
bool enable_early_data = false;
- int tls13_variant = 0;
bool enable_client_custom_extension = false;
bool enable_server_custom_extension = false;
bool custom_extension_skip = false;
@@ -166,12 +165,15 @@
bool fail_ocsp_callback = false;
bool install_cert_compression_algs = false;
bool reverify_on_resume = false;
+ bool enforce_rsa_key_usage = false;
bool is_handshaker_supported = false;
bool handshaker_resume = false;
std::string handshaker_path;
bool jdk11_workaround = false;
bool server_preference = false;
bool export_traffic_secrets = false;
+ bool key_update = false;
+ std::string delegated_credential;
int argc;
char **argv;
diff --git a/src/ssl/tls13_both.cc b/src/ssl/tls13_both.cc
index 6baeaf7..ba5719f 100644
--- a/src/ssl/tls13_both.cc
+++ b/src/ssl/tls13_both.cc
@@ -212,7 +212,8 @@
}
// TLS 1.3 always uses certificate keys for signing thus the correct
// keyUsage is enforced.
- if (!ssl_cert_check_digital_signature_key_usage(&certificate)) {
+ if (!ssl_cert_check_key_usage(&certificate,
+ key_usage_digital_signature)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return false;
}
@@ -418,6 +419,7 @@
bool tls13_add_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
CERT *const cert = hs->config->cert.get();
+ DC *const dc = cert->dc.get();
ScopedCBB cbb;
CBB *body, body_storage, certificate_list;
@@ -441,7 +443,7 @@
return false;
}
- if (!ssl_has_certificate(hs->config)) {
+ if (!ssl_has_certificate(hs)) {
return ssl_add_message_cbb(ssl, cbb.get());
}
@@ -484,6 +486,19 @@
}
}
+ if (ssl_signing_with_dc(hs)) {
+ const CRYPTO_BUFFER *raw = dc->raw.get();
+ if (!CBB_add_u16(&extensions, TLSEXT_TYPE_delegated_credential) ||
+ !CBB_add_u16(&extensions, CRYPTO_BUFFER_len(raw)) ||
+ !CBB_add_bytes(&extensions,
+ CRYPTO_BUFFER_data(raw),
+ CRYPTO_BUFFER_len(raw)) ||
+ !CBB_flush(&extensions)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+
for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(cert->chain.get()); i++) {
CRYPTO_BUFFER *cert_buf = sk_CRYPTO_BUFFER_value(cert->chain.get(), i);
CBB child;
@@ -607,6 +622,25 @@
return true;
}
+bool tls13_add_key_update(SSL *ssl, int update_requested) {
+ ScopedCBB cbb;
+ CBB body_cbb;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body_cbb,
+ SSL3_MT_KEY_UPDATE) ||
+ !CBB_add_u8(&body_cbb, update_requested) ||
+ !ssl_add_message_cbb(ssl, cbb.get()) ||
+ !tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
+ return false;
+ }
+
+ // Suppress KeyUpdate acknowledgments until this change is written to the
+ // wire. This prevents us from accumulating write obligations when read and
+ // write progress at different rates. See RFC 8446, section 4.6.3.
+ ssl->s3->key_update_pending = true;
+
+ return true;
+}
+
static bool tls13_receive_key_update(SSL *ssl, const SSLMessage &msg) {
CBS body = msg.body;
uint8_t key_update_request;
@@ -625,21 +659,9 @@
// Acknowledge the KeyUpdate
if (key_update_request == SSL_KEY_UPDATE_REQUESTED &&
- !ssl->s3->key_update_pending) {
- ScopedCBB cbb;
- CBB body_cbb;
- if (!ssl->method->init_message(ssl, cbb.get(), &body_cbb,
- SSL3_MT_KEY_UPDATE) ||
- !CBB_add_u8(&body_cbb, SSL_KEY_UPDATE_NOT_REQUESTED) ||
- !ssl_add_message_cbb(ssl, cbb.get()) ||
- !tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
- return false;
- }
-
- // Suppress KeyUpdate acknowledgments until this change is written to the
- // wire. This prevents us from accumulating write obligations when read and
- // write progress at different rates. See RFC 8446, section 4.6.3.
- ssl->s3->key_update_pending = true;
+ !ssl->s3->key_update_pending &&
+ !tls13_add_key_update(ssl, SSL_KEY_UPDATE_NOT_REQUESTED)) {
+ return false;
}
return true;
@@ -648,7 +670,7 @@
bool tls13_post_handshake(SSL *ssl, const SSLMessage &msg) {
if (msg.type == SSL3_MT_KEY_UPDATE) {
ssl->s3->key_update_count++;
- if (ssl->ctx->quic_method != nullptr ||
+ if (ssl->quic_method != nullptr ||
ssl->s3->key_update_count > kMaxKeyUpdates) {
OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_KEY_UPDATES);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index 40913dc..ac97165 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -294,16 +294,14 @@
return ssl_hs_error;
}
- if (ssl_is_draft28(ssl->version)) {
- // Recheck supported_versions, in case this is the second ServerHello.
- uint16_t version;
- if (!have_supported_versions ||
- !CBS_get_u16(&supported_versions, &version) ||
- version != ssl->version) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_SECOND_SERVERHELLO_VERSION_MISMATCH);
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- return ssl_hs_error;
- }
+ // Recheck supported_versions, in case this is the second ServerHello.
+ uint16_t version;
+ if (!have_supported_versions ||
+ !CBS_get_u16(&supported_versions, &version) ||
+ version != ssl->version) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_SECOND_SERVERHELLO_VERSION_MISMATCH);
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ return ssl_hs_error;
}
alert = SSL_AD_DECODE_ERROR;
@@ -685,7 +683,7 @@
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) {
// Don't send CertificateVerify if there is no certificate.
- if (!ssl_has_certificate(hs->config)) {
+ if (!ssl_has_certificate(hs)) {
hs->tls13_state = state_complete_second_flight;
return ssl_hs_ok;
}
@@ -883,8 +881,7 @@
session->timeout = server_timeout;
}
- if (!tls13_derive_session_psk(session.get(), ticket_nonce,
- ssl->ctx->quic_method != nullptr)) {
+ if (!tls13_derive_session_psk(session.get(), ticket_nonce)) {
return false;
}
diff --git a/src/ssl/tls13_enc.cc b/src/ssl/tls13_enc.cc
index f18084e..7353561 100644
--- a/src/ssl/tls13_enc.cc
+++ b/src/ssl/tls13_enc.cc
@@ -69,27 +69,19 @@
static bool 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,
- bool use_quic_label) {
+ const uint8_t *hash, size_t hash_len,
+ size_t len) {
static const char kTLS13ProtocolLabel[] = "tls13 ";
- static const char kQUICProtocolLabel[] = "quic ";
-
- const char *protocol_label;
- if (use_quic_label) {
- protocol_label = kQUICProtocolLabel;
- } else {
- protocol_label = kTLS13ProtocolLabel;
- }
ScopedCBB cbb;
CBB child;
Array<uint8_t> hkdf_label;
- if (!CBB_init(cbb.get(),
- 2 + 1 + strlen(protocol_label) + label_len + 1 + hash_len) ||
+ if (!CBB_init(cbb.get(), 2 + 1 + strlen(kTLS13ProtocolLabel) + label_len + 1 +
+ hash_len) ||
!CBB_add_u16(cbb.get(), len) ||
!CBB_add_u8_length_prefixed(cbb.get(), &child) ||
- !CBB_add_bytes(&child, (const uint8_t *)protocol_label,
- strlen(protocol_label)) ||
+ !CBB_add_bytes(&child, (const uint8_t *)kTLS13ProtocolLabel,
+ strlen(kTLS13ProtocolLabel)) ||
!CBB_add_bytes(&child, (const uint8_t *)label, label_len) ||
!CBB_add_u8_length_prefixed(cbb.get(), &child) ||
!CBB_add_bytes(&child, hash, hash_len) ||
@@ -115,8 +107,7 @@
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,
- hs->ssl->ctx->quic_method != nullptr)) {
+ derive_context_len, hs->hash_len)) {
return false;
}
@@ -137,8 +128,7 @@
return hkdf_expand_label(out, hs->transcript.Digest(), hs->secret,
hs->hash_len, label, label_len, context_hash,
- context_hash_len, len,
- hs->ssl->ctx->quic_method != nullptr);
+ context_hash_len, len);
}
bool tls13_set_traffic_key(SSL *ssl, enum ssl_encryption_level_t level,
@@ -154,7 +144,7 @@
}
UniquePtr<SSLAEADContext> traffic_aead;
- if (ssl->ctx->quic_method == nullptr) {
+ if (ssl->quic_method == nullptr) {
// Look up cipher suite properties.
const EVP_AEAD *aead;
size_t discard;
@@ -169,8 +159,7 @@
size_t key_len = EVP_AEAD_key_length(aead);
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len,
- "key", 3, NULL, 0, key_len,
- ssl->ctx->quic_method != nullptr)) {
+ "key", 3, NULL, 0, key_len)) {
return false;
}
@@ -178,8 +167,7 @@
size_t iv_len = EVP_AEAD_nonce_length(aead);
uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, "iv",
- 2, NULL, 0, iv_len,
- ssl->ctx->quic_method != nullptr)) {
+ 2, NULL, 0, iv_len)) {
return false;
}
@@ -249,16 +237,16 @@
}
ssl->s3->early_exporter_secret_len = hs->hash_len;
- if (ssl->ctx->quic_method != nullptr) {
+ if (ssl->quic_method != nullptr) {
if (ssl->server) {
- if (!ssl->ctx->quic_method->set_encryption_secrets(
+ if (!ssl->quic_method->set_encryption_secrets(
ssl, ssl_encryption_early_data, nullptr, hs->early_traffic_secret,
hs->hash_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
return false;
}
} else {
- if (!ssl->ctx->quic_method->set_encryption_secrets(
+ if (!ssl->quic_method->set_encryption_secrets(
ssl, ssl_encryption_early_data, hs->early_traffic_secret, nullptr,
hs->hash_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
@@ -285,16 +273,16 @@
return false;
}
- if (ssl->ctx->quic_method != nullptr) {
+ if (ssl->quic_method != nullptr) {
if (ssl->server) {
- if (!ssl->ctx->quic_method->set_encryption_secrets(
+ if (!ssl->quic_method->set_encryption_secrets(
ssl, ssl_encryption_handshake, hs->client_handshake_secret,
hs->server_handshake_secret, hs->hash_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
return false;
}
} else {
- if (!ssl->ctx->quic_method->set_encryption_secrets(
+ if (!ssl->quic_method->set_encryption_secrets(
ssl, ssl_encryption_handshake, hs->server_handshake_secret,
hs->client_handshake_secret, hs->hash_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
@@ -326,16 +314,16 @@
return false;
}
- if (ssl->ctx->quic_method != nullptr) {
+ if (ssl->quic_method != nullptr) {
if (ssl->server) {
- if (!ssl->ctx->quic_method->set_encryption_secrets(
+ if (!ssl->quic_method->set_encryption_secrets(
ssl, ssl_encryption_application, hs->client_traffic_secret_0,
hs->server_traffic_secret_0, hs->hash_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
return false;
}
} else {
- if (!ssl->ctx->quic_method->set_encryption_secrets(
+ if (!ssl->quic_method->set_encryption_secrets(
ssl, ssl_encryption_application, hs->server_traffic_secret_0,
hs->client_traffic_secret_0, hs->hash_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
@@ -364,7 +352,7 @@
if (!hkdf_expand_label(secret, digest, secret, secret_len,
kTLS13LabelApplicationTraffic,
strlen(kTLS13LabelApplicationTraffic), NULL, 0,
- secret_len, ssl->ctx->quic_method != nullptr)) {
+ secret_len)) {
return false;
}
@@ -392,13 +380,11 @@
static bool tls13_verify_data(const EVP_MD *digest, uint16_t version,
uint8_t *out, size_t *out_len,
const uint8_t *secret, size_t hash_len,
- uint8_t *context, size_t context_len,
- bool use_quic) {
+ uint8_t *context, size_t context_len) {
uint8_t key[EVP_MAX_MD_SIZE];
unsigned len;
if (!hkdf_expand_label(key, digest, secret, hash_len, kTLS13LabelFinished,
- strlen(kTLS13LabelFinished), NULL, 0, hash_len,
- use_quic) ||
+ strlen(kTLS13LabelFinished), NULL, 0, hash_len) ||
HMAC(digest, key, hash_len, context, context_len, out, &len) == NULL) {
return false;
}
@@ -420,8 +406,7 @@
if (!hs->transcript.GetHash(context_hash, &context_hash_len) ||
!tls13_verify_data(hs->transcript.Digest(), hs->ssl->version, out,
out_len, traffic_secret, hs->hash_len, context_hash,
- context_hash_len,
- hs->ssl->ctx->quic_method != nullptr)) {
+ context_hash_len)) {
return 0;
}
return 1;
@@ -429,13 +414,12 @@
static const char kTLS13LabelResumptionPSK[] = "resumption";
-bool tls13_derive_session_psk(SSL_SESSION *session, Span<const uint8_t> nonce,
- bool use_quic) {
+bool tls13_derive_session_psk(SSL_SESSION *session, Span<const uint8_t> nonce) {
const EVP_MD *digest = ssl_session_get_digest(session);
return hkdf_expand_label(session->master_key, digest, session->master_key,
session->master_key_length, kTLS13LabelResumptionPSK,
strlen(kTLS13LabelResumptionPSK), nonce.data(),
- nonce.size(), session->master_key_length, use_quic);
+ nonce.size(), session->master_key_length);
}
static const char kTLS13LabelExportKeying[] = "exporter";
@@ -464,12 +448,11 @@
nullptr) &&
hkdf_expand_label(derived_secret, digest, secret.data(), secret.size(),
label.data(), label.size(), export_context,
- export_context_len, derived_secret_len,
- ssl->ctx->quic_method != nullptr) &&
+ export_context_len, derived_secret_len) &&
hkdf_expand_label(out.data(), digest, derived_secret,
derived_secret_len, kTLS13LabelExportKeying,
strlen(kTLS13LabelExportKeying), hash, hash_len,
- out.size(), ssl->ctx->quic_method != nullptr);
+ out.size());
}
static const char kTLS13LabelPSKBinder[] = "res binder";
@@ -477,7 +460,7 @@
static bool tls13_psk_binder(uint8_t *out, uint16_t version,
const EVP_MD *digest, uint8_t *psk, size_t psk_len,
uint8_t *context, size_t context_len,
- size_t hash_len, bool use_quic) {
+ size_t hash_len) {
uint8_t binder_context[EVP_MAX_MD_SIZE];
unsigned binder_context_len;
if (!EVP_Digest(NULL, 0, binder_context, &binder_context_len, digest, NULL)) {
@@ -495,10 +478,9 @@
size_t len;
if (!hkdf_expand_label(binder_key, digest, early_secret, hash_len,
kTLS13LabelPSKBinder, strlen(kTLS13LabelPSKBinder),
- binder_context, binder_context_len, hash_len,
- use_quic) ||
+ binder_context, binder_context_len, hash_len) ||
!tls13_verify_data(digest, version, out, &len, binder_key, hash_len,
- context, context_len, use_quic)) {
+ context, context_len)) {
return false;
}
@@ -531,7 +513,7 @@
if (!tls13_psk_binder(verify_data, ssl->session->ssl_version, digest,
ssl->session->master_key,
ssl->session->master_key_length, context, context_len,
- hash_len, ssl->ctx->quic_method != nullptr)) {
+ hash_len)) {
return false;
}
@@ -563,8 +545,7 @@
CBS binder;
if (!tls13_psk_binder(verify_data, hs->ssl->version, hs->transcript.Digest(),
session->master_key, session->master_key_length,
- context, context_len, hash_len,
- hs->ssl->ctx->quic_method != nullptr) ||
+ context, context_len, hash_len) ||
// We only consider the first PSK, so compare against the first binder.
!CBS_get_u8_length_prefixed(binders, &binder)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 7073b57..caaf0c7 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -17,6 +17,8 @@
#include <assert.h>
#include <string.h>
+#include <tuple>
+
#include <openssl/aead.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
@@ -95,6 +97,37 @@
return 1;
}
+// CipherScorer produces a "score" for each possible cipher suite offered by
+// the client.
+class CipherScorer {
+ public:
+ CipherScorer(uint16_t group_id)
+ : aes_is_fine_(EVP_has_aes_hardware()),
+ security_128_is_fine_(group_id != SSL_CURVE_CECPQ2) {}
+
+ typedef std::tuple<bool, bool, bool> Score;
+
+ // MinScore returns a |Score| that will compare less than the score of all
+ // cipher suites.
+ Score MinScore() const {
+ return Score(false, false, false);
+ }
+
+ Score Evaluate(const SSL_CIPHER *a) const {
+ return Score(
+ // Something is always preferable to nothing.
+ true,
+ // Either 128-bit is fine, or 256-bit is preferred.
+ security_128_is_fine_ || a->algorithm_enc != SSL_AES128GCM,
+ // Either AES is fine, or else ChaCha20 is preferred.
+ aes_is_fine_ || a->algorithm_enc == SSL_CHACHA20POLY1305);
+ }
+
+ private:
+ const bool aes_is_fine_;
+ const bool security_128_is_fine_;
+};
+
static const SSL_CIPHER *choose_tls13_cipher(
const SSL *ssl, const SSL_CLIENT_HELLO *client_hello, uint16_t group_id) {
if (client_hello->cipher_suites_len % 2 != 0) {
@@ -105,11 +138,12 @@
CBS_init(&cipher_suites, client_hello->cipher_suites,
client_hello->cipher_suites_len);
- const bool aes_is_fine = EVP_has_aes_hardware();
- const bool require_256_bit = group_id == SSL_CURVE_CECPQ2;
const uint16_t version = ssl_protocol_version(ssl);
const SSL_CIPHER *best = nullptr;
+ CipherScorer scorer(group_id);
+ CipherScorer::Score best_score = scorer.MinScore();
+
while (CBS_len(&cipher_suites) > 0) {
uint16_t cipher_suite;
if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
@@ -124,23 +158,12 @@
continue;
}
- // Post-quantum key exchanges should be paired with 256-bit ciphers.
- if (require_256_bit && candidate->algorithm_enc == SSL_AES128GCM) {
- continue;
- }
-
- // TLS 1.3 removes legacy ciphers, so honor the client order, but prefer
- // ChaCha20 if we do not have AES hardware.
- if (aes_is_fine) {
- return candidate;
- }
-
- if (candidate->algorithm_enc == SSL_CHACHA20POLY1305) {
- return candidate;
- }
-
- if (best == nullptr) {
+ const CipherScorer::Score candidate_score = scorer.Evaluate(candidate);
+ // |candidate_score| must be larger to displace the current choice. That way
+ // the client's order controls between ciphers with an equal score.
+ if (candidate_score > best_score) {
best = candidate;
+ best_score = candidate_score;
}
}
@@ -194,8 +217,7 @@
!CBB_add_u8_length_prefixed(&body, &nonce_cbb) ||
!CBB_add_bytes(&nonce_cbb, nonce, sizeof(nonce)) ||
!CBB_add_u16_length_prefixed(&body, &ticket) ||
- !tls13_derive_session_psk(session.get(), nonce,
- ssl->ctx->quic_method != nullptr) ||
+ !tls13_derive_session_psk(session.get(), nonce) ||
!ssl_encrypt_ticket(hs, &ticket, session.get()) ||
!CBB_add_u16_length_prefixed(&body, &extensions)) {
return false;
@@ -663,7 +685,7 @@
// Send the server Certificate message, if necessary.
if (!ssl->s3->session_reused) {
- if (!ssl_has_certificate(hs->config)) {
+ if (!ssl_has_certificate(hs)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
return ssl_hs_error;
}