From 2eb6f2af1ea3bc272fc91131dbcf11e1d6c6761e Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 24 Nov 2017 14:27:31 +0000 Subject: [PATCH] Update bogo to latest version for draft22 tests --- .../google/boringssl/ssl/test/LICENSE | 28 +- .../google/boringssl/ssl/test/bssl_shim.cc | 98 +- .../google/boringssl/ssl/test/fuzzer.h | 413 +- .../google/boringssl/ssl/test/fuzzer_tags.h | 45 + .../ssl/test/runner/cipher_suites.go | 25 +- .../boringssl/ssl/test/runner/common.go | 181 +- .../google/boringssl/ssl/test/runner/conn.go | 221 +- .../google/boringssl/ssl/test/runner/dtls.go | 136 +- .../ssl/test/runner/fuzzer_mode.json | 20 +- .../ssl/test/runner/handshake_client.go | 166 +- .../ssl/test/runner/handshake_messages.go | 439 ++- .../ssl/test/runner/handshake_server.go | 208 +- .../ssl/test/runner/key_agreement.go | 61 +- .../google/boringssl/ssl/test/runner/prf.go | 96 +- .../ssl/test/runner/recordingconn.go | 4 + .../boringssl/ssl/test/runner/runner.go | 3486 ++++++++++------- .../google/boringssl/ssl/test/test_config.cc | 5 +- .../google/boringssl/ssl/test/test_config.h | 4 +- vendor/manifest | 2 +- 19 files changed, 3574 insertions(+), 2064 deletions(-) create mode 100644 vendor/github.com/google/boringssl/ssl/test/fuzzer_tags.h diff --git a/vendor/github.com/google/boringssl/ssl/test/LICENSE b/vendor/github.com/google/boringssl/ssl/test/LICENSE index a25996f..ff4116f 100644 --- a/vendor/github.com/google/boringssl/ssl/test/LICENSE +++ b/vendor/github.com/google/boringssl/ssl/test/LICENSE @@ -6,7 +6,9 @@ Contributors to BoringSSL are required to follow the CLA rules for Chromium: https://cla.developers.google.com/clas Some files from Intel are under yet another license, which is also included -underneath. +underneath. Files in third_party/ have their own licenses, as described +therein. The MIT license, for third_party/fiat, which, unlike other third_party +directories, is compiled into non-test libraries, is included below. The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the OpenSSL License and the original SSLeay license apply to the toolkit. See below @@ -190,3 +192,27 @@ Some files from Intel carry the following license: # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +The code in third_party/fiat carries the MIT license: + +Copyright (c) 2015-2016 the fiat-crypto authors (see +https://github.com/mit-plv/fiat-crypto/blob/master/AUTHORS). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/google/boringssl/ssl/test/bssl_shim.cc b/vendor/github.com/google/boringssl/ssl/test/bssl_shim.cc index 0c97438..8acabd7 100644 --- a/vendor/github.com/google/boringssl/ssl/test/bssl_shim.cc +++ b/vendor/github.com/google/boringssl/ssl/test/bssl_shim.cc @@ -56,6 +56,7 @@ OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib")) #include #include +#include #include #include #include @@ -63,7 +64,7 @@ OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib")) #include "../../crypto/internal.h" #include "../internal.h" #include "async_bio.h" -#include "fuzzer.h" +#include "fuzzer_tags.h" #include "packeted_bio.h" #include "test_config.h" @@ -432,10 +433,7 @@ static ssl_private_key_result_t AsyncPrivateKeyComplete( } static const SSL_PRIVATE_KEY_METHOD g_async_private_key_method = { - nullptr /* type */, - nullptr /* max_signature_len */, AsyncPrivateKeySign, - nullptr /* sign_digest */, AsyncPrivateKeyDecrypt, AsyncPrivateKeyComplete, }; @@ -452,27 +450,6 @@ static bool GetCertificate(SSL *ssl, bssl::UniquePtr *out_x509, bssl::UniquePtr *out_pkey) { const TestConfig *config = GetTestConfig(ssl); - if (!config->digest_prefs.empty()) { - bssl::UniquePtr digest_prefs( - OPENSSL_strdup(config->digest_prefs.c_str())); - std::vector digest_list; - - for (;;) { - char *token = - strtok(digest_list.empty() ? digest_prefs.get() : nullptr, ","); - if (token == nullptr) { - break; - } - - digest_list.push_back(EVP_MD_type(EVP_get_digestbyname(token))); - } - - if (!SSL_set_private_key_digest_prefs(ssl, digest_list.data(), - digest_list.size())) { - return false; - } - } - if (!config->signing_prefs.empty()) { std::vector u16s(config->signing_prefs.begin(), config->signing_prefs.end()); @@ -854,7 +831,7 @@ static void ChannelIdCallback(SSL *ssl, EVP_PKEY **out_pkey) { *out_pkey = GetTestState(ssl)->channel_id.release(); } -static SSL_SESSION *GetSessionCallback(SSL *ssl, uint8_t *data, int len, +static SSL_SESSION *GetSessionCallback(SSL *ssl, const uint8_t *data, int len, int *copy) { TestState *async_state = GetTestState(ssl); if (async_state->session) { @@ -1100,7 +1077,6 @@ static void MessageCallback(int is_write, int version, int content_type, // Connect returns a new socket connected to localhost on |port| or -1 on // error. static int Connect(uint16_t port) { - time_t start_time = time(nullptr); for (int af : { AF_INET6, AF_INET }) { int sock = socket(af, SOCK_STREAM, 0); if (sock == -1) { @@ -1147,11 +1123,6 @@ static int Connect(uint16_t port) { } PrintSocketError("connect"); - // TODO(davidben): Remove this logging when https://crbug.com/boringssl/199 is - // resolved. - fprintf(stderr, "start_time = %lld, end_time = %lld\n", - static_cast(start_time), - static_cast(time(nullptr))); return -1; } @@ -1283,6 +1254,9 @@ static bssl::UniquePtr SetupCtx(SSL_CTX *old_ctx, if (!config->use_client_ca_list.empty()) { if (config->use_client_ca_list == "") { SSL_CTX_set_client_CA_list(ssl_ctx.get(), nullptr); + } else if (config->use_client_ca_list == "") { + bssl::UniquePtr names; + SSL_CTX_set_client_CA_list(ssl_ctx.get(), names.release()); } else { bssl::UniquePtr names = DecodeHexX509Names(config->use_client_ca_list); @@ -1408,6 +1382,32 @@ static bool RetryAsync(SSL *ssl, int ret) { } } +// CheckIdempotentError runs |func|, an operation on |ssl|, ensuring that +// errors are idempotent. +static int CheckIdempotentError(const char *name, SSL *ssl, + std::function func) { + int ret = func(); + int ssl_err = SSL_get_error(ssl, ret); + uint32_t err = ERR_peek_error(); + if (ssl_err == SSL_ERROR_SSL || ssl_err == SSL_ERROR_ZERO_RETURN) { + int ret2 = func(); + int ssl_err2 = SSL_get_error(ssl, ret2); + uint32_t err2 = ERR_peek_error(); + if (ret != ret2 || ssl_err != ssl_err2 || err != err2) { + fprintf(stderr, "Repeating %s did not replay the error.\n", name); + char buf[256]; + ERR_error_string_n(err, buf, sizeof(buf)); + fprintf(stderr, "Wanted: %d %d %s\n", ret, ssl_err, buf); + ERR_error_string_n(err2, buf, sizeof(buf)); + fprintf(stderr, "Got: %d %d %s\n", ret2, ssl_err2, buf); + // runner treats exit code 90 as always failing. Otherwise, it may + // accidentally consider the result an expected protocol failure. + exit(90); + } + } + return ret; +} + // DoRead reads from |ssl|, resolving any asynchronous operations. It returns // the result value of the final |SSL_read| call. static int DoRead(SSL *ssl, uint8_t *out, size_t max_out) { @@ -1421,8 +1421,10 @@ static int DoRead(SSL *ssl, uint8_t *out, size_t max_out) { // trigger a retransmit, so disconnect the write quota. AsyncBioEnforceWriteQuota(test_state->async_bio, false); } - ret = config->peek_then_read ? SSL_peek(ssl, out, max_out) - : SSL_read(ssl, out, max_out); + ret = CheckIdempotentError("SSL_peek/SSL_read", ssl, [&]() -> int { + return config->peek_then_read ? SSL_peek(ssl, out, max_out) + : SSL_read(ssl, out, max_out); + }); if (config->async) { AsyncBioEnforceWriteQuota(test_state->async_bio, true); } @@ -2163,13 +2165,21 @@ static bool DoExchange(bssl::UniquePtr *out_session, SSL *ssl, int ret; if (!config->implicit_handshake) { do { - ret = SSL_do_handshake(ssl); + ret = CheckIdempotentError("SSL_do_handshake", ssl, [&]() -> int { + return SSL_do_handshake(ssl); + }); } while (config->async && RetryAsync(ssl, ret)); if (ret != 1 || !CheckHandshakeProperties(ssl, is_resume, config)) { return false; } + if (is_resume && !is_retry && !config->is_server && + config->expect_no_offer_early_data && SSL_in_early_data(ssl)) { + fprintf(stderr, "Client unexpectedly offered early data.\n"); + return false; + } + if (config->handshake_twice) { do { ret = SSL_do_handshake(ssl); @@ -2365,14 +2375,13 @@ static bool DoExchange(bssl::UniquePtr *out_session, SSL *ssl, } if (expect_new_session) { - bool got_early_data_info = + bool got_early_data = GetTestState(ssl)->new_session->ticket_max_early_data != 0; - if (config->expect_early_data_info != got_early_data_info) { - fprintf( - stderr, - "new session did%s include ticket_early_data_info, but we expected " - "the opposite\n", - got_early_data_info ? "" : " not"); + if (config->expect_ticket_supports_early_data != got_early_data) { + fprintf(stderr, + "new session did%s support early data, but we expected the " + "opposite\n", + got_early_data ? "" : " not"); return false; } } @@ -2407,6 +2416,11 @@ static bool DoExchange(bssl::UniquePtr *out_session, SSL *ssl, return false; } + if (SSL_session_reused(ssl)) { + fprintf(stderr, "Renegotiations should never resume sessions.\n"); + return false; + } + // Re-check authentication properties after a renegotiation. The reported // values should remain unchanged even if the server sent different SCT // lists. diff --git a/vendor/github.com/google/boringssl/ssl/test/fuzzer.h b/vendor/github.com/google/boringssl/ssl/test/fuzzer.h index e52f55e..c794c4c 100644 --- a/vendor/github.com/google/boringssl/ssl/test/fuzzer.h +++ b/vendor/github.com/google/boringssl/ssl/test/fuzzer.h @@ -15,104 +15,46 @@ #ifndef HEADER_SSL_TEST_FUZZER #define HEADER_SSL_TEST_FUZZER +#include +#include +#include + +#include + +#include #include +#include +#include +#include +#include #include +#include + +#include "./fuzzer_tags.h" -// SSL fuzzer utilities. -// -// The TLS client and server fuzzers coordinate with bssl_shim on a common -// format to encode configuration parameters in a fuzzer file. To add a new -// configuration, define a tag, update |SetupTest| below to parse it, and -// update |WriteSettings| in bssl_shim to serialize it. Finally, record -// transcripts from a test run, and use the BORINGSSL_FUZZER_DEBUG environment -// variable to confirm the transcripts are compatible. +namespace { -// kDataTag denotes that the remainder of the input should be passed to the TLS -// stack. -static const uint16_t kDataTag = 0; +const uint8_t kP256KeyPKCS8[] = { + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, 0xfa, 0x16, 0xdf, + 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, 0x91, 0x95, 0xab, + 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, 0x44, 0x03, 0x42, + 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, 0x37, 0x9a, 0xd5, + 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, 0x20, 0xcb, 0x90, + 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, 0xc0, 0xdb, 0xba, + 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, 0x61, 0x99, 0x73, + 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, 0x0d, 0x10, 0xa7, + 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec, +}; -// kSessionTag is followed by a u24-length-prefixed serialized SSL_SESSION to -// resume. -static const uint16_t kSessionTag = 1; +const uint8_t kOCSPResponse[] = {0x01, 0x02, 0x03, 0x04}; -// kRequestClientCert denotes that the server should request client -// certificates. -static const uint16_t kRequestClientCert = 2; +const uint8_t kSCT[] = {0x00, 0x06, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08}; -// kTLS13Variant is followed by a u8 denoting the TLS 1.3 variant to configure. -static const uint16_t kTLS13Variant = 3; - -// SetupTest parses parameters from |cbs| and returns a newly-configured |SSL| -// object or nullptr on error. On success, the caller should feed the remaining -// input in |cbs| to the SSL stack. -static inline bssl::UniquePtr SetupTest(CBS *cbs, SSL_CTX *ctx, - bool is_server) { - // |ctx| is shared between runs, so we must clear any modifications to it made - // later on in this function. - SSL_CTX_flush_sessions(ctx, 0); - - bssl::UniquePtr ssl(SSL_new(ctx)); - if (is_server) { - SSL_set_accept_state(ssl.get()); - } else { - SSL_set_connect_state(ssl.get()); - } - - for (;;) { - uint16_t tag; - if (!CBS_get_u16(cbs, &tag)) { - return nullptr; - } - switch (tag) { - case kDataTag: - return ssl; - - case kSessionTag: { - CBS data; - if (!CBS_get_u24_length_prefixed(cbs, &data)) { - return nullptr; - } - bssl::UniquePtr session( - SSL_SESSION_from_bytes(CBS_data(&data), CBS_len(&data), ctx)); - if (!session) { - return nullptr; - } - - if (is_server) { - SSL_CTX_add_session(ctx, session.get()); - } else { - SSL_set_session(ssl.get(), session.get()); - } - break; - } - - case kRequestClientCert: - if (!is_server) { - return nullptr; - } - 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(variant)); - break; - } - - default: - return nullptr; - } - } -} - - -// Additional shared constants. - -static const uint8_t kCertificateDER[] = { +const uint8_t kCertificateDER[] = { 0x30, 0x82, 0x02, 0xff, 0x30, 0x82, 0x01, 0xe7, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0xb1, 0x84, 0xee, 0x34, 0x99, 0x98, 0x76, 0xfb, 0x6f, 0xb2, 0x15, 0xc8, 0x47, 0x79, 0x05, 0x9b, 0x30, 0x0d, 0x06, 0x09, @@ -180,7 +122,7 @@ static const uint8_t kCertificateDER[] = { 0x76, 0x8a, 0xbb, }; -static const uint8_t kRSAPrivateKeyDER[] = { +const uint8_t kRSAPrivateKeyDER[] = { 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xce, 0x47, 0xcb, 0x11, 0xbb, 0xd2, 0x9d, 0x8e, 0x9e, 0xd2, 0x1e, 0x14, 0xaf, 0xc7, 0xea, 0xb6, 0xc9, 0x38, 0x2a, 0x6f, 0xb3, 0x7e, 0xfb, 0xbc, @@ -283,5 +225,294 @@ static const uint8_t kRSAPrivateKeyDER[] = { 0x98, 0x46, 0x89, 0x82, 0x40, }; +const uint8_t kALPNProtocols[] = { + 0x01, 'a', 0x02, 'a', 'a', 0x03, 'a', 'a', 'a', +}; + +int ALPNSelectCallback(SSL *ssl, const uint8_t **out, uint8_t *out_len, + const uint8_t *in, unsigned in_len, void *arg) { + static const uint8_t kProtocol[] = {'a', 'a'}; + *out = kProtocol; + *out_len = sizeof(kProtocol); + return SSL_TLSEXT_ERR_OK; +} + +int NPNSelectCallback(SSL *ssl, uint8_t **out, uint8_t *out_len, + const uint8_t *in, unsigned in_len, void *arg) { + static const uint8_t kProtocol[] = {'a', 'a'}; + *out = const_cast(kProtocol); + *out_len = sizeof(kProtocol); + return SSL_TLSEXT_ERR_OK; +} + +int NPNAdvertiseCallback(SSL *ssl, const uint8_t **out, unsigned *out_len, + void *arg) { + static const uint8_t kProtocols[] = { + 0x01, 'a', 0x02, 'a', 'a', 0x03, 'a', 'a', 'a', + }; + *out = kProtocols; + *out_len = sizeof(kProtocols); + return SSL_TLSEXT_ERR_OK; +} + +class TLSFuzzer { + public: + enum Protocol { + kTLS, + kDTLS, + }; + + enum Role { + kClient, + kServer, + }; + + TLSFuzzer(Protocol protocol, Role role) + : debug_(getenv("BORINGSSL_FUZZER_DEBUG") != nullptr), + protocol_(protocol), + role_(role) { + if (!Init()) { + abort(); + } + } + + int TestOneInput(const uint8_t *buf, size_t len) { + RAND_reset_for_fuzzing(); + + CBS cbs; + CBS_init(&cbs, buf, len); + bssl::UniquePtr ssl = SetupTest(&cbs); + if (!ssl) { + if (debug_) { + fprintf(stderr, "Error parsing parameters.\n"); + } + return 0; + } + + if (role_ == kClient) { + SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_freely); + SSL_set_tlsext_host_name(ssl.get(), "hostname"); + } + + SSL_set0_rbio(ssl.get(), MakeBIO(CBS_data(&cbs), CBS_len(&cbs)).release()); + SSL_set0_wbio(ssl.get(), BIO_new(BIO_s_mem())); + + if (SSL_do_handshake(ssl.get()) == 1) { + // Keep reading application data until error or EOF. + uint8_t tmp[1024]; + for (;;) { + if (SSL_read(ssl.get(), tmp, sizeof(tmp)) <= 0) { + break; + } + } + } else if (debug_) { + fprintf(stderr, "Handshake failed.\n"); + } + + if (debug_) { + ERR_print_errors_fp(stderr); + } + ERR_clear_error(); + return 0; + } + + private: + // Init initializes |ctx_| with settings common to all inputs. + bool Init() { + ctx_.reset(SSL_CTX_new(protocol_ == kDTLS ? DTLS_method() : TLS_method())); + bssl::UniquePtr pkey(EVP_PKEY_new()); + bssl::UniquePtr privkey(RSA_private_key_from_bytes( + kRSAPrivateKeyDER, sizeof(kRSAPrivateKeyDER))); + if (!ctx_ || !privkey || !pkey || + !EVP_PKEY_set1_RSA(pkey.get(), privkey.get()) || + !SSL_CTX_use_PrivateKey(ctx_.get(), pkey.get())) { + return false; + } + + const uint8_t *bufp = kCertificateDER; + bssl::UniquePtr cert(d2i_X509(NULL, &bufp, sizeof(kCertificateDER))); + if (!cert || + !SSL_CTX_use_certificate(ctx_.get(), cert.get()) || + !SSL_CTX_set_ocsp_response(ctx_.get(), kOCSPResponse, + sizeof(kOCSPResponse)) || + !SSL_CTX_set_signed_cert_timestamp_list(ctx_.get(), kSCT, + sizeof(kSCT))) { + return false; + } + + // When accepting peer certificates, allow any certificate. + SSL_CTX_set_cert_verify_callback( + ctx_.get(), + [](X509_STORE_CTX *store_ctx, void *arg) -> int { return 1; }, nullptr); + + SSL_CTX_enable_signed_cert_timestamps(ctx_.get()); + SSL_CTX_enable_ocsp_stapling(ctx_.get()); + + // Enable versions and ciphers that are off by default. + if (!SSL_CTX_set_strict_cipher_list(ctx_.get(), "ALL:NULL-SHA")) { + return false; + } + if (protocol_ == kTLS) { + if (!SSL_CTX_set_max_proto_version(ctx_.get(), TLS1_3_VERSION) || + !SSL_CTX_set_min_proto_version(ctx_.get(), SSL3_VERSION)) { + return false; + } + } + + SSL_CTX_set_early_data_enabled(ctx_.get(), 1); + + SSL_CTX_set_next_proto_select_cb(ctx_.get(), NPNSelectCallback, nullptr); + SSL_CTX_set_next_protos_advertised_cb(ctx_.get(), NPNAdvertiseCallback, + nullptr); + + SSL_CTX_set_alpn_select_cb(ctx_.get(), ALPNSelectCallback, nullptr); + if (SSL_CTX_set_alpn_protos(ctx_.get(), kALPNProtocols, + sizeof(kALPNProtocols)) != 0) { + return false; + } + + CBS cbs; + CBS_init(&cbs, kP256KeyPKCS8, sizeof(kP256KeyPKCS8)); + pkey.reset(EVP_parse_private_key(&cbs)); + if (!pkey || !SSL_CTX_set1_tls_channel_id(ctx_.get(), pkey.get())) { + return false; + } + SSL_CTX_set_tls_channel_id_enabled(ctx_.get(), 1); + + return true; + } + + // SetupTest parses parameters from |cbs| and returns a newly-configured |SSL| + // object or nullptr on error. On success, the caller should feed the + // remaining input in |cbs| to the SSL stack. + bssl::UniquePtr SetupTest(CBS *cbs) { + // |ctx| is shared between runs, so we must clear any modifications to it + // made later on in this function. + SSL_CTX_flush_sessions(ctx_.get(), 0); + + bssl::UniquePtr ssl(SSL_new(ctx_.get())); + if (role_ == kServer) { + SSL_set_accept_state(ssl.get()); + } else { + SSL_set_connect_state(ssl.get()); + } + + for (;;) { + uint16_t tag; + if (!CBS_get_u16(cbs, &tag)) { + return nullptr; + } + switch (tag) { + case kDataTag: + return ssl; + + case kSessionTag: { + CBS data; + if (!CBS_get_u24_length_prefixed(cbs, &data)) { + return nullptr; + } + bssl::UniquePtr session(SSL_SESSION_from_bytes( + CBS_data(&data), CBS_len(&data), ctx_.get())); + if (!session) { + return nullptr; + } + + if (role_ == kServer) { + SSL_CTX_add_session(ctx_.get(), session.get()); + } else { + SSL_set_session(ssl.get(), session.get()); + } + break; + } + + case kRequestClientCert: + if (role_ == kClient) { + return nullptr; + } + 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(variant)); + break; + } + + default: + return nullptr; + } + } + } + + struct BIOData { + Protocol protocol; + CBS cbs; + }; + + bssl::UniquePtr MakeBIO(const uint8_t *in, size_t len) { + BIOData *b = new BIOData; + b->protocol = protocol_; + CBS_init(&b->cbs, in, len); + + bssl::UniquePtr bio(BIO_new(&kBIOMethod)); + bio->init = 1; + bio->ptr = b; + return bio; + } + + static int BIORead(BIO *bio, char *out, int len) { + assert(bio->method == &kBIOMethod); + BIOData *b = reinterpret_cast(bio->ptr); + if (b->protocol == kTLS) { + len = std::min(static_cast(len), CBS_len(&b->cbs)); + memcpy(out, CBS_data(&b->cbs), len); + CBS_skip(&b->cbs, len); + return len; + } + + // Preserve packet boundaries for DTLS. + CBS packet; + if (!CBS_get_u24_length_prefixed(&b->cbs, &packet)) { + return -1; + } + len = std::min(static_cast(len), CBS_len(&packet)); + memcpy(out, CBS_data(&packet), len); + return len; + } + + static int BIODestroy(BIO *bio) { + assert(bio->method == &kBIOMethod); + BIOData *b = reinterpret_cast(bio->ptr); + delete b; + return 1; + } + + static const BIO_METHOD kBIOMethod; + + bool debug_; + Protocol protocol_; + Role role_; + bssl::UniquePtr ctx_; +}; + +const BIO_METHOD TLSFuzzer::kBIOMethod = { + 0, // type + nullptr, // name + nullptr, // bwrite + TLSFuzzer::BIORead, + nullptr, // bputs + nullptr, // bgets + nullptr, // ctrl + nullptr, // create + TLSFuzzer::BIODestroy, + nullptr, // callback_ctrl +}; + +} // namespace + #endif // HEADER_SSL_TEST_FUZZER diff --git a/vendor/github.com/google/boringssl/ssl/test/fuzzer_tags.h b/vendor/github.com/google/boringssl/ssl/test/fuzzer_tags.h new file mode 100644 index 0000000..b161d80 --- /dev/null +++ b/vendor/github.com/google/boringssl/ssl/test/fuzzer_tags.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2017, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef HEADER_SSL_TEST_FUZZER_TAGS +#define HEADER_SSL_TEST_FUZZER_TAGS + +#include + + +// SSL fuzzer tag constants. +// +// The TLS client and server fuzzers coordinate with bssl_shim on a common +// format to encode configuration parameters in a fuzzer file. To add a new +// configuration, define a tag, update |SetupTest| in fuzzer.h to parse it, and +// update |WriteSettings| in bssl_shim to serialize it. Finally, record +// transcripts from a test run, and use the BORINGSSL_FUZZER_DEBUG environment +// variable to confirm the transcripts are compatible. + +// kDataTag denotes that the remainder of the input should be passed to the TLS +// stack. +static const uint16_t kDataTag = 0; + +// kSessionTag is followed by a u24-length-prefixed serialized SSL_SESSION to +// resume. +static const uint16_t kSessionTag = 1; + +// kRequestClientCert denotes that the server should request client +// 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; + +#endif // HEADER_SSL_TEST_FUZZER_TAGS diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/cipher_suites.go b/vendor/github.com/google/boringssl/ssl/test/runner/cipher_suites.go index 2490bee..f4c5900 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/cipher_suites.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/cipher_suites.go @@ -11,7 +11,6 @@ import ( "crypto/des" "crypto/hmac" "crypto/md5" - "crypto/rc4" "crypto/sha1" "crypto/sha256" "crypto/sha512" @@ -48,8 +47,6 @@ const ( // client indicates that it supports ECC with a curve and point format // that we're happy with. suiteECDHE = 1 << iota - // suiteDHE indicates that the cipher suite involves Diffie-Hellman. - suiteDHE // suiteECDSA indicates that the cipher suite involves an ECDSA // signature and therefore may only be selected when the server's // certificate is ECDSA. If this is not set then the cipher suite is @@ -64,9 +61,6 @@ const ( // suiteSHA384 indicates that the cipher suite uses SHA384 as the // handshake hash. suiteSHA384 - // suiteNoDTLS indicates that the cipher suite cannot be used - // in DTLS. - suiteNoDTLS // suitePSK indicates that the cipher suite authenticates with // a pre-shared key rather than a server private key. suitePSK @@ -101,8 +95,6 @@ func (cs cipherSuite) hash() crypto.Hash { } var cipherSuites = []*cipherSuite{ - // Ciphersuite order is chosen so that ECDHE comes before plain RSA - // and RC4 comes before AES (because of the Lucky13 attack). {TLS_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, nil, suiteTLS13, nil, nil, aeadCHACHA20POLY1305}, {TLS_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, nil, suiteTLS13, nil, nil, aeadAESGCM}, {TLS_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, nil, suiteTLS13 | suiteSHA384, nil, nil, aeadAESGCM}, @@ -112,8 +104,6 @@ var cipherSuites = []*cipherSuite{ {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM}, {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, - {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, noIV, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil}, - {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, noIV, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil}, {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil}, {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, @@ -124,8 +114,6 @@ var cipherSuites = []*cipherSuite{ {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil}, {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, - {TLS_RSA_WITH_RC4_128_SHA, 16, 20, noIV, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil}, - {TLS_RSA_WITH_RC4_128_MD5, 16, 16, noIV, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil}, {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, {TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, ivLenAES, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, rsaKA, 0, cipherAES, macSHA1, nil}, @@ -135,10 +123,9 @@ var cipherSuites = []*cipherSuite{ {TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadCHACHA20POLY1305}, {TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil}, {TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil}, - {TLS_PSK_WITH_RC4_128_SHA, 16, 20, noIV, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil}, {TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, pskKA, suitePSK, cipherAES, macSHA1, nil}, {TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, pskKA, suitePSK, cipherAES, macSHA1, nil}, - {TLS_RSA_WITH_NULL_SHA, 0, 20, noIV, rsaKA, suiteNoDTLS, cipherNull, macSHA1, nil}, + {TLS_RSA_WITH_NULL_SHA, 0, 20, noIV, rsaKA, 0, cipherNull, macSHA1, nil}, } func noIV(vers uint16) int { @@ -170,11 +157,6 @@ func cipherNull(key, iv []byte, isRead bool) interface{} { return nullCipher{} } -func cipherRC4(key, iv []byte, isRead bool) interface{} { - cipher, _ := rc4.NewCipher(key) - return cipher -} - func cipher3DES(key, iv []byte, isRead bool) interface{} { block, _ := des.NewTripleDESCipher(key) if isRead { @@ -450,22 +432,17 @@ func cipherSuiteFromID(id uint16) *cipherSuite { // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml const ( TLS_RSA_WITH_NULL_SHA uint16 = 0x0002 - TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004 - TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003d - TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008a TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008c TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008d TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d - TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a - TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014 diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/common.go b/vendor/github.com/google/boringssl/ssl/test/runner/common.go index 7244527..0216401 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/common.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/common.go @@ -33,22 +33,30 @@ const ( // A draft version of TLS 1.3 that is sent over the wire for the current draft. const ( - tls13DraftVersion = 0x7f12 - tls13ExperimentVersion = 0x7e01 - tls13RecordTypeExperimentVersion = 0x7a12 + tls13DraftVersion = 0x7f12 + tls13Draft21Version = 0x7f15 + tls13ExperimentVersion = 0x7e01 + tls13Experiment2Version = 0x7e02 + tls13Experiment3Version = 0x7e03 + tls13Draft22Version = 0x7e04 ) const ( - TLS13Default = 0 - TLS13Experiment = 1 - TLS13RecordTypeExperiment = 2 - TLS13NoSessionIDExperiment = 3 + TLS13Default = 0 + TLS13Experiment = 1 + TLS13Experiment2 = 2 + TLS13Experiment3 = 3 + TLS13Draft21 = 4 + TLS13Draft22 = 5 ) var allTLSWireVersions = []uint16{ tls13DraftVersion, + tls13Draft22Version, + tls13Draft21Version, + tls13Experiment3Version, + tls13Experiment2Version, tls13ExperimentVersion, - tls13RecordTypeExperimentVersion, VersionTLS12, VersionTLS11, VersionTLS10, @@ -89,6 +97,7 @@ const ( typeServerHello uint8 = 2 typeHelloVerifyRequest uint8 = 3 typeNewSessionTicket uint8 = 4 + typeEndOfEarlyData uint8 = 5 // draft-ietf-tls-tls13-21 typeHelloRetryRequest uint8 = 6 // draft-ietf-tls-tls13-16 typeEncryptedExtensions uint8 = 8 // draft-ietf-tls-tls13-16 typeCertificate uint8 = 11 @@ -102,6 +111,7 @@ const ( typeKeyUpdate uint8 = 24 // draft-ietf-tls-tls13-16 typeNextProtocol uint8 = 67 // Not IANA assigned typeChannelID uint8 = 203 // Not IANA assigned + typeMessageHash uint8 = 254 // draft-ietf-tls-tls13-21 ) // TLS compression types. @@ -119,6 +129,7 @@ const ( extensionUseSRTP uint16 = 14 extensionALPN uint16 = 16 extensionSignedCertificateTimestamp uint16 = 18 + extensionPadding uint16 = 21 extensionExtendedMasterSecret uint16 = 23 extensionSessionTicket uint16 = 35 extensionKeyShare uint16 = 40 // draft-ietf-tls-tls13-16 @@ -128,6 +139,7 @@ const ( extensionCookie uint16 = 44 // draft-ietf-tls-tls13-16 extensionPSKKeyExchangeModes uint16 = 45 // draft-ietf-tls-tls13-18 extensionTicketEarlyDataInfo uint16 = 46 // draft-ietf-tls-tls13-18 + extensionCertificateAuthorities uint16 = 47 // draft-ietf-tls-tls13-21 extensionCustom uint16 = 1234 // not IANA assigned extensionNextProtoNeg uint16 = 13172 // not IANA assigned extensionRenegotiationInfo uint16 = 0xff01 @@ -139,6 +151,12 @@ const ( scsvRenegotiation uint16 = 0x00ff ) +var tls13HelloRetryRequest = []uint8{ + 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, + 0x02, 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, + 0x8c, 0x5e, 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, +} + // CurveID is the type of a TLS identifier for an elliptic curve. See // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 type CurveID uint16 @@ -275,6 +293,7 @@ type ClientSessionState struct { sessionId []uint8 // Session ID supplied by the server. nil if the session has a ticket. sessionTicket []uint8 // Encrypted ticket used for session resumption with server vers uint16 // SSL/TLS version negotiated for the session + wireVersion uint16 // Wire SSL/TLS version negotiated for the session cipherSuite uint16 // Ciphersuite negotiated for the session masterSecret []byte // MasterSecret generated by client on a full handshake handshakeHash []byte // Handshake hash for Channel ID purposes. @@ -452,8 +471,7 @@ type Config struct { // MaxEarlyDataSize controls the maximum number of bytes that the // server will accept in early data and advertise in a // NewSessionTicketMsg. If 0, no early data will be accepted and - // the TicketEarlyDataInfo extension in the NewSessionTicketMsg - // will be omitted. + // the early_data extension in the NewSessionTicketMsg will be omitted. MaxEarlyDataSize uint32 // SRTPProtectionProfiles, if not nil, is the list of SRTP @@ -493,7 +511,11 @@ const ( RSABadValueCorrupt RSABadValueTooLong RSABadValueTooShort - RSABadValueWrongVersion + RSABadValueWrongVersion1 + RSABadValueWrongVersion2 + RSABadValueWrongBlockType + RSABadValueWrongLeadingByte + RSABadValueNoZero NumRSABadValues ) @@ -556,6 +578,10 @@ type ProtocolBugs struct { // NewSessionTicket message despite promising to in ServerHello. SkipNewSessionTicket bool + // UseFirstSessionTicket causes the client to cache only the first session + // ticket received. + UseFirstSessionTicket bool + // SkipClientCertificate causes the client to skip the Certificate // message. SkipClientCertificate bool @@ -569,18 +595,22 @@ type ProtocolBugs struct { // message. SkipFinished bool - // SkipEndOfEarlyData causes the implementation to skip the - // end_of_early_data alert. + // SkipEndOfEarlyData causes the implementation to skip + // end_of_early_data. SkipEndOfEarlyData bool + // NonEmptyEndOfEarlyData causes the implementation to end an extra byte in the + // EndOfEarlyData. + NonEmptyEndOfEarlyData bool + // SkipCertificateVerify, if true causes peer to skip sending a // CertificateVerify message after the Certificate message. SkipCertificateVerify bool // EarlyChangeCipherSpec causes the client to send an early // ChangeCipherSpec message before the ClientKeyExchange. A value of - // zero disables this behavior. One and two configure variants for 0.9.8 - // and 1.0.1 modes, respectively. + // zero disables this behavior. One and two configure variants for + // 1.0.1 and 0.9.8 modes, respectively. EarlyChangeCipherSpec int // StrayChangeCipherSpec causes every pre-ChangeCipherSpec handshake @@ -598,6 +628,14 @@ type ProtocolBugs struct { // messages. FragmentAcrossChangeCipherSpec bool + // SendExtraChangeCipherSpec causes the implementation to send extra + // ChangeCipherSpec messages. + SendExtraChangeCipherSpec int + + // SendPostHandshakeChangeCipherSpec causes the implementation to send + // a ChangeCipherSpec record before every application data record. + SendPostHandshakeChangeCipherSpec bool + // SendUnencryptedFinished, if true, causes the Finished message to be // send unencrypted before ChangeCipherSpec rather than after it. SendUnencryptedFinished bool @@ -735,10 +773,6 @@ type ProtocolBugs struct { // connection if there is not a SessionID in the ClientHello. ExpectClientHelloSessionID bool - // ExpectEmptyClientHelloSessionID, if true, causes the server to fail the - // connection if there is a SessionID in the ClientHello. - ExpectEmptyClientHelloSessionID bool - // ExpectNoTLS12Session, if true, causes the server to fail the // connection if either a session ID or TLS 1.2 ticket is offered. ExpectNoTLS12Session bool @@ -747,6 +781,10 @@ type ProtocolBugs struct { // if a TLS 1.3 PSK is offered. ExpectNoTLS13PSK bool + // ExpectNoTLS13PSKAfterHRR, if true, causes the server to fail the connection + // if a TLS 1.3 PSK is offered after HRR. + ExpectNoTLS13PSKAfterHRR bool + // RequireExtendedMasterSecret, if true, requires that the peer support // the extended master secret option. RequireExtendedMasterSecret bool @@ -948,10 +986,22 @@ type ProtocolBugs struct { // record size. PackHandshakeFragments int - // PackHandshakeRecords, if true, causes handshake records in DTLS to be - // packed into individual packets, up to the specified packet size. + // PackHandshakeRecords, if non-zero, causes handshake and + // ChangeCipherSpec records in DTLS to be packed into individual + // packets, up to the specified packet size. PackHandshakeRecords int + // PackAppDataWithHandshake, if true, extends PackHandshakeRecords to + // additionally include the first application data record sent after the + // final Finished message in a handshake. (If the final Finished message + // is sent by the peer, this option has no effect.) This requires that + // the runner rather than shim speak first in a given test. + PackAppDataWithHandshake bool + + // SplitAndPackAppData, if true, causes application data in DTLS to be + // split into two records each and packed into one packet. + SplitAndPackAppData bool + // PackHandshakeFlight, if true, causes each handshake flight in TLS to // be packed into records, up to the largest size record available. PackHandshakeFlight bool @@ -1034,13 +1084,13 @@ type ProtocolBugs struct { // receipt of a NewSessionTicket message. ExpectNoNewSessionTicket bool - // DuplicateTicketEarlyDataInfo causes an extra empty extension of - // ticket_early_data_info to be sent in NewSessionTicket. - DuplicateTicketEarlyDataInfo bool + // DuplicateTicketEarlyData causes an extra empty extension of early_data to + // be sent in NewSessionTicket. + DuplicateTicketEarlyData bool - // ExpectTicketEarlyDataInfo, if true, means that the client will fail upon - // absence of the ticket_early_data_info extension. - ExpectTicketEarlyDataInfo bool + // ExpectTicketEarlyData, if true, means that the client will fail upon + // absence of the early_data extension. + ExpectTicketEarlyData bool // ExpectTicketAge, if non-zero, is the expected age of the ticket that the // server receives from the client. @@ -1288,6 +1338,10 @@ type ProtocolBugs struct { // the specified curve in a HelloRetryRequest. SendHelloRetryRequestCurve CurveID + // SendHelloRetryRequestCipherSuite, if non-zero, causes the server to send + // the specified cipher suite in a HelloRetryRequest. + SendHelloRetryRequestCipherSuite uint16 + // SendHelloRetryRequestCookie, if not nil, contains a cookie to be // sent by the server in HelloRetryRequest. SendHelloRetryRequestCookie []byte @@ -1325,6 +1379,14 @@ type ProtocolBugs struct { // a TLS 1.3 CertificateRequest. SendRequestContext []byte + // OmitCertificateRequestAlgorithms, if true, omits the signature_algorithm + // extension in a TLS 1.3 CertificateRequest. + OmitCertificateRequestAlgorithms bool + + // SendCustomCertificateRequest, if non-zero, send an additional custom + // extension in a TLS 1.3 CertificateRequest. + SendCustomCertificateRequest uint16 + // SendSNIWarningAlert, if true, causes the server to send an // unrecognized_name alert before the ServerHello. SendSNIWarningAlert bool @@ -1386,6 +1448,12 @@ type ProtocolBugs struct { // empty slice, no extension will be sent. SendSupportedPointFormats []byte + // SendServerSupportedCurves, if true, causes the server to send its + // supported curves list in the ServerHello (TLS 1.2) or + // EncryptedExtensions (TLS 1.3) message. This is invalid in TLS 1.2 and + // valid in TLS 1.3. + SendServerSupportedCurves bool + // MaxReceivePlaintext, if non-zero, is the maximum plaintext record // length accepted from the peer. MaxReceivePlaintext int @@ -1406,6 +1474,10 @@ type ProtocolBugs struct { // renegotiation handshakes. RenegotiationCertificate *Certificate + // ExpectNoCertificateAuthoritiesExtension, if true, causes the client to + // reject CertificateRequest with the CertificateAuthorities extension. + ExpectNoCertificateAuthoritiesExtension bool + // UseLegacySigningAlgorithm, if non-zero, is the signature algorithm // to use when signing in TLS 1.1 and earlier where algorithms are not // negotiated. @@ -1434,6 +1506,10 @@ type ProtocolBugs struct { // ExpectRecordSplitting, if true, causes application records to only be // accepted if they follow a 1/n-1 record split. ExpectRecordSplitting bool + + // PadClientHello, if non-zero, pads the ClientHello to a multiple of + // that many bytes. + PadClientHello int } func (c *Config) serverInit() { @@ -1534,12 +1610,59 @@ func (c *Config) defaultCurves() map[CurveID]bool { return defaultCurves } +func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) { + if isDTLS { + switch vers { + case VersionDTLS12: + return VersionTLS12, true + case VersionDTLS10: + return VersionTLS10, true + } + } else { + switch vers { + case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12: + return vers, true + case tls13DraftVersion, tls13Draft22Version, tls13Draft21Version, tls13ExperimentVersion, tls13Experiment2Version, tls13Experiment3Version: + return VersionTLS13, true + } + } + + return 0, false +} + +func isDraft21(vers uint16) bool { + return vers == tls13Draft21Version || vers == tls13Draft22Version +} + +func isDraft22(vers uint16) bool { + return vers == tls13Draft22Version +} + +func isResumptionExperiment(vers uint16) bool { + return vers == tls13ExperimentVersion || vers == tls13Experiment2Version || vers == tls13Experiment3Version || vers == tls13Draft22Version +} + +func isResumptionClientCCSExperiment(vers uint16) bool { + return vers == tls13ExperimentVersion || vers == tls13Experiment2Version || vers == tls13Draft22Version +} + +func isResumptionRecordVersionExperiment(vers uint16) bool { + return vers == tls13Experiment2Version || vers == tls13Experiment3Version || vers == tls13Draft22Version +} + +func isResumptionRecordVersionVariant(variant int) bool { + return variant == TLS13Experiment2 || variant == TLS13Experiment3 || variant == TLS13Draft22 +} + // isSupportedVersion checks if the specified wire version is acceptable. If so, // it returns true and the corresponding protocol version. Otherwise, it returns // false. func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) { - if (c.TLS13Variant != TLS13Experiment && c.TLS13Variant != TLS13NoSessionIDExperiment && wireVers == tls13ExperimentVersion) || - (c.TLS13Variant != TLS13RecordTypeExperiment && wireVers == tls13RecordTypeExperimentVersion) || + if (c.TLS13Variant != TLS13Experiment && wireVers == tls13ExperimentVersion) || + (c.TLS13Variant != TLS13Experiment2 && wireVers == tls13Experiment2Version) || + (c.TLS13Variant != TLS13Experiment3 && wireVers == tls13Experiment3Version) || + (c.TLS13Variant != TLS13Draft22 && wireVers == tls13Draft22Version) || + (c.TLS13Variant != TLS13Draft21 && wireVers == tls13Draft21Version) || (c.TLS13Variant != TLS13Default && wireVers == tls13DraftVersion) { return 0, false } diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/conn.go b/vendor/github.com/google/boringssl/ssl/test/runner/conn.go index 2332e6b..21f491a 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/conn.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/conn.go @@ -96,10 +96,13 @@ type Conn struct { handMsg []byte // pending assembled handshake message handMsgLen int // handshake message length, not including the header pendingFragments [][]byte // pending outgoing handshake fragments. + pendingPacket []byte // pending outgoing packet. keyUpdateRequested bool seenOneByteRecord bool + expectTLS13ChangeCipherSpec bool + tmp [16]byte } @@ -151,14 +154,15 @@ func (c *Conn) SetWriteDeadline(t time.Time) error { type halfConn struct { sync.Mutex - err error // first permanent error - version uint16 // protocol version - isDTLS bool - cipher interface{} // cipher algorithm - mac macFunction - seq [8]byte // 64-bit sequence number - outSeq [8]byte // Mapped sequence number - bfree *block // list of free blocks + err error // first permanent error + version uint16 // protocol version + wireVersion uint16 // wire version + isDTLS bool + cipher interface{} // cipher algorithm + mac macFunction + seq [8]byte // 64-bit sequence number + outSeq [8]byte // Mapped sequence number + bfree *block // list of free blocks nextCipher interface{} // next encryption state nextMac macFunction // next MAC algorithm @@ -188,7 +192,12 @@ func (hc *halfConn) error() error { // prepareCipherSpec sets the encryption and MAC states // that a subsequent changeCipherSpec will use. func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) { - hc.version = version + hc.wireVersion = version + protocolVersion, ok := wireToVersion(version, hc.isDTLS) + if !ok { + panic("TLS: unknown version") + } + hc.version = protocolVersion hc.nextCipher = cipher hc.nextMac = mac } @@ -215,7 +224,12 @@ func (hc *halfConn) changeCipherSpec(config *Config) error { // useTrafficSecret sets the current cipher state for TLS 1.3. func (hc *halfConn) useTrafficSecret(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) { - hc.version = version + hc.wireVersion = version + protocolVersion, ok := wireToVersion(version, hc.isDTLS) + if !ok { + panic("TLS: unknown version") + } + hc.version = protocolVersion hc.cipher = deriveTrafficAEAD(version, suite, secret, side) if hc.config.Bugs.NullAllCiphers { hc.cipher = nullCipher{} @@ -232,14 +246,6 @@ func (hc *halfConn) resetCipher() { hc.incEpoch() } -func (hc *halfConn) doKeyUpdate(c *Conn, isOutgoing bool) { - side := serverWrite - if c.isClient == isOutgoing { - side = clientWrite - } - hc.useTrafficSecret(hc.version, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), hc.trafficSecret), side) -} - // incSeq increments the sequence number. func (hc *halfConn) incSeq(isOutgoing bool) { limit := 0 @@ -725,6 +731,26 @@ func (hc *halfConn) splitBlock(b *block, n int) (*block, *block) { return b, bb } +func (c *Conn) useInTrafficSecret(version uint16, suite *cipherSuite, secret []byte) error { + if c.hand.Len() != 0 { + return c.in.setErrorLocked(errors.New("tls: buffered handshake messages on cipher change")) + } + side := serverWrite + if !c.isClient { + side = clientWrite + } + c.in.useTrafficSecret(version, suite, secret, side) + return nil +} + +func (c *Conn) useOutTrafficSecret(version uint16, suite *cipherSuite, secret []byte) { + side := serverWrite + if c.isClient { + side = clientWrite + } + c.out.useTrafficSecret(version, suite, secret, side) +} + func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) { RestartReadRecord: if c.isDTLS { @@ -763,11 +789,6 @@ RestartReadRecord: return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received")) } - // Accept server_plaintext_handshake records when the content type TLS 1.3 variant is enabled. - if c.isClient && c.in.cipher == nil && c.config.TLS13Variant == TLS13RecordTypeExperiment && want == recordTypeHandshake && typ == recordTypePlaintextHandshake { - typ = recordTypeHandshake - } - vers := uint16(b.data[1])<<8 | uint16(b.data[2]) n := int(b.data[3])<<8 | int(b.data[4]) @@ -781,6 +802,9 @@ RestartReadRecord: if c.vers >= VersionTLS13 { expect = VersionTLS10 } + if isResumptionRecordVersionExperiment(c.wireVersion) { + expect = VersionTLS12 + } } else { expect = c.config.Bugs.ExpectInitialRecordVersion } @@ -855,6 +879,47 @@ RestartReadRecord: return typ, b, nil } +func (c *Conn) readTLS13ChangeCipherSpec() error { + if !c.expectTLS13ChangeCipherSpec { + panic("c.expectTLS13ChangeCipherSpec not set") + } + + // Read the ChangeCipherSpec. + if c.rawInput == nil { + c.rawInput = c.in.newBlock() + } + b := c.rawInput + if err := b.readFromUntil(c.conn, 1); err != nil { + return c.in.setErrorLocked(fmt.Errorf("tls: error reading TLS 1.3 ChangeCipherSpec: %s", err)) + } + if recordType(b.data[0]) == recordTypeAlert { + // If the client is sending an alert, allow the ChangeCipherSpec + // to be skipped. It may be rejecting a sufficiently malformed + // ServerHello that it can't parse out the version. + c.expectTLS13ChangeCipherSpec = false + return nil + } + if err := b.readFromUntil(c.conn, 6); err != nil { + return c.in.setErrorLocked(fmt.Errorf("tls: error reading TLS 1.3 ChangeCipherSpec: %s", err)) + } + + // Check they match that we expect. + expected := [6]byte{byte(recordTypeChangeCipherSpec), 3, 1, 0, 1, 1} + if isResumptionRecordVersionExperiment(c.wireVersion) { + expected[2] = 3 + } + if !bytes.Equal(b.data[:6], expected[:]) { + return c.in.setErrorLocked(fmt.Errorf("tls: error invalid TLS 1.3 ChangeCipherSpec: %x", b.data[:6])) + } + + // Discard the data. + b, c.rawInput = c.in.splitBlock(b, 6) + c.in.freeBlock(b) + + c.expectTLS13ChangeCipherSpec = false + return nil +} + // readRecord reads the next TLS record from the connection // and updates the record layer state. // c.in.Mutex <= L; c.input == nil. @@ -875,6 +940,12 @@ func (c *Conn) readRecord(want recordType) error { break } + if c.expectTLS13ChangeCipherSpec { + if err := c.readTLS13ChangeCipherSpec(); err != nil { + return err + } + } + Again: typ, b, err := c.doReadRecord(want) if err != nil { @@ -929,11 +1000,12 @@ Again: c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) break } - if c.wireVersion != tls13ExperimentVersion { - err := c.in.changeCipherSpec(c.config) - if err != nil { - c.in.setErrorLocked(c.sendAlert(err.(alert))) - } + if c.hand.Len() != 0 { + c.in.setErrorLocked(errors.New("tls: buffered handshake messages on cipher change")) + break + } + if err := c.in.changeCipherSpec(c.config); err != nil { + c.in.setErrorLocked(c.sendAlert(err.(alert))) } case recordTypeApplicationData: @@ -1063,6 +1135,12 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { return 0, err } + if typ == recordTypeApplicationData && c.config.Bugs.SendPostHandshakeChangeCipherSpec { + if _, err := c.doWriteRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { + return 0, err + } + } + return c.doWriteRecord(typ, data) } @@ -1125,6 +1203,10 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) { // layer to {3, 1}. vers = VersionTLS10 } + if isResumptionRecordVersionExperiment(c.wireVersion) || isResumptionRecordVersionExperiment(c.out.wireVersion) { + vers = VersionTLS12 + } + if c.config.Bugs.SendRecordVersion != 0 { vers = c.config.Bugs.SendRecordVersion } @@ -1156,7 +1238,7 @@ func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) { } c.out.freeBlock(b) - if typ == recordTypeChangeCipherSpec && c.wireVersion != tls13ExperimentVersion { + if typ == recordTypeChangeCipherSpec && !isResumptionExperiment(c.wireVersion) { err = c.out.changeCipherSpec(c.config) if err != nil { return n, c.sendAlertLocked(alertLevelError, err.(alert)) @@ -1244,7 +1326,8 @@ func (c *Conn) readHandshake() (interface{}, error) { m = new(helloRetryRequestMsg) case typeNewSessionTicket: m = &newSessionTicketMsg{ - version: c.vers, + vers: c.wireVersion, + isDTLS: c.isDTLS, } case typeEncryptedExtensions: m = new(encryptedExtensionsMsg) @@ -1254,6 +1337,7 @@ func (c *Conn) readHandshake() (interface{}, error) { } case typeCertificateRequest: m = &certificateRequestMsg{ + vers: c.wireVersion, hasSignatureAlgorithm: c.vers >= VersionTLS12, hasRequestContext: c.vers >= VersionTLS13, } @@ -1279,6 +1363,8 @@ func (c *Conn) readHandshake() (interface{}, error) { m = new(channelIDMsg) case typeKeyUpdate: m = new(keyUpdateMsg) + case typeEndOfEarlyData: + m = new(endOfEarlyDataMsg) default: return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) } @@ -1288,6 +1374,14 @@ func (c *Conn) readHandshake() (interface{}, error) { // so pass in a fresh copy that won't be overwritten. data = append([]byte(nil), data...) + if data[0] == typeServerHello && len(data) >= 38 { + vers := uint16(data[4])<<8 | uint16(data[5]) + if vers == VersionTLS12 && bytes.Equal(data[6:38], tls13HelloRetryRequest) { + m = new(helloRetryRequestMsg) + m.(*helloRetryRequestMsg).isServerHello = true + } + } + if !m.unmarshal(data) { return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) } @@ -1386,10 +1480,6 @@ func (c *Conn) Write(b []byte) (int, error) { c.out.Lock() defer c.out.Unlock() - // Flush any pending handshake data. PackHelloRequestWithFinished may - // have been set and the handshake not followed by Renegotiate. - c.flushHandshake() - if err := c.out.err; err != nil { return 0, err } @@ -1443,8 +1533,8 @@ func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMs return errors.New("tls: no GREASE ticket extension found") } - if c.config.Bugs.ExpectTicketEarlyDataInfo && newSessionTicket.maxEarlyDataSize == 0 { - return errors.New("tls: no ticket_early_data_info extension found") + if c.config.Bugs.ExpectTicketEarlyData && newSessionTicket.maxEarlyDataSize == 0 { + return errors.New("tls: no early_data ticket extension found") } if c.config.Bugs.ExpectNoNewSessionTicket { @@ -1458,6 +1548,7 @@ func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMs session := &ClientSessionState{ sessionTicket: newSessionTicket.ticket, vers: c.vers, + wireVersion: c.wireVersion, cipherSuite: cipherSuite.id, masterSecret: c.resumptionSecret, serverCertificates: c.peerCertificates, @@ -1470,8 +1561,15 @@ func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMs earlyALPN: c.clientProtocol, } + if isDraft21(c.wireVersion) { + session.masterSecret = deriveSessionPSK(cipherSuite, c.wireVersion, c.resumptionSecret, newSessionTicket.ticketNonce) + } + cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config) - c.config.ClientSessionCache.Put(cacheKey, session) + _, ok := c.config.ClientSessionCache.Get(cacheKey) + if !ok || !c.config.Bugs.UseFirstSessionTicket { + c.config.ClientSessionCache.Put(cacheKey, session) + } return nil } @@ -1507,7 +1605,9 @@ func (c *Conn) handlePostHandshakeMessage() error { if c.config.Bugs.RejectUnsolicitedKeyUpdate { return errors.New("tls: unexpected KeyUpdate message") } - c.in.doKeyUpdate(c, false) + if err := c.useInTrafficSecret(c.in.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.wireVersion, c.in.trafficSecret)); err != nil { + return err + } if keyUpdate.keyUpdateRequest == keyUpdateRequested { c.keyUpdateRequested = true } @@ -1539,8 +1639,7 @@ func (c *Conn) ReadKeyUpdateACK() error { return errors.New("tls: received invalid KeyUpdate message") } - c.in.doKeyUpdate(c, false) - return nil + return c.useInTrafficSecret(c.in.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.wireVersion, c.in.trafficSecret)) } func (c *Conn) Renegotiate() error { @@ -1758,9 +1857,16 @@ func (c *Conn) ExportKeyingMaterial(length int, label, context []byte, useContex } if c.vers >= VersionTLS13 { - // TODO(davidben): What should we do with useContext? See - // https://github.com/tlswg/tls13-spec/issues/546 - return hkdfExpandLabel(c.cipherSuite.hash(), c.exporterSecret, label, context, length), nil + if isDraft21(c.wireVersion) { + hash := c.cipherSuite.hash() + exporterKeyingLabel := []byte("exporter") + contextHash := hash.New() + contextHash.Write(context) + exporterContext := hash.New().Sum(nil) + derivedSecret := hkdfExpandLabel(c.cipherSuite.hash(), c.wireVersion, c.exporterSecret, label, exporterContext, hash.Size()) + return hkdfExpandLabel(c.cipherSuite.hash(), c.wireVersion, derivedSecret, exporterKeyingLabel, contextHash.Sum(nil), length), nil + } + return hkdfExpandLabel(c.cipherSuite.hash(), c.wireVersion, c.exporterSecret, label, context, length), nil } seedLen := len(c.clientRandom) + len(c.serverRandom) @@ -1794,7 +1900,7 @@ func (c *Conn) noRenegotiationInfo() bool { return false } -func (c *Conn) SendNewSessionTicket() error { +func (c *Conn) SendNewSessionTicket(nonce []byte) error { if c.isClient || c.vers < VersionTLS13 { return errors.New("tls: cannot send post-handshake NewSessionTicket") } @@ -1814,12 +1920,17 @@ func (c *Conn) SendNewSessionTicket() error { // TODO(davidben): Allow configuring these values. m := &newSessionTicketMsg{ - version: c.vers, - ticketLifetime: uint32(24 * time.Hour / time.Second), - duplicateEarlyDataInfo: c.config.Bugs.DuplicateTicketEarlyDataInfo, - customExtension: c.config.Bugs.CustomTicketExtension, - ticketAgeAdd: ticketAgeAdd, - maxEarlyDataSize: c.config.MaxEarlyDataSize, + vers: c.wireVersion, + isDTLS: c.isDTLS, + ticketLifetime: uint32(24 * time.Hour / time.Second), + duplicateEarlyDataExtension: c.config.Bugs.DuplicateTicketEarlyData, + customExtension: c.config.Bugs.CustomTicketExtension, + ticketAgeAdd: ticketAgeAdd, + maxEarlyDataSize: c.config.MaxEarlyDataSize, + } + + if isDraft21(c.wireVersion) { + m.ticketNonce = nonce } if c.config.Bugs.SendTicketLifetime != 0 { @@ -1837,6 +1948,10 @@ func (c *Conn) SendNewSessionTicket() error { earlyALPN: []byte(c.clientProtocol), } + if isDraft21(c.wireVersion) { + state.masterSecret = deriveSessionPSK(c.cipherSuite, c.wireVersion, c.resumptionSecret, nonce) + } + if !c.config.Bugs.SendEmptySessionTicket { var err error m.ticket, err = c.encryptTicket(&state) @@ -1870,7 +1985,7 @@ func (c *Conn) sendKeyUpdateLocked(keyUpdateRequest byte) error { if err := c.flushHandshake(); err != nil { return err } - c.out.doKeyUpdate(c, true) + c.useOutTrafficSecret(c.out.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.wireVersion, c.out.trafficSecret)) return nil } @@ -1881,6 +1996,10 @@ func (c *Conn) sendFakeEarlyData(len int) error { payload[0] = byte(recordTypeApplicationData) payload[1] = 3 payload[2] = 1 + if isResumptionRecordVersionVariant(c.config.TLS13Variant) { + payload[1] = 3 + payload[2] = 3 + } payload[3] = byte(len >> 8) payload[4] = byte(len) _, err := c.conn.Write(payload) diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/dtls.go b/vendor/github.com/google/boringssl/ssl/test/runner/dtls.go index c81955e..b97f829 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/dtls.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/dtls.go @@ -23,26 +23,6 @@ import ( "net" ) -func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) { - if isDTLS { - switch vers { - case VersionDTLS12: - return VersionTLS12, true - case VersionDTLS10: - return VersionTLS10, true - } - } else { - switch vers { - case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12: - return vers, true - case tls13DraftVersion, tls13ExperimentVersion, tls13RecordTypeExperimentVersion: - return VersionTLS13, true - } - } - - return 0, false -} - func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) { recordHeaderLen := dtlsRecordHeaderLen @@ -149,25 +129,37 @@ func (c *Conn) makeFragment(header, data []byte, fragOffset, fragLen int) []byte } func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) { + // Only handshake messages are fragmented. if typ != recordTypeHandshake { reorder := typ == recordTypeChangeCipherSpec && c.config.Bugs.ReorderChangeCipherSpec - // Flush pending handshake messages before writing a new record. + // Flush pending handshake messages before encrypting a new record. if !reorder { - err = c.dtlsFlushHandshake() + err = c.dtlsPackHandshake() if err != nil { return } } - // Only handshake messages are fragmented. - n, err = c.dtlsWriteRawRecord(typ, data) - if err != nil { - return + if typ == recordTypeApplicationData && len(data) > 1 && c.config.Bugs.SplitAndPackAppData { + _, err = c.dtlsPackRecord(typ, data[:len(data)/2], false) + if err != nil { + return + } + _, err = c.dtlsPackRecord(typ, data[len(data)/2:], true) + if err != nil { + return + } + n = len(data) + } else { + n, err = c.dtlsPackRecord(typ, data, false) + if err != nil { + return + } } if reorder { - err = c.dtlsFlushHandshake() + err = c.dtlsPackHandshake() if err != nil { return } @@ -178,12 +170,19 @@ func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) { if err != nil { return n, c.sendAlertLocked(alertLevelError, err.(alert)) } + } else { + // ChangeCipherSpec is part of the handshake and not + // flushed until dtlsFlushPacket. + err = c.dtlsFlushPacket() + if err != nil { + return + } } return } if c.out.cipher == nil && c.config.Bugs.StrayChangeCipherSpec { - _, err = c.dtlsWriteRawRecord(recordTypeChangeCipherSpec, []byte{1}) + _, err = c.dtlsPackRecord(recordTypeChangeCipherSpec, []byte{1}, false) if err != nil { return } @@ -209,8 +208,8 @@ func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) { isFinished := header[0] == typeFinished if c.config.Bugs.SendEmptyFragments { - fragment := c.makeFragment(header, data, 0, 0) - c.pendingFragments = append(c.pendingFragments, fragment) + c.pendingFragments = append(c.pendingFragments, c.makeFragment(header, data, 0, 0)) + c.pendingFragments = append(c.pendingFragments, c.makeFragment(header, data, len(data), 0)) } firstRun := true @@ -263,7 +262,9 @@ func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) { return } -func (c *Conn) dtlsFlushHandshake() error { +// dtlsPackHandshake packs the pending handshake flight into the pending +// record. Callers should follow up with dtlsFlushPacket to write the packets. +func (c *Conn) dtlsPackHandshake() error { // This is a test-only DTLS implementation, so there is no need to // retain |c.pendingFragments| for a future retransmit. var fragments [][]byte @@ -285,7 +286,6 @@ func (c *Conn) dtlsFlushHandshake() error { } maxRecordLen := c.config.Bugs.PackHandshakeFragments - maxPacketLen := c.config.Bugs.PackHandshakeRecords // Pack handshake fragments into records. var records [][]byte @@ -305,42 +305,39 @@ func (c *Conn) dtlsFlushHandshake() error { } } - // Format them into packets. - var packets [][]byte + // Send the records. for _, record := range records { - b, err := c.dtlsSealRecord(recordTypeHandshake, record) + _, err := c.dtlsPackRecord(recordTypeHandshake, record, false) if err != nil { return err } - - if i := len(packets) - 1; len(packets) > 0 && len(packets[i])+len(b.data) <= maxPacketLen { - packets[i] = append(packets[i], b.data...) - } else { - // The sealed record will be appended to and reused by - // |c.out|, so copy it. - packets = append(packets, append([]byte{}, b.data...)) - } - c.out.freeBlock(b) } - // Send all the packets. - for _, packet := range packets { - if _, err := c.conn.Write(packet); err != nil { - return err - } - } return nil } -// dtlsSealRecord seals a record into a block from |c.out|'s pool. -func (c *Conn) dtlsSealRecord(typ recordType, data []byte) (b *block, err error) { +func (c *Conn) dtlsFlushHandshake() error { + if err := c.dtlsPackHandshake(); err != nil { + return err + } + if err := c.dtlsFlushPacket(); err != nil { + return err + } + + return nil +} + +// dtlsPackRecord packs a single record to the pending packet, flushing it +// if necessary. The caller should call dtlsFlushPacket to flush the current +// pending packet afterwards. +func (c *Conn) dtlsPackRecord(typ recordType, data []byte, mustPack bool) (n int, err error) { recordHeaderLen := dtlsRecordHeaderLen maxLen := c.config.Bugs.MaxHandshakeRecordLength if maxLen <= 0 { maxLen = 1024 } - b = c.out.newBlock() + b := c.out.newBlock() explicitIVLen := 0 explicitIVIsSeq := false @@ -392,23 +389,30 @@ func (c *Conn) dtlsSealRecord(typ recordType, data []byte) (b *block, err error) } copy(b.data[recordHeaderLen+explicitIVLen:], data) c.out.encrypt(b, explicitIVLen, typ) + + // Flush the current pending packet if necessary. + if !mustPack && len(b.data)+len(c.pendingPacket) > c.config.Bugs.PackHandshakeRecords { + err = c.dtlsFlushPacket() + if err != nil { + c.out.freeBlock(b) + return + } + } + + // Add the record to the pending packet. + c.pendingPacket = append(c.pendingPacket, b.data...) + c.out.freeBlock(b) + n = len(data) return } -func (c *Conn) dtlsWriteRawRecord(typ recordType, data []byte) (n int, err error) { - b, err := c.dtlsSealRecord(typ, data) - if err != nil { - return +func (c *Conn) dtlsFlushPacket() error { + if len(c.pendingPacket) == 0 { + return nil } - - _, err = c.conn.Write(b.data) - if err != nil { - return - } - n = len(data) - - c.out.freeBlock(b) - return + _, err := c.conn.Write(c.pendingPacket) + c.pendingPacket = nil + return err } func (c *Conn) dtlsDoReadHandshake() ([]byte, error) { diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/fuzzer_mode.json b/vendor/github.com/google/boringssl/ssl/test/runner/fuzzer_mode.json index 9fa49b5..fd029d3 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/fuzzer_mode.json +++ b/vendor/github.com/google/boringssl/ssl/test/runner/fuzzer_mode.json @@ -35,17 +35,17 @@ "Resume-Server-*Binder*": "Fuzzer mode does not check binders.", "SkipEarlyData*": "Trial decryption does not work with the NULL cipher.", - "*-EarlyDataChannelID-OfferBoth-Server": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-NonZeroRTTSession-Server": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-SkipEndOfEarlyData": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-ALPNMismatch-Server": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-ALPNOmitted1-Client": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-ALPNOmitted2-Client": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-ALPNOmitted1-Server": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-ALPNOmitted2-Server": "Trial decryption does not work with the NULL cipher.", + "EarlyDataChannelID-OfferBoth-Server-*": "Trial decryption does not work with the NULL cipher.", + "EarlyData-NonZeroRTTSession-Server-*": "Trial decryption does not work with the NULL cipher.", + "EarlyData-SkipEndOfEarlyData-*": "Trial decryption does not work with the NULL cipher.", + "EarlyData-ALPNMismatch-Server-*": "Trial decryption does not work with the NULL cipher.", + "EarlyData-ALPNOmitted1-Client-*": "Trial decryption does not work with the NULL cipher.", + "EarlyData-ALPNOmitted2-Client-*": "Trial decryption does not work with the NULL cipher.", + "EarlyData-ALPNOmitted1-Server-*": "Trial decryption does not work with the NULL cipher.", + "EarlyData-ALPNOmitted2-Server-*": "Trial decryption does not work with the NULL cipher.", "*-EarlyData-RejectUnfinishedWrite-Client-*": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-Reject-Client": "Trial decryption does not work with the NULL cipher.", - "*-EarlyData-RejectTicket-Client": "Trial decryption does not work with the NULL cipher.", + "EarlyData-Reject-Client-*": "Trial decryption does not work with the NULL cipher.", + "EarlyData-RejectTicket-Client-*": "Trial decryption does not work with the NULL cipher.", "Renegotiate-Client-BadExt*": "Fuzzer mode does not check renegotiation_info.", diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/handshake_client.go b/vendor/github.com/google/boringssl/ssl/test/runner/handshake_client.go index 83f2d7d..5f22ecd 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/handshake_client.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/handshake_client.go @@ -211,10 +211,6 @@ NextCipherSuite: if maxVersion < VersionTLS12 && suite.flags&suiteTLS12 != 0 { continue } - // Don't advertise non-DTLS cipher suites in DTLS. - if c.isDTLS && suite.flags&suiteNoDTLS != 0 { - continue - } hello.cipherSuites = append(hello.cipherSuites, suiteId) continue NextCipherSuite } @@ -376,7 +372,14 @@ NextCipherSuite: c.writeV2Record(helloBytes) } else { if len(hello.pskIdentities) > 0 { - generatePSKBinders(hello, pskCipherSuite, session.masterSecret, []byte{}, c.config) + 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. + if session.vers < VersionTLS13 { + version = tls13DraftVersion + } + generatePSKBinders(version, hello, pskCipherSuite, session.masterSecret, []byte{}, []byte{}, c.config) } helloBytes = hello.marshal() @@ -407,11 +410,23 @@ NextCipherSuite: // Derive early write keys and set Conn state to allow early writes. if sendEarlyData { - finishedHash := newFinishedHash(session.vers, pskCipherSuite) + finishedHash := newFinishedHash(session.wireVersion, c.isDTLS, pskCipherSuite) finishedHash.addEntropy(session.masterSecret) finishedHash.Write(helloBytes) - earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel) - c.out.useTrafficSecret(session.vers, pskCipherSuite, earlyTrafficSecret, clientWrite) + + earlyLabel := earlyTrafficLabel + if isDraft21(session.wireVersion) { + earlyLabel = earlyTrafficLabelDraft21 + } + + if !c.config.Bugs.SkipChangeCipherSpec && isDraft22(session.wireVersion) { + c.wireVersion = session.wireVersion + c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + c.wireVersion = 0 + } + + earlyTrafficSecret := finishedHash.deriveSecret(earlyLabel) + c.useOutTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret) for _, earlyData := range c.config.Bugs.SendEarlyData { if _, err := c.writeRecord(recordTypeApplicationData, earlyData); err != nil { return err @@ -470,9 +485,22 @@ NextCipherSuite: c.vers = serverVersion c.haveVers = true + if isDraft22(c.wireVersion) { + // The first server message must be followed by a ChangeCipherSpec. + c.expectTLS13ChangeCipherSpec = true + } + helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg) var secondHelloBytes []byte if haveHelloRetryRequest { + if isDraft22(c.wireVersion) { + // Explicitly read the ChangeCipherSpec now; it should + // be attached to the first flight, not the second flight. + if err := c.readTLS13ChangeCipherSpec(); err != nil { + return err + } + } + c.out.resetCipher() if len(helloRetryRequest.cookie) > 0 { hello.tls13Cookie = helloRetryRequest.cookie @@ -518,7 +546,7 @@ NextCipherSuite: hello.raw = nil if len(hello.pskIdentities) > 0 { - generatePSKBinders(hello, pskCipherSuite, session.masterSecret, append(helloBytes, helloRetryRequest.marshal()...), c.config) + generatePSKBinders(c.wireVersion, hello, pskCipherSuite, session.masterSecret, helloBytes, helloRetryRequest.marshal(), c.config) } secondHelloBytes = hello.marshal() @@ -588,13 +616,19 @@ NextCipherSuite: serverHello: serverHello, hello: hello, suite: suite, - finishedHash: newFinishedHash(c.vers, suite), + finishedHash: newFinishedHash(c.wireVersion, c.isDTLS, suite), keyShares: keyShares, session: session, } hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1) if haveHelloRetryRequest { + if isDraft21(c.wireVersion) { + err = hs.finishedHash.UpdateForHelloRetryRequest() + if err != nil { + return err + } + } hs.writeServerHash(helloRetryRequest.marshal()) hs.writeClientHash(secondHelloBytes) } @@ -690,7 +724,13 @@ NextCipherSuite: func (hs *clientHandshakeState) doTLS13Handshake() error { c := hs.c - if c.wireVersion == tls13ExperimentVersion && !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) { + if isResumptionExperiment(c.wireVersion) && !isDraft22(c.wireVersion) { + // Early versions of the middlebox hacks inserted + // ChangeCipherSpec differently on 0-RTT and 2-RTT handshakes. + c.expectTLS13ChangeCipherSpec = true + } + + if isResumptionExperiment(c.wireVersion) && !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) { return errors.New("tls: session IDs did not match.") } @@ -739,22 +779,27 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { if err != nil { return err } + hs.finishedHash.nextSecret() hs.finishedHash.addEntropy(ecdheSecret) } else { + hs.finishedHash.nextSecret() hs.finishedHash.addEntropy(zeroSecret) } - if c.wireVersion == tls13ExperimentVersion { - if err := c.readRecord(recordTypeChangeCipherSpec); err != nil { - return err - } + clientLabel := clientHandshakeTrafficLabel + serverLabel := serverHandshakeTrafficLabel + if isDraft21(c.wireVersion) { + clientLabel = clientHandshakeTrafficLabelDraft21 + serverLabel = serverHandshakeTrafficLabelDraft21 } // Derive handshake traffic keys and switch read key to handshake // traffic key. - clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel) - serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel) - c.in.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite) + clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientLabel) + serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) + if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret); err != nil { + return err + } msg, err := c.readHandshake() if err != nil { @@ -793,6 +838,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { return errors.New("tls: non-empty certificate request context sent in handshake") } + if c.config.Bugs.ExpectNoCertificateAuthoritiesExtension && certReq.hasCAExtension { + return errors.New("tls: expected no certificate_authorities extension") + } + if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences { certReq.signatureAlgorithms = c.config.signSignatureAlgorithms() } @@ -881,17 +930,30 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { // The various secrets do not incorporate the client's final leg, so // derive them now before updating the handshake context. + hs.finishedHash.nextSecret() hs.finishedHash.addEntropy(zeroSecret) - clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel) - serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel) - c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel) + + clientLabel = clientApplicationTrafficLabel + serverLabel = serverApplicationTrafficLabel + exportLabel := exporterLabel + if isDraft21(c.wireVersion) { + clientLabel = clientApplicationTrafficLabelDraft21 + serverLabel = serverApplicationTrafficLabelDraft21 + exportLabel = exporterLabelDraft21 + } + + clientTrafficSecret := hs.finishedHash.deriveSecret(clientLabel) + serverTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) + c.exporterSecret = hs.finishedHash.deriveSecret(exportLabel) // Switch to application data keys on read. In particular, any alerts // from the client certificate are read over these keys. - c.in.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite) + if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret); err != nil { + return err + } - // If we're expecting 0.5-RTT messages from the server, read them - // now. + // If we're expecting 0.5-RTT messages from the server, read them now. + var deferredTickets []*newSessionTicketMsg if encryptedExtensions.extensions.hasEarlyData { // BoringSSL will always send two tickets half-RTT when // negotiating 0-RTT. @@ -904,9 +966,8 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { if !ok { return errors.New("tls: expected half-RTT ticket") } - if err := c.processTLS13NewSessionTicket(newSessionTicket, hs.suite); err != nil { - return err - } + // Defer processing until the resumption secret is computed. + deferredTickets = append(deferredTickets, newSessionTicket) } for _, expectedMsg := range c.config.Bugs.ExpectHalfRTTData { if err := c.readRecord(recordTypeApplicationData); err != nil { @@ -922,19 +983,30 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { // Send EndOfEarlyData and then switch write key to handshake // traffic key. - if c.out.cipher != nil && !c.config.Bugs.SkipEndOfEarlyData { + if encryptedExtensions.extensions.hasEarlyData && c.out.cipher != nil && !c.config.Bugs.SkipEndOfEarlyData { if c.config.Bugs.SendStrayEarlyHandshake { helloRequest := new(helloRequestMsg) c.writeRecord(recordTypeHandshake, helloRequest.marshal()) } - c.sendAlert(alertEndOfEarlyData) + if isDraft21(c.wireVersion) { + endOfEarlyData := new(endOfEarlyDataMsg) + endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData + c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal()) + hs.writeClientHash(endOfEarlyData.marshal()) + } else { + c.sendAlert(alertEndOfEarlyData) + } } - if c.wireVersion == tls13ExperimentVersion { + if !c.config.Bugs.SkipChangeCipherSpec && isResumptionClientCCSExperiment(c.wireVersion) && !hs.hello.hasEarlyData { c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) } - c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite) + for i := 0; i < c.config.Bugs.SendExtraChangeCipherSpec; i++ { + c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + } + + c.useOutTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret) if certReq != nil && !c.config.Bugs.SkipClientCertificate { certMsg := &certificateMsg{ @@ -1020,9 +1092,20 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { c.flushHandshake() // Switch to application data keys. - c.out.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite) + c.useOutTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret) + + resumeLabel := resumptionLabel + if isDraft21(c.wireVersion) { + resumeLabel = resumptionLabelDraft21 + } + + c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel) + for _, ticket := range deferredTickets { + if err := c.processTLS13NewSessionTicket(ticket, hs.suite); err != nil { + return err + } + } - c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel) return nil } @@ -1287,8 +1370,8 @@ func (hs *clientHandshakeState) establishKeys() error { serverCipher = hs.suite.aead(c.vers, serverKey, serverIV) } - c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) - c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) + c.in.prepareCipherSpec(c.wireVersion, serverCipher, serverHash) + c.out.prepareCipherSpec(c.wireVersion, clientCipher, clientHash) return nil } @@ -1498,6 +1581,7 @@ func (hs *clientHandshakeState) readSessionTicket() error { // session ID or session ticket will be attached. session := &ClientSessionState{ vers: c.vers, + wireVersion: c.wireVersion, cipherSuite: hs.suite.id, masterSecret: hs.masterSecret, handshakeHash: hs.finishedHash.Sum(), @@ -1622,7 +1706,9 @@ func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error { } } - c.flushHandshake() + if !isResume || !c.config.Bugs.PackAppDataWithHandshake { + c.flushHandshake() + } return nil } @@ -1729,7 +1815,7 @@ func writeIntPadded(b []byte, x *big.Int) { copy(b[len(b)-len(xb):], xb) } -func generatePSKBinders(hello *clientHelloMsg, pskCipherSuite *cipherSuite, psk, transcript []byte, config *Config) { +func generatePSKBinders(version uint16, hello *clientHelloMsg, pskCipherSuite *cipherSuite, psk, firstClientHello, helloRetryRequest []byte, config *Config) { if config.Bugs.SendNoPSKBinder { return } @@ -1755,7 +1841,11 @@ func generatePSKBinders(hello *clientHelloMsg, pskCipherSuite *cipherSuite, psk, helloBytes := hello.marshal() binderSize := len(hello.pskBinders)*(binderLen+1) + 2 truncatedHello := helloBytes[:len(helloBytes)-binderSize] - binder := computePSKBinder(psk, resumptionPSKBinderLabel, pskCipherSuite, transcript, truncatedHello) + binderLabel := resumptionPSKBinderLabel + if isDraft21(version) { + binderLabel = resumptionPSKBinderLabelDraft21 + } + binder := computePSKBinder(psk, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello) if config.Bugs.SendShortPSKBinder { binder = binder[:binderLen] } diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/handshake_messages.go b/vendor/github.com/google/boringssl/ssl/test/runner/handshake_messages.go index 7da08d8..93da121 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/handshake_messages.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/handshake_messages.go @@ -175,6 +175,7 @@ type clientHelloMsg struct { pskBinderFirst bool omitExtensions bool emptyExtensions bool + pad int } func (m *clientHelloMsg) equal(i interface{}) bool { @@ -222,7 +223,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool { m.hasGREASEExtension == m1.hasGREASEExtension && m.pskBinderFirst == m1.pskBinderFirst && m.omitExtensions == m1.omitExtensions && - m.emptyExtensions == m1.emptyExtensions + m.emptyExtensions == m1.emptyExtensions && + m.pad == m1.pad } func (m *clientHelloMsg) marshal() []byte { @@ -454,6 +456,16 @@ func (m *clientHelloMsg) marshal() []byte { } } + if m.pad != 0 && hello.len()%m.pad != 0 { + extensions.addU16(extensionPadding) + padding := extensions.addU16LengthPrefixed() + // Note hello.len() has changed at this point from the length + // prefix. + if l := hello.len() % m.pad; l != 0 { + padding.addBytes(make([]byte, m.pad-l)) + } + } + if m.omitExtensions || m.emptyExtensions { // Silently erase any extensions which were sent. hello.discardChild() @@ -463,6 +475,10 @@ func (m *clientHelloMsg) marshal() []byte { } m.raw = handshakeMsg.finish() + // Sanity-check padding. + if m.pad != 0 && (len(m.raw)-4)%m.pad != 0 { + panic(fmt.Sprintf("%d is not a multiple of %d", len(m.raw)-4, m.pad)) + } return m.raw } @@ -865,19 +881,19 @@ func (m *serverHelloMsg) marshal() []byte { } if m.versOverride != 0 { hello.addU16(m.versOverride) - } else if m.vers == tls13ExperimentVersion { + } else if isResumptionExperiment(m.vers) { hello.addU16(VersionTLS12) } else { hello.addU16(m.vers) } hello.addBytes(m.random) - if vers < VersionTLS13 || m.vers == tls13ExperimentVersion { + if vers < VersionTLS13 || isResumptionExperiment(m.vers) { sessionId := hello.addU8LengthPrefixed() sessionId.addBytes(m.sessionId) } hello.addU16(m.cipherSuite) - if vers < VersionTLS13 || m.vers == tls13ExperimentVersion { + if vers < VersionTLS13 || isResumptionExperiment(m.vers) { hello.addU8(m.compressionMethod) } @@ -896,7 +912,7 @@ func (m *serverHelloMsg) marshal() []byte { extensions.addU16(2) // Length extensions.addU16(m.pskIdentity) } - if m.vers == tls13ExperimentVersion || m.supportedVersOverride != 0 { + if isResumptionExperiment(m.vers) || m.supportedVersOverride != 0 { extensions.addU16(extensionSupportedVersions) extensions.addU16(2) // Length if m.supportedVersOverride != 0 { @@ -950,7 +966,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { } m.random = data[6:38] data = data[38:] - if vers < VersionTLS13 || m.vers == tls13ExperimentVersion { + if vers < VersionTLS13 || isResumptionExperiment(m.vers) { sessionIdLen := int(data[0]) if sessionIdLen > 32 || len(data) < 1+sessionIdLen { return false @@ -963,7 +979,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { } m.cipherSuite = uint16(data[0])<<8 | uint16(data[1]) data = data[2:] - if vers < VersionTLS13 || m.vers == tls13ExperimentVersion { + if vers < VersionTLS13 || isResumptionExperiment(m.vers) { if len(data) < 1 { return false } @@ -1052,7 +1068,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { m.pskIdentity = uint16(d[0])<<8 | uint16(d[1]) m.hasPSKIdentity = true case extensionSupportedVersions: - if m.vers != tls13ExperimentVersion { + if !isResumptionExperiment(m.vers) { return false } default: @@ -1133,6 +1149,7 @@ type serverExtensions struct { keyShare keyShareEntry supportedVersion uint16 supportedPoints []uint8 + supportedCurves []CurveID serverNameAck bool } @@ -1240,6 +1257,15 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) { supportedPoints := supportedPointsList.addU8LengthPrefixed() supportedPoints.addBytes(m.supportedPoints) } + if len(m.supportedCurves) > 0 { + // https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.4 + extensions.addU16(extensionSupportedCurves) + supportedCurvesList := extensions.addU16LengthPrefixed() + supportedCurves := supportedCurvesList.addU16LengthPrefixed() + for _, curve := range m.supportedCurves { + supportedCurves.addU16(uint16(curve)) + } + } if m.hasEarlyData { extensions.addU16(extensionEarlyData) extensions.addBytes([]byte{0, 0}) @@ -1380,6 +1406,9 @@ func (m *serverExtensions) unmarshal(data []byte, version uint16) bool { type helloRetryRequestMsg struct { raw []byte vers uint16 + isServerHello bool + sessionId []byte + cipherSuite uint16 hasSelectedGroup bool selectedGroup CurveID cookie []byte @@ -1393,9 +1422,26 @@ func (m *helloRetryRequestMsg) marshal() []byte { } retryRequestMsg := newByteBuilder() - retryRequestMsg.addU8(typeHelloRetryRequest) + if isDraft22(m.vers) { + retryRequestMsg.addU8(typeServerHello) + } else { + retryRequestMsg.addU8(typeHelloRetryRequest) + } retryRequest := retryRequestMsg.addU24LengthPrefixed() - retryRequest.addU16(m.vers) + + if isDraft22(m.vers) { + retryRequest.addU16(VersionTLS12) + retryRequest.addBytes(tls13HelloRetryRequest) + sessionId := retryRequest.addU8LengthPrefixed() + sessionId.addBytes(m.sessionId) + retryRequest.addU16(m.cipherSuite) + retryRequest.addU8(0) + } else { + retryRequest.addU16(m.vers) + if isDraft21(m.vers) { + retryRequest.addU16(m.cipherSuite) + } + } extensions := retryRequest.addU16LengthPrefixed() count := 1 @@ -1404,12 +1450,18 @@ func (m *helloRetryRequestMsg) marshal() []byte { } for i := 0; i < count; i++ { + if isDraft22(m.vers) { + extensions.addU16(extensionSupportedVersions) + extensions.addU16(2) // Length + extensions.addU16(m.vers) + } if m.hasSelectedGroup { extensions.addU16(extensionKeyShare) extensions.addU16(2) // length extensions.addU16(uint16(m.selectedGroup)) } - if len(m.cookie) > 0 { + // m.cookie may be a non-nil empty slice for empty cookie tests. + if m.cookie != nil { extensions.addU16(extensionCookie) body := extensions.addU16LengthPrefixed() body.addU16LengthPrefixed().addBytes(m.cookie) @@ -1430,8 +1482,29 @@ func (m *helloRetryRequestMsg) unmarshal(data []byte) bool { return false } m.vers = uint16(data[4])<<8 | uint16(data[5]) - extLen := int(data[6])<<8 | int(data[7]) - data = data[8:] + data = data[6:] + if m.isServerHello { + if len(data) < 33 { + return false + } + data = data[32:] // Random + sessionIdLen := int(data[0]) + if sessionIdLen > 32 || len(data) < 1+sessionIdLen+3 { + return false + } + m.sessionId = data[1 : 1+sessionIdLen] + data = data[1+sessionIdLen:] + m.cipherSuite = uint16(data[0])<<8 | uint16(data[1]) + data = data[2:] + data = data[1:] // Compression Method + } else { + if isDraft21(m.vers) { + m.cipherSuite = uint16(data[0])<<8 | uint16(data[1]) + data = data[2:] + } + } + extLen := int(data[0])<<8 | int(data[1]) + data = data[2:] if len(data) != extLen || len(data) == 0 { return false } @@ -1447,6 +1520,11 @@ func (m *helloRetryRequestMsg) unmarshal(data []byte) bool { } switch extension { + case extensionSupportedVersions: + if length != 2 || !m.isServerHello { + return false + } + m.vers = uint16(data[0])<<8 | uint16(data[1]) case extensionKeyShare: if length != 2 { return false @@ -1844,7 +1922,8 @@ func (m *nextProtoMsg) unmarshal(data []byte) bool { } type certificateRequestMsg struct { - raw []byte + raw []byte + vers uint16 // hasSignatureAlgorithm indicates whether this message includes a list // of signature and hash functions. This change was introduced with TLS // 1.2. @@ -1858,6 +1937,8 @@ type certificateRequestMsg struct { requestContext []byte signatureAlgorithms []signatureAlgorithm certificateAuthorities [][]byte + hasCAExtension bool + customExtension uint16 } func (m *certificateRequestMsg) marshal() []byte { @@ -1873,33 +1954,119 @@ func (m *certificateRequestMsg) marshal() []byte { if m.hasRequestContext { requestContext := body.addU8LengthPrefixed() requestContext.addBytes(m.requestContext) + extensions := newByteBuilder() + if isDraft21(m.vers) { + extensions = body.addU16LengthPrefixed() + if m.hasSignatureAlgorithm { + extensions.addU16(extensionSignatureAlgorithms) + signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed() + for _, sigAlg := range m.signatureAlgorithms { + signatureAlgorithms.addU16(uint16(sigAlg)) + } + } + if len(m.certificateAuthorities) > 0 { + extensions.addU16(extensionCertificateAuthorities) + certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed() + for _, ca := range m.certificateAuthorities { + caEntry := certificateAuthorities.addU16LengthPrefixed() + caEntry.addBytes(ca) + } + } + } else { + if m.hasSignatureAlgorithm { + signatureAlgorithms := body.addU16LengthPrefixed() + for _, sigAlg := range m.signatureAlgorithms { + signatureAlgorithms.addU16(uint16(sigAlg)) + } + } + + certificateAuthorities := body.addU16LengthPrefixed() + for _, ca := range m.certificateAuthorities { + caEntry := certificateAuthorities.addU16LengthPrefixed() + caEntry.addBytes(ca) + } + extensions = body.addU16LengthPrefixed() + } + + if m.customExtension > 0 { + extensions.addU16(m.customExtension) + extensions.addU16LengthPrefixed() + } } else { certificateTypes := body.addU8LengthPrefixed() certificateTypes.addBytes(m.certificateTypes) - } - if m.hasSignatureAlgorithm { - signatureAlgorithms := body.addU16LengthPrefixed() - for _, sigAlg := range m.signatureAlgorithms { - signatureAlgorithms.addU16(uint16(sigAlg)) + if m.hasSignatureAlgorithm { + signatureAlgorithms := body.addU16LengthPrefixed() + for _, sigAlg := range m.signatureAlgorithms { + signatureAlgorithms.addU16(uint16(sigAlg)) + } } - } - certificateAuthorities := body.addU16LengthPrefixed() - for _, ca := range m.certificateAuthorities { - caEntry := certificateAuthorities.addU16LengthPrefixed() - caEntry.addBytes(ca) - } - - if m.hasRequestContext { - // Emit no certificate extensions. - body.addU16(0) + certificateAuthorities := body.addU16LengthPrefixed() + for _, ca := range m.certificateAuthorities { + caEntry := certificateAuthorities.addU16LengthPrefixed() + caEntry.addBytes(ca) + } } m.raw = builder.finish() return m.raw } +func parseSignatureAlgorithms(data []byte) ([]signatureAlgorithm, []byte, bool) { + if len(data) < 2 { + return nil, nil, false + } + sigAlgsLen := int(data[0])<<8 | int(data[1]) + data = data[2:] + if sigAlgsLen&1 != 0 { + return nil, nil, false + } + if len(data) < int(sigAlgsLen) { + return nil, nil, false + } + numSigAlgs := sigAlgsLen / 2 + signatureAlgorithms := make([]signatureAlgorithm, numSigAlgs) + for i := range signatureAlgorithms { + signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1]) + data = data[2:] + } + + return signatureAlgorithms, data, true +} + +func parseCAs(data []byte) ([][]byte, []byte, bool) { + if len(data) < 2 { + return nil, nil, false + } + casLength := uint16(data[0])<<8 | uint16(data[1]) + data = data[2:] + if len(data) < int(casLength) { + return nil, nil, false + } + + cas := data[:casLength] + data = data[casLength:] + + var certificateAuthorities [][]byte + for len(cas) > 0 { + if len(cas) < 2 { + return nil, nil, false + } + caLen := uint16(cas[0])<<8 | uint16(cas[1]) + cas = cas[2:] + + if len(cas) < int(caLen) { + return nil, nil, false + } + + certificateAuthorities = append(certificateAuthorities, cas[:caLen]) + cas = cas[caLen:] + } + return certificateAuthorities, data, true +} + func (m *certificateRequestMsg) unmarshal(data []byte) bool { m.raw = data @@ -1916,6 +2083,70 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool { m.requestContext = make([]byte, contextLen) copy(m.requestContext, data[1:]) data = data[1+contextLen:] + if isDraft21(m.vers) { + if len(data) < 2 { + return false + } + extensionsLen := int(data[0])<<8 | int(data[1]) + if len(data) < 2+extensionsLen { + return false + } + extensions := data[2 : 2+extensionsLen] + data = data[2+extensionsLen:] + for len(extensions) != 0 { + if len(extensions) < 4 { + return false + } + extension := uint16(extensions[0])<<8 | uint16(extensions[1]) + length := int(extensions[2])<<8 | int(extensions[3]) + if len(extensions) < 4+length { + return false + } + contents := extensions[4 : 4+length] + extensions = extensions[4+length:] + switch extension { + case extensionSignatureAlgorithms: + sigAlgs, rest, ok := parseSignatureAlgorithms(contents) + if !ok || len(rest) != 0 { + return false + } + m.signatureAlgorithms = sigAlgs + case extensionCertificateAuthorities: + cas, rest, ok := parseCAs(contents) + if !ok || len(rest) != 0 { + return false + } + m.hasCAExtension = true + m.certificateAuthorities = cas + } + } + } else { + if m.hasSignatureAlgorithm { + sigAlgs, rest, ok := parseSignatureAlgorithms(data) + if !ok { + return false + } + m.signatureAlgorithms = sigAlgs + data = rest + } + + cas, rest, ok := parseCAs(data) + if !ok { + return false + } + m.certificateAuthorities = cas + data = rest + + // Ignore certificate extensions. + if len(data) < 2 { + return false + } + extsLength := int(data[0])<<8 | int(data[1]) + if len(data) < 2+extsLength { + return false + } + data = data[2+extsLength:] + } } else { numCertTypes := int(data[0]) if len(data) < 1+numCertTypes { @@ -1924,66 +2155,22 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool { m.certificateTypes = make([]byte, numCertTypes) copy(m.certificateTypes, data[1:]) data = data[1+numCertTypes:] - } - if m.hasSignatureAlgorithm { - if len(data) < 2 { - return false - } - sigAlgsLen := uint16(data[0])<<8 | uint16(data[1]) - data = data[2:] - if sigAlgsLen&1 != 0 { - return false - } - if len(data) < int(sigAlgsLen) { - return false - } - numSigAlgs := sigAlgsLen / 2 - m.signatureAlgorithms = make([]signatureAlgorithm, numSigAlgs) - for i := range m.signatureAlgorithms { - m.signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1]) - data = data[2:] - } - } - - if len(data) < 2 { - return false - } - casLength := uint16(data[0])<<8 | uint16(data[1]) - data = data[2:] - if len(data) < int(casLength) { - return false - } - cas := make([]byte, casLength) - copy(cas, data) - data = data[casLength:] - - m.certificateAuthorities = nil - for len(cas) > 0 { - if len(cas) < 2 { - return false - } - caLen := uint16(cas[0])<<8 | uint16(cas[1]) - cas = cas[2:] - - if len(cas) < int(caLen) { - return false + if m.hasSignatureAlgorithm { + sigAlgs, rest, ok := parseSignatureAlgorithms(data) + if !ok { + return false + } + m.signatureAlgorithms = sigAlgs + data = rest } - m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen]) - cas = cas[caLen:] - } - - if m.hasRequestContext { - // Ignore certificate extensions. - if len(data) < 2 { + cas, rest, ok := parseCAs(data) + if !ok { return false } - extsLength := int(data[0])<<8 | int(data[1]) - if len(data) < 2+extsLength { - return false - } - data = data[2+extsLength:] + m.certificateAuthorities = cas + data = rest } if len(data) > 0 { @@ -2064,15 +2251,17 @@ func (m *certificateVerifyMsg) unmarshal(data []byte) bool { } type newSessionTicketMsg struct { - raw []byte - version uint16 - ticketLifetime uint32 - ticketAgeAdd uint32 - ticket []byte - maxEarlyDataSize uint32 - customExtension string - duplicateEarlyDataInfo bool - hasGREASEExtension bool + raw []byte + vers uint16 + isDTLS bool + ticketLifetime uint32 + ticketAgeAdd uint32 + ticketNonce []byte + ticket []byte + maxEarlyDataSize uint32 + customExtension string + duplicateEarlyDataExtension bool + hasGREASEExtension bool } func (m *newSessionTicketMsg) marshal() []byte { @@ -2080,25 +2269,37 @@ func (m *newSessionTicketMsg) marshal() []byte { return m.raw } + version, ok := wireToVersion(m.vers, m.isDTLS) + if !ok { + panic("unknown version") + } + // See http://tools.ietf.org/html/rfc5077#section-3.3 ticketMsg := newByteBuilder() ticketMsg.addU8(typeNewSessionTicket) body := ticketMsg.addU24LengthPrefixed() body.addU32(m.ticketLifetime) - if m.version >= VersionTLS13 { + if version >= VersionTLS13 { body.addU32(m.ticketAgeAdd) + if isDraft21(m.vers) { + body.addU8LengthPrefixed().addBytes(m.ticketNonce) + } } ticket := body.addU16LengthPrefixed() ticket.addBytes(m.ticket) - if m.version >= VersionTLS13 { + if version >= VersionTLS13 { extensions := body.addU16LengthPrefixed() if m.maxEarlyDataSize > 0 { - extensions.addU16(extensionTicketEarlyDataInfo) + extID := extensionTicketEarlyDataInfo + if isDraft21(m.vers) { + extID = extensionEarlyData + } + extensions.addU16(extID) extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize) - if m.duplicateEarlyDataInfo { - extensions.addU16(extensionTicketEarlyDataInfo) + if m.duplicateEarlyDataExtension { + extensions.addU16(extID) extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize) } } @@ -2115,18 +2316,32 @@ func (m *newSessionTicketMsg) marshal() []byte { func (m *newSessionTicketMsg) unmarshal(data []byte) bool { m.raw = data + version, ok := wireToVersion(m.vers, m.isDTLS) + if !ok { + panic("unknown version") + } + if len(data) < 8 { return false } m.ticketLifetime = uint32(data[4])<<24 | uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7]) data = data[8:] - if m.version >= VersionTLS13 { + if version >= VersionTLS13 { if len(data) < 4 { return false } m.ticketAgeAdd = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3]) data = data[4:] + if isDraft21(m.vers) { + nonceLen := int(data[0]) + data = data[1:] + if len(data) < nonceLen { + return false + } + m.ticketNonce = data[:nonceLen] + data = data[nonceLen:] + } } if len(data) < 2 { @@ -2138,14 +2353,14 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool { return false } - if m.version >= VersionTLS13 && ticketLen == 0 { + if version >= VersionTLS13 && ticketLen == 0 { return false } m.ticket = data[:ticketLen] data = data[ticketLen:] - if m.version >= VersionTLS13 { + if version >= VersionTLS13 { if len(data) < 2 { return false } @@ -2156,6 +2371,11 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool { return false } + extID := extensionTicketEarlyDataInfo + if isDraft21(m.vers) { + extID = extensionEarlyData + } + for len(data) != 0 { if len(data) < 4 { return false @@ -2168,7 +2388,7 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool { } switch extension { - case extensionTicketEarlyDataInfo: + case extID: if length != 4 { return false } @@ -2355,6 +2575,21 @@ func (m *keyUpdateMsg) unmarshal(data []byte) bool { return m.keyUpdateRequest == keyUpdateNotRequested || m.keyUpdateRequest == keyUpdateRequested } +type endOfEarlyDataMsg struct { + nonEmpty bool +} + +func (m *endOfEarlyDataMsg) marshal() []byte { + if m.nonEmpty { + return []byte{typeEndOfEarlyData, 0, 0, 1, 42} + } + return []byte{typeEndOfEarlyData, 0, 0, 0} +} + +func (*endOfEarlyDataMsg) unmarshal(data []byte) bool { + return len(data) == 4 +} + // ssl3NoCertificateMsg is a dummy message to handle SSL 3.0 using a warning // alert in the handshake. type ssl3NoCertificateMsg struct{} diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/handshake_server.go b/vendor/github.com/google/boringssl/ssl/test/runner/handshake_server.go index 5dee5fb..4286911 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/handshake_server.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/handshake_server.go @@ -80,7 +80,7 @@ func (c *Conn) serverHandshake() error { return err } } - if err := hs.sendFinished(c.firstFinished[:]); err != nil { + if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil { return err } // Most retransmits are triggered by a timeout, but the final @@ -120,7 +120,7 @@ func (c *Conn) serverHandshake() error { if err := hs.sendSessionTicket(); err != nil { return err } - if err := hs.sendFinished(nil); err != nil { + if err := hs.sendFinished(nil, isResume); err != nil { return err } } @@ -281,7 +281,7 @@ func (hs *serverHandshakeState) readClientHello() error { } if config.Bugs.ExpectNoTLS12Session { - if len(hs.clientHello.sessionId) > 0 && c.wireVersion != tls13ExperimentVersion { + if len(hs.clientHello.sessionId) > 0 && !isResumptionExperiment(c.wireVersion) { return fmt.Errorf("tls: client offered an unexpected session ID") } if len(hs.clientHello.sessionTicket) > 0 { @@ -358,6 +358,12 @@ func (hs *serverHandshakeState) doTLS13Handshake() error { c := hs.c config := c.config + // We've read the ClientHello, so the next record in draft 22 must be + // preceded with ChangeCipherSpec. + if isDraft22(c.wireVersion) { + c.expectTLS13ChangeCipherSpec = true + } + hs.hello = &serverHelloMsg{ isDTLS: c.isDTLS, vers: c.wireVersion, @@ -412,7 +418,7 @@ func (hs *serverHandshakeState) doTLS13Handshake() error { hs.hello.cipherSuite = c.config.Bugs.SendCipherSuite } - hs.finishedHash = newFinishedHash(c.vers, hs.suite) + hs.finishedHash = newFinishedHash(c.wireVersion, c.isDTLS, hs.suite) hs.finishedHash.discardHandshakeBuffer() hs.writeClientHash(hs.clientHello.marshal()) @@ -496,7 +502,7 @@ Curves: // AcceptAnyBinder is set. See https://crbug.com/boringssl/115. if hs.sessionState != nil && !config.Bugs.AcceptAnySession { binderToVerify := hs.clientHello.pskBinders[pskIndex] - if err := verifyPSKBinder(hs.clientHello, hs.sessionState, binderToVerify, []byte{}); err != nil { + if err := verifyPSKBinder(c.wireVersion, hs.clientHello, hs.sessionState, binderToVerify, []byte{}, []byte{}); err != nil { return err } } @@ -520,8 +526,14 @@ Curves: ResendHelloRetryRequest: var sendHelloRetryRequest bool + cipherSuite := hs.suite.id + if config.Bugs.SendHelloRetryRequestCipherSuite != 0 { + cipherSuite = config.Bugs.SendHelloRetryRequestCipherSuite + } helloRetryRequest := &helloRetryRequestMsg{ vers: c.wireVersion, + sessionId: hs.clientHello.sessionId, + cipherSuite: cipherSuite, duplicateExtensions: config.Bugs.DuplicateHelloRetryRequestExtensions, } @@ -571,15 +583,21 @@ ResendHelloRetryRequest: } if sendHelloRetryRequest { + if isDraft21(c.wireVersion) { + if err := hs.finishedHash.UpdateForHelloRetryRequest(); err != nil { + return err + } + } + oldClientHelloBytes := hs.clientHello.marshal() hs.writeServerHash(helloRetryRequest.marshal()) - if c.vers == tls13RecordTypeExperimentVersion { - c.writeRecord(recordTypePlaintextHandshake, helloRetryRequest.marshal()) - } else { - c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal()) - } + c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal()) c.flushHandshake() + if !c.config.Bugs.SkipChangeCipherSpec && isDraft22(c.wireVersion) { + c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + } + if hs.clientHello.hasEarlyData { c.skipEarlyData = true } @@ -596,6 +614,10 @@ ResendHelloRetryRequest: } hs.writeClientHash(newClientHello.marshal()) + if config.Bugs.ExpectNoTLS13PSKAfterHRR && len(newClientHello.pskIdentities) > 0 { + return fmt.Errorf("tls: client offered unexpected PSK identities after HelloRetryRequest") + } + if newClientHello.hasEarlyData { return errors.New("tls: EarlyData sent in new ClientHello") } @@ -630,11 +652,15 @@ ResendHelloRetryRequest: // PSK binders and obfuscated ticket age are both updated in the // second ClientHello. - if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) { - return errors.New("tls: PSK identity count from old and new ClientHello do not match") - } - for i, identity := range oldClientHelloCopy.pskIdentities { - newClientHelloCopy.pskIdentities[i].obfuscatedTicketAge = identity.obfuscatedTicketAge + if isDraft21(c.wireVersion) && len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) { + newClientHelloCopy.pskIdentities = oldClientHelloCopy.pskIdentities + } else { + if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) { + return errors.New("tls: PSK identity count from old and new ClientHello do not match") + } + for i, identity := range oldClientHelloCopy.pskIdentities { + newClientHelloCopy.pskIdentities[i].obfuscatedTicketAge = identity.obfuscatedTicketAge + } } newClientHelloCopy.pskBinders = oldClientHelloCopy.pskBinders newClientHelloCopy.hasEarlyData = oldClientHelloCopy.hasEarlyData @@ -652,8 +678,7 @@ ResendHelloRetryRequest: // AcceptAnyBinder is set. See https://crbug.com/115. if hs.sessionState != nil && !config.Bugs.AcceptAnySession { binderToVerify := newClientHello.pskBinders[pskIndex] - err := verifyPSKBinder(newClientHello, hs.sessionState, binderToVerify, append(oldClientHelloBytes, helloRetryRequest.marshal()...)) - if err != nil { + if err := verifyPSKBinder(c.wireVersion, newClientHello, hs.sessionState, binderToVerify, oldClientHelloBytes, helloRetryRequest.marshal()); err != nil { return err } } @@ -667,8 +692,15 @@ ResendHelloRetryRequest: } } if encryptedExtensions.extensions.hasEarlyData { - earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel) - c.in.useTrafficSecret(c.vers, hs.suite, earlyTrafficSecret, clientWrite) + earlyLabel := earlyTrafficLabel + if isDraft21(c.wireVersion) { + earlyLabel = earlyTrafficLabelDraft21 + } + + earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyLabel) + if err := c.useInTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret); err != nil { + return err + } for _, expectedMsg := range config.Bugs.ExpectEarlyData { if err := c.readRecord(recordTypeApplicationData); err != nil { @@ -719,6 +751,7 @@ ResendHelloRetryRequest: c.sendAlert(alertHandshakeFailure) return err } + hs.finishedHash.nextSecret() hs.finishedHash.addEntropy(ecdheSecret) hs.hello.hasKeyShare = true @@ -743,6 +776,7 @@ ResendHelloRetryRequest: } } } else { + hs.finishedHash.nextSecret() hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret()) } @@ -755,23 +789,30 @@ ResendHelloRetryRequest: toWrite = append(toWrite, typeEncryptedExtensions) c.writeRecord(recordTypeHandshake, toWrite) } else { - if c.vers == tls13RecordTypeExperimentVersion { - c.writeRecord(recordTypePlaintextHandshake, hs.hello.marshal()) - } else { - c.writeRecord(recordTypeHandshake, hs.hello.marshal()) - } + c.writeRecord(recordTypeHandshake, hs.hello.marshal()) } c.flushHandshake() - if c.wireVersion == tls13ExperimentVersion { + if !c.config.Bugs.SkipChangeCipherSpec && isResumptionExperiment(c.wireVersion) && !sendHelloRetryRequest { c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) } + for i := 0; i < c.config.Bugs.SendExtraChangeCipherSpec; i++ { + c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + } + + clientLabel := clientHandshakeTrafficLabel + serverLabel := serverHandshakeTrafficLabel + if isDraft21(c.wireVersion) { + clientLabel = clientHandshakeTrafficLabelDraft21 + serverLabel = serverHandshakeTrafficLabelDraft21 + } + // Switch to handshake traffic keys. - serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel) - c.out.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite) + serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) + c.useOutTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret) // Derive handshake traffic read key, but don't switch yet. - clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel) + clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientLabel) // Send EncryptedExtensions. hs.writeServerHash(encryptedExtensions.marshal()) @@ -786,9 +827,11 @@ ResendHelloRetryRequest: if config.ClientAuth >= RequestClientCert { // Request a client certificate certReq := &certificateRequestMsg{ - hasSignatureAlgorithm: true, + vers: c.wireVersion, + hasSignatureAlgorithm: !config.Bugs.OmitCertificateRequestAlgorithms, hasRequestContext: true, requestContext: config.Bugs.SendRequestContext, + customExtension: config.Bugs.SendCustomCertificateRequest, } if !config.Bugs.NoSignatureAlgorithms { certReq.signatureAlgorithms = config.verifySignatureAlgorithms() @@ -903,14 +946,25 @@ ResendHelloRetryRequest: // The various secrets do not incorporate the client's final leg, so // derive them now before updating the handshake context. + hs.finishedHash.nextSecret() hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret()) - clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel) - serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel) - c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel) + + clientLabel = clientApplicationTrafficLabel + serverLabel = serverApplicationTrafficLabel + exportLabel := exporterLabel + if isDraft21(c.wireVersion) { + clientLabel = clientApplicationTrafficLabelDraft21 + serverLabel = serverApplicationTrafficLabelDraft21 + exportLabel = exporterLabelDraft21 + } + + clientTrafficSecret := hs.finishedHash.deriveSecret(clientLabel) + serverTrafficSecret := hs.finishedHash.deriveSecret(serverLabel) + c.exporterSecret = hs.finishedHash.deriveSecret(exportLabel) // Switch to application data keys on write. In particular, any alerts // from the client certificate are sent over these keys. - c.out.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite) + c.useOutTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret) // Send 0.5-RTT messages. for _, halfRTTMsg := range config.Bugs.SendHalfRTTData { @@ -919,24 +973,39 @@ ResendHelloRetryRequest: } } - // Read end_of_early_data alert. + // Read end_of_early_data. if encryptedExtensions.extensions.hasEarlyData { - if err := c.readRecord(recordTypeAlert); err != errEndOfEarlyDataAlert { - if err == nil { - panic("readRecord(recordTypeAlert) returned nil") + if isDraft21(c.wireVersion) { + msg, err := c.readHandshake() + if err != nil { + return err + } + + endOfEarlyData, ok := msg.(*endOfEarlyDataMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(endOfEarlyData, msg) + } + hs.writeClientHash(endOfEarlyData.marshal()) + } else { + if err := c.readRecord(recordTypeAlert); err != errEndOfEarlyDataAlert { + if err == nil { + panic("readRecord(recordTypeAlert) returned nil") + } + return err } - return err } } - - if c.wireVersion == tls13ExperimentVersion && !c.skipEarlyData { - if err := c.readRecord(recordTypeChangeCipherSpec); err != nil { - return err - } + if isResumptionClientCCSExperiment(c.wireVersion) && !isDraft22(c.wireVersion) && !hs.clientHello.hasEarlyData { + // Early versions of the middlebox hacks inserted + // ChangeCipherSpec differently on 0-RTT and 2-RTT handshakes. + c.expectTLS13ChangeCipherSpec = true } // Switch input stream to handshake traffic keys. - c.in.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite) + if err := c.useInTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret); err != nil { + return err + } // If we requested a client certificate, then the client must send a // certificate message, even if it's empty. @@ -1040,17 +1109,25 @@ ResendHelloRetryRequest: hs.writeClientHash(clientFinished.marshal()) // Switch to application data keys on read. - c.in.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite) + if err := c.useInTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret); err != nil { + return err + } c.cipherSuite = hs.suite - c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel) + + resumeLabel := resumptionLabel + if isDraft21(c.wireVersion) { + resumeLabel = resumptionLabelDraft21 + } + + c.resumptionSecret = hs.finishedHash.deriveSecret(resumeLabel) // TODO(davidben): Allow configuring the number of tickets sent for // testing. if !c.config.SessionTicketsDisabled && foundKEMode { ticketCount := 2 for i := 0; i < ticketCount; i++ { - c.SendNewSessionTicket() + c.SendNewSessionTicket([]byte{byte(i)}) } } return nil @@ -1089,9 +1166,6 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS12) } - if len(hs.clientHello.sessionId) > 0 && c.config.Bugs.ExpectEmptyClientHelloSessionID { - return false, errors.New("tls: expected empty session ID from client") - } if len(hs.clientHello.sessionId) == 0 && c.config.Bugs.ExpectClientHelloSessionID { return false, errors.New("tls: expected non-empty session ID from client") } @@ -1308,6 +1382,10 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server serverExtensions.supportedPoints = c.config.Bugs.SendSupportedPointFormats } + if c.config.Bugs.SendServerSupportedCurves { + serverExtensions.supportedCurves = c.config.curvePreferences() + } + if !hs.clientHello.hasGREASEExtension && config.Bugs.ExpectGREASE { return errors.New("tls: no GREASE extension found") } @@ -1410,7 +1488,7 @@ func (hs *serverHandshakeState) doResumeHandshake() error { hs.hello.extensions.ocspStapling = true } - hs.finishedHash = newFinishedHash(c.vers, hs.suite) + hs.finishedHash = newFinishedHash(c.wireVersion, c.isDTLS, hs.suite) hs.finishedHash.discardHandshakeBuffer() hs.writeClientHash(hs.clientHello.marshal()) hs.writeServerHash(hs.hello.marshal()) @@ -1462,7 +1540,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { } } - hs.finishedHash = newFinishedHash(c.vers, hs.suite) + hs.finishedHash = newFinishedHash(c.wireVersion, c.isDTLS, hs.suite) hs.writeClientHash(hs.clientHello.marshal()) hs.writeServerHash(hs.hello.marshal()) @@ -1516,6 +1594,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { if config.ClientAuth >= RequestClientCert { // Request a client certificate certReq := &certificateRequestMsg{ + vers: c.wireVersion, certificateTypes: config.ClientCertificateTypes, } if certReq.certificateTypes == nil { @@ -1697,8 +1776,8 @@ func (hs *serverHandshakeState) establishKeys() error { serverCipher = hs.suite.aead(c.vers, serverKey, serverIV) } - c.in.prepareCipherSpec(c.vers, clientCipher, clientHash) - c.out.prepareCipherSpec(c.vers, serverCipher, serverHash) + c.in.prepareCipherSpec(c.wireVersion, clientCipher, clientHash) + c.out.prepareCipherSpec(c.wireVersion, serverCipher, serverHash) return nil } @@ -1789,6 +1868,8 @@ func (hs *serverHandshakeState) sendSessionTicket() error { } m := new(newSessionTicketMsg) + m.vers = c.wireVersion + m.isDTLS = c.isDTLS if c.config.Bugs.SendTicketLifetime != 0 { m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second) } @@ -1807,7 +1888,7 @@ func (hs *serverHandshakeState) sendSessionTicket() error { return nil } -func (hs *serverHandshakeState) sendFinished(out []byte) error { +func (hs *serverHandshakeState) sendFinished(out []byte, isResume bool) error { c := hs.c finished := new(finishedMsg) @@ -1852,8 +1933,8 @@ func (hs *serverHandshakeState) sendFinished(out []byte) error { } } - if !c.config.Bugs.PackHelloRequestWithFinished { - // Defer flushing until renegotiation. + if isResume || (!c.config.Bugs.PackHelloRequestWithFinished && !c.config.Bugs.PackAppDataWithHandshake) { + // Defer flushing until Renegotiate() or Write(). c.flushHandshake() } @@ -1935,7 +2016,7 @@ func verifyChannelIDMessage(channelIDMsg *channelIDMsg, channelIDHash []byte) (* if !elliptic.P256().IsOnCurve(x, y) { return nil, errors.New("tls: invalid channel ID public key") } - channelID := &ecdsa.PublicKey{elliptic.P256(), x, y} + channelID := &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y} if !ecdsa.Verify(channelID, channelIDHash, r, s) { return nil, errors.New("tls: invalid channel ID signature") } @@ -2002,9 +2083,6 @@ func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 { continue } - if c.isDTLS && candidate.flags&suiteNoDTLS != 0 { - continue - } return candidate } } @@ -2027,7 +2105,7 @@ func isGREASEValue(val uint16) bool { return val&0x0f0f == 0x0a0a && val&0xff == val>>8 } -func verifyPSKBinder(clientHello *clientHelloMsg, sessionState *sessionState, binderToVerify, transcript []byte) error { +func verifyPSKBinder(version uint16, clientHello *clientHelloMsg, sessionState *sessionState, binderToVerify, firstClientHello, helloRetryRequest []byte) error { binderLen := 2 for _, binder := range clientHello.pskBinders { binderLen += 1 + len(binder) @@ -2040,7 +2118,11 @@ func verifyPSKBinder(clientHello *clientHelloMsg, sessionState *sessionState, bi return errors.New("tls: Unknown cipher suite for PSK in session") } - binder := computePSKBinder(sessionState.masterSecret, resumptionPSKBinderLabel, pskCipherSuite, transcript, truncatedHello) + binderLabel := resumptionPSKBinderLabel + if isDraft21(version) { + binderLabel = resumptionPSKBinderLabelDraft21 + } + binder := computePSKBinder(sessionState.masterSecret, version, binderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello) if !bytes.Equal(binder, binderToVerify) { return errors.New("tls: PSK binder does not verify") } diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/key_agreement.go b/vendor/github.com/google/boringssl/ssl/test/runner/key_agreement.go index e33557b..5071985 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/key_agreement.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/key_agreement.go @@ -136,12 +136,47 @@ func (ka *rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello return errors.New("tls: unexpected ServerKeyExchange") } +func rsaSize(pub *rsa.PublicKey) int { + return (pub.N.BitLen() + 7) / 8 +} + +func rsaRawEncrypt(pub *rsa.PublicKey, msg []byte) ([]byte, error) { + k := rsaSize(pub) + if len(msg) != k { + return nil, errors.New("tls: bad padded RSA input") + } + m := new(big.Int).SetBytes(msg) + e := big.NewInt(int64(pub.E)) + m.Exp(m, e, pub.N) + unpadded := m.Bytes() + ret := make([]byte, k) + copy(ret[len(ret)-len(unpadded):], unpadded) + return ret, nil +} + +// nonZeroRandomBytes fills the given slice with non-zero random octets. +func nonZeroRandomBytes(s []byte, rand io.Reader) { + if _, err := io.ReadFull(rand, s); err != nil { + panic(err) + } + + for i := range s { + for s[i] == 0 { + if _, err := io.ReadFull(rand, s[i:i+1]); err != nil { + panic(err) + } + } + } +} + func (ka *rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { bad := config.Bugs.BadRSAClientKeyExchange preMasterSecret := make([]byte, 48) vers := clientHello.vers - if bad == RSABadValueWrongVersion { + if bad == RSABadValueWrongVersion1 { vers ^= 1 + } else if bad == RSABadValueWrongVersion2 { + vers ^= 0x100 } preMasterSecret[0] = byte(vers >> 8) preMasterSecret[1] = byte(vers) @@ -152,13 +187,31 @@ func (ka *rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello sentPreMasterSecret := preMasterSecret if bad == RSABadValueTooLong { - sentPreMasterSecret = make([]byte, len(sentPreMasterSecret)+1) - copy(sentPreMasterSecret, preMasterSecret) + sentPreMasterSecret = make([]byte, 1, len(sentPreMasterSecret)+1) + sentPreMasterSecret = append(sentPreMasterSecret, preMasterSecret...) } else if bad == RSABadValueTooShort { sentPreMasterSecret = sentPreMasterSecret[:len(sentPreMasterSecret)-1] } - encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), sentPreMasterSecret) + // Pad for PKCS#1 v1.5. + padded := make([]byte, rsaSize(cert.PublicKey.(*rsa.PublicKey))) + padded[1] = 2 + nonZeroRandomBytes(padded[2:len(padded)-len(sentPreMasterSecret)-1], config.rand()) + copy(padded[len(padded)-len(sentPreMasterSecret):], sentPreMasterSecret) + + if bad == RSABadValueWrongBlockType { + padded[1] = 3 + } else if bad == RSABadValueWrongLeadingByte { + padded[0] = 1 + } else if bad == RSABadValueNoZero { + for i := 2; i < len(padded); i++ { + if padded[i] == 0 { + padded[i]++ + } + } + } + + encrypted, err := rsaRawEncrypt(cert.PublicKey.(*rsa.PublicKey), padded) if err != nil { return nil, nil, err } diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/prf.go b/vendor/github.com/google/boringssl/ssl/test/runner/prf.go index cfc383d..6fa3c4c 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/prf.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/prf.go @@ -180,9 +180,14 @@ func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clie return } -func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { +func newFinishedHash(wireVersion uint16, isDTLS bool, cipherSuite *cipherSuite) finishedHash { var ret finishedHash + version, ok := wireToVersion(wireVersion, isDTLS) + if !ok { + panic("unknown version") + } + if version >= VersionTLS12 { ret.hash = cipherSuite.hash() @@ -207,6 +212,7 @@ func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { ret.buffer = []byte{} ret.version = version + ret.wireVersion = wireVersion return ret } @@ -226,13 +232,28 @@ type finishedHash struct { // full buffer is required. buffer []byte - version uint16 - prf func(result, secret, label, seed []byte) + version uint16 + wireVersion uint16 + prf func(result, secret, label, seed []byte) // secret, in TLS 1.3, is the running input secret. secret []byte } +func (h *finishedHash) UpdateForHelloRetryRequest() (err error) { + data := newByteBuilder() + data.addU8(typeMessageHash) + data.addU24(h.hash.Size()) + data.addBytes(h.Sum()) + h.client = h.hash.New() + h.server = h.hash.New() + if h.buffer != nil { + h.buffer = []byte{} + } + h.Write(data.finish()) + return nil +} + func (h *finishedHash) Write(msg []byte) (n int, err error) { h.client.Write(msg) h.server.Write(msg) @@ -307,7 +328,7 @@ func (h finishedHash) clientSum(baseKey []byte) []byte { return out } - clientFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size()) + clientFinishedKey := hkdfExpandLabel(h.hash, h.wireVersion, baseKey, finishedLabel, nil, h.hash.Size()) finishedHMAC := hmac.New(h.hash.New, clientFinishedKey) finishedHMAC.Write(h.appendContextHashes(nil)) return finishedHMAC.Sum(nil) @@ -326,7 +347,7 @@ func (h finishedHash) serverSum(baseKey []byte) []byte { return out } - serverFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size()) + serverFinishedKey := hkdfExpandLabel(h.hash, h.wireVersion, baseKey, finishedLabel, nil, h.hash.Size()) finishedHMAC := hmac.New(h.hash.New, serverFinishedKey) finishedHMAC.Write(h.appendContextHashes(nil)) return finishedHMAC.Sum(nil) @@ -374,20 +395,33 @@ func (h *finishedHash) addEntropy(ikm []byte) { h.secret = hkdfExtract(h.hash.New, h.secret, ikm) } +func (h *finishedHash) nextSecret() { + if isDraft21(h.wireVersion) { + derivedLabel := []byte("derived") + h.secret = hkdfExpandLabel(h.hash, h.wireVersion, h.secret, derivedLabel, h.hash.New().Sum(nil), h.hash.Size()) + } +} + // hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined // in section 7.1 of draft-ietf-tls-tls13-16. -func hkdfExpandLabel(hash crypto.Hash, secret, label, hashValue []byte, length int) []byte { +func hkdfExpandLabel(hash crypto.Hash, version uint16, secret, label, hashValue []byte, length int) []byte { if len(label) > 255 || len(hashValue) > 255 { panic("hkdfExpandLabel: label or hashValue too long") } - hkdfLabel := make([]byte, 3+9+len(label)+1+len(hashValue)) + + versionLabel := []byte("TLS 1.3, ") + if isDraft21(version) { + versionLabel = []byte("tls13 ") + } + + hkdfLabel := make([]byte, 3+len(versionLabel)+len(label)+1+len(hashValue)) x := hkdfLabel x[0] = byte(length >> 8) x[1] = byte(length) - x[2] = byte(9 + len(label)) + x[2] = byte(len(versionLabel) + len(label)) x = x[3:] - copy(x, []byte("TLS 1.3, ")) - x = x[9:] + copy(x, versionLabel) + x = x[len(versionLabel):] copy(x, label) x = x[len(label):] x[0] = byte(len(hashValue)) @@ -414,12 +448,25 @@ var ( applicationTrafficLabel = []byte("application traffic secret") exporterLabel = []byte("exporter master secret") resumptionLabel = []byte("resumption master secret") + + externalPSKBinderLabelDraft21 = []byte("ext binder") + resumptionPSKBinderLabelDraft21 = []byte("res binder") + earlyTrafficLabelDraft21 = []byte("c e traffic") + clientHandshakeTrafficLabelDraft21 = []byte("c hs traffic") + serverHandshakeTrafficLabelDraft21 = []byte("s hs traffic") + clientApplicationTrafficLabelDraft21 = []byte("c ap traffic") + serverApplicationTrafficLabelDraft21 = []byte("s ap traffic") + applicationTrafficLabelDraft21 = []byte("traffic upd") + exporterLabelDraft21 = []byte("exp master") + resumptionLabelDraft21 = []byte("res master") + + resumptionPSKLabel = []byte("resumption") ) // deriveSecret implements TLS 1.3's Derive-Secret function, as defined in // section 7.1 of draft ietf-tls-tls13-16. func (h *finishedHash) deriveSecret(label []byte) []byte { - return hkdfExpandLabel(h.hash, h.secret, label, h.appendContextHashes(nil), h.hash.Size()) + return hkdfExpandLabel(h.hash, h.wireVersion, h.secret, label, h.appendContextHashes(nil), h.hash.Size()) } // The following are context strings for CertificateVerify in TLS 1.3. @@ -458,21 +505,34 @@ var ( // deriveTrafficAEAD derives traffic keys and constructs an AEAD given a traffic // secret. func deriveTrafficAEAD(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) interface{} { - key := hkdfExpandLabel(suite.hash(), secret, keyTLS13, nil, suite.keyLen) - iv := hkdfExpandLabel(suite.hash(), secret, ivTLS13, nil, suite.ivLen(version)) + key := hkdfExpandLabel(suite.hash(), version, secret, keyTLS13, nil, suite.keyLen) + iv := hkdfExpandLabel(suite.hash(), version, secret, ivTLS13, nil, suite.ivLen(version)) return suite.aead(version, key, iv) } -func updateTrafficSecret(hash crypto.Hash, secret []byte) []byte { - return hkdfExpandLabel(hash, secret, applicationTrafficLabel, nil, hash.Size()) +func updateTrafficSecret(hash crypto.Hash, version uint16, secret []byte) []byte { + trafficLabel := applicationTrafficLabel + if isDraft21(version) { + trafficLabel = applicationTrafficLabelDraft21 + } + return hkdfExpandLabel(hash, version, secret, trafficLabel, nil, hash.Size()) } -func computePSKBinder(psk, label []byte, cipherSuite *cipherSuite, transcript, truncatedHello []byte) []byte { - finishedHash := newFinishedHash(VersionTLS13, cipherSuite) +func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cipherSuite, clientHello, helloRetryRequest, truncatedHello []byte) []byte { + finishedHash := newFinishedHash(version, false, cipherSuite) finishedHash.addEntropy(psk) binderKey := finishedHash.deriveSecret(label) - finishedHash.Write(transcript) + finishedHash.Write(clientHello) + if isDraft21(version) && len(helloRetryRequest) != 0 { + finishedHash.UpdateForHelloRetryRequest() + } + finishedHash.Write(helloRetryRequest) finishedHash.Write(truncatedHello) return finishedHash.clientSum(binderKey) } + +func deriveSessionPSK(suite *cipherSuite, version uint16, masterSecret []byte, nonce []byte) []byte { + hash := suite.hash() + return hkdfExpandLabel(hash, version, masterSecret, resumptionPSKLabel, nonce, hash.Size()) +} diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/recordingconn.go b/vendor/github.com/google/boringssl/ssl/test/runner/recordingconn.go index 4dae435..427b236 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/recordingconn.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/recordingconn.go @@ -112,6 +112,10 @@ func (r *recordingConn) Transcript() []byte { if flow.flowType != writeFlow { continue } + if r.isDatagram { + // Prepend a length prefix to preserve packet boundaries. + ret = append(ret, byte(len(flow.data)>>16), byte(len(flow.data)>>8), byte(len(flow.data))) + } ret = append(ret, flow.data...) } return ret diff --git a/vendor/github.com/google/boringssl/ssl/test/runner/runner.go b/vendor/github.com/google/boringssl/ssl/test/runner/runner.go index 0ce6849..8700af2 100644 --- a/vendor/github.com/google/boringssl/ssl/test/runner/runner.go +++ b/vendor/github.com/google/boringssl/ssl/test/runner/runner.go @@ -837,6 +837,13 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, tr if err != nil { return err } + if config.Bugs.SplitAndPackAppData { + m, err := tlsConn.Read(bufTmp[n:]) + if err != nil { + return err + } + n += m + } if n != len(buf) { return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf)) } @@ -894,28 +901,20 @@ var ( // exit first. func acceptOrWait(listener *net.TCPListener, waitChan chan error) (net.Conn, error) { type connOrError struct { - conn net.Conn - err error - startTime, endTime time.Time + conn net.Conn + err error } connChan := make(chan connOrError, 1) go func() { - startTime := time.Now() if !*useGDB { listener.SetDeadline(time.Now().Add(*idleTimeout)) } conn, err := listener.Accept() - endTime := time.Now() - connChan <- connOrError{conn, err, startTime, endTime} + connChan <- connOrError{conn, err} close(connChan) }() select { case result := <-connChan: - if result.err != nil { - // TODO(davidben): Remove this logging when - // https://crbug.com/boringssl/199 is resolved. - fmt.Fprintf(os.Stderr, "acceptOrWait failed, startTime=%v, endTime=%v\n", result.startTime, result.endTime) - } return result.conn, result.err case childErr := <-waitChan: waitChan <- childErr @@ -1145,28 +1144,36 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error { listener.Close() listener = nil - var shimKilledLock sync.Mutex - var shimKilled bool - waitTimeout := time.AfterFunc(*idleTimeout, func() { + var childErr error + if *useGDB { + childErr = <-waitChan + } else { + var shimKilledLock sync.Mutex + var shimKilled bool + waitTimeout := time.AfterFunc(*idleTimeout, func() { + shimKilledLock.Lock() + shimKilled = true + shimKilledLock.Unlock() + shim.Process.Kill() + }) + childErr = <-waitChan + waitTimeout.Stop() shimKilledLock.Lock() - shimKilled = true + if shimKilled && err == nil { + err = errors.New("timeout waiting for the shim to exit.") + } shimKilledLock.Unlock() - shim.Process.Kill() - }) - childErr := <-waitChan - waitTimeout.Stop() - shimKilledLock.Lock() - if shimKilled && err == nil { - err = errors.New("timeout waiting for the shim to exit.") } - shimKilledLock.Unlock() - var isValgrindError bool + + var isValgrindError, mustFail bool if exitError, ok := childErr.(*exec.ExitError); ok { switch exitError.Sys().(syscall.WaitStatus).ExitStatus() { case 88: return errMoreMallocs case 89: return errUnimplemented + case 90: + mustFail = true case 99: isValgrindError = true } @@ -1196,7 +1203,7 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error { correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError) } - if failed != test.shouldFail || failed && !correctFailure { + if failed != test.shouldFail || failed && !correctFailure || mustFail { childError := "none" if childErr != nil { childError = childErr.Error() @@ -1210,6 +1217,8 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error { msg = "unexpected success" case failed && !correctFailure: msg = "bad error (wanted '" + expectedError + "' / '" + test.expectedLocalError + "')" + case mustFail: + msg = "test failure" default: panic("internal error") } @@ -1295,6 +1304,20 @@ var tlsVersions = []tlsVersion{ versionWire: tls13DraftVersion, tls13Variant: TLS13Default, }, + { + name: "TLS13Draft21", + version: VersionTLS13, + excludeFlag: "-no-tls13", + versionWire: tls13Draft21Version, + tls13Variant: TLS13Draft21, + }, + { + name: "TLS13Draft22", + version: VersionTLS13, + excludeFlag: "-no-tls13", + versionWire: tls13Draft22Version, + tls13Variant: TLS13Draft22, + }, { name: "TLS13Experiment", version: VersionTLS13, @@ -1303,11 +1326,18 @@ var tlsVersions = []tlsVersion{ tls13Variant: TLS13Experiment, }, { - name: "TLS13RecordTypeExperiment", + name: "TLS13Experiment2", version: VersionTLS13, excludeFlag: "-no-tls13", - versionWire: tls13RecordTypeExperimentVersion, - tls13Variant: TLS13RecordTypeExperiment, + versionWire: tls13Experiment2Version, + tls13Variant: TLS13Experiment2, + }, + { + name: "TLS13Experiment3", + version: VersionTLS13, + excludeFlag: "-no-tls13", + versionWire: tls13Experiment3Version, + tls13Variant: TLS13Experiment3, }, } @@ -1378,10 +1408,6 @@ func isTLS13Suite(suiteName string) bool { return strings.HasPrefix(suiteName, "AEAD-") } -func isDTLSCipher(suiteName string) bool { - return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL") -} - func bigFromHex(hex string) *big.Int { ret, ok := new(big.Int).SetString(hex, 16) if !ok { @@ -2122,6 +2148,19 @@ read alert 1 0 }, }, }, + { + testType: serverTest, + protocol: dtls, + name: "SendEmptyFragments-Padded-DTLS", + config: Config{ + Bugs: ProtocolBugs{ + // Test empty fragments for a message with a + // nice power-of-two length. + PadClientHello: 64, + SendEmptyFragments: true, + }, + }, + }, { name: "BadFinished-Client", config: Config{ @@ -2266,17 +2305,6 @@ read alert 1 0 }, flags: []string{"-async"}, }, - { - protocol: dtls, - name: "PackDTLSHandshake", - config: Config{ - Bugs: ProtocolBugs{ - MaxHandshakeRecordLength: 2, - PackHandshakeFragments: 20, - PackHandshakeRecords: 200, - }, - }, - }, { name: "SendEmptyRecords-Pass", sendEmptyRecords: 32, @@ -2414,9 +2442,10 @@ read alert 1 0 SendLargeRecords: true, }, }, - messageLen: maxPlaintext + 1, - shouldFail: true, - expectedError: ":DATA_LENGTH_TOO_LONG:", + messageLen: maxPlaintext + 1, + shouldFail: true, + expectedError: ":DATA_LENGTH_TOO_LONG:", + expectedLocalError: "remote error: record overflow", }, { protocol: dtls, @@ -2426,9 +2455,64 @@ read alert 1 0 SendLargeRecords: true, }, }, - messageLen: maxPlaintext + 1, - shouldFail: true, - expectedError: ":DATA_LENGTH_TOO_LONG:", + messageLen: maxPlaintext + 1, + shouldFail: true, + expectedError: ":DATA_LENGTH_TOO_LONG:", + expectedLocalError: "remote error: record overflow", + }, + { + name: "LargePlaintext-TLS13-Padded-8192-8192", + config: Config{ + MinVersion: VersionTLS13, + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + RecordPadding: 8192, + SendLargeRecords: true, + }, + }, + messageLen: 8192, + }, + { + name: "LargePlaintext-TLS13-Padded-8193-8192", + config: Config{ + MinVersion: VersionTLS13, + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + RecordPadding: 8193, + SendLargeRecords: true, + }, + }, + messageLen: 8192, + shouldFail: true, + expectedError: ":DATA_LENGTH_TOO_LONG:", + expectedLocalError: "remote error: record overflow", + }, + { + name: "LargePlaintext-TLS13-Padded-16383-1", + config: Config{ + MinVersion: VersionTLS13, + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + RecordPadding: 1, + SendLargeRecords: true, + }, + }, + messageLen: 16383, + }, + { + name: "LargePlaintext-TLS13-Padded-16384-1", + config: Config{ + MinVersion: VersionTLS13, + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + RecordPadding: 1, + SendLargeRecords: true, + }, + }, + messageLen: 16384, + shouldFail: true, + expectedError: ":DATA_LENGTH_TOO_LONG:", + expectedLocalError: "remote error: record overflow", }, { name: "LargeCiphertext", @@ -2469,7 +2553,7 @@ read alert 1 0 "-expect-total-renegotiations", "1", }, shouldFail: true, - expectedError: ":EXCESSIVE_MESSAGE_SIZE:", + expectedError: ":BAD_HELLO_REQUEST:", }, { name: "BadHelloRequest-2", @@ -2735,11 +2819,12 @@ read alert 1 0 }, }, { - // Test the server so there is a large certificate as - // well as application data. + // Test the TLS 1.2 server so there is a large + // unencrypted certificate as well as application data. testType: serverTest, - name: "MaxSendFragment", + name: "MaxSendFragment-TLS12", config: Config{ + MaxVersion: VersionTLS12, Bugs: ProtocolBugs{ MaxReceivePlaintext: 512, }, @@ -2751,11 +2836,12 @@ read alert 1 0 }, }, { - // Test the server so there is a large certificate as - // well as application data. + // Test the TLS 1.2 server so there is a large + // unencrypted certificate as well as application data. testType: serverTest, - name: "MaxSendFragment-TooLarge", + name: "MaxSendFragment-TLS12-TooLarge", config: Config{ + MaxVersion: VersionTLS12, Bugs: ProtocolBugs{ // Ensure that some of the records are // 512. @@ -2770,6 +2856,65 @@ read alert 1 0 shouldFail: true, expectedLocalError: "local error: record overflow", }, + { + // Test the TLS 1.3 server so there is a large encrypted + // certificate as well as application data. + testType: serverTest, + name: "MaxSendFragment-TLS13", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + MaxReceivePlaintext: 512, + }, + }, + messageLen: 1024, + flags: []string{ + "-max-send-fragment", "512", + "-read-size", "1024", + }, + }, + { + // Test the TLS 1.3 server so there is a large encrypted + // certificate as well as application data. + testType: serverTest, + name: "MaxSendFragment-TLS13-TooLarge", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + // Ensure that some of the records are + // 512. + MaxReceivePlaintext: 511, + }, + }, + messageLen: 1024, + flags: []string{ + "-max-send-fragment", "512", + "-read-size", "1024", + }, + shouldFail: true, + expectedLocalError: "local error: record overflow", + }, + { + // Test that DTLS can handle multiple application data + // records in a single packet. + protocol: dtls, + name: "SplitAndPackAppData-DTLS", + config: Config{ + Bugs: ProtocolBugs{ + SplitAndPackAppData: true, + }, + }, + }, + { + protocol: dtls, + name: "SplitAndPackAppData-DTLS-Async", + config: Config{ + Bugs: ProtocolBugs{ + SplitAndPackAppData: true, + }, + }, + flags: []string{"-async"}, + }, } testCases = append(testCases, basicTests...) @@ -2869,10 +3014,6 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto shouldClientFail = true shouldServerFail = true } - if !isDTLSCipher(suite.name) && protocol == dtls { - shouldClientFail = true - shouldServerFail = true - } var sendCipherSuite uint16 var expectedServerError, expectedClientError string @@ -3059,7 +3200,7 @@ func addCipherSuiteTests() { }, }, shouldFail: true, - expectedError: ":UNKNOWN_CIPHER_RETURNED:", + expectedError: ":WRONG_CIPHER_RETURNED:", }) // The server must be tolerant to bogus ciphers. @@ -3712,6 +3853,25 @@ func addClientAuthTests() { "-use-client-ca-list", "", }, }) + + // Test that an empty client CA list doesn't send a CA extension. + testCases = append(testCases, testCase{ + testType: serverTest, + name: "TLS13Draft21-Empty-Client-CA-List", + config: Config{ + MaxVersion: VersionTLS13, + Certificates: []Certificate{rsaCertificate}, + Bugs: ProtocolBugs{ + ExpectNoCertificateAuthoritiesExtension: true, + }, + }, + tls13Variant: TLS13Draft21, + flags: []string{ + "-require-any-client-certificate", + "-use-client-ca-list", "", + }, + }) + } func addExtendedMasterSecretTests() { @@ -3905,11 +4065,11 @@ func addExtendedMasterSecretTests() { } type stateMachineTestConfig struct { - protocol protocol - async bool - splitHandshake bool - packHandshakeFlight bool - implicitHandshake bool + protocol protocol + async bool + splitHandshake bool + packHandshake bool + implicitHandshake bool } // Adds tests that try to cover the range of the handshake state machine, under @@ -3932,13 +4092,11 @@ func addAllStateMachineCoverageTests() { async: async, splitHandshake: true, }) - if protocol == tls { - addStateMachineCoverageTests(stateMachineTestConfig{ - protocol: protocol, - async: async, - packHandshakeFlight: true, - }) - } + addStateMachineCoverageTests(stateMachineTestConfig{ + protocol: protocol, + async: async, + packHandshake: true, + }) } } } @@ -4065,82 +4223,34 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { }) tests = append(tests, testCase{ - testType: clientTest, - name: "TLS13-EarlyData-Client", + name: "TLS13Draft22-HelloRetryRequest-Client", config: Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - MaxEarlyDataSize: 16384, + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + // P-384 requires a HelloRetryRequest against BoringSSL's default + // configuration. Assert this with ExpectMissingKeyShare. + CurvePreferences: []CurveID{CurveP384}, Bugs: ProtocolBugs{ - ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}}, + ExpectMissingKeyShare: true, }, }, + tls13Variant: TLS13Draft22, + // Cover HelloRetryRequest during an ECDHE-PSK resumption. resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-accept-early-data", - "-on-resume-shim-writes-first", - }, }) tests = append(tests, testCase{ - testType: clientTest, - name: "TLS13Experiment-EarlyData-Client", + testType: serverTest, + name: "TLS13Draft22-HelloRetryRequest-Server", config: Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - MaxEarlyDataSize: 16384, + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + // Require a HelloRetryRequest for every curve. + DefaultCurves: []CurveID{}, }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}}, - }, - }, - tls13Variant: TLS13Experiment, + tls13Variant: TLS13Draft22, + // Cover HelloRetryRequest during an ECDHE-PSK resumption. resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-accept-early-data", - "-on-resume-shim-writes-first", - }, - }) - - tests = append(tests, testCase{ - testType: clientTest, - name: "TLS13RecordTypeExperiment-EarlyData-Client", - config: Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - TLS13Variant: TLS13RecordTypeExperiment, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - TLS13Variant: TLS13RecordTypeExperiment, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}}, - }, - }, - tls13Variant: TLS13RecordTypeExperiment, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-accept-early-data", - "-on-resume-shim-writes-first", - }, }) tests = append(tests, testCase{ @@ -4163,7 +4273,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { resumeSession: true, flags: []string{ "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", "-expect-accept-early-data", "-on-resume-shim-writes-first", }, @@ -4192,7 +4302,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { resumeSession: true, flags: []string{ "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", "-expect-accept-early-data", "-on-resume-read-with-unfinished-write", "-on-resume-shim-writes-first", @@ -4221,7 +4331,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { resumeSession: true, flags: []string{ "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", "-expect-reject-early-data", "-on-resume-read-with-unfinished-write", "-on-resume-shim-writes-first", @@ -4229,68 +4339,6 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { }) } - tests = append(tests, testCase{ - testType: serverTest, - name: "TLS13-EarlyData-Server", - config: Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - Bugs: ProtocolBugs{ - 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", - }, - }) - - tests = append(tests, testCase{ - testType: serverTest, - name: "TLS13Experiment-EarlyData-Server", - config: Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendEarlyData: [][]byte{{1, 2, 3, 4}}, - ExpectEarlyDataAccepted: true, - ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}}, - }, - }, - tls13Variant: TLS13Experiment, - messageCount: 2, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-accept-early-data", - }, - }) - - tests = append(tests, testCase{ - testType: serverTest, - name: "TLS13RecordTypeExperiment-EarlyData-Server", - config: Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendEarlyData: [][]byte{{1, 2, 3, 4}}, - ExpectEarlyDataAccepted: true, - ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}}, - }, - }, - tls13Variant: TLS13RecordTypeExperiment, - messageCount: 2, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-accept-early-data", - }, - }) - tests = append(tests, testCase{ testType: serverTest, name: "TLS13-MaxEarlyData-Server", @@ -4718,7 +4766,7 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { config: Config{ MaxVersion: VersionTLS12, Bugs: ProtocolBugs{ - PackHelloRequestWithFinished: config.packHandshakeFlight, + PackHelloRequestWithFinished: config.packHandshake, }, }, sendHalfHelloRequest: true, @@ -4994,6 +5042,92 @@ read alert 1 0 sendWarningAlerts: 1, flags: []string{"-check-close-notify"}, }) + + // Test that SSL_shutdown still processes KeyUpdate. + tests = append(tests, testCase{ + name: "Shutdown-Shim-KeyUpdate", + config: Config{ + MinVersion: VersionTLS13, + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + ExpectCloseNotify: true, + }, + }, + shimShutsDown: true, + sendKeyUpdates: 1, + keyUpdateRequest: keyUpdateRequested, + flags: []string{"-check-close-notify"}, + }) + + // Test that SSL_shutdown processes HelloRequest + // correctly. + tests = append(tests, testCase{ + name: "Shutdown-Shim-HelloRequest-Ignore", + config: Config{ + MinVersion: VersionTLS12, + MaxVersion: VersionTLS12, + Bugs: ProtocolBugs{ + SendHelloRequestBeforeEveryAppDataRecord: true, + ExpectCloseNotify: true, + }, + }, + shimShutsDown: true, + flags: []string{ + "-renegotiate-ignore", + "-check-close-notify", + }, + }) + tests = append(tests, testCase{ + name: "Shutdown-Shim-HelloRequest-Reject", + config: Config{ + MinVersion: VersionTLS12, + MaxVersion: VersionTLS12, + Bugs: ProtocolBugs{ + SendHelloRequestBeforeEveryAppDataRecord: true, + ExpectCloseNotify: true, + }, + }, + shimShutsDown: true, + shouldFail: true, + expectedError: ":NO_RENEGOTIATION:", + flags: []string{"-check-close-notify"}, + }) + tests = append(tests, testCase{ + name: "Shutdown-Shim-HelloRequest-CannotHandshake", + config: Config{ + MinVersion: VersionTLS12, + MaxVersion: VersionTLS12, + Bugs: ProtocolBugs{ + SendHelloRequestBeforeEveryAppDataRecord: true, + ExpectCloseNotify: true, + }, + }, + shimShutsDown: true, + shouldFail: true, + expectedError: ":NO_RENEGOTIATION:", + flags: []string{ + "-check-close-notify", + "-renegotiate-freely", + }, + }) + + tests = append(tests, testCase{ + testType: serverTest, + name: "Shutdown-Shim-Renegotiate-Server-Forbidden", + config: Config{ + MaxVersion: VersionTLS12, + Bugs: ProtocolBugs{ + ExpectCloseNotify: true, + }, + }, + shimShutsDown: true, + renegotiate: 1, + shouldFail: true, + expectedError: ":NO_RENEGOTIATION:", + flags: []string{ + "-check-close-notify", + }, + }) } } else { // TODO(davidben): DTLS 1.3 will want a similar thing for @@ -5028,9 +5162,16 @@ read alert 1 0 test.flags = append(test.flags, "-mtu", "256") } } - if config.packHandshakeFlight { - test.name += "-PackHandshakeFlight" - test.config.Bugs.PackHandshakeFlight = true + if config.packHandshake { + test.name += "-PackHandshake" + if config.protocol == dtls { + test.config.Bugs.MaxHandshakeRecordLength = 2 + test.config.Bugs.PackHandshakeFragments = 20 + test.config.Bugs.PackHandshakeRecords = 1500 + test.config.Bugs.PackAppDataWithHandshake = true + } else { + test.config.Bugs.PackHandshakeFlight = true + } } if config.implicitHandshake { test.name += "-ImplicitHandshake" @@ -5124,14 +5265,13 @@ func addVersionNegotiationTests() { } // When running and shim have different TLS 1.3 variants enabled, // shim clients are expected to fall back to TLS 1.2, while shim - // servers support both variants when enabled when the experiment is - // enabled. + // servers support multiple variants. expectedServerVersion := expectedVersion expectedClientVersion := expectedVersion if expectedVersion == VersionTLS13 && runnerVers.tls13Variant != shimVers.tls13Variant { expectedClientVersion = VersionTLS12 expectedServerVersion = VersionTLS12 - if shimVers.tls13Variant != TLS13Default { + if shimVers.tls13Variant != TLS13Default && runnerVers.tls13Variant != TLS13Draft21 && runnerVers.tls13Variant != TLS13Draft22 { expectedServerVersion = VersionTLS13 } } @@ -5150,6 +5290,9 @@ func addVersionNegotiationTests() { serverVers := expectedServerVersion if expectedServerVersion >= VersionTLS13 { serverVers = VersionTLS10 + if runnerVers.tls13Variant == TLS13Experiment2 || runnerVers.tls13Variant == TLS13Experiment3 || runnerVers.tls13Variant == TLS13Draft22 { + serverVers = VersionTLS12 + } } serverVers = recordVersionToWire(serverVers, protocol) @@ -7115,6 +7258,9 @@ func addRenegotiationTests() { }, }, renegotiate: 1, + // Test renegotiation after both an initial and resumption + // handshake. + resumeSession: true, flags: []string{ "-renegotiate-freely", "-expect-total-renegotiations", "1", @@ -8160,8 +8306,8 @@ func addSignatureAlgorithmTests() { expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:", }) - // Test that hash preferences are enforced. BoringSSL does not implement - // MD5 signatures. + // Test that signature preferences are enforced. BoringSSL does not + // implement MD5 signatures. testCases = append(testCases, testCase{ testType: serverTest, name: "ClientAuth-Enforced", @@ -8230,26 +8376,8 @@ func addSignatureAlgorithmTests() { expectedError: ":WRONG_SIGNATURE_TYPE:", }) - // Test that the agreed upon digest respects the client preferences and - // the server digests. - testCases = append(testCases, testCase{ - name: "NoCommonAlgorithms-Digests", - config: Config{ - MaxVersion: VersionTLS12, - ClientAuth: RequireAnyClientCert, - VerifySignatureAlgorithms: []signatureAlgorithm{ - signatureRSAPKCS1WithSHA512, - signatureRSAPKCS1WithSHA1, - }, - }, - flags: []string{ - "-cert-file", path.Join(*resourceDir, rsaCertificateFile), - "-key-file", path.Join(*resourceDir, rsaKeyFile), - "-digest-prefs", "SHA256", - }, - shouldFail: true, - expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:", - }) + // Test that the negotiated signature algorithm respects the client and + // server preferences. testCases = append(testCases, testCase{ name: "NoCommonAlgorithms", config: Config{ @@ -8299,7 +8427,8 @@ func addSignatureAlgorithmTests() { flags: []string{ "-cert-file", path.Join(*resourceDir, rsaCertificateFile), "-key-file", path.Join(*resourceDir, rsaKeyFile), - "-digest-prefs", "SHA256,SHA1", + "-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)), + "-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA1)), }, expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA256, }) @@ -8315,7 +8444,9 @@ func addSignatureAlgorithmTests() { flags: []string{ "-cert-file", path.Join(*resourceDir, rsaCertificateFile), "-key-file", path.Join(*resourceDir, rsaKeyFile), - "-digest-prefs", "SHA512,SHA256,SHA1", + "-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA512)), + "-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)), + "-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA1)), }, expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA1, }) @@ -9154,7 +9285,7 @@ func addCustomExtensionTests() { flags: []string{ "-enable-client-custom-extension", "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", "-expect-reject-early-data", }, }) @@ -9173,7 +9304,7 @@ func addCustomExtensionTests() { flags: []string{ "-enable-client-custom-extension", "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", "-expect-accept-early-data", }, }) @@ -9194,7 +9325,7 @@ func addCustomExtensionTests() { flags: []string{ "-enable-client-custom-extension", "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", "-expect-reject-early-data", }, }) @@ -9225,7 +9356,7 @@ func addCustomExtensionTests() { flags: []string{ "-enable-client-custom-extension", "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", }, }) @@ -9247,7 +9378,7 @@ func addCustomExtensionTests() { flags: []string{ "-enable-server-custom-extension", "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", }, }) @@ -9727,6 +9858,28 @@ func addCurveTests() { expectedError: ":ERROR_PARSING_EXTENSION:", }) + // Server-sent supported groups/curves are legal in TLS 1.3. They are + // illegal in TLS 1.2, but some servers send them anyway, so we must + // tolerate them. + testCases = append(testCases, testCase{ + name: "SupportedCurves-ServerHello-TLS12", + config: Config{ + MaxVersion: VersionTLS12, + Bugs: ProtocolBugs{ + SendServerSupportedCurves: true, + }, + }, + }) + testCases = append(testCases, testCase{ + name: "SupportedCurves-EncryptedExtensions-TLS13", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendServerSupportedCurves: true, + }, + }, + }) + // Test that we tolerate unknown point formats, as long as // pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to // check they are still functional. @@ -9987,7 +10140,7 @@ func addSessionTicketTests() { }, flags: []string{ "-enable-early-data", - "-expect-early-data-info", + "-expect-ticket-supports-early-data", }, }) @@ -10008,7 +10161,7 @@ func addSessionTicketTests() { MaxVersion: VersionTLS13, MaxEarlyDataSize: 16384, Bugs: ProtocolBugs{ - DuplicateTicketEarlyDataInfo: true, + DuplicateTicketEarlyData: true, }, }, shouldFail: true, @@ -10022,7 +10175,7 @@ func addSessionTicketTests() { config: Config{ MaxVersion: VersionTLS13, Bugs: ProtocolBugs{ - ExpectTicketEarlyDataInfo: true, + ExpectTicketEarlyData: true, }, }, flags: []string{ @@ -10681,13 +10834,38 @@ func makePerMessageTests() []perMessageTest { }, }) + ret = append(ret, perMessageTest{ + messageType: typeEndOfEarlyData, + test: testCase{ + testType: serverTest, + name: "TLS13Draft22-EndOfEarlyData", + config: Config{ + MaxVersion: VersionTLS13, + }, + resumeConfig: &Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendEarlyData: [][]byte{{1, 2, 3, 4}}, + ExpectEarlyDataAccepted: true, + }, + }, + tls13Variant: TLS13Draft22, + resumeSession: true, + flags: []string{"-enable-early-data"}, + }, + }) + return ret } func addWrongMessageTypeTests() { for _, t := range makePerMessageTests() { t.test.name = "WrongMessageType-" + t.test.name - t.test.config.Bugs.SendWrongMessageType = t.messageType + if t.test.resumeConfig != nil { + t.test.resumeConfig.Bugs.SendWrongMessageType = t.messageType + } else { + t.test.config.Bugs.SendWrongMessageType = t.messageType + } t.test.shouldFail = true t.test.expectedError = ":UNEXPECTED_MESSAGE:" t.test.expectedLocalError = "remote error: unexpected message" @@ -10722,7 +10900,11 @@ func addWrongMessageTypeTests() { func addTrailingMessageDataTests() { for _, t := range makePerMessageTests() { t.test.name = "TrailingMessageData-" + t.test.name - t.test.config.Bugs.SendTrailingMessageData = t.messageType + if t.test.resumeConfig != nil { + t.test.resumeConfig.Bugs.SendTrailingMessageData = t.messageType + } else { + t.test.config.Bugs.SendTrailingMessageData = t.messageType + } t.test.shouldFail = true t.test.expectedError = ":DECODE_ERROR:" t.test.expectedLocalError = "remote error: error decoding message" @@ -10746,597 +10928,100 @@ func addTrailingMessageDataTests() { } func addTLS13HandshakeTests() { - testCases = append(testCases, testCase{ - testType: clientTest, - name: "NegotiatePSKResumption-TLS13", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - NegotiatePSKResumption: true, - }, - }, - resumeSession: true, - shouldFail: true, - expectedError: ":MISSING_KEY_SHARE:", - }) - - testCases = append(testCases, testCase{ - testType: clientTest, - name: "MissingKeyShare-Client", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - MissingKeyShare: true, - }, - }, - shouldFail: true, - expectedError: ":MISSING_KEY_SHARE:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "MissingKeyShare-Server", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - MissingKeyShare: true, - }, - }, - shouldFail: true, - expectedError: ":MISSING_KEY_SHARE:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "DuplicateKeyShares", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - DuplicateKeyShares: true, - }, - }, - shouldFail: true, - expectedError: ":DUPLICATE_KEY_SHARE:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 4, - }, - }, - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-TLS13Experiment", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 4, - }, - }, - tls13Variant: TLS13Experiment, - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-TLS13RecordTypeExperiment", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 4, - }, - }, - tls13Variant: TLS13RecordTypeExperiment, - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-OmitEarlyDataExtension", - 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-TooMuchData", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 16384 + 1, - }, - }, - shouldFail: true, - expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-Interleaved", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 4, - InterleaveEarlyData: true, - }, - }, - shouldFail: true, - expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-EarlyDataInTLS12", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 4, - }, - }, - shouldFail: true, - expectedError: ":UNEXPECTED_RECORD:", - flags: []string{"-max-version", strconv.Itoa(VersionTLS12)}, - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-HRR", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 4, - }, - DefaultCurves: []CurveID{}, - }, - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-HRR-Interleaved", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 4, - InterleaveEarlyData: true, - }, - DefaultCurves: []CurveID{}, - }, - shouldFail: true, - expectedError: ":UNEXPECTED_RECORD:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-HRR-TooMuchData", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendFakeEarlyDataLength: 16384 + 1, - }, - DefaultCurves: []CurveID{}, - }, - shouldFail: true, - expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:", - }) - - // Test that skipping early data looking for cleartext correctly - // processes an alert record. - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-HRR-FatalAlert", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendEarlyAlert: true, - SendFakeEarlyDataLength: 4, - }, - DefaultCurves: []CurveID{}, - }, - shouldFail: true, - expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SkipEarlyData-SecondClientHelloEarlyData", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendEarlyDataOnSecondClientHello: true, - }, - DefaultCurves: []CurveID{}, - }, - shouldFail: true, - expectedLocalError: "remote error: bad record MAC", - }) - - testCases = append(testCases, testCase{ - testType: clientTest, - name: "EmptyEncryptedExtensions", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - EmptyEncryptedExtensions: true, - }, - }, - shouldFail: true, - expectedLocalError: "remote error: error decoding message", - }) - - testCases = append(testCases, testCase{ - testType: clientTest, - name: "EncryptedExtensionsWithKeyShare", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - EncryptedExtensionsWithKeyShare: true, - }, - }, - shouldFail: true, - expectedLocalError: "remote error: unsupported extension", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SendHelloRetryRequest", - config: Config{ - MaxVersion: VersionTLS13, - // Require a HelloRetryRequest for every curve. - DefaultCurves: []CurveID{}, - }, - expectedCurveID: CurveX25519, - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SendHelloRetryRequest-2", - config: Config{ - MaxVersion: VersionTLS13, - DefaultCurves: []CurveID{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{ - name: "UnknownCurve-HelloRetryRequest", - config: Config{ - MaxVersion: VersionTLS13, - // P-384 requires HelloRetryRequest in BoringSSL. - CurvePreferences: []CurveID{CurveP384}, - Bugs: ProtocolBugs{ - SendHelloRetryRequestCurve: bogusCurve, - }, - }, - shouldFail: true, - expectedError: ":WRONG_CURVE:", - }) - - testCases = append(testCases, testCase{ - name: "DisabledCurve-HelloRetryRequest", - config: Config{ - MaxVersion: VersionTLS13, - CurvePreferences: []CurveID{CurveP256}, - Bugs: ProtocolBugs{ - IgnorePeerCurvePreferences: true, - }, - }, - flags: []string{"-p384-only"}, - shouldFail: true, - expectedError: ":WRONG_CURVE:", - }) - - testCases = append(testCases, testCase{ - name: "UnnecessaryHelloRetryRequest", - config: Config{ - MaxVersion: VersionTLS13, - CurvePreferences: []CurveID{CurveX25519}, - Bugs: ProtocolBugs{ - SendHelloRetryRequestCurve: CurveX25519, - }, - }, - shouldFail: true, - expectedError: ":WRONG_CURVE:", - }) - - testCases = append(testCases, testCase{ - name: "SecondHelloRetryRequest", - config: Config{ - MaxVersion: VersionTLS13, - // P-384 requires HelloRetryRequest in BoringSSL. - CurvePreferences: []CurveID{CurveP384}, - Bugs: ProtocolBugs{ - SecondHelloRetryRequest: true, - }, - }, - shouldFail: true, - expectedError: ":UNEXPECTED_MESSAGE:", - }) - - testCases = append(testCases, testCase{ - name: "HelloRetryRequest-Empty", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - AlwaysSendHelloRetryRequest: true, - }, - }, - shouldFail: true, - expectedError: ":DECODE_ERROR:", - }) - - testCases = append(testCases, testCase{ - name: "HelloRetryRequest-DuplicateCurve", - 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, - }, - }, - shouldFail: true, - expectedError: ":DUPLICATE_EXTENSION:", - expectedLocalError: "remote error: illegal parameter", - }) - - testCases = append(testCases, testCase{ - name: "HelloRetryRequest-Cookie", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendHelloRetryRequestCookie: []byte("cookie"), - }, - }, - }) - - testCases = append(testCases, testCase{ - name: "HelloRetryRequest-DuplicateCookie", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendHelloRetryRequestCookie: []byte("cookie"), - DuplicateHelloRetryRequestExtensions: true, - }, - }, - shouldFail: true, - expectedError: ":DUPLICATE_EXTENSION:", - expectedLocalError: "remote error: illegal parameter", - }) - - testCases = append(testCases, testCase{ - name: "HelloRetryRequest-EmptyCookie", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendHelloRetryRequestCookie: []byte{}, - }, - }, - shouldFail: true, - expectedError: ":DECODE_ERROR:", - }) - - testCases = append(testCases, testCase{ - name: "HelloRetryRequest-Cookie-Curve", - 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-Unknown", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - CustomHelloRetryRequestExtension: "extension", - }, - }, - shouldFail: true, - expectedError: ":UNEXPECTED_EXTENSION:", - expectedLocalError: "remote error: unsupported extension", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SecondClientHelloMissingKeyShare", - config: Config{ - MaxVersion: VersionTLS13, - DefaultCurves: []CurveID{}, - Bugs: ProtocolBugs{ - SecondClientHelloMissingKeyShare: true, - }, - }, - shouldFail: true, - expectedError: ":MISSING_KEY_SHARE:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "SecondClientHelloWrongCurve", - config: Config{ - MaxVersion: VersionTLS13, - DefaultCurves: []CurveID{}, - Bugs: ProtocolBugs{ - MisinterpretHelloRetryRequestCurve: CurveP521, - }, - }, - shouldFail: true, - expectedError: ":WRONG_CURVE:", - }) - - testCases = append(testCases, testCase{ - name: "HelloRetryRequestVersionMismatch", - config: Config{ - MaxVersion: VersionTLS13, - // P-384 requires HelloRetryRequest in BoringSSL. - CurvePreferences: []CurveID{CurveP384}, - Bugs: ProtocolBugs{ - SendServerHelloVersion: 0x0305, - }, - }, - shouldFail: true, - expectedError: ":WRONG_VERSION_NUMBER:", - }) - - testCases = append(testCases, testCase{ - name: "HelloRetryRequestCurveMismatch", - 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, - }, - }, - shouldFail: true, - expectedError: ":WRONG_CURVE:", - }) - - // Test the server selecting a curve that requires a HelloRetryRequest - // without sending it. - testCases = append(testCases, testCase{ - name: "SkipHelloRetryRequest", - config: Config{ - MaxVersion: VersionTLS13, - // P-384 requires HelloRetryRequest in BoringSSL. - CurvePreferences: []CurveID{CurveP384}, - Bugs: ProtocolBugs{ - SkipHelloRetryRequest: true, - }, - }, - shouldFail: true, - expectedError: ":WRONG_CURVE:", - }) - - testCases = append(testCases, testCase{ - name: "TLS13-RequestContextInHandshake", - config: Config{ - MaxVersion: VersionTLS13, - MinVersion: VersionTLS13, - ClientAuth: RequireAnyClientCert, - Bugs: ProtocolBugs{ - SendRequestContext: []byte("request context"), - }, - }, - 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: "TLS13-TrailingKeyShareData", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - TrailingKeyShareData: true, - }, - }, - shouldFail: true, - expectedError: ":DECODE_ERROR:", - }) - - testCases = append(testCases, testCase{ - name: "TLS13-AlwaysSelectPSKIdentity", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - AlwaysSelectPSKIdentity: true, - }, - }, - shouldFail: true, - expectedError: ":UNEXPECTED_EXTENSION:", - }) - - testCases = append(testCases, testCase{ - name: "TLS13-InvalidPSKIdentity", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SelectPSKIdentityOnResume: 1, - }, - }, - resumeSession: true, - shouldFail: true, - expectedError: ":PSK_IDENTITY_NOT_FOUND:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-ExtraPSKIdentity", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - ExtraPSKIdentity: true, - SendExtraPSKBinder: true, - }, - }, - resumeSession: true, - }) - - // Test that unknown NewSessionTicket extensions are tolerated. - testCases = append(testCases, testCase{ - name: "TLS13-CustomTicketExtension", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - CustomTicketExtension: "1234", - }, - }, - }) - - for _, noSessionID := range []bool{false, true} { - prefix := "TLS13Experiment" - variant := TLS13Experiment - if noSessionID { - prefix = "TLS13NoSessionIDExperiment" - variant = TLS13NoSessionIDExperiment + 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, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":MISSING_KEY_SHARE:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "MissingKeyShare-Server-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + MissingKeyShare: true, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":MISSING_KEY_SHARE:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "DuplicateKeyShares-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + DuplicateKeyShares: true, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":DUPLICATE_KEY_SHARE:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-" + name, + 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: prefix + "-ResumeTLS12SessionID", + name: "ResumeTLS12SessionID-" + name, config: Config{ MaxVersion: VersionTLS12, SessionTicketsDisabled: true, }, + tls13Variant: variant, resumeSession: true, - flags: []string{"-tls13-variant", strconv.Itoa(variant)}, }) // Test that the server correctly echoes back session IDs of // various lengths. testCases = append(testCases, testCase{ testType: serverTest, - name: prefix + "-EmptySessionID", + name: "EmptySessionID-" + name, config: Config{ MaxVersion: VersionTLS13, Bugs: ProtocolBugs{ @@ -11348,7 +11033,7 @@ func addTLS13HandshakeTests() { testCases = append(testCases, testCase{ testType: serverTest, - name: prefix + "-ShortSessionID", + name: "ShortSessionID-" + name, config: Config{ MaxVersion: VersionTLS13, Bugs: ProtocolBugs{ @@ -11360,7 +11045,7 @@ func addTLS13HandshakeTests() { testCases = append(testCases, testCase{ testType: serverTest, - name: prefix + "-FullSessionID", + name: "FullSessionID-" + name, config: Config{ MaxVersion: VersionTLS13, Bugs: ProtocolBugs{ @@ -11369,707 +11054,1468 @@ func addTLS13HandshakeTests() { }, tls13Variant: variant, }) + + hasSessionID := false + if variant != TLS13Default { + hasSessionID = true + } + + // Test that the client sends a fake session ID in the correct experiments. + testCases = append(testCases, testCase{ + testType: clientTest, + name: "TLS13SessionID-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + ExpectClientHelloSessionID: hasSessionID, + }, + }, + tls13Variant: variant, + }) + + testCases = append(testCases, testCase{ + testType: clientTest, + name: "EarlyData-Client-" + name, + 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, + 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-Reject-Client-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + }, + 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", + }, + }) + + 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-" + 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-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 4, + OmitEarlyDataExtension: true, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-TooMuchData-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 16384 + 1, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-Interleaved-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 4, + InterleaveEarlyData: true, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-EarlyDataInTLS12-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 4, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":UNEXPECTED_RECORD:", + flags: []string{"-max-version", strconv.Itoa(VersionTLS12)}, + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-HRR-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 4, + }, + DefaultCurves: []CurveID{}, + }, + tls13Variant: variant, + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-HRR-Interleaved-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 4, + InterleaveEarlyData: true, + }, + DefaultCurves: []CurveID{}, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":UNEXPECTED_RECORD:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-HRR-TooMuchData-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendFakeEarlyDataLength: 16384 + 1, + }, + DefaultCurves: []CurveID{}, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:", + }) + + // 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{}, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "SkipEarlyData-SecondClientHelloEarlyData-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendEarlyDataOnSecondClientHello: true, + }, + DefaultCurves: []CurveID{}, + }, + tls13Variant: variant, + shouldFail: true, + expectedLocalError: "remote error: bad record MAC", + }) + + testCases = append(testCases, testCase{ + testType: clientTest, + name: "EmptyEncryptedExtensions-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + EmptyEncryptedExtensions: true, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedLocalError: "remote error: error decoding message", + }) + + 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-" + 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-" + name, + config: Config{ + MaxVersion: VersionTLS13, + DefaultCurves: []CurveID{CurveP384}, + }, + tls13Variant: variant, + // 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{ + name: "UnknownCurve-HelloRetryRequest-" + name, + config: Config{ + MaxVersion: VersionTLS13, + // P-384 requires HelloRetryRequest in BoringSSL. + CurvePreferences: []CurveID{CurveP384}, + Bugs: ProtocolBugs{ + SendHelloRetryRequestCurve: bogusCurve, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":WRONG_CURVE:", + }) + + if isDraft21(version.versionWire) { + testCases = append(testCases, testCase{ + name: "HelloRetryRequest-CipherChange-" + name, + config: Config{ + MaxVersion: VersionTLS13, + // P-384 requires HelloRetryRequest in BoringSSL. + CurvePreferences: []CurveID{CurveP384}, + Bugs: ProtocolBugs{ + SendCipherSuite: TLS_AES_128_GCM_SHA256, + SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256, + }, + }, + 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, + }, + CipherSuites: []uint16{ + TLS_AES_256_GCM_SHA384, + }, + }, + tls13Variant: variant, + resumeSession: true, + expectResumeRejected: true, + }) + } + + testCases = append(testCases, testCase{ + name: "DisabledCurve-HelloRetryRequest-" + name, + config: Config{ + MaxVersion: VersionTLS13, + CurvePreferences: []CurveID{CurveP256}, + Bugs: ProtocolBugs{ + IgnorePeerCurvePreferences: true, + }, + }, + tls13Variant: variant, + flags: []string{"-p384-only"}, + shouldFail: true, + expectedError: ":WRONG_CURVE:", + }) + + testCases = append(testCases, testCase{ + name: "UnnecessaryHelloRetryRequest-" + name, + config: Config{ + MaxVersion: VersionTLS13, + CurvePreferences: []CurveID{CurveX25519}, + Bugs: ProtocolBugs{ + SendHelloRetryRequestCurve: CurveX25519, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":UNEXPECTED_MESSAGE:", + }) + + testCases = append(testCases, testCase{ + name: "HelloRetryRequest-Empty-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + AlwaysSendHelloRetryRequest: true, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + 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"), + }, + }, + tls13Variant: variant, + }) + + testCases = append(testCases, testCase{ + name: "HelloRetryRequest-DuplicateCookie-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendHelloRetryRequestCookie: []byte("cookie"), + DuplicateHelloRetryRequestExtensions: true, + }, + }, + tls13Variant: variant, + 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{}, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + }) + + testCases = append(testCases, testCase{ + name: "HelloRetryRequest-Unknown-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + CustomHelloRetryRequestExtension: "extension", + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":WRONG_CURVE:", + }) + + testCases = append(testCases, testCase{ + name: "RequestContextInHandshake-" + name, + 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), + }, + shouldFail: true, + expectedError: ":DECODE_ERROR:", + }) + + if isDraft21(version.versionWire) { + testCases = append(testCases, testCase{ + name: "UnknownExtensionInCertificateRequest-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + ClientAuth: RequireAnyClientCert, + Bugs: ProtocolBugs{ + SendCustomCertificateRequest: 0x1212, + }, + }, + tls13Variant: variant, + flags: []string{ + "-cert-file", path.Join(*resourceDir, rsaCertificateFile), + "-key-file", path.Join(*resourceDir, rsaKeyFile), + }, + }) + + testCases = append(testCases, testCase{ + name: "MissingSignatureAlgorithmsInCertificateRequest-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MinVersion: VersionTLS13, + ClientAuth: RequireAnyClientCert, + Bugs: ProtocolBugs{ + OmitCertificateRequestAlgorithms: true, + }, + }, + tls13Variant: variant, + flags: []string{ + "-cert-file", path.Join(*resourceDir, rsaCertificateFile), + "-key-file", path.Join(*resourceDir, rsaKeyFile), + }, + shouldFail: true, + expectedError: ":DECODE_ERROR:", + }) + } + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "TrailingKeyShareData-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + TrailingKeyShareData: true, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":DECODE_ERROR:", + }) + + testCases = append(testCases, testCase{ + name: "AlwaysSelectPSKIdentity-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + AlwaysSelectPSKIdentity: true, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":UNEXPECTED_EXTENSION:", + }) + + testCases = append(testCases, testCase{ + name: "InvalidPSKIdentity-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SelectPSKIdentityOnResume: 1, + }, + }, + tls13Variant: variant, + 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, + }, + }, + tls13Variant: variant, + resumeSession: true, + }) + + // Test that unknown NewSessionTicket extensions are tolerated. + testCases = append(testCases, testCase{ + name: "CustomTicketExtension-" + name, + 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-HRR-Client-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + }, + 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", + }, + }) + + // 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, + }, + 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:", + }) + + // 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:", + }) + + // 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, + }, + 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:", + }) + + if isDraft22(version.versionWire) { + testCases = append(testCases, testCase{ + testType: clientTest, + name: "SkipChangeCipherSpec-Client-" + name, + 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, + }, + }, + tls13Variant: variant, + }) + + testCases = append(testCases, testCase{ + testType: clientTest, + name: "TooManyChangeCipherSpec-Client-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendExtraChangeCipherSpec: 33, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: "TooManyChangeCipherSpec-Server-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendExtraChangeCipherSpec: 33, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:", + }) + + testCases = append(testCases, testCase{ + name: "SendPostHandshakeChangeCipherSpec-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendPostHandshakeChangeCipherSpec: true, + }, + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":UNEXPECTED_RECORD:", + expectedLocalError: "remote error: unexpected message", + }) + } + + 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, + }, + }, + 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", + }, + }) + + // 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 second connection. + testCases = append(testCases, testCase{ + testType: clientTest, + name: "EarlyData-ALPNOmitted2-Client-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + NextProtos: []string{"foo"}, + }, + 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", + }, + }) + + // 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-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + NextProtos: []string{"foo", "bar"}, + }, + 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", + }, + }) + + // 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, + }, + 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", + }, + }) + + // 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{}, + }, + 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", + }, + }) + + // 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"}, + }, + 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", "", + }, + }) + + // 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-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + RequestChannelID: 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), + }, + }) + + // 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-" + 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-" + 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-" + 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-" + name, + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendEarlyData: [][]byte{{1, 2, 3, 4}}, + ExpectEarlyDataAccepted: true, + SkipEndOfEarlyData: true, + }, + }, + tls13Variant: variant, + resumeSession: true, + flags: []string{"-enable-early-data"}, + shouldFail: true, + expectedLocalError: "remote error: bad record MAC", + expectedError: ":BAD_DECRYPT:", + }) + + expectedError := ":UNEXPECTED_RECORD:" + if isDraft21(version.versionWire) { + // In draft-21 and up, early data is expected to be + // terminated by a handshake message, though we test + // with the wrong one. + expectedError = ":UNEXPECTED_MESSAGE:" + } + testCases = append(testCases, testCase{ + 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: expectedError, + 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-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + }, + tls13Variant: variant, + resumeSession: true, + flags: []string{ + "-enable-early-data", + "-expect-ticket-supports-early-data", + "-expect-accept-early-data", + "-expect-version", strconv.Itoa(VersionTLS13), + }, + }) + + // 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, + MaxEarlyDataSize: 16384, + }, + resumeConfig: &Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + 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", + }, + shouldFail: true, + expectedError: ":DIGEST_CHECK_FAILED:", + expectedLocalError: "remote error: error decrypting message", + }) + + if isDraft21(version.versionWire) { + testCases = append(testCases, testCase{ + testType: serverTest, + name: "Server-NonEmptyEndOfEarlyData-" + name, + config: Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + }, + resumeConfig: &Config{ + MaxVersion: VersionTLS13, + MaxEarlyDataSize: 16384, + Bugs: ProtocolBugs{ + SendEarlyData: [][]byte{{1, 2, 3, 4}}, + ExpectEarlyDataAccepted: true, + NonEmptyEndOfEarlyData: true, + }, + }, + resumeSession: true, + flags: []string{ + "-enable-early-data", + "-expect-ticket-supports-early-data", + "-expect-accept-early-data", + }, + tls13Variant: variant, + shouldFail: true, + expectedError: ":DECODE_ERROR:", + }) + } + + 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", + }) } - - // Test that the client sends a fake session ID in TLS13Experiment. - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13Experiment-RequireSessionID", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - ExpectClientHelloSessionID: true, - }, - }, - tls13Variant: TLS13Experiment, - }) - - // Test that the client does not send a fake session ID in - // TLS13NoSessionIDExperiment. - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13NoSessionIDExperiment-RequireEmptySessionID", - config: Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - ExpectEmptyClientHelloSessionID: true, - }, - }, - tls13Variant: TLS13NoSessionIDExperiment, - }) - - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13-EarlyData-Reject-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - AlwaysRejectEarlyData: true, - }, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-reject-early-data", - "-on-resume-shim-writes-first", - }, - }) - - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13Experiment-EarlyData-Reject-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - AlwaysRejectEarlyData: true, - }, - }, - tls13Variant: TLS13Experiment, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-reject-early-data", - "-on-resume-shim-writes-first", - }, - }) - - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13RecordTypeExperiment-EarlyData-Reject-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - AlwaysRejectEarlyData: true, - }, - }, - tls13Variant: TLS13RecordTypeExperiment, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-reject-early-data", - "-on-resume-shim-writes-first", - }, - }) - - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13-EarlyData-RejectTicket-Client", - 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-early-data-info", - "-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: "TLS13-EarlyData-HRR-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - SendHelloRetryRequestCookie: []byte{1, 2, 3, 4}, - }, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-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: "TLS13-EarlyDataWithoutResume-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - SessionTicketsDisabled: true, - Bugs: ProtocolBugs{ - SendEarlyDataExtension: true, - }, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - }, - 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: "TLS13-EarlyDataVersionDowngrade-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS12, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - }, - 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: "TLS13-ServerAcceptsEarlyDataOnHRR-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - SendHelloRetryRequestCookie: []byte{1, 2, 3, 4}, - SendEarlyDataExtension: true, - }, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-reject-early-data", - }, - shouldFail: true, - expectedError: ":UNEXPECTED_EXTENSION:", - }) - - 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: "TLS13-EarlyData-ALPNMismatch-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - ALPNProtocol: &fooString, - }, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - ALPNProtocol: &barString, - }, - }, - resumeSession: true, - flags: []string{ - "-advertise-alpn", "\x03foo\x03bar", - "-enable-early-data", - "-expect-early-data-info", - "-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: "TLS13-EarlyData-ALPNOmitted1-Client", - 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-early-data-info", - "-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: "TLS13-EarlyData-ALPNOmitted2-Client", - 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-early-data-info", - "-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 enforces ALPN match on 0-RTT accept. - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13-EarlyData-BadALPNMismatch-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - ALPNProtocol: &fooString, - }, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - AlwaysAcceptEarlyData: true, - ALPNProtocol: &barString, - }, - }, - resumeSession: true, - flags: []string{ - "-advertise-alpn", "\x03foo\x03bar", - "-enable-early-data", - "-expect-early-data-info", - "-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 server correctly rejects 0-RTT when the previous - // session did not allow early data on resumption. - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-EarlyData-NonZeroRTTSession-Server", - config: Config{ - MaxVersion: VersionTLS13, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendEarlyData: [][]byte{{1, 2, 3, 4}}, - ExpectEarlyDataAccepted: false, - }, - }, - resumeSession: true, - flags: []string{ - "-on-resume-enable-early-data", - "-expect-reject-early-data", - }, - }) - - // Test that we reject early data where ALPN is omitted from the first - // connection. - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-EarlyData-ALPNOmitted1-Server", - config: Config{ - MaxVersion: VersionTLS13, - NextProtos: []string{}, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - NextProtos: []string{"foo"}, - Bugs: ProtocolBugs{ - SendEarlyData: [][]byte{{1, 2, 3, 4}}, - ExpectEarlyDataAccepted: false, - }, - }, - 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 second - // connection. - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-EarlyData-ALPNOmitted2-Server", - config: Config{ - MaxVersion: VersionTLS13, - NextProtos: []string{"foo"}, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - NextProtos: []string{}, - Bugs: ProtocolBugs{ - SendEarlyData: [][]byte{{1, 2, 3, 4}}, - ExpectEarlyDataAccepted: false, - }, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-on-initial-select-alpn", "foo", - "-on-resume-select-alpn", "", - }, - }) - - // Test that we reject early data with mismatched ALPN. - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-EarlyData-ALPNMismatch-Server", - config: Config{ - MaxVersion: VersionTLS13, - NextProtos: []string{"foo"}, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - NextProtos: []string{"bar"}, - Bugs: ProtocolBugs{ - SendEarlyData: [][]byte{{1, 2, 3, 4}}, - ExpectEarlyDataAccepted: false, - }, - }, - 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: "TLS13-EarlyDataChannelID-AcceptBoth-Client", - 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-early-data-info", - "-send-channel-id", path.Join(*resourceDir, channelIDKeyFile), - }, - }) - - // Test that the client offering Channel ID and 0-RTT allows the server - // to decline 0-RTT. - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13-EarlyDataChannelID-AcceptChannelID-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - RequestChannelID: true, - Bugs: ProtocolBugs{ - AlwaysRejectEarlyData: true, - }, - }, - resumeSession: true, - expectChannelID: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-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: "TLS13-EarlyDataChannelID-AcceptEarlyData-Client", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-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: "TLS13-EarlyDataChannelID-OfferBoth-Server", - 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 accepts 0-RTT - // if not offered Channel ID. - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-EarlyDataChannelID-OfferEarlyData-Server", - 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 rejects 0-RTT streams without end_of_early_data. - // The subsequent records should fail to decrypt. - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-EarlyData-SkipEndOfEarlyData", - 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:", - }) - - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-EarlyData-UnexpectedHandshake-Server", - config: Config{ - MaxVersion: VersionTLS13, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - Bugs: ProtocolBugs{ - SendEarlyData: [][]byte{{1, 2, 3, 4}}, - SendStrayEarlyHandshake: true, - ExpectEarlyDataAccepted: true, - }, - }, - resumeSession: true, - shouldFail: true, - expectedError: ":UNEXPECTED_RECORD:", - 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: "TLS13-EarlyData-Client-VersionAPI", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-accept-early-data", - "-expect-version", strconv.Itoa(VersionTLS13), - }, - }) - - // Test that client and server both notice handshake errors after data - // has started flowing. - testCases = append(testCases, testCase{ - testType: clientTest, - name: "TLS13-EarlyData-Client-BadFinished", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - Bugs: ProtocolBugs{ - BadFinished: true, - }, - }, - resumeSession: true, - flags: []string{ - "-enable-early-data", - "-expect-early-data-info", - "-expect-accept-early-data", - }, - shouldFail: true, - expectedError: ":DIGEST_CHECK_FAILED:", - expectedLocalError: "remote error: error decrypting message", - }) - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-EarlyData-Server-BadFinished", - config: Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - }, - resumeConfig: &Config{ - MaxVersion: VersionTLS13, - MaxEarlyDataSize: 16384, - 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", - }) - testCases = append(testCases, testCase{ - testType: serverTest, - name: "TLS13-ServerSkipCertificateVerify", - config: Config{ - MinVersion: VersionTLS13, - MaxVersion: VersionTLS13, - Certificates: []Certificate{rsaChainCertificate}, - Bugs: ProtocolBugs{ - SkipCertificateVerify: 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: "TLS13-ClientSkipCertificateVerify", - config: Config{ - MinVersion: VersionTLS13, - MaxVersion: VersionTLS13, - Certificates: []Certificate{rsaChainCertificate}, - Bugs: ProtocolBugs{ - SkipCertificateVerify: true, - }, - }, - 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() { diff --git a/vendor/github.com/google/boringssl/ssl/test/test_config.cc b/vendor/github.com/google/boringssl/ssl/test/test_config.cc index 6df8d2a..a5ce5a1 100644 --- a/vendor/github.com/google/boringssl/ssl/test/test_config.cc +++ b/vendor/github.com/google/boringssl/ssl/test/test_config.cc @@ -81,7 +81,8 @@ const Flag kBoolFlags[] = { { "-tls-unique", &TestConfig::tls_unique }, { "-expect-ticket-renewal", &TestConfig::expect_ticket_renewal }, { "-expect-no-session", &TestConfig::expect_no_session }, - { "-expect-early-data-info", &TestConfig::expect_early_data_info }, + { "-expect-ticket-supports-early-data", + &TestConfig::expect_ticket_supports_early_data }, { "-use-ticket-callback", &TestConfig::use_ticket_callback }, { "-renew-ticket", &TestConfig::renew_ticket }, { "-enable-early-data", &TestConfig::enable_early_data }, @@ -121,6 +122,7 @@ const Flag kBoolFlags[] = { { "-expect-no-session-id", &TestConfig::expect_no_session_id }, { "-expect-accept-early-data", &TestConfig::expect_accept_early_data }, { "-expect-reject-early-data", &TestConfig::expect_reject_early_data }, + { "-expect-no-offer-early-data", &TestConfig::expect_no_offer_early_data }, { "-no-op-extra-handshake", &TestConfig::no_op_extra_handshake }, { "-handshake-twice", &TestConfig::handshake_twice }, { "-allow-unknown-alpn-protos", &TestConfig::allow_unknown_alpn_protos }, @@ -130,7 +132,6 @@ const Flag kBoolFlags[] = { const Flag kStringFlags[] = { { "-write-settings", &TestConfig::write_settings }, - { "-digest-prefs", &TestConfig::digest_prefs }, { "-key-file", &TestConfig::key_file }, { "-cert-file", &TestConfig::cert_file }, { "-expect-server-name", &TestConfig::expected_server_name }, diff --git a/vendor/github.com/google/boringssl/ssl/test/test_config.h b/vendor/github.com/google/boringssl/ssl/test/test_config.h index 9af64bc..ea12d34 100644 --- a/vendor/github.com/google/boringssl/ssl/test/test_config.h +++ b/vendor/github.com/google/boringssl/ssl/test/test_config.h @@ -26,7 +26,6 @@ struct TestConfig { int resume_count = 0; std::string write_settings; bool fallback_scsv = false; - std::string digest_prefs; std::vector signing_prefs; std::vector verify_prefs; std::string key_file; @@ -87,9 +86,10 @@ struct TestConfig { bool tls_unique = false; bool expect_ticket_renewal = false; bool expect_no_session = false; - bool expect_early_data_info = false; + bool expect_ticket_supports_early_data = false; bool expect_accept_early_data = false; bool expect_reject_early_data = false; + bool expect_no_offer_early_data = false; bool use_ticket_callback = false; bool renew_ticket = false; bool enable_early_data = false; diff --git a/vendor/manifest b/vendor/manifest index ccf5ab4..322d8a8 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -5,7 +5,7 @@ "importpath": "github.com/google/boringssl/ssl/test", "repository": "https://github.com/google/boringssl", "vcs": "git", - "revision": "74795b32c60104939f4c410a47e22b3027e98d06", + "revision": "855d5046c7899f19e2fad6ac83504a40cd92c6cc", "branch": "master", "path": "/ssl/test", "notests": true,