aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/boringssl/src/ssl/test
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/boringssl/src/ssl/test')
-rw-r--r--third_party/boringssl/src/ssl/test/CMakeLists.txt14
-rw-r--r--third_party/boringssl/src/ssl/test/async_bio.cc180
-rw-r--r--third_party/boringssl/src/ssl/test/async_bio.h42
-rw-r--r--third_party/boringssl/src/ssl/test/bssl_shim.cc1392
-rw-r--r--third_party/boringssl/src/ssl/test/packeted_bio.cc218
-rw-r--r--third_party/boringssl/src/ssl/test/packeted_bio.h44
-rw-r--r--third_party/boringssl/src/ssl/test/runner/alert.go77
-rw-r--r--third_party/boringssl/src/ssl/test/runner/cert.pem15
-rw-r--r--third_party/boringssl/src/ssl/test/runner/chacha20_poly1305.go159
-rw-r--r--third_party/boringssl/src/ssl/test/runner/chacha20_poly1305_test.go99
-rw-r--r--third_party/boringssl/src/ssl/test/runner/channel_id_key.pem5
-rw-r--r--third_party/boringssl/src/ssl/test/runner/cipher_suites.go423
-rw-r--r--third_party/boringssl/src/ssl/test/runner/common.go1123
-rw-r--r--third_party/boringssl/src/ssl/test/runner/conn.go1410
-rw-r--r--third_party/boringssl/src/ssl/test/runner/dtls.go431
-rw-r--r--third_party/boringssl/src/ssl/test/runner/ecdsa_cert.pem12
-rw-r--r--third_party/boringssl/src/ssl/test/runner/ecdsa_key.pem8
-rw-r--r--third_party/boringssl/src/ssl/test/runner/handshake_client.go1000
-rw-r--r--third_party/boringssl/src/ssl/test/runner/handshake_messages.go1759
-rw-r--r--third_party/boringssl/src/ssl/test/runner/handshake_server.go1049
-rw-r--r--third_party/boringssl/src/ssl/test/runner/key.pem15
-rw-r--r--third_party/boringssl/src/ssl/test/runner/key_agreement.go842
-rw-r--r--third_party/boringssl/src/ssl/test/runner/packet_adapter.go166
-rw-r--r--third_party/boringssl/src/ssl/test/runner/poly1305.go1540
-rw-r--r--third_party/boringssl/src/ssl/test/runner/prf.go388
-rw-r--r--third_party/boringssl/src/ssl/test/runner/recordingconn.go130
-rw-r--r--third_party/boringssl/src/ssl/test/runner/runner.go4442
-rw-r--r--third_party/boringssl/src/ssl/test/runner/runner_test.go7
-rw-r--r--third_party/boringssl/src/ssl/test/runner/test_output.go79
-rw-r--r--third_party/boringssl/src/ssl/test/runner/ticket.go221
-rw-r--r--third_party/boringssl/src/ssl/test/runner/tls.go279
-rw-r--r--third_party/boringssl/src/ssl/test/scoped_types.h28
-rw-r--r--third_party/boringssl/src/ssl/test/test_config.cc201
-rw-r--r--third_party/boringssl/src/ssl/test/test_config.h105
34 files changed, 0 insertions, 17903 deletions
diff --git a/third_party/boringssl/src/ssl/test/CMakeLists.txt b/third_party/boringssl/src/ssl/test/CMakeLists.txt
deleted file mode 100644
index 3b07903084..0000000000
--- a/third_party/boringssl/src/ssl/test/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-include_directories(../../include)
-
-add_executable(
- bssl_shim
-
- async_bio.cc
- bssl_shim.cc
- packeted_bio.cc
- test_config.cc
-
- $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(bssl_shim ssl crypto)
diff --git a/third_party/boringssl/src/ssl/test/async_bio.cc b/third_party/boringssl/src/ssl/test/async_bio.cc
deleted file mode 100644
index 05348457d8..0000000000
--- a/third_party/boringssl/src/ssl/test/async_bio.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Copyright (c) 2014, 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. */
-
-#include "async_bio.h"
-
-#include <errno.h>
-#include <string.h>
-
-#include <openssl/mem.h>
-
-
-namespace {
-
-extern const BIO_METHOD g_async_bio_method;
-
-struct AsyncBio {
- bool datagram;
- size_t read_quota;
- size_t write_quota;
-};
-
-AsyncBio *GetData(BIO *bio) {
- if (bio->method != &g_async_bio_method) {
- return NULL;
- }
- return (AsyncBio *)bio->ptr;
-}
-
-static int AsyncWrite(BIO *bio, const char *in, int inl) {
- AsyncBio *a = GetData(bio);
- if (a == NULL || bio->next_bio == NULL) {
- return 0;
- }
-
- if (a->datagram) {
- // Perform writes synchronously; the DTLS implementation drops any packets
- // that failed to send.
- return BIO_write(bio->next_bio, in, inl);
- }
-
- BIO_clear_retry_flags(bio);
-
- if (a->write_quota == 0) {
- BIO_set_retry_write(bio);
- errno = EAGAIN;
- return -1;
- }
-
- if (!a->datagram && (size_t)inl > a->write_quota) {
- inl = a->write_quota;
- }
- int ret = BIO_write(bio->next_bio, in, inl);
- if (ret <= 0) {
- BIO_copy_next_retry(bio);
- } else {
- a->write_quota -= (a->datagram ? 1 : ret);
- }
- return ret;
-}
-
-static int AsyncRead(BIO *bio, char *out, int outl) {
- AsyncBio *a = GetData(bio);
- if (a == NULL || bio->next_bio == NULL) {
- return 0;
- }
-
- BIO_clear_retry_flags(bio);
-
- if (a->read_quota == 0) {
- BIO_set_retry_read(bio);
- errno = EAGAIN;
- return -1;
- }
-
- if (!a->datagram && (size_t)outl > a->read_quota) {
- outl = a->read_quota;
- }
- int ret = BIO_read(bio->next_bio, out, outl);
- if (ret <= 0) {
- BIO_copy_next_retry(bio);
- } else {
- a->read_quota -= (a->datagram ? 1 : ret);
- }
- return ret;
-}
-
-static long AsyncCtrl(BIO *bio, int cmd, long num, void *ptr) {
- if (bio->next_bio == NULL) {
- return 0;
- }
- BIO_clear_retry_flags(bio);
- int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
- BIO_copy_next_retry(bio);
- return ret;
-}
-
-static int AsyncNew(BIO *bio) {
- AsyncBio *a = (AsyncBio *)OPENSSL_malloc(sizeof(*a));
- if (a == NULL) {
- return 0;
- }
- memset(a, 0, sizeof(*a));
- bio->init = 1;
- bio->ptr = (char *)a;
- return 1;
-}
-
-static int AsyncFree(BIO *bio) {
- if (bio == NULL) {
- return 0;
- }
-
- OPENSSL_free(bio->ptr);
- bio->ptr = NULL;
- bio->init = 0;
- bio->flags = 0;
- return 1;
-}
-
-static long AsyncCallbackCtrl(BIO *bio, int cmd, bio_info_cb fp) {
- if (bio->next_bio == NULL) {
- return 0;
- }
- return BIO_callback_ctrl(bio->next_bio, cmd, fp);
-}
-
-const BIO_METHOD g_async_bio_method = {
- BIO_TYPE_FILTER,
- "async bio",
- AsyncWrite,
- AsyncRead,
- NULL /* puts */,
- NULL /* gets */,
- AsyncCtrl,
- AsyncNew,
- AsyncFree,
- AsyncCallbackCtrl,
-};
-
-} // namespace
-
-ScopedBIO AsyncBioCreate() {
- return ScopedBIO(BIO_new(&g_async_bio_method));
-}
-
-ScopedBIO AsyncBioCreateDatagram() {
- ScopedBIO ret(BIO_new(&g_async_bio_method));
- if (!ret) {
- return nullptr;
- }
- GetData(ret.get())->datagram = true;
- return ret;
-}
-
-void AsyncBioAllowRead(BIO *bio, size_t count) {
- AsyncBio *a = GetData(bio);
- if (a == NULL) {
- return;
- }
- a->read_quota += count;
-}
-
-void AsyncBioAllowWrite(BIO *bio, size_t count) {
- AsyncBio *a = GetData(bio);
- if (a == NULL) {
- return;
- }
- a->write_quota += count;
-}
diff --git a/third_party/boringssl/src/ssl/test/async_bio.h b/third_party/boringssl/src/ssl/test/async_bio.h
deleted file mode 100644
index 1ccdf9b872..0000000000
--- a/third_party/boringssl/src/ssl/test/async_bio.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright (c) 2014, 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_ASYNC_BIO
-#define HEADER_ASYNC_BIO
-
-#include <openssl/bio.h>
-
-#include "../../crypto/test/scoped_types.h"
-
-
-// AsyncBioCreate creates a filter BIO for testing asynchronous state
-// machines which consume a stream socket. Reads and writes will fail
-// and return EAGAIN unless explicitly allowed. Each async BIO has a
-// read quota and a write quota. Initially both are zero. As each is
-// incremented, bytes are allowed to flow through the BIO.
-ScopedBIO AsyncBioCreate();
-
-// AsyncBioCreateDatagram creates a filter BIO for testing for
-// asynchronous state machines which consume datagram sockets. The read
-// and write quota count in packets rather than bytes.
-ScopedBIO AsyncBioCreateDatagram();
-
-// AsyncBioAllowRead increments |bio|'s read quota by |count|.
-void AsyncBioAllowRead(BIO *bio, size_t count);
-
-// AsyncBioAllowWrite increments |bio|'s write quota by |count|.
-void AsyncBioAllowWrite(BIO *bio, size_t count);
-
-
-#endif // HEADER_ASYNC_BIO
diff --git a/third_party/boringssl/src/ssl/test/bssl_shim.cc b/third_party/boringssl/src/ssl/test/bssl_shim.cc
deleted file mode 100644
index edae67b9ce..0000000000
--- a/third_party/boringssl/src/ssl/test/bssl_shim.cc
+++ /dev/null
@@ -1,1392 +0,0 @@
-/* Copyright (c) 2014, 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. */
-
-#include <openssl/base.h>
-
-#if !defined(OPENSSL_WINDOWS)
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-#else
-#include <io.h>
-#pragma warning(push, 3)
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#pragma warning(pop)
-
-#pragma comment(lib, "Ws2_32.lib")
-#endif
-
-#include <string.h>
-#include <sys/types.h>
-
-#include <openssl/bio.h>
-#include <openssl/buf.h>
-#include <openssl/bytestring.h>
-#include <openssl/cipher.h>
-#include <openssl/err.h>
-#include <openssl/hmac.h>
-#include <openssl/rand.h>
-#include <openssl/ssl.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "../../crypto/test/scoped_types.h"
-#include "async_bio.h"
-#include "packeted_bio.h"
-#include "scoped_types.h"
-#include "test_config.h"
-
-
-#if !defined(OPENSSL_WINDOWS)
-static int closesocket(int sock) {
- return close(sock);
-}
-
-static void PrintSocketError(const char *func) {
- perror(func);
-}
-#else
-static void PrintSocketError(const char *func) {
- fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
-}
-#endif
-
-static int Usage(const char *program) {
- fprintf(stderr, "Usage: %s [flags...]\n", program);
- return 1;
-}
-
-struct TestState {
- TestState() {
- // MSVC cannot initialize these inline.
- memset(&clock, 0, sizeof(clock));
- memset(&clock_delta, 0, sizeof(clock_delta));
- }
-
- // async_bio is async BIO which pauses reads and writes.
- BIO *async_bio = nullptr;
- // clock is the current time for the SSL connection.
- timeval clock;
- // clock_delta is how far the clock advanced in the most recent failed
- // |BIO_read|.
- timeval clock_delta;
- ScopedEVP_PKEY channel_id;
- bool cert_ready = false;
- ScopedSSL_SESSION session;
- ScopedSSL_SESSION pending_session;
- bool early_callback_called = false;
- bool handshake_done = false;
- // private_key is the underlying private key used when testing custom keys.
- ScopedEVP_PKEY private_key;
- std::vector<uint8_t> signature;
- // signature_retries is the number of times an asynchronous sign operation has
- // been retried.
- unsigned signature_retries = 0;
- bool got_new_session = false;
-};
-
-static void TestStateExFree(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
- int index, long argl, void *argp) {
- delete ((TestState *)ptr);
-}
-
-static int g_config_index = 0;
-static int g_state_index = 0;
-
-static bool SetConfigPtr(SSL *ssl, const TestConfig *config) {
- return SSL_set_ex_data(ssl, g_config_index, (void *)config) == 1;
-}
-
-static const TestConfig *GetConfigPtr(const SSL *ssl) {
- return (const TestConfig *)SSL_get_ex_data(ssl, g_config_index);
-}
-
-static bool SetTestState(SSL *ssl, std::unique_ptr<TestState> async) {
- if (SSL_set_ex_data(ssl, g_state_index, (void *)async.get()) == 1) {
- async.release();
- return true;
- }
- return false;
-}
-
-static TestState *GetTestState(const SSL *ssl) {
- return (TestState *)SSL_get_ex_data(ssl, g_state_index);
-}
-
-static ScopedEVP_PKEY LoadPrivateKey(const std::string &file) {
- ScopedBIO bio(BIO_new(BIO_s_file()));
- if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
- return nullptr;
- }
- ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL));
- return pkey;
-}
-
-static int AsyncPrivateKeyType(SSL *ssl) {
- return EVP_PKEY_id(GetTestState(ssl)->private_key.get());
-}
-
-static size_t AsyncPrivateKeyMaxSignatureLen(SSL *ssl) {
- return EVP_PKEY_size(GetTestState(ssl)->private_key.get());
-}
-
-static ssl_private_key_result_t AsyncPrivateKeySign(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
- const EVP_MD *md, const uint8_t *in, size_t in_len) {
- TestState *test_state = GetTestState(ssl);
- if (!test_state->signature.empty()) {
- fprintf(stderr, "AsyncPrivateKeySign called with operation pending.\n");
- abort();
- }
-
- ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(test_state->private_key.get(),
- nullptr));
- if (!ctx) {
- return ssl_private_key_failure;
- }
-
- // Write the signature into |test_state|.
- size_t len = 0;
- if (!EVP_PKEY_sign_init(ctx.get()) ||
- !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
- !EVP_PKEY_sign(ctx.get(), nullptr, &len, in, in_len)) {
- return ssl_private_key_failure;
- }
- test_state->signature.resize(len);
- if (!EVP_PKEY_sign(ctx.get(), bssl::vector_data(&test_state->signature), &len,
- in, in_len)) {
- return ssl_private_key_failure;
- }
- test_state->signature.resize(len);
-
- // The signature will be released asynchronously in |AsyncPrivateKeySignComplete|.
- return ssl_private_key_retry;
-}
-
-static ssl_private_key_result_t AsyncPrivateKeySignComplete(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
- TestState *test_state = GetTestState(ssl);
- if (test_state->signature.empty()) {
- fprintf(stderr,
- "AsyncPrivateKeySignComplete called without operation pending.\n");
- abort();
- }
-
- if (test_state->signature_retries < 2) {
- // Only return the signature on the second attempt, to test both incomplete
- // |sign| and |sign_complete|.
- return ssl_private_key_retry;
- }
-
- if (max_out < test_state->signature.size()) {
- fprintf(stderr, "Output buffer too small.\n");
- return ssl_private_key_failure;
- }
- memcpy(out, bssl::vector_data(&test_state->signature),
- test_state->signature.size());
- *out_len = test_state->signature.size();
-
- test_state->signature.clear();
- test_state->signature_retries = 0;
- return ssl_private_key_success;
-}
-
-static const SSL_PRIVATE_KEY_METHOD g_async_private_key_method = {
- AsyncPrivateKeyType,
- AsyncPrivateKeyMaxSignatureLen,
- AsyncPrivateKeySign,
- AsyncPrivateKeySignComplete,
-};
-
-template<typename T>
-struct Free {
- void operator()(T *buf) {
- free(buf);
- }
-};
-
-static bool InstallCertificate(SSL *ssl) {
- const TestConfig *config = GetConfigPtr(ssl);
- TestState *test_state = GetTestState(ssl);
-
- if (!config->digest_prefs.empty()) {
- std::unique_ptr<char, Free<char>> digest_prefs(
- strdup(config->digest_prefs.c_str()));
- std::vector<int> 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->key_file.empty()) {
- if (config->use_async_private_key) {
- test_state->private_key = LoadPrivateKey(config->key_file.c_str());
- if (!test_state->private_key) {
- return false;
- }
- SSL_set_private_key_method(ssl, &g_async_private_key_method);
- } else if (!SSL_use_PrivateKey_file(ssl, config->key_file.c_str(),
- SSL_FILETYPE_PEM)) {
- return false;
- }
- }
- if (!config->cert_file.empty() &&
- !SSL_use_certificate_file(ssl, config->cert_file.c_str(),
- SSL_FILETYPE_PEM)) {
- return false;
- }
- if (!config->ocsp_response.empty() &&
- !SSL_CTX_set_ocsp_response(ssl->ctx,
- (const uint8_t *)config->ocsp_response.data(),
- config->ocsp_response.size())) {
- return false;
- }
- return true;
-}
-
-static int SelectCertificateCallback(const struct ssl_early_callback_ctx *ctx) {
- const TestConfig *config = GetConfigPtr(ctx->ssl);
- GetTestState(ctx->ssl)->early_callback_called = true;
-
- if (!config->expected_server_name.empty()) {
- const uint8_t *extension_data;
- size_t extension_len;
- CBS extension, server_name_list, host_name;
- uint8_t name_type;
-
- if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
- &extension_data,
- &extension_len)) {
- fprintf(stderr, "Could not find server_name extension.\n");
- return -1;
- }
-
- CBS_init(&extension, extension_data, extension_len);
- if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) ||
- CBS_len(&extension) != 0 ||
- !CBS_get_u8(&server_name_list, &name_type) ||
- name_type != TLSEXT_NAMETYPE_host_name ||
- !CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
- CBS_len(&server_name_list) != 0) {
- fprintf(stderr, "Could not decode server_name extension.\n");
- return -1;
- }
-
- if (!CBS_mem_equal(&host_name,
- (const uint8_t*)config->expected_server_name.data(),
- config->expected_server_name.size())) {
- fprintf(stderr, "Server name mismatch.\n");
- }
- }
-
- if (config->fail_early_callback) {
- return -1;
- }
-
- // Install the certificate in the early callback.
- if (config->use_early_callback) {
- if (config->async) {
- // Install the certificate asynchronously.
- return 0;
- }
- if (!InstallCertificate(ctx->ssl)) {
- return -1;
- }
- }
- return 1;
-}
-
-static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) {
- SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx,
- SSL_get_ex_data_X509_STORE_CTX_idx());
- const TestConfig *config = GetConfigPtr(ssl);
-
- if (!config->expected_ocsp_response.empty()) {
- const uint8_t *data;
- size_t len;
- SSL_get0_ocsp_response(ssl, &data, &len);
- if (len == 0) {
- fprintf(stderr, "OCSP response not available in verify callback\n");
- return 0;
- }
- }
-
- return 1;
-}
-
-static int VerifyFail(X509_STORE_CTX *store_ctx, void *arg) {
- store_ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
- return 0;
-}
-
-static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out,
- unsigned int *out_len, void *arg) {
- const TestConfig *config = GetConfigPtr(ssl);
- if (config->advertise_npn.empty()) {
- return SSL_TLSEXT_ERR_NOACK;
- }
-
- *out = (const uint8_t*)config->advertise_npn.data();
- *out_len = config->advertise_npn.size();
- return SSL_TLSEXT_ERR_OK;
-}
-
-static int NextProtoSelectCallback(SSL* ssl, uint8_t** out, uint8_t* outlen,
- const uint8_t* in, unsigned inlen, void* arg) {
- const TestConfig *config = GetConfigPtr(ssl);
- if (config->select_next_proto.empty()) {
- return SSL_TLSEXT_ERR_NOACK;
- }
-
- *out = (uint8_t*)config->select_next_proto.data();
- *outlen = config->select_next_proto.size();
- return SSL_TLSEXT_ERR_OK;
-}
-
-static int AlpnSelectCallback(SSL* ssl, const uint8_t** out, uint8_t* outlen,
- const uint8_t* in, unsigned inlen, void* arg) {
- const TestConfig *config = GetConfigPtr(ssl);
- if (config->select_alpn.empty()) {
- return SSL_TLSEXT_ERR_NOACK;
- }
-
- if (!config->expected_advertised_alpn.empty() &&
- (config->expected_advertised_alpn.size() != inlen ||
- memcmp(config->expected_advertised_alpn.data(),
- in, inlen) != 0)) {
- fprintf(stderr, "bad ALPN select callback inputs\n");
- exit(1);
- }
-
- *out = (const uint8_t*)config->select_alpn.data();
- *outlen = config->select_alpn.size();
- return SSL_TLSEXT_ERR_OK;
-}
-
-static unsigned PskClientCallback(SSL *ssl, const char *hint,
- char *out_identity,
- unsigned max_identity_len,
- uint8_t *out_psk, unsigned max_psk_len) {
- const TestConfig *config = GetConfigPtr(ssl);
-
- if (strcmp(hint ? hint : "", config->psk_identity.c_str()) != 0) {
- fprintf(stderr, "Server PSK hint did not match.\n");
- return 0;
- }
-
- // Account for the trailing '\0' for the identity.
- if (config->psk_identity.size() >= max_identity_len ||
- config->psk.size() > max_psk_len) {
- fprintf(stderr, "PSK buffers too small\n");
- return 0;
- }
-
- BUF_strlcpy(out_identity, config->psk_identity.c_str(),
- max_identity_len);
- memcpy(out_psk, config->psk.data(), config->psk.size());
- return config->psk.size();
-}
-
-static unsigned PskServerCallback(SSL *ssl, const char *identity,
- uint8_t *out_psk, unsigned max_psk_len) {
- const TestConfig *config = GetConfigPtr(ssl);
-
- if (strcmp(identity, config->psk_identity.c_str()) != 0) {
- fprintf(stderr, "Client PSK identity did not match.\n");
- return 0;
- }
-
- if (config->psk.size() > max_psk_len) {
- fprintf(stderr, "PSK buffers too small\n");
- return 0;
- }
-
- memcpy(out_psk, config->psk.data(), config->psk.size());
- return config->psk.size();
-}
-
-static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
- *out_clock = GetTestState(ssl)->clock;
-}
-
-static void ChannelIdCallback(SSL *ssl, EVP_PKEY **out_pkey) {
- *out_pkey = GetTestState(ssl)->channel_id.release();
-}
-
-static int CertCallback(SSL *ssl, void *arg) {
- if (!GetTestState(ssl)->cert_ready) {
- return -1;
- }
- if (!InstallCertificate(ssl)) {
- return 0;
- }
- return 1;
-}
-
-static SSL_SESSION *GetSessionCallback(SSL *ssl, uint8_t *data, int len,
- int *copy) {
- TestState *async_state = GetTestState(ssl);
- if (async_state->session) {
- *copy = 0;
- return async_state->session.release();
- } else if (async_state->pending_session) {
- return SSL_magic_pending_session_ptr();
- } else {
- return NULL;
- }
-}
-
-static int DDoSCallback(const struct ssl_early_callback_ctx *early_context) {
- const TestConfig *config = GetConfigPtr(early_context->ssl);
- static int callback_num = 0;
-
- callback_num++;
- if (config->fail_ddos_callback ||
- (config->fail_second_ddos_callback && callback_num == 2)) {
- return 0;
- }
- return 1;
-}
-
-static void InfoCallback(const SSL *ssl, int type, int val) {
- if (type == SSL_CB_HANDSHAKE_DONE) {
- if (GetConfigPtr(ssl)->handshake_never_done) {
- fprintf(stderr, "handshake completed\n");
- // Abort before any expected error code is printed, to ensure the overall
- // test fails.
- abort();
- }
- GetTestState(ssl)->handshake_done = true;
- }
-}
-
-static int NewSessionCallback(SSL *ssl, SSL_SESSION *session) {
- GetTestState(ssl)->got_new_session = true;
- // BoringSSL passes a reference to |session|.
- SSL_SESSION_free(session);
- return 1;
-}
-
-static int TicketKeyCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv,
- EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
- int encrypt) {
- // This is just test code, so use the all-zeros key.
- static const uint8_t kZeros[16] = {0};
-
- if (encrypt) {
- memcpy(key_name, kZeros, sizeof(kZeros));
- RAND_bytes(iv, 16);
- } else if (memcmp(key_name, kZeros, 16) != 0) {
- return 0;
- }
-
- if (!HMAC_Init_ex(hmac_ctx, kZeros, sizeof(kZeros), EVP_sha256(), NULL) ||
- !EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, kZeros, iv, encrypt)) {
- return -1;
- }
-
- if (!encrypt) {
- return GetConfigPtr(ssl)->renew_ticket ? 2 : 1;
- }
- return 1;
-}
-
-// kCustomExtensionValue is the extension value that the custom extension
-// callbacks will add.
-static const uint16_t kCustomExtensionValue = 1234;
-static void *const kCustomExtensionAddArg =
- reinterpret_cast<void *>(kCustomExtensionValue);
-static void *const kCustomExtensionParseArg =
- reinterpret_cast<void *>(kCustomExtensionValue + 1);
-static const char kCustomExtensionContents[] = "custom extension";
-
-static int CustomExtensionAddCallback(SSL *ssl, unsigned extension_value,
- const uint8_t **out, size_t *out_len,
- int *out_alert_value, void *add_arg) {
- if (extension_value != kCustomExtensionValue ||
- add_arg != kCustomExtensionAddArg) {
- abort();
- }
-
- if (GetConfigPtr(ssl)->custom_extension_skip) {
- return 0;
- }
- if (GetConfigPtr(ssl)->custom_extension_fail_add) {
- return -1;
- }
-
- *out = reinterpret_cast<const uint8_t*>(kCustomExtensionContents);
- *out_len = sizeof(kCustomExtensionContents) - 1;
-
- return 1;
-}
-
-static void CustomExtensionFreeCallback(SSL *ssl, unsigned extension_value,
- const uint8_t *out, void *add_arg) {
- if (extension_value != kCustomExtensionValue ||
- add_arg != kCustomExtensionAddArg ||
- out != reinterpret_cast<const uint8_t *>(kCustomExtensionContents)) {
- abort();
- }
-}
-
-static int CustomExtensionParseCallback(SSL *ssl, unsigned extension_value,
- const uint8_t *contents,
- size_t contents_len,
- int *out_alert_value, void *parse_arg) {
- if (extension_value != kCustomExtensionValue ||
- parse_arg != kCustomExtensionParseArg) {
- abort();
- }
-
- if (contents_len != sizeof(kCustomExtensionContents) - 1 ||
- memcmp(contents, kCustomExtensionContents, contents_len) != 0) {
- *out_alert_value = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- return 1;
-}
-
-// Connect returns a new socket connected to localhost on |port| or -1 on
-// error.
-static int Connect(uint16_t port) {
- int sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock == -1) {
- PrintSocketError("socket");
- return -1;
- }
- int nodelay = 1;
- if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
- reinterpret_cast<const char*>(&nodelay), sizeof(nodelay)) != 0) {
- PrintSocketError("setsockopt");
- closesocket(sock);
- return -1;
- }
- sockaddr_in sin;
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
- PrintSocketError("inet_pton");
- closesocket(sock);
- return -1;
- }
- if (connect(sock, reinterpret_cast<const sockaddr*>(&sin),
- sizeof(sin)) != 0) {
- PrintSocketError("connect");
- closesocket(sock);
- return -1;
- }
- return sock;
-}
-
-class SocketCloser {
- public:
- explicit SocketCloser(int sock) : sock_(sock) {}
- ~SocketCloser() {
- // Half-close and drain the socket before releasing it. This seems to be
- // necessary for graceful shutdown on Windows. It will also avoid write
- // failures in the test runner.
-#if defined(OPENSSL_WINDOWS)
- shutdown(sock_, SD_SEND);
-#else
- shutdown(sock_, SHUT_WR);
-#endif
- while (true) {
- char buf[1024];
- if (recv(sock_, buf, sizeof(buf), 0) <= 0) {
- break;
- }
- }
- closesocket(sock_);
- }
-
- private:
- const int sock_;
-};
-
-static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
- ScopedSSL_CTX ssl_ctx(SSL_CTX_new(
- config->is_dtls ? DTLS_method() : TLS_method()));
- if (!ssl_ctx) {
- return nullptr;
- }
-
- std::string cipher_list = "ALL";
- if (!config->cipher.empty()) {
- cipher_list = config->cipher;
- SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
- }
- if (!SSL_CTX_set_cipher_list(ssl_ctx.get(), cipher_list.c_str())) {
- return nullptr;
- }
-
- if (!config->cipher_tls10.empty() &&
- !SSL_CTX_set_cipher_list_tls10(ssl_ctx.get(),
- config->cipher_tls10.c_str())) {
- return nullptr;
- }
- if (!config->cipher_tls11.empty() &&
- !SSL_CTX_set_cipher_list_tls11(ssl_ctx.get(),
- config->cipher_tls11.c_str())) {
- return nullptr;
- }
-
- ScopedDH dh(DH_get_2048_256(NULL));
- if (!dh || !SSL_CTX_set_tmp_dh(ssl_ctx.get(), dh.get())) {
- return nullptr;
- }
-
- if (config->async && config->is_server) {
- // Disable the internal session cache. To test asynchronous session lookup,
- // we use an external session cache.
- SSL_CTX_set_session_cache_mode(
- ssl_ctx.get(), SSL_SESS_CACHE_BOTH | SSL_SESS_CACHE_NO_INTERNAL);
- SSL_CTX_sess_set_get_cb(ssl_ctx.get(), GetSessionCallback);
- } else {
- SSL_CTX_set_session_cache_mode(ssl_ctx.get(), SSL_SESS_CACHE_BOTH);
- }
-
- ssl_ctx->select_certificate_cb = SelectCertificateCallback;
-
- SSL_CTX_set_next_protos_advertised_cb(
- ssl_ctx.get(), NextProtosAdvertisedCallback, NULL);
- if (!config->select_next_proto.empty()) {
- SSL_CTX_set_next_proto_select_cb(ssl_ctx.get(), NextProtoSelectCallback,
- NULL);
- }
-
- if (!config->select_alpn.empty()) {
- SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), AlpnSelectCallback, NULL);
- }
-
- SSL_CTX_enable_tls_channel_id(ssl_ctx.get());
- SSL_CTX_set_channel_id_cb(ssl_ctx.get(), ChannelIdCallback);
-
- ssl_ctx->current_time_cb = CurrentTimeCallback;
-
- SSL_CTX_set_info_callback(ssl_ctx.get(), InfoCallback);
- SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
-
- if (config->use_ticket_callback) {
- SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx.get(), TicketKeyCallback);
- }
-
- if (config->enable_client_custom_extension &&
- !SSL_CTX_add_client_custom_ext(
- ssl_ctx.get(), kCustomExtensionValue, CustomExtensionAddCallback,
- CustomExtensionFreeCallback, kCustomExtensionAddArg,
- CustomExtensionParseCallback, kCustomExtensionParseArg)) {
- return nullptr;
- }
-
- if (config->enable_server_custom_extension &&
- !SSL_CTX_add_server_custom_ext(
- ssl_ctx.get(), kCustomExtensionValue, CustomExtensionAddCallback,
- CustomExtensionFreeCallback, kCustomExtensionAddArg,
- CustomExtensionParseCallback, kCustomExtensionParseArg)) {
- return nullptr;
- }
-
- if (config->verify_fail) {
- SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifyFail, NULL);
- } else {
- SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifySucceed, NULL);
- }
-
- if (!config->signed_cert_timestamps.empty() &&
- !SSL_CTX_set_signed_cert_timestamp_list(
- ssl_ctx.get(), (const uint8_t *)config->signed_cert_timestamps.data(),
- config->signed_cert_timestamps.size())) {
- return nullptr;
- }
-
- return ssl_ctx;
-}
-
-// RetryAsync is called after a failed operation on |ssl| with return code
-// |ret|. If the operation should be retried, it simulates one asynchronous
-// event and returns true. Otherwise it returns false.
-static bool RetryAsync(SSL *ssl, int ret) {
- // No error; don't retry.
- if (ret >= 0) {
- return false;
- }
-
- TestState *test_state = GetTestState(ssl);
- if (test_state->clock_delta.tv_usec != 0 ||
- test_state->clock_delta.tv_sec != 0) {
- // Process the timeout and retry.
- test_state->clock.tv_usec += test_state->clock_delta.tv_usec;
- test_state->clock.tv_sec += test_state->clock.tv_usec / 1000000;
- test_state->clock.tv_usec %= 1000000;
- test_state->clock.tv_sec += test_state->clock_delta.tv_sec;
- memset(&test_state->clock_delta, 0, sizeof(test_state->clock_delta));
-
- if (DTLSv1_handle_timeout(ssl) < 0) {
- fprintf(stderr, "Error retransmitting.\n");
- return false;
- }
- return true;
- }
-
- // See if we needed to read or write more. If so, allow one byte through on
- // the appropriate end to maximally stress the state machine.
- switch (SSL_get_error(ssl, ret)) {
- case SSL_ERROR_WANT_READ:
- AsyncBioAllowRead(test_state->async_bio, 1);
- return true;
- case SSL_ERROR_WANT_WRITE:
- AsyncBioAllowWrite(test_state->async_bio, 1);
- return true;
- case SSL_ERROR_WANT_CHANNEL_ID_LOOKUP: {
- ScopedEVP_PKEY pkey = LoadPrivateKey(GetConfigPtr(ssl)->send_channel_id);
- if (!pkey) {
- return false;
- }
- test_state->channel_id = std::move(pkey);
- return true;
- }
- case SSL_ERROR_WANT_X509_LOOKUP:
- test_state->cert_ready = true;
- return true;
- case SSL_ERROR_PENDING_SESSION:
- test_state->session = std::move(test_state->pending_session);
- return true;
- case SSL_ERROR_PENDING_CERTIFICATE:
- // The handshake will resume without a second call to the early callback.
- return InstallCertificate(ssl);
- case SSL_ERROR_WANT_PRIVATE_KEY_OPERATION:
- test_state->signature_retries++;
- return true;
- default:
- return false;
- }
-}
-
-// 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) {
- const TestConfig *config = GetConfigPtr(ssl);
- int ret;
- do {
- ret = SSL_read(ssl, out, max_out);
- } while (config->async && RetryAsync(ssl, ret));
- return ret;
-}
-
-// WriteAll writes |in_len| bytes from |in| to |ssl|, resolving any asynchronous
-// operations. It returns the result of the final |SSL_write| call.
-static int WriteAll(SSL *ssl, const uint8_t *in, size_t in_len) {
- const TestConfig *config = GetConfigPtr(ssl);
- int ret;
- do {
- ret = SSL_write(ssl, in, in_len);
- if (ret > 0) {
- in += ret;
- in_len -= ret;
- }
- } while ((config->async && RetryAsync(ssl, ret)) || (ret > 0 && in_len > 0));
- return ret;
-}
-
-// DoShutdown calls |SSL_shutdown|, resolving any asynchronous operations. It
-// returns the result of the final |SSL_shutdown| call.
-static int DoShutdown(SSL *ssl) {
- const TestConfig *config = GetConfigPtr(ssl);
- int ret;
- do {
- ret = SSL_shutdown(ssl);
- } while (config->async && RetryAsync(ssl, ret));
- return ret;
-}
-
-// CheckHandshakeProperties checks, immediately after |ssl| completes its
-// initial handshake (or False Starts), whether all the properties are
-// consistent with the test configuration and invariants.
-static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
- const TestConfig *config = GetConfigPtr(ssl);
-
- if (SSL_get_current_cipher(ssl) == nullptr) {
- fprintf(stderr, "null cipher after handshake\n");
- return false;
- }
-
- if (is_resume &&
- (!!SSL_session_reused(ssl) == config->expect_session_miss)) {
- fprintf(stderr, "session was%s reused\n",
- SSL_session_reused(ssl) ? "" : " not");
- return false;
- }
-
- bool expect_handshake_done = is_resume || !config->false_start;
- if (expect_handshake_done != GetTestState(ssl)->handshake_done) {
- fprintf(stderr, "handshake was%s completed\n",
- GetTestState(ssl)->handshake_done ? "" : " not");
- return false;
- }
-
- if (expect_handshake_done && !config->is_server) {
- bool expect_new_session =
- !config->expect_no_session &&
- (!SSL_session_reused(ssl) || config->expect_ticket_renewal);
- if (expect_new_session != GetTestState(ssl)->got_new_session) {
- fprintf(stderr,
- "new session was%s established, but we expected the opposite\n",
- GetTestState(ssl)->got_new_session ? "" : " not");
- return false;
- }
- }
-
- if (config->is_server && !GetTestState(ssl)->early_callback_called) {
- fprintf(stderr, "early callback not called\n");
- return false;
- }
-
- if (!config->expected_server_name.empty()) {
- const char *server_name =
- SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
- if (server_name != config->expected_server_name) {
- fprintf(stderr, "servername mismatch (got %s; want %s)\n",
- server_name, config->expected_server_name.c_str());
- return false;
- }
- }
-
- if (!config->expected_certificate_types.empty()) {
- const uint8_t *certificate_types;
- size_t certificate_types_len =
- SSL_get0_certificate_types(ssl, &certificate_types);
- if (certificate_types_len != config->expected_certificate_types.size() ||
- memcmp(certificate_types,
- config->expected_certificate_types.data(),
- certificate_types_len) != 0) {
- fprintf(stderr, "certificate types mismatch\n");
- return false;
- }
- }
-
- if (!config->expected_next_proto.empty()) {
- const uint8_t *next_proto;
- unsigned next_proto_len;
- SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
- if (next_proto_len != config->expected_next_proto.size() ||
- memcmp(next_proto, config->expected_next_proto.data(),
- next_proto_len) != 0) {
- fprintf(stderr, "negotiated next proto mismatch\n");
- return false;
- }
- }
-
- if (!config->expected_alpn.empty()) {
- const uint8_t *alpn_proto;
- unsigned alpn_proto_len;
- SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
- if (alpn_proto_len != config->expected_alpn.size() ||
- memcmp(alpn_proto, config->expected_alpn.data(),
- alpn_proto_len) != 0) {
- fprintf(stderr, "negotiated alpn proto mismatch\n");
- return false;
- }
- }
-
- if (!config->expected_channel_id.empty()) {
- uint8_t channel_id[64];
- if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
- fprintf(stderr, "no channel id negotiated\n");
- return false;
- }
- if (config->expected_channel_id.size() != 64 ||
- memcmp(config->expected_channel_id.data(),
- channel_id, 64) != 0) {
- fprintf(stderr, "channel id mismatch\n");
- return false;
- }
- }
-
- if (config->expect_extended_master_secret) {
- if (!ssl->session->extended_master_secret) {
- fprintf(stderr, "No EMS for session when expected");
- return false;
- }
- }
-
- if (!config->expected_ocsp_response.empty()) {
- const uint8_t *data;
- size_t len;
- SSL_get0_ocsp_response(ssl, &data, &len);
- if (config->expected_ocsp_response.size() != len ||
- memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
- fprintf(stderr, "OCSP response mismatch\n");
- return false;
- }
- }
-
- if (!config->expected_signed_cert_timestamps.empty()) {
- const uint8_t *data;
- size_t len;
- SSL_get0_signed_cert_timestamp_list(ssl, &data, &len);
- if (config->expected_signed_cert_timestamps.size() != len ||
- memcmp(config->expected_signed_cert_timestamps.data(),
- data, len) != 0) {
- fprintf(stderr, "SCT list mismatch\n");
- return false;
- }
- }
-
- if (config->expect_verify_result) {
- int expected_verify_result = config->verify_fail ?
- X509_V_ERR_APPLICATION_VERIFICATION :
- X509_V_OK;
-
- if (SSL_get_verify_result(ssl) != expected_verify_result) {
- fprintf(stderr, "Wrong certificate verification result\n");
- return false;
- }
- }
-
- if (!config->is_server) {
- /* Clients should expect a peer certificate chain iff this was not a PSK
- * cipher suite. */
- if (config->psk.empty()) {
- if (SSL_get_peer_cert_chain(ssl) == nullptr) {
- fprintf(stderr, "Missing peer certificate chain!\n");
- return false;
- }
- } else if (SSL_get_peer_cert_chain(ssl) != nullptr) {
- fprintf(stderr, "Unexpected peer certificate chain!\n");
- return false;
- }
- }
- return true;
-}
-
-// DoExchange runs a test SSL exchange against the peer. On success, it returns
-// true and sets |*out_session| to the negotiated SSL session. If the test is a
-// resumption attempt, |is_resume| is true and |session| is the session from the
-// previous exchange.
-static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
- const TestConfig *config, bool is_resume,
- SSL_SESSION *session) {
- ScopedSSL ssl(SSL_new(ssl_ctx));
- if (!ssl) {
- return false;
- }
-
- if (!SetConfigPtr(ssl.get(), config) ||
- !SetTestState(ssl.get(), std::unique_ptr<TestState>(new TestState))) {
- return false;
- }
-
- if (config->fallback_scsv &&
- !SSL_set_mode(ssl.get(), SSL_MODE_SEND_FALLBACK_SCSV)) {
- return false;
- }
- if (!config->use_early_callback) {
- if (config->async) {
- // TODO(davidben): Also test |s->ctx->client_cert_cb| on the client.
- SSL_set_cert_cb(ssl.get(), CertCallback, NULL);
- } else if (!InstallCertificate(ssl.get())) {
- return false;
- }
- }
- if (config->require_any_client_certificate) {
- SSL_set_verify(ssl.get(), SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
- NULL);
- }
- if (config->verify_peer) {
- SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL);
- }
- if (config->false_start) {
- SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_FALSE_START);
- }
- if (config->cbc_record_splitting) {
- SSL_set_mode(ssl.get(), SSL_MODE_CBC_RECORD_SPLITTING);
- }
- if (config->partial_write) {
- SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_PARTIAL_WRITE);
- }
- if (config->no_tls12) {
- SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_2);
- }
- if (config->no_tls11) {
- SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_1);
- }
- if (config->no_tls1) {
- SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1);
- }
- if (config->no_ssl3) {
- SSL_set_options(ssl.get(), SSL_OP_NO_SSLv3);
- }
- if (config->tls_d5_bug) {
- SSL_set_options(ssl.get(), SSL_OP_TLS_D5_BUG);
- }
- if (config->microsoft_big_sslv3_buffer) {
- SSL_set_options(ssl.get(), SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
- }
- if (config->no_legacy_server_connect) {
- SSL_clear_options(ssl.get(), SSL_OP_LEGACY_SERVER_CONNECT);
- }
- if (!config->expected_channel_id.empty()) {
- SSL_enable_tls_channel_id(ssl.get());
- }
- if (!config->send_channel_id.empty()) {
- SSL_enable_tls_channel_id(ssl.get());
- if (!config->async) {
- // The async case will be supplied by |ChannelIdCallback|.
- ScopedEVP_PKEY pkey = LoadPrivateKey(config->send_channel_id);
- if (!pkey || !SSL_set1_tls_channel_id(ssl.get(), pkey.get())) {
- return false;
- }
- }
- }
- if (!config->host_name.empty() &&
- !SSL_set_tlsext_host_name(ssl.get(), config->host_name.c_str())) {
- return false;
- }
- if (!config->advertise_alpn.empty() &&
- SSL_set_alpn_protos(ssl.get(),
- (const uint8_t *)config->advertise_alpn.data(),
- config->advertise_alpn.size()) != 0) {
- return false;
- }
- if (!config->psk.empty()) {
- SSL_set_psk_client_callback(ssl.get(), PskClientCallback);
- SSL_set_psk_server_callback(ssl.get(), PskServerCallback);
- }
- if (!config->psk_identity.empty() &&
- !SSL_use_psk_identity_hint(ssl.get(), config->psk_identity.c_str())) {
- return false;
- }
- if (!config->srtp_profiles.empty() &&
- !SSL_set_srtp_profiles(ssl.get(), config->srtp_profiles.c_str())) {
- return false;
- }
- if (config->enable_ocsp_stapling &&
- !SSL_enable_ocsp_stapling(ssl.get())) {
- return false;
- }
- if (config->enable_signed_cert_timestamps &&
- !SSL_enable_signed_cert_timestamps(ssl.get())) {
- return false;
- }
- if (config->min_version != 0) {
- SSL_set_min_version(ssl.get(), (uint16_t)config->min_version);
- }
- if (config->max_version != 0) {
- SSL_set_max_version(ssl.get(), (uint16_t)config->max_version);
- }
- if (config->mtu != 0) {
- SSL_set_options(ssl.get(), SSL_OP_NO_QUERY_MTU);
- SSL_set_mtu(ssl.get(), config->mtu);
- }
- if (config->install_ddos_callback) {
- SSL_CTX_set_dos_protection_cb(ssl_ctx, DDoSCallback);
- }
- if (!config->reject_peer_renegotiations) {
- /* Renegotiations are disabled by default. */
- SSL_set_reject_peer_renegotiations(ssl.get(), 0);
- }
- if (!config->check_close_notify) {
- SSL_set_quiet_shutdown(ssl.get(), 1);
- }
-
- int sock = Connect(config->port);
- if (sock == -1) {
- return false;
- }
- SocketCloser closer(sock);
-
- ScopedBIO bio(BIO_new_socket(sock, BIO_NOCLOSE));
- if (!bio) {
- return false;
- }
- if (config->is_dtls) {
- ScopedBIO packeted =
- PacketedBioCreate(&GetTestState(ssl.get())->clock_delta);
- BIO_push(packeted.get(), bio.release());
- bio = std::move(packeted);
- }
- if (config->async) {
- ScopedBIO async_scoped =
- config->is_dtls ? AsyncBioCreateDatagram() : AsyncBioCreate();
- BIO_push(async_scoped.get(), bio.release());
- GetTestState(ssl.get())->async_bio = async_scoped.get();
- bio = std::move(async_scoped);
- }
- SSL_set_bio(ssl.get(), bio.get(), bio.get());
- bio.release(); // SSL_set_bio takes ownership.
-
- if (session != NULL) {
- if (!config->is_server) {
- if (SSL_set_session(ssl.get(), session) != 1) {
- return false;
- }
- } else if (config->async) {
- // The internal session cache is disabled, so install the session
- // manually.
- GetTestState(ssl.get())->pending_session.reset(
- SSL_SESSION_up_ref(session));
- }
- }
-
- if (SSL_get_current_cipher(ssl.get()) != nullptr) {
- fprintf(stderr, "non-null cipher before handshake\n");
- return false;
- }
-
- int ret;
- if (config->implicit_handshake) {
- if (config->is_server) {
- SSL_set_accept_state(ssl.get());
- } else {
- SSL_set_connect_state(ssl.get());
- }
- } else {
- do {
- if (config->is_server) {
- ret = SSL_accept(ssl.get());
- } else {
- ret = SSL_connect(ssl.get());
- }
- } while (config->async && RetryAsync(ssl.get(), ret));
- if (ret != 1 ||
- !CheckHandshakeProperties(ssl.get(), is_resume)) {
- return false;
- }
-
- // Reset the state to assert later that the callback isn't called in
- // renegotations.
- GetTestState(ssl.get())->got_new_session = false;
- }
-
- if (config->export_keying_material > 0) {
- std::vector<uint8_t> result(
- static_cast<size_t>(config->export_keying_material));
- if (!SSL_export_keying_material(
- ssl.get(), result.data(), result.size(),
- config->export_label.data(), config->export_label.size(),
- reinterpret_cast<const uint8_t*>(config->export_context.data()),
- config->export_context.size(), config->use_export_context)) {
- fprintf(stderr, "failed to export keying material\n");
- return false;
- }
- if (WriteAll(ssl.get(), result.data(), result.size()) < 0) {
- return false;
- }
- }
-
- if (config->tls_unique) {
- uint8_t tls_unique[16];
- size_t tls_unique_len;
- if (!SSL_get_tls_unique(ssl.get(), tls_unique, &tls_unique_len,
- sizeof(tls_unique))) {
- fprintf(stderr, "failed to get tls-unique\n");
- return false;
- }
-
- if (tls_unique_len != 12) {
- fprintf(stderr, "expected 12 bytes of tls-unique but got %u",
- static_cast<unsigned>(tls_unique_len));
- return false;
- }
-
- if (WriteAll(ssl.get(), tls_unique, tls_unique_len) < 0) {
- return false;
- }
- }
-
- if (config->write_different_record_sizes) {
- if (config->is_dtls) {
- fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
- return false;
- }
- // This mode writes a number of different record sizes in an attempt to
- // trip up the CBC record splitting code.
- static const size_t kBufLen = 32769;
- std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
- memset(buf.get(), 0x42, kBufLen);
- static const size_t kRecordSizes[] = {
- 0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
- for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]);
- i++) {
- const size_t len = kRecordSizes[i];
- if (len > kBufLen) {
- fprintf(stderr, "Bad kRecordSizes value.\n");
- return false;
- }
- if (WriteAll(ssl.get(), buf.get(), len) < 0) {
- return false;
- }
- }
- } else {
- if (config->shim_writes_first) {
- if (WriteAll(ssl.get(), reinterpret_cast<const uint8_t *>("hello"),
- 5) < 0) {
- return false;
- }
- }
- if (!config->shim_shuts_down) {
- for (;;) {
- static const size_t kBufLen = 16384;
- std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
-
- // Read only 512 bytes at a time in TLS to ensure records may be
- // returned in multiple reads.
- int n = DoRead(ssl.get(), buf.get(), config->is_dtls ? kBufLen : 512);
- int err = SSL_get_error(ssl.get(), n);
- if (err == SSL_ERROR_ZERO_RETURN ||
- (n == 0 && err == SSL_ERROR_SYSCALL)) {
- if (n != 0) {
- fprintf(stderr, "Invalid SSL_get_error output\n");
- return false;
- }
- // Stop on either clean or unclean shutdown.
- break;
- } else if (err != SSL_ERROR_NONE) {
- if (n > 0) {
- fprintf(stderr, "Invalid SSL_get_error output\n");
- return false;
- }
- return false;
- }
- // Successfully read data.
- if (n <= 0) {
- fprintf(stderr, "Invalid SSL_get_error output\n");
- return false;
- }
-
- // After a successful read, with or without False Start, the handshake
- // must be complete.
- if (!GetTestState(ssl.get())->handshake_done) {
- fprintf(stderr, "handshake was not completed after SSL_read\n");
- return false;
- }
-
- for (int i = 0; i < n; i++) {
- buf[i] ^= 0xff;
- }
- if (WriteAll(ssl.get(), buf.get(), n) < 0) {
- return false;
- }
- }
- }
- }
-
- if (!config->is_server && !config->false_start &&
- !config->implicit_handshake &&
- GetTestState(ssl.get())->got_new_session) {
- fprintf(stderr, "new session was established after the handshake\n");
- return false;
- }
-
- if (out_session) {
- out_session->reset(SSL_get1_session(ssl.get()));
- }
-
- ret = DoShutdown(ssl.get());
-
- if (config->shim_shuts_down && config->check_close_notify) {
- // We initiate shutdown, so |SSL_shutdown| will return in two stages. First
- // it returns zero when our close_notify is sent, then one when the peer's
- // is received.
- if (ret != 0) {
- fprintf(stderr, "Unexpected SSL_shutdown result: %d != 0\n", ret);
- return false;
- }
- ret = DoShutdown(ssl.get());
- }
-
- if (ret != 1) {
- fprintf(stderr, "Unexpected SSL_shutdown result: %d != 1\n", ret);
- return false;
- }
-
- return true;
-}
-
-int main(int argc, char **argv) {
-#if defined(OPENSSL_WINDOWS)
- /* Initialize Winsock. */
- WORD wsa_version = MAKEWORD(2, 2);
- WSADATA wsa_data;
- int wsa_err = WSAStartup(wsa_version, &wsa_data);
- if (wsa_err != 0) {
- fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
- return 1;
- }
- if (wsa_data.wVersion != wsa_version) {
- fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
- return 1;
- }
-#else
- signal(SIGPIPE, SIG_IGN);
-#endif
-
- if (!SSL_library_init()) {
- return 1;
- }
- g_config_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- g_state_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, TestStateExFree);
- if (g_config_index < 0 || g_state_index < 0) {
- return 1;
- }
-
- TestConfig config;
- if (!ParseConfig(argc - 1, argv + 1, &config)) {
- return Usage(argv[0]);
- }
-
- ScopedSSL_CTX ssl_ctx = SetupCtx(&config);
- if (!ssl_ctx) {
- ERR_print_errors_fp(stderr);
- return 1;
- }
-
- ScopedSSL_SESSION session;
- if (!DoExchange(&session, ssl_ctx.get(), &config, false /* is_resume */,
- NULL /* session */)) {
- ERR_print_errors_fp(stderr);
- return 1;
- }
-
- if (config.resume &&
- !DoExchange(NULL, ssl_ctx.get(), &config, true /* is_resume */,
- session.get())) {
- ERR_print_errors_fp(stderr);
- return 1;
- }
-
- return 0;
-}
diff --git a/third_party/boringssl/src/ssl/test/packeted_bio.cc b/third_party/boringssl/src/ssl/test/packeted_bio.cc
deleted file mode 100644
index e831082aeb..0000000000
--- a/third_party/boringssl/src/ssl/test/packeted_bio.cc
+++ /dev/null
@@ -1,218 +0,0 @@
-/* Copyright (c) 2014, 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. */
-
-#include "packeted_bio.h"
-
-#include <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/mem.h>
-
-
-namespace {
-
-extern const BIO_METHOD g_packeted_bio_method;
-
-const uint8_t kOpcodePacket = 'P';
-const uint8_t kOpcodeTimeout = 'T';
-const uint8_t kOpcodeTimeoutAck = 't';
-
-// ReadAll reads |len| bytes from |bio| into |out|. It returns 1 on success and
-// 0 or -1 on error.
-static int ReadAll(BIO *bio, uint8_t *out, size_t len) {
- while (len > 0) {
- int chunk_len = INT_MAX;
- if (len <= INT_MAX) {
- chunk_len = (int)len;
- }
- int ret = BIO_read(bio, out, chunk_len);
- if (ret <= 0) {
- return ret;
- }
- out += ret;
- len -= ret;
- }
- return 1;
-}
-
-static int PacketedWrite(BIO *bio, const char *in, int inl) {
- if (bio->next_bio == NULL) {
- return 0;
- }
-
- BIO_clear_retry_flags(bio);
-
- // Write the header.
- uint8_t header[5];
- header[0] = kOpcodePacket;
- header[1] = (inl >> 24) & 0xff;
- header[2] = (inl >> 16) & 0xff;
- header[3] = (inl >> 8) & 0xff;
- header[4] = inl & 0xff;
- int ret = BIO_write(bio->next_bio, header, sizeof(header));
- if (ret <= 0) {
- BIO_copy_next_retry(bio);
- return ret;
- }
-
- // Write the buffer.
- ret = BIO_write(bio->next_bio, in, inl);
- if (ret < 0 || (inl > 0 && ret == 0)) {
- BIO_copy_next_retry(bio);
- return ret;
- }
- assert(ret == inl);
- return ret;
-}
-
-static int PacketedRead(BIO *bio, char *out, int outl) {
- if (bio->next_bio == NULL) {
- return 0;
- }
-
- BIO_clear_retry_flags(bio);
-
- // Read the opcode.
- uint8_t opcode;
- int ret = ReadAll(bio->next_bio, &opcode, sizeof(opcode));
- if (ret <= 0) {
- BIO_copy_next_retry(bio);
- return ret;
- }
-
- if (opcode == kOpcodeTimeout) {
- // Process the timeout.
- uint8_t buf[8];
- ret = ReadAll(bio->next_bio, buf, sizeof(buf));
- if (ret <= 0) {
- BIO_copy_next_retry(bio);
- return ret;
- }
- uint64_t timeout = (static_cast<uint64_t>(buf[0]) << 56) |
- (static_cast<uint64_t>(buf[1]) << 48) |
- (static_cast<uint64_t>(buf[2]) << 40) |
- (static_cast<uint64_t>(buf[3]) << 32) |
- (static_cast<uint64_t>(buf[4]) << 24) |
- (static_cast<uint64_t>(buf[5]) << 16) |
- (static_cast<uint64_t>(buf[6]) << 8) |
- static_cast<uint64_t>(buf[7]);
- timeout /= 1000; // Convert nanoseconds to microseconds.
- timeval *out_timeout = reinterpret_cast<timeval *>(bio->ptr);
- assert(out_timeout->tv_usec == 0);
- assert(out_timeout->tv_sec == 0);
- out_timeout->tv_usec = timeout % 1000000;
- out_timeout->tv_sec = timeout / 1000000;
-
- // Send an ACK to the peer.
- ret = BIO_write(bio->next_bio, &kOpcodeTimeoutAck, 1);
- if (ret <= 0) {
- return ret;
- }
- assert(ret == 1);
-
- // Signal to the caller to retry the read, after processing the
- // new clock.
- BIO_set_retry_read(bio);
- return -1;
- }
-
- if (opcode != kOpcodePacket) {
- fprintf(stderr, "Unknown opcode, %u\n", opcode);
- return -1;
- }
-
- // Read the length prefix.
- uint8_t len_bytes[4];
- ret = ReadAll(bio->next_bio, len_bytes, sizeof(len_bytes));
- if (ret <= 0) {
- BIO_copy_next_retry(bio);
- return ret;
- }
-
- uint32_t len = (len_bytes[0] << 24) | (len_bytes[1] << 16) |
- (len_bytes[2] << 8) | len_bytes[3];
- uint8_t *buf = (uint8_t *)OPENSSL_malloc(len);
- if (buf == NULL) {
- return -1;
- }
- ret = ReadAll(bio->next_bio, buf, len);
- if (ret <= 0) {
- fprintf(stderr, "Packeted BIO was truncated\n");
- return -1;
- }
-
- if (outl > (int)len) {
- outl = len;
- }
- memcpy(out, buf, outl);
- OPENSSL_free(buf);
- return outl;
-}
-
-static long PacketedCtrl(BIO *bio, int cmd, long num, void *ptr) {
- if (bio->next_bio == NULL) {
- return 0;
- }
- BIO_clear_retry_flags(bio);
- int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
- BIO_copy_next_retry(bio);
- return ret;
-}
-
-static int PacketedNew(BIO *bio) {
- bio->init = 1;
- return 1;
-}
-
-static int PacketedFree(BIO *bio) {
- if (bio == NULL) {
- return 0;
- }
-
- bio->init = 0;
- return 1;
-}
-
-static long PacketedCallbackCtrl(BIO *bio, int cmd, bio_info_cb fp) {
- if (bio->next_bio == NULL) {
- return 0;
- }
- return BIO_callback_ctrl(bio->next_bio, cmd, fp);
-}
-
-const BIO_METHOD g_packeted_bio_method = {
- BIO_TYPE_FILTER,
- "packeted bio",
- PacketedWrite,
- PacketedRead,
- NULL /* puts */,
- NULL /* gets */,
- PacketedCtrl,
- PacketedNew,
- PacketedFree,
- PacketedCallbackCtrl,
-};
-
-} // namespace
-
-ScopedBIO PacketedBioCreate(timeval *out_timeout) {
- ScopedBIO bio(BIO_new(&g_packeted_bio_method));
- if (!bio) {
- return nullptr;
- }
- bio->ptr = out_timeout;
- return bio;
-}
diff --git a/third_party/boringssl/src/ssl/test/packeted_bio.h b/third_party/boringssl/src/ssl/test/packeted_bio.h
deleted file mode 100644
index 30697a5bec..0000000000
--- a/third_party/boringssl/src/ssl/test/packeted_bio.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (c) 2014, 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_PACKETED_BIO
-#define HEADER_PACKETED_BIO
-
-#include <openssl/base.h>
-#include <openssl/bio.h>
-
-#include "../../crypto/test/scoped_types.h"
-
-#if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
-#include <winsock2.h>
-#pragma warning(pop)
-#else
-#include <sys/types.h>
-#endif
-
-
-// PacketedBioCreate creates a filter BIO which implements a reliable in-order
-// blocking datagram socket. The resulting BIO, on |BIO_read|, may simulate a
-// timeout which sets |*out_timeout| to the timeout and fails the read.
-// |*out_timeout| must be zero on entry to |BIO_read|; it is an error to not
-// apply the timeout before the next |BIO_read|.
-//
-// Note: The read timeout simulation is intended to be used with the async BIO
-// wrapper. It doesn't simulate BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, used in DTLS's
-// blocking mode.
-ScopedBIO PacketedBioCreate(timeval *out_timeout);
-
-
-#endif // HEADER_PACKETED_BIO
diff --git a/third_party/boringssl/src/ssl/test/runner/alert.go b/third_party/boringssl/src/ssl/test/runner/alert.go
deleted file mode 100644
index 541216edeb..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/alert.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import "strconv"
-
-type alert uint8
-
-const (
- // alert level
- alertLevelWarning = 1
- alertLevelError = 2
-)
-
-const (
- alertCloseNotify alert = 0
- alertUnexpectedMessage alert = 10
- alertBadRecordMAC alert = 20
- alertDecryptionFailed alert = 21
- alertRecordOverflow alert = 22
- alertDecompressionFailure alert = 30
- alertHandshakeFailure alert = 40
- alertBadCertificate alert = 42
- alertUnsupportedCertificate alert = 43
- alertCertificateRevoked alert = 44
- alertCertificateExpired alert = 45
- alertCertificateUnknown alert = 46
- alertIllegalParameter alert = 47
- alertUnknownCA alert = 48
- alertAccessDenied alert = 49
- alertDecodeError alert = 50
- alertDecryptError alert = 51
- alertProtocolVersion alert = 70
- alertInsufficientSecurity alert = 71
- alertInternalError alert = 80
- alertUserCanceled alert = 90
- alertNoRenegotiation alert = 100
-)
-
-var alertText = map[alert]string{
- alertCloseNotify: "close notify",
- alertUnexpectedMessage: "unexpected message",
- alertBadRecordMAC: "bad record MAC",
- alertDecryptionFailed: "decryption failed",
- alertRecordOverflow: "record overflow",
- alertDecompressionFailure: "decompression failure",
- alertHandshakeFailure: "handshake failure",
- alertBadCertificate: "bad certificate",
- alertUnsupportedCertificate: "unsupported certificate",
- alertCertificateRevoked: "revoked certificate",
- alertCertificateExpired: "expired certificate",
- alertCertificateUnknown: "unknown certificate",
- alertIllegalParameter: "illegal parameter",
- alertUnknownCA: "unknown certificate authority",
- alertAccessDenied: "access denied",
- alertDecodeError: "error decoding message",
- alertDecryptError: "error decrypting message",
- alertProtocolVersion: "protocol version not supported",
- alertInsufficientSecurity: "insufficient security level",
- alertInternalError: "internal error",
- alertUserCanceled: "user canceled",
- alertNoRenegotiation: "no renegotiation",
-}
-
-func (e alert) String() string {
- s, ok := alertText[e]
- if ok {
- return s
- }
- return "alert(" + strconv.Itoa(int(e)) + ")"
-}
-
-func (e alert) Error() string {
- return e.String()
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/cert.pem b/third_party/boringssl/src/ssl/test/runner/cert.pem
deleted file mode 100644
index 4de4f49a34..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/cert.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
-BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
-aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF
-MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
-ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci
-HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV
-W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV
-HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f
-Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht
-ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr
-T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f
-j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==
------END CERTIFICATE-----
diff --git a/third_party/boringssl/src/ssl/test/runner/chacha20_poly1305.go b/third_party/boringssl/src/ssl/test/runner/chacha20_poly1305.go
deleted file mode 100644
index f2a1bbff56..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/chacha20_poly1305.go
+++ /dev/null
@@ -1,159 +0,0 @@
-package runner
-
-import (
- "crypto/cipher"
- "crypto/subtle"
- "encoding/binary"
- "errors"
-)
-
-// See draft-agl-tls-chacha20poly1305-04 and
-// draft-irtf-cfrg-chacha20-poly1305-10. Where the two differ, the
-// draft-agl-tls-chacha20poly1305-04 variant is implemented.
-
-func leftRotate(a uint32, n uint) uint32 {
- return (a << n) | (a >> (32 - n))
-}
-
-func chaChaQuarterRound(state *[16]uint32, a, b, c, d int) {
- state[a] += state[b]
- state[d] = leftRotate(state[d]^state[a], 16)
-
- state[c] += state[d]
- state[b] = leftRotate(state[b]^state[c], 12)
-
- state[a] += state[b]
- state[d] = leftRotate(state[d]^state[a], 8)
-
- state[c] += state[d]
- state[b] = leftRotate(state[b]^state[c], 7)
-}
-
-func chaCha20Block(state *[16]uint32, out []byte) {
- var workingState [16]uint32
- copy(workingState[:], state[:])
- for i := 0; i < 10; i++ {
- chaChaQuarterRound(&workingState, 0, 4, 8, 12)
- chaChaQuarterRound(&workingState, 1, 5, 9, 13)
- chaChaQuarterRound(&workingState, 2, 6, 10, 14)
- chaChaQuarterRound(&workingState, 3, 7, 11, 15)
- chaChaQuarterRound(&workingState, 0, 5, 10, 15)
- chaChaQuarterRound(&workingState, 1, 6, 11, 12)
- chaChaQuarterRound(&workingState, 2, 7, 8, 13)
- chaChaQuarterRound(&workingState, 3, 4, 9, 14)
- }
- for i := 0; i < 16; i++ {
- binary.LittleEndian.PutUint32(out[i*4:i*4+4], workingState[i]+state[i])
- }
-}
-
-// sliceForAppend takes a slice and a requested number of bytes. It returns a
-// slice with the contents of the given slice followed by that many bytes and a
-// second slice that aliases into it and contains only the extra bytes. If the
-// original slice has sufficient capacity then no allocation is performed.
-func sliceForAppend(in []byte, n int) (head, tail []byte) {
- if total := len(in) + n; cap(in) >= total {
- head = in[:total]
- } else {
- head = make([]byte, total)
- copy(head, in)
- }
- tail = head[len(in):]
- return
-}
-
-type chaCha20Poly1305 struct {
- key [32]byte
-}
-
-func newChaCha20Poly1305(key []byte) (cipher.AEAD, error) {
- if len(key) != 32 {
- return nil, errors.New("bad key length")
- }
- aead := new(chaCha20Poly1305)
- copy(aead.key[:], key)
- return aead, nil
-}
-
-func (c *chaCha20Poly1305) NonceSize() int { return 8 }
-func (c *chaCha20Poly1305) Overhead() int { return 16 }
-
-func (c *chaCha20Poly1305) chaCha20(out, in, nonce []byte, counter uint64) {
- var state [16]uint32
- state[0] = 0x61707865
- state[1] = 0x3320646e
- state[2] = 0x79622d32
- state[3] = 0x6b206574
- for i := 0; i < 8; i++ {
- state[4+i] = binary.LittleEndian.Uint32(c.key[i*4 : i*4+4])
- }
- state[14] = binary.LittleEndian.Uint32(nonce[0:4])
- state[15] = binary.LittleEndian.Uint32(nonce[4:8])
-
- for i := 0; i < len(in); i += 64 {
- state[12] = uint32(counter & 0xffffffff)
- state[13] = uint32(counter >> 32)
-
- var tmp [64]byte
- chaCha20Block(&state, tmp[:])
- count := 64
- if len(in)-i < count {
- count = len(in) - i
- }
- for j := 0; j < count; j++ {
- out[i+j] = in[i+j] ^ tmp[j]
- }
-
- counter++
- }
-}
-
-func (c *chaCha20Poly1305) poly1305(tag *[16]byte, nonce, ciphertext, additionalData []byte) {
- input := make([]byte, 0, len(additionalData)+8+len(ciphertext)+8)
- input = append(input, additionalData...)
- input, out := sliceForAppend(input, 8)
- binary.LittleEndian.PutUint64(out, uint64(len(additionalData)))
- input = append(input, ciphertext...)
- input, out = sliceForAppend(input, 8)
- binary.LittleEndian.PutUint64(out, uint64(len(ciphertext)))
-
- var poly1305Key [32]byte
- c.chaCha20(poly1305Key[:], poly1305Key[:], nonce, 0)
-
- poly1305Sum(tag, input, &poly1305Key)
-}
-
-func (c *chaCha20Poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
- if len(nonce) != 8 {
- panic("Bad nonce length")
- }
-
- ret, out := sliceForAppend(dst, len(plaintext)+16)
- c.chaCha20(out[:len(plaintext)], plaintext, nonce, 1)
-
- var tag [16]byte
- c.poly1305(&tag, nonce, out[:len(plaintext)], additionalData)
- copy(out[len(plaintext):], tag[:])
-
- return ret
-}
-
-func (c *chaCha20Poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
- if len(nonce) != 8 {
- panic("Bad nonce length")
- }
- if len(ciphertext) < 16 {
- return nil, errors.New("chacha20: message authentication failed")
- }
- plaintextLen := len(ciphertext) - 16
-
- var tag [16]byte
- c.poly1305(&tag, nonce, ciphertext[:plaintextLen], additionalData)
- if subtle.ConstantTimeCompare(tag[:], ciphertext[plaintextLen:]) != 1 {
- return nil, errors.New("chacha20: message authentication failed")
- }
-
- ret, out := sliceForAppend(dst, plaintextLen)
- c.chaCha20(out, ciphertext[:plaintextLen], nonce, 1)
- return ret, nil
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/chacha20_poly1305_test.go b/third_party/boringssl/src/ssl/test/runner/chacha20_poly1305_test.go
deleted file mode 100644
index be49b11969..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/chacha20_poly1305_test.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package runner
-
-import (
- "bytes"
- "encoding/hex"
- "testing"
-)
-
-// See draft-irtf-cfrg-chacha20-poly1305-10, section 2.1.1.
-func TestChaChaQuarterRound(t *testing.T) {
- state := [16]uint32{0x11111111, 0x01020304, 0x9b8d6f43, 0x01234567}
- chaChaQuarterRound(&state, 0, 1, 2, 3)
-
- a, b, c, d := state[0], state[1], state[2], state[3]
- if a != 0xea2a92f4 || b != 0xcb1cf8ce || c != 0x4581472e || d != 0x5881c4bb {
- t.Errorf("Incorrect results: %x", state)
- }
-}
-
-// See draft-irtf-cfrg-chacha20-poly1305-10, section 2.2.1.
-func TestChaChaQuarterRoundState(t *testing.T) {
- state := [16]uint32{
- 0x879531e0, 0xc5ecf37d, 0x516461b1, 0xc9a62f8a,
- 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0x2a5f714c,
- 0x53372767, 0xb00a5631, 0x974c541a, 0x359e9963,
- 0x5c971061, 0x3d631689, 0x2098d9d6, 0x91dbd320,
- }
- chaChaQuarterRound(&state, 2, 7, 8, 13)
-
- expected := [16]uint32{
- 0x879531e0, 0xc5ecf37d, 0xbdb886dc, 0xc9a62f8a,
- 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0xcfacafd2,
- 0xe46bea80, 0xb00a5631, 0x974c541a, 0x359e9963,
- 0x5c971061, 0xccc07c79, 0x2098d9d6, 0x91dbd320,
- }
- for i := range state {
- if state[i] != expected[i] {
- t.Errorf("Mismatch at %d: %x vs %x", i, state, expected)
- }
- }
-}
-
-// See draft-irtf-cfrg-chacha20-poly1305-10, section 2.3.2.
-func TestChaCha20Block(t *testing.T) {
- state := [16]uint32{
- 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
- 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
- 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
- 0x00000001, 0x09000000, 0x4a000000, 0x00000000,
- }
- out := make([]byte, 64)
- chaCha20Block(&state, out)
-
- expected := []byte{
- 0x10, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15,
- 0x50, 0x0f, 0xdd, 0x1f, 0xa3, 0x20, 0x71, 0xc4,
- 0xc7, 0xd1, 0xf4, 0xc7, 0x33, 0xc0, 0x68, 0x03,
- 0x04, 0x22, 0xaa, 0x9a, 0xc3, 0xd4, 0x6c, 0x4e,
- 0xd2, 0x82, 0x64, 0x46, 0x07, 0x9f, 0xaa, 0x09,
- 0x14, 0xc2, 0xd7, 0x05, 0xd9, 0x8b, 0x02, 0xa2,
- 0xb5, 0x12, 0x9c, 0xd1, 0xde, 0x16, 0x4e, 0xb9,
- 0xcb, 0xd0, 0x83, 0xe8, 0xa2, 0x50, 0x3c, 0x4e,
- }
- if !bytes.Equal(out, expected) {
- t.Errorf("Got %x, wanted %x", out, expected)
- }
-}
-
-// See draft-agl-tls-chacha20poly1305-04, section 7.
-func TestChaCha20Poly1305(t *testing.T) {
- key, _ := hex.DecodeString("4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007")
- input, _ := hex.DecodeString("86d09974840bded2a5ca")
- nonce, _ := hex.DecodeString("cd7cf67be39c794a")
- ad, _ := hex.DecodeString("87e229d4500845a079c0")
- output, _ := hex.DecodeString("e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6")
-
- aead, err := newChaCha20Poly1305(key)
- if err != nil {
- t.Fatal(err)
- }
-
- out, err := aead.Open(nil, nonce, output, ad)
- if err != nil {
- t.Errorf("Open failed: %s", err)
- } else if !bytes.Equal(out, input) {
- t.Errorf("Open gave %x, wanted %x", out, input)
- }
-
- out = aead.Seal(nil, nonce, input, ad)
- if !bytes.Equal(out, output) {
- t.Errorf("Open gave %x, wanted %x", out, output)
- }
-
- out[0]++
- _, err = aead.Open(nil, nonce, out, ad)
- if err == nil {
- t.Errorf("Open on malformed data unexpectedly succeeded")
- }
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/channel_id_key.pem b/third_party/boringssl/src/ssl/test/runner/channel_id_key.pem
deleted file mode 100644
index 604752bcda..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/channel_id_key.pem
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIPwxu50c7LEhVNRYJFRWBUnoaz7JSos96T5hBp4rjyptoAoGCCqGSM49
-AwEHoUQDQgAEzFSVTE5guxJRQ0VbZ8dicPs5e/DT7xpW7Yc9hq0VOchv7cbXuI/T
-CwadDjGWX/oaz0ftFqrVmfkwZu+C58ioWg==
------END EC PRIVATE KEY-----
diff --git a/third_party/boringssl/src/ssl/test/runner/cipher_suites.go b/third_party/boringssl/src/ssl/test/runner/cipher_suites.go
deleted file mode 100644
index c406000acb..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/cipher_suites.go
+++ /dev/null
@@ -1,423 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import (
- "crypto/aes"
- "crypto/cipher"
- "crypto/des"
- "crypto/hmac"
- "crypto/md5"
- "crypto/rc4"
- "crypto/sha1"
- "crypto/sha256"
- "crypto/sha512"
- "crypto/x509"
- "hash"
-)
-
-// a keyAgreement implements the client and server side of a TLS key agreement
-// protocol by generating and processing key exchange messages.
-type keyAgreement interface {
- // On the server side, the first two methods are called in order.
-
- // In the case that the key agreement protocol doesn't use a
- // ServerKeyExchange message, generateServerKeyExchange can return nil,
- // nil.
- generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
- processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
-
- // On the client side, the next two methods are called in order.
-
- // This method may not be called if the server doesn't send a
- // ServerKeyExchange message.
- processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
- generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
-}
-
-const (
- // suiteECDH indicates that the cipher suite involves elliptic curve
- // Diffie-Hellman. This means that it should only be selected when the
- // client indicates that it supports ECC with a curve and point format
- // that we're happy with.
- suiteECDHE = 1 << iota
- // 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
- // RSA based.
- suiteECDSA
- // suiteTLS12 indicates that the cipher suite should only be advertised
- // and accepted when using TLS 1.2.
- suiteTLS12
- // 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
-)
-
-type tlsAead struct {
- cipher.AEAD
- explicitNonce bool
-}
-
-// A cipherSuite is a specific combination of key agreement, cipher and MAC
-// function. All cipher suites currently assume RSA key agreement.
-type cipherSuite struct {
- id uint16
- // the lengths, in bytes, of the key material needed for each component.
- keyLen int
- macLen int
- ivLen int
- ka func(version uint16) keyAgreement
- // flags is a bitmask of the suite* values, above.
- flags int
- cipher func(key, iv []byte, isRead bool) interface{}
- mac func(version uint16, macKey []byte) macFunction
- aead func(key, fixedNonce []byte) *tlsAead
-}
-
-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_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
- {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 0, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
- {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
- {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
- {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
- {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
- {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil},
- {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil},
- {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
- {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil},
- {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
- {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
- {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
- {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
- {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
- {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
- {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM},
- {TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
- {TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
- {TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
- {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
- {TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
- {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
- {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
- {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil},
- {TLS_RSA_WITH_RC4_128_MD5, 16, 16, 0, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil},
- {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
- {TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
- {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
- {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
- {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
- {TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil},
- {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
- {TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
- {TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
- {TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
- {TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
- {TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
- {TLS_RSA_WITH_NULL_SHA, 0, 20, 0, rsaKA, suiteNoDTLS, cipherNull, macSHA1, nil},
-}
-
-type nullCipher struct{}
-
-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 {
- return cipher.NewCBCDecrypter(block, iv)
- }
- return cipher.NewCBCEncrypter(block, iv)
-}
-
-func cipherAES(key, iv []byte, isRead bool) interface{} {
- block, _ := aes.NewCipher(key)
- if isRead {
- return cipher.NewCBCDecrypter(block, iv)
- }
- return cipher.NewCBCEncrypter(block, iv)
-}
-
-// macSHA1 returns a macFunction for the given protocol version.
-func macSHA1(version uint16, key []byte) macFunction {
- if version == VersionSSL30 {
- mac := ssl30MAC{
- h: sha1.New(),
- key: make([]byte, len(key)),
- }
- copy(mac.key, key)
- return mac
- }
- return tls10MAC{hmac.New(sha1.New, key)}
-}
-
-func macMD5(version uint16, key []byte) macFunction {
- if version == VersionSSL30 {
- mac := ssl30MAC{
- h: md5.New(),
- key: make([]byte, len(key)),
- }
- copy(mac.key, key)
- return mac
- }
- return tls10MAC{hmac.New(md5.New, key)}
-}
-
-func macSHA256(version uint16, key []byte) macFunction {
- if version == VersionSSL30 {
- mac := ssl30MAC{
- h: sha256.New(),
- key: make([]byte, len(key)),
- }
- copy(mac.key, key)
- return mac
- }
- return tls10MAC{hmac.New(sha256.New, key)}
-}
-
-func macSHA384(version uint16, key []byte) macFunction {
- if version == VersionSSL30 {
- mac := ssl30MAC{
- h: sha512.New384(),
- key: make([]byte, len(key)),
- }
- copy(mac.key, key)
- return mac
- }
- return tls10MAC{hmac.New(sha512.New384, key)}
-}
-
-type macFunction interface {
- Size() int
- MAC(digestBuf, seq, header, length, data []byte) []byte
-}
-
-// fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to
-// each call.
-type fixedNonceAEAD struct {
- // sealNonce and openNonce are buffers where the larger nonce will be
- // constructed. Since a seal and open operation may be running
- // concurrently, there is a separate buffer for each.
- sealNonce, openNonce []byte
- aead cipher.AEAD
-}
-
-func (f *fixedNonceAEAD) NonceSize() int { return 8 }
-func (f *fixedNonceAEAD) Overhead() int { return f.aead.Overhead() }
-
-func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
- copy(f.sealNonce[len(f.sealNonce)-8:], nonce)
- return f.aead.Seal(out, f.sealNonce, plaintext, additionalData)
-}
-
-func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) {
- copy(f.openNonce[len(f.openNonce)-8:], nonce)
- return f.aead.Open(out, f.openNonce, plaintext, additionalData)
-}
-
-func aeadAESGCM(key, fixedNonce []byte) *tlsAead {
- aes, err := aes.NewCipher(key)
- if err != nil {
- panic(err)
- }
- aead, err := cipher.NewGCM(aes)
- if err != nil {
- panic(err)
- }
-
- nonce1, nonce2 := make([]byte, 12), make([]byte, 12)
- copy(nonce1, fixedNonce)
- copy(nonce2, fixedNonce)
-
- return &tlsAead{&fixedNonceAEAD{nonce1, nonce2, aead}, true}
-}
-
-func aeadCHACHA20POLY1305(key, fixedNonce []byte) *tlsAead {
- aead, err := newChaCha20Poly1305(key)
- if err != nil {
- panic(err)
- }
- return &tlsAead{aead, false}
-}
-
-// ssl30MAC implements the SSLv3 MAC function, as defined in
-// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1
-type ssl30MAC struct {
- h hash.Hash
- key []byte
-}
-
-func (s ssl30MAC) Size() int {
- return s.h.Size()
-}
-
-var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}
-
-var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
-
-func (s ssl30MAC) MAC(digestBuf, seq, header, length, data []byte) []byte {
- padLength := 48
- if s.h.Size() == 20 {
- padLength = 40
- }
-
- s.h.Reset()
- s.h.Write(s.key)
- s.h.Write(ssl30Pad1[:padLength])
- s.h.Write(seq)
- s.h.Write(header[:1])
- s.h.Write(length)
- s.h.Write(data)
- digestBuf = s.h.Sum(digestBuf[:0])
-
- s.h.Reset()
- s.h.Write(s.key)
- s.h.Write(ssl30Pad2[:padLength])
- s.h.Write(digestBuf)
- return s.h.Sum(digestBuf[:0])
-}
-
-// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
-type tls10MAC struct {
- h hash.Hash
-}
-
-func (s tls10MAC) Size() int {
- return s.h.Size()
-}
-
-func (s tls10MAC) MAC(digestBuf, seq, header, length, data []byte) []byte {
- s.h.Reset()
- s.h.Write(seq)
- s.h.Write(header)
- s.h.Write(length)
- s.h.Write(data)
- return s.h.Sum(digestBuf[:0])
-}
-
-func rsaKA(version uint16) keyAgreement {
- return &rsaKeyAgreement{version: version}
-}
-
-func ecdheECDSAKA(version uint16) keyAgreement {
- return &ecdheKeyAgreement{
- auth: &signedKeyAgreement{
- sigType: signatureECDSA,
- version: version,
- },
- }
-}
-
-func ecdheRSAKA(version uint16) keyAgreement {
- return &ecdheKeyAgreement{
- auth: &signedKeyAgreement{
- sigType: signatureRSA,
- version: version,
- },
- }
-}
-
-func dheRSAKA(version uint16) keyAgreement {
- return &dheKeyAgreement{
- auth: &signedKeyAgreement{
- sigType: signatureRSA,
- version: version,
- },
- }
-}
-
-func pskKA(version uint16) keyAgreement {
- return &pskKeyAgreement{
- base: &nilKeyAgreement{},
- }
-}
-
-func ecdhePSKKA(version uint16) keyAgreement {
- return &pskKeyAgreement{
- base: &ecdheKeyAgreement{
- auth: &nilKeyAgreementAuthentication{},
- },
- }
-}
-
-// mutualCipherSuite returns a cipherSuite given a list of supported
-// ciphersuites and the id requested by the peer.
-func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
- for _, id := range have {
- if id == want {
- for _, suite := range cipherSuites {
- if suite.id == want {
- return suite
- }
- }
- return nil
- }
- }
- return nil
-}
-
-// A list of the possible cipher suite ids. Taken from
-// 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_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
- TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
- TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
- TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c
- TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003d
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
- TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006b
- 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_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009e
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009f
- 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
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xc024
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xc028
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
- TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xc035
- TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xc036
- renegotiationSCSV uint16 = 0x00ff
- fallbackSCSV uint16 = 0x5600
-)
-
-// Additional cipher suite IDs, not IANA-assigned.
-const (
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcc13
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcc14
-)
diff --git a/third_party/boringssl/src/ssl/test/runner/common.go b/third_party/boringssl/src/ssl/test/runner/common.go
deleted file mode 100644
index 3e5696d140..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/common.go
+++ /dev/null
@@ -1,1123 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import (
- "container/list"
- "crypto"
- "crypto/ecdsa"
- "crypto/rand"
- "crypto/x509"
- "fmt"
- "io"
- "math/big"
- "strings"
- "sync"
- "time"
-)
-
-const (
- VersionSSL30 = 0x0300
- VersionTLS10 = 0x0301
- VersionTLS11 = 0x0302
- VersionTLS12 = 0x0303
-)
-
-const (
- maxPlaintext = 16384 // maximum plaintext payload length
- maxCiphertext = 16384 + 2048 // maximum ciphertext payload length
- tlsRecordHeaderLen = 5 // record header length
- dtlsRecordHeaderLen = 13
- maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
-
- minVersion = VersionSSL30
- maxVersion = VersionTLS12
-)
-
-// TLS record types.
-type recordType uint8
-
-const (
- recordTypeChangeCipherSpec recordType = 20
- recordTypeAlert recordType = 21
- recordTypeHandshake recordType = 22
- recordTypeApplicationData recordType = 23
-)
-
-// TLS handshake message types.
-const (
- typeHelloRequest uint8 = 0
- typeClientHello uint8 = 1
- typeServerHello uint8 = 2
- typeHelloVerifyRequest uint8 = 3
- typeNewSessionTicket uint8 = 4
- typeCertificate uint8 = 11
- typeServerKeyExchange uint8 = 12
- typeCertificateRequest uint8 = 13
- typeServerHelloDone uint8 = 14
- typeCertificateVerify uint8 = 15
- typeClientKeyExchange uint8 = 16
- typeFinished uint8 = 20
- typeCertificateStatus uint8 = 22
- typeNextProtocol uint8 = 67 // Not IANA assigned
- typeEncryptedExtensions uint8 = 203 // Not IANA assigned
-)
-
-// TLS compression types.
-const (
- compressionNone uint8 = 0
-)
-
-// TLS extension numbers
-const (
- extensionServerName uint16 = 0
- extensionStatusRequest uint16 = 5
- extensionSupportedCurves uint16 = 10
- extensionSupportedPoints uint16 = 11
- extensionSignatureAlgorithms uint16 = 13
- extensionUseSRTP uint16 = 14
- extensionALPN uint16 = 16
- extensionSignedCertificateTimestamp uint16 = 18
- extensionExtendedMasterSecret uint16 = 23
- extensionSessionTicket uint16 = 35
- extensionCustom uint16 = 1234 // not IANA assigned
- extensionNextProtoNeg uint16 = 13172 // not IANA assigned
- extensionRenegotiationInfo uint16 = 0xff01
- extensionChannelID uint16 = 30032 // not IANA assigned
-)
-
-// TLS signaling cipher suite values
-const (
- scsvRenegotiation uint16 = 0x00ff
-)
-
-// 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
-
-const (
- CurveP224 CurveID = 21
- CurveP256 CurveID = 23
- CurveP384 CurveID = 24
- CurveP521 CurveID = 25
-)
-
-// TLS Elliptic Curve Point Formats
-// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
-const (
- pointFormatUncompressed uint8 = 0
-)
-
-// TLS CertificateStatusType (RFC 3546)
-const (
- statusTypeOCSP uint8 = 1
-)
-
-// Certificate types (for certificateRequestMsg)
-const (
- CertTypeRSASign = 1 // A certificate containing an RSA key
- CertTypeDSSSign = 2 // A certificate containing a DSA key
- CertTypeRSAFixedDH = 3 // A certificate containing a static DH key
- CertTypeDSSFixedDH = 4 // A certificate containing a static DH key
-
- // See RFC4492 sections 3 and 5.5.
- CertTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
- CertTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
- CertTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
-
- // Rest of these are reserved by the TLS spec
-)
-
-// Hash functions for TLS 1.2 (See RFC 5246, section A.4.1)
-const (
- hashMD5 uint8 = 1
- hashSHA1 uint8 = 2
- hashSHA224 uint8 = 3
- hashSHA256 uint8 = 4
- hashSHA384 uint8 = 5
- hashSHA512 uint8 = 6
-)
-
-// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
-const (
- signatureRSA uint8 = 1
- signatureECDSA uint8 = 3
-)
-
-// signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
-// RFC 5246, section A.4.1.
-type signatureAndHash struct {
- signature, hash uint8
-}
-
-// supportedSKXSignatureAlgorithms contains the signature and hash algorithms
-// that the code advertises as supported in a TLS 1.2 ClientHello.
-var supportedSKXSignatureAlgorithms = []signatureAndHash{
- {signatureRSA, hashSHA256},
- {signatureECDSA, hashSHA256},
- {signatureRSA, hashSHA1},
- {signatureECDSA, hashSHA1},
-}
-
-// supportedClientCertSignatureAlgorithms contains the signature and hash
-// algorithms that the code advertises as supported in a TLS 1.2
-// CertificateRequest.
-var supportedClientCertSignatureAlgorithms = []signatureAndHash{
- {signatureRSA, hashSHA256},
- {signatureECDSA, hashSHA256},
-}
-
-// SRTP protection profiles (See RFC 5764, section 4.1.2)
-const (
- SRTP_AES128_CM_HMAC_SHA1_80 uint16 = 0x0001
- SRTP_AES128_CM_HMAC_SHA1_32 = 0x0002
-)
-
-// ConnectionState records basic TLS details about the connection.
-type ConnectionState struct {
- Version uint16 // TLS version used by the connection (e.g. VersionTLS12)
- HandshakeComplete bool // TLS handshake is complete
- DidResume bool // connection resumes a previous TLS connection
- CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
- NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos)
- NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server
- NegotiatedProtocolFromALPN bool // protocol negotiated with ALPN
- ServerName string // server name requested by client, if any (server side only)
- PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
- VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
- ChannelID *ecdsa.PublicKey // the channel ID for this connection
- SRTPProtectionProfile uint16 // the negotiated DTLS-SRTP protection profile
- TLSUnique []byte // the tls-unique channel binding
- SCTList []byte // signed certificate timestamp list
- ClientCertSignatureHash uint8 // TLS id of the hash used by the client to sign the handshake
-}
-
-// ClientAuthType declares the policy the server will follow for
-// TLS Client Authentication.
-type ClientAuthType int
-
-const (
- NoClientCert ClientAuthType = iota
- RequestClientCert
- RequireAnyClientCert
- VerifyClientCertIfGiven
- RequireAndVerifyClientCert
-)
-
-// ClientSessionState contains the state needed by clients to resume TLS
-// sessions.
-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
- 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.
- serverCertificates []*x509.Certificate // Certificate chain presented by the server
- extendedMasterSecret bool // Whether an extended master secret was used to generate the session
- sctList []byte
- ocspResponse []byte
-}
-
-// ClientSessionCache is a cache of ClientSessionState objects that can be used
-// by a client to resume a TLS session with a given server. ClientSessionCache
-// implementations should expect to be called concurrently from different
-// goroutines.
-type ClientSessionCache interface {
- // Get searches for a ClientSessionState associated with the given key.
- // On return, ok is true if one was found.
- Get(sessionKey string) (session *ClientSessionState, ok bool)
-
- // Put adds the ClientSessionState to the cache with the given key.
- Put(sessionKey string, cs *ClientSessionState)
-}
-
-// ServerSessionCache is a cache of sessionState objects that can be used by a
-// client to resume a TLS session with a given server. ServerSessionCache
-// implementations should expect to be called concurrently from different
-// goroutines.
-type ServerSessionCache interface {
- // Get searches for a sessionState associated with the given session
- // ID. On return, ok is true if one was found.
- Get(sessionId string) (session *sessionState, ok bool)
-
- // Put adds the sessionState to the cache with the given session ID.
- Put(sessionId string, session *sessionState)
-}
-
-// A Config structure is used to configure a TLS client or server.
-// After one has been passed to a TLS function it must not be
-// modified. A Config may be reused; the tls package will also not
-// modify it.
-type Config struct {
- // Rand provides the source of entropy for nonces and RSA blinding.
- // If Rand is nil, TLS uses the cryptographic random reader in package
- // crypto/rand.
- // The Reader must be safe for use by multiple goroutines.
- Rand io.Reader
-
- // Time returns the current time as the number of seconds since the epoch.
- // If Time is nil, TLS uses time.Now.
- Time func() time.Time
-
- // Certificates contains one or more certificate chains
- // to present to the other side of the connection.
- // Server configurations must include at least one certificate.
- Certificates []Certificate
-
- // NameToCertificate maps from a certificate name to an element of
- // Certificates. Note that a certificate name can be of the form
- // '*.example.com' and so doesn't have to be a domain name as such.
- // See Config.BuildNameToCertificate
- // The nil value causes the first element of Certificates to be used
- // for all connections.
- NameToCertificate map[string]*Certificate
-
- // RootCAs defines the set of root certificate authorities
- // that clients use when verifying server certificates.
- // If RootCAs is nil, TLS uses the host's root CA set.
- RootCAs *x509.CertPool
-
- // NextProtos is a list of supported, application level protocols.
- NextProtos []string
-
- // ServerName is used to verify the hostname on the returned
- // certificates unless InsecureSkipVerify is given. It is also included
- // in the client's handshake to support virtual hosting.
- ServerName string
-
- // ClientAuth determines the server's policy for
- // TLS Client Authentication. The default is NoClientCert.
- ClientAuth ClientAuthType
-
- // ClientCAs defines the set of root certificate authorities
- // that servers use if required to verify a client certificate
- // by the policy in ClientAuth.
- ClientCAs *x509.CertPool
-
- // ClientCertificateTypes defines the set of allowed client certificate
- // types. The default is CertTypeRSASign and CertTypeECDSASign.
- ClientCertificateTypes []byte
-
- // InsecureSkipVerify controls whether a client verifies the
- // server's certificate chain and host name.
- // If InsecureSkipVerify is true, TLS accepts any certificate
- // presented by the server and any host name in that certificate.
- // In this mode, TLS is susceptible to man-in-the-middle attacks.
- // This should be used only for testing.
- InsecureSkipVerify bool
-
- // CipherSuites is a list of supported cipher suites. If CipherSuites
- // is nil, TLS uses a list of suites supported by the implementation.
- CipherSuites []uint16
-
- // PreferServerCipherSuites controls whether the server selects the
- // client's most preferred ciphersuite, or the server's most preferred
- // ciphersuite. If true then the server's preference, as expressed in
- // the order of elements in CipherSuites, is used.
- PreferServerCipherSuites bool
-
- // SessionTicketsDisabled may be set to true to disable session ticket
- // (resumption) support.
- SessionTicketsDisabled bool
-
- // SessionTicketKey is used by TLS servers to provide session
- // resumption. See RFC 5077. If zero, it will be filled with
- // random data before the first server handshake.
- //
- // If multiple servers are terminating connections for the same host
- // they should all have the same SessionTicketKey. If the
- // SessionTicketKey leaks, previously recorded and future TLS
- // connections using that key are compromised.
- SessionTicketKey [32]byte
-
- // ClientSessionCache is a cache of ClientSessionState entries
- // for TLS session resumption.
- ClientSessionCache ClientSessionCache
-
- // ServerSessionCache is a cache of sessionState entries for TLS session
- // resumption.
- ServerSessionCache ServerSessionCache
-
- // MinVersion contains the minimum SSL/TLS version that is acceptable.
- // If zero, then SSLv3 is taken as the minimum.
- MinVersion uint16
-
- // MaxVersion contains the maximum SSL/TLS version that is acceptable.
- // If zero, then the maximum version supported by this package is used,
- // which is currently TLS 1.2.
- MaxVersion uint16
-
- // CurvePreferences contains the elliptic curves that will be used in
- // an ECDHE handshake, in preference order. If empty, the default will
- // be used.
- CurvePreferences []CurveID
-
- // ChannelID contains the ECDSA key for the client to use as
- // its TLS Channel ID.
- ChannelID *ecdsa.PrivateKey
-
- // RequestChannelID controls whether the server requests a TLS
- // Channel ID. If negotiated, the client's public key is
- // returned in the ConnectionState.
- RequestChannelID bool
-
- // PreSharedKey, if not nil, is the pre-shared key to use with
- // the PSK cipher suites.
- PreSharedKey []byte
-
- // PreSharedKeyIdentity, if not empty, is the identity to use
- // with the PSK cipher suites.
- PreSharedKeyIdentity string
-
- // SRTPProtectionProfiles, if not nil, is the list of SRTP
- // protection profiles to offer in DTLS-SRTP.
- SRTPProtectionProfiles []uint16
-
- // SignatureAndHashes, if not nil, overrides the default set of
- // supported signature and hash algorithms to advertise in
- // CertificateRequest.
- SignatureAndHashes []signatureAndHash
-
- // Bugs specifies optional misbehaviour to be used for testing other
- // implementations.
- Bugs ProtocolBugs
-
- serverInitOnce sync.Once // guards calling (*Config).serverInit
-}
-
-type BadValue int
-
-const (
- BadValueNone BadValue = iota
- BadValueNegative
- BadValueZero
- BadValueLimit
- BadValueLarge
- NumBadValues
-)
-
-type ProtocolBugs struct {
- // InvalidSKXSignature specifies that the signature in a
- // ServerKeyExchange message should be invalid.
- InvalidSKXSignature bool
-
- // InvalidCertVerifySignature specifies that the signature in a
- // CertificateVerify message should be invalid.
- InvalidCertVerifySignature bool
-
- // InvalidSKXCurve causes the curve ID in the ServerKeyExchange message
- // to be wrong.
- InvalidSKXCurve bool
-
- // BadECDSAR controls ways in which the 'r' value of an ECDSA signature
- // can be invalid.
- BadECDSAR BadValue
- BadECDSAS BadValue
-
- // MaxPadding causes CBC records to have the maximum possible padding.
- MaxPadding bool
- // PaddingFirstByteBad causes the first byte of the padding to be
- // incorrect.
- PaddingFirstByteBad bool
- // PaddingFirstByteBadIf255 causes the first byte of padding to be
- // incorrect if there's a maximum amount of padding (i.e. 255 bytes).
- PaddingFirstByteBadIf255 bool
-
- // FailIfNotFallbackSCSV causes a server handshake to fail if the
- // client doesn't send the fallback SCSV value.
- FailIfNotFallbackSCSV bool
-
- // DuplicateExtension causes an extra empty extension of bogus type to
- // be emitted in either the ClientHello or the ServerHello.
- DuplicateExtension bool
-
- // UnauthenticatedECDH causes the server to pretend ECDHE_RSA
- // and ECDHE_ECDSA cipher suites are actually ECDH_anon. No
- // Certificate message is sent and no signature is added to
- // ServerKeyExchange.
- UnauthenticatedECDH bool
-
- // SkipHelloVerifyRequest causes a DTLS server to skip the
- // HelloVerifyRequest message.
- SkipHelloVerifyRequest bool
-
- // SkipCertificateStatus, if true, causes the server to skip the
- // CertificateStatus message. This is legal because CertificateStatus is
- // optional, even with a status_request in ServerHello.
- SkipCertificateStatus bool
-
- // SkipServerKeyExchange causes the server to skip sending
- // ServerKeyExchange messages.
- SkipServerKeyExchange bool
-
- // SkipNewSessionTicket causes the server to skip sending the
- // NewSessionTicket message despite promising to in ServerHello.
- SkipNewSessionTicket bool
-
- // SkipChangeCipherSpec causes the implementation to skip
- // sending the ChangeCipherSpec message (and adjusting cipher
- // state accordingly for the Finished message).
- SkipChangeCipherSpec bool
-
- // SkipFinished causes the implementation to skip sending the Finished
- // message.
- SkipFinished 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.
- EarlyChangeCipherSpec int
-
- // FragmentAcrossChangeCipherSpec causes the implementation to fragment
- // the Finished (or NextProto) message around the ChangeCipherSpec
- // messages.
- FragmentAcrossChangeCipherSpec bool
-
- // SendV2ClientHello causes the client to send a V2ClientHello
- // instead of a normal ClientHello.
- SendV2ClientHello bool
-
- // SendFallbackSCSV causes the client to include
- // TLS_FALLBACK_SCSV in the ClientHello.
- SendFallbackSCSV bool
-
- // SendRenegotiationSCSV causes the client to include the renegotiation
- // SCSV in the ClientHello.
- SendRenegotiationSCSV bool
-
- // MaxHandshakeRecordLength, if non-zero, is the maximum size of a
- // handshake record. Handshake messages will be split into multiple
- // records at the specified size, except that the client_version will
- // never be fragmented. For DTLS, it is the maximum handshake fragment
- // size, not record size; DTLS allows multiple handshake fragments in a
- // single handshake record. See |PackHandshakeFragments|.
- MaxHandshakeRecordLength int
-
- // FragmentClientVersion will allow MaxHandshakeRecordLength to apply to
- // the first 6 bytes of the ClientHello.
- FragmentClientVersion bool
-
- // FragmentAlert will cause all alerts to be fragmented across
- // two records.
- FragmentAlert bool
-
- // SendSpuriousAlert, if non-zero, will cause an spurious, unwanted
- // alert to be sent.
- SendSpuriousAlert alert
-
- // RsaClientKeyExchangeVersion, if non-zero, causes the client to send a
- // ClientKeyExchange with the specified version rather than the
- // client_version when performing the RSA key exchange.
- RsaClientKeyExchangeVersion uint16
-
- // RenewTicketOnResume causes the server to renew the session ticket and
- // send a NewSessionTicket message during an abbreviated handshake.
- RenewTicketOnResume bool
-
- // SendClientVersion, if non-zero, causes the client to send a different
- // TLS version in the ClientHello than the maximum supported version.
- SendClientVersion uint16
-
- // ExpectFalseStart causes the server to, on full handshakes,
- // expect the peer to False Start; the server Finished message
- // isn't sent until we receive an application data record
- // from the peer.
- ExpectFalseStart bool
-
- // AlertBeforeFalseStartTest, if non-zero, causes the server to, on full
- // handshakes, send an alert just before reading the application data
- // record to test False Start. This can be used in a negative False
- // Start test to determine whether the peer processed the alert (and
- // closed the connection) before or after sending app data.
- AlertBeforeFalseStartTest alert
-
- // SSL3RSAKeyExchange causes the client to always send an RSA
- // ClientKeyExchange message without the two-byte length
- // prefix, as if it were SSL3.
- SSL3RSAKeyExchange bool
-
- // SkipCipherVersionCheck causes the server to negotiate
- // TLS 1.2 ciphers in earlier versions of TLS.
- SkipCipherVersionCheck bool
-
- // ExpectServerName, if not empty, is the hostname the client
- // must specify in the server_name extension.
- ExpectServerName string
-
- // SwapNPNAndALPN switches the relative order between NPN and ALPN in
- // both ClientHello and ServerHello.
- SwapNPNAndALPN bool
-
- // ALPNProtocol, if not nil, sets the ALPN protocol that a server will
- // return.
- ALPNProtocol *string
-
- // AllowSessionVersionMismatch causes the server to resume sessions
- // regardless of the version associated with the session.
- AllowSessionVersionMismatch bool
-
- // CorruptTicket causes a client to corrupt a session ticket before
- // sending it in a resume handshake.
- CorruptTicket bool
-
- // OversizedSessionId causes the session id that is sent with a ticket
- // resumption attempt to be too large (33 bytes).
- OversizedSessionId bool
-
- // RequireExtendedMasterSecret, if true, requires that the peer support
- // the extended master secret option.
- RequireExtendedMasterSecret bool
-
- // NoExtendedMasterSecret causes the client and server to behave as if
- // they didn't support an extended master secret.
- NoExtendedMasterSecret bool
-
- // EmptyRenegotiationInfo causes the renegotiation extension to be
- // empty in a renegotiation handshake.
- EmptyRenegotiationInfo bool
-
- // BadRenegotiationInfo causes the renegotiation extension value in a
- // renegotiation handshake to be incorrect.
- BadRenegotiationInfo bool
-
- // NoRenegotiationInfo causes the client to behave as if it
- // didn't support the renegotiation info extension.
- NoRenegotiationInfo bool
-
- // RequireRenegotiationInfo, if true, causes the client to return an
- // error if the server doesn't reply with the renegotiation extension.
- RequireRenegotiationInfo bool
-
- // SequenceNumberMapping, if non-nil, is the mapping function to apply
- // to the sequence number of outgoing packets. For both TLS and DTLS,
- // the two most-significant bytes in the resulting sequence number are
- // ignored so that the DTLS epoch cannot be changed.
- SequenceNumberMapping func(uint64) uint64
-
- // RSAEphemeralKey, if true, causes the server to send a
- // ServerKeyExchange message containing an ephemeral key (as in
- // RSA_EXPORT) in the plain RSA key exchange.
- RSAEphemeralKey bool
-
- // SRTPMasterKeyIdentifer, if not empty, is the SRTP MKI value that the
- // client offers when negotiating SRTP. MKI support is still missing so
- // the peer must still send none.
- SRTPMasterKeyIdentifer string
-
- // SendSRTPProtectionProfile, if non-zero, is the SRTP profile that the
- // server sends in the ServerHello instead of the negotiated one.
- SendSRTPProtectionProfile uint16
-
- // NoSignatureAndHashes, if true, causes the client to omit the
- // signature and hashes extension.
- //
- // For a server, it will cause an empty list to be sent in the
- // CertificateRequest message. None the less, the configured set will
- // still be enforced.
- NoSignatureAndHashes bool
-
- // NoSupportedCurves, if true, causes the client to omit the
- // supported_curves extension.
- NoSupportedCurves bool
-
- // RequireSameRenegoClientVersion, if true, causes the server
- // to require that all ClientHellos match in offered version
- // across a renego.
- RequireSameRenegoClientVersion bool
-
- // ExpectInitialRecordVersion, if non-zero, is the expected
- // version of the records before the version is determined.
- ExpectInitialRecordVersion uint16
-
- // MaxPacketLength, if non-zero, is the maximum acceptable size for a
- // packet.
- MaxPacketLength int
-
- // SendCipherSuite, if non-zero, is the cipher suite value that the
- // server will send in the ServerHello. This does not affect the cipher
- // the server believes it has actually negotiated.
- SendCipherSuite uint16
-
- // AppDataBeforeHandshake, if not nil, causes application data to be
- // sent immediately before the first handshake message.
- AppDataBeforeHandshake []byte
-
- // AppDataAfterChangeCipherSpec, if not nil, causes application data to
- // be sent immediately after ChangeCipherSpec.
- AppDataAfterChangeCipherSpec []byte
-
- // AlertAfterChangeCipherSpec, if non-zero, causes an alert to be sent
- // immediately after ChangeCipherSpec.
- AlertAfterChangeCipherSpec alert
-
- // TimeoutSchedule is the schedule of packet drops and simulated
- // timeouts for before each handshake leg from the peer.
- TimeoutSchedule []time.Duration
-
- // PacketAdaptor is the packetAdaptor to use to simulate timeouts.
- PacketAdaptor *packetAdaptor
-
- // ReorderHandshakeFragments, if true, causes handshake fragments in
- // DTLS to overlap and be sent in the wrong order. It also causes
- // pre-CCS flights to be sent twice. (Post-CCS flights consist of
- // Finished and will trigger a spurious retransmit.)
- ReorderHandshakeFragments bool
-
- // MixCompleteMessageWithFragments, if true, causes handshake
- // messages in DTLS to redundantly both fragment the message
- // and include a copy of the full one.
- MixCompleteMessageWithFragments bool
-
- // SendInvalidRecordType, if true, causes a record with an invalid
- // content type to be sent immediately following the handshake.
- SendInvalidRecordType bool
-
- // WrongCertificateMessageType, if true, causes Certificate message to
- // be sent with the wrong message type.
- WrongCertificateMessageType bool
-
- // FragmentMessageTypeMismatch, if true, causes all non-initial
- // handshake fragments in DTLS to have the wrong message type.
- FragmentMessageTypeMismatch bool
-
- // FragmentMessageLengthMismatch, if true, causes all non-initial
- // handshake fragments in DTLS to have the wrong message length.
- FragmentMessageLengthMismatch bool
-
- // SplitFragments, if non-zero, causes the handshake fragments in DTLS
- // to be split across two records. The value of |SplitFragments| is the
- // number of bytes in the first fragment.
- SplitFragments int
-
- // SendEmptyFragments, if true, causes handshakes to include empty
- // fragments in DTLS.
- SendEmptyFragments bool
-
- // SendSplitAlert, if true, causes an alert to be sent with the header
- // and record body split across multiple packets. The peer should
- // discard these packets rather than process it.
- SendSplitAlert bool
-
- // FailIfResumeOnRenego, if true, causes renegotiations to fail if the
- // client offers a resumption or the server accepts one.
- FailIfResumeOnRenego bool
-
- // IgnorePeerCipherPreferences, if true, causes the peer's cipher
- // preferences to be ignored.
- IgnorePeerCipherPreferences bool
-
- // IgnorePeerSignatureAlgorithmPreferences, if true, causes the peer's
- // signature algorithm preferences to be ignored.
- IgnorePeerSignatureAlgorithmPreferences bool
-
- // IgnorePeerCurvePreferences, if true, causes the peer's curve
- // preferences to be ignored.
- IgnorePeerCurvePreferences bool
-
- // BadFinished, if true, causes the Finished hash to be broken.
- BadFinished bool
-
- // DHGroupPrime, if not nil, is used to define the (finite field)
- // Diffie-Hellman group. The generator used is always two.
- DHGroupPrime *big.Int
-
- // PackHandshakeFragments, if true, causes handshake fragments to be
- // packed into individual handshake records, up to the specified record
- // size.
- PackHandshakeFragments int
-
- // PackHandshakeRecords, if true, causes handshake records to be packed
- // into individual packets, up to the specified packet size.
- PackHandshakeRecords int
-
- // EnableAllCiphersInDTLS, if true, causes RC4 to be enabled in DTLS.
- EnableAllCiphersInDTLS bool
-
- // EmptyCertificateList, if true, causes the server to send an empty
- // certificate list in the Certificate message.
- EmptyCertificateList bool
-
- // ExpectNewTicket, if true, causes the client to abort if it does not
- // receive a new ticket.
- ExpectNewTicket bool
-
- // RequireClientHelloSize, if not zero, is the required length in bytes
- // of the ClientHello /record/. This is checked by the server.
- RequireClientHelloSize int
-
- // CustomExtension, if not empty, contains the contents of an extension
- // that will be added to client/server hellos.
- CustomExtension string
-
- // ExpectedCustomExtension, if not nil, contains the expected contents
- // of a custom extension.
- ExpectedCustomExtension *string
-
- // NoCloseNotify, if true, causes the close_notify alert to be skipped
- // on connection shutdown.
- NoCloseNotify bool
-
- // ExpectCloseNotify, if true, requires a close_notify from the peer on
- // shutdown. Records from the peer received after close_notify is sent
- // are not discard.
- ExpectCloseNotify bool
-
- // SendLargeRecords, if true, allows outgoing records to be sent
- // arbitrarily large.
- SendLargeRecords bool
-
- // NegotiateALPNAndNPN, if true, causes the server to negotiate both
- // ALPN and NPN in the same connetion.
- NegotiateALPNAndNPN bool
-}
-
-func (c *Config) serverInit() {
- if c.SessionTicketsDisabled {
- return
- }
-
- // If the key has already been set then we have nothing to do.
- for _, b := range c.SessionTicketKey {
- if b != 0 {
- return
- }
- }
-
- if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
- c.SessionTicketsDisabled = true
- }
-}
-
-func (c *Config) rand() io.Reader {
- r := c.Rand
- if r == nil {
- return rand.Reader
- }
- return r
-}
-
-func (c *Config) time() time.Time {
- t := c.Time
- if t == nil {
- t = time.Now
- }
- return t()
-}
-
-func (c *Config) cipherSuites() []uint16 {
- s := c.CipherSuites
- if s == nil {
- s = defaultCipherSuites()
- }
- return s
-}
-
-func (c *Config) minVersion() uint16 {
- if c == nil || c.MinVersion == 0 {
- return minVersion
- }
- return c.MinVersion
-}
-
-func (c *Config) maxVersion() uint16 {
- if c == nil || c.MaxVersion == 0 {
- return maxVersion
- }
- return c.MaxVersion
-}
-
-var defaultCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
-
-func (c *Config) curvePreferences() []CurveID {
- if c == nil || len(c.CurvePreferences) == 0 {
- return defaultCurvePreferences
- }
- return c.CurvePreferences
-}
-
-// mutualVersion returns the protocol version to use given the advertised
-// version of the peer.
-func (c *Config) mutualVersion(vers uint16) (uint16, bool) {
- minVersion := c.minVersion()
- maxVersion := c.maxVersion()
-
- if vers < minVersion {
- return 0, false
- }
- if vers > maxVersion {
- vers = maxVersion
- }
- return vers, true
-}
-
-// getCertificateForName returns the best certificate for the given name,
-// defaulting to the first element of c.Certificates if there are no good
-// options.
-func (c *Config) getCertificateForName(name string) *Certificate {
- if len(c.Certificates) == 1 || c.NameToCertificate == nil {
- // There's only one choice, so no point doing any work.
- return &c.Certificates[0]
- }
-
- name = strings.ToLower(name)
- for len(name) > 0 && name[len(name)-1] == '.' {
- name = name[:len(name)-1]
- }
-
- if cert, ok := c.NameToCertificate[name]; ok {
- return cert
- }
-
- // try replacing labels in the name with wildcards until we get a
- // match.
- labels := strings.Split(name, ".")
- for i := range labels {
- labels[i] = "*"
- candidate := strings.Join(labels, ".")
- if cert, ok := c.NameToCertificate[candidate]; ok {
- return cert
- }
- }
-
- // If nothing matches, return the first certificate.
- return &c.Certificates[0]
-}
-
-func (c *Config) signatureAndHashesForServer() []signatureAndHash {
- if c != nil && c.SignatureAndHashes != nil {
- return c.SignatureAndHashes
- }
- return supportedClientCertSignatureAlgorithms
-}
-
-func (c *Config) signatureAndHashesForClient() []signatureAndHash {
- if c != nil && c.SignatureAndHashes != nil {
- return c.SignatureAndHashes
- }
- return supportedSKXSignatureAlgorithms
-}
-
-// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
-// from the CommonName and SubjectAlternateName fields of each of the leaf
-// certificates.
-func (c *Config) BuildNameToCertificate() {
- c.NameToCertificate = make(map[string]*Certificate)
- for i := range c.Certificates {
- cert := &c.Certificates[i]
- x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
- if err != nil {
- continue
- }
- if len(x509Cert.Subject.CommonName) > 0 {
- c.NameToCertificate[x509Cert.Subject.CommonName] = cert
- }
- for _, san := range x509Cert.DNSNames {
- c.NameToCertificate[san] = cert
- }
- }
-}
-
-// A Certificate is a chain of one or more certificates, leaf first.
-type Certificate struct {
- Certificate [][]byte
- PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
- // OCSPStaple contains an optional OCSP response which will be served
- // to clients that request it.
- OCSPStaple []byte
- // SignedCertificateTimestampList contains an optional encoded
- // SignedCertificateTimestampList structure which will be
- // served to clients that request it.
- SignedCertificateTimestampList []byte
- // Leaf is the parsed form of the leaf certificate, which may be
- // initialized using x509.ParseCertificate to reduce per-handshake
- // processing for TLS clients doing client authentication. If nil, the
- // leaf certificate will be parsed as needed.
- Leaf *x509.Certificate
-}
-
-// A TLS record.
-type record struct {
- contentType recordType
- major, minor uint8
- payload []byte
-}
-
-type handshakeMessage interface {
- marshal() []byte
- unmarshal([]byte) bool
-}
-
-// lruSessionCache is a client or server session cache implementation
-// that uses an LRU caching strategy.
-type lruSessionCache struct {
- sync.Mutex
-
- m map[string]*list.Element
- q *list.List
- capacity int
-}
-
-type lruSessionCacheEntry struct {
- sessionKey string
- state interface{}
-}
-
-// Put adds the provided (sessionKey, cs) pair to the cache.
-func (c *lruSessionCache) Put(sessionKey string, cs interface{}) {
- c.Lock()
- defer c.Unlock()
-
- if elem, ok := c.m[sessionKey]; ok {
- entry := elem.Value.(*lruSessionCacheEntry)
- entry.state = cs
- c.q.MoveToFront(elem)
- return
- }
-
- if c.q.Len() < c.capacity {
- entry := &lruSessionCacheEntry{sessionKey, cs}
- c.m[sessionKey] = c.q.PushFront(entry)
- return
- }
-
- elem := c.q.Back()
- entry := elem.Value.(*lruSessionCacheEntry)
- delete(c.m, entry.sessionKey)
- entry.sessionKey = sessionKey
- entry.state = cs
- c.q.MoveToFront(elem)
- c.m[sessionKey] = elem
-}
-
-// Get returns the value associated with a given key. It returns (nil,
-// false) if no value is found.
-func (c *lruSessionCache) Get(sessionKey string) (interface{}, bool) {
- c.Lock()
- defer c.Unlock()
-
- if elem, ok := c.m[sessionKey]; ok {
- c.q.MoveToFront(elem)
- return elem.Value.(*lruSessionCacheEntry).state, true
- }
- return nil, false
-}
-
-// lruClientSessionCache is a ClientSessionCache implementation that
-// uses an LRU caching strategy.
-type lruClientSessionCache struct {
- lruSessionCache
-}
-
-func (c *lruClientSessionCache) Put(sessionKey string, cs *ClientSessionState) {
- c.lruSessionCache.Put(sessionKey, cs)
-}
-
-func (c *lruClientSessionCache) Get(sessionKey string) (*ClientSessionState, bool) {
- cs, ok := c.lruSessionCache.Get(sessionKey)
- if !ok {
- return nil, false
- }
- return cs.(*ClientSessionState), true
-}
-
-// lruServerSessionCache is a ServerSessionCache implementation that
-// uses an LRU caching strategy.
-type lruServerSessionCache struct {
- lruSessionCache
-}
-
-func (c *lruServerSessionCache) Put(sessionId string, session *sessionState) {
- c.lruSessionCache.Put(sessionId, session)
-}
-
-func (c *lruServerSessionCache) Get(sessionId string) (*sessionState, bool) {
- cs, ok := c.lruSessionCache.Get(sessionId)
- if !ok {
- return nil, false
- }
- return cs.(*sessionState), true
-}
-
-// NewLRUClientSessionCache returns a ClientSessionCache with the given
-// capacity that uses an LRU strategy. If capacity is < 1, a default capacity
-// is used instead.
-func NewLRUClientSessionCache(capacity int) ClientSessionCache {
- const defaultSessionCacheCapacity = 64
-
- if capacity < 1 {
- capacity = defaultSessionCacheCapacity
- }
- return &lruClientSessionCache{
- lruSessionCache{
- m: make(map[string]*list.Element),
- q: list.New(),
- capacity: capacity,
- },
- }
-}
-
-// NewLRUServerSessionCache returns a ServerSessionCache with the given
-// capacity that uses an LRU strategy. If capacity is < 1, a default capacity
-// is used instead.
-func NewLRUServerSessionCache(capacity int) ServerSessionCache {
- const defaultSessionCacheCapacity = 64
-
- if capacity < 1 {
- capacity = defaultSessionCacheCapacity
- }
- return &lruServerSessionCache{
- lruSessionCache{
- m: make(map[string]*list.Element),
- q: list.New(),
- capacity: capacity,
- },
- }
-}
-
-// TODO(jsing): Make these available to both crypto/x509 and crypto/tls.
-type dsaSignature struct {
- R, S *big.Int
-}
-
-type ecdsaSignature dsaSignature
-
-var emptyConfig Config
-
-func defaultConfig() *Config {
- return &emptyConfig
-}
-
-var (
- once sync.Once
- varDefaultCipherSuites []uint16
-)
-
-func defaultCipherSuites() []uint16 {
- once.Do(initDefaultCipherSuites)
- return varDefaultCipherSuites
-}
-
-func initDefaultCipherSuites() {
- for _, suite := range cipherSuites {
- if suite.flags&suitePSK == 0 {
- varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id)
- }
- }
-}
-
-func unexpectedMessageError(wanted, got interface{}) error {
- return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
-}
-
-func isSupportedSignatureAndHash(sigHash signatureAndHash, sigHashes []signatureAndHash) bool {
- for _, s := range sigHashes {
- if s == sigHash {
- return true
- }
- }
- return false
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/conn.go b/third_party/boringssl/src/ssl/test/runner/conn.go
deleted file mode 100644
index 986e2b5d0e..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/conn.go
+++ /dev/null
@@ -1,1410 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// TLS low level connection and record layer
-
-package runner
-
-import (
- "bytes"
- "crypto/cipher"
- "crypto/ecdsa"
- "crypto/subtle"
- "crypto/x509"
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "net"
- "sync"
- "time"
-)
-
-// A Conn represents a secured connection.
-// It implements the net.Conn interface.
-type Conn struct {
- // constant
- conn net.Conn
- isDTLS bool
- isClient bool
-
- // constant after handshake; protected by handshakeMutex
- handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex
- handshakeErr error // error resulting from handshake
- vers uint16 // TLS version
- haveVers bool // version has been negotiated
- config *Config // configuration passed to constructor
- handshakeComplete bool
- didResume bool // whether this connection was a session resumption
- extendedMasterSecret bool // whether this session used an extended master secret
- cipherSuite *cipherSuite
- ocspResponse []byte // stapled OCSP response
- sctList []byte // signed certificate timestamp list
- peerCertificates []*x509.Certificate
- // verifiedChains contains the certificate chains that we built, as
- // opposed to the ones presented by the server.
- verifiedChains [][]*x509.Certificate
- // serverName contains the server name indicated by the client, if any.
- serverName string
- // firstFinished contains the first Finished hash sent during the
- // handshake. This is the "tls-unique" channel binding value.
- firstFinished [12]byte
- // clientCertSignatureHash contains the TLS hash id for the hash that
- // was used by the client to sign the handshake with a client
- // certificate. This is only set by a server and is zero if no client
- // certificates were used.
- clientCertSignatureHash uint8
-
- clientRandom, serverRandom [32]byte
- masterSecret [48]byte
-
- clientProtocol string
- clientProtocolFallback bool
- usedALPN bool
-
- // verify_data values for the renegotiation extension.
- clientVerify []byte
- serverVerify []byte
-
- channelID *ecdsa.PublicKey
-
- srtpProtectionProfile uint16
-
- clientVersion uint16
-
- // input/output
- in, out halfConn // in.Mutex < out.Mutex
- rawInput *block // raw input, right off the wire
- input *block // application record waiting to be read
- hand bytes.Buffer // handshake record waiting to be read
-
- // DTLS state
- sendHandshakeSeq uint16
- recvHandshakeSeq uint16
- handMsg []byte // pending assembled handshake message
- handMsgLen int // handshake message length, not including the header
- pendingFragments [][]byte // pending outgoing handshake fragments.
-
- tmp [16]byte
-}
-
-func (c *Conn) init() {
- c.in.isDTLS = c.isDTLS
- c.out.isDTLS = c.isDTLS
- c.in.config = c.config
- c.out.config = c.config
-
- c.out.updateOutSeq()
-}
-
-// Access to net.Conn methods.
-// Cannot just embed net.Conn because that would
-// export the struct field too.
-
-// LocalAddr returns the local network address.
-func (c *Conn) LocalAddr() net.Addr {
- return c.conn.LocalAddr()
-}
-
-// RemoteAddr returns the remote network address.
-func (c *Conn) RemoteAddr() net.Addr {
- return c.conn.RemoteAddr()
-}
-
-// SetDeadline sets the read and write deadlines associated with the connection.
-// A zero value for t means Read and Write will not time out.
-// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
-func (c *Conn) SetDeadline(t time.Time) error {
- return c.conn.SetDeadline(t)
-}
-
-// SetReadDeadline sets the read deadline on the underlying connection.
-// A zero value for t means Read will not time out.
-func (c *Conn) SetReadDeadline(t time.Time) error {
- return c.conn.SetReadDeadline(t)
-}
-
-// SetWriteDeadline sets the write deadline on the underlying conneciton.
-// A zero value for t means Write will not time out.
-// After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
-func (c *Conn) SetWriteDeadline(t time.Time) error {
- return c.conn.SetWriteDeadline(t)
-}
-
-// A halfConn represents one direction of the record layer
-// connection, either sending or receiving.
-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
-
- nextCipher interface{} // next encryption state
- nextMac macFunction // next MAC algorithm
- nextSeq [6]byte // next epoch's starting sequence number in DTLS
-
- // used to save allocating a new buffer for each MAC.
- inDigestBuf, outDigestBuf []byte
-
- config *Config
-}
-
-func (hc *halfConn) setErrorLocked(err error) error {
- hc.err = err
- return err
-}
-
-func (hc *halfConn) error() error {
- // This should be locked, but I've removed it for the renegotiation
- // tests since we don't concurrently read and write the same tls.Conn
- // in any case during testing.
- err := hc.err
- return err
-}
-
-// 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.nextCipher = cipher
- hc.nextMac = mac
-}
-
-// changeCipherSpec changes the encryption and MAC states
-// to the ones previously passed to prepareCipherSpec.
-func (hc *halfConn) changeCipherSpec(config *Config) error {
- if hc.nextCipher == nil {
- return alertInternalError
- }
- hc.cipher = hc.nextCipher
- hc.mac = hc.nextMac
- hc.nextCipher = nil
- hc.nextMac = nil
- hc.config = config
- hc.incEpoch()
- return nil
-}
-
-// incSeq increments the sequence number.
-func (hc *halfConn) incSeq(isOutgoing bool) {
- limit := 0
- increment := uint64(1)
- if hc.isDTLS {
- // Increment up to the epoch in DTLS.
- limit = 2
- }
- for i := 7; i >= limit; i-- {
- increment += uint64(hc.seq[i])
- hc.seq[i] = byte(increment)
- increment >>= 8
- }
-
- // Not allowed to let sequence number wrap.
- // Instead, must renegotiate before it does.
- // Not likely enough to bother.
- if increment != 0 {
- panic("TLS: sequence number wraparound")
- }
-
- hc.updateOutSeq()
-}
-
-// incNextSeq increments the starting sequence number for the next epoch.
-func (hc *halfConn) incNextSeq() {
- for i := len(hc.nextSeq) - 1; i >= 0; i-- {
- hc.nextSeq[i]++
- if hc.nextSeq[i] != 0 {
- return
- }
- }
- panic("TLS: sequence number wraparound")
-}
-
-// incEpoch resets the sequence number. In DTLS, it also increments the epoch
-// half of the sequence number.
-func (hc *halfConn) incEpoch() {
- if hc.isDTLS {
- for i := 1; i >= 0; i-- {
- hc.seq[i]++
- if hc.seq[i] != 0 {
- break
- }
- if i == 0 {
- panic("TLS: epoch number wraparound")
- }
- }
- copy(hc.seq[2:], hc.nextSeq[:])
- for i := range hc.nextSeq {
- hc.nextSeq[i] = 0
- }
- } else {
- for i := range hc.seq {
- hc.seq[i] = 0
- }
- }
-
- hc.updateOutSeq()
-}
-
-func (hc *halfConn) updateOutSeq() {
- if hc.config.Bugs.SequenceNumberMapping != nil {
- seqU64 := binary.BigEndian.Uint64(hc.seq[:])
- seqU64 = hc.config.Bugs.SequenceNumberMapping(seqU64)
- binary.BigEndian.PutUint64(hc.outSeq[:], seqU64)
-
- // The DTLS epoch cannot be changed.
- copy(hc.outSeq[:2], hc.seq[:2])
- return
- }
-
- copy(hc.outSeq[:], hc.seq[:])
-}
-
-func (hc *halfConn) recordHeaderLen() int {
- if hc.isDTLS {
- return dtlsRecordHeaderLen
- }
- return tlsRecordHeaderLen
-}
-
-// removePadding returns an unpadded slice, in constant time, which is a prefix
-// of the input. It also returns a byte which is equal to 255 if the padding
-// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
-func removePadding(payload []byte) ([]byte, byte) {
- if len(payload) < 1 {
- return payload, 0
- }
-
- paddingLen := payload[len(payload)-1]
- t := uint(len(payload)-1) - uint(paddingLen)
- // if len(payload) >= (paddingLen - 1) then the MSB of t is zero
- good := byte(int32(^t) >> 31)
-
- toCheck := 255 // the maximum possible padding length
- // The length of the padded data is public, so we can use an if here
- if toCheck+1 > len(payload) {
- toCheck = len(payload) - 1
- }
-
- for i := 0; i < toCheck; i++ {
- t := uint(paddingLen) - uint(i)
- // if i <= paddingLen then the MSB of t is zero
- mask := byte(int32(^t) >> 31)
- b := payload[len(payload)-1-i]
- good &^= mask&paddingLen ^ mask&b
- }
-
- // We AND together the bits of good and replicate the result across
- // all the bits.
- good &= good << 4
- good &= good << 2
- good &= good << 1
- good = uint8(int8(good) >> 7)
-
- toRemove := good&paddingLen + 1
- return payload[:len(payload)-int(toRemove)], good
-}
-
-// removePaddingSSL30 is a replacement for removePadding in the case that the
-// protocol version is SSLv3. In this version, the contents of the padding
-// are random and cannot be checked.
-func removePaddingSSL30(payload []byte) ([]byte, byte) {
- if len(payload) < 1 {
- return payload, 0
- }
-
- paddingLen := int(payload[len(payload)-1]) + 1
- if paddingLen > len(payload) {
- return payload, 0
- }
-
- return payload[:len(payload)-paddingLen], 255
-}
-
-func roundUp(a, b int) int {
- return a + (b-a%b)%b
-}
-
-// cbcMode is an interface for block ciphers using cipher block chaining.
-type cbcMode interface {
- cipher.BlockMode
- SetIV([]byte)
-}
-
-// decrypt checks and strips the mac and decrypts the data in b. Returns a
-// success boolean, the number of bytes to skip from the start of the record in
-// order to get the application payload, and an optional alert value.
-func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert) {
- recordHeaderLen := hc.recordHeaderLen()
-
- // pull out payload
- payload := b.data[recordHeaderLen:]
-
- macSize := 0
- if hc.mac != nil {
- macSize = hc.mac.Size()
- }
-
- paddingGood := byte(255)
- explicitIVLen := 0
-
- seq := hc.seq[:]
- if hc.isDTLS {
- // DTLS sequence numbers are explicit.
- seq = b.data[3:11]
- }
-
- // decrypt
- if hc.cipher != nil {
- switch c := hc.cipher.(type) {
- case cipher.Stream:
- c.XORKeyStream(payload, payload)
- case *tlsAead:
- nonce := seq
- if c.explicitNonce {
- explicitIVLen = 8
- if len(payload) < explicitIVLen {
- return false, 0, alertBadRecordMAC
- }
- nonce = payload[:8]
- payload = payload[8:]
- }
-
- var additionalData [13]byte
- copy(additionalData[:], seq)
- copy(additionalData[8:], b.data[:3])
- n := len(payload) - c.Overhead()
- additionalData[11] = byte(n >> 8)
- additionalData[12] = byte(n)
- var err error
- payload, err = c.Open(payload[:0], nonce, payload, additionalData[:])
- if err != nil {
- return false, 0, alertBadRecordMAC
- }
- b.resize(recordHeaderLen + explicitIVLen + len(payload))
- case cbcMode:
- blockSize := c.BlockSize()
- if hc.version >= VersionTLS11 || hc.isDTLS {
- explicitIVLen = blockSize
- }
-
- if len(payload)%blockSize != 0 || len(payload) < roundUp(explicitIVLen+macSize+1, blockSize) {
- return false, 0, alertBadRecordMAC
- }
-
- if explicitIVLen > 0 {
- c.SetIV(payload[:explicitIVLen])
- payload = payload[explicitIVLen:]
- }
- c.CryptBlocks(payload, payload)
- if hc.version == VersionSSL30 {
- payload, paddingGood = removePaddingSSL30(payload)
- } else {
- payload, paddingGood = removePadding(payload)
- }
- b.resize(recordHeaderLen + explicitIVLen + len(payload))
-
- // note that we still have a timing side-channel in the
- // MAC check, below. An attacker can align the record
- // so that a correct padding will cause one less hash
- // block to be calculated. Then they can iteratively
- // decrypt a record by breaking each byte. See
- // "Password Interception in a SSL/TLS Channel", Brice
- // Canvel et al.
- //
- // However, our behavior matches OpenSSL, so we leak
- // only as much as they do.
- case nullCipher:
- break
- default:
- panic("unknown cipher type")
- }
- }
-
- // check, strip mac
- if hc.mac != nil {
- if len(payload) < macSize {
- return false, 0, alertBadRecordMAC
- }
-
- // strip mac off payload, b.data
- n := len(payload) - macSize
- b.data[recordHeaderLen-2] = byte(n >> 8)
- b.data[recordHeaderLen-1] = byte(n)
- b.resize(recordHeaderLen + explicitIVLen + n)
- remoteMAC := payload[n:]
- localMAC := hc.mac.MAC(hc.inDigestBuf, seq, b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], payload[:n])
-
- if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
- return false, 0, alertBadRecordMAC
- }
- hc.inDigestBuf = localMAC
- }
- hc.incSeq(false)
-
- return true, recordHeaderLen + explicitIVLen, 0
-}
-
-// padToBlockSize calculates the needed padding block, if any, for a payload.
-// On exit, prefix aliases payload and extends to the end of the last full
-// block of payload. finalBlock is a fresh slice which contains the contents of
-// any suffix of payload as well as the needed padding to make finalBlock a
-// full block.
-func padToBlockSize(payload []byte, blockSize int, config *Config) (prefix, finalBlock []byte) {
- overrun := len(payload) % blockSize
- prefix = payload[:len(payload)-overrun]
-
- paddingLen := blockSize - overrun
- finalSize := blockSize
- if config.Bugs.MaxPadding {
- for paddingLen+blockSize <= 256 {
- paddingLen += blockSize
- }
- finalSize = 256
- }
- finalBlock = make([]byte, finalSize)
- for i := range finalBlock {
- finalBlock[i] = byte(paddingLen - 1)
- }
- if config.Bugs.PaddingFirstByteBad || config.Bugs.PaddingFirstByteBadIf255 && paddingLen == 256 {
- finalBlock[overrun] ^= 0xff
- }
- copy(finalBlock, payload[len(payload)-overrun:])
- return
-}
-
-// encrypt encrypts and macs the data in b.
-func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
- recordHeaderLen := hc.recordHeaderLen()
-
- // mac
- if hc.mac != nil {
- mac := hc.mac.MAC(hc.outDigestBuf, hc.outSeq[0:], b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:])
-
- n := len(b.data)
- b.resize(n + len(mac))
- copy(b.data[n:], mac)
- hc.outDigestBuf = mac
- }
-
- payload := b.data[recordHeaderLen:]
-
- // encrypt
- if hc.cipher != nil {
- switch c := hc.cipher.(type) {
- case cipher.Stream:
- c.XORKeyStream(payload, payload)
- case *tlsAead:
- payloadLen := len(b.data) - recordHeaderLen - explicitIVLen
- b.resize(len(b.data) + c.Overhead())
- nonce := hc.outSeq[:]
- if c.explicitNonce {
- nonce = b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
- }
- payload := b.data[recordHeaderLen+explicitIVLen:]
- payload = payload[:payloadLen]
-
- var additionalData [13]byte
- copy(additionalData[:], hc.outSeq[:])
- copy(additionalData[8:], b.data[:3])
- additionalData[11] = byte(payloadLen >> 8)
- additionalData[12] = byte(payloadLen)
-
- c.Seal(payload[:0], nonce, payload, additionalData[:])
- case cbcMode:
- blockSize := c.BlockSize()
- if explicitIVLen > 0 {
- c.SetIV(payload[:explicitIVLen])
- payload = payload[explicitIVLen:]
- }
- prefix, finalBlock := padToBlockSize(payload, blockSize, hc.config)
- b.resize(recordHeaderLen + explicitIVLen + len(prefix) + len(finalBlock))
- c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen:], prefix)
- c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen+len(prefix):], finalBlock)
- case nullCipher:
- break
- default:
- panic("unknown cipher type")
- }
- }
-
- // update length to include MAC and any block padding needed.
- n := len(b.data) - recordHeaderLen
- b.data[recordHeaderLen-2] = byte(n >> 8)
- b.data[recordHeaderLen-1] = byte(n)
- hc.incSeq(true)
-
- return true, 0
-}
-
-// A block is a simple data buffer.
-type block struct {
- data []byte
- off int // index for Read
- link *block
-}
-
-// resize resizes block to be n bytes, growing if necessary.
-func (b *block) resize(n int) {
- if n > cap(b.data) {
- b.reserve(n)
- }
- b.data = b.data[0:n]
-}
-
-// reserve makes sure that block contains a capacity of at least n bytes.
-func (b *block) reserve(n int) {
- if cap(b.data) >= n {
- return
- }
- m := cap(b.data)
- if m == 0 {
- m = 1024
- }
- for m < n {
- m *= 2
- }
- data := make([]byte, len(b.data), m)
- copy(data, b.data)
- b.data = data
-}
-
-// readFromUntil reads from r into b until b contains at least n bytes
-// or else returns an error.
-func (b *block) readFromUntil(r io.Reader, n int) error {
- // quick case
- if len(b.data) >= n {
- return nil
- }
-
- // read until have enough.
- b.reserve(n)
- for {
- m, err := r.Read(b.data[len(b.data):cap(b.data)])
- b.data = b.data[0 : len(b.data)+m]
- if len(b.data) >= n {
- // TODO(bradfitz,agl): slightly suspicious
- // that we're throwing away r.Read's err here.
- break
- }
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-func (b *block) Read(p []byte) (n int, err error) {
- n = copy(p, b.data[b.off:])
- b.off += n
- return
-}
-
-// newBlock allocates a new block, from hc's free list if possible.
-func (hc *halfConn) newBlock() *block {
- b := hc.bfree
- if b == nil {
- return new(block)
- }
- hc.bfree = b.link
- b.link = nil
- b.resize(0)
- return b
-}
-
-// freeBlock returns a block to hc's free list.
-// The protocol is such that each side only has a block or two on
-// its free list at a time, so there's no need to worry about
-// trimming the list, etc.
-func (hc *halfConn) freeBlock(b *block) {
- b.link = hc.bfree
- hc.bfree = b
-}
-
-// splitBlock splits a block after the first n bytes,
-// returning a block with those n bytes and a
-// block with the remainder. the latter may be nil.
-func (hc *halfConn) splitBlock(b *block, n int) (*block, *block) {
- if len(b.data) <= n {
- return b, nil
- }
- bb := hc.newBlock()
- bb.resize(len(b.data) - n)
- copy(bb.data, b.data[n:])
- b.data = b.data[0:n]
- return b, bb
-}
-
-func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) {
- if c.isDTLS {
- return c.dtlsDoReadRecord(want)
- }
-
- recordHeaderLen := tlsRecordHeaderLen
-
- if c.rawInput == nil {
- c.rawInput = c.in.newBlock()
- }
- b := c.rawInput
-
- // Read header, payload.
- if err := b.readFromUntil(c.conn, recordHeaderLen); err != nil {
- // RFC suggests that EOF without an alertCloseNotify is
- // an error, but popular web sites seem to do this,
- // so we can't make it an error, outside of tests.
- if err == io.EOF && c.config.Bugs.ExpectCloseNotify {
- err = io.ErrUnexpectedEOF
- }
- if e, ok := err.(net.Error); !ok || !e.Temporary() {
- c.in.setErrorLocked(err)
- }
- return 0, nil, err
- }
- typ := recordType(b.data[0])
-
- // No valid TLS record has a type of 0x80, however SSLv2 handshakes
- // start with a uint16 length where the MSB is set and the first record
- // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
- // an SSLv2 client.
- if want == recordTypeHandshake && typ == 0x80 {
- c.sendAlert(alertProtocolVersion)
- return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
- }
-
- vers := uint16(b.data[1])<<8 | uint16(b.data[2])
- n := int(b.data[3])<<8 | int(b.data[4])
- if c.haveVers {
- if vers != c.vers {
- c.sendAlert(alertProtocolVersion)
- return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
- }
- } else {
- if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
- c.sendAlert(alertProtocolVersion)
- return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, expect))
- }
- }
- if n > maxCiphertext {
- c.sendAlert(alertRecordOverflow)
- return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: oversized record received with length %d", n))
- }
- if !c.haveVers {
- // First message, be extra suspicious:
- // this might not be a TLS client.
- // Bail out before reading a full 'body', if possible.
- // The current max version is 3.1.
- // If the version is >= 16.0, it's probably not real.
- // Similarly, a clientHello message encodes in
- // well under a kilobyte. If the length is >= 12 kB,
- // it's probably not real.
- if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 || n >= 0x3000 {
- c.sendAlert(alertUnexpectedMessage)
- return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: first record does not look like a TLS handshake"))
- }
- }
- if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- if e, ok := err.(net.Error); !ok || !e.Temporary() {
- c.in.setErrorLocked(err)
- }
- return 0, nil, err
- }
-
- // Process message.
- b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
- ok, off, err := c.in.decrypt(b)
- if !ok {
- c.in.setErrorLocked(c.sendAlert(err))
- }
- b.off = off
- return typ, b, nil
-}
-
-// readRecord reads the next TLS record from the connection
-// and updates the record layer state.
-// c.in.Mutex <= L; c.input == nil.
-func (c *Conn) readRecord(want recordType) error {
- // Caller must be in sync with connection:
- // handshake data if handshake not yet completed,
- // else application data.
- switch want {
- default:
- c.sendAlert(alertInternalError)
- return c.in.setErrorLocked(errors.New("tls: unknown record type requested"))
- case recordTypeHandshake, recordTypeChangeCipherSpec:
- if c.handshakeComplete {
- c.sendAlert(alertInternalError)
- return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete"))
- }
- case recordTypeApplicationData:
- if !c.handshakeComplete && !c.config.Bugs.ExpectFalseStart {
- c.sendAlert(alertInternalError)
- return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete"))
- }
- case recordTypeAlert:
- // Looking for a close_notify. Note: unlike a real
- // implementation, this is not tolerant of additional records.
- // See the documentation for ExpectCloseNotify.
- }
-
-Again:
- typ, b, err := c.doReadRecord(want)
- if err != nil {
- return err
- }
- data := b.data[b.off:]
- if len(data) > maxPlaintext {
- err := c.sendAlert(alertRecordOverflow)
- c.in.freeBlock(b)
- return c.in.setErrorLocked(err)
- }
-
- switch typ {
- default:
- c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
-
- case recordTypeAlert:
- if len(data) != 2 {
- c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
- break
- }
- if alert(data[1]) == alertCloseNotify {
- c.in.setErrorLocked(io.EOF)
- break
- }
- switch data[0] {
- case alertLevelWarning:
- // drop on the floor
- c.in.freeBlock(b)
- goto Again
- case alertLevelError:
- c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])})
- default:
- c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
- }
-
- case recordTypeChangeCipherSpec:
- if typ != want || len(data) != 1 || data[0] != 1 {
- c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
- break
- }
- err := c.in.changeCipherSpec(c.config)
- if err != nil {
- c.in.setErrorLocked(c.sendAlert(err.(alert)))
- }
-
- case recordTypeApplicationData:
- if typ != want {
- c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
- break
- }
- c.input = b
- b = nil
-
- case recordTypeHandshake:
- // TODO(rsc): Should at least pick off connection close.
- if typ != want {
- // A client might need to process a HelloRequest from
- // the server, thus receiving a handshake message when
- // application data is expected is ok.
- if !c.isClient || want != recordTypeApplicationData {
- return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
- }
- }
- c.hand.Write(data)
- }
-
- if b != nil {
- c.in.freeBlock(b)
- }
- return c.in.err
-}
-
-// sendAlert sends a TLS alert message.
-// c.out.Mutex <= L.
-func (c *Conn) sendAlertLocked(level byte, err alert) error {
- c.tmp[0] = level
- c.tmp[1] = byte(err)
- if c.config.Bugs.FragmentAlert {
- c.writeRecord(recordTypeAlert, c.tmp[0:1])
- c.writeRecord(recordTypeAlert, c.tmp[1:2])
- } else {
- c.writeRecord(recordTypeAlert, c.tmp[0:2])
- }
- // Error alerts are fatal to the connection.
- if level == alertLevelError {
- return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
- }
- return nil
-}
-
-// sendAlert sends a TLS alert message.
-// L < c.out.Mutex.
-func (c *Conn) sendAlert(err alert) error {
- level := byte(alertLevelError)
- if err == alertNoRenegotiation || err == alertCloseNotify {
- level = alertLevelWarning
- }
- return c.SendAlert(level, err)
-}
-
-func (c *Conn) SendAlert(level byte, err alert) error {
- c.out.Lock()
- defer c.out.Unlock()
- return c.sendAlertLocked(level, err)
-}
-
-// writeV2Record writes a record for a V2ClientHello.
-func (c *Conn) writeV2Record(data []byte) (n int, err error) {
- record := make([]byte, 2+len(data))
- record[0] = uint8(len(data)>>8) | 0x80
- record[1] = uint8(len(data))
- copy(record[2:], data)
- return c.conn.Write(record)
-}
-
-// writeRecord writes a TLS record with the given type and payload
-// to the connection and updates the record layer state.
-// c.out.Mutex <= L.
-func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
- if c.isDTLS {
- return c.dtlsWriteRecord(typ, data)
- }
-
- recordHeaderLen := tlsRecordHeaderLen
- b := c.out.newBlock()
- first := true
- isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello
- for len(data) > 0 || first {
- m := len(data)
- if m > maxPlaintext && !c.config.Bugs.SendLargeRecords {
- m = maxPlaintext
- }
- if typ == recordTypeHandshake && c.config.Bugs.MaxHandshakeRecordLength > 0 && m > c.config.Bugs.MaxHandshakeRecordLength {
- m = c.config.Bugs.MaxHandshakeRecordLength
- // By default, do not fragment the client_version or
- // server_version, which are located in the first 6
- // bytes.
- if first && isClientHello && !c.config.Bugs.FragmentClientVersion && m < 6 {
- m = 6
- }
- }
- explicitIVLen := 0
- explicitIVIsSeq := false
- first = false
-
- var cbc cbcMode
- if c.out.version >= VersionTLS11 {
- var ok bool
- if cbc, ok = c.out.cipher.(cbcMode); ok {
- explicitIVLen = cbc.BlockSize()
- }
- }
- if explicitIVLen == 0 {
- if aead, ok := c.out.cipher.(*tlsAead); ok && aead.explicitNonce {
- explicitIVLen = 8
- // The AES-GCM construction in TLS has an
- // explicit nonce so that the nonce can be
- // random. However, the nonce is only 8 bytes
- // which is too small for a secure, random
- // nonce. Therefore we use the sequence number
- // as the nonce.
- explicitIVIsSeq = true
- }
- }
- b.resize(recordHeaderLen + explicitIVLen + m)
- b.data[0] = byte(typ)
- vers := c.vers
- if vers == 0 {
- // Some TLS servers fail if the record version is
- // greater than TLS 1.0 for the initial ClientHello.
- vers = VersionTLS10
- }
- b.data[1] = byte(vers >> 8)
- b.data[2] = byte(vers)
- b.data[3] = byte(m >> 8)
- b.data[4] = byte(m)
- if explicitIVLen > 0 {
- explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
- if explicitIVIsSeq {
- copy(explicitIV, c.out.seq[:])
- } else {
- if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil {
- break
- }
- }
- }
- copy(b.data[recordHeaderLen+explicitIVLen:], data)
- c.out.encrypt(b, explicitIVLen)
- _, err = c.conn.Write(b.data)
- if err != nil {
- break
- }
- n += m
- data = data[m:]
- }
- c.out.freeBlock(b)
-
- if typ == recordTypeChangeCipherSpec {
- err = c.out.changeCipherSpec(c.config)
- if err != nil {
- // Cannot call sendAlert directly,
- // because we already hold c.out.Mutex.
- c.tmp[0] = alertLevelError
- c.tmp[1] = byte(err.(alert))
- c.writeRecord(recordTypeAlert, c.tmp[0:2])
- return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
- }
- }
- return
-}
-
-func (c *Conn) doReadHandshake() ([]byte, error) {
- if c.isDTLS {
- return c.dtlsDoReadHandshake()
- }
-
- for c.hand.Len() < 4 {
- if err := c.in.err; err != nil {
- return nil, err
- }
- if err := c.readRecord(recordTypeHandshake); err != nil {
- return nil, err
- }
- }
-
- data := c.hand.Bytes()
- n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
- if n > maxHandshake {
- return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError))
- }
- for c.hand.Len() < 4+n {
- if err := c.in.err; err != nil {
- return nil, err
- }
- if err := c.readRecord(recordTypeHandshake); err != nil {
- return nil, err
- }
- }
- return c.hand.Next(4 + n), nil
-}
-
-// readHandshake reads the next handshake message from
-// the record layer.
-// c.in.Mutex < L; c.out.Mutex < L.
-func (c *Conn) readHandshake() (interface{}, error) {
- data, err := c.doReadHandshake()
- if err != nil {
- return nil, err
- }
-
- var m handshakeMessage
- switch data[0] {
- case typeHelloRequest:
- m = new(helloRequestMsg)
- case typeClientHello:
- m = &clientHelloMsg{
- isDTLS: c.isDTLS,
- }
- case typeServerHello:
- m = &serverHelloMsg{
- isDTLS: c.isDTLS,
- }
- case typeNewSessionTicket:
- m = new(newSessionTicketMsg)
- case typeCertificate:
- m = new(certificateMsg)
- case typeCertificateRequest:
- m = &certificateRequestMsg{
- hasSignatureAndHash: c.vers >= VersionTLS12,
- }
- case typeCertificateStatus:
- m = new(certificateStatusMsg)
- case typeServerKeyExchange:
- m = new(serverKeyExchangeMsg)
- case typeServerHelloDone:
- m = new(serverHelloDoneMsg)
- case typeClientKeyExchange:
- m = new(clientKeyExchangeMsg)
- case typeCertificateVerify:
- m = &certificateVerifyMsg{
- hasSignatureAndHash: c.vers >= VersionTLS12,
- }
- case typeNextProtocol:
- m = new(nextProtoMsg)
- case typeFinished:
- m = new(finishedMsg)
- case typeHelloVerifyRequest:
- m = new(helloVerifyRequestMsg)
- case typeEncryptedExtensions:
- m = new(encryptedExtensionsMsg)
- default:
- return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
- }
-
- // The handshake message unmarshallers
- // expect to be able to keep references to data,
- // so pass in a fresh copy that won't be overwritten.
- data = append([]byte(nil), data...)
-
- if !m.unmarshal(data) {
- return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
- }
- return m, nil
-}
-
-// skipPacket processes all the DTLS records in packet. It updates
-// sequence number expectations but otherwise ignores them.
-func (c *Conn) skipPacket(packet []byte) error {
- for len(packet) > 0 {
- if len(packet) < 13 {
- return errors.New("tls: bad packet")
- }
- // Dropped packets are completely ignored save to update
- // expected sequence numbers for this and the next epoch. (We
- // don't assert on the contents of the packets both for
- // simplicity and because a previous test with one shorter
- // timeout schedule would have done so.)
- epoch := packet[3:5]
- seq := packet[5:11]
- length := uint16(packet[11])<<8 | uint16(packet[12])
- if bytes.Equal(c.in.seq[:2], epoch) {
- if !bytes.Equal(c.in.seq[2:], seq) {
- return errors.New("tls: sequence mismatch")
- }
- c.in.incSeq(false)
- } else {
- if !bytes.Equal(c.in.nextSeq[:], seq) {
- return errors.New("tls: sequence mismatch")
- }
- c.in.incNextSeq()
- }
- if len(packet) < 13+int(length) {
- return errors.New("tls: bad packet")
- }
- packet = packet[13+length:]
- }
- return nil
-}
-
-// simulatePacketLoss simulates the loss of a handshake leg from the
-// peer based on the schedule in c.config.Bugs. If resendFunc is
-// non-nil, it is called after each simulated timeout to retransmit
-// handshake messages from the local end. This is used in cases where
-// the peer retransmits on a stale Finished rather than a timeout.
-func (c *Conn) simulatePacketLoss(resendFunc func()) error {
- if len(c.config.Bugs.TimeoutSchedule) == 0 {
- return nil
- }
- if !c.isDTLS {
- return errors.New("tls: TimeoutSchedule may only be set in DTLS")
- }
- if c.config.Bugs.PacketAdaptor == nil {
- return errors.New("tls: TimeoutSchedule set without PacketAdapter")
- }
- for _, timeout := range c.config.Bugs.TimeoutSchedule {
- // Simulate a timeout.
- packets, err := c.config.Bugs.PacketAdaptor.SendReadTimeout(timeout)
- if err != nil {
- return err
- }
- for _, packet := range packets {
- if err := c.skipPacket(packet); err != nil {
- return err
- }
- }
- if resendFunc != nil {
- resendFunc()
- }
- }
- return nil
-}
-
-// Write writes data to the connection.
-func (c *Conn) Write(b []byte) (int, error) {
- if err := c.Handshake(); err != nil {
- return 0, err
- }
-
- c.out.Lock()
- defer c.out.Unlock()
-
- if err := c.out.err; err != nil {
- return 0, err
- }
-
- if !c.handshakeComplete {
- return 0, alertInternalError
- }
-
- if c.config.Bugs.SendSpuriousAlert != 0 {
- c.sendAlertLocked(alertLevelError, c.config.Bugs.SendSpuriousAlert)
- }
-
- // SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
- // attack when using block mode ciphers due to predictable IVs.
- // This can be prevented by splitting each Application Data
- // record into two records, effectively randomizing the IV.
- //
- // http://www.openssl.org/~bodo/tls-cbc.txt
- // https://bugzilla.mozilla.org/show_bug.cgi?id=665814
- // http://www.imperialviolet.org/2012/01/15/beastfollowup.html
-
- var m int
- if len(b) > 1 && c.vers <= VersionTLS10 && !c.isDTLS {
- if _, ok := c.out.cipher.(cipher.BlockMode); ok {
- n, err := c.writeRecord(recordTypeApplicationData, b[:1])
- if err != nil {
- return n, c.out.setErrorLocked(err)
- }
- m, b = 1, b[1:]
- }
- }
-
- n, err := c.writeRecord(recordTypeApplicationData, b)
- return n + m, c.out.setErrorLocked(err)
-}
-
-func (c *Conn) handleRenegotiation() error {
- c.handshakeComplete = false
- if !c.isClient {
- panic("renegotiation should only happen for a client")
- }
-
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
- _, ok := msg.(*helloRequestMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return alertUnexpectedMessage
- }
-
- return c.Handshake()
-}
-
-func (c *Conn) Renegotiate() error {
- if !c.isClient {
- helloReq := new(helloRequestMsg)
- c.writeRecord(recordTypeHandshake, helloReq.marshal())
- }
-
- c.handshakeComplete = false
- return c.Handshake()
-}
-
-// Read can be made to time out and return a net.Error with Timeout() == true
-// after a fixed time limit; see SetDeadline and SetReadDeadline.
-func (c *Conn) Read(b []byte) (n int, err error) {
- if err = c.Handshake(); err != nil {
- return
- }
-
- c.in.Lock()
- defer c.in.Unlock()
-
- // Some OpenSSL servers send empty records in order to randomize the
- // CBC IV. So this loop ignores a limited number of empty records.
- const maxConsecutiveEmptyRecords = 100
- for emptyRecordCount := 0; emptyRecordCount <= maxConsecutiveEmptyRecords; emptyRecordCount++ {
- for c.input == nil && c.in.err == nil {
- if err := c.readRecord(recordTypeApplicationData); err != nil {
- // Soft error, like EAGAIN
- return 0, err
- }
- if c.hand.Len() > 0 {
- // We received handshake bytes, indicating the
- // start of a renegotiation.
- if err := c.handleRenegotiation(); err != nil {
- return 0, err
- }
- continue
- }
- }
- if err := c.in.err; err != nil {
- return 0, err
- }
-
- n, err = c.input.Read(b)
- if c.input.off >= len(c.input.data) || c.isDTLS {
- c.in.freeBlock(c.input)
- c.input = nil
- }
-
- // If a close-notify alert is waiting, read it so that
- // we can return (n, EOF) instead of (n, nil), to signal
- // to the HTTP response reading goroutine that the
- // connection is now closed. This eliminates a race
- // where the HTTP response reading goroutine would
- // otherwise not observe the EOF until its next read,
- // by which time a client goroutine might have already
- // tried to reuse the HTTP connection for a new
- // request.
- // See https://codereview.appspot.com/76400046
- // and http://golang.org/issue/3514
- if ri := c.rawInput; ri != nil &&
- n != 0 && err == nil &&
- c.input == nil && len(ri.data) > 0 && recordType(ri.data[0]) == recordTypeAlert {
- if recErr := c.readRecord(recordTypeApplicationData); recErr != nil {
- err = recErr // will be io.EOF on closeNotify
- }
- }
-
- if n != 0 || err != nil {
- return n, err
- }
- }
-
- return 0, io.ErrNoProgress
-}
-
-// Close closes the connection.
-func (c *Conn) Close() error {
- var alertErr error
-
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
- if c.handshakeComplete && !c.config.Bugs.NoCloseNotify {
- alertErr = c.sendAlert(alertCloseNotify)
- }
-
- // Consume a close_notify from the peer if one hasn't been received
- // already. This avoids the peer from failing |SSL_shutdown| due to a
- // write failing.
- if c.handshakeComplete && alertErr == nil && c.config.Bugs.ExpectCloseNotify {
- for c.in.error() == nil {
- c.readRecord(recordTypeAlert)
- }
- if c.in.error() != io.EOF {
- alertErr = c.in.error()
- }
- }
-
- if err := c.conn.Close(); err != nil {
- return err
- }
- return alertErr
-}
-
-// Handshake runs the client or server handshake
-// protocol if it has not yet been run.
-// Most uses of this package need not call Handshake
-// explicitly: the first Read or Write will call it automatically.
-func (c *Conn) Handshake() error {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
- if err := c.handshakeErr; err != nil {
- return err
- }
- if c.handshakeComplete {
- return nil
- }
-
- if c.isDTLS && c.config.Bugs.SendSplitAlert {
- c.conn.Write([]byte{
- byte(recordTypeAlert), // type
- 0xfe, 0xff, // version
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // sequence
- 0x0, 0x2, // length
- })
- c.conn.Write([]byte{alertLevelError, byte(alertInternalError)})
- }
- if data := c.config.Bugs.AppDataBeforeHandshake; data != nil {
- c.writeRecord(recordTypeApplicationData, data)
- }
- if c.isClient {
- c.handshakeErr = c.clientHandshake()
- } else {
- c.handshakeErr = c.serverHandshake()
- }
- if c.handshakeErr == nil && c.config.Bugs.SendInvalidRecordType {
- c.writeRecord(recordType(42), []byte("invalid record"))
- }
- return c.handshakeErr
-}
-
-// ConnectionState returns basic TLS details about the connection.
-func (c *Conn) ConnectionState() ConnectionState {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
-
- var state ConnectionState
- state.HandshakeComplete = c.handshakeComplete
- if c.handshakeComplete {
- state.Version = c.vers
- state.NegotiatedProtocol = c.clientProtocol
- state.DidResume = c.didResume
- state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
- state.NegotiatedProtocolFromALPN = c.usedALPN
- state.CipherSuite = c.cipherSuite.id
- state.PeerCertificates = c.peerCertificates
- state.VerifiedChains = c.verifiedChains
- state.ServerName = c.serverName
- state.ChannelID = c.channelID
- state.SRTPProtectionProfile = c.srtpProtectionProfile
- state.TLSUnique = c.firstFinished[:]
- state.SCTList = c.sctList
- state.ClientCertSignatureHash = c.clientCertSignatureHash
- }
-
- return state
-}
-
-// OCSPResponse returns the stapled OCSP response from the TLS server, if
-// any. (Only valid for client connections.)
-func (c *Conn) OCSPResponse() []byte {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
-
- return c.ocspResponse
-}
-
-// VerifyHostname checks that the peer certificate chain is valid for
-// connecting to host. If so, it returns nil; if not, it returns an error
-// describing the problem.
-func (c *Conn) VerifyHostname(host string) error {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
- if !c.isClient {
- return errors.New("tls: VerifyHostname called on TLS server connection")
- }
- if !c.handshakeComplete {
- return errors.New("tls: handshake has not yet been performed")
- }
- return c.peerCertificates[0].VerifyHostname(host)
-}
-
-// ExportKeyingMaterial exports keying material from the current connection
-// state, as per RFC 5705.
-func (c *Conn) ExportKeyingMaterial(length int, label, context []byte, useContext bool) ([]byte, error) {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
- if !c.handshakeComplete {
- return nil, errors.New("tls: handshake has not yet been performed")
- }
-
- seedLen := len(c.clientRandom) + len(c.serverRandom)
- if useContext {
- seedLen += 2 + len(context)
- }
- seed := make([]byte, 0, seedLen)
- seed = append(seed, c.clientRandom[:]...)
- seed = append(seed, c.serverRandom[:]...)
- if useContext {
- seed = append(seed, byte(len(context)>>8), byte(len(context)))
- seed = append(seed, context...)
- }
- result := make([]byte, length)
- prfForVersion(c.vers, c.cipherSuite)(result, c.masterSecret[:], label, seed)
- return result, nil
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/dtls.go b/third_party/boringssl/src/ssl/test/runner/dtls.go
deleted file mode 100644
index fac035e3e2..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/dtls.go
+++ /dev/null
@@ -1,431 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// DTLS implementation.
-//
-// NOTE: This is a not even a remotely production-quality DTLS
-// implementation. It is the bare minimum necessary to be able to
-// achieve coverage on BoringSSL's implementation. Of note is that
-// this implementation assumes the underlying net.PacketConn is not
-// only reliable but also ordered. BoringSSL will be expected to deal
-// with simulated loss, but there is no point in forcing the test
-// driver to.
-
-package runner
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "math/rand"
- "net"
-)
-
-func versionToWire(vers uint16, isDTLS bool) uint16 {
- if isDTLS {
- return ^(vers - 0x0201)
- }
- return vers
-}
-
-func wireToVersion(vers uint16, isDTLS bool) uint16 {
- if isDTLS {
- return ^vers + 0x0201
- }
- return vers
-}
-
-func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
- recordHeaderLen := dtlsRecordHeaderLen
-
- if c.rawInput == nil {
- c.rawInput = c.in.newBlock()
- }
- b := c.rawInput
-
- // Read a new packet only if the current one is empty.
- if len(b.data) == 0 {
- // Pick some absurdly large buffer size.
- b.resize(maxCiphertext + recordHeaderLen)
- n, err := c.conn.Read(c.rawInput.data)
- if err != nil {
- return 0, nil, err
- }
- if c.config.Bugs.MaxPacketLength != 0 && n > c.config.Bugs.MaxPacketLength {
- return 0, nil, fmt.Errorf("dtls: exceeded maximum packet length")
- }
- c.rawInput.resize(n)
- }
-
- // Read out one record.
- //
- // A real DTLS implementation should be tolerant of errors,
- // but this is test code. We should not be tolerant of our
- // peer sending garbage.
- if len(b.data) < recordHeaderLen {
- return 0, nil, errors.New("dtls: failed to read record header")
- }
- typ := recordType(b.data[0])
- vers := wireToVersion(uint16(b.data[1])<<8|uint16(b.data[2]), c.isDTLS)
- if c.haveVers {
- if vers != c.vers {
- c.sendAlert(alertProtocolVersion)
- return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, c.vers))
- }
- } else {
- if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
- c.sendAlert(alertProtocolVersion)
- return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, expect))
- }
- }
- seq := b.data[3:11]
- // For test purposes, we assume a reliable channel. Require
- // that the explicit sequence number matches the incrementing
- // one we maintain. A real implementation would maintain a
- // replay window and such.
- if !bytes.Equal(seq, c.in.seq[:]) {
- c.sendAlert(alertIllegalParameter)
- return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: bad sequence number"))
- }
- n := int(b.data[11])<<8 | int(b.data[12])
- if n > maxCiphertext || len(b.data) < recordHeaderLen+n {
- c.sendAlert(alertRecordOverflow)
- return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: oversized record received with length %d", n))
- }
-
- // Process message.
- b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
- ok, off, err := c.in.decrypt(b)
- if !ok {
- c.in.setErrorLocked(c.sendAlert(err))
- }
- b.off = off
- return typ, b, nil
-}
-
-func (c *Conn) makeFragment(header, data []byte, fragOffset, fragLen int) []byte {
- fragment := make([]byte, 0, 12+fragLen)
- fragment = append(fragment, header...)
- fragment = append(fragment, byte(c.sendHandshakeSeq>>8), byte(c.sendHandshakeSeq))
- fragment = append(fragment, byte(fragOffset>>16), byte(fragOffset>>8), byte(fragOffset))
- fragment = append(fragment, byte(fragLen>>16), byte(fragLen>>8), byte(fragLen))
- fragment = append(fragment, data[fragOffset:fragOffset+fragLen]...)
- return fragment
-}
-
-func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) {
- if typ != recordTypeHandshake {
- // Only handshake messages are fragmented.
- return c.dtlsWriteRawRecord(typ, data)
- }
-
- maxLen := c.config.Bugs.MaxHandshakeRecordLength
- if maxLen <= 0 {
- maxLen = 1024
- }
-
- // Handshake messages have to be modified to include fragment
- // offset and length and with the header replicated. Save the
- // TLS header here.
- //
- // TODO(davidben): This assumes that data contains exactly one
- // handshake message. This is incompatible with
- // FragmentAcrossChangeCipherSpec. (Which is unfortunate
- // because OpenSSL's DTLS implementation will probably accept
- // such fragmentation and could do with a fix + tests.)
- header := data[:4]
- data = data[4:]
-
- isFinished := header[0] == typeFinished
-
- if c.config.Bugs.SendEmptyFragments {
- fragment := c.makeFragment(header, data, 0, 0)
- c.pendingFragments = append(c.pendingFragments, fragment)
- }
-
- firstRun := true
- fragOffset := 0
- for firstRun || fragOffset < len(data) {
- firstRun = false
- fragLen := len(data) - fragOffset
- if fragLen > maxLen {
- fragLen = maxLen
- }
-
- fragment := c.makeFragment(header, data, fragOffset, fragLen)
- if c.config.Bugs.FragmentMessageTypeMismatch && fragOffset > 0 {
- fragment[0]++
- }
- if c.config.Bugs.FragmentMessageLengthMismatch && fragOffset > 0 {
- fragment[3]++
- }
-
- // Buffer the fragment for later. They will be sent (and
- // reordered) on flush.
- c.pendingFragments = append(c.pendingFragments, fragment)
- if c.config.Bugs.ReorderHandshakeFragments {
- // Don't duplicate Finished to avoid the peer
- // interpreting it as a retransmit request.
- if !isFinished {
- c.pendingFragments = append(c.pendingFragments, fragment)
- }
-
- if fragLen > (maxLen+1)/2 {
- // Overlap each fragment by half.
- fragLen = (maxLen + 1) / 2
- }
- }
- fragOffset += fragLen
- n += fragLen
- }
- if !isFinished && c.config.Bugs.MixCompleteMessageWithFragments {
- fragment := c.makeFragment(header, data, 0, len(data))
- c.pendingFragments = append(c.pendingFragments, fragment)
- }
-
- // Increment the handshake sequence number for the next
- // handshake message.
- c.sendHandshakeSeq++
- return
-}
-
-func (c *Conn) dtlsFlushHandshake() error {
- if !c.isDTLS {
- return nil
- }
-
- // This is a test-only DTLS implementation, so there is no need to
- // retain |c.pendingFragments| for a future retransmit.
- var fragments [][]byte
- fragments, c.pendingFragments = c.pendingFragments, fragments
-
- if c.config.Bugs.ReorderHandshakeFragments {
- perm := rand.New(rand.NewSource(0)).Perm(len(fragments))
- tmp := make([][]byte, len(fragments))
- for i := range tmp {
- tmp[i] = fragments[perm[i]]
- }
- fragments = tmp
- }
-
- maxRecordLen := c.config.Bugs.PackHandshakeFragments
- maxPacketLen := c.config.Bugs.PackHandshakeRecords
-
- // Pack handshake fragments into records.
- var records [][]byte
- for _, fragment := range fragments {
- if n := c.config.Bugs.SplitFragments; n > 0 {
- if len(fragment) > n {
- records = append(records, fragment[:n])
- records = append(records, fragment[n:])
- } else {
- records = append(records, fragment)
- }
- } else if i := len(records) - 1; len(records) > 0 && len(records[i])+len(fragment) <= maxRecordLen {
- records[i] = append(records[i], fragment...)
- } else {
- // The fragment will be appended to, so copy it.
- records = append(records, append([]byte{}, fragment...))
- }
- }
-
- // Format them into packets.
- var packets [][]byte
- for _, record := range records {
- b, err := c.dtlsSealRecord(recordTypeHandshake, record)
- 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) {
- recordHeaderLen := dtlsRecordHeaderLen
- maxLen := c.config.Bugs.MaxHandshakeRecordLength
- if maxLen <= 0 {
- maxLen = 1024
- }
-
- b = c.out.newBlock()
-
- explicitIVLen := 0
- explicitIVIsSeq := false
-
- if cbc, ok := c.out.cipher.(cbcMode); ok {
- // Block cipher modes have an explicit IV.
- explicitIVLen = cbc.BlockSize()
- } else if aead, ok := c.out.cipher.(*tlsAead); ok {
- if aead.explicitNonce {
- explicitIVLen = 8
- // The AES-GCM construction in TLS has an explicit nonce so that
- // the nonce can be random. However, the nonce is only 8 bytes
- // which is too small for a secure, random nonce. Therefore we
- // use the sequence number as the nonce.
- explicitIVIsSeq = true
- }
- } else if c.out.cipher != nil {
- panic("Unknown cipher")
- }
- b.resize(recordHeaderLen + explicitIVLen + len(data))
- b.data[0] = byte(typ)
- vers := c.vers
- if vers == 0 {
- // Some TLS servers fail if the record version is greater than
- // TLS 1.0 for the initial ClientHello.
- vers = VersionTLS10
- }
- vers = versionToWire(vers, c.isDTLS)
- b.data[1] = byte(vers >> 8)
- b.data[2] = byte(vers)
- // DTLS records include an explicit sequence number.
- copy(b.data[3:11], c.out.outSeq[0:])
- b.data[11] = byte(len(data) >> 8)
- b.data[12] = byte(len(data))
- if explicitIVLen > 0 {
- explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
- if explicitIVIsSeq {
- copy(explicitIV, c.out.outSeq[:])
- } else {
- if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil {
- return
- }
- }
- }
- copy(b.data[recordHeaderLen+explicitIVLen:], data)
- c.out.encrypt(b, explicitIVLen)
- return
-}
-
-func (c *Conn) dtlsWriteRawRecord(typ recordType, data []byte) (n int, err error) {
- b, err := c.dtlsSealRecord(typ, data)
- if err != nil {
- return
- }
-
- _, err = c.conn.Write(b.data)
- if err != nil {
- return
- }
- n = len(data)
-
- c.out.freeBlock(b)
-
- if typ == recordTypeChangeCipherSpec {
- err = c.out.changeCipherSpec(c.config)
- if err != nil {
- // Cannot call sendAlert directly,
- // because we already hold c.out.Mutex.
- c.tmp[0] = alertLevelError
- c.tmp[1] = byte(err.(alert))
- c.writeRecord(recordTypeAlert, c.tmp[0:2])
- return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
- }
- }
- return
-}
-
-func (c *Conn) dtlsDoReadHandshake() ([]byte, error) {
- // Assemble a full handshake message. For test purposes, this
- // implementation assumes fragments arrive in order. It may
- // need to be cleverer if we ever test BoringSSL's retransmit
- // behavior.
- for len(c.handMsg) < 4+c.handMsgLen {
- // Get a new handshake record if the previous has been
- // exhausted.
- if c.hand.Len() == 0 {
- if err := c.in.err; err != nil {
- return nil, err
- }
- if err := c.readRecord(recordTypeHandshake); err != nil {
- return nil, err
- }
- }
-
- // Read the next fragment. It must fit entirely within
- // the record.
- if c.hand.Len() < 12 {
- return nil, errors.New("dtls: bad handshake record")
- }
- header := c.hand.Next(12)
- fragN := int(header[1])<<16 | int(header[2])<<8 | int(header[3])
- fragSeq := uint16(header[4])<<8 | uint16(header[5])
- fragOff := int(header[6])<<16 | int(header[7])<<8 | int(header[8])
- fragLen := int(header[9])<<16 | int(header[10])<<8 | int(header[11])
-
- if c.hand.Len() < fragLen {
- return nil, errors.New("dtls: fragment length too long")
- }
- fragment := c.hand.Next(fragLen)
-
- // Check it's a fragment for the right message.
- if fragSeq != c.recvHandshakeSeq {
- return nil, errors.New("dtls: bad handshake sequence number")
- }
-
- // Check that the length is consistent.
- if c.handMsg == nil {
- c.handMsgLen = fragN
- if c.handMsgLen > maxHandshake {
- return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError))
- }
- // Start with the TLS handshake header,
- // without the DTLS bits.
- c.handMsg = append([]byte{}, header[:4]...)
- } else if fragN != c.handMsgLen {
- return nil, errors.New("dtls: bad handshake length")
- }
-
- // Add the fragment to the pending message.
- if 4+fragOff != len(c.handMsg) {
- return nil, errors.New("dtls: bad fragment offset")
- }
- if fragOff+fragLen > c.handMsgLen {
- return nil, errors.New("dtls: bad fragment length")
- }
- c.handMsg = append(c.handMsg, fragment...)
- }
- c.recvHandshakeSeq++
- ret := c.handMsg
- c.handMsg, c.handMsgLen = nil, 0
- return ret, nil
-}
-
-// DTLSServer returns a new DTLS server side connection
-// using conn as the underlying transport.
-// The configuration config must be non-nil and must have
-// at least one certificate.
-func DTLSServer(conn net.Conn, config *Config) *Conn {
- c := &Conn{config: config, isDTLS: true, conn: conn}
- c.init()
- return c
-}
-
-// DTLSClient returns a new DTLS client side connection
-// using conn as the underlying transport.
-// The config cannot be nil: users must set either ServerHostname or
-// InsecureSkipVerify in the config.
-func DTLSClient(conn net.Conn, config *Config) *Conn {
- c := &Conn{config: config, isClient: true, isDTLS: true, conn: conn}
- c.init()
- return c
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/ecdsa_cert.pem b/third_party/boringssl/src/ssl/test/runner/ecdsa_cert.pem
deleted file mode 100644
index 50bcbf5bfd..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/ecdsa_cert.pem
+++ /dev/null
@@ -1,12 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIBzzCCAXagAwIBAgIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
-QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
-dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ
-BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
-dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni
-v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa
-HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw
-HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ
-BgcqhkjOPQQBA0gAMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E
-BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQ=
------END CERTIFICATE-----
diff --git a/third_party/boringssl/src/ssl/test/runner/ecdsa_key.pem b/third_party/boringssl/src/ssl/test/runner/ecdsa_key.pem
deleted file mode 100644
index b9116f0cac..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/ecdsa_key.pem
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN EC PARAMETERS-----
-BggqhkjOPQMBBw==
------END EC PARAMETERS-----
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIAcPCHJ61KBKnN1ZyU2JaHcItW/JXTB3DujRyc4Ki7RqoAoGCCqGSM49
-AwEHoUQDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY
-+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwQ==
------END EC PRIVATE KEY-----
diff --git a/third_party/boringssl/src/ssl/test/runner/handshake_client.go b/third_party/boringssl/src/ssl/test/runner/handshake_client.go
deleted file mode 100644
index e63d5eb2b6..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/handshake_client.go
+++ /dev/null
@@ -1,1000 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import (
- "bytes"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rsa"
- "crypto/subtle"
- "crypto/x509"
- "encoding/asn1"
- "errors"
- "fmt"
- "io"
- "math/big"
- "net"
- "strconv"
-)
-
-type clientHandshakeState struct {
- c *Conn
- serverHello *serverHelloMsg
- hello *clientHelloMsg
- suite *cipherSuite
- finishedHash finishedHash
- masterSecret []byte
- session *ClientSessionState
- finishedBytes []byte
-}
-
-func (c *Conn) clientHandshake() error {
- if c.config == nil {
- c.config = defaultConfig()
- }
-
- if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
- return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
- }
-
- c.sendHandshakeSeq = 0
- c.recvHandshakeSeq = 0
-
- nextProtosLength := 0
- for _, proto := range c.config.NextProtos {
- if l := len(proto); l > 255 {
- return errors.New("tls: invalid NextProtos value")
- } else {
- nextProtosLength += 1 + l
- }
- }
- if nextProtosLength > 0xffff {
- return errors.New("tls: NextProtos values too large")
- }
-
- hello := &clientHelloMsg{
- isDTLS: c.isDTLS,
- vers: c.config.maxVersion(),
- compressionMethods: []uint8{compressionNone},
- random: make([]byte, 32),
- ocspStapling: true,
- sctListSupported: true,
- serverName: c.config.ServerName,
- supportedCurves: c.config.curvePreferences(),
- supportedPoints: []uint8{pointFormatUncompressed},
- nextProtoNeg: len(c.config.NextProtos) > 0,
- secureRenegotiation: []byte{},
- alpnProtocols: c.config.NextProtos,
- duplicateExtension: c.config.Bugs.DuplicateExtension,
- channelIDSupported: c.config.ChannelID != nil,
- npnLast: c.config.Bugs.SwapNPNAndALPN,
- extendedMasterSecret: c.config.maxVersion() >= VersionTLS10,
- srtpProtectionProfiles: c.config.SRTPProtectionProfiles,
- srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
- customExtension: c.config.Bugs.CustomExtension,
- }
-
- if c.config.Bugs.SendClientVersion != 0 {
- hello.vers = c.config.Bugs.SendClientVersion
- }
-
- if c.config.Bugs.NoExtendedMasterSecret {
- hello.extendedMasterSecret = false
- }
-
- if c.config.Bugs.NoSupportedCurves {
- hello.supportedCurves = nil
- }
-
- if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
- if c.config.Bugs.BadRenegotiationInfo {
- hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
- hello.secureRenegotiation[0] ^= 0x80
- } else {
- hello.secureRenegotiation = c.clientVerify
- }
- }
-
- if c.config.Bugs.NoRenegotiationInfo {
- hello.secureRenegotiation = nil
- }
-
- possibleCipherSuites := c.config.cipherSuites()
- hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
-
-NextCipherSuite:
- for _, suiteId := range possibleCipherSuites {
- for _, suite := range cipherSuites {
- if suite.id != suiteId {
- continue
- }
- // Don't advertise TLS 1.2-only cipher suites unless
- // we're attempting TLS 1.2.
- if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
- continue
- }
- // Don't advertise non-DTLS cipher suites on DTLS.
- if c.isDTLS && suite.flags&suiteNoDTLS != 0 && !c.config.Bugs.EnableAllCiphersInDTLS {
- continue
- }
- hello.cipherSuites = append(hello.cipherSuites, suiteId)
- continue NextCipherSuite
- }
- }
-
- if c.config.Bugs.SendRenegotiationSCSV {
- hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
- }
-
- if c.config.Bugs.SendFallbackSCSV {
- hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
- }
-
- _, err := io.ReadFull(c.config.rand(), hello.random)
- if err != nil {
- c.sendAlert(alertInternalError)
- return errors.New("tls: short read from Rand: " + err.Error())
- }
-
- if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAndHashes {
- hello.signatureAndHashes = c.config.signatureAndHashesForClient()
- }
-
- var session *ClientSessionState
- var cacheKey string
- sessionCache := c.config.ClientSessionCache
-
- if sessionCache != nil {
- hello.ticketSupported = !c.config.SessionTicketsDisabled
-
- // Try to resume a previously negotiated TLS session, if
- // available.
- cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
- candidateSession, ok := sessionCache.Get(cacheKey)
- if ok {
- ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
-
- // Check that the ciphersuite/version used for the
- // previous session are still valid.
- cipherSuiteOk := false
- for _, id := range hello.cipherSuites {
- if id == candidateSession.cipherSuite {
- cipherSuiteOk = true
- break
- }
- }
-
- versOk := candidateSession.vers >= c.config.minVersion() &&
- candidateSession.vers <= c.config.maxVersion()
- if ticketOk && versOk && cipherSuiteOk {
- session = candidateSession
- }
- }
- }
-
- if session != nil {
- if session.sessionTicket != nil {
- hello.sessionTicket = session.sessionTicket
- if c.config.Bugs.CorruptTicket {
- hello.sessionTicket = make([]byte, len(session.sessionTicket))
- copy(hello.sessionTicket, session.sessionTicket)
- if len(hello.sessionTicket) > 0 {
- offset := 40
- if offset > len(hello.sessionTicket) {
- offset = len(hello.sessionTicket) - 1
- }
- hello.sessionTicket[offset] ^= 0x40
- }
- }
- // A random session ID is used to detect when the
- // server accepted the ticket and is resuming a session
- // (see RFC 5077).
- sessionIdLen := 16
- if c.config.Bugs.OversizedSessionId {
- sessionIdLen = 33
- }
- hello.sessionId = make([]byte, sessionIdLen)
- if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
- c.sendAlert(alertInternalError)
- return errors.New("tls: short read from Rand: " + err.Error())
- }
- } else {
- hello.sessionId = session.sessionId
- }
- }
-
- var helloBytes []byte
- if c.config.Bugs.SendV2ClientHello {
- // Test that the peer left-pads random.
- hello.random[0] = 0
- v2Hello := &v2ClientHelloMsg{
- vers: hello.vers,
- cipherSuites: hello.cipherSuites,
- // No session resumption for V2ClientHello.
- sessionId: nil,
- challenge: hello.random[1:],
- }
- helloBytes = v2Hello.marshal()
- c.writeV2Record(helloBytes)
- } else {
- helloBytes = hello.marshal()
- c.writeRecord(recordTypeHandshake, helloBytes)
- }
- c.dtlsFlushHandshake()
-
- if err := c.simulatePacketLoss(nil); err != nil {
- return err
- }
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
-
- if c.isDTLS {
- helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
- if ok {
- if helloVerifyRequest.vers != VersionTLS10 {
- // Per RFC 6347, the version field in
- // HelloVerifyRequest SHOULD be always DTLS
- // 1.0. Enforce this for testing purposes.
- return errors.New("dtls: bad HelloVerifyRequest version")
- }
-
- hello.raw = nil
- hello.cookie = helloVerifyRequest.cookie
- helloBytes = hello.marshal()
- c.writeRecord(recordTypeHandshake, helloBytes)
- c.dtlsFlushHandshake()
-
- if err := c.simulatePacketLoss(nil); err != nil {
- return err
- }
- msg, err = c.readHandshake()
- if err != nil {
- return err
- }
- }
- }
-
- serverHello, ok := msg.(*serverHelloMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(serverHello, msg)
- }
-
- c.vers, ok = c.config.mutualVersion(serverHello.vers)
- if !ok {
- c.sendAlert(alertProtocolVersion)
- return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers)
- }
- c.haveVers = true
-
- suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
- if suite == nil {
- c.sendAlert(alertHandshakeFailure)
- return fmt.Errorf("tls: server selected an unsupported cipher suite")
- }
-
- if c.config.Bugs.RequireRenegotiationInfo && serverHello.secureRenegotiation == nil {
- return errors.New("tls: renegotiation extension missing")
- }
-
- if len(c.clientVerify) > 0 && !c.config.Bugs.NoRenegotiationInfo {
- var expectedRenegInfo []byte
- expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
- expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
- if !bytes.Equal(serverHello.secureRenegotiation, expectedRenegInfo) {
- c.sendAlert(alertHandshakeFailure)
- return fmt.Errorf("tls: renegotiation mismatch")
- }
- }
-
- if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
- if serverHello.customExtension != *expected {
- return fmt.Errorf("tls: bad custom extension contents %q", serverHello.customExtension)
- }
- }
-
- hs := &clientHandshakeState{
- c: c,
- serverHello: serverHello,
- hello: hello,
- suite: suite,
- finishedHash: newFinishedHash(c.vers, suite),
- session: session,
- }
-
- hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
- hs.writeServerHash(hs.serverHello.marshal())
-
- if c.config.Bugs.EarlyChangeCipherSpec > 0 {
- hs.establishKeys()
- c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
- }
-
- isResume, err := hs.processServerHello()
- if err != nil {
- return err
- }
-
- if isResume {
- if c.config.Bugs.EarlyChangeCipherSpec == 0 {
- if err := hs.establishKeys(); err != nil {
- return err
- }
- }
- if err := hs.readSessionTicket(); err != nil {
- return err
- }
- if err := hs.readFinished(c.firstFinished[:]); err != nil {
- return err
- }
- if err := hs.sendFinished(nil, isResume); err != nil {
- return err
- }
- } else {
- if err := hs.doFullHandshake(); err != nil {
- return err
- }
- if err := hs.establishKeys(); err != nil {
- return err
- }
- if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
- return err
- }
- // Most retransmits are triggered by a timeout, but the final
- // leg of the handshake is retransmited upon re-receiving a
- // Finished.
- if err := c.simulatePacketLoss(func() {
- c.writeRecord(recordTypeHandshake, hs.finishedBytes)
- c.dtlsFlushHandshake()
- }); err != nil {
- return err
- }
- if err := hs.readSessionTicket(); err != nil {
- return err
- }
- if err := hs.readFinished(nil); err != nil {
- return err
- }
- }
-
- if sessionCache != nil && hs.session != nil && session != hs.session {
- sessionCache.Put(cacheKey, hs.session)
- }
-
- c.didResume = isResume
- c.handshakeComplete = true
- c.cipherSuite = suite
- copy(c.clientRandom[:], hs.hello.random)
- copy(c.serverRandom[:], hs.serverHello.random)
- copy(c.masterSecret[:], hs.masterSecret)
-
- return nil
-}
-
-func (hs *clientHandshakeState) doFullHandshake() error {
- c := hs.c
-
- var leaf *x509.Certificate
- if hs.suite.flags&suitePSK == 0 {
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
-
- certMsg, ok := msg.(*certificateMsg)
- if !ok || len(certMsg.certificates) == 0 {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(certMsg, msg)
- }
- hs.writeServerHash(certMsg.marshal())
-
- certs := make([]*x509.Certificate, len(certMsg.certificates))
- for i, asn1Data := range certMsg.certificates {
- cert, err := x509.ParseCertificate(asn1Data)
- if err != nil {
- c.sendAlert(alertBadCertificate)
- return errors.New("tls: failed to parse certificate from server: " + err.Error())
- }
- certs[i] = cert
- }
- leaf = certs[0]
-
- if !c.config.InsecureSkipVerify {
- opts := x509.VerifyOptions{
- Roots: c.config.RootCAs,
- CurrentTime: c.config.time(),
- DNSName: c.config.ServerName,
- Intermediates: x509.NewCertPool(),
- }
-
- for i, cert := range certs {
- if i == 0 {
- continue
- }
- opts.Intermediates.AddCert(cert)
- }
- c.verifiedChains, err = leaf.Verify(opts)
- if err != nil {
- c.sendAlert(alertBadCertificate)
- return err
- }
- }
-
- switch leaf.PublicKey.(type) {
- case *rsa.PublicKey, *ecdsa.PublicKey:
- break
- default:
- c.sendAlert(alertUnsupportedCertificate)
- return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leaf.PublicKey)
- }
-
- c.peerCertificates = certs
- }
-
- if hs.serverHello.ocspStapling {
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
- cs, ok := msg.(*certificateStatusMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(cs, msg)
- }
- hs.writeServerHash(cs.marshal())
-
- if cs.statusType == statusTypeOCSP {
- c.ocspResponse = cs.response
- }
- }
-
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
-
- keyAgreement := hs.suite.ka(c.vers)
-
- skx, ok := msg.(*serverKeyExchangeMsg)
- if ok {
- hs.writeServerHash(skx.marshal())
- err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
- if err != nil {
- c.sendAlert(alertUnexpectedMessage)
- return err
- }
-
- msg, err = c.readHandshake()
- if err != nil {
- return err
- }
- }
-
- var chainToSend *Certificate
- var certRequested bool
- certReq, ok := msg.(*certificateRequestMsg)
- if ok {
- certRequested = true
-
- // RFC 4346 on the certificateAuthorities field:
- // A list of the distinguished names of acceptable certificate
- // authorities. These distinguished names may specify a desired
- // distinguished name for a root CA or for a subordinate CA;
- // thus, this message can be used to describe both known roots
- // and a desired authorization space. If the
- // certificate_authorities list is empty then the client MAY
- // send any certificate of the appropriate
- // ClientCertificateType, unless there is some external
- // arrangement to the contrary.
-
- hs.writeServerHash(certReq.marshal())
-
- var rsaAvail, ecdsaAvail bool
- for _, certType := range certReq.certificateTypes {
- switch certType {
- case CertTypeRSASign:
- rsaAvail = true
- case CertTypeECDSASign:
- ecdsaAvail = true
- }
- }
-
- // We need to search our list of client certs for one
- // where SignatureAlgorithm is RSA and the Issuer is in
- // certReq.certificateAuthorities
- findCert:
- for i, chain := range c.config.Certificates {
- if !rsaAvail && !ecdsaAvail {
- continue
- }
-
- for j, cert := range chain.Certificate {
- x509Cert := chain.Leaf
- // parse the certificate if this isn't the leaf
- // node, or if chain.Leaf was nil
- if j != 0 || x509Cert == nil {
- if x509Cert, err = x509.ParseCertificate(cert); err != nil {
- c.sendAlert(alertInternalError)
- return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
- }
- }
-
- switch {
- case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
- case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
- default:
- continue findCert
- }
-
- if len(certReq.certificateAuthorities) == 0 {
- // they gave us an empty list, so just take the
- // first RSA cert from c.config.Certificates
- chainToSend = &chain
- break findCert
- }
-
- for _, ca := range certReq.certificateAuthorities {
- if bytes.Equal(x509Cert.RawIssuer, ca) {
- chainToSend = &chain
- break findCert
- }
- }
- }
- }
-
- msg, err = c.readHandshake()
- if err != nil {
- return err
- }
- }
-
- shd, ok := msg.(*serverHelloDoneMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(shd, msg)
- }
- hs.writeServerHash(shd.marshal())
-
- // If the server requested a certificate then we have to send a
- // Certificate message, even if it's empty because we don't have a
- // certificate to send.
- if certRequested {
- certMsg := new(certificateMsg)
- if chainToSend != nil {
- certMsg.certificates = chainToSend.Certificate
- }
- hs.writeClientHash(certMsg.marshal())
- c.writeRecord(recordTypeHandshake, certMsg.marshal())
- }
-
- preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
- if err != nil {
- c.sendAlert(alertInternalError)
- return err
- }
- if ckx != nil {
- if c.config.Bugs.EarlyChangeCipherSpec < 2 {
- hs.writeClientHash(ckx.marshal())
- }
- c.writeRecord(recordTypeHandshake, ckx.marshal())
- }
-
- if hs.serverHello.extendedMasterSecret && c.vers >= VersionTLS10 {
- hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
- c.extendedMasterSecret = true
- } else {
- if c.config.Bugs.RequireExtendedMasterSecret {
- return errors.New("tls: extended master secret required but not supported by peer")
- }
- hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
- }
-
- if chainToSend != nil {
- var signed []byte
- certVerify := &certificateVerifyMsg{
- hasSignatureAndHash: c.vers >= VersionTLS12,
- }
-
- // Determine the hash to sign.
- var signatureType uint8
- switch c.config.Certificates[0].PrivateKey.(type) {
- case *ecdsa.PrivateKey:
- signatureType = signatureECDSA
- case *rsa.PrivateKey:
- signatureType = signatureRSA
- default:
- c.sendAlert(alertInternalError)
- return errors.New("unknown private key type")
- }
- if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
- certReq.signatureAndHashes = c.config.signatureAndHashesForClient()
- }
- certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, c.config.signatureAndHashesForClient(), signatureType)
- if err != nil {
- c.sendAlert(alertInternalError)
- return err
- }
- digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
- if err != nil {
- c.sendAlert(alertInternalError)
- return err
- }
- if c.config.Bugs.InvalidCertVerifySignature {
- digest[0] ^= 0x80
- }
-
- switch key := c.config.Certificates[0].PrivateKey.(type) {
- case *ecdsa.PrivateKey:
- var r, s *big.Int
- r, s, err = ecdsa.Sign(c.config.rand(), key, digest)
- if err == nil {
- signed, err = asn1.Marshal(ecdsaSignature{r, s})
- }
- case *rsa.PrivateKey:
- signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
- default:
- err = errors.New("unknown private key type")
- }
- if err != nil {
- c.sendAlert(alertInternalError)
- return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
- }
- certVerify.signature = signed
-
- hs.writeClientHash(certVerify.marshal())
- c.writeRecord(recordTypeHandshake, certVerify.marshal())
- }
- c.dtlsFlushHandshake()
-
- hs.finishedHash.discardHandshakeBuffer()
-
- return nil
-}
-
-func (hs *clientHandshakeState) establishKeys() error {
- c := hs.c
-
- clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
- var clientCipher, serverCipher interface{}
- var clientHash, serverHash macFunction
- if hs.suite.cipher != nil {
- clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
- clientHash = hs.suite.mac(c.vers, clientMAC)
- serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
- serverHash = hs.suite.mac(c.vers, serverMAC)
- } else {
- clientCipher = hs.suite.aead(clientKey, clientIV)
- serverCipher = hs.suite.aead(serverKey, serverIV)
- }
-
- c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
- c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
- return nil
-}
-
-func (hs *clientHandshakeState) serverResumedSession() bool {
- // If the server responded with the same sessionId then it means the
- // sessionTicket is being used to resume a TLS session.
- return hs.session != nil && hs.hello.sessionId != nil &&
- bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
-}
-
-func (hs *clientHandshakeState) processServerHello() (bool, error) {
- c := hs.c
-
- if hs.serverHello.compressionMethod != compressionNone {
- c.sendAlert(alertUnexpectedMessage)
- return false, errors.New("tls: server selected unsupported compression format")
- }
-
- clientDidNPN := hs.hello.nextProtoNeg
- clientDidALPN := len(hs.hello.alpnProtocols) > 0
- serverHasNPN := hs.serverHello.nextProtoNeg
- serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
-
- if !clientDidNPN && serverHasNPN {
- c.sendAlert(alertHandshakeFailure)
- return false, errors.New("server advertised unrequested NPN extension")
- }
-
- if !clientDidALPN && serverHasALPN {
- c.sendAlert(alertHandshakeFailure)
- return false, errors.New("server advertised unrequested ALPN extension")
- }
-
- if serverHasNPN && serverHasALPN {
- c.sendAlert(alertHandshakeFailure)
- return false, errors.New("server advertised both NPN and ALPN extensions")
- }
-
- if serverHasALPN {
- c.clientProtocol = hs.serverHello.alpnProtocol
- c.clientProtocolFallback = false
- c.usedALPN = true
- }
-
- if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
- c.sendAlert(alertHandshakeFailure)
- return false, errors.New("server advertised unrequested Channel ID extension")
- }
-
- if hs.serverHello.srtpProtectionProfile != 0 {
- if hs.serverHello.srtpMasterKeyIdentifier != "" {
- return false, errors.New("tls: server selected SRTP MKI value")
- }
-
- found := false
- for _, p := range c.config.SRTPProtectionProfiles {
- if p == hs.serverHello.srtpProtectionProfile {
- found = true
- break
- }
- }
- if !found {
- return false, errors.New("tls: server advertised unsupported SRTP profile")
- }
-
- c.srtpProtectionProfile = hs.serverHello.srtpProtectionProfile
- }
-
- if hs.serverResumedSession() {
- // For test purposes, assert that the server never accepts the
- // resumption offer on renegotiation.
- if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
- return false, errors.New("tls: server resumed session on renegotiation")
- }
-
- if hs.serverHello.sctList != nil {
- return false, errors.New("tls: server sent SCT extension on session resumption")
- }
-
- if hs.serverHello.ocspStapling {
- return false, errors.New("tls: server sent OCSP extension on session resumption")
- }
-
- // Restore masterSecret and peerCerts from previous state
- hs.masterSecret = hs.session.masterSecret
- c.peerCertificates = hs.session.serverCertificates
- c.extendedMasterSecret = hs.session.extendedMasterSecret
- c.sctList = hs.session.sctList
- c.ocspResponse = hs.session.ocspResponse
- hs.finishedHash.discardHandshakeBuffer()
- return true, nil
- }
-
- if hs.serverHello.sctList != nil {
- c.sctList = hs.serverHello.sctList
- }
-
- return false, nil
-}
-
-func (hs *clientHandshakeState) readFinished(out []byte) error {
- c := hs.c
-
- c.readRecord(recordTypeChangeCipherSpec)
- if err := c.in.error(); err != nil {
- return err
- }
-
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
- serverFinished, ok := msg.(*finishedMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(serverFinished, msg)
- }
-
- if c.config.Bugs.EarlyChangeCipherSpec == 0 {
- verify := hs.finishedHash.serverSum(hs.masterSecret)
- if len(verify) != len(serverFinished.verifyData) ||
- subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
- c.sendAlert(alertHandshakeFailure)
- return errors.New("tls: server's Finished message was incorrect")
- }
- }
- c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
- copy(out, serverFinished.verifyData)
- hs.writeServerHash(serverFinished.marshal())
- return nil
-}
-
-func (hs *clientHandshakeState) readSessionTicket() error {
- c := hs.c
-
- // Create a session with no server identifier. Either a
- // session ID or session ticket will be attached.
- session := &ClientSessionState{
- vers: c.vers,
- cipherSuite: hs.suite.id,
- masterSecret: hs.masterSecret,
- handshakeHash: hs.finishedHash.server.Sum(nil),
- serverCertificates: c.peerCertificates,
- sctList: c.sctList,
- ocspResponse: c.ocspResponse,
- }
-
- if !hs.serverHello.ticketSupported {
- if c.config.Bugs.ExpectNewTicket {
- return errors.New("tls: expected new ticket")
- }
- if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
- session.sessionId = hs.serverHello.sessionId
- hs.session = session
- }
- return nil
- }
-
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
- sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(sessionTicketMsg, msg)
- }
-
- session.sessionTicket = sessionTicketMsg.ticket
- hs.session = session
-
- hs.writeServerHash(sessionTicketMsg.marshal())
-
- return nil
-}
-
-func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
- c := hs.c
-
- var postCCSBytes []byte
- seqno := hs.c.sendHandshakeSeq
- if hs.serverHello.nextProtoNeg {
- nextProto := new(nextProtoMsg)
- proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
- nextProto.proto = proto
- c.clientProtocol = proto
- c.clientProtocolFallback = fallback
-
- nextProtoBytes := nextProto.marshal()
- hs.writeHash(nextProtoBytes, seqno)
- seqno++
- postCCSBytes = append(postCCSBytes, nextProtoBytes...)
- }
-
- if hs.serverHello.channelIDRequested {
- encryptedExtensions := new(encryptedExtensionsMsg)
- if c.config.ChannelID.Curve != elliptic.P256() {
- return fmt.Errorf("tls: Channel ID is not on P-256.")
- }
- var resumeHash []byte
- if isResume {
- resumeHash = hs.session.handshakeHash
- }
- r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
- if err != nil {
- return err
- }
- channelID := make([]byte, 128)
- writeIntPadded(channelID[0:32], c.config.ChannelID.X)
- writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
- writeIntPadded(channelID[64:96], r)
- writeIntPadded(channelID[96:128], s)
- encryptedExtensions.channelID = channelID
-
- c.channelID = &c.config.ChannelID.PublicKey
-
- encryptedExtensionsBytes := encryptedExtensions.marshal()
- hs.writeHash(encryptedExtensionsBytes, seqno)
- seqno++
- postCCSBytes = append(postCCSBytes, encryptedExtensionsBytes...)
- }
-
- finished := new(finishedMsg)
- if c.config.Bugs.EarlyChangeCipherSpec == 2 {
- finished.verifyData = hs.finishedHash.clientSum(nil)
- } else {
- finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
- }
- copy(out, finished.verifyData)
- if c.config.Bugs.BadFinished {
- finished.verifyData[0]++
- }
- c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
- hs.finishedBytes = finished.marshal()
- hs.writeHash(hs.finishedBytes, seqno)
- postCCSBytes = append(postCCSBytes, hs.finishedBytes...)
-
- if c.config.Bugs.FragmentAcrossChangeCipherSpec {
- c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
- postCCSBytes = postCCSBytes[5:]
- }
- c.dtlsFlushHandshake()
-
- if !c.config.Bugs.SkipChangeCipherSpec &&
- c.config.Bugs.EarlyChangeCipherSpec == 0 {
- c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
- }
-
- if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
- c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
- }
- if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
- c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
- return errors.New("tls: simulating post-CCS alert")
- }
-
- if !c.config.Bugs.SkipFinished {
- c.writeRecord(recordTypeHandshake, postCCSBytes)
- c.dtlsFlushHandshake()
- }
- return nil
-}
-
-func (hs *clientHandshakeState) writeClientHash(msg []byte) {
- // writeClientHash is called before writeRecord.
- hs.writeHash(msg, hs.c.sendHandshakeSeq)
-}
-
-func (hs *clientHandshakeState) writeServerHash(msg []byte) {
- // writeServerHash is called after readHandshake.
- hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
-}
-
-func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
- if hs.c.isDTLS {
- // This is somewhat hacky. DTLS hashes a slightly different format.
- // First, the TLS header.
- hs.finishedHash.Write(msg[:4])
- // Then the sequence number and reassembled fragment offset (always 0).
- hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
- // Then the reassembled fragment (always equal to the message length).
- hs.finishedHash.Write(msg[1:4])
- // And then the message body.
- hs.finishedHash.Write(msg[4:])
- } else {
- hs.finishedHash.Write(msg)
- }
-}
-
-// clientSessionCacheKey returns a key used to cache sessionTickets that could
-// be used to resume previously negotiated TLS sessions with a server.
-func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
- if len(config.ServerName) > 0 {
- return config.ServerName
- }
- return serverAddr.String()
-}
-
-// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
-// given list of possible protocols and a list of the preference order. The
-// first list must not be empty. It returns the resulting protocol and flag
-// indicating if the fallback case was reached.
-func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
- for _, s := range preferenceProtos {
- for _, c := range protos {
- if s == c {
- return s, false
- }
- }
- }
-
- return protos[0], true
-}
-
-// writeIntPadded writes x into b, padded up with leading zeros as
-// needed.
-func writeIntPadded(b []byte, x *big.Int) {
- for i := range b {
- b[i] = 0
- }
- xb := x.Bytes()
- copy(b[len(b)-len(xb):], xb)
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/handshake_messages.go b/third_party/boringssl/src/ssl/test/runner/handshake_messages.go
deleted file mode 100644
index 530ddbcfb6..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/handshake_messages.go
+++ /dev/null
@@ -1,1759 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import "bytes"
-
-type clientHelloMsg struct {
- raw []byte
- isDTLS bool
- vers uint16
- random []byte
- sessionId []byte
- cookie []byte
- cipherSuites []uint16
- compressionMethods []uint8
- nextProtoNeg bool
- serverName string
- ocspStapling bool
- supportedCurves []CurveID
- supportedPoints []uint8
- ticketSupported bool
- sessionTicket []uint8
- signatureAndHashes []signatureAndHash
- secureRenegotiation []byte
- alpnProtocols []string
- duplicateExtension bool
- channelIDSupported bool
- npnLast bool
- extendedMasterSecret bool
- srtpProtectionProfiles []uint16
- srtpMasterKeyIdentifier string
- sctListSupported bool
- customExtension string
-}
-
-func (m *clientHelloMsg) equal(i interface{}) bool {
- m1, ok := i.(*clientHelloMsg)
- if !ok {
- return false
- }
-
- return bytes.Equal(m.raw, m1.raw) &&
- m.isDTLS == m1.isDTLS &&
- m.vers == m1.vers &&
- bytes.Equal(m.random, m1.random) &&
- bytes.Equal(m.sessionId, m1.sessionId) &&
- bytes.Equal(m.cookie, m1.cookie) &&
- eqUint16s(m.cipherSuites, m1.cipherSuites) &&
- bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
- m.nextProtoNeg == m1.nextProtoNeg &&
- m.serverName == m1.serverName &&
- m.ocspStapling == m1.ocspStapling &&
- eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
- bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
- m.ticketSupported == m1.ticketSupported &&
- bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
- eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
- bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
- (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
- eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
- m.duplicateExtension == m1.duplicateExtension &&
- m.channelIDSupported == m1.channelIDSupported &&
- m.npnLast == m1.npnLast &&
- m.extendedMasterSecret == m1.extendedMasterSecret &&
- eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
- m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
- m.sctListSupported == m1.sctListSupported &&
- m.customExtension == m1.customExtension
-}
-
-func (m *clientHelloMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
-
- length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods)
- if m.isDTLS {
- length += 1 + len(m.cookie)
- }
- numExtensions := 0
- extensionsLength := 0
- if m.nextProtoNeg {
- numExtensions++
- }
- if m.ocspStapling {
- extensionsLength += 1 + 2 + 2
- numExtensions++
- }
- if len(m.serverName) > 0 {
- extensionsLength += 5 + len(m.serverName)
- numExtensions++
- }
- if len(m.supportedCurves) > 0 {
- extensionsLength += 2 + 2*len(m.supportedCurves)
- numExtensions++
- }
- if len(m.supportedPoints) > 0 {
- extensionsLength += 1 + len(m.supportedPoints)
- numExtensions++
- }
- if m.ticketSupported {
- extensionsLength += len(m.sessionTicket)
- numExtensions++
- }
- if len(m.signatureAndHashes) > 0 {
- extensionsLength += 2 + 2*len(m.signatureAndHashes)
- numExtensions++
- }
- if m.secureRenegotiation != nil {
- extensionsLength += 1 + len(m.secureRenegotiation)
- numExtensions++
- }
- if m.duplicateExtension {
- numExtensions += 2
- }
- if m.channelIDSupported {
- numExtensions++
- }
- if len(m.alpnProtocols) > 0 {
- extensionsLength += 2
- for _, s := range m.alpnProtocols {
- if l := len(s); l > 255 {
- panic("invalid ALPN protocol")
- }
- extensionsLength++
- extensionsLength += len(s)
- }
- numExtensions++
- }
- if m.extendedMasterSecret {
- numExtensions++
- }
- if len(m.srtpProtectionProfiles) > 0 {
- extensionsLength += 2 + 2*len(m.srtpProtectionProfiles)
- extensionsLength += 1 + len(m.srtpMasterKeyIdentifier)
- numExtensions++
- }
- if m.sctListSupported {
- numExtensions++
- }
- if l := len(m.customExtension); l > 0 {
- extensionsLength += l
- numExtensions++
- }
- if numExtensions > 0 {
- extensionsLength += 4 * numExtensions
- length += 2 + extensionsLength
- }
-
- x := make([]byte, 4+length)
- x[0] = typeClientHello
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
- vers := versionToWire(m.vers, m.isDTLS)
- x[4] = uint8(vers >> 8)
- x[5] = uint8(vers)
- copy(x[6:38], m.random)
- x[38] = uint8(len(m.sessionId))
- copy(x[39:39+len(m.sessionId)], m.sessionId)
- y := x[39+len(m.sessionId):]
- if m.isDTLS {
- y[0] = uint8(len(m.cookie))
- copy(y[1:], m.cookie)
- y = y[1+len(m.cookie):]
- }
- y[0] = uint8(len(m.cipherSuites) >> 7)
- y[1] = uint8(len(m.cipherSuites) << 1)
- for i, suite := range m.cipherSuites {
- y[2+i*2] = uint8(suite >> 8)
- y[3+i*2] = uint8(suite)
- }
- z := y[2+len(m.cipherSuites)*2:]
- z[0] = uint8(len(m.compressionMethods))
- copy(z[1:], m.compressionMethods)
-
- z = z[1+len(m.compressionMethods):]
- if numExtensions > 0 {
- z[0] = byte(extensionsLength >> 8)
- z[1] = byte(extensionsLength)
- z = z[2:]
- }
- if m.duplicateExtension {
- // Add a duplicate bogus extension at the beginning and end.
- z[0] = 0xff
- z[1] = 0xff
- z = z[4:]
- }
- if m.nextProtoNeg && !m.npnLast {
- z[0] = byte(extensionNextProtoNeg >> 8)
- z[1] = byte(extensionNextProtoNeg & 0xff)
- // The length is always 0
- z = z[4:]
- }
- if len(m.serverName) > 0 {
- z[0] = byte(extensionServerName >> 8)
- z[1] = byte(extensionServerName & 0xff)
- l := len(m.serverName) + 5
- z[2] = byte(l >> 8)
- z[3] = byte(l)
- z = z[4:]
-
- // RFC 3546, section 3.1
- //
- // struct {
- // NameType name_type;
- // select (name_type) {
- // case host_name: HostName;
- // } name;
- // } ServerName;
- //
- // enum {
- // host_name(0), (255)
- // } NameType;
- //
- // opaque HostName<1..2^16-1>;
- //
- // struct {
- // ServerName server_name_list<1..2^16-1>
- // } ServerNameList;
-
- z[0] = byte((len(m.serverName) + 3) >> 8)
- z[1] = byte(len(m.serverName) + 3)
- z[3] = byte(len(m.serverName) >> 8)
- z[4] = byte(len(m.serverName))
- copy(z[5:], []byte(m.serverName))
- z = z[l:]
- }
- if m.ocspStapling {
- // RFC 4366, section 3.6
- z[0] = byte(extensionStatusRequest >> 8)
- z[1] = byte(extensionStatusRequest)
- z[2] = 0
- z[3] = 5
- z[4] = 1 // OCSP type
- // Two zero valued uint16s for the two lengths.
- z = z[9:]
- }
- if len(m.supportedCurves) > 0 {
- // http://tools.ietf.org/html/rfc4492#section-5.5.1
- z[0] = byte(extensionSupportedCurves >> 8)
- z[1] = byte(extensionSupportedCurves)
- l := 2 + 2*len(m.supportedCurves)
- z[2] = byte(l >> 8)
- z[3] = byte(l)
- l -= 2
- z[4] = byte(l >> 8)
- z[5] = byte(l)
- z = z[6:]
- for _, curve := range m.supportedCurves {
- z[0] = byte(curve >> 8)
- z[1] = byte(curve)
- z = z[2:]
- }
- }
- if len(m.supportedPoints) > 0 {
- // http://tools.ietf.org/html/rfc4492#section-5.5.2
- z[0] = byte(extensionSupportedPoints >> 8)
- z[1] = byte(extensionSupportedPoints)
- l := 1 + len(m.supportedPoints)
- z[2] = byte(l >> 8)
- z[3] = byte(l)
- l--
- z[4] = byte(l)
- z = z[5:]
- for _, pointFormat := range m.supportedPoints {
- z[0] = byte(pointFormat)
- z = z[1:]
- }
- }
- if m.ticketSupported {
- // http://tools.ietf.org/html/rfc5077#section-3.2
- z[0] = byte(extensionSessionTicket >> 8)
- z[1] = byte(extensionSessionTicket)
- l := len(m.sessionTicket)
- z[2] = byte(l >> 8)
- z[3] = byte(l)
- z = z[4:]
- copy(z, m.sessionTicket)
- z = z[len(m.sessionTicket):]
- }
- if len(m.signatureAndHashes) > 0 {
- // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
- z[0] = byte(extensionSignatureAlgorithms >> 8)
- z[1] = byte(extensionSignatureAlgorithms)
- l := 2 + 2*len(m.signatureAndHashes)
- z[2] = byte(l >> 8)
- z[3] = byte(l)
- z = z[4:]
-
- l -= 2
- z[0] = byte(l >> 8)
- z[1] = byte(l)
- z = z[2:]
- for _, sigAndHash := range m.signatureAndHashes {
- z[0] = sigAndHash.hash
- z[1] = sigAndHash.signature
- z = z[2:]
- }
- }
- if m.secureRenegotiation != nil {
- z[0] = byte(extensionRenegotiationInfo >> 8)
- z[1] = byte(extensionRenegotiationInfo & 0xff)
- z[2] = 0
- z[3] = byte(1 + len(m.secureRenegotiation))
- z[4] = byte(len(m.secureRenegotiation))
- z = z[5:]
- copy(z, m.secureRenegotiation)
- z = z[len(m.secureRenegotiation):]
- }
- if len(m.alpnProtocols) > 0 {
- z[0] = byte(extensionALPN >> 8)
- z[1] = byte(extensionALPN & 0xff)
- lengths := z[2:]
- z = z[6:]
-
- stringsLength := 0
- for _, s := range m.alpnProtocols {
- l := len(s)
- z[0] = byte(l)
- copy(z[1:], s)
- z = z[1+l:]
- stringsLength += 1 + l
- }
-
- lengths[2] = byte(stringsLength >> 8)
- lengths[3] = byte(stringsLength)
- stringsLength += 2
- lengths[0] = byte(stringsLength >> 8)
- lengths[1] = byte(stringsLength)
- }
- if m.channelIDSupported {
- z[0] = byte(extensionChannelID >> 8)
- z[1] = byte(extensionChannelID & 0xff)
- z = z[4:]
- }
- if m.nextProtoNeg && m.npnLast {
- z[0] = byte(extensionNextProtoNeg >> 8)
- z[1] = byte(extensionNextProtoNeg & 0xff)
- // The length is always 0
- z = z[4:]
- }
- if m.duplicateExtension {
- // Add a duplicate bogus extension at the beginning and end.
- z[0] = 0xff
- z[1] = 0xff
- z = z[4:]
- }
- if m.extendedMasterSecret {
- // https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
- z[0] = byte(extensionExtendedMasterSecret >> 8)
- z[1] = byte(extensionExtendedMasterSecret & 0xff)
- z = z[4:]
- }
- if len(m.srtpProtectionProfiles) > 0 {
- z[0] = byte(extensionUseSRTP >> 8)
- z[1] = byte(extensionUseSRTP & 0xff)
-
- profilesLen := 2 * len(m.srtpProtectionProfiles)
- mkiLen := len(m.srtpMasterKeyIdentifier)
- l := 2 + profilesLen + 1 + mkiLen
- z[2] = byte(l >> 8)
- z[3] = byte(l & 0xff)
-
- z[4] = byte(profilesLen >> 8)
- z[5] = byte(profilesLen & 0xff)
- z = z[6:]
- for _, p := range m.srtpProtectionProfiles {
- z[0] = byte(p >> 8)
- z[1] = byte(p & 0xff)
- z = z[2:]
- }
-
- z[0] = byte(mkiLen)
- copy(z[1:], []byte(m.srtpMasterKeyIdentifier))
- z = z[1+mkiLen:]
- }
- if m.sctListSupported {
- z[0] = byte(extensionSignedCertificateTimestamp >> 8)
- z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
- z = z[4:]
- }
- if l := len(m.customExtension); l > 0 {
- z[0] = byte(extensionCustom >> 8)
- z[1] = byte(extensionCustom & 0xff)
- z[2] = byte(l >> 8)
- z[3] = byte(l & 0xff)
- copy(z[4:], []byte(m.customExtension))
- z = z[4+l:]
- }
-
- m.raw = x
-
- return x
-}
-
-func (m *clientHelloMsg) unmarshal(data []byte) bool {
- if len(data) < 42 {
- return false
- }
- m.raw = data
- m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
- m.random = data[6:38]
- sessionIdLen := int(data[38])
- if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
- return false
- }
- m.sessionId = data[39 : 39+sessionIdLen]
- data = data[39+sessionIdLen:]
- if m.isDTLS {
- if len(data) < 1 {
- return false
- }
- cookieLen := int(data[0])
- if cookieLen > 32 || len(data) < 1+cookieLen {
- return false
- }
- m.cookie = data[1 : 1+cookieLen]
- data = data[1+cookieLen:]
- }
- if len(data) < 2 {
- return false
- }
- // cipherSuiteLen is the number of bytes of cipher suite numbers. Since
- // they are uint16s, the number must be even.
- cipherSuiteLen := int(data[0])<<8 | int(data[1])
- if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
- return false
- }
- numCipherSuites := cipherSuiteLen / 2
- m.cipherSuites = make([]uint16, numCipherSuites)
- for i := 0; i < numCipherSuites; i++ {
- m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
- if m.cipherSuites[i] == scsvRenegotiation {
- m.secureRenegotiation = []byte{}
- }
- }
- data = data[2+cipherSuiteLen:]
- if len(data) < 1 {
- return false
- }
- compressionMethodsLen := int(data[0])
- if len(data) < 1+compressionMethodsLen {
- return false
- }
- m.compressionMethods = data[1 : 1+compressionMethodsLen]
-
- data = data[1+compressionMethodsLen:]
-
- m.nextProtoNeg = false
- m.serverName = ""
- m.ocspStapling = false
- m.ticketSupported = false
- m.sessionTicket = nil
- m.signatureAndHashes = nil
- m.alpnProtocols = nil
- m.extendedMasterSecret = false
- m.customExtension = ""
-
- if len(data) == 0 {
- // ClientHello is optionally followed by extension data
- return true
- }
- if len(data) < 2 {
- return false
- }
-
- extensionsLength := int(data[0])<<8 | int(data[1])
- data = data[2:]
- if extensionsLength != len(data) {
- return false
- }
-
- for len(data) != 0 {
- if len(data) < 4 {
- return false
- }
- extension := uint16(data[0])<<8 | uint16(data[1])
- length := int(data[2])<<8 | int(data[3])
- data = data[4:]
- if len(data) < length {
- return false
- }
-
- switch extension {
- case extensionServerName:
- if length < 2 {
- return false
- }
- numNames := int(data[0])<<8 | int(data[1])
- d := data[2:]
- for i := 0; i < numNames; i++ {
- if len(d) < 3 {
- return false
- }
- nameType := d[0]
- nameLen := int(d[1])<<8 | int(d[2])
- d = d[3:]
- if len(d) < nameLen {
- return false
- }
- if nameType == 0 {
- m.serverName = string(d[0:nameLen])
- break
- }
- d = d[nameLen:]
- }
- case extensionNextProtoNeg:
- if length > 0 {
- return false
- }
- m.nextProtoNeg = true
- case extensionStatusRequest:
- m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
- case extensionSupportedCurves:
- // http://tools.ietf.org/html/rfc4492#section-5.5.1
- if length < 2 {
- return false
- }
- l := int(data[0])<<8 | int(data[1])
- if l%2 == 1 || length != l+2 {
- return false
- }
- numCurves := l / 2
- m.supportedCurves = make([]CurveID, numCurves)
- d := data[2:]
- for i := 0; i < numCurves; i++ {
- m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
- d = d[2:]
- }
- case extensionSupportedPoints:
- // http://tools.ietf.org/html/rfc4492#section-5.5.2
- if length < 1 {
- return false
- }
- l := int(data[0])
- if length != l+1 {
- return false
- }
- m.supportedPoints = make([]uint8, l)
- copy(m.supportedPoints, data[1:])
- case extensionSessionTicket:
- // http://tools.ietf.org/html/rfc5077#section-3.2
- m.ticketSupported = true
- m.sessionTicket = data[:length]
- case extensionSignatureAlgorithms:
- // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
- if length < 2 || length&1 != 0 {
- return false
- }
- l := int(data[0])<<8 | int(data[1])
- if l != length-2 {
- return false
- }
- n := l / 2
- d := data[2:]
- m.signatureAndHashes = make([]signatureAndHash, n)
- for i := range m.signatureAndHashes {
- m.signatureAndHashes[i].hash = d[0]
- m.signatureAndHashes[i].signature = d[1]
- d = d[2:]
- }
- case extensionRenegotiationInfo:
- if length < 1 || length != int(data[0])+1 {
- return false
- }
- m.secureRenegotiation = data[1:length]
- case extensionALPN:
- if length < 2 {
- return false
- }
- l := int(data[0])<<8 | int(data[1])
- if l != length-2 {
- return false
- }
- d := data[2:length]
- for len(d) != 0 {
- stringLen := int(d[0])
- d = d[1:]
- if stringLen == 0 || stringLen > len(d) {
- return false
- }
- m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
- d = d[stringLen:]
- }
- case extensionChannelID:
- if length > 0 {
- return false
- }
- m.channelIDSupported = true
- case extensionExtendedMasterSecret:
- if length != 0 {
- return false
- }
- m.extendedMasterSecret = true
- case extensionUseSRTP:
- if length < 2 {
- return false
- }
- l := int(data[0])<<8 | int(data[1])
- if l > length-2 || l%2 != 0 {
- return false
- }
- n := l / 2
- m.srtpProtectionProfiles = make([]uint16, n)
- d := data[2:length]
- for i := 0; i < n; i++ {
- m.srtpProtectionProfiles[i] = uint16(d[0])<<8 | uint16(d[1])
- d = d[2:]
- }
- if len(d) < 1 || int(d[0]) != len(d)-1 {
- return false
- }
- m.srtpMasterKeyIdentifier = string(d[1:])
- case extensionSignedCertificateTimestamp:
- if length != 0 {
- return false
- }
- m.sctListSupported = true
- case extensionCustom:
- m.customExtension = string(data[:length])
- }
- data = data[length:]
- }
-
- return true
-}
-
-type serverHelloMsg struct {
- raw []byte
- isDTLS bool
- vers uint16
- random []byte
- sessionId []byte
- cipherSuite uint16
- compressionMethod uint8
- nextProtoNeg bool
- nextProtos []string
- ocspStapling bool
- ticketSupported bool
- secureRenegotiation []byte
- alpnProtocol string
- alpnProtocolEmpty bool
- duplicateExtension bool
- channelIDRequested bool
- extendedMasterSecret bool
- srtpProtectionProfile uint16
- srtpMasterKeyIdentifier string
- sctList []byte
- customExtension string
- npnLast bool
-}
-
-func (m *serverHelloMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
-
- length := 38 + len(m.sessionId)
- numExtensions := 0
- extensionsLength := 0
-
- nextProtoLen := 0
- if m.nextProtoNeg {
- numExtensions++
- for _, v := range m.nextProtos {
- nextProtoLen += len(v)
- }
- nextProtoLen += len(m.nextProtos)
- extensionsLength += nextProtoLen
- }
- if m.ocspStapling {
- numExtensions++
- }
- if m.ticketSupported {
- numExtensions++
- }
- if m.secureRenegotiation != nil {
- extensionsLength += 1 + len(m.secureRenegotiation)
- numExtensions++
- }
- if m.duplicateExtension {
- numExtensions += 2
- }
- if m.channelIDRequested {
- numExtensions++
- }
- if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
- if alpnLen >= 256 {
- panic("invalid ALPN protocol")
- }
- extensionsLength += 2 + 1 + alpnLen
- numExtensions++
- }
- if m.extendedMasterSecret {
- numExtensions++
- }
- if m.srtpProtectionProfile != 0 {
- extensionsLength += 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
- numExtensions++
- }
- if m.sctList != nil {
- extensionsLength += len(m.sctList)
- numExtensions++
- }
- if l := len(m.customExtension); l > 0 {
- extensionsLength += l
- numExtensions++
- }
-
- if numExtensions > 0 {
- extensionsLength += 4 * numExtensions
- length += 2 + extensionsLength
- }
-
- x := make([]byte, 4+length)
- x[0] = typeServerHello
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
- vers := versionToWire(m.vers, m.isDTLS)
- x[4] = uint8(vers >> 8)
- x[5] = uint8(vers)
- copy(x[6:38], m.random)
- x[38] = uint8(len(m.sessionId))
- copy(x[39:39+len(m.sessionId)], m.sessionId)
- z := x[39+len(m.sessionId):]
- z[0] = uint8(m.cipherSuite >> 8)
- z[1] = uint8(m.cipherSuite)
- z[2] = uint8(m.compressionMethod)
-
- z = z[3:]
- if numExtensions > 0 {
- z[0] = byte(extensionsLength >> 8)
- z[1] = byte(extensionsLength)
- z = z[2:]
- }
- if m.duplicateExtension {
- // Add a duplicate bogus extension at the beginning and end.
- z[0] = 0xff
- z[1] = 0xff
- z = z[4:]
- }
- if m.nextProtoNeg && !m.npnLast {
- z[0] = byte(extensionNextProtoNeg >> 8)
- z[1] = byte(extensionNextProtoNeg & 0xff)
- z[2] = byte(nextProtoLen >> 8)
- z[3] = byte(nextProtoLen)
- z = z[4:]
-
- for _, v := range m.nextProtos {
- l := len(v)
- if l > 255 {
- l = 255
- }
- z[0] = byte(l)
- copy(z[1:], []byte(v[0:l]))
- z = z[1+l:]
- }
- }
- if m.ocspStapling {
- z[0] = byte(extensionStatusRequest >> 8)
- z[1] = byte(extensionStatusRequest)
- z = z[4:]
- }
- if m.ticketSupported {
- z[0] = byte(extensionSessionTicket >> 8)
- z[1] = byte(extensionSessionTicket)
- z = z[4:]
- }
- if m.secureRenegotiation != nil {
- z[0] = byte(extensionRenegotiationInfo >> 8)
- z[1] = byte(extensionRenegotiationInfo & 0xff)
- z[2] = 0
- z[3] = byte(1 + len(m.secureRenegotiation))
- z[4] = byte(len(m.secureRenegotiation))
- z = z[5:]
- copy(z, m.secureRenegotiation)
- z = z[len(m.secureRenegotiation):]
- }
- if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
- z[0] = byte(extensionALPN >> 8)
- z[1] = byte(extensionALPN & 0xff)
- l := 2 + 1 + alpnLen
- z[2] = byte(l >> 8)
- z[3] = byte(l)
- l -= 2
- z[4] = byte(l >> 8)
- z[5] = byte(l)
- l -= 1
- z[6] = byte(l)
- copy(z[7:], []byte(m.alpnProtocol))
- z = z[7+alpnLen:]
- }
- if m.channelIDRequested {
- z[0] = byte(extensionChannelID >> 8)
- z[1] = byte(extensionChannelID & 0xff)
- z = z[4:]
- }
- if m.duplicateExtension {
- // Add a duplicate bogus extension at the beginning and end.
- z[0] = 0xff
- z[1] = 0xff
- z = z[4:]
- }
- if m.extendedMasterSecret {
- z[0] = byte(extensionExtendedMasterSecret >> 8)
- z[1] = byte(extensionExtendedMasterSecret & 0xff)
- z = z[4:]
- }
- if m.srtpProtectionProfile != 0 {
- z[0] = byte(extensionUseSRTP >> 8)
- z[1] = byte(extensionUseSRTP & 0xff)
- l := 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
- z[2] = byte(l >> 8)
- z[3] = byte(l & 0xff)
- z[4] = 0
- z[5] = 2
- z[6] = byte(m.srtpProtectionProfile >> 8)
- z[7] = byte(m.srtpProtectionProfile & 0xff)
- l = len(m.srtpMasterKeyIdentifier)
- z[8] = byte(l)
- copy(z[9:], []byte(m.srtpMasterKeyIdentifier))
- z = z[9+l:]
- }
- if m.sctList != nil {
- z[0] = byte(extensionSignedCertificateTimestamp >> 8)
- z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
- l := len(m.sctList)
- z[2] = byte(l >> 8)
- z[3] = byte(l & 0xff)
- copy(z[4:], m.sctList)
- z = z[4+l:]
- }
- if l := len(m.customExtension); l > 0 {
- z[0] = byte(extensionCustom >> 8)
- z[1] = byte(extensionCustom & 0xff)
- z[2] = byte(l >> 8)
- z[3] = byte(l & 0xff)
- copy(z[4:], []byte(m.customExtension))
- z = z[4+l:]
- }
- if m.nextProtoNeg && m.npnLast {
- z[0] = byte(extensionNextProtoNeg >> 8)
- z[1] = byte(extensionNextProtoNeg & 0xff)
- z[2] = byte(nextProtoLen >> 8)
- z[3] = byte(nextProtoLen)
- z = z[4:]
-
- for _, v := range m.nextProtos {
- l := len(v)
- if l > 255 {
- l = 255
- }
- z[0] = byte(l)
- copy(z[1:], []byte(v[0:l]))
- z = z[1+l:]
- }
- }
-
- m.raw = x
-
- return x
-}
-
-func (m *serverHelloMsg) unmarshal(data []byte) bool {
- if len(data) < 42 {
- return false
- }
- m.raw = data
- m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
- m.random = data[6:38]
- sessionIdLen := int(data[38])
- if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
- return false
- }
- m.sessionId = data[39 : 39+sessionIdLen]
- data = data[39+sessionIdLen:]
- if len(data) < 3 {
- return false
- }
- m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
- m.compressionMethod = data[2]
- data = data[3:]
-
- m.nextProtoNeg = false
- m.nextProtos = nil
- m.ocspStapling = false
- m.ticketSupported = false
- m.alpnProtocol = ""
- m.alpnProtocolEmpty = false
- m.extendedMasterSecret = false
- m.customExtension = ""
-
- if len(data) == 0 {
- // ServerHello is optionally followed by extension data
- return true
- }
- if len(data) < 2 {
- return false
- }
-
- extensionsLength := int(data[0])<<8 | int(data[1])
- data = data[2:]
- if len(data) != extensionsLength {
- return false
- }
-
- for len(data) != 0 {
- if len(data) < 4 {
- return false
- }
- extension := uint16(data[0])<<8 | uint16(data[1])
- length := int(data[2])<<8 | int(data[3])
- data = data[4:]
- if len(data) < length {
- return false
- }
-
- switch extension {
- case extensionNextProtoNeg:
- m.nextProtoNeg = true
- d := data[:length]
- for len(d) > 0 {
- l := int(d[0])
- d = d[1:]
- if l == 0 || l > len(d) {
- return false
- }
- m.nextProtos = append(m.nextProtos, string(d[:l]))
- d = d[l:]
- }
- case extensionStatusRequest:
- if length > 0 {
- return false
- }
- m.ocspStapling = true
- case extensionSessionTicket:
- if length > 0 {
- return false
- }
- m.ticketSupported = true
- case extensionRenegotiationInfo:
- if length < 1 || length != int(data[0])+1 {
- return false
- }
- m.secureRenegotiation = data[1:length]
- case extensionALPN:
- d := data[:length]
- if len(d) < 3 {
- return false
- }
- l := int(d[0])<<8 | int(d[1])
- if l != len(d)-2 {
- return false
- }
- d = d[2:]
- l = int(d[0])
- if l != len(d)-1 {
- return false
- }
- d = d[1:]
- m.alpnProtocol = string(d)
- m.alpnProtocolEmpty = len(d) == 0
- case extensionChannelID:
- if length > 0 {
- return false
- }
- m.channelIDRequested = true
- case extensionExtendedMasterSecret:
- if length != 0 {
- return false
- }
- m.extendedMasterSecret = true
- case extensionUseSRTP:
- if length < 2+2+1 {
- return false
- }
- if data[0] != 0 || data[1] != 2 {
- return false
- }
- m.srtpProtectionProfile = uint16(data[2])<<8 | uint16(data[3])
- d := data[4:length]
- l := int(d[0])
- if l != len(d)-1 {
- return false
- }
- m.srtpMasterKeyIdentifier = string(d[1:])
- case extensionSignedCertificateTimestamp:
- m.sctList = data[:length]
- case extensionCustom:
- m.customExtension = string(data[:length])
- }
- data = data[length:]
- }
-
- return true
-}
-
-type certificateMsg struct {
- raw []byte
- certificates [][]byte
-}
-
-func (m *certificateMsg) marshal() (x []byte) {
- if m.raw != nil {
- return m.raw
- }
-
- var i int
- for _, slice := range m.certificates {
- i += len(slice)
- }
-
- length := 3 + 3*len(m.certificates) + i
- x = make([]byte, 4+length)
- x[0] = typeCertificate
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
-
- certificateOctets := length - 3
- x[4] = uint8(certificateOctets >> 16)
- x[5] = uint8(certificateOctets >> 8)
- x[6] = uint8(certificateOctets)
-
- y := x[7:]
- for _, slice := range m.certificates {
- y[0] = uint8(len(slice) >> 16)
- y[1] = uint8(len(slice) >> 8)
- y[2] = uint8(len(slice))
- copy(y[3:], slice)
- y = y[3+len(slice):]
- }
-
- m.raw = x
- return
-}
-
-func (m *certificateMsg) unmarshal(data []byte) bool {
- if len(data) < 7 {
- return false
- }
-
- m.raw = data
- certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
- if uint32(len(data)) != certsLen+7 {
- return false
- }
-
- numCerts := 0
- d := data[7:]
- for certsLen > 0 {
- if len(d) < 4 {
- return false
- }
- certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
- if uint32(len(d)) < 3+certLen {
- return false
- }
- d = d[3+certLen:]
- certsLen -= 3 + certLen
- numCerts++
- }
-
- m.certificates = make([][]byte, numCerts)
- d = data[7:]
- for i := 0; i < numCerts; i++ {
- certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
- m.certificates[i] = d[3 : 3+certLen]
- d = d[3+certLen:]
- }
-
- return true
-}
-
-type serverKeyExchangeMsg struct {
- raw []byte
- key []byte
-}
-
-func (m *serverKeyExchangeMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
- length := len(m.key)
- x := make([]byte, length+4)
- x[0] = typeServerKeyExchange
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
- copy(x[4:], m.key)
-
- m.raw = x
- return x
-}
-
-func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
- m.raw = data
- if len(data) < 4 {
- return false
- }
- m.key = data[4:]
- return true
-}
-
-type certificateStatusMsg struct {
- raw []byte
- statusType uint8
- response []byte
-}
-
-func (m *certificateStatusMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
-
- var x []byte
- if m.statusType == statusTypeOCSP {
- x = make([]byte, 4+4+len(m.response))
- x[0] = typeCertificateStatus
- l := len(m.response) + 4
- x[1] = byte(l >> 16)
- x[2] = byte(l >> 8)
- x[3] = byte(l)
- x[4] = statusTypeOCSP
-
- l -= 4
- x[5] = byte(l >> 16)
- x[6] = byte(l >> 8)
- x[7] = byte(l)
- copy(x[8:], m.response)
- } else {
- x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
- }
-
- m.raw = x
- return x
-}
-
-func (m *certificateStatusMsg) unmarshal(data []byte) bool {
- m.raw = data
- if len(data) < 5 {
- return false
- }
- m.statusType = data[4]
-
- m.response = nil
- if m.statusType == statusTypeOCSP {
- if len(data) < 8 {
- return false
- }
- respLen := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
- if uint32(len(data)) != 4+4+respLen {
- return false
- }
- m.response = data[8:]
- }
- return true
-}
-
-type serverHelloDoneMsg struct{}
-
-func (m *serverHelloDoneMsg) marshal() []byte {
- x := make([]byte, 4)
- x[0] = typeServerHelloDone
- return x
-}
-
-func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
- return len(data) == 4
-}
-
-type clientKeyExchangeMsg struct {
- raw []byte
- ciphertext []byte
-}
-
-func (m *clientKeyExchangeMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
- length := len(m.ciphertext)
- x := make([]byte, length+4)
- x[0] = typeClientKeyExchange
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
- copy(x[4:], m.ciphertext)
-
- m.raw = x
- return x
-}
-
-func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
- m.raw = data
- if len(data) < 4 {
- return false
- }
- l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
- if l != len(data)-4 {
- return false
- }
- m.ciphertext = data[4:]
- return true
-}
-
-type finishedMsg struct {
- raw []byte
- verifyData []byte
-}
-
-func (m *finishedMsg) marshal() (x []byte) {
- if m.raw != nil {
- return m.raw
- }
-
- x = make([]byte, 4+len(m.verifyData))
- x[0] = typeFinished
- x[3] = byte(len(m.verifyData))
- copy(x[4:], m.verifyData)
- m.raw = x
- return
-}
-
-func (m *finishedMsg) unmarshal(data []byte) bool {
- m.raw = data
- if len(data) < 4 {
- return false
- }
- m.verifyData = data[4:]
- return true
-}
-
-type nextProtoMsg struct {
- raw []byte
- proto string
-}
-
-func (m *nextProtoMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
- l := len(m.proto)
- if l > 255 {
- l = 255
- }
-
- padding := 32 - (l+2)%32
- length := l + padding + 2
- x := make([]byte, length+4)
- x[0] = typeNextProtocol
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
-
- y := x[4:]
- y[0] = byte(l)
- copy(y[1:], []byte(m.proto[0:l]))
- y = y[1+l:]
- y[0] = byte(padding)
-
- m.raw = x
-
- return x
-}
-
-func (m *nextProtoMsg) unmarshal(data []byte) bool {
- m.raw = data
-
- if len(data) < 5 {
- return false
- }
- data = data[4:]
- protoLen := int(data[0])
- data = data[1:]
- if len(data) < protoLen {
- return false
- }
- m.proto = string(data[0:protoLen])
- data = data[protoLen:]
-
- if len(data) < 1 {
- return false
- }
- paddingLen := int(data[0])
- data = data[1:]
- if len(data) != paddingLen {
- return false
- }
-
- return true
-}
-
-type certificateRequestMsg struct {
- raw []byte
- // hasSignatureAndHash indicates whether this message includes a list
- // of signature and hash functions. This change was introduced with TLS
- // 1.2.
- hasSignatureAndHash bool
-
- certificateTypes []byte
- signatureAndHashes []signatureAndHash
- certificateAuthorities [][]byte
-}
-
-func (m *certificateRequestMsg) marshal() (x []byte) {
- if m.raw != nil {
- return m.raw
- }
-
- // See http://tools.ietf.org/html/rfc4346#section-7.4.4
- length := 1 + len(m.certificateTypes) + 2
- casLength := 0
- for _, ca := range m.certificateAuthorities {
- casLength += 2 + len(ca)
- }
- length += casLength
-
- if m.hasSignatureAndHash {
- length += 2 + 2*len(m.signatureAndHashes)
- }
-
- x = make([]byte, 4+length)
- x[0] = typeCertificateRequest
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
-
- x[4] = uint8(len(m.certificateTypes))
-
- copy(x[5:], m.certificateTypes)
- y := x[5+len(m.certificateTypes):]
-
- if m.hasSignatureAndHash {
- n := len(m.signatureAndHashes) * 2
- y[0] = uint8(n >> 8)
- y[1] = uint8(n)
- y = y[2:]
- for _, sigAndHash := range m.signatureAndHashes {
- y[0] = sigAndHash.hash
- y[1] = sigAndHash.signature
- y = y[2:]
- }
- }
-
- y[0] = uint8(casLength >> 8)
- y[1] = uint8(casLength)
- y = y[2:]
- for _, ca := range m.certificateAuthorities {
- y[0] = uint8(len(ca) >> 8)
- y[1] = uint8(len(ca))
- y = y[2:]
- copy(y, ca)
- y = y[len(ca):]
- }
-
- m.raw = x
- return
-}
-
-func (m *certificateRequestMsg) unmarshal(data []byte) bool {
- m.raw = data
-
- if len(data) < 5 {
- return false
- }
-
- length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
- if uint32(len(data))-4 != length {
- return false
- }
-
- numCertTypes := int(data[4])
- data = data[5:]
- if numCertTypes == 0 || len(data) <= numCertTypes {
- return false
- }
-
- m.certificateTypes = make([]byte, numCertTypes)
- if copy(m.certificateTypes, data) != numCertTypes {
- return false
- }
-
- data = data[numCertTypes:]
-
- if m.hasSignatureAndHash {
- if len(data) < 2 {
- return false
- }
- sigAndHashLen := uint16(data[0])<<8 | uint16(data[1])
- data = data[2:]
- if sigAndHashLen&1 != 0 {
- return false
- }
- if len(data) < int(sigAndHashLen) {
- return false
- }
- numSigAndHash := sigAndHashLen / 2
- m.signatureAndHashes = make([]signatureAndHash, numSigAndHash)
- for i := range m.signatureAndHashes {
- m.signatureAndHashes[i].hash = data[0]
- m.signatureAndHashes[i].signature = 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
- }
-
- m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
- cas = cas[caLen:]
- }
- if len(data) > 0 {
- return false
- }
-
- return true
-}
-
-type certificateVerifyMsg struct {
- raw []byte
- hasSignatureAndHash bool
- signatureAndHash signatureAndHash
- signature []byte
-}
-
-func (m *certificateVerifyMsg) marshal() (x []byte) {
- if m.raw != nil {
- return m.raw
- }
-
- // See http://tools.ietf.org/html/rfc4346#section-7.4.8
- siglength := len(m.signature)
- length := 2 + siglength
- if m.hasSignatureAndHash {
- length += 2
- }
- x = make([]byte, 4+length)
- x[0] = typeCertificateVerify
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
- y := x[4:]
- if m.hasSignatureAndHash {
- y[0] = m.signatureAndHash.hash
- y[1] = m.signatureAndHash.signature
- y = y[2:]
- }
- y[0] = uint8(siglength >> 8)
- y[1] = uint8(siglength)
- copy(y[2:], m.signature)
-
- m.raw = x
-
- return
-}
-
-func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
- m.raw = data
-
- if len(data) < 6 {
- return false
- }
-
- length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
- if uint32(len(data))-4 != length {
- return false
- }
-
- data = data[4:]
- if m.hasSignatureAndHash {
- m.signatureAndHash.hash = data[0]
- m.signatureAndHash.signature = data[1]
- data = data[2:]
- }
-
- if len(data) < 2 {
- return false
- }
- siglength := int(data[0])<<8 + int(data[1])
- data = data[2:]
- if len(data) != siglength {
- return false
- }
-
- m.signature = data
-
- return true
-}
-
-type newSessionTicketMsg struct {
- raw []byte
- ticket []byte
-}
-
-func (m *newSessionTicketMsg) marshal() (x []byte) {
- if m.raw != nil {
- return m.raw
- }
-
- // See http://tools.ietf.org/html/rfc5077#section-3.3
- ticketLen := len(m.ticket)
- length := 2 + 4 + ticketLen
- x = make([]byte, 4+length)
- x[0] = typeNewSessionTicket
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
- x[8] = uint8(ticketLen >> 8)
- x[9] = uint8(ticketLen)
- copy(x[10:], m.ticket)
-
- m.raw = x
-
- return
-}
-
-func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
- m.raw = data
-
- if len(data) < 10 {
- return false
- }
-
- length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
- if uint32(len(data))-4 != length {
- return false
- }
-
- ticketLen := int(data[8])<<8 + int(data[9])
- if len(data)-10 != ticketLen {
- return false
- }
-
- m.ticket = data[10:]
-
- return true
-}
-
-type v2ClientHelloMsg struct {
- raw []byte
- vers uint16
- cipherSuites []uint16
- sessionId []byte
- challenge []byte
-}
-
-func (m *v2ClientHelloMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
-
- length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
-
- x := make([]byte, length)
- x[0] = 1
- x[1] = uint8(m.vers >> 8)
- x[2] = uint8(m.vers)
- x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
- x[4] = uint8(len(m.cipherSuites) * 3)
- x[5] = uint8(len(m.sessionId) >> 8)
- x[6] = uint8(len(m.sessionId))
- x[7] = uint8(len(m.challenge) >> 8)
- x[8] = uint8(len(m.challenge))
- y := x[9:]
- for i, spec := range m.cipherSuites {
- y[i*3] = 0
- y[i*3+1] = uint8(spec >> 8)
- y[i*3+2] = uint8(spec)
- }
- y = y[len(m.cipherSuites)*3:]
- copy(y, m.sessionId)
- y = y[len(m.sessionId):]
- copy(y, m.challenge)
-
- m.raw = x
-
- return x
-}
-
-type helloVerifyRequestMsg struct {
- raw []byte
- vers uint16
- cookie []byte
-}
-
-func (m *helloVerifyRequestMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
-
- length := 2 + 1 + len(m.cookie)
-
- x := make([]byte, 4+length)
- x[0] = typeHelloVerifyRequest
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
- vers := versionToWire(m.vers, true)
- x[4] = uint8(vers >> 8)
- x[5] = uint8(vers)
- x[6] = uint8(len(m.cookie))
- copy(x[7:7+len(m.cookie)], m.cookie)
-
- return x
-}
-
-func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
- if len(data) < 4+2+1 {
- return false
- }
- m.raw = data
- m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true)
- cookieLen := int(data[6])
- if cookieLen > 32 || len(data) != 7+cookieLen {
- return false
- }
- m.cookie = data[7 : 7+cookieLen]
-
- return true
-}
-
-type encryptedExtensionsMsg struct {
- raw []byte
- channelID []byte
-}
-
-func (m *encryptedExtensionsMsg) marshal() []byte {
- if m.raw != nil {
- return m.raw
- }
-
- length := 2 + 2 + len(m.channelID)
-
- x := make([]byte, 4+length)
- x[0] = typeEncryptedExtensions
- x[1] = uint8(length >> 16)
- x[2] = uint8(length >> 8)
- x[3] = uint8(length)
- x[4] = uint8(extensionChannelID >> 8)
- x[5] = uint8(extensionChannelID & 0xff)
- x[6] = uint8(len(m.channelID) >> 8)
- x[7] = uint8(len(m.channelID) & 0xff)
- copy(x[8:], m.channelID)
-
- return x
-}
-
-func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
- if len(data) != 4+2+2+128 {
- return false
- }
- m.raw = data
- if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
- return false
- }
- if int(data[6])<<8|int(data[7]) != 128 {
- return false
- }
- m.channelID = data[4+2+2:]
-
- return true
-}
-
-type helloRequestMsg struct {
-}
-
-func (*helloRequestMsg) marshal() []byte {
- return []byte{typeHelloRequest, 0, 0, 0}
-}
-
-func (*helloRequestMsg) unmarshal(data []byte) bool {
- return len(data) == 4
-}
-
-func eqUint16s(x, y []uint16) bool {
- if len(x) != len(y) {
- return false
- }
- for i, v := range x {
- if y[i] != v {
- return false
- }
- }
- return true
-}
-
-func eqCurveIDs(x, y []CurveID) bool {
- if len(x) != len(y) {
- return false
- }
- for i, v := range x {
- if y[i] != v {
- return false
- }
- }
- return true
-}
-
-func eqStrings(x, y []string) bool {
- if len(x) != len(y) {
- return false
- }
- for i, v := range x {
- if y[i] != v {
- return false
- }
- }
- return true
-}
-
-func eqByteSlices(x, y [][]byte) bool {
- if len(x) != len(y) {
- return false
- }
- for i, v := range x {
- if !bytes.Equal(v, y[i]) {
- return false
- }
- }
- return true
-}
-
-func eqSignatureAndHashes(x, y []signatureAndHash) bool {
- if len(x) != len(y) {
- return false
- }
- for i, v := range x {
- v2 := y[i]
- if v.hash != v2.hash || v.signature != v2.signature {
- return false
- }
- }
- return true
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/handshake_server.go b/third_party/boringssl/src/ssl/test/runner/handshake_server.go
deleted file mode 100644
index aa91723022..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/handshake_server.go
+++ /dev/null
@@ -1,1049 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import (
- "bytes"
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rsa"
- "crypto/subtle"
- "crypto/x509"
- "encoding/asn1"
- "errors"
- "fmt"
- "io"
- "math/big"
-)
-
-// serverHandshakeState contains details of a server handshake in progress.
-// It's discarded once the handshake has completed.
-type serverHandshakeState struct {
- c *Conn
- clientHello *clientHelloMsg
- hello *serverHelloMsg
- suite *cipherSuite
- ellipticOk bool
- ecdsaOk bool
- sessionState *sessionState
- finishedHash finishedHash
- masterSecret []byte
- certsFromClient [][]byte
- cert *Certificate
- finishedBytes []byte
-}
-
-// serverHandshake performs a TLS handshake as a server.
-func (c *Conn) serverHandshake() error {
- config := c.config
-
- // If this is the first server handshake, we generate a random key to
- // encrypt the tickets with.
- config.serverInitOnce.Do(config.serverInit)
-
- c.sendHandshakeSeq = 0
- c.recvHandshakeSeq = 0
-
- hs := serverHandshakeState{
- c: c,
- }
- isResume, err := hs.readClientHello()
- if err != nil {
- return err
- }
-
- // For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
- if isResume {
- // The client has included a session ticket and so we do an abbreviated handshake.
- if err := hs.doResumeHandshake(); err != nil {
- return err
- }
- if err := hs.establishKeys(); err != nil {
- return err
- }
- if c.config.Bugs.RenewTicketOnResume {
- if err := hs.sendSessionTicket(); err != nil {
- return err
- }
- }
- if err := hs.sendFinished(c.firstFinished[:]); err != nil {
- return err
- }
- // Most retransmits are triggered by a timeout, but the final
- // leg of the handshake is retransmited upon re-receiving a
- // Finished.
- if err := c.simulatePacketLoss(func() {
- c.writeRecord(recordTypeHandshake, hs.finishedBytes)
- c.dtlsFlushHandshake()
- }); err != nil {
- return err
- }
- if err := hs.readFinished(nil, isResume); err != nil {
- return err
- }
- c.didResume = true
- } else {
- // The client didn't include a session ticket, or it wasn't
- // valid so we do a full handshake.
- if err := hs.doFullHandshake(); err != nil {
- return err
- }
- if err := hs.establishKeys(); err != nil {
- return err
- }
- if err := hs.readFinished(c.firstFinished[:], isResume); err != nil {
- return err
- }
- if c.config.Bugs.AlertBeforeFalseStartTest != 0 {
- c.sendAlert(c.config.Bugs.AlertBeforeFalseStartTest)
- }
- if c.config.Bugs.ExpectFalseStart {
- if err := c.readRecord(recordTypeApplicationData); err != nil {
- return fmt.Errorf("tls: peer did not false start: %s", err)
- }
- }
- if err := hs.sendSessionTicket(); err != nil {
- return err
- }
- if err := hs.sendFinished(nil); err != nil {
- return err
- }
- }
- c.handshakeComplete = true
- copy(c.clientRandom[:], hs.clientHello.random)
- copy(c.serverRandom[:], hs.hello.random)
- copy(c.masterSecret[:], hs.masterSecret)
-
- return nil
-}
-
-// readClientHello reads a ClientHello message from the client and decides
-// whether we will perform session resumption.
-func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
- config := hs.c.config
- c := hs.c
-
- if err := c.simulatePacketLoss(nil); err != nil {
- return false, err
- }
- msg, err := c.readHandshake()
- if err != nil {
- return false, err
- }
- var ok bool
- hs.clientHello, ok = msg.(*clientHelloMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return false, unexpectedMessageError(hs.clientHello, msg)
- }
- if size := config.Bugs.RequireClientHelloSize; size != 0 && len(hs.clientHello.raw) != size {
- return false, fmt.Errorf("tls: ClientHello record size is %d, but expected %d", len(hs.clientHello.raw), size)
- }
-
- if c.isDTLS && !config.Bugs.SkipHelloVerifyRequest {
- // Per RFC 6347, the version field in HelloVerifyRequest SHOULD
- // be always DTLS 1.0
- helloVerifyRequest := &helloVerifyRequestMsg{
- vers: VersionTLS10,
- cookie: make([]byte, 32),
- }
- if _, err := io.ReadFull(c.config.rand(), helloVerifyRequest.cookie); err != nil {
- c.sendAlert(alertInternalError)
- return false, errors.New("dtls: short read from Rand: " + err.Error())
- }
- c.writeRecord(recordTypeHandshake, helloVerifyRequest.marshal())
- c.dtlsFlushHandshake()
-
- if err := c.simulatePacketLoss(nil); err != nil {
- return false, err
- }
- msg, err := c.readHandshake()
- if err != nil {
- return false, err
- }
- newClientHello, ok := msg.(*clientHelloMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return false, unexpectedMessageError(hs.clientHello, msg)
- }
- if !bytes.Equal(newClientHello.cookie, helloVerifyRequest.cookie) {
- return false, errors.New("dtls: invalid cookie")
- }
-
- // Apart from the cookie, the two ClientHellos must
- // match. Note that clientHello.equal compares the
- // serialization, so we make a copy.
- oldClientHelloCopy := *hs.clientHello
- oldClientHelloCopy.raw = nil
- oldClientHelloCopy.cookie = nil
- newClientHelloCopy := *newClientHello
- newClientHelloCopy.raw = nil
- newClientHelloCopy.cookie = nil
- if !oldClientHelloCopy.equal(&newClientHelloCopy) {
- return false, errors.New("dtls: retransmitted ClientHello does not match")
- }
- hs.clientHello = newClientHello
- }
-
- if config.Bugs.RequireSameRenegoClientVersion && c.clientVersion != 0 {
- if c.clientVersion != hs.clientHello.vers {
- return false, fmt.Errorf("tls: client offered different version on renego")
- }
- }
- c.clientVersion = hs.clientHello.vers
-
- // Reject < 1.2 ClientHellos with signature_algorithms.
- if c.clientVersion < VersionTLS12 && len(hs.clientHello.signatureAndHashes) > 0 {
- return false, fmt.Errorf("tls: client included signature_algorithms before TLS 1.2")
- }
- if config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
- hs.clientHello.signatureAndHashes = config.signatureAndHashesForServer()
- }
-
- c.vers, ok = config.mutualVersion(hs.clientHello.vers)
- if !ok {
- c.sendAlert(alertProtocolVersion)
- return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
- }
- c.haveVers = true
-
- hs.hello = &serverHelloMsg{
- isDTLS: c.isDTLS,
- customExtension: config.Bugs.CustomExtension,
- npnLast: config.Bugs.SwapNPNAndALPN,
- }
-
- supportedCurve := false
- preferredCurves := config.curvePreferences()
- if config.Bugs.IgnorePeerCurvePreferences {
- hs.clientHello.supportedCurves = preferredCurves
- }
-Curves:
- for _, curve := range hs.clientHello.supportedCurves {
- for _, supported := range preferredCurves {
- if supported == curve {
- supportedCurve = true
- break Curves
- }
- }
- }
-
- supportedPointFormat := false
- for _, pointFormat := range hs.clientHello.supportedPoints {
- if pointFormat == pointFormatUncompressed {
- supportedPointFormat = true
- break
- }
- }
- hs.ellipticOk = supportedCurve && supportedPointFormat
-
- foundCompression := false
- // We only support null compression, so check that the client offered it.
- for _, compression := range hs.clientHello.compressionMethods {
- if compression == compressionNone {
- foundCompression = true
- break
- }
- }
-
- if !foundCompression {
- c.sendAlert(alertHandshakeFailure)
- return false, errors.New("tls: client does not support uncompressed connections")
- }
-
- hs.hello.vers = c.vers
- hs.hello.random = make([]byte, 32)
- _, err = io.ReadFull(config.rand(), hs.hello.random)
- if err != nil {
- c.sendAlert(alertInternalError)
- return false, err
- }
-
- if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
- c.sendAlert(alertHandshakeFailure)
- return false, errors.New("tls: renegotiation mismatch")
- }
-
- if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
- hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.clientVerify...)
- hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.serverVerify...)
- if c.config.Bugs.BadRenegotiationInfo {
- hs.hello.secureRenegotiation[0] ^= 0x80
- }
- } else {
- hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
- }
-
- if c.config.Bugs.NoRenegotiationInfo {
- hs.hello.secureRenegotiation = nil
- }
-
- hs.hello.compressionMethod = compressionNone
- hs.hello.duplicateExtension = c.config.Bugs.DuplicateExtension
- if len(hs.clientHello.serverName) > 0 {
- c.serverName = hs.clientHello.serverName
- }
-
- if len(hs.clientHello.alpnProtocols) > 0 {
- if proto := c.config.Bugs.ALPNProtocol; proto != nil {
- hs.hello.alpnProtocol = *proto
- hs.hello.alpnProtocolEmpty = len(*proto) == 0
- c.clientProtocol = *proto
- c.usedALPN = true
- } else if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
- hs.hello.alpnProtocol = selectedProto
- c.clientProtocol = selectedProto
- c.usedALPN = true
- }
- }
- if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN {
- // Although sending an empty NPN extension is reasonable, Firefox has
- // had a bug around this. Best to send nothing at all if
- // config.NextProtos is empty. See
- // https://code.google.com/p/go/issues/detail?id=5445.
- if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
- hs.hello.nextProtoNeg = true
- hs.hello.nextProtos = config.NextProtos
- }
- }
- hs.hello.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret
-
- if len(config.Certificates) == 0 {
- c.sendAlert(alertInternalError)
- return false, errors.New("tls: no certificates configured")
- }
- hs.cert = &config.Certificates[0]
- if len(hs.clientHello.serverName) > 0 {
- hs.cert = config.getCertificateForName(hs.clientHello.serverName)
- }
- if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
- return false, errors.New("tls: unexpected server name")
- }
-
- if hs.clientHello.channelIDSupported && config.RequestChannelID {
- hs.hello.channelIDRequested = true
- }
-
- if hs.clientHello.srtpProtectionProfiles != nil {
- SRTPLoop:
- for _, p1 := range c.config.SRTPProtectionProfiles {
- for _, p2 := range hs.clientHello.srtpProtectionProfiles {
- if p1 == p2 {
- hs.hello.srtpProtectionProfile = p1
- c.srtpProtectionProfile = p1
- break SRTPLoop
- }
- }
- }
- }
-
- if c.config.Bugs.SendSRTPProtectionProfile != 0 {
- hs.hello.srtpProtectionProfile = c.config.Bugs.SendSRTPProtectionProfile
- }
-
- if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
- if hs.clientHello.customExtension != *expected {
- return false, fmt.Errorf("tls: bad custom extension contents %q", hs.clientHello.customExtension)
- }
- }
-
- _, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
-
- // For test purposes, check that the peer never offers a session when
- // renegotiating.
- if c.cipherSuite != nil && len(hs.clientHello.sessionId) > 0 && c.config.Bugs.FailIfResumeOnRenego {
- return false, errors.New("tls: offered resumption on renegotiation")
- }
-
- if hs.checkForResumption() {
- return true, nil
- }
-
- var scsvFound bool
-
- for _, cipherSuite := range hs.clientHello.cipherSuites {
- if cipherSuite == fallbackSCSV {
- scsvFound = true
- break
- }
- }
-
- if !scsvFound && config.Bugs.FailIfNotFallbackSCSV {
- return false, errors.New("tls: no fallback SCSV found when expected")
- } else if scsvFound && !config.Bugs.FailIfNotFallbackSCSV {
- return false, errors.New("tls: fallback SCSV found when not expected")
- }
-
- if config.Bugs.IgnorePeerCipherPreferences {
- hs.clientHello.cipherSuites = c.config.cipherSuites()
- }
- var preferenceList, supportedList []uint16
- if c.config.PreferServerCipherSuites {
- preferenceList = c.config.cipherSuites()
- supportedList = hs.clientHello.cipherSuites
- } else {
- preferenceList = hs.clientHello.cipherSuites
- supportedList = c.config.cipherSuites()
- }
-
- for _, id := range preferenceList {
- if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk); hs.suite != nil {
- break
- }
- }
-
- if hs.suite == nil {
- c.sendAlert(alertHandshakeFailure)
- return false, errors.New("tls: no cipher suite supported by both client and server")
- }
-
- return false, nil
-}
-
-// checkForResumption returns true if we should perform resumption on this connection.
-func (hs *serverHandshakeState) checkForResumption() bool {
- c := hs.c
-
- if len(hs.clientHello.sessionTicket) > 0 {
- if c.config.SessionTicketsDisabled {
- return false
- }
-
- var ok bool
- if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
- return false
- }
- } else {
- if c.config.ServerSessionCache == nil {
- return false
- }
-
- var ok bool
- sessionId := string(hs.clientHello.sessionId)
- if hs.sessionState, ok = c.config.ServerSessionCache.Get(sessionId); !ok {
- return false
- }
- }
-
- // Never resume a session for a different SSL version.
- if !c.config.Bugs.AllowSessionVersionMismatch && c.vers != hs.sessionState.vers {
- return false
- }
-
- cipherSuiteOk := false
- // Check that the client is still offering the ciphersuite in the session.
- for _, id := range hs.clientHello.cipherSuites {
- if id == hs.sessionState.cipherSuite {
- cipherSuiteOk = true
- break
- }
- }
- if !cipherSuiteOk {
- return false
- }
-
- // Check that we also support the ciphersuite from the session.
- hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk)
- if hs.suite == nil {
- return false
- }
-
- sessionHasClientCerts := len(hs.sessionState.certificates) != 0
- needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
- if needClientCerts && !sessionHasClientCerts {
- return false
- }
- if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
- return false
- }
-
- return true
-}
-
-func (hs *serverHandshakeState) doResumeHandshake() error {
- c := hs.c
-
- hs.hello.cipherSuite = hs.suite.id
- if c.config.Bugs.SendCipherSuite != 0 {
- hs.hello.cipherSuite = c.config.Bugs.SendCipherSuite
- }
- // We echo the client's session ID in the ServerHello to let it know
- // that we're doing a resumption.
- hs.hello.sessionId = hs.clientHello.sessionId
- hs.hello.ticketSupported = c.config.Bugs.RenewTicketOnResume
-
- hs.finishedHash = newFinishedHash(c.vers, hs.suite)
- hs.finishedHash.discardHandshakeBuffer()
- hs.writeClientHash(hs.clientHello.marshal())
- hs.writeServerHash(hs.hello.marshal())
-
- c.writeRecord(recordTypeHandshake, hs.hello.marshal())
-
- if len(hs.sessionState.certificates) > 0 {
- if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
- return err
- }
- }
-
- hs.masterSecret = hs.sessionState.masterSecret
- c.extendedMasterSecret = hs.sessionState.extendedMasterSecret
-
- return nil
-}
-
-func (hs *serverHandshakeState) doFullHandshake() error {
- config := hs.c.config
- c := hs.c
-
- isPSK := hs.suite.flags&suitePSK != 0
- if !isPSK && hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
- hs.hello.ocspStapling = true
- }
-
- if hs.clientHello.sctListSupported && len(hs.cert.SignedCertificateTimestampList) > 0 {
- hs.hello.sctList = hs.cert.SignedCertificateTimestampList
- }
-
- hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled && c.vers > VersionSSL30
- hs.hello.cipherSuite = hs.suite.id
- if config.Bugs.SendCipherSuite != 0 {
- hs.hello.cipherSuite = config.Bugs.SendCipherSuite
- }
- c.extendedMasterSecret = hs.hello.extendedMasterSecret
-
- // Generate a session ID if we're to save the session.
- if !hs.hello.ticketSupported && config.ServerSessionCache != nil {
- hs.hello.sessionId = make([]byte, 32)
- if _, err := io.ReadFull(config.rand(), hs.hello.sessionId); err != nil {
- c.sendAlert(alertInternalError)
- return errors.New("tls: short read from Rand: " + err.Error())
- }
- }
-
- hs.finishedHash = newFinishedHash(c.vers, hs.suite)
- hs.writeClientHash(hs.clientHello.marshal())
- hs.writeServerHash(hs.hello.marshal())
-
- c.writeRecord(recordTypeHandshake, hs.hello.marshal())
-
- if !isPSK {
- certMsg := new(certificateMsg)
- if !config.Bugs.EmptyCertificateList {
- certMsg.certificates = hs.cert.Certificate
- }
- if !config.Bugs.UnauthenticatedECDH {
- certMsgBytes := certMsg.marshal()
- if config.Bugs.WrongCertificateMessageType {
- certMsgBytes[0] += 42
- }
- hs.writeServerHash(certMsgBytes)
- c.writeRecord(recordTypeHandshake, certMsgBytes)
- }
- }
-
- if hs.hello.ocspStapling && !c.config.Bugs.SkipCertificateStatus {
- certStatus := new(certificateStatusMsg)
- certStatus.statusType = statusTypeOCSP
- certStatus.response = hs.cert.OCSPStaple
- hs.writeServerHash(certStatus.marshal())
- c.writeRecord(recordTypeHandshake, certStatus.marshal())
- }
-
- keyAgreement := hs.suite.ka(c.vers)
- skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
- if err != nil {
- c.sendAlert(alertHandshakeFailure)
- return err
- }
- if skx != nil && !config.Bugs.SkipServerKeyExchange {
- hs.writeServerHash(skx.marshal())
- c.writeRecord(recordTypeHandshake, skx.marshal())
- }
-
- if config.ClientAuth >= RequestClientCert {
- // Request a client certificate
- certReq := &certificateRequestMsg{
- certificateTypes: config.ClientCertificateTypes,
- }
- if certReq.certificateTypes == nil {
- certReq.certificateTypes = []byte{
- byte(CertTypeRSASign),
- byte(CertTypeECDSASign),
- }
- }
- if c.vers >= VersionTLS12 {
- certReq.hasSignatureAndHash = true
- if !config.Bugs.NoSignatureAndHashes {
- certReq.signatureAndHashes = config.signatureAndHashesForServer()
- }
- }
-
- // An empty list of certificateAuthorities signals to
- // the client that it may send any certificate in response
- // to our request. When we know the CAs we trust, then
- // we can send them down, so that the client can choose
- // an appropriate certificate to give to us.
- if config.ClientCAs != nil {
- certReq.certificateAuthorities = config.ClientCAs.Subjects()
- }
- hs.writeServerHash(certReq.marshal())
- c.writeRecord(recordTypeHandshake, certReq.marshal())
- }
-
- helloDone := new(serverHelloDoneMsg)
- hs.writeServerHash(helloDone.marshal())
- c.writeRecord(recordTypeHandshake, helloDone.marshal())
- c.dtlsFlushHandshake()
-
- var pub crypto.PublicKey // public key for client auth, if any
-
- if err := c.simulatePacketLoss(nil); err != nil {
- return err
- }
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
-
- var ok bool
- // If we requested a client certificate, then the client must send a
- // certificate message, even if it's empty.
- if config.ClientAuth >= RequestClientCert {
- var certMsg *certificateMsg
- if certMsg, ok = msg.(*certificateMsg); !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(certMsg, msg)
- }
- hs.writeClientHash(certMsg.marshal())
-
- if len(certMsg.certificates) == 0 {
- // The client didn't actually send a certificate
- switch config.ClientAuth {
- case RequireAnyClientCert, RequireAndVerifyClientCert:
- c.sendAlert(alertBadCertificate)
- return errors.New("tls: client didn't provide a certificate")
- }
- }
-
- pub, err = hs.processCertsFromClient(certMsg.certificates)
- if err != nil {
- return err
- }
-
- msg, err = c.readHandshake()
- if err != nil {
- return err
- }
- }
-
- // Get client key exchange
- ckx, ok := msg.(*clientKeyExchangeMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(ckx, msg)
- }
- hs.writeClientHash(ckx.marshal())
-
- preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
- if err != nil {
- c.sendAlert(alertHandshakeFailure)
- return err
- }
- if c.extendedMasterSecret {
- hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
- } else {
- if c.config.Bugs.RequireExtendedMasterSecret {
- return errors.New("tls: extended master secret required but not supported by peer")
- }
- hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
- }
-
- // If we received a client cert in response to our certificate request message,
- // the client will send us a certificateVerifyMsg immediately after the
- // clientKeyExchangeMsg. This message is a digest of all preceding
- // handshake-layer messages that is signed using the private key corresponding
- // to the client's certificate. This allows us to verify that the client is in
- // possession of the private key of the certificate.
- if len(c.peerCertificates) > 0 {
- msg, err = c.readHandshake()
- if err != nil {
- return err
- }
- certVerify, ok := msg.(*certificateVerifyMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(certVerify, msg)
- }
-
- // Determine the signature type.
- var signatureAndHash signatureAndHash
- if certVerify.hasSignatureAndHash {
- signatureAndHash = certVerify.signatureAndHash
- if !isSupportedSignatureAndHash(signatureAndHash, config.signatureAndHashesForServer()) {
- return errors.New("tls: unsupported hash function for client certificate")
- }
- c.clientCertSignatureHash = signatureAndHash.hash
- } else {
- // Before TLS 1.2 the signature algorithm was implicit
- // from the key type, and only one hash per signature
- // algorithm was possible. Leave the hash as zero.
- switch pub.(type) {
- case *ecdsa.PublicKey:
- signatureAndHash.signature = signatureECDSA
- case *rsa.PublicKey:
- signatureAndHash.signature = signatureRSA
- }
- }
-
- switch key := pub.(type) {
- case *ecdsa.PublicKey:
- if signatureAndHash.signature != signatureECDSA {
- err = errors.New("tls: bad signature type for client's ECDSA certificate")
- break
- }
- ecdsaSig := new(ecdsaSignature)
- if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
- break
- }
- if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
- err = errors.New("ECDSA signature contained zero or negative values")
- break
- }
- var digest []byte
- digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
- if err != nil {
- break
- }
- if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
- err = errors.New("ECDSA verification failure")
- break
- }
- case *rsa.PublicKey:
- if signatureAndHash.signature != signatureRSA {
- err = errors.New("tls: bad signature type for client's RSA certificate")
- break
- }
- var digest []byte
- var hashFunc crypto.Hash
- digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
- if err != nil {
- break
- }
- err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
- }
- if err != nil {
- c.sendAlert(alertBadCertificate)
- return errors.New("could not validate signature of connection nonces: " + err.Error())
- }
-
- hs.writeClientHash(certVerify.marshal())
- }
-
- hs.finishedHash.discardHandshakeBuffer()
-
- return nil
-}
-
-func (hs *serverHandshakeState) establishKeys() error {
- c := hs.c
-
- clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
-
- var clientCipher, serverCipher interface{}
- var clientHash, serverHash macFunction
-
- if hs.suite.aead == nil {
- clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
- clientHash = hs.suite.mac(c.vers, clientMAC)
- serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
- serverHash = hs.suite.mac(c.vers, serverMAC)
- } else {
- clientCipher = hs.suite.aead(clientKey, clientIV)
- serverCipher = hs.suite.aead(serverKey, serverIV)
- }
-
- c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
- c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
-
- return nil
-}
-
-func (hs *serverHandshakeState) readFinished(out []byte, isResume bool) error {
- c := hs.c
-
- c.readRecord(recordTypeChangeCipherSpec)
- if err := c.in.error(); err != nil {
- return err
- }
-
- if hs.hello.nextProtoNeg {
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
- nextProto, ok := msg.(*nextProtoMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(nextProto, msg)
- }
- hs.writeClientHash(nextProto.marshal())
- c.clientProtocol = nextProto.proto
- }
-
- if hs.hello.channelIDRequested {
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
- encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(encryptedExtensions, msg)
- }
- x := new(big.Int).SetBytes(encryptedExtensions.channelID[0:32])
- y := new(big.Int).SetBytes(encryptedExtensions.channelID[32:64])
- r := new(big.Int).SetBytes(encryptedExtensions.channelID[64:96])
- s := new(big.Int).SetBytes(encryptedExtensions.channelID[96:128])
- if !elliptic.P256().IsOnCurve(x, y) {
- return errors.New("tls: invalid channel ID public key")
- }
- channelID := &ecdsa.PublicKey{elliptic.P256(), x, y}
- var resumeHash []byte
- if isResume {
- resumeHash = hs.sessionState.handshakeHash
- }
- if !ecdsa.Verify(channelID, hs.finishedHash.hashForChannelID(resumeHash), r, s) {
- return errors.New("tls: invalid channel ID signature")
- }
- c.channelID = channelID
-
- hs.writeClientHash(encryptedExtensions.marshal())
- }
-
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
- clientFinished, ok := msg.(*finishedMsg)
- if !ok {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(clientFinished, msg)
- }
-
- verify := hs.finishedHash.clientSum(hs.masterSecret)
- if len(verify) != len(clientFinished.verifyData) ||
- subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
- c.sendAlert(alertHandshakeFailure)
- return errors.New("tls: client's Finished message is incorrect")
- }
- c.clientVerify = append(c.clientVerify[:0], clientFinished.verifyData...)
- copy(out, clientFinished.verifyData)
-
- hs.writeClientHash(clientFinished.marshal())
- return nil
-}
-
-func (hs *serverHandshakeState) sendSessionTicket() error {
- c := hs.c
- state := sessionState{
- vers: c.vers,
- cipherSuite: hs.suite.id,
- masterSecret: hs.masterSecret,
- certificates: hs.certsFromClient,
- handshakeHash: hs.finishedHash.server.Sum(nil),
- }
-
- if !hs.hello.ticketSupported || hs.c.config.Bugs.SkipNewSessionTicket {
- if c.config.ServerSessionCache != nil && len(hs.hello.sessionId) != 0 {
- c.config.ServerSessionCache.Put(string(hs.hello.sessionId), &state)
- }
- return nil
- }
-
- m := new(newSessionTicketMsg)
-
- var err error
- m.ticket, err = c.encryptTicket(&state)
- if err != nil {
- return err
- }
-
- hs.writeServerHash(m.marshal())
- c.writeRecord(recordTypeHandshake, m.marshal())
-
- return nil
-}
-
-func (hs *serverHandshakeState) sendFinished(out []byte) error {
- c := hs.c
-
- finished := new(finishedMsg)
- finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
- copy(out, finished.verifyData)
- if c.config.Bugs.BadFinished {
- finished.verifyData[0]++
- }
- c.serverVerify = append(c.serverVerify[:0], finished.verifyData...)
- hs.finishedBytes = finished.marshal()
- hs.writeServerHash(hs.finishedBytes)
- postCCSBytes := hs.finishedBytes
-
- if c.config.Bugs.FragmentAcrossChangeCipherSpec {
- c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
- postCCSBytes = postCCSBytes[5:]
- }
- c.dtlsFlushHandshake()
-
- if !c.config.Bugs.SkipChangeCipherSpec {
- c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
- }
-
- if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
- c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
- }
- if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
- c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
- return errors.New("tls: simulating post-CCS alert")
- }
-
- if !c.config.Bugs.SkipFinished {
- c.writeRecord(recordTypeHandshake, postCCSBytes)
- c.dtlsFlushHandshake()
- }
-
- c.cipherSuite = hs.suite
-
- return nil
-}
-
-// processCertsFromClient takes a chain of client certificates either from a
-// Certificates message or from a sessionState and verifies them. It returns
-// the public key of the leaf certificate.
-func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
- c := hs.c
-
- hs.certsFromClient = certificates
- certs := make([]*x509.Certificate, len(certificates))
- var err error
- for i, asn1Data := range certificates {
- if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
- c.sendAlert(alertBadCertificate)
- return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
- }
- }
-
- if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
- opts := x509.VerifyOptions{
- Roots: c.config.ClientCAs,
- CurrentTime: c.config.time(),
- Intermediates: x509.NewCertPool(),
- KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
- }
-
- for _, cert := range certs[1:] {
- opts.Intermediates.AddCert(cert)
- }
-
- chains, err := certs[0].Verify(opts)
- if err != nil {
- c.sendAlert(alertBadCertificate)
- return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
- }
-
- ok := false
- for _, ku := range certs[0].ExtKeyUsage {
- if ku == x509.ExtKeyUsageClientAuth {
- ok = true
- break
- }
- }
- if !ok {
- c.sendAlert(alertHandshakeFailure)
- return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
- }
-
- c.verifiedChains = chains
- }
-
- if len(certs) > 0 {
- var pub crypto.PublicKey
- switch key := certs[0].PublicKey.(type) {
- case *ecdsa.PublicKey, *rsa.PublicKey:
- pub = key
- default:
- c.sendAlert(alertUnsupportedCertificate)
- return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
- }
- c.peerCertificates = certs
- return pub, nil
- }
-
- return nil, nil
-}
-
-func (hs *serverHandshakeState) writeServerHash(msg []byte) {
- // writeServerHash is called before writeRecord.
- hs.writeHash(msg, hs.c.sendHandshakeSeq)
-}
-
-func (hs *serverHandshakeState) writeClientHash(msg []byte) {
- // writeClientHash is called after readHandshake.
- hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
-}
-
-func (hs *serverHandshakeState) writeHash(msg []byte, seqno uint16) {
- if hs.c.isDTLS {
- // This is somewhat hacky. DTLS hashes a slightly different format.
- // First, the TLS header.
- hs.finishedHash.Write(msg[:4])
- // Then the sequence number and reassembled fragment offset (always 0).
- hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
- // Then the reassembled fragment (always equal to the message length).
- hs.finishedHash.Write(msg[1:4])
- // And then the message body.
- hs.finishedHash.Write(msg[4:])
- } else {
- hs.finishedHash.Write(msg)
- }
-}
-
-// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
-// is acceptable to use.
-func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16, ellipticOk, ecdsaOk bool) *cipherSuite {
- for _, supported := range supportedCipherSuites {
- if id == supported {
- var candidate *cipherSuite
-
- for _, s := range cipherSuites {
- if s.id == id {
- candidate = s
- break
- }
- }
- if candidate == nil {
- continue
- }
- // Don't select a ciphersuite which we can't
- // support for this client.
- if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
- continue
- }
- if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
- continue
- }
- if !c.config.Bugs.SkipCipherVersionCheck && version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
- continue
- }
- if c.isDTLS && candidate.flags&suiteNoDTLS != 0 {
- continue
- }
- return candidate
- }
- }
-
- return nil
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/key.pem b/third_party/boringssl/src/ssl/test/runner/key.pem
deleted file mode 100644
index e9107bfee9..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/key.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92
-kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF
-KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB
-AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe
-i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+
-WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ
-m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj
-QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk
-aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj
-LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk
-104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/
-tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd
-moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==
------END RSA PRIVATE KEY-----
diff --git a/third_party/boringssl/src/ssl/test/runner/key_agreement.go b/third_party/boringssl/src/ssl/test/runner/key_agreement.go
deleted file mode 100644
index 3a9b899748..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/key_agreement.go
+++ /dev/null
@@ -1,842 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import (
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/md5"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha1"
- "crypto/x509"
- "encoding/asn1"
- "errors"
- "io"
- "math/big"
-)
-
-var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
-var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
-
-// rsaKeyAgreement implements the standard TLS key agreement where the client
-// encrypts the pre-master secret to the server's public key.
-type rsaKeyAgreement struct {
- version uint16
- clientVersion uint16
- exportKey *rsa.PrivateKey
-}
-
-func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- // Save the client version for comparison later.
- ka.clientVersion = versionToWire(clientHello.vers, clientHello.isDTLS)
-
- if !config.Bugs.RSAEphemeralKey {
- return nil, nil
- }
-
- // Generate an ephemeral RSA key to use instead of the real
- // one, as in RSA_EXPORT.
- key, err := rsa.GenerateKey(config.rand(), 512)
- if err != nil {
- return nil, err
- }
- ka.exportKey = key
-
- modulus := key.N.Bytes()
- exponent := big.NewInt(int64(key.E)).Bytes()
- serverRSAParams := make([]byte, 0, 2+len(modulus)+2+len(exponent))
- serverRSAParams = append(serverRSAParams, byte(len(modulus)>>8), byte(len(modulus)))
- serverRSAParams = append(serverRSAParams, modulus...)
- serverRSAParams = append(serverRSAParams, byte(len(exponent)>>8), byte(len(exponent)))
- serverRSAParams = append(serverRSAParams, exponent...)
-
- var tls12HashId uint8
- if ka.version >= VersionTLS12 {
- if tls12HashId, err = pickTLS12HashForSignature(signatureRSA, clientHello.signatureAndHashes, config.signatureAndHashesForServer()); err != nil {
- return nil, err
- }
- }
-
- digest, hashFunc, err := hashForServerKeyExchange(signatureRSA, tls12HashId, ka.version, clientHello.random, hello.random, serverRSAParams)
- if err != nil {
- return nil, err
- }
- privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
- if !ok {
- return nil, errors.New("RSA ephemeral key requires an RSA server private key")
- }
- sig, err := rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
- if err != nil {
- return nil, errors.New("failed to sign RSA parameters: " + err.Error())
- }
-
- skx := new(serverKeyExchangeMsg)
- sigAndHashLen := 0
- if ka.version >= VersionTLS12 {
- sigAndHashLen = 2
- }
- skx.key = make([]byte, len(serverRSAParams)+sigAndHashLen+2+len(sig))
- copy(skx.key, serverRSAParams)
- k := skx.key[len(serverRSAParams):]
- if ka.version >= VersionTLS12 {
- k[0] = tls12HashId
- k[1] = signatureRSA
- k = k[2:]
- }
- k[0] = byte(len(sig) >> 8)
- k[1] = byte(len(sig))
- copy(k[2:], sig)
-
- return skx, nil
-}
-
-func (ka *rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
- preMasterSecret := make([]byte, 48)
- _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
- if err != nil {
- return nil, err
- }
-
- if len(ckx.ciphertext) < 2 {
- return nil, errClientKeyExchange
- }
-
- ciphertext := ckx.ciphertext
- if version != VersionSSL30 {
- ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
- if ciphertextLen != len(ckx.ciphertext)-2 {
- return nil, errClientKeyExchange
- }
- ciphertext = ckx.ciphertext[2:]
- }
-
- key := cert.PrivateKey.(*rsa.PrivateKey)
- if ka.exportKey != nil {
- key = ka.exportKey
- }
- err = rsa.DecryptPKCS1v15SessionKey(config.rand(), key, ciphertext, preMasterSecret)
- if err != nil {
- return nil, err
- }
- // This check should be done in constant-time, but this is a testing
- // implementation. See the discussion at the end of section 7.4.7.1 of
- // RFC 4346.
- vers := uint16(preMasterSecret[0])<<8 | uint16(preMasterSecret[1])
- if ka.clientVersion != vers {
- return nil, errors.New("tls: invalid version in RSA premaster")
- }
- return preMasterSecret, nil
-}
-
-func (ka *rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
- return errors.New("tls: unexpected ServerKeyExchange")
-}
-
-func (ka *rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
- preMasterSecret := make([]byte, 48)
- vers := clientHello.vers
- if config.Bugs.RsaClientKeyExchangeVersion != 0 {
- vers = config.Bugs.RsaClientKeyExchangeVersion
- }
- vers = versionToWire(vers, clientHello.isDTLS)
- preMasterSecret[0] = byte(vers >> 8)
- preMasterSecret[1] = byte(vers)
- _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
- if err != nil {
- return nil, nil, err
- }
-
- encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
- if err != nil {
- return nil, nil, err
- }
- ckx := new(clientKeyExchangeMsg)
- if clientHello.vers != VersionSSL30 && !config.Bugs.SSL3RSAKeyExchange {
- ckx.ciphertext = make([]byte, len(encrypted)+2)
- ckx.ciphertext[0] = byte(len(encrypted) >> 8)
- ckx.ciphertext[1] = byte(len(encrypted))
- copy(ckx.ciphertext[2:], encrypted)
- } else {
- ckx.ciphertext = encrypted
- }
- return preMasterSecret, ckx, nil
-}
-
-// sha1Hash calculates a SHA1 hash over the given byte slices.
-func sha1Hash(slices [][]byte) []byte {
- hsha1 := sha1.New()
- for _, slice := range slices {
- hsha1.Write(slice)
- }
- return hsha1.Sum(nil)
-}
-
-// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
-// concatenation of an MD5 and SHA1 hash.
-func md5SHA1Hash(slices [][]byte) []byte {
- md5sha1 := make([]byte, md5.Size+sha1.Size)
- hmd5 := md5.New()
- for _, slice := range slices {
- hmd5.Write(slice)
- }
- copy(md5sha1, hmd5.Sum(nil))
- copy(md5sha1[md5.Size:], sha1Hash(slices))
- return md5sha1
-}
-
-// hashForServerKeyExchange hashes the given slices and returns their digest
-// and the identifier of the hash function used. The hashFunc argument is only
-// used for >= TLS 1.2 and precisely identifies the hash function to use.
-func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
- if version >= VersionTLS12 {
- hash, err := lookupTLSHash(hashFunc)
- if err != nil {
- return nil, 0, err
- }
- h := hash.New()
- for _, slice := range slices {
- h.Write(slice)
- }
- return h.Sum(nil), hash, nil
- }
- if sigType == signatureECDSA {
- return sha1Hash(slices), crypto.SHA1, nil
- }
- return md5SHA1Hash(slices), crypto.MD5SHA1, nil
-}
-
-// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
-// ServerKeyExchange given the signature type being used and the client's
-// advertized list of supported signature and hash combinations.
-func pickTLS12HashForSignature(sigType uint8, clientList, serverList []signatureAndHash) (uint8, error) {
- if len(clientList) == 0 {
- // If the client didn't specify any signature_algorithms
- // extension then we can assume that it supports SHA1. See
- // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
- return hashSHA1, nil
- }
-
- for _, sigAndHash := range clientList {
- if sigAndHash.signature != sigType {
- continue
- }
- if isSupportedSignatureAndHash(sigAndHash, serverList) {
- return sigAndHash.hash, nil
- }
- }
-
- return 0, errors.New("tls: client doesn't support any common hash functions")
-}
-
-func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
- switch id {
- case CurveP224:
- return elliptic.P224(), true
- case CurveP256:
- return elliptic.P256(), true
- case CurveP384:
- return elliptic.P384(), true
- case CurveP521:
- return elliptic.P521(), true
- default:
- return nil, false
- }
-
-}
-
-// keyAgreementAuthentication is a helper interface that specifies how
-// to authenticate the ServerKeyExchange parameters.
-type keyAgreementAuthentication interface {
- signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error)
- verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error
-}
-
-// nilKeyAgreementAuthentication does not authenticate the key
-// agreement parameters.
-type nilKeyAgreementAuthentication struct{}
-
-func (ka *nilKeyAgreementAuthentication) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
- skx := new(serverKeyExchangeMsg)
- skx.key = params
- return skx, nil
-}
-
-func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
- return nil
-}
-
-// signedKeyAgreement signs the ServerKeyExchange parameters with the
-// server's private key.
-type signedKeyAgreement struct {
- version uint16
- sigType uint8
-}
-
-func (ka *signedKeyAgreement) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
- var tls12HashId uint8
- var err error
- if ka.version >= VersionTLS12 {
- if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes, config.signatureAndHashesForServer()); err != nil {
- return nil, err
- }
- }
-
- digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, params)
- if err != nil {
- return nil, err
- }
-
- if config.Bugs.InvalidSKXSignature {
- digest[0] ^= 0x80
- }
-
- var sig []byte
- switch ka.sigType {
- case signatureECDSA:
- privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
- if !ok {
- return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key")
- }
- r, s, err := ecdsa.Sign(config.rand(), privKey, digest)
- if err != nil {
- return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
- }
- order := privKey.Curve.Params().N
- r = maybeCorruptECDSAValue(r, config.Bugs.BadECDSAR, order)
- s = maybeCorruptECDSAValue(s, config.Bugs.BadECDSAS, order)
- sig, err = asn1.Marshal(ecdsaSignature{r, s})
- case signatureRSA:
- privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
- if !ok {
- return nil, errors.New("ECDHE RSA requires a RSA server private key")
- }
- sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
- if err != nil {
- return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
- }
- default:
- return nil, errors.New("unknown ECDHE signature algorithm")
- }
-
- skx := new(serverKeyExchangeMsg)
- if config.Bugs.UnauthenticatedECDH {
- skx.key = params
- } else {
- sigAndHashLen := 0
- if ka.version >= VersionTLS12 {
- sigAndHashLen = 2
- }
- skx.key = make([]byte, len(params)+sigAndHashLen+2+len(sig))
- copy(skx.key, params)
- k := skx.key[len(params):]
- if ka.version >= VersionTLS12 {
- k[0] = tls12HashId
- k[1] = ka.sigType
- k = k[2:]
- }
- k[0] = byte(len(sig) >> 8)
- k[1] = byte(len(sig))
- copy(k[2:], sig)
- }
-
- return skx, nil
-}
-
-func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
- if len(sig) < 2 {
- return errServerKeyExchange
- }
-
- var tls12HashId uint8
- if ka.version >= VersionTLS12 {
- // handle SignatureAndHashAlgorithm
- var sigAndHash []uint8
- sigAndHash, sig = sig[:2], sig[2:]
- if sigAndHash[1] != ka.sigType {
- return errServerKeyExchange
- }
- tls12HashId = sigAndHash[0]
- if len(sig) < 2 {
- return errServerKeyExchange
- }
-
- if !isSupportedSignatureAndHash(signatureAndHash{ka.sigType, tls12HashId}, config.signatureAndHashesForClient()) {
- return errors.New("tls: unsupported hash function for ServerKeyExchange")
- }
- }
- sigLen := int(sig[0])<<8 | int(sig[1])
- if sigLen+2 != len(sig) {
- return errServerKeyExchange
- }
- sig = sig[2:]
-
- digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, params)
- if err != nil {
- return err
- }
- switch ka.sigType {
- case signatureECDSA:
- pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
- if !ok {
- return errors.New("ECDHE ECDSA requires a ECDSA server public key")
- }
- ecdsaSig := new(ecdsaSignature)
- if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
- return err
- }
- if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
- return errors.New("ECDSA signature contained zero or negative values")
- }
- if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
- return errors.New("ECDSA verification failure")
- }
- case signatureRSA:
- pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
- if !ok {
- return errors.New("ECDHE RSA requires a RSA server public key")
- }
- if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
- return err
- }
- default:
- return errors.New("unknown ECDHE signature algorithm")
- }
-
- return nil
-}
-
-// ecdheRSAKeyAgreement implements a TLS key agreement where the server
-// generates a ephemeral EC public/private key pair and signs it. The
-// pre-master secret is then calculated using ECDH. The signature may
-// either be ECDSA or RSA.
-type ecdheKeyAgreement struct {
- auth keyAgreementAuthentication
- privateKey []byte
- curve elliptic.Curve
- x, y *big.Int
-}
-
-func maybeCorruptECDSAValue(n *big.Int, typeOfCorruption BadValue, limit *big.Int) *big.Int {
- switch typeOfCorruption {
- case BadValueNone:
- return n
- case BadValueNegative:
- return new(big.Int).Neg(n)
- case BadValueZero:
- return big.NewInt(0)
- case BadValueLimit:
- return limit
- case BadValueLarge:
- bad := new(big.Int).Set(limit)
- return bad.Lsh(bad, 20)
- default:
- panic("unknown BadValue type")
- }
-}
-
-func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- var curveid CurveID
- preferredCurves := config.curvePreferences()
-
-NextCandidate:
- for _, candidate := range preferredCurves {
- for _, c := range clientHello.supportedCurves {
- if candidate == c {
- curveid = c
- break NextCandidate
- }
- }
- }
-
- if curveid == 0 {
- return nil, errors.New("tls: no supported elliptic curves offered")
- }
-
- var ok bool
- if ka.curve, ok = curveForCurveID(curveid); !ok {
- return nil, errors.New("tls: preferredCurves includes unsupported curve")
- }
-
- var x, y *big.Int
- var err error
- ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
- if err != nil {
- return nil, err
- }
- ecdhePublic := elliptic.Marshal(ka.curve, x, y)
-
- // http://tools.ietf.org/html/rfc4492#section-5.4
- serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
- serverECDHParams[0] = 3 // named curve
- serverECDHParams[1] = byte(curveid >> 8)
- serverECDHParams[2] = byte(curveid)
- if config.Bugs.InvalidSKXCurve {
- serverECDHParams[2] ^= 0xff
- }
- serverECDHParams[3] = byte(len(ecdhePublic))
- copy(serverECDHParams[4:], ecdhePublic)
-
- return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams)
-}
-
-func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
- if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
- return nil, errClientKeyExchange
- }
- x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
- if x == nil {
- return nil, errClientKeyExchange
- }
- x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
- preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
- xBytes := x.Bytes()
- copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
-
- return preMasterSecret, nil
-}
-
-func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
- if len(skx.key) < 4 {
- return errServerKeyExchange
- }
- if skx.key[0] != 3 { // named curve
- return errors.New("tls: server selected unsupported curve")
- }
- curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
-
- var ok bool
- if ka.curve, ok = curveForCurveID(curveid); !ok {
- return errors.New("tls: server selected unsupported curve")
- }
-
- publicLen := int(skx.key[3])
- if publicLen+4 > len(skx.key) {
- return errServerKeyExchange
- }
- ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
- if ka.x == nil {
- return errServerKeyExchange
- }
- serverECDHParams := skx.key[:4+publicLen]
- sig := skx.key[4+publicLen:]
-
- return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
-}
-
-func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
- if ka.curve == nil {
- return nil, nil, errors.New("missing ServerKeyExchange message")
- }
- priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
- if err != nil {
- return nil, nil, err
- }
- x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
- preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
- xBytes := x.Bytes()
- copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
-
- serialized := elliptic.Marshal(ka.curve, mx, my)
-
- ckx := new(clientKeyExchangeMsg)
- ckx.ciphertext = make([]byte, 1+len(serialized))
- ckx.ciphertext[0] = byte(len(serialized))
- copy(ckx.ciphertext[1:], serialized)
-
- return preMasterSecret, ckx, nil
-}
-
-// dheRSAKeyAgreement implements a TLS key agreement where the server generates
-// an ephemeral Diffie-Hellman public/private key pair and signs it. The
-// pre-master secret is then calculated using Diffie-Hellman.
-type dheKeyAgreement struct {
- auth keyAgreementAuthentication
- p, g *big.Int
- yTheirs *big.Int
- xOurs *big.Int
-}
-
-func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- var q *big.Int
- if p := config.Bugs.DHGroupPrime; p != nil {
- ka.p = p
- ka.g = big.NewInt(2)
- q = p
- } else {
- // 2048-bit MODP Group with 256-bit Prime Order Subgroup (RFC
- // 5114, Section 2.3)
- ka.p, _ = new(big.Int).SetString("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597", 16)
- ka.g, _ = new(big.Int).SetString("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659", 16)
- q, _ = new(big.Int).SetString("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3", 16)
- }
-
- var err error
- ka.xOurs, err = rand.Int(config.rand(), q)
- if err != nil {
- return nil, err
- }
- yOurs := new(big.Int).Exp(ka.g, ka.xOurs, ka.p)
-
- // http://tools.ietf.org/html/rfc5246#section-7.4.3
- pBytes := ka.p.Bytes()
- gBytes := ka.g.Bytes()
- yBytes := yOurs.Bytes()
- serverDHParams := make([]byte, 0, 2+len(pBytes)+2+len(gBytes)+2+len(yBytes))
- serverDHParams = append(serverDHParams, byte(len(pBytes)>>8), byte(len(pBytes)))
- serverDHParams = append(serverDHParams, pBytes...)
- serverDHParams = append(serverDHParams, byte(len(gBytes)>>8), byte(len(gBytes)))
- serverDHParams = append(serverDHParams, gBytes...)
- serverDHParams = append(serverDHParams, byte(len(yBytes)>>8), byte(len(yBytes)))
- serverDHParams = append(serverDHParams, yBytes...)
-
- return ka.auth.signParameters(config, cert, clientHello, hello, serverDHParams)
-}
-
-func (ka *dheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
- if len(ckx.ciphertext) < 2 {
- return nil, errClientKeyExchange
- }
- yLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1])
- if yLen != len(ckx.ciphertext)-2 {
- return nil, errClientKeyExchange
- }
- yTheirs := new(big.Int).SetBytes(ckx.ciphertext[2:])
- if yTheirs.Sign() <= 0 || yTheirs.Cmp(ka.p) >= 0 {
- return nil, errClientKeyExchange
- }
- return new(big.Int).Exp(yTheirs, ka.xOurs, ka.p).Bytes(), nil
-}
-
-func (ka *dheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
- // Read dh_p
- k := skx.key
- if len(k) < 2 {
- return errServerKeyExchange
- }
- pLen := (int(k[0]) << 8) | int(k[1])
- k = k[2:]
- if len(k) < pLen {
- return errServerKeyExchange
- }
- ka.p = new(big.Int).SetBytes(k[:pLen])
- k = k[pLen:]
-
- // Read dh_g
- if len(k) < 2 {
- return errServerKeyExchange
- }
- gLen := (int(k[0]) << 8) | int(k[1])
- k = k[2:]
- if len(k) < gLen {
- return errServerKeyExchange
- }
- ka.g = new(big.Int).SetBytes(k[:gLen])
- k = k[gLen:]
-
- // Read dh_Ys
- if len(k) < 2 {
- return errServerKeyExchange
- }
- yLen := (int(k[0]) << 8) | int(k[1])
- k = k[2:]
- if len(k) < yLen {
- return errServerKeyExchange
- }
- ka.yTheirs = new(big.Int).SetBytes(k[:yLen])
- k = k[yLen:]
- if ka.yTheirs.Sign() <= 0 || ka.yTheirs.Cmp(ka.p) >= 0 {
- return errServerKeyExchange
- }
-
- sig := k
- serverDHParams := skx.key[:len(skx.key)-len(sig)]
-
- return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverDHParams, sig)
-}
-
-func (ka *dheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
- if ka.p == nil || ka.g == nil || ka.yTheirs == nil {
- return nil, nil, errors.New("missing ServerKeyExchange message")
- }
-
- xOurs, err := rand.Int(config.rand(), ka.p)
- if err != nil {
- return nil, nil, err
- }
- preMasterSecret := new(big.Int).Exp(ka.yTheirs, xOurs, ka.p).Bytes()
-
- yOurs := new(big.Int).Exp(ka.g, xOurs, ka.p)
- yBytes := yOurs.Bytes()
- ckx := new(clientKeyExchangeMsg)
- ckx.ciphertext = make([]byte, 2+len(yBytes))
- ckx.ciphertext[0] = byte(len(yBytes) >> 8)
- ckx.ciphertext[1] = byte(len(yBytes))
- copy(ckx.ciphertext[2:], yBytes)
-
- return preMasterSecret, ckx, nil
-}
-
-// nilKeyAgreement is a fake key agreement used to implement the plain PSK key
-// exchange.
-type nilKeyAgreement struct{}
-
-func (ka *nilKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- return nil, nil
-}
-
-func (ka *nilKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
- if len(ckx.ciphertext) != 0 {
- return nil, errClientKeyExchange
- }
-
- // Although in plain PSK, otherSecret is all zeros, the base key
- // agreement does not access to the length of the pre-shared
- // key. pskKeyAgreement instead interprets nil to mean to use all zeros
- // of the appropriate length.
- return nil, nil
-}
-
-func (ka *nilKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
- if len(skx.key) != 0 {
- return errServerKeyExchange
- }
- return nil
-}
-
-func (ka *nilKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
- // Although in plain PSK, otherSecret is all zeros, the base key
- // agreement does not access to the length of the pre-shared
- // key. pskKeyAgreement instead interprets nil to mean to use all zeros
- // of the appropriate length.
- return nil, &clientKeyExchangeMsg{}, nil
-}
-
-// makePSKPremaster formats a PSK pre-master secret based on otherSecret from
-// the base key exchange and psk.
-func makePSKPremaster(otherSecret, psk []byte) []byte {
- out := make([]byte, 0, 2+len(otherSecret)+2+len(psk))
- out = append(out, byte(len(otherSecret)>>8), byte(len(otherSecret)))
- out = append(out, otherSecret...)
- out = append(out, byte(len(psk)>>8), byte(len(psk)))
- out = append(out, psk...)
- return out
-}
-
-// pskKeyAgreement implements the PSK key agreement.
-type pskKeyAgreement struct {
- base keyAgreement
- identityHint string
-}
-
-func (ka *pskKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- // Assemble the identity hint.
- bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
- bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
- bytes[1] = byte(len(config.PreSharedKeyIdentity))
- copy(bytes[2:], []byte(config.PreSharedKeyIdentity))
-
- // If there is one, append the base key agreement's
- // ServerKeyExchange.
- baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello)
- if err != nil {
- return nil, err
- }
-
- if baseSkx != nil {
- bytes = append(bytes, baseSkx.key...)
- } else if config.PreSharedKeyIdentity == "" {
- // ServerKeyExchange is optional if the identity hint is empty
- // and there would otherwise be no ServerKeyExchange.
- return nil, nil
- }
-
- skx := new(serverKeyExchangeMsg)
- skx.key = bytes
- return skx, nil
-}
-
-func (ka *pskKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
- // First, process the PSK identity.
- if len(ckx.ciphertext) < 2 {
- return nil, errClientKeyExchange
- }
- identityLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1])
- if 2+identityLen > len(ckx.ciphertext) {
- return nil, errClientKeyExchange
- }
- identity := string(ckx.ciphertext[2 : 2+identityLen])
-
- if identity != config.PreSharedKeyIdentity {
- return nil, errors.New("tls: unexpected identity")
- }
-
- if config.PreSharedKey == nil {
- return nil, errors.New("tls: pre-shared key not configured")
- }
-
- // Process the remainder of the ClientKeyExchange to compute the base
- // pre-master secret.
- newCkx := new(clientKeyExchangeMsg)
- newCkx.ciphertext = ckx.ciphertext[2+identityLen:]
- otherSecret, err := ka.base.processClientKeyExchange(config, cert, newCkx, version)
- if err != nil {
- return nil, err
- }
-
- if otherSecret == nil {
- // Special-case for the plain PSK key exchanges.
- otherSecret = make([]byte, len(config.PreSharedKey))
- }
- return makePSKPremaster(otherSecret, config.PreSharedKey), nil
-}
-
-func (ka *pskKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
- if len(skx.key) < 2 {
- return errServerKeyExchange
- }
- identityLen := (int(skx.key[0]) << 8) | int(skx.key[1])
- if 2+identityLen > len(skx.key) {
- return errServerKeyExchange
- }
- ka.identityHint = string(skx.key[2 : 2+identityLen])
-
- // Process the remainder of the ServerKeyExchange.
- newSkx := new(serverKeyExchangeMsg)
- newSkx.key = skx.key[2+identityLen:]
- return ka.base.processServerKeyExchange(config, clientHello, serverHello, cert, newSkx)
-}
-
-func (ka *pskKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
- // The server only sends an identity hint but, for purposes of
- // test code, the server always sends the hint and it is
- // required to match.
- if ka.identityHint != config.PreSharedKeyIdentity {
- return nil, nil, errors.New("tls: unexpected identity")
- }
-
- // Serialize the identity.
- bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
- bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
- bytes[1] = byte(len(config.PreSharedKeyIdentity))
- copy(bytes[2:], []byte(config.PreSharedKeyIdentity))
-
- // Append the base key exchange's ClientKeyExchange.
- otherSecret, baseCkx, err := ka.base.generateClientKeyExchange(config, clientHello, cert)
- if err != nil {
- return nil, nil, err
- }
- ckx := new(clientKeyExchangeMsg)
- ckx.ciphertext = append(bytes, baseCkx.ciphertext...)
-
- if config.PreSharedKey == nil {
- return nil, nil, errors.New("tls: pre-shared key not configured")
- }
- if otherSecret == nil {
- otherSecret = make([]byte, len(config.PreSharedKey))
- }
- return makePSKPremaster(otherSecret, config.PreSharedKey), ckx, nil
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/packet_adapter.go b/third_party/boringssl/src/ssl/test/runner/packet_adapter.go
deleted file mode 100644
index b432659619..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/packet_adapter.go
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import (
- "encoding/binary"
- "fmt"
- "io"
- "net"
- "time"
-)
-
-// opcodePacket signals a packet, encoded with a 32-bit length prefix, followed
-// by the payload.
-const opcodePacket = byte('P')
-
-// opcodeTimeout signals a read timeout, encoded by a 64-bit number of
-// nanoseconds. On receipt, the peer should reply with
-// opcodeTimeoutAck. opcodeTimeout may only be sent by the Go side.
-const opcodeTimeout = byte('T')
-
-// opcodeTimeoutAck acknowledges a read timeout. This opcode has no payload and
-// may only be sent by the C side. Timeout ACKs act as a synchronization point
-// at the timeout, to bracket one flight of messages from C.
-const opcodeTimeoutAck = byte('t')
-
-type packetAdaptor struct {
- net.Conn
-}
-
-// newPacketAdaptor wraps a reliable streaming net.Conn into a reliable
-// packet-based net.Conn. The stream contains packets and control commands,
-// distinguished by a one byte opcode.
-func newPacketAdaptor(conn net.Conn) *packetAdaptor {
- return &packetAdaptor{conn}
-}
-
-func (p *packetAdaptor) readOpcode() (byte, error) {
- out := make([]byte, 1)
- if _, err := io.ReadFull(p.Conn, out); err != nil {
- return 0, err
- }
- return out[0], nil
-}
-
-func (p *packetAdaptor) readPacketBody() ([]byte, error) {
- var length uint32
- if err := binary.Read(p.Conn, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- out := make([]byte, length)
- if _, err := io.ReadFull(p.Conn, out); err != nil {
- return nil, err
- }
- return out, nil
-}
-
-func (p *packetAdaptor) Read(b []byte) (int, error) {
- opcode, err := p.readOpcode()
- if err != nil {
- return 0, err
- }
- if opcode != opcodePacket {
- return 0, fmt.Errorf("unexpected opcode '%d'", opcode)
- }
- out, err := p.readPacketBody()
- if err != nil {
- return 0, err
- }
- return copy(b, out), nil
-}
-
-func (p *packetAdaptor) Write(b []byte) (int, error) {
- payload := make([]byte, 1+4+len(b))
- payload[0] = opcodePacket
- binary.BigEndian.PutUint32(payload[1:5], uint32(len(b)))
- copy(payload[5:], b)
- if _, err := p.Conn.Write(payload); err != nil {
- return 0, err
- }
- return len(b), nil
-}
-
-// SendReadTimeout instructs the peer to simulate a read timeout. It then waits
-// for acknowledgement of the timeout, buffering any packets received since
-// then. The packets are then returned.
-func (p *packetAdaptor) SendReadTimeout(d time.Duration) ([][]byte, error) {
- payload := make([]byte, 1+8)
- payload[0] = opcodeTimeout
- binary.BigEndian.PutUint64(payload[1:], uint64(d.Nanoseconds()))
- if _, err := p.Conn.Write(payload); err != nil {
- return nil, err
- }
-
- var packets [][]byte
- for {
- opcode, err := p.readOpcode()
- if err != nil {
- return nil, err
- }
- switch opcode {
- case opcodeTimeoutAck:
- // Done! Return the packets buffered and continue.
- return packets, nil
- case opcodePacket:
- // Buffer the packet for the caller to process.
- packet, err := p.readPacketBody()
- if err != nil {
- return nil, err
- }
- packets = append(packets, packet)
- default:
- return nil, fmt.Errorf("unexpected opcode '%d'", opcode)
- }
- }
-}
-
-type replayAdaptor struct {
- net.Conn
- prevWrite []byte
-}
-
-// newReplayAdaptor wraps a packeted net.Conn. It transforms it into
-// one which, after writing a packet, always replays the previous
-// write.
-func newReplayAdaptor(conn net.Conn) net.Conn {
- return &replayAdaptor{Conn: conn}
-}
-
-func (r *replayAdaptor) Write(b []byte) (int, error) {
- n, err := r.Conn.Write(b)
-
- // Replay the previous packet and save the current one to
- // replay next.
- if r.prevWrite != nil {
- r.Conn.Write(r.prevWrite)
- }
- r.prevWrite = append(r.prevWrite[:0], b...)
-
- return n, err
-}
-
-type damageAdaptor struct {
- net.Conn
- damage bool
-}
-
-// newDamageAdaptor wraps a packeted net.Conn. It transforms it into one which
-// optionally damages the final byte of every Write() call.
-func newDamageAdaptor(conn net.Conn) *damageAdaptor {
- return &damageAdaptor{Conn: conn}
-}
-
-func (d *damageAdaptor) setDamage(damage bool) {
- d.damage = damage
-}
-
-func (d *damageAdaptor) Write(b []byte) (int, error) {
- if d.damage && len(b) > 0 {
- b = append([]byte{}, b...)
- b[len(b)-1]++
- }
- return d.Conn.Write(b)
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/poly1305.go b/third_party/boringssl/src/ssl/test/runner/poly1305.go
deleted file mode 100644
index edef3384bc..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/poly1305.go
+++ /dev/null
@@ -1,1540 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-// Based on original, public domain implementation from NaCl by D. J.
-// Bernstein.
-
-import (
- "crypto/subtle"
- "math"
-)
-
-const (
- alpham80 = 0.00000000558793544769287109375
- alpham48 = 24.0
- alpham16 = 103079215104.0
- alpha0 = 6755399441055744.0
- alpha18 = 1770887431076116955136.0
- alpha32 = 29014219670751100192948224.0
- alpha50 = 7605903601369376408980219232256.0
- alpha64 = 124615124604835863084731911901282304.0
- alpha82 = 32667107224410092492483962313449748299776.0
- alpha96 = 535217884764734955396857238543560676143529984.0
- alpha112 = 35076039295941670036888435985190792471742381031424.0
- alpha130 = 9194973245195333150150082162901855101712434733101613056.0
- scale = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125
- offset0 = 6755408030990331.0
- offset1 = 29014256564239239022116864.0
- offset2 = 124615283061160854719918951570079744.0
- offset3 = 535219245894202480694386063513315216128475136.0
-)
-
-// poly1305Verify returns true if mac is a valid authenticator for m with the
-// given key.
-func poly1305Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
- var tmp [16]byte
- poly1305Sum(&tmp, m, key)
- return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
-}
-
-// poly1305Sum generates an authenticator for m using a one-time key and puts
-// the 16-byte result into out. Authenticating two different messages with the
-// same key allows an attacker to forge messages at will.
-func poly1305Sum(out *[16]byte, m []byte, key *[32]byte) {
- r := key
- s := key[16:]
- var (
- y7 float64
- y6 float64
- y1 float64
- y0 float64
- y5 float64
- y4 float64
- x7 float64
- x6 float64
- x1 float64
- x0 float64
- y3 float64
- y2 float64
- x5 float64
- r3lowx0 float64
- x4 float64
- r0lowx6 float64
- x3 float64
- r3highx0 float64
- x2 float64
- r0highx6 float64
- r0lowx0 float64
- sr1lowx6 float64
- r0highx0 float64
- sr1highx6 float64
- sr3low float64
- r1lowx0 float64
- sr2lowx6 float64
- r1highx0 float64
- sr2highx6 float64
- r2lowx0 float64
- sr3lowx6 float64
- r2highx0 float64
- sr3highx6 float64
- r1highx4 float64
- r1lowx4 float64
- r0highx4 float64
- r0lowx4 float64
- sr3highx4 float64
- sr3lowx4 float64
- sr2highx4 float64
- sr2lowx4 float64
- r0lowx2 float64
- r0highx2 float64
- r1lowx2 float64
- r1highx2 float64
- r2lowx2 float64
- r2highx2 float64
- sr3lowx2 float64
- sr3highx2 float64
- z0 float64
- z1 float64
- z2 float64
- z3 float64
- m0 int64
- m1 int64
- m2 int64
- m3 int64
- m00 uint32
- m01 uint32
- m02 uint32
- m03 uint32
- m10 uint32
- m11 uint32
- m12 uint32
- m13 uint32
- m20 uint32
- m21 uint32
- m22 uint32
- m23 uint32
- m30 uint32
- m31 uint32
- m32 uint32
- m33 uint64
- lbelow2 int32
- lbelow3 int32
- lbelow4 int32
- lbelow5 int32
- lbelow6 int32
- lbelow7 int32
- lbelow8 int32
- lbelow9 int32
- lbelow10 int32
- lbelow11 int32
- lbelow12 int32
- lbelow13 int32
- lbelow14 int32
- lbelow15 int32
- s00 uint32
- s01 uint32
- s02 uint32
- s03 uint32
- s10 uint32
- s11 uint32
- s12 uint32
- s13 uint32
- s20 uint32
- s21 uint32
- s22 uint32
- s23 uint32
- s30 uint32
- s31 uint32
- s32 uint32
- s33 uint32
- bits32 uint64
- f uint64
- f0 uint64
- f1 uint64
- f2 uint64
- f3 uint64
- f4 uint64
- g uint64
- g0 uint64
- g1 uint64
- g2 uint64
- g3 uint64
- g4 uint64
- )
-
- var p int32
-
- l := int32(len(m))
-
- r00 := uint32(r[0])
-
- r01 := uint32(r[1])
-
- r02 := uint32(r[2])
- r0 := int64(2151)
-
- r03 := uint32(r[3])
- r03 &= 15
- r0 <<= 51
-
- r10 := uint32(r[4])
- r10 &= 252
- r01 <<= 8
- r0 += int64(r00)
-
- r11 := uint32(r[5])
- r02 <<= 16
- r0 += int64(r01)
-
- r12 := uint32(r[6])
- r03 <<= 24
- r0 += int64(r02)
-
- r13 := uint32(r[7])
- r13 &= 15
- r1 := int64(2215)
- r0 += int64(r03)
-
- d0 := r0
- r1 <<= 51
- r2 := int64(2279)
-
- r20 := uint32(r[8])
- r20 &= 252
- r11 <<= 8
- r1 += int64(r10)
-
- r21 := uint32(r[9])
- r12 <<= 16
- r1 += int64(r11)
-
- r22 := uint32(r[10])
- r13 <<= 24
- r1 += int64(r12)
-
- r23 := uint32(r[11])
- r23 &= 15
- r2 <<= 51
- r1 += int64(r13)
-
- d1 := r1
- r21 <<= 8
- r2 += int64(r20)
-
- r30 := uint32(r[12])
- r30 &= 252
- r22 <<= 16
- r2 += int64(r21)
-
- r31 := uint32(r[13])
- r23 <<= 24
- r2 += int64(r22)
-
- r32 := uint32(r[14])
- r2 += int64(r23)
- r3 := int64(2343)
-
- d2 := r2
- r3 <<= 51
-
- r33 := uint32(r[15])
- r33 &= 15
- r31 <<= 8
- r3 += int64(r30)
-
- r32 <<= 16
- r3 += int64(r31)
-
- r33 <<= 24
- r3 += int64(r32)
-
- r3 += int64(r33)
- h0 := alpha32 - alpha32
-
- d3 := r3
- h1 := alpha32 - alpha32
-
- h2 := alpha32 - alpha32
-
- h3 := alpha32 - alpha32
-
- h4 := alpha32 - alpha32
-
- r0low := math.Float64frombits(uint64(d0))
- h5 := alpha32 - alpha32
-
- r1low := math.Float64frombits(uint64(d1))
- h6 := alpha32 - alpha32
-
- r2low := math.Float64frombits(uint64(d2))
- h7 := alpha32 - alpha32
-
- r0low -= alpha0
-
- r1low -= alpha32
-
- r2low -= alpha64
-
- r0high := r0low + alpha18
-
- r3low := math.Float64frombits(uint64(d3))
-
- r1high := r1low + alpha50
- sr1low := scale * r1low
-
- r2high := r2low + alpha82
- sr2low := scale * r2low
-
- r0high -= alpha18
- r0high_stack := r0high
-
- r3low -= alpha96
-
- r1high -= alpha50
- r1high_stack := r1high
-
- sr1high := sr1low + alpham80
-
- r0low -= r0high
-
- r2high -= alpha82
- sr3low = scale * r3low
-
- sr2high := sr2low + alpham48
-
- r1low -= r1high
- r1low_stack := r1low
-
- sr1high -= alpham80
- sr1high_stack := sr1high
-
- r2low -= r2high
- r2low_stack := r2low
-
- sr2high -= alpham48
- sr2high_stack := sr2high
-
- r3high := r3low + alpha112
- r0low_stack := r0low
-
- sr1low -= sr1high
- sr1low_stack := sr1low
-
- sr3high := sr3low + alpham16
- r2high_stack := r2high
-
- sr2low -= sr2high
- sr2low_stack := sr2low
-
- r3high -= alpha112
- r3high_stack := r3high
-
- sr3high -= alpham16
- sr3high_stack := sr3high
-
- r3low -= r3high
- r3low_stack := r3low
-
- sr3low -= sr3high
- sr3low_stack := sr3low
-
- if l < 16 {
- goto addatmost15bytes
- }
-
- m00 = uint32(m[p+0])
- m0 = 2151
-
- m0 <<= 51
- m1 = 2215
- m01 = uint32(m[p+1])
-
- m1 <<= 51
- m2 = 2279
- m02 = uint32(m[p+2])
-
- m2 <<= 51
- m3 = 2343
- m03 = uint32(m[p+3])
-
- m10 = uint32(m[p+4])
- m01 <<= 8
- m0 += int64(m00)
-
- m11 = uint32(m[p+5])
- m02 <<= 16
- m0 += int64(m01)
-
- m12 = uint32(m[p+6])
- m03 <<= 24
- m0 += int64(m02)
-
- m13 = uint32(m[p+7])
- m3 <<= 51
- m0 += int64(m03)
-
- m20 = uint32(m[p+8])
- m11 <<= 8
- m1 += int64(m10)
-
- m21 = uint32(m[p+9])
- m12 <<= 16
- m1 += int64(m11)
-
- m22 = uint32(m[p+10])
- m13 <<= 24
- m1 += int64(m12)
-
- m23 = uint32(m[p+11])
- m1 += int64(m13)
-
- m30 = uint32(m[p+12])
- m21 <<= 8
- m2 += int64(m20)
-
- m31 = uint32(m[p+13])
- m22 <<= 16
- m2 += int64(m21)
-
- m32 = uint32(m[p+14])
- m23 <<= 24
- m2 += int64(m22)
-
- m33 = uint64(m[p+15])
- m2 += int64(m23)
-
- d0 = m0
- m31 <<= 8
- m3 += int64(m30)
-
- d1 = m1
- m32 <<= 16
- m3 += int64(m31)
-
- d2 = m2
- m33 += 256
-
- m33 <<= 24
- m3 += int64(m32)
-
- m3 += int64(m33)
- d3 = m3
-
- p += 16
- l -= 16
-
- z0 = math.Float64frombits(uint64(d0))
-
- z1 = math.Float64frombits(uint64(d1))
-
- z2 = math.Float64frombits(uint64(d2))
-
- z3 = math.Float64frombits(uint64(d3))
-
- z0 -= alpha0
-
- z1 -= alpha32
-
- z2 -= alpha64
-
- z3 -= alpha96
-
- h0 += z0
-
- h1 += z1
-
- h3 += z2
-
- h5 += z3
-
- if l < 16 {
- goto multiplyaddatmost15bytes
- }
-
-multiplyaddatleast16bytes:
-
- m2 = 2279
- m20 = uint32(m[p+8])
- y7 = h7 + alpha130
-
- m2 <<= 51
- m3 = 2343
- m21 = uint32(m[p+9])
- y6 = h6 + alpha130
-
- m3 <<= 51
- m0 = 2151
- m22 = uint32(m[p+10])
- y1 = h1 + alpha32
-
- m0 <<= 51
- m1 = 2215
- m23 = uint32(m[p+11])
- y0 = h0 + alpha32
-
- m1 <<= 51
- m30 = uint32(m[p+12])
- y7 -= alpha130
-
- m21 <<= 8
- m2 += int64(m20)
- m31 = uint32(m[p+13])
- y6 -= alpha130
-
- m22 <<= 16
- m2 += int64(m21)
- m32 = uint32(m[p+14])
- y1 -= alpha32
-
- m23 <<= 24
- m2 += int64(m22)
- m33 = uint64(m[p+15])
- y0 -= alpha32
-
- m2 += int64(m23)
- m00 = uint32(m[p+0])
- y5 = h5 + alpha96
-
- m31 <<= 8
- m3 += int64(m30)
- m01 = uint32(m[p+1])
- y4 = h4 + alpha96
-
- m32 <<= 16
- m02 = uint32(m[p+2])
- x7 = h7 - y7
- y7 *= scale
-
- m33 += 256
- m03 = uint32(m[p+3])
- x6 = h6 - y6
- y6 *= scale
-
- m33 <<= 24
- m3 += int64(m31)
- m10 = uint32(m[p+4])
- x1 = h1 - y1
-
- m01 <<= 8
- m3 += int64(m32)
- m11 = uint32(m[p+5])
- x0 = h0 - y0
-
- m3 += int64(m33)
- m0 += int64(m00)
- m12 = uint32(m[p+6])
- y5 -= alpha96
-
- m02 <<= 16
- m0 += int64(m01)
- m13 = uint32(m[p+7])
- y4 -= alpha96
-
- m03 <<= 24
- m0 += int64(m02)
- d2 = m2
- x1 += y7
-
- m0 += int64(m03)
- d3 = m3
- x0 += y6
-
- m11 <<= 8
- m1 += int64(m10)
- d0 = m0
- x7 += y5
-
- m12 <<= 16
- m1 += int64(m11)
- x6 += y4
-
- m13 <<= 24
- m1 += int64(m12)
- y3 = h3 + alpha64
-
- m1 += int64(m13)
- d1 = m1
- y2 = h2 + alpha64
-
- x0 += x1
-
- x6 += x7
-
- y3 -= alpha64
- r3low = r3low_stack
-
- y2 -= alpha64
- r0low = r0low_stack
-
- x5 = h5 - y5
- r3lowx0 = r3low * x0
- r3high = r3high_stack
-
- x4 = h4 - y4
- r0lowx6 = r0low * x6
- r0high = r0high_stack
-
- x3 = h3 - y3
- r3highx0 = r3high * x0
- sr1low = sr1low_stack
-
- x2 = h2 - y2
- r0highx6 = r0high * x6
- sr1high = sr1high_stack
-
- x5 += y3
- r0lowx0 = r0low * x0
- r1low = r1low_stack
-
- h6 = r3lowx0 + r0lowx6
- sr1lowx6 = sr1low * x6
- r1high = r1high_stack
-
- x4 += y2
- r0highx0 = r0high * x0
- sr2low = sr2low_stack
-
- h7 = r3highx0 + r0highx6
- sr1highx6 = sr1high * x6
- sr2high = sr2high_stack
-
- x3 += y1
- r1lowx0 = r1low * x0
- r2low = r2low_stack
-
- h0 = r0lowx0 + sr1lowx6
- sr2lowx6 = sr2low * x6
- r2high = r2high_stack
-
- x2 += y0
- r1highx0 = r1high * x0
- sr3low = sr3low_stack
-
- h1 = r0highx0 + sr1highx6
- sr2highx6 = sr2high * x6
- sr3high = sr3high_stack
-
- x4 += x5
- r2lowx0 = r2low * x0
- z2 = math.Float64frombits(uint64(d2))
-
- h2 = r1lowx0 + sr2lowx6
- sr3lowx6 = sr3low * x6
-
- x2 += x3
- r2highx0 = r2high * x0
- z3 = math.Float64frombits(uint64(d3))
-
- h3 = r1highx0 + sr2highx6
- sr3highx6 = sr3high * x6
-
- r1highx4 = r1high * x4
- z2 -= alpha64
-
- h4 = r2lowx0 + sr3lowx6
- r1lowx4 = r1low * x4
-
- r0highx4 = r0high * x4
- z3 -= alpha96
-
- h5 = r2highx0 + sr3highx6
- r0lowx4 = r0low * x4
-
- h7 += r1highx4
- sr3highx4 = sr3high * x4
-
- h6 += r1lowx4
- sr3lowx4 = sr3low * x4
-
- h5 += r0highx4
- sr2highx4 = sr2high * x4
-
- h4 += r0lowx4
- sr2lowx4 = sr2low * x4
-
- h3 += sr3highx4
- r0lowx2 = r0low * x2
-
- h2 += sr3lowx4
- r0highx2 = r0high * x2
-
- h1 += sr2highx4
- r1lowx2 = r1low * x2
-
- h0 += sr2lowx4
- r1highx2 = r1high * x2
-
- h2 += r0lowx2
- r2lowx2 = r2low * x2
-
- h3 += r0highx2
- r2highx2 = r2high * x2
-
- h4 += r1lowx2
- sr3lowx2 = sr3low * x2
-
- h5 += r1highx2
- sr3highx2 = sr3high * x2
-
- p += 16
- l -= 16
- h6 += r2lowx2
-
- h7 += r2highx2
-
- z1 = math.Float64frombits(uint64(d1))
- h0 += sr3lowx2
-
- z0 = math.Float64frombits(uint64(d0))
- h1 += sr3highx2
-
- z1 -= alpha32
-
- z0 -= alpha0
-
- h5 += z3
-
- h3 += z2
-
- h1 += z1
-
- h0 += z0
-
- if l >= 16 {
- goto multiplyaddatleast16bytes
- }
-
-multiplyaddatmost15bytes:
-
- y7 = h7 + alpha130
-
- y6 = h6 + alpha130
-
- y1 = h1 + alpha32
-
- y0 = h0 + alpha32
-
- y7 -= alpha130
-
- y6 -= alpha130
-
- y1 -= alpha32
-
- y0 -= alpha32
-
- y5 = h5 + alpha96
-
- y4 = h4 + alpha96
-
- x7 = h7 - y7
- y7 *= scale
-
- x6 = h6 - y6
- y6 *= scale
-
- x1 = h1 - y1
-
- x0 = h0 - y0
-
- y5 -= alpha96
-
- y4 -= alpha96
-
- x1 += y7
-
- x0 += y6
-
- x7 += y5
-
- x6 += y4
-
- y3 = h3 + alpha64
-
- y2 = h2 + alpha64
-
- x0 += x1
-
- x6 += x7
-
- y3 -= alpha64
- r3low = r3low_stack
-
- y2 -= alpha64
- r0low = r0low_stack
-
- x5 = h5 - y5
- r3lowx0 = r3low * x0
- r3high = r3high_stack
-
- x4 = h4 - y4
- r0lowx6 = r0low * x6
- r0high = r0high_stack
-
- x3 = h3 - y3
- r3highx0 = r3high * x0
- sr1low = sr1low_stack
-
- x2 = h2 - y2
- r0highx6 = r0high * x6
- sr1high = sr1high_stack
-
- x5 += y3
- r0lowx0 = r0low * x0
- r1low = r1low_stack
-
- h6 = r3lowx0 + r0lowx6
- sr1lowx6 = sr1low * x6
- r1high = r1high_stack
-
- x4 += y2
- r0highx0 = r0high * x0
- sr2low = sr2low_stack
-
- h7 = r3highx0 + r0highx6
- sr1highx6 = sr1high * x6
- sr2high = sr2high_stack
-
- x3 += y1
- r1lowx0 = r1low * x0
- r2low = r2low_stack
-
- h0 = r0lowx0 + sr1lowx6
- sr2lowx6 = sr2low * x6
- r2high = r2high_stack
-
- x2 += y0
- r1highx0 = r1high * x0
- sr3low = sr3low_stack
-
- h1 = r0highx0 + sr1highx6
- sr2highx6 = sr2high * x6
- sr3high = sr3high_stack
-
- x4 += x5
- r2lowx0 = r2low * x0
-
- h2 = r1lowx0 + sr2lowx6
- sr3lowx6 = sr3low * x6
-
- x2 += x3
- r2highx0 = r2high * x0
-
- h3 = r1highx0 + sr2highx6
- sr3highx6 = sr3high * x6
-
- r1highx4 = r1high * x4
-
- h4 = r2lowx0 + sr3lowx6
- r1lowx4 = r1low * x4
-
- r0highx4 = r0high * x4
-
- h5 = r2highx0 + sr3highx6
- r0lowx4 = r0low * x4
-
- h7 += r1highx4
- sr3highx4 = sr3high * x4
-
- h6 += r1lowx4
- sr3lowx4 = sr3low * x4
-
- h5 += r0highx4
- sr2highx4 = sr2high * x4
-
- h4 += r0lowx4
- sr2lowx4 = sr2low * x4
-
- h3 += sr3highx4
- r0lowx2 = r0low * x2
-
- h2 += sr3lowx4
- r0highx2 = r0high * x2
-
- h1 += sr2highx4
- r1lowx2 = r1low * x2
-
- h0 += sr2lowx4
- r1highx2 = r1high * x2
-
- h2 += r0lowx2
- r2lowx2 = r2low * x2
-
- h3 += r0highx2
- r2highx2 = r2high * x2
-
- h4 += r1lowx2
- sr3lowx2 = sr3low * x2
-
- h5 += r1highx2
- sr3highx2 = sr3high * x2
-
- h6 += r2lowx2
-
- h7 += r2highx2
-
- h0 += sr3lowx2
-
- h1 += sr3highx2
-
-addatmost15bytes:
-
- if l == 0 {
- goto nomorebytes
- }
-
- lbelow2 = l - 2
-
- lbelow3 = l - 3
-
- lbelow2 >>= 31
- lbelow4 = l - 4
-
- m00 = uint32(m[p+0])
- lbelow3 >>= 31
- p += lbelow2
-
- m01 = uint32(m[p+1])
- lbelow4 >>= 31
- p += lbelow3
-
- m02 = uint32(m[p+2])
- p += lbelow4
- m0 = 2151
-
- m03 = uint32(m[p+3])
- m0 <<= 51
- m1 = 2215
-
- m0 += int64(m00)
- m01 &^= uint32(lbelow2)
-
- m02 &^= uint32(lbelow3)
- m01 -= uint32(lbelow2)
-
- m01 <<= 8
- m03 &^= uint32(lbelow4)
-
- m0 += int64(m01)
- lbelow2 -= lbelow3
-
- m02 += uint32(lbelow2)
- lbelow3 -= lbelow4
-
- m02 <<= 16
- m03 += uint32(lbelow3)
-
- m03 <<= 24
- m0 += int64(m02)
-
- m0 += int64(m03)
- lbelow5 = l - 5
-
- lbelow6 = l - 6
- lbelow7 = l - 7
-
- lbelow5 >>= 31
- lbelow8 = l - 8
-
- lbelow6 >>= 31
- p += lbelow5
-
- m10 = uint32(m[p+4])
- lbelow7 >>= 31
- p += lbelow6
-
- m11 = uint32(m[p+5])
- lbelow8 >>= 31
- p += lbelow7
-
- m12 = uint32(m[p+6])
- m1 <<= 51
- p += lbelow8
-
- m13 = uint32(m[p+7])
- m10 &^= uint32(lbelow5)
- lbelow4 -= lbelow5
-
- m10 += uint32(lbelow4)
- lbelow5 -= lbelow6
-
- m11 &^= uint32(lbelow6)
- m11 += uint32(lbelow5)
-
- m11 <<= 8
- m1 += int64(m10)
-
- m1 += int64(m11)
- m12 &^= uint32(lbelow7)
-
- lbelow6 -= lbelow7
- m13 &^= uint32(lbelow8)
-
- m12 += uint32(lbelow6)
- lbelow7 -= lbelow8
-
- m12 <<= 16
- m13 += uint32(lbelow7)
-
- m13 <<= 24
- m1 += int64(m12)
-
- m1 += int64(m13)
- m2 = 2279
-
- lbelow9 = l - 9
- m3 = 2343
-
- lbelow10 = l - 10
- lbelow11 = l - 11
-
- lbelow9 >>= 31
- lbelow12 = l - 12
-
- lbelow10 >>= 31
- p += lbelow9
-
- m20 = uint32(m[p+8])
- lbelow11 >>= 31
- p += lbelow10
-
- m21 = uint32(m[p+9])
- lbelow12 >>= 31
- p += lbelow11
-
- m22 = uint32(m[p+10])
- m2 <<= 51
- p += lbelow12
-
- m23 = uint32(m[p+11])
- m20 &^= uint32(lbelow9)
- lbelow8 -= lbelow9
-
- m20 += uint32(lbelow8)
- lbelow9 -= lbelow10
-
- m21 &^= uint32(lbelow10)
- m21 += uint32(lbelow9)
-
- m21 <<= 8
- m2 += int64(m20)
-
- m2 += int64(m21)
- m22 &^= uint32(lbelow11)
-
- lbelow10 -= lbelow11
- m23 &^= uint32(lbelow12)
-
- m22 += uint32(lbelow10)
- lbelow11 -= lbelow12
-
- m22 <<= 16
- m23 += uint32(lbelow11)
-
- m23 <<= 24
- m2 += int64(m22)
-
- m3 <<= 51
- lbelow13 = l - 13
-
- lbelow13 >>= 31
- lbelow14 = l - 14
-
- lbelow14 >>= 31
- p += lbelow13
- lbelow15 = l - 15
-
- m30 = uint32(m[p+12])
- lbelow15 >>= 31
- p += lbelow14
-
- m31 = uint32(m[p+13])
- p += lbelow15
- m2 += int64(m23)
-
- m32 = uint32(m[p+14])
- m30 &^= uint32(lbelow13)
- lbelow12 -= lbelow13
-
- m30 += uint32(lbelow12)
- lbelow13 -= lbelow14
-
- m3 += int64(m30)
- m31 &^= uint32(lbelow14)
-
- m31 += uint32(lbelow13)
- m32 &^= uint32(lbelow15)
-
- m31 <<= 8
- lbelow14 -= lbelow15
-
- m3 += int64(m31)
- m32 += uint32(lbelow14)
- d0 = m0
-
- m32 <<= 16
- m33 = uint64(lbelow15 + 1)
- d1 = m1
-
- m33 <<= 24
- m3 += int64(m32)
- d2 = m2
-
- m3 += int64(m33)
- d3 = m3
-
- z3 = math.Float64frombits(uint64(d3))
-
- z2 = math.Float64frombits(uint64(d2))
-
- z1 = math.Float64frombits(uint64(d1))
-
- z0 = math.Float64frombits(uint64(d0))
-
- z3 -= alpha96
-
- z2 -= alpha64
-
- z1 -= alpha32
-
- z0 -= alpha0
-
- h5 += z3
-
- h3 += z2
-
- h1 += z1
-
- h0 += z0
-
- y7 = h7 + alpha130
-
- y6 = h6 + alpha130
-
- y1 = h1 + alpha32
-
- y0 = h0 + alpha32
-
- y7 -= alpha130
-
- y6 -= alpha130
-
- y1 -= alpha32
-
- y0 -= alpha32
-
- y5 = h5 + alpha96
-
- y4 = h4 + alpha96
-
- x7 = h7 - y7
- y7 *= scale
-
- x6 = h6 - y6
- y6 *= scale
-
- x1 = h1 - y1
-
- x0 = h0 - y0
-
- y5 -= alpha96
-
- y4 -= alpha96
-
- x1 += y7
-
- x0 += y6
-
- x7 += y5
-
- x6 += y4
-
- y3 = h3 + alpha64
-
- y2 = h2 + alpha64
-
- x0 += x1
-
- x6 += x7
-
- y3 -= alpha64
- r3low = r3low_stack
-
- y2 -= alpha64
- r0low = r0low_stack
-
- x5 = h5 - y5
- r3lowx0 = r3low * x0
- r3high = r3high_stack
-
- x4 = h4 - y4
- r0lowx6 = r0low * x6
- r0high = r0high_stack
-
- x3 = h3 - y3
- r3highx0 = r3high * x0
- sr1low = sr1low_stack
-
- x2 = h2 - y2
- r0highx6 = r0high * x6
- sr1high = sr1high_stack
-
- x5 += y3
- r0lowx0 = r0low * x0
- r1low = r1low_stack
-
- h6 = r3lowx0 + r0lowx6
- sr1lowx6 = sr1low * x6
- r1high = r1high_stack
-
- x4 += y2
- r0highx0 = r0high * x0
- sr2low = sr2low_stack
-
- h7 = r3highx0 + r0highx6
- sr1highx6 = sr1high * x6
- sr2high = sr2high_stack
-
- x3 += y1
- r1lowx0 = r1low * x0
- r2low = r2low_stack
-
- h0 = r0lowx0 + sr1lowx6
- sr2lowx6 = sr2low * x6
- r2high = r2high_stack
-
- x2 += y0
- r1highx0 = r1high * x0
- sr3low = sr3low_stack
-
- h1 = r0highx0 + sr1highx6
- sr2highx6 = sr2high * x6
- sr3high = sr3high_stack
-
- x4 += x5
- r2lowx0 = r2low * x0
-
- h2 = r1lowx0 + sr2lowx6
- sr3lowx6 = sr3low * x6
-
- x2 += x3
- r2highx0 = r2high * x0
-
- h3 = r1highx0 + sr2highx6
- sr3highx6 = sr3high * x6
-
- r1highx4 = r1high * x4
-
- h4 = r2lowx0 + sr3lowx6
- r1lowx4 = r1low * x4
-
- r0highx4 = r0high * x4
-
- h5 = r2highx0 + sr3highx6
- r0lowx4 = r0low * x4
-
- h7 += r1highx4
- sr3highx4 = sr3high * x4
-
- h6 += r1lowx4
- sr3lowx4 = sr3low * x4
-
- h5 += r0highx4
- sr2highx4 = sr2high * x4
-
- h4 += r0lowx4
- sr2lowx4 = sr2low * x4
-
- h3 += sr3highx4
- r0lowx2 = r0low * x2
-
- h2 += sr3lowx4
- r0highx2 = r0high * x2
-
- h1 += sr2highx4
- r1lowx2 = r1low * x2
-
- h0 += sr2lowx4
- r1highx2 = r1high * x2
-
- h2 += r0lowx2
- r2lowx2 = r2low * x2
-
- h3 += r0highx2
- r2highx2 = r2high * x2
-
- h4 += r1lowx2
- sr3lowx2 = sr3low * x2
-
- h5 += r1highx2
- sr3highx2 = sr3high * x2
-
- h6 += r2lowx2
-
- h7 += r2highx2
-
- h0 += sr3lowx2
-
- h1 += sr3highx2
-
-nomorebytes:
-
- y7 = h7 + alpha130
-
- y0 = h0 + alpha32
-
- y1 = h1 + alpha32
-
- y2 = h2 + alpha64
-
- y7 -= alpha130
-
- y3 = h3 + alpha64
-
- y4 = h4 + alpha96
-
- y5 = h5 + alpha96
-
- x7 = h7 - y7
- y7 *= scale
-
- y0 -= alpha32
-
- y1 -= alpha32
-
- y2 -= alpha64
-
- h6 += x7
-
- y3 -= alpha64
-
- y4 -= alpha96
-
- y5 -= alpha96
-
- y6 = h6 + alpha130
-
- x0 = h0 - y0
-
- x1 = h1 - y1
-
- x2 = h2 - y2
-
- y6 -= alpha130
-
- x0 += y7
-
- x3 = h3 - y3
-
- x4 = h4 - y4
-
- x5 = h5 - y5
-
- x6 = h6 - y6
-
- y6 *= scale
-
- x2 += y0
-
- x3 += y1
-
- x4 += y2
-
- x0 += y6
-
- x5 += y3
-
- x6 += y4
-
- x2 += x3
-
- x0 += x1
-
- x4 += x5
-
- x6 += y5
-
- x2 += offset1
- d1 = int64(math.Float64bits(x2))
-
- x0 += offset0
- d0 = int64(math.Float64bits(x0))
-
- x4 += offset2
- d2 = int64(math.Float64bits(x4))
-
- x6 += offset3
- d3 = int64(math.Float64bits(x6))
-
- f0 = uint64(d0)
-
- f1 = uint64(d1)
- bits32 = math.MaxUint64
-
- f2 = uint64(d2)
- bits32 >>= 32
-
- f3 = uint64(d3)
- f = f0 >> 32
-
- f0 &= bits32
- f &= 255
-
- f1 += f
- g0 = f0 + 5
-
- g = g0 >> 32
- g0 &= bits32
-
- f = f1 >> 32
- f1 &= bits32
-
- f &= 255
- g1 = f1 + g
-
- g = g1 >> 32
- f2 += f
-
- f = f2 >> 32
- g1 &= bits32
-
- f2 &= bits32
- f &= 255
-
- f3 += f
- g2 = f2 + g
-
- g = g2 >> 32
- g2 &= bits32
-
- f4 = f3 >> 32
- f3 &= bits32
-
- f4 &= 255
- g3 = f3 + g
-
- g = g3 >> 32
- g3 &= bits32
-
- g4 = f4 + g
-
- g4 = g4 - 4
- s00 = uint32(s[0])
-
- f = uint64(int64(g4) >> 63)
- s01 = uint32(s[1])
-
- f0 &= f
- g0 &^= f
- s02 = uint32(s[2])
-
- f1 &= f
- f0 |= g0
- s03 = uint32(s[3])
-
- g1 &^= f
- f2 &= f
- s10 = uint32(s[4])
-
- f3 &= f
- g2 &^= f
- s11 = uint32(s[5])
-
- g3 &^= f
- f1 |= g1
- s12 = uint32(s[6])
-
- f2 |= g2
- f3 |= g3
- s13 = uint32(s[7])
-
- s01 <<= 8
- f0 += uint64(s00)
- s20 = uint32(s[8])
-
- s02 <<= 16
- f0 += uint64(s01)
- s21 = uint32(s[9])
-
- s03 <<= 24
- f0 += uint64(s02)
- s22 = uint32(s[10])
-
- s11 <<= 8
- f1 += uint64(s10)
- s23 = uint32(s[11])
-
- s12 <<= 16
- f1 += uint64(s11)
- s30 = uint32(s[12])
-
- s13 <<= 24
- f1 += uint64(s12)
- s31 = uint32(s[13])
-
- f0 += uint64(s03)
- f1 += uint64(s13)
- s32 = uint32(s[14])
-
- s21 <<= 8
- f2 += uint64(s20)
- s33 = uint32(s[15])
-
- s22 <<= 16
- f2 += uint64(s21)
-
- s23 <<= 24
- f2 += uint64(s22)
-
- s31 <<= 8
- f3 += uint64(s30)
-
- s32 <<= 16
- f3 += uint64(s31)
-
- s33 <<= 24
- f3 += uint64(s32)
-
- f2 += uint64(s23)
- f3 += uint64(s33)
-
- out[0] = byte(f0)
- f0 >>= 8
- out[1] = byte(f0)
- f0 >>= 8
- out[2] = byte(f0)
- f0 >>= 8
- out[3] = byte(f0)
- f0 >>= 8
- f1 += f0
-
- out[4] = byte(f1)
- f1 >>= 8
- out[5] = byte(f1)
- f1 >>= 8
- out[6] = byte(f1)
- f1 >>= 8
- out[7] = byte(f1)
- f1 >>= 8
- f2 += f1
-
- out[8] = byte(f2)
- f2 >>= 8
- out[9] = byte(f2)
- f2 >>= 8
- out[10] = byte(f2)
- f2 >>= 8
- out[11] = byte(f2)
- f2 >>= 8
- f3 += f2
-
- out[12] = byte(f3)
- f3 >>= 8
- out[13] = byte(f3)
- f3 >>= 8
- out[14] = byte(f3)
- f3 >>= 8
- out[15] = byte(f3)
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/prf.go b/third_party/boringssl/src/ssl/test/runner/prf.go
deleted file mode 100644
index 8521abaa6f..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/prf.go
+++ /dev/null
@@ -1,388 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import (
- "crypto"
- "crypto/hmac"
- "crypto/md5"
- "crypto/sha1"
- "crypto/sha256"
- "crypto/sha512"
- "errors"
- "hash"
-)
-
-// Split a premaster secret in two as specified in RFC 4346, section 5.
-func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
- s1 = secret[0 : (len(secret)+1)/2]
- s2 = secret[len(secret)/2:]
- return
-}
-
-// pHash implements the P_hash function, as defined in RFC 4346, section 5.
-func pHash(result, secret, seed []byte, hash func() hash.Hash) {
- h := hmac.New(hash, secret)
- h.Write(seed)
- a := h.Sum(nil)
-
- j := 0
- for j < len(result) {
- h.Reset()
- h.Write(a)
- h.Write(seed)
- b := h.Sum(nil)
- todo := len(b)
- if j+todo > len(result) {
- todo = len(result) - j
- }
- copy(result[j:j+todo], b)
- j += todo
-
- h.Reset()
- h.Write(a)
- a = h.Sum(nil)
- }
-}
-
-// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
-func prf10(result, secret, label, seed []byte) {
- hashSHA1 := sha1.New
- hashMD5 := md5.New
-
- labelAndSeed := make([]byte, len(label)+len(seed))
- copy(labelAndSeed, label)
- copy(labelAndSeed[len(label):], seed)
-
- s1, s2 := splitPreMasterSecret(secret)
- pHash(result, s1, labelAndSeed, hashMD5)
- result2 := make([]byte, len(result))
- pHash(result2, s2, labelAndSeed, hashSHA1)
-
- for i, b := range result2 {
- result[i] ^= b
- }
-}
-
-// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
-func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
- return func(result, secret, label, seed []byte) {
- labelAndSeed := make([]byte, len(label)+len(seed))
- copy(labelAndSeed, label)
- copy(labelAndSeed[len(label):], seed)
-
- pHash(result, secret, labelAndSeed, hashFunc)
- }
-}
-
-// prf30 implements the SSL 3.0 pseudo-random function, as defined in
-// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
-func prf30(result, secret, label, seed []byte) {
- hashSHA1 := sha1.New()
- hashMD5 := md5.New()
-
- done := 0
- i := 0
- // RFC5246 section 6.3 says that the largest PRF output needed is 128
- // bytes. Since no more ciphersuites will be added to SSLv3, this will
- // remain true. Each iteration gives us 16 bytes so 10 iterations will
- // be sufficient.
- var b [11]byte
- for done < len(result) {
- for j := 0; j <= i; j++ {
- b[j] = 'A' + byte(i)
- }
-
- hashSHA1.Reset()
- hashSHA1.Write(b[:i+1])
- hashSHA1.Write(secret)
- hashSHA1.Write(seed)
- digest := hashSHA1.Sum(nil)
-
- hashMD5.Reset()
- hashMD5.Write(secret)
- hashMD5.Write(digest)
-
- done += copy(result[done:], hashMD5.Sum(nil))
- i++
- }
-}
-
-const (
- tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
- masterSecretLength = 48 // Length of a master secret in TLS 1.1.
- finishedVerifyLength = 12 // Length of verify_data in a Finished message.
-)
-
-var masterSecretLabel = []byte("master secret")
-var extendedMasterSecretLabel = []byte("extended master secret")
-var keyExpansionLabel = []byte("key expansion")
-var clientFinishedLabel = []byte("client finished")
-var serverFinishedLabel = []byte("server finished")
-var channelIDLabel = []byte("TLS Channel ID signature\x00")
-var channelIDResumeLabel = []byte("Resumption\x00")
-
-func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
- switch version {
- case VersionSSL30:
- return prf30
- case VersionTLS10, VersionTLS11:
- return prf10
- case VersionTLS12:
- if suite.flags&suiteSHA384 != 0 {
- return prf12(sha512.New384)
- }
- return prf12(sha256.New)
- default:
- panic("unknown version")
- }
-}
-
-// masterFromPreMasterSecret generates the master secret from the pre-master
-// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
-func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
- var seed [tlsRandomLength * 2]byte
- copy(seed[0:len(clientRandom)], clientRandom)
- copy(seed[len(clientRandom):], serverRandom)
- masterSecret := make([]byte, masterSecretLength)
- prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
- return masterSecret
-}
-
-// extendedMasterFromPreMasterSecret generates the master secret from the
-// pre-master secret when the Triple Handshake fix is in effect. See
-// https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
-func extendedMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret []byte, h finishedHash) []byte {
- masterSecret := make([]byte, masterSecretLength)
- prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, h.Sum())
- return masterSecret
-}
-
-// keysFromMasterSecret generates the connection keys from the master
-// secret, given the lengths of the MAC key, cipher key and IV, as defined in
-// RFC 2246, section 6.3.
-func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
- var seed [tlsRandomLength * 2]byte
- copy(seed[0:len(clientRandom)], serverRandom)
- copy(seed[len(serverRandom):], clientRandom)
-
- n := 2*macLen + 2*keyLen + 2*ivLen
- keyMaterial := make([]byte, n)
- prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
- clientMAC = keyMaterial[:macLen]
- keyMaterial = keyMaterial[macLen:]
- serverMAC = keyMaterial[:macLen]
- keyMaterial = keyMaterial[macLen:]
- clientKey = keyMaterial[:keyLen]
- keyMaterial = keyMaterial[keyLen:]
- serverKey = keyMaterial[:keyLen]
- keyMaterial = keyMaterial[keyLen:]
- clientIV = keyMaterial[:ivLen]
- keyMaterial = keyMaterial[ivLen:]
- serverIV = keyMaterial[:ivLen]
- return
-}
-
-// lookupTLSHash looks up the corresponding crypto.Hash for a given
-// TLS hash identifier.
-func lookupTLSHash(hash uint8) (crypto.Hash, error) {
- switch hash {
- case hashMD5:
- return crypto.MD5, nil
- case hashSHA1:
- return crypto.SHA1, nil
- case hashSHA224:
- return crypto.SHA224, nil
- case hashSHA256:
- return crypto.SHA256, nil
- case hashSHA384:
- return crypto.SHA384, nil
- case hashSHA512:
- return crypto.SHA512, nil
- default:
- return 0, errors.New("tls: unsupported hash algorithm")
- }
-}
-
-func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
- if version >= VersionTLS12 {
- newHash := sha256.New
- if cipherSuite.flags&suiteSHA384 != 0 {
- newHash = sha512.New384
- }
-
- return finishedHash{newHash(), newHash(), nil, nil, []byte{}, version, prf12(newHash)}
- }
- return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), []byte{}, version, prf10}
-}
-
-// A finishedHash calculates the hash of a set of handshake messages suitable
-// for including in a Finished message.
-type finishedHash struct {
- client hash.Hash
- server hash.Hash
-
- // Prior to TLS 1.2, an additional MD5 hash is required.
- clientMD5 hash.Hash
- serverMD5 hash.Hash
-
- // In TLS 1.2 (and SSL 3 for implementation convenience), a
- // full buffer is required.
- buffer []byte
-
- version uint16
- prf func(result, secret, label, seed []byte)
-}
-
-func (h *finishedHash) Write(msg []byte) (n int, err error) {
- h.client.Write(msg)
- h.server.Write(msg)
-
- if h.version < VersionTLS12 {
- h.clientMD5.Write(msg)
- h.serverMD5.Write(msg)
- }
-
- if h.buffer != nil {
- h.buffer = append(h.buffer, msg...)
- }
-
- return len(msg), nil
-}
-
-func (h finishedHash) Sum() []byte {
- if h.version >= VersionTLS12 {
- return h.client.Sum(nil)
- }
-
- out := make([]byte, 0, md5.Size+sha1.Size)
- out = h.clientMD5.Sum(out)
- return h.client.Sum(out)
-}
-
-// finishedSum30 calculates the contents of the verify_data member of a SSLv3
-// Finished message given the MD5 and SHA1 hashes of a set of handshake
-// messages.
-func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
- md5.Write(magic)
- md5.Write(masterSecret)
- md5.Write(ssl30Pad1[:])
- md5Digest := md5.Sum(nil)
-
- md5.Reset()
- md5.Write(masterSecret)
- md5.Write(ssl30Pad2[:])
- md5.Write(md5Digest)
- md5Digest = md5.Sum(nil)
-
- sha1.Write(magic)
- sha1.Write(masterSecret)
- sha1.Write(ssl30Pad1[:40])
- sha1Digest := sha1.Sum(nil)
-
- sha1.Reset()
- sha1.Write(masterSecret)
- sha1.Write(ssl30Pad2[:40])
- sha1.Write(sha1Digest)
- sha1Digest = sha1.Sum(nil)
-
- ret := make([]byte, len(md5Digest)+len(sha1Digest))
- copy(ret, md5Digest)
- copy(ret[len(md5Digest):], sha1Digest)
- return ret
-}
-
-var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
-var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
-
-// clientSum returns the contents of the verify_data member of a client's
-// Finished message.
-func (h finishedHash) clientSum(masterSecret []byte) []byte {
- if h.version == VersionSSL30 {
- return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
- }
-
- out := make([]byte, finishedVerifyLength)
- h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
- return out
-}
-
-// serverSum returns the contents of the verify_data member of a server's
-// Finished message.
-func (h finishedHash) serverSum(masterSecret []byte) []byte {
- if h.version == VersionSSL30 {
- return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
- }
-
- out := make([]byte, finishedVerifyLength)
- h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
- return out
-}
-
-// selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
-// client's CertificateVerify with, or an error if none can be found.
-func (h finishedHash) selectClientCertSignatureAlgorithm(serverList, clientList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
- if h.version < VersionTLS12 {
- // Nothing to negotiate before TLS 1.2.
- return signatureAndHash{signature: sigType}, nil
- }
-
- for _, v := range serverList {
- if v.signature == sigType && isSupportedSignatureAndHash(v, clientList) {
- return v, nil
- }
- }
- return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate")
-}
-
-// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
-// id suitable for signing by a TLS client certificate.
-func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
- if h.version == VersionSSL30 {
- if signatureAndHash.signature != signatureRSA {
- return nil, 0, errors.New("tls: unsupported signature type for client certificate")
- }
-
- md5Hash := md5.New()
- md5Hash.Write(h.buffer)
- sha1Hash := sha1.New()
- sha1Hash.Write(h.buffer)
- return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
- }
- if h.version >= VersionTLS12 {
- hashAlg, err := lookupTLSHash(signatureAndHash.hash)
- if err != nil {
- return nil, 0, err
- }
- hash := hashAlg.New()
- hash.Write(h.buffer)
- return hash.Sum(nil), hashAlg, nil
- }
- if signatureAndHash.signature == signatureECDSA {
- return h.server.Sum(nil), crypto.SHA1, nil
- }
-
- return h.Sum(), crypto.MD5SHA1, nil
-}
-
-// hashForChannelID returns the hash to be signed for TLS Channel
-// ID. If a resumption, resumeHash has the previous handshake
-// hash. Otherwise, it is nil.
-func (h finishedHash) hashForChannelID(resumeHash []byte) []byte {
- hash := sha256.New()
- hash.Write(channelIDLabel)
- if resumeHash != nil {
- hash.Write(channelIDResumeLabel)
- hash.Write(resumeHash)
- }
- hash.Write(h.server.Sum(nil))
- return hash.Sum(nil)
-}
-
-// discardHandshakeBuffer is called when there is no more need to
-// buffer the entirety of the handshake messages.
-func (h *finishedHash) discardHandshakeBuffer() {
- h.buffer = nil
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/recordingconn.go b/third_party/boringssl/src/ssl/test/runner/recordingconn.go
deleted file mode 100644
index 6537714707..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/recordingconn.go
+++ /dev/null
@@ -1,130 +0,0 @@
-package runner
-
-import (
- "bufio"
- "encoding/hex"
- "errors"
- "fmt"
- "io"
- "net"
- "strconv"
- "strings"
- "sync"
-)
-
-// recordingConn is a net.Conn that records the traffic that passes through it.
-// WriteTo can be used to produce output that can be later be loaded with
-// ParseTestData.
-type recordingConn struct {
- net.Conn
- sync.Mutex
- flows [][]byte
- reading bool
-}
-
-func (r *recordingConn) Read(b []byte) (n int, err error) {
- if n, err = r.Conn.Read(b); n == 0 {
- return
- }
- b = b[:n]
-
- r.Lock()
- defer r.Unlock()
-
- if l := len(r.flows); l == 0 || !r.reading {
- buf := make([]byte, len(b))
- copy(buf, b)
- r.flows = append(r.flows, buf)
- } else {
- r.flows[l-1] = append(r.flows[l-1], b[:n]...)
- }
- r.reading = true
- return
-}
-
-func (r *recordingConn) Write(b []byte) (n int, err error) {
- if n, err = r.Conn.Write(b); n == 0 {
- return
- }
- b = b[:n]
-
- r.Lock()
- defer r.Unlock()
-
- if l := len(r.flows); l == 0 || r.reading {
- buf := make([]byte, len(b))
- copy(buf, b)
- r.flows = append(r.flows, buf)
- } else {
- r.flows[l-1] = append(r.flows[l-1], b[:n]...)
- }
- r.reading = false
- return
-}
-
-// WriteTo writes hex dumps to w that contains the recorded traffic.
-func (r *recordingConn) WriteTo(w io.Writer) {
- // TLS always starts with a client to server flow.
- clientToServer := true
-
- for i, flow := range r.flows {
- source, dest := "client", "server"
- if !clientToServer {
- source, dest = dest, source
- }
- fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, source, dest)
- dumper := hex.Dumper(w)
- dumper.Write(flow)
- dumper.Close()
- clientToServer = !clientToServer
- }
-}
-
-func parseTestData(r io.Reader) (flows [][]byte, err error) {
- var currentFlow []byte
-
- scanner := bufio.NewScanner(r)
- for scanner.Scan() {
- line := scanner.Text()
- // If the line starts with ">>> " then it marks the beginning
- // of a new flow.
- if strings.HasPrefix(line, ">>> ") {
- if len(currentFlow) > 0 || len(flows) > 0 {
- flows = append(flows, currentFlow)
- currentFlow = nil
- }
- continue
- }
-
- // Otherwise the line is a line of hex dump that looks like:
- // 00000170 fc f5 06 bf (...) |.....X{&?......!|
- // (Some bytes have been omitted from the middle section.)
-
- if i := strings.IndexByte(line, ' '); i >= 0 {
- line = line[i:]
- } else {
- return nil, errors.New("invalid test data")
- }
-
- if i := strings.IndexByte(line, '|'); i >= 0 {
- line = line[:i]
- } else {
- return nil, errors.New("invalid test data")
- }
-
- hexBytes := strings.Fields(line)
- for _, hexByte := range hexBytes {
- val, err := strconv.ParseUint(hexByte, 16, 8)
- if err != nil {
- return nil, errors.New("invalid hex byte in test data: " + err.Error())
- }
- currentFlow = append(currentFlow, byte(val))
- }
- }
-
- if len(currentFlow) > 0 {
- flows = append(flows, currentFlow)
- }
-
- return flows, nil
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/runner.go b/third_party/boringssl/src/ssl/test/runner/runner.go
deleted file mode 100644
index a9823fcd25..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/runner.go
+++ /dev/null
@@ -1,4442 +0,0 @@
-package runner
-
-import (
- "bytes"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/x509"
- "encoding/base64"
- "encoding/pem"
- "flag"
- "fmt"
- "io"
- "io/ioutil"
- "math/big"
- "net"
- "os"
- "os/exec"
- "path"
- "runtime"
- "strconv"
- "strings"
- "sync"
- "syscall"
- "time"
-)
-
-var (
- useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
- useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
- flagDebug = flag.Bool("debug", false, "Hexdump the contents of the connection")
- mallocTest = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
- mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
- jsonOutput = flag.String("json-output", "", "The file to output JSON results to.")
- pipe = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
- testToRun = flag.String("test", "", "The name of a test to run, or empty to run all tests")
- numWorkers = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
- shimPath = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
- resourceDir = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
-)
-
-const (
- rsaCertificateFile = "cert.pem"
- ecdsaCertificateFile = "ecdsa_cert.pem"
-)
-
-const (
- rsaKeyFile = "key.pem"
- ecdsaKeyFile = "ecdsa_key.pem"
- channelIDKeyFile = "channel_id_key.pem"
-)
-
-var rsaCertificate, ecdsaCertificate Certificate
-var channelIDKey *ecdsa.PrivateKey
-var channelIDBytes []byte
-
-var testOCSPResponse = []byte{1, 2, 3, 4}
-var testSCTList = []byte{5, 6, 7, 8}
-
-func initCertificates() {
- var err error
- rsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, rsaCertificateFile), path.Join(*resourceDir, rsaKeyFile))
- if err != nil {
- panic(err)
- }
- rsaCertificate.OCSPStaple = testOCSPResponse
- rsaCertificate.SignedCertificateTimestampList = testSCTList
-
- ecdsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, ecdsaCertificateFile), path.Join(*resourceDir, ecdsaKeyFile))
- if err != nil {
- panic(err)
- }
- ecdsaCertificate.OCSPStaple = testOCSPResponse
- ecdsaCertificate.SignedCertificateTimestampList = testSCTList
-
- channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
- if err != nil {
- panic(err)
- }
- channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
- if channelIDDERBlock.Type != "EC PRIVATE KEY" {
- panic("bad key type")
- }
- channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
- if err != nil {
- panic(err)
- }
- if channelIDKey.Curve != elliptic.P256() {
- panic("bad curve")
- }
-
- channelIDBytes = make([]byte, 64)
- writeIntPadded(channelIDBytes[:32], channelIDKey.X)
- writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
-}
-
-var certificateOnce sync.Once
-
-func getRSACertificate() Certificate {
- certificateOnce.Do(initCertificates)
- return rsaCertificate
-}
-
-func getECDSACertificate() Certificate {
- certificateOnce.Do(initCertificates)
- return ecdsaCertificate
-}
-
-type testType int
-
-const (
- clientTest testType = iota
- serverTest
-)
-
-type protocol int
-
-const (
- tls protocol = iota
- dtls
-)
-
-const (
- alpn = 1
- npn = 2
-)
-
-type testCase struct {
- testType testType
- protocol protocol
- name string
- config Config
- shouldFail bool
- expectedError string
- // expectedLocalError, if not empty, contains a substring that must be
- // found in the local error.
- expectedLocalError string
- // expectedVersion, if non-zero, specifies the TLS version that must be
- // negotiated.
- expectedVersion uint16
- // expectedResumeVersion, if non-zero, specifies the TLS version that
- // must be negotiated on resumption. If zero, expectedVersion is used.
- expectedResumeVersion uint16
- // expectedCipher, if non-zero, specifies the TLS cipher suite that
- // should be negotiated.
- expectedCipher uint16
- // expectChannelID controls whether the connection should have
- // negotiated a Channel ID with channelIDKey.
- expectChannelID bool
- // expectedNextProto controls whether the connection should
- // negotiate a next protocol via NPN or ALPN.
- expectedNextProto string
- // expectedNextProtoType, if non-zero, is the expected next
- // protocol negotiation mechanism.
- expectedNextProtoType int
- // expectedSRTPProtectionProfile is the DTLS-SRTP profile that
- // should be negotiated. If zero, none should be negotiated.
- expectedSRTPProtectionProfile uint16
- // expectedOCSPResponse, if not nil, is the expected OCSP response to be received.
- expectedOCSPResponse []uint8
- // expectedSCTList, if not nil, is the expected SCT list to be received.
- expectedSCTList []uint8
- // expectedClientCertSignatureHash, if not zero, is the TLS id of the
- // hash function that the client should have used when signing the
- // handshake with a client certificate.
- expectedClientCertSignatureHash uint8
- // messageLen is the length, in bytes, of the test message that will be
- // sent.
- messageLen int
- // messageCount is the number of test messages that will be sent.
- messageCount int
- // digestPrefs is the list of digest preferences from the client.
- digestPrefs string
- // certFile is the path to the certificate to use for the server.
- certFile string
- // keyFile is the path to the private key to use for the server.
- keyFile string
- // resumeSession controls whether a second connection should be tested
- // which attempts to resume the first session.
- resumeSession bool
- // expectResumeRejected, if true, specifies that the attempted
- // resumption must be rejected by the client. This is only valid for a
- // serverTest.
- expectResumeRejected bool
- // resumeConfig, if not nil, points to a Config to be used on
- // resumption. Unless newSessionsOnResume is set,
- // SessionTicketKey, ServerSessionCache, and
- // ClientSessionCache are copied from the initial connection's
- // config. If nil, the initial connection's config is used.
- resumeConfig *Config
- // newSessionsOnResume, if true, will cause resumeConfig to
- // use a different session resumption context.
- newSessionsOnResume bool
- // noSessionCache, if true, will cause the server to run without a
- // session cache.
- noSessionCache bool
- // sendPrefix sends a prefix on the socket before actually performing a
- // handshake.
- sendPrefix string
- // shimWritesFirst controls whether the shim sends an initial "hello"
- // message before doing a roundtrip with the runner.
- shimWritesFirst bool
- // shimShutsDown, if true, runs a test where the shim shuts down the
- // connection immediately after the handshake rather than echoing
- // messages from the runner.
- shimShutsDown bool
- // renegotiate indicates the the connection should be renegotiated
- // during the exchange.
- renegotiate bool
- // renegotiateCiphers is a list of ciphersuite ids that will be
- // switched in just before renegotiation.
- renegotiateCiphers []uint16
- // replayWrites, if true, configures the underlying transport
- // to replay every write it makes in DTLS tests.
- replayWrites bool
- // damageFirstWrite, if true, configures the underlying transport to
- // damage the final byte of the first application data write.
- damageFirstWrite bool
- // exportKeyingMaterial, if non-zero, configures the test to exchange
- // keying material and verify they match.
- exportKeyingMaterial int
- exportLabel string
- exportContext string
- useExportContext bool
- // flags, if not empty, contains a list of command-line flags that will
- // be passed to the shim program.
- flags []string
- // testTLSUnique, if true, causes the shim to send the tls-unique value
- // which will be compared against the expected value.
- testTLSUnique bool
- // sendEmptyRecords is the number of consecutive empty records to send
- // before and after the test message.
- sendEmptyRecords int
- // sendWarningAlerts is the number of consecutive warning alerts to send
- // before and after the test message.
- sendWarningAlerts int
- // expectMessageDropped, if true, means the test message is expected to
- // be dropped by the client rather than echoed back.
- expectMessageDropped bool
-}
-
-var testCases []testCase
-
-func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
- var connDebug *recordingConn
- var connDamage *damageAdaptor
- if *flagDebug {
- connDebug = &recordingConn{Conn: conn}
- conn = connDebug
- defer func() {
- connDebug.WriteTo(os.Stdout)
- }()
- }
-
- if test.protocol == dtls {
- config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
- conn = config.Bugs.PacketAdaptor
- if test.replayWrites {
- conn = newReplayAdaptor(conn)
- }
- }
-
- if test.damageFirstWrite {
- connDamage = newDamageAdaptor(conn)
- conn = connDamage
- }
-
- if test.sendPrefix != "" {
- if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
- return err
- }
- }
-
- var tlsConn *Conn
- if test.testType == clientTest {
- if test.protocol == dtls {
- tlsConn = DTLSServer(conn, config)
- } else {
- tlsConn = Server(conn, config)
- }
- } else {
- config.InsecureSkipVerify = true
- if test.protocol == dtls {
- tlsConn = DTLSClient(conn, config)
- } else {
- tlsConn = Client(conn, config)
- }
- }
- defer tlsConn.Close()
-
- if err := tlsConn.Handshake(); err != nil {
- return err
- }
-
- // TODO(davidben): move all per-connection expectations into a dedicated
- // expectations struct that can be specified separately for the two
- // legs.
- expectedVersion := test.expectedVersion
- if isResume && test.expectedResumeVersion != 0 {
- expectedVersion = test.expectedResumeVersion
- }
- connState := tlsConn.ConnectionState()
- if vers := connState.Version; expectedVersion != 0 && vers != expectedVersion {
- return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
- }
-
- if cipher := connState.CipherSuite; test.expectedCipher != 0 && cipher != test.expectedCipher {
- return fmt.Errorf("got cipher %x, expected %x", cipher, test.expectedCipher)
- }
- if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
- return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
- }
-
- if test.expectChannelID {
- channelID := connState.ChannelID
- if channelID == nil {
- return fmt.Errorf("no channel ID negotiated")
- }
- if channelID.Curve != channelIDKey.Curve ||
- channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
- channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
- return fmt.Errorf("incorrect channel ID")
- }
- }
-
- if expected := test.expectedNextProto; expected != "" {
- if actual := connState.NegotiatedProtocol; actual != expected {
- return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
- }
- }
-
- if test.expectedNextProtoType != 0 {
- if (test.expectedNextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
- return fmt.Errorf("next proto type mismatch")
- }
- }
-
- if p := connState.SRTPProtectionProfile; p != test.expectedSRTPProtectionProfile {
- return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, test.expectedSRTPProtectionProfile)
- }
-
- if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
- return fmt.Errorf("OCSP Response mismatch")
- }
-
- if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
- return fmt.Errorf("SCT list mismatch")
- }
-
- if expected := test.expectedClientCertSignatureHash; expected != 0 && expected != connState.ClientCertSignatureHash {
- return fmt.Errorf("expected client to sign handshake with hash %d, but got %d", expected, connState.ClientCertSignatureHash)
- }
-
- if test.exportKeyingMaterial > 0 {
- actual := make([]byte, test.exportKeyingMaterial)
- if _, err := io.ReadFull(tlsConn, actual); err != nil {
- return err
- }
- expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
- if err != nil {
- return err
- }
- if !bytes.Equal(actual, expected) {
- return fmt.Errorf("keying material mismatch")
- }
- }
-
- if test.testTLSUnique {
- var peersValue [12]byte
- if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
- return err
- }
- expected := tlsConn.ConnectionState().TLSUnique
- if !bytes.Equal(peersValue[:], expected) {
- return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
- }
- }
-
- if test.shimWritesFirst {
- var buf [5]byte
- _, err := io.ReadFull(tlsConn, buf[:])
- if err != nil {
- return err
- }
- if string(buf[:]) != "hello" {
- return fmt.Errorf("bad initial message")
- }
- }
-
- for i := 0; i < test.sendEmptyRecords; i++ {
- tlsConn.Write(nil)
- }
-
- for i := 0; i < test.sendWarningAlerts; i++ {
- tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
- }
-
- if test.renegotiate {
- if test.renegotiateCiphers != nil {
- config.CipherSuites = test.renegotiateCiphers
- }
- if err := tlsConn.Renegotiate(); err != nil {
- return err
- }
- } else if test.renegotiateCiphers != nil {
- panic("renegotiateCiphers without renegotiate")
- }
-
- if test.damageFirstWrite {
- connDamage.setDamage(true)
- tlsConn.Write([]byte("DAMAGED WRITE"))
- connDamage.setDamage(false)
- }
-
- messageLen := test.messageLen
- if messageLen < 0 {
- if test.protocol == dtls {
- return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
- }
- // Read until EOF.
- _, err := io.Copy(ioutil.Discard, tlsConn)
- return err
- }
- if messageLen == 0 {
- messageLen = 32
- }
-
- messageCount := test.messageCount
- if messageCount == 0 {
- messageCount = 1
- }
-
- for j := 0; j < messageCount; j++ {
- testMessage := make([]byte, messageLen)
- for i := range testMessage {
- testMessage[i] = 0x42 ^ byte(j)
- }
- tlsConn.Write(testMessage)
-
- for i := 0; i < test.sendEmptyRecords; i++ {
- tlsConn.Write(nil)
- }
-
- for i := 0; i < test.sendWarningAlerts; i++ {
- tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
- }
-
- if test.shimShutsDown || test.expectMessageDropped {
- // The shim will not respond.
- continue
- }
-
- buf := make([]byte, len(testMessage))
- if test.protocol == dtls {
- bufTmp := make([]byte, len(buf)+1)
- n, err := tlsConn.Read(bufTmp)
- if err != nil {
- return err
- }
- if n != len(buf) {
- return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
- }
- copy(buf, bufTmp)
- } else {
- _, err := io.ReadFull(tlsConn, buf)
- if err != nil {
- return err
- }
- }
-
- for i, v := range buf {
- if v != testMessage[i]^0xff {
- return fmt.Errorf("bad reply contents at byte %d", i)
- }
- }
- }
-
- return nil
-}
-
-func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
- valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
- if dbAttach {
- valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
- }
- valgrindArgs = append(valgrindArgs, path)
- valgrindArgs = append(valgrindArgs, args...)
-
- return exec.Command("valgrind", valgrindArgs...)
-}
-
-func gdbOf(path string, args ...string) *exec.Cmd {
- xtermArgs := []string{"-e", "gdb", "--args"}
- xtermArgs = append(xtermArgs, path)
- xtermArgs = append(xtermArgs, args...)
-
- return exec.Command("xterm", xtermArgs...)
-}
-
-type moreMallocsError struct{}
-
-func (moreMallocsError) Error() string {
- return "child process did not exhaust all allocation calls"
-}
-
-var errMoreMallocs = moreMallocsError{}
-
-// accept accepts a connection from listener, unless waitChan signals a process
-// exit first.
-func acceptOrWait(listener net.Listener, waitChan chan error) (net.Conn, error) {
- type connOrError struct {
- conn net.Conn
- err error
- }
- connChan := make(chan connOrError, 1)
- go func() {
- conn, err := listener.Accept()
- connChan <- connOrError{conn, err}
- close(connChan)
- }()
- select {
- case result := <-connChan:
- return result.conn, result.err
- case childErr := <-waitChan:
- waitChan <- childErr
- return nil, fmt.Errorf("child exited early: %s", childErr)
- }
-}
-
-func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
- if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
- panic("Error expected without shouldFail in " + test.name)
- }
-
- if test.expectResumeRejected && !test.resumeSession {
- panic("expectResumeRejected without resumeSession in " + test.name)
- }
-
- if test.testType != clientTest && test.expectedClientCertSignatureHash != 0 {
- panic("expectedClientCertSignatureHash non-zero with serverTest in " + test.name)
- }
-
- listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
- if err != nil {
- panic(err)
- }
- defer func() {
- if listener != nil {
- listener.Close()
- }
- }()
-
- flags := []string{"-port", strconv.Itoa(listener.Addr().(*net.TCPAddr).Port)}
- if test.testType == serverTest {
- flags = append(flags, "-server")
-
- flags = append(flags, "-key-file")
- if test.keyFile == "" {
- flags = append(flags, path.Join(*resourceDir, rsaKeyFile))
- } else {
- flags = append(flags, path.Join(*resourceDir, test.keyFile))
- }
-
- flags = append(flags, "-cert-file")
- if test.certFile == "" {
- flags = append(flags, path.Join(*resourceDir, rsaCertificateFile))
- } else {
- flags = append(flags, path.Join(*resourceDir, test.certFile))
- }
- }
-
- if test.digestPrefs != "" {
- flags = append(flags, "-digest-prefs")
- flags = append(flags, test.digestPrefs)
- }
-
- if test.protocol == dtls {
- flags = append(flags, "-dtls")
- }
-
- if test.resumeSession {
- flags = append(flags, "-resume")
- }
-
- if test.shimWritesFirst {
- flags = append(flags, "-shim-writes-first")
- }
-
- if test.shimShutsDown {
- flags = append(flags, "-shim-shuts-down")
- }
-
- if test.exportKeyingMaterial > 0 {
- flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
- flags = append(flags, "-export-label", test.exportLabel)
- flags = append(flags, "-export-context", test.exportContext)
- if test.useExportContext {
- flags = append(flags, "-use-export-context")
- }
- }
- if test.expectResumeRejected {
- flags = append(flags, "-expect-session-miss")
- }
-
- if test.testTLSUnique {
- flags = append(flags, "-tls-unique")
- }
-
- flags = append(flags, test.flags...)
-
- var shim *exec.Cmd
- if *useValgrind {
- shim = valgrindOf(false, shimPath, flags...)
- } else if *useGDB {
- shim = gdbOf(shimPath, flags...)
- } else {
- shim = exec.Command(shimPath, flags...)
- }
- shim.Stdin = os.Stdin
- var stdoutBuf, stderrBuf bytes.Buffer
- shim.Stdout = &stdoutBuf
- shim.Stderr = &stderrBuf
- if mallocNumToFail >= 0 {
- shim.Env = os.Environ()
- shim.Env = append(shim.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
- if *mallocTestDebug {
- shim.Env = append(shim.Env, "MALLOC_BREAK_ON_FAIL=1")
- }
- shim.Env = append(shim.Env, "_MALLOC_CHECK=1")
- }
-
- if err := shim.Start(); err != nil {
- panic(err)
- }
- waitChan := make(chan error, 1)
- go func() { waitChan <- shim.Wait() }()
-
- config := test.config
- if !test.noSessionCache {
- config.ClientSessionCache = NewLRUClientSessionCache(1)
- config.ServerSessionCache = NewLRUServerSessionCache(1)
- }
- if test.testType == clientTest {
- if len(config.Certificates) == 0 {
- config.Certificates = []Certificate{getRSACertificate()}
- }
- } else {
- // Supply a ServerName to ensure a constant session cache key,
- // rather than falling back to net.Conn.RemoteAddr.
- if len(config.ServerName) == 0 {
- config.ServerName = "test"
- }
- }
-
- conn, err := acceptOrWait(listener, waitChan)
- if err == nil {
- err = doExchange(test, &config, conn, false /* not a resumption */)
- conn.Close()
- }
-
- if err == nil && test.resumeSession {
- var resumeConfig Config
- if test.resumeConfig != nil {
- resumeConfig = *test.resumeConfig
- if len(resumeConfig.ServerName) == 0 {
- resumeConfig.ServerName = config.ServerName
- }
- if len(resumeConfig.Certificates) == 0 {
- resumeConfig.Certificates = []Certificate{getRSACertificate()}
- }
- if test.newSessionsOnResume {
- if !test.noSessionCache {
- resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
- resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
- }
- } else {
- resumeConfig.SessionTicketKey = config.SessionTicketKey
- resumeConfig.ClientSessionCache = config.ClientSessionCache
- resumeConfig.ServerSessionCache = config.ServerSessionCache
- }
- } else {
- resumeConfig = config
- }
- var connResume net.Conn
- connResume, err = acceptOrWait(listener, waitChan)
- if err == nil {
- err = doExchange(test, &resumeConfig, connResume, true /* resumption */)
- connResume.Close()
- }
- }
-
- // Close the listener now. This is to avoid hangs should the shim try to
- // open more connections than expected.
- listener.Close()
- listener = nil
-
- childErr := <-waitChan
- if exitError, ok := childErr.(*exec.ExitError); ok {
- if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
- return errMoreMallocs
- }
- }
-
- stdout := string(stdoutBuf.Bytes())
- stderr := string(stderrBuf.Bytes())
- failed := err != nil || childErr != nil
- correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
- localError := "none"
- if err != nil {
- localError = err.Error()
- }
- if len(test.expectedLocalError) != 0 {
- correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
- }
-
- if failed != test.shouldFail || failed && !correctFailure {
- childError := "none"
- if childErr != nil {
- childError = childErr.Error()
- }
-
- var msg string
- switch {
- case failed && !test.shouldFail:
- msg = "unexpected failure"
- case !failed && test.shouldFail:
- msg = "unexpected success"
- case failed && !correctFailure:
- msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
- default:
- panic("internal error")
- }
-
- return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, stdout, stderr)
- }
-
- if !*useValgrind && !failed && len(stderr) > 0 {
- println(stderr)
- }
-
- return nil
-}
-
-var tlsVersions = []struct {
- name string
- version uint16
- flag string
- hasDTLS bool
-}{
- {"SSL3", VersionSSL30, "-no-ssl3", false},
- {"TLS1", VersionTLS10, "-no-tls1", true},
- {"TLS11", VersionTLS11, "-no-tls11", false},
- {"TLS12", VersionTLS12, "-no-tls12", true},
-}
-
-var testCipherSuites = []struct {
- name string
- id uint16
-}{
- {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
- {"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
- {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
- {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
- {"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
- {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
- {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
- {"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
- {"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
- {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
- {"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
- {"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
- {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
- {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
- {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
- {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
- {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
- {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
- {"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
- {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
- {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
- {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
- {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
- {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
- {"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
- {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
- {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
- {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
- {"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
- {"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
- {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
- {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
- {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
- {"NULL-SHA", TLS_RSA_WITH_NULL_SHA},
-}
-
-func hasComponent(suiteName, component string) bool {
- return strings.Contains("-"+suiteName+"-", "-"+component+"-")
-}
-
-func isTLS12Only(suiteName string) bool {
- return hasComponent(suiteName, "GCM") ||
- hasComponent(suiteName, "SHA256") ||
- hasComponent(suiteName, "SHA384") ||
- hasComponent(suiteName, "POLY1305")
-}
-
-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 {
- panic("failed to parse hex number 0x" + hex)
- }
- return ret
-}
-
-func addBasicTests() {
- basicTests := []testCase{
- {
- name: "BadRSASignature",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- InvalidSKXSignature: true,
- },
- },
- shouldFail: true,
- expectedError: ":BAD_SIGNATURE:",
- },
- {
- name: "BadECDSASignature",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- InvalidSKXSignature: true,
- },
- Certificates: []Certificate{getECDSACertificate()},
- },
- shouldFail: true,
- expectedError: ":BAD_SIGNATURE:",
- },
- {
- testType: serverTest,
- name: "BadRSASignature-ClientAuth",
- config: Config{
- Bugs: ProtocolBugs{
- InvalidCertVerifySignature: true,
- },
- Certificates: []Certificate{getRSACertificate()},
- },
- shouldFail: true,
- expectedError: ":BAD_SIGNATURE:",
- flags: []string{"-require-any-client-certificate"},
- },
- {
- testType: serverTest,
- name: "BadECDSASignature-ClientAuth",
- config: Config{
- Bugs: ProtocolBugs{
- InvalidCertVerifySignature: true,
- },
- Certificates: []Certificate{getECDSACertificate()},
- },
- shouldFail: true,
- expectedError: ":BAD_SIGNATURE:",
- flags: []string{"-require-any-client-certificate"},
- },
- {
- name: "BadECDSACurve",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- InvalidSKXCurve: true,
- },
- Certificates: []Certificate{getECDSACertificate()},
- },
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- },
- {
- testType: serverTest,
- name: "BadRSAVersion",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
- Bugs: ProtocolBugs{
- RsaClientKeyExchangeVersion: VersionTLS11,
- },
- },
- shouldFail: true,
- expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
- },
- {
- name: "NoFallbackSCSV",
- config: Config{
- Bugs: ProtocolBugs{
- FailIfNotFallbackSCSV: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "no fallback SCSV found",
- },
- {
- name: "SendFallbackSCSV",
- config: Config{
- Bugs: ProtocolBugs{
- FailIfNotFallbackSCSV: true,
- },
- },
- flags: []string{"-fallback-scsv"},
- },
- {
- name: "ClientCertificateTypes",
- config: Config{
- ClientAuth: RequestClientCert,
- ClientCertificateTypes: []byte{
- CertTypeDSSSign,
- CertTypeRSASign,
- CertTypeECDSASign,
- },
- },
- flags: []string{
- "-expect-certificate-types",
- base64.StdEncoding.EncodeToString([]byte{
- CertTypeDSSSign,
- CertTypeRSASign,
- CertTypeECDSASign,
- }),
- },
- },
- {
- name: "NoClientCertificate",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- },
- shouldFail: true,
- expectedLocalError: "client didn't provide a certificate",
- },
- {
- name: "UnauthenticatedECDH",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- UnauthenticatedECDH: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- },
- {
- name: "SkipCertificateStatus",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- SkipCertificateStatus: true,
- },
- },
- flags: []string{
- "-enable-ocsp-stapling",
- },
- },
- {
- name: "SkipServerKeyExchange",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- SkipServerKeyExchange: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- },
- {
- name: "SkipChangeCipherSpec-Client",
- config: Config{
- Bugs: ProtocolBugs{
- SkipChangeCipherSpec: true,
- },
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "SkipChangeCipherSpec-Server",
- config: Config{
- Bugs: ProtocolBugs{
- SkipChangeCipherSpec: true,
- },
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "SkipChangeCipherSpec-Server-NPN",
- config: Config{
- NextProtos: []string{"bar"},
- Bugs: ProtocolBugs{
- SkipChangeCipherSpec: true,
- },
- },
- flags: []string{
- "-advertise-npn", "\x03foo\x03bar\x03baz",
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- name: "FragmentAcrossChangeCipherSpec-Client",
- config: Config{
- Bugs: ProtocolBugs{
- FragmentAcrossChangeCipherSpec: true,
- },
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "FragmentAcrossChangeCipherSpec-Server",
- config: Config{
- Bugs: ProtocolBugs{
- FragmentAcrossChangeCipherSpec: true,
- },
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "FragmentAcrossChangeCipherSpec-Server-NPN",
- config: Config{
- NextProtos: []string{"bar"},
- Bugs: ProtocolBugs{
- FragmentAcrossChangeCipherSpec: true,
- },
- },
- flags: []string{
- "-advertise-npn", "\x03foo\x03bar\x03baz",
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_RECORD_BEFORE_CCS:",
- },
- {
- testType: serverTest,
- name: "Alert",
- config: Config{
- Bugs: ProtocolBugs{
- SendSpuriousAlert: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
- },
- {
- protocol: dtls,
- testType: serverTest,
- name: "Alert-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendSpuriousAlert: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
- },
- {
- testType: serverTest,
- name: "FragmentAlert",
- config: Config{
- Bugs: ProtocolBugs{
- FragmentAlert: true,
- SendSpuriousAlert: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":BAD_ALERT:",
- },
- {
- protocol: dtls,
- testType: serverTest,
- name: "FragmentAlert-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- FragmentAlert: true,
- SendSpuriousAlert: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":BAD_ALERT:",
- },
- {
- testType: serverTest,
- name: "EarlyChangeCipherSpec-server-1",
- config: Config{
- Bugs: ProtocolBugs{
- EarlyChangeCipherSpec: 1,
- },
- },
- shouldFail: true,
- expectedError: ":CCS_RECEIVED_EARLY:",
- },
- {
- testType: serverTest,
- name: "EarlyChangeCipherSpec-server-2",
- config: Config{
- Bugs: ProtocolBugs{
- EarlyChangeCipherSpec: 2,
- },
- },
- shouldFail: true,
- expectedError: ":CCS_RECEIVED_EARLY:",
- },
- {
- name: "SkipNewSessionTicket",
- config: Config{
- Bugs: ProtocolBugs{
- SkipNewSessionTicket: true,
- },
- },
- shouldFail: true,
- expectedError: ":CCS_RECEIVED_EARLY:",
- },
- {
- testType: serverTest,
- name: "FallbackSCSV",
- config: Config{
- MaxVersion: VersionTLS11,
- Bugs: ProtocolBugs{
- SendFallbackSCSV: true,
- },
- },
- shouldFail: true,
- expectedError: ":INAPPROPRIATE_FALLBACK:",
- },
- {
- testType: serverTest,
- name: "FallbackSCSV-VersionMatch",
- config: Config{
- Bugs: ProtocolBugs{
- SendFallbackSCSV: true,
- },
- },
- },
- {
- testType: serverTest,
- name: "FragmentedClientVersion",
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: 1,
- FragmentClientVersion: true,
- },
- },
- expectedVersion: VersionTLS12,
- },
- {
- testType: serverTest,
- name: "MinorVersionTolerance",
- config: Config{
- Bugs: ProtocolBugs{
- SendClientVersion: 0x03ff,
- },
- },
- expectedVersion: VersionTLS12,
- },
- {
- testType: serverTest,
- name: "MajorVersionTolerance",
- config: Config{
- Bugs: ProtocolBugs{
- SendClientVersion: 0x0400,
- },
- },
- expectedVersion: VersionTLS12,
- },
- {
- testType: serverTest,
- name: "VersionTooLow",
- config: Config{
- Bugs: ProtocolBugs{
- SendClientVersion: 0x0200,
- },
- },
- shouldFail: true,
- expectedError: ":UNSUPPORTED_PROTOCOL:",
- },
- {
- testType: serverTest,
- name: "HttpGET",
- sendPrefix: "GET / HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTP_REQUEST:",
- },
- {
- testType: serverTest,
- name: "HttpPOST",
- sendPrefix: "POST / HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTP_REQUEST:",
- },
- {
- testType: serverTest,
- name: "HttpHEAD",
- sendPrefix: "HEAD / HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTP_REQUEST:",
- },
- {
- testType: serverTest,
- name: "HttpPUT",
- sendPrefix: "PUT / HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTP_REQUEST:",
- },
- {
- testType: serverTest,
- name: "HttpCONNECT",
- sendPrefix: "CONNECT www.google.com:443 HTTP/1.0\n",
- shouldFail: true,
- expectedError: ":HTTPS_PROXY_REQUEST:",
- },
- {
- testType: serverTest,
- name: "Garbage",
- sendPrefix: "blah",
- shouldFail: true,
- expectedError: ":WRONG_VERSION_NUMBER:",
- },
- {
- name: "SkipCipherVersionCheck",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- MaxVersion: VersionTLS11,
- Bugs: ProtocolBugs{
- SkipCipherVersionCheck: true,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_CIPHER_RETURNED:",
- },
- {
- name: "RSAEphemeralKey",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- Bugs: ProtocolBugs{
- RSAEphemeralKey: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- },
- {
- name: "DisableEverything",
- flags: []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
- shouldFail: true,
- expectedError: ":WRONG_SSL_VERSION:",
- },
- {
- protocol: dtls,
- name: "DisableEverything-DTLS",
- flags: []string{"-no-tls12", "-no-tls1"},
- shouldFail: true,
- expectedError: ":WRONG_SSL_VERSION:",
- },
- {
- name: "NoSharedCipher",
- config: Config{
- CipherSuites: []uint16{},
- },
- shouldFail: true,
- expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
- },
- {
- protocol: dtls,
- testType: serverTest,
- name: "MTU",
- config: Config{
- Bugs: ProtocolBugs{
- MaxPacketLength: 256,
- },
- },
- flags: []string{"-mtu", "256"},
- },
- {
- protocol: dtls,
- testType: serverTest,
- name: "MTUExceeded",
- config: Config{
- Bugs: ProtocolBugs{
- MaxPacketLength: 255,
- },
- },
- flags: []string{"-mtu", "256"},
- shouldFail: true,
- expectedLocalError: "dtls: exceeded maximum packet length",
- },
- {
- name: "CertMismatchRSA",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- Certificates: []Certificate{getECDSACertificate()},
- Bugs: ProtocolBugs{
- SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_CERTIFICATE_TYPE:",
- },
- {
- name: "CertMismatchECDSA",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Certificates: []Certificate{getRSACertificate()},
- Bugs: ProtocolBugs{
- SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_CERTIFICATE_TYPE:",
- },
- {
- name: "EmptyCertificateList",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- EmptyCertificateList: true,
- },
- },
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- },
- {
- name: "TLSFatalBadPackets",
- damageFirstWrite: true,
- shouldFail: true,
- expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
- },
- {
- protocol: dtls,
- name: "DTLSIgnoreBadPackets",
- damageFirstWrite: true,
- },
- {
- protocol: dtls,
- name: "DTLSIgnoreBadPackets-Async",
- damageFirstWrite: true,
- flags: []string{"-async"},
- },
- {
- name: "AppDataBeforeHandshake",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataBeforeHandshake: []byte("TEST MESSAGE"),
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- name: "AppDataBeforeHandshake-Empty",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataBeforeHandshake: []byte{},
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- protocol: dtls,
- name: "AppDataBeforeHandshake-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataBeforeHandshake: []byte("TEST MESSAGE"),
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- protocol: dtls,
- name: "AppDataBeforeHandshake-DTLS-Empty",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataBeforeHandshake: []byte{},
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- name: "AppDataAfterChangeCipherSpec",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
- },
- },
- shouldFail: true,
- expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
- },
- {
- name: "AppDataAfterChangeCipherSpec-Empty",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataAfterChangeCipherSpec: []byte{},
- },
- },
- shouldFail: true,
- expectedError: ":DATA_BETWEEN_CCS_AND_FINISHED:",
- },
- {
- protocol: dtls,
- name: "AppDataAfterChangeCipherSpec-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
- },
- },
- // BoringSSL's DTLS implementation will drop the out-of-order
- // application data.
- },
- {
- protocol: dtls,
- name: "AppDataAfterChangeCipherSpec-DTLS-Empty",
- config: Config{
- Bugs: ProtocolBugs{
- AppDataAfterChangeCipherSpec: []byte{},
- },
- },
- // BoringSSL's DTLS implementation will drop the out-of-order
- // application data.
- },
- {
- name: "AlertAfterChangeCipherSpec",
- config: Config{
- Bugs: ProtocolBugs{
- AlertAfterChangeCipherSpec: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
- },
- {
- protocol: dtls,
- name: "AlertAfterChangeCipherSpec-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- AlertAfterChangeCipherSpec: alertRecordOverflow,
- },
- },
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
- },
- {
- protocol: dtls,
- name: "ReorderHandshakeFragments-Small-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- ReorderHandshakeFragments: true,
- // Small enough that every handshake message is
- // fragmented.
- MaxHandshakeRecordLength: 2,
- },
- },
- },
- {
- protocol: dtls,
- name: "ReorderHandshakeFragments-Large-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- ReorderHandshakeFragments: true,
- // Large enough that no handshake message is
- // fragmented.
- MaxHandshakeRecordLength: 2048,
- },
- },
- },
- {
- protocol: dtls,
- name: "MixCompleteMessageWithFragments-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- ReorderHandshakeFragments: true,
- MixCompleteMessageWithFragments: true,
- MaxHandshakeRecordLength: 2,
- },
- },
- },
- {
- name: "SendInvalidRecordType",
- config: Config{
- Bugs: ProtocolBugs{
- SendInvalidRecordType: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- protocol: dtls,
- name: "SendInvalidRecordType-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendInvalidRecordType: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- name: "FalseStart-SkipServerSecondLeg",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- SkipNewSessionTicket: true,
- SkipChangeCipherSpec: true,
- SkipFinished: true,
- ExpectFalseStart: true,
- },
- },
- flags: []string{
- "-false-start",
- "-handshake-never-done",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- name: "FalseStart-SkipServerSecondLeg-Implicit",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- SkipNewSessionTicket: true,
- SkipChangeCipherSpec: true,
- SkipFinished: true,
- },
- },
- flags: []string{
- "-implicit-handshake",
- "-false-start",
- "-handshake-never-done",
- "-advertise-alpn", "\x03foo",
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
- },
- {
- testType: serverTest,
- name: "FailEarlyCallback",
- flags: []string{"-fail-early-callback"},
- shouldFail: true,
- expectedError: ":CONNECTION_REJECTED:",
- expectedLocalError: "remote error: access denied",
- },
- {
- name: "WrongMessageType",
- config: Config{
- Bugs: ProtocolBugs{
- WrongCertificateMessageType: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- expectedLocalError: "remote error: unexpected message",
- },
- {
- protocol: dtls,
- name: "WrongMessageType-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- WrongCertificateMessageType: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- expectedLocalError: "remote error: unexpected message",
- },
- {
- protocol: dtls,
- name: "FragmentMessageTypeMismatch-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: 2,
- FragmentMessageTypeMismatch: true,
- },
- },
- shouldFail: true,
- expectedError: ":FRAGMENT_MISMATCH:",
- },
- {
- protocol: dtls,
- name: "FragmentMessageLengthMismatch-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: 2,
- FragmentMessageLengthMismatch: true,
- },
- },
- shouldFail: true,
- expectedError: ":FRAGMENT_MISMATCH:",
- },
- {
- protocol: dtls,
- name: "SplitFragments-Header-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SplitFragments: 2,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_MESSAGE:",
- },
- {
- protocol: dtls,
- name: "SplitFragments-Boundary-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SplitFragments: dtlsRecordHeaderLen,
- },
- },
- shouldFail: true,
- expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
- },
- {
- protocol: dtls,
- name: "SplitFragments-Body-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SplitFragments: dtlsRecordHeaderLen + 1,
- },
- },
- shouldFail: true,
- expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
- },
- {
- protocol: dtls,
- name: "SendEmptyFragments-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendEmptyFragments: true,
- },
- },
- },
- {
- name: "UnsupportedCipherSuite",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
- Bugs: ProtocolBugs{
- IgnorePeerCipherPreferences: true,
- },
- },
- flags: []string{"-cipher", "DEFAULT:!RC4"},
- shouldFail: true,
- expectedError: ":WRONG_CIPHER_RETURNED:",
- },
- {
- name: "UnsupportedCurve",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- // BoringSSL implements P-224 but doesn't enable it by
- // default.
- CurvePreferences: []CurveID{CurveP224},
- Bugs: ProtocolBugs{
- IgnorePeerCurvePreferences: true,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- },
- {
- name: "BadFinished",
- config: Config{
- Bugs: ProtocolBugs{
- BadFinished: true,
- },
- },
- shouldFail: true,
- expectedError: ":DIGEST_CHECK_FAILED:",
- },
- {
- name: "FalseStart-BadFinished",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- BadFinished: true,
- ExpectFalseStart: true,
- },
- },
- flags: []string{
- "-false-start",
- "-handshake-never-done",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":DIGEST_CHECK_FAILED:",
- },
- {
- name: "NoFalseStart-NoALPN",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- AlertBeforeFalseStartTest: alertAccessDenied,
- },
- },
- flags: []string{
- "-false-start",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
- expectedLocalError: "tls: peer did not false start: EOF",
- },
- {
- name: "NoFalseStart-NoAEAD",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- AlertBeforeFalseStartTest: alertAccessDenied,
- },
- },
- flags: []string{
- "-false-start",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
- expectedLocalError: "tls: peer did not false start: EOF",
- },
- {
- name: "NoFalseStart-RSA",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- AlertBeforeFalseStartTest: alertAccessDenied,
- },
- },
- flags: []string{
- "-false-start",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
- expectedLocalError: "tls: peer did not false start: EOF",
- },
- {
- name: "NoFalseStart-DHE_RSA",
- config: Config{
- CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- AlertBeforeFalseStartTest: alertAccessDenied,
- },
- },
- flags: []string{
- "-false-start",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- shouldFail: true,
- expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
- expectedLocalError: "tls: peer did not false start: EOF",
- },
- {
- testType: serverTest,
- name: "NoSupportedCurves",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- NoSupportedCurves: true,
- },
- },
- },
- {
- testType: serverTest,
- name: "NoCommonCurves",
- config: Config{
- CipherSuites: []uint16{
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
- },
- CurvePreferences: []CurveID{CurveP224},
- },
- expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
- },
- {
- protocol: dtls,
- name: "SendSplitAlert-Sync",
- config: Config{
- Bugs: ProtocolBugs{
- SendSplitAlert: true,
- },
- },
- },
- {
- protocol: dtls,
- name: "SendSplitAlert-Async",
- config: Config{
- Bugs: ProtocolBugs{
- SendSplitAlert: true,
- },
- },
- flags: []string{"-async"},
- },
- {
- protocol: dtls,
- name: "PackDTLSHandshake",
- config: Config{
- Bugs: ProtocolBugs{
- MaxHandshakeRecordLength: 2,
- PackHandshakeFragments: 20,
- PackHandshakeRecords: 200,
- },
- },
- },
- {
- testType: serverTest,
- protocol: dtls,
- name: "NoRC4-DTLS",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
- Bugs: ProtocolBugs{
- EnableAllCiphersInDTLS: true,
- },
- },
- shouldFail: true,
- expectedError: ":NO_SHARED_CIPHER:",
- },
- {
- name: "SendEmptyRecords-Pass",
- sendEmptyRecords: 32,
- },
- {
- name: "SendEmptyRecords",
- sendEmptyRecords: 33,
- shouldFail: true,
- expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
- },
- {
- name: "SendEmptyRecords-Async",
- sendEmptyRecords: 33,
- flags: []string{"-async"},
- shouldFail: true,
- expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
- },
- {
- name: "SendWarningAlerts-Pass",
- sendWarningAlerts: 4,
- },
- {
- protocol: dtls,
- name: "SendWarningAlerts-DTLS-Pass",
- sendWarningAlerts: 4,
- },
- {
- name: "SendWarningAlerts",
- sendWarningAlerts: 5,
- shouldFail: true,
- expectedError: ":TOO_MANY_WARNING_ALERTS:",
- },
- {
- name: "SendWarningAlerts-Async",
- sendWarningAlerts: 5,
- flags: []string{"-async"},
- shouldFail: true,
- expectedError: ":TOO_MANY_WARNING_ALERTS:",
- },
- {
- name: "EmptySessionID",
- config: Config{
- SessionTicketsDisabled: true,
- },
- noSessionCache: true,
- flags: []string{"-expect-no-session"},
- },
- {
- name: "Unclean-Shutdown",
- config: Config{
- Bugs: ProtocolBugs{
- NoCloseNotify: true,
- ExpectCloseNotify: true,
- },
- },
- shimShutsDown: true,
- flags: []string{"-check-close-notify"},
- shouldFail: true,
- expectedError: "Unexpected SSL_shutdown result: -1 != 1",
- },
- {
- name: "Unclean-Shutdown-Ignored",
- config: Config{
- Bugs: ProtocolBugs{
- NoCloseNotify: true,
- },
- },
- shimShutsDown: true,
- },
- {
- name: "LargePlaintext",
- config: Config{
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- messageLen: maxPlaintext + 1,
- shouldFail: true,
- expectedError: ":DATA_LENGTH_TOO_LONG:",
- },
- {
- protocol: dtls,
- name: "LargePlaintext-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- messageLen: maxPlaintext + 1,
- shouldFail: true,
- expectedError: ":DATA_LENGTH_TOO_LONG:",
- },
- {
- name: "LargeCiphertext",
- config: Config{
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- messageLen: maxPlaintext * 2,
- shouldFail: true,
- expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
- },
- {
- protocol: dtls,
- name: "LargeCiphertext-DTLS",
- config: Config{
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- messageLen: maxPlaintext * 2,
- // Unlike the other four cases, DTLS drops records which
- // are invalid before authentication, so the connection
- // does not fail.
- expectMessageDropped: true,
- },
- }
- testCases = append(testCases, basicTests...)
-}
-
-func addCipherSuiteTests() {
- for _, suite := range testCipherSuites {
- const psk = "12345"
- const pskIdentity = "luggage combo"
-
- var cert Certificate
- var certFile string
- var keyFile string
- if hasComponent(suite.name, "ECDSA") {
- cert = getECDSACertificate()
- certFile = ecdsaCertificateFile
- keyFile = ecdsaKeyFile
- } else {
- cert = getRSACertificate()
- certFile = rsaCertificateFile
- keyFile = rsaKeyFile
- }
-
- var flags []string
- if hasComponent(suite.name, "PSK") {
- flags = append(flags,
- "-psk", psk,
- "-psk-identity", pskIdentity)
- }
- if hasComponent(suite.name, "NULL") {
- // NULL ciphers must be explicitly enabled.
- flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
- }
-
- for _, ver := range tlsVersions {
- if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
- continue
- }
-
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: ver.name + "-" + suite.name + "-client",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- flags: flags,
- resumeSession: true,
- })
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: ver.name + "-" + suite.name + "-server",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- certFile: certFile,
- keyFile: keyFile,
- flags: flags,
- resumeSession: true,
- })
-
- if ver.hasDTLS && isDTLSCipher(suite.name) {
- testCases = append(testCases, testCase{
- testType: clientTest,
- protocol: dtls,
- name: "D" + ver.name + "-" + suite.name + "-client",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- flags: flags,
- resumeSession: true,
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- protocol: dtls,
- name: "D" + ver.name + "-" + suite.name + "-server",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- certFile: certFile,
- keyFile: keyFile,
- flags: flags,
- resumeSession: true,
- })
- }
- }
-
- // Ensure both TLS and DTLS accept their maximum record sizes.
- testCases = append(testCases, testCase{
- name: suite.name + "-LargeRecord",
- config: Config{
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- flags: flags,
- messageLen: maxPlaintext,
- })
- testCases = append(testCases, testCase{
- name: suite.name + "-LargeRecord-Extra",
- config: Config{
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- Bugs: ProtocolBugs{
- SendLargeRecords: true,
- },
- },
- flags: append(flags, "-microsoft-big-sslv3-buffer"),
- messageLen: maxPlaintext + 16384,
- })
- if isDTLSCipher(suite.name) {
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: suite.name + "-LargeRecord-DTLS",
- config: Config{
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- flags: flags,
- messageLen: maxPlaintext,
- })
- }
- }
-
- testCases = append(testCases, testCase{
- name: "WeakDH",
- config: Config{
- CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- // This is a 1023-bit prime number, generated
- // with:
- // openssl gendh 1023 | openssl asn1parse -i
- DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
- },
- },
- shouldFail: true,
- expectedError: "BAD_DH_P_LENGTH",
- })
-
- // versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
- // 1.1 specific cipher suite settings. A server is setup with the given
- // cipher lists and then a connection is made for each member of
- // expectations. The cipher suite that the server selects must match
- // the specified one.
- var versionSpecificCiphersTest = []struct {
- ciphersDefault, ciphersTLS10, ciphersTLS11 string
- // expectations is a map from TLS version to cipher suite id.
- expectations map[uint16]uint16
- }{
- {
- // Test that the null case (where no version-specific ciphers are set)
- // works as expected.
- "RC4-SHA:AES128-SHA", // default ciphers
- "", // no ciphers specifically for TLS ≥ 1.0
- "", // no ciphers specifically for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
- },
- },
- {
- // With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
- // cipher.
- "RC4-SHA:AES128-SHA", // default
- "AES128-SHA", // these ciphers for TLS ≥ 1.0
- "", // no ciphers specifically for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
- },
- },
- {
- // With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
- // cipher.
- "RC4-SHA:AES128-SHA", // default
- "", // no ciphers specifically for TLS ≥ 1.0
- "AES128-SHA", // these ciphers for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
- },
- },
- {
- // With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
- // mask ciphers_tls10 for TLS 1.1 and 1.2.
- "RC4-SHA:AES128-SHA", // default
- "AES128-SHA", // these ciphers for TLS ≥ 1.0
- "AES256-SHA", // these ciphers for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
- VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
- },
- },
- }
-
- for i, test := range versionSpecificCiphersTest {
- for version, expectedCipherSuite := range test.expectations {
- flags := []string{"-cipher", test.ciphersDefault}
- if len(test.ciphersTLS10) > 0 {
- flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
- }
- if len(test.ciphersTLS11) > 0 {
- flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
- }
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
- config: Config{
- MaxVersion: version,
- MinVersion: version,
- CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
- },
- flags: flags,
- expectedCipher: expectedCipherSuite,
- })
- }
- }
-}
-
-func addBadECDSASignatureTests() {
- for badR := BadValue(1); badR < NumBadValues; badR++ {
- for badS := BadValue(1); badS < NumBadValues; badS++ {
- testCases = append(testCases, testCase{
- name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
- Certificates: []Certificate{getECDSACertificate()},
- Bugs: ProtocolBugs{
- BadECDSAR: badR,
- BadECDSAS: badS,
- },
- },
- shouldFail: true,
- expectedError: "SIGNATURE",
- })
- }
- }
-}
-
-func addCBCPaddingTests() {
- testCases = append(testCases, testCase{
- name: "MaxCBCPadding",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- Bugs: ProtocolBugs{
- MaxPadding: true,
- },
- },
- messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
- })
- testCases = append(testCases, testCase{
- name: "BadCBCPadding",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- Bugs: ProtocolBugs{
- PaddingFirstByteBad: true,
- },
- },
- shouldFail: true,
- expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
- })
- // OpenSSL previously had an issue where the first byte of padding in
- // 255 bytes of padding wasn't checked.
- testCases = append(testCases, testCase{
- name: "BadCBCPadding255",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- Bugs: ProtocolBugs{
- MaxPadding: true,
- PaddingFirstByteBadIf255: true,
- },
- },
- messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
- shouldFail: true,
- expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
- })
-}
-
-func addCBCSplittingTests() {
- testCases = append(testCases, testCase{
- name: "CBCRecordSplitting",
- config: Config{
- MaxVersion: VersionTLS10,
- MinVersion: VersionTLS10,
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- },
- messageLen: -1, // read until EOF
- resumeSession: true,
- flags: []string{
- "-async",
- "-write-different-record-sizes",
- "-cbc-record-splitting",
- },
- })
- testCases = append(testCases, testCase{
- name: "CBCRecordSplittingPartialWrite",
- config: Config{
- MaxVersion: VersionTLS10,
- MinVersion: VersionTLS10,
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- },
- messageLen: -1, // read until EOF
- flags: []string{
- "-async",
- "-write-different-record-sizes",
- "-cbc-record-splitting",
- "-partial-write",
- },
- })
-}
-
-func addClientAuthTests() {
- // Add a dummy cert pool to stress certificate authority parsing.
- // TODO(davidben): Add tests that those values parse out correctly.
- certPool := x509.NewCertPool()
- cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
- if err != nil {
- panic(err)
- }
- certPool.AddCert(cert)
-
- for _, ver := range tlsVersions {
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: ver.name + "-Client-ClientAuth-RSA",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- ClientAuth: RequireAnyClientCert,
- ClientCAs: certPool,
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: ver.name + "-Server-ClientAuth-RSA",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- Certificates: []Certificate{rsaCertificate},
- },
- flags: []string{"-require-any-client-certificate"},
- })
- if ver.version != VersionSSL30 {
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: ver.name + "-Server-ClientAuth-ECDSA",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- Certificates: []Certificate{ecdsaCertificate},
- },
- flags: []string{"-require-any-client-certificate"},
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: ver.name + "-Client-ClientAuth-ECDSA",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- ClientAuth: RequireAnyClientCert,
- ClientCAs: certPool,
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
- "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
- },
- })
- }
- }
-}
-
-func addExtendedMasterSecretTests() {
- const expectEMSFlag = "-expect-extended-master-secret"
-
- for _, with := range []bool{false, true} {
- prefix := "No"
- var flags []string
- if with {
- prefix = ""
- flags = []string{expectEMSFlag}
- }
-
- for _, isClient := range []bool{false, true} {
- suffix := "-Server"
- testType := serverTest
- if isClient {
- suffix = "-Client"
- testType = clientTest
- }
-
- for _, ver := range tlsVersions {
- test := testCase{
- testType: testType,
- name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- Bugs: ProtocolBugs{
- NoExtendedMasterSecret: !with,
- RequireExtendedMasterSecret: with,
- },
- },
- flags: flags,
- shouldFail: ver.version == VersionSSL30 && with,
- }
- if test.shouldFail {
- test.expectedLocalError = "extended master secret required but not supported by peer"
- }
- testCases = append(testCases, test)
- }
- }
- }
-
- for _, isClient := range []bool{false, true} {
- for _, supportedInFirstConnection := range []bool{false, true} {
- for _, supportedInResumeConnection := range []bool{false, true} {
- boolToWord := func(b bool) string {
- if b {
- return "Yes"
- }
- return "No"
- }
- suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
- if isClient {
- suffix += "Client"
- } else {
- suffix += "Server"
- }
-
- supportedConfig := Config{
- Bugs: ProtocolBugs{
- RequireExtendedMasterSecret: true,
- },
- }
-
- noSupportConfig := Config{
- Bugs: ProtocolBugs{
- NoExtendedMasterSecret: true,
- },
- }
-
- test := testCase{
- name: "ExtendedMasterSecret-" + suffix,
- resumeSession: true,
- }
-
- if !isClient {
- test.testType = serverTest
- }
-
- if supportedInFirstConnection {
- test.config = supportedConfig
- } else {
- test.config = noSupportConfig
- }
-
- if supportedInResumeConnection {
- test.resumeConfig = &supportedConfig
- } else {
- test.resumeConfig = &noSupportConfig
- }
-
- switch suffix {
- case "YesToYes-Client", "YesToYes-Server":
- // When a session is resumed, it should
- // still be aware that its master
- // secret was generated via EMS and
- // thus it's safe to use tls-unique.
- test.flags = []string{expectEMSFlag}
- case "NoToYes-Server":
- // If an original connection did not
- // contain EMS, but a resumption
- // handshake does, then a server should
- // not resume the session.
- test.expectResumeRejected = true
- case "YesToNo-Server":
- // Resuming an EMS session without the
- // EMS extension should cause the
- // server to abort the connection.
- test.shouldFail = true
- test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
- case "NoToYes-Client":
- // A client should abort a connection
- // where the server resumed a non-EMS
- // session but echoed the EMS
- // extension.
- test.shouldFail = true
- test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
- case "YesToNo-Client":
- // A client should abort a connection
- // where the server didn't echo EMS
- // when the session used it.
- test.shouldFail = true
- test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
- }
-
- testCases = append(testCases, test)
- }
- }
- }
-}
-
-// Adds tests that try to cover the range of the handshake state machine, under
-// various conditions. Some of these are redundant with other tests, but they
-// only cover the synchronous case.
-func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
- var tests []testCase
-
- // Basic handshake, with resumption. Client and server,
- // session ID and session ticket.
- tests = append(tests, testCase{
- name: "Basic-Client",
- resumeSession: true,
- })
- tests = append(tests, testCase{
- name: "Basic-Client-RenewTicket",
- config: Config{
- Bugs: ProtocolBugs{
- RenewTicketOnResume: true,
- },
- },
- flags: []string{"-expect-ticket-renewal"},
- resumeSession: true,
- })
- tests = append(tests, testCase{
- name: "Basic-Client-NoTicket",
- config: Config{
- SessionTicketsDisabled: true,
- },
- resumeSession: true,
- })
- tests = append(tests, testCase{
- name: "Basic-Client-Implicit",
- flags: []string{"-implicit-handshake"},
- resumeSession: true,
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "Basic-Server",
- resumeSession: true,
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "Basic-Server-NoTickets",
- config: Config{
- SessionTicketsDisabled: true,
- },
- resumeSession: true,
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "Basic-Server-Implicit",
- flags: []string{"-implicit-handshake"},
- resumeSession: true,
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "Basic-Server-EarlyCallback",
- flags: []string{"-use-early-callback"},
- resumeSession: true,
- })
-
- // TLS client auth.
- tests = append(tests, testCase{
- testType: clientTest,
- name: "ClientAuth-Client",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- })
- if async {
- tests = append(tests, testCase{
- testType: clientTest,
- name: "ClientAuth-Client-AsyncKey",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- "-use-async-private-key",
- },
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "Basic-Server-RSAAsyncKey",
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- "-use-async-private-key",
- },
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "Basic-Server-ECDSAAsyncKey",
- flags: []string{
- "-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
- "-key-file", path.Join(*resourceDir, ecdsaKeyFile),
- "-use-async-private-key",
- },
- })
- }
- tests = append(tests, testCase{
- testType: serverTest,
- name: "ClientAuth-Server",
- config: Config{
- Certificates: []Certificate{rsaCertificate},
- },
- flags: []string{"-require-any-client-certificate"},
- })
-
- // No session ticket support; server doesn't send NewSessionTicket.
- tests = append(tests, testCase{
- name: "SessionTicketsDisabled-Client",
- config: Config{
- SessionTicketsDisabled: true,
- },
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "SessionTicketsDisabled-Server",
- config: Config{
- SessionTicketsDisabled: true,
- },
- })
-
- // Skip ServerKeyExchange in PSK key exchange if there's no
- // identity hint.
- tests = append(tests, testCase{
- name: "EmptyPSKHint-Client",
- config: Config{
- CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
- PreSharedKey: []byte("secret"),
- },
- flags: []string{"-psk", "secret"},
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "EmptyPSKHint-Server",
- config: Config{
- CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
- PreSharedKey: []byte("secret"),
- },
- flags: []string{"-psk", "secret"},
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "OCSPStapling-Client",
- flags: []string{
- "-enable-ocsp-stapling",
- "-expect-ocsp-response",
- base64.StdEncoding.EncodeToString(testOCSPResponse),
- "-verify-peer",
- },
- resumeSession: true,
- })
-
- tests = append(tests, testCase{
- testType: serverTest,
- name: "OCSPStapling-Server",
- expectedOCSPResponse: testOCSPResponse,
- flags: []string{
- "-ocsp-response",
- base64.StdEncoding.EncodeToString(testOCSPResponse),
- },
- resumeSession: true,
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "CertificateVerificationSucceed",
- flags: []string{
- "-verify-peer",
- },
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "CertificateVerificationFail",
- flags: []string{
- "-verify-fail",
- "-verify-peer",
- },
- shouldFail: true,
- expectedError: ":CERTIFICATE_VERIFY_FAILED:",
- })
-
- tests = append(tests, testCase{
- testType: clientTest,
- name: "CertificateVerificationSoftFail",
- flags: []string{
- "-verify-fail",
- "-expect-verify-result",
- },
- })
-
- if protocol == tls {
- tests = append(tests, testCase{
- name: "Renegotiate-Client",
- renegotiate: true,
- })
- // NPN on client and server; results in post-handshake message.
- tests = append(tests, testCase{
- name: "NPN-Client",
- config: Config{
- NextProtos: []string{"foo"},
- },
- flags: []string{"-select-next-proto", "foo"},
- expectedNextProto: "foo",
- expectedNextProtoType: npn,
- })
- tests = append(tests, testCase{
- testType: serverTest,
- name: "NPN-Server",
- config: Config{
- NextProtos: []string{"bar"},
- },
- flags: []string{
- "-advertise-npn", "\x03foo\x03bar\x03baz",
- "-expect-next-proto", "bar",
- },
- expectedNextProto: "bar",
- expectedNextProtoType: npn,
- })
-
- // TODO(davidben): Add tests for when False Start doesn't trigger.
-
- // Client does False Start and negotiates NPN.
- tests = append(tests, testCase{
- name: "FalseStart",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- },
- },
- flags: []string{
- "-false-start",
- "-select-next-proto", "foo",
- },
- shimWritesFirst: true,
- resumeSession: true,
- })
-
- // Client does False Start and negotiates ALPN.
- tests = append(tests, testCase{
- name: "FalseStart-ALPN",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- },
- },
- flags: []string{
- "-false-start",
- "-advertise-alpn", "\x03foo",
- },
- shimWritesFirst: true,
- resumeSession: true,
- })
-
- // Client does False Start but doesn't explicitly call
- // SSL_connect.
- tests = append(tests, testCase{
- name: "FalseStart-Implicit",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- },
- flags: []string{
- "-implicit-handshake",
- "-false-start",
- "-advertise-alpn", "\x03foo",
- },
- })
-
- // False Start without session tickets.
- tests = append(tests, testCase{
- name: "FalseStart-SessionTicketsDisabled",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- SessionTicketsDisabled: true,
- Bugs: ProtocolBugs{
- ExpectFalseStart: true,
- },
- },
- flags: []string{
- "-false-start",
- "-select-next-proto", "foo",
- },
- shimWritesFirst: true,
- })
-
- // Server parses a V2ClientHello.
- tests = append(tests, testCase{
- testType: serverTest,
- name: "SendV2ClientHello",
- config: Config{
- // Choose a cipher suite that does not involve
- // elliptic curves, so no extensions are
- // involved.
- CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
- Bugs: ProtocolBugs{
- SendV2ClientHello: true,
- },
- },
- })
-
- // Client sends a Channel ID.
- tests = append(tests, testCase{
- name: "ChannelID-Client",
- config: Config{
- RequestChannelID: true,
- },
- flags: []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
- resumeSession: true,
- expectChannelID: true,
- })
-
- // Server accepts a Channel ID.
- tests = append(tests, testCase{
- testType: serverTest,
- name: "ChannelID-Server",
- config: Config{
- ChannelID: channelIDKey,
- },
- flags: []string{
- "-expect-channel-id",
- base64.StdEncoding.EncodeToString(channelIDBytes),
- },
- resumeSession: true,
- expectChannelID: true,
- })
-
- // Bidirectional shutdown with the runner initiating.
- tests = append(tests, testCase{
- name: "Shutdown-Runner",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectCloseNotify: true,
- },
- },
- flags: []string{"-check-close-notify"},
- })
-
- // Bidirectional shutdown with the shim initiating. The runner,
- // in the meantime, sends garbage before the close_notify which
- // the shim must ignore.
- tests = append(tests, testCase{
- name: "Shutdown-Shim",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectCloseNotify: true,
- },
- },
- shimShutsDown: true,
- sendEmptyRecords: 1,
- sendWarningAlerts: 1,
- flags: []string{"-check-close-notify"},
- })
- } else {
- tests = append(tests, testCase{
- name: "SkipHelloVerifyRequest",
- config: Config{
- Bugs: ProtocolBugs{
- SkipHelloVerifyRequest: true,
- },
- },
- })
- }
-
- var suffix string
- var flags []string
- var maxHandshakeRecordLength int
- if protocol == dtls {
- suffix = "-DTLS"
- }
- if async {
- suffix += "-Async"
- flags = append(flags, "-async")
- } else {
- suffix += "-Sync"
- }
- if splitHandshake {
- suffix += "-SplitHandshakeRecords"
- maxHandshakeRecordLength = 1
- }
- for _, test := range tests {
- test.protocol = protocol
- test.name += suffix
- test.config.Bugs.MaxHandshakeRecordLength = maxHandshakeRecordLength
- test.flags = append(test.flags, flags...)
- testCases = append(testCases, test)
- }
-}
-
-func addDDoSCallbackTests() {
- // DDoS callback.
-
- for _, resume := range []bool{false, true} {
- suffix := "Resume"
- if resume {
- suffix = "No" + suffix
- }
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Server-DDoS-OK-" + suffix,
- flags: []string{"-install-ddos-callback"},
- resumeSession: resume,
- })
-
- failFlag := "-fail-ddos-callback"
- if resume {
- failFlag = "-fail-second-ddos-callback"
- }
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Server-DDoS-Reject-" + suffix,
- flags: []string{"-install-ddos-callback", failFlag},
- resumeSession: resume,
- shouldFail: true,
- expectedError: ":CONNECTION_REJECTED:",
- })
- }
-}
-
-func addVersionNegotiationTests() {
- for i, shimVers := range tlsVersions {
- // Assemble flags to disable all newer versions on the shim.
- var flags []string
- for _, vers := range tlsVersions[i+1:] {
- flags = append(flags, vers.flag)
- }
-
- for _, runnerVers := range tlsVersions {
- protocols := []protocol{tls}
- if runnerVers.hasDTLS && shimVers.hasDTLS {
- protocols = append(protocols, dtls)
- }
- for _, protocol := range protocols {
- expectedVersion := shimVers.version
- if runnerVers.version < shimVers.version {
- expectedVersion = runnerVers.version
- }
-
- suffix := shimVers.name + "-" + runnerVers.name
- if protocol == dtls {
- suffix += "-DTLS"
- }
-
- shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
-
- clientVers := shimVers.version
- if clientVers > VersionTLS10 {
- clientVers = VersionTLS10
- }
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: clientTest,
- name: "VersionNegotiation-Client-" + suffix,
- config: Config{
- MaxVersion: runnerVers.version,
- Bugs: ProtocolBugs{
- ExpectInitialRecordVersion: clientVers,
- },
- },
- flags: flags,
- expectedVersion: expectedVersion,
- })
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: clientTest,
- name: "VersionNegotiation-Client2-" + suffix,
- config: Config{
- MaxVersion: runnerVers.version,
- Bugs: ProtocolBugs{
- ExpectInitialRecordVersion: clientVers,
- },
- },
- flags: []string{"-max-version", shimVersFlag},
- expectedVersion: expectedVersion,
- })
-
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: serverTest,
- name: "VersionNegotiation-Server-" + suffix,
- config: Config{
- MaxVersion: runnerVers.version,
- Bugs: ProtocolBugs{
- ExpectInitialRecordVersion: expectedVersion,
- },
- },
- flags: flags,
- expectedVersion: expectedVersion,
- })
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: serverTest,
- name: "VersionNegotiation-Server2-" + suffix,
- config: Config{
- MaxVersion: runnerVers.version,
- Bugs: ProtocolBugs{
- ExpectInitialRecordVersion: expectedVersion,
- },
- },
- flags: []string{"-max-version", shimVersFlag},
- expectedVersion: expectedVersion,
- })
- }
- }
- }
-}
-
-func addMinimumVersionTests() {
- for i, shimVers := range tlsVersions {
- // Assemble flags to disable all older versions on the shim.
- var flags []string
- for _, vers := range tlsVersions[:i] {
- flags = append(flags, vers.flag)
- }
-
- for _, runnerVers := range tlsVersions {
- protocols := []protocol{tls}
- if runnerVers.hasDTLS && shimVers.hasDTLS {
- protocols = append(protocols, dtls)
- }
- for _, protocol := range protocols {
- suffix := shimVers.name + "-" + runnerVers.name
- if protocol == dtls {
- suffix += "-DTLS"
- }
- shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
-
- var expectedVersion uint16
- var shouldFail bool
- var expectedError string
- var expectedLocalError string
- if runnerVers.version >= shimVers.version {
- expectedVersion = runnerVers.version
- } else {
- shouldFail = true
- expectedError = ":UNSUPPORTED_PROTOCOL:"
- if runnerVers.version > VersionSSL30 {
- expectedLocalError = "remote error: protocol version not supported"
- } else {
- expectedLocalError = "remote error: handshake failure"
- }
- }
-
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: clientTest,
- name: "MinimumVersion-Client-" + suffix,
- config: Config{
- MaxVersion: runnerVers.version,
- },
- flags: flags,
- expectedVersion: expectedVersion,
- shouldFail: shouldFail,
- expectedError: expectedError,
- expectedLocalError: expectedLocalError,
- })
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: clientTest,
- name: "MinimumVersion-Client2-" + suffix,
- config: Config{
- MaxVersion: runnerVers.version,
- },
- flags: []string{"-min-version", shimVersFlag},
- expectedVersion: expectedVersion,
- shouldFail: shouldFail,
- expectedError: expectedError,
- expectedLocalError: expectedLocalError,
- })
-
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: serverTest,
- name: "MinimumVersion-Server-" + suffix,
- config: Config{
- MaxVersion: runnerVers.version,
- },
- flags: flags,
- expectedVersion: expectedVersion,
- shouldFail: shouldFail,
- expectedError: expectedError,
- expectedLocalError: expectedLocalError,
- })
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: serverTest,
- name: "MinimumVersion-Server2-" + suffix,
- config: Config{
- MaxVersion: runnerVers.version,
- },
- flags: []string{"-min-version", shimVersFlag},
- expectedVersion: expectedVersion,
- shouldFail: shouldFail,
- expectedError: expectedError,
- expectedLocalError: expectedLocalError,
- })
- }
- }
- }
-}
-
-func addD5BugTests() {
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "D5Bug-NoQuirk-Reject",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- SSL3RSAKeyExchange: true,
- },
- },
- shouldFail: true,
- expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "D5Bug-Quirk-Normal",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- },
- flags: []string{"-tls-d5-bug"},
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "D5Bug-Quirk-Bug",
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- SSL3RSAKeyExchange: true,
- },
- },
- flags: []string{"-tls-d5-bug"},
- })
-}
-
-func addExtensionTests() {
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "DuplicateExtensionClient",
- config: Config{
- Bugs: ProtocolBugs{
- DuplicateExtension: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "remote error: error decoding message",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "DuplicateExtensionServer",
- config: Config{
- Bugs: ProtocolBugs{
- DuplicateExtension: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "remote error: error decoding message",
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ServerNameExtensionClient",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectServerName: "example.com",
- },
- },
- flags: []string{"-host-name", "example.com"},
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ServerNameExtensionClientMismatch",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectServerName: "mismatch.com",
- },
- },
- flags: []string{"-host-name", "example.com"},
- shouldFail: true,
- expectedLocalError: "tls: unexpected server name",
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ServerNameExtensionClientMissing",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectServerName: "missing.com",
- },
- },
- shouldFail: true,
- expectedLocalError: "tls: unexpected server name",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ServerNameExtensionServer",
- config: Config{
- ServerName: "example.com",
- },
- flags: []string{"-expect-server-name", "example.com"},
- resumeSession: true,
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ALPNClient",
- config: Config{
- NextProtos: []string{"foo"},
- },
- flags: []string{
- "-advertise-alpn", "\x03foo\x03bar\x03baz",
- "-expect-alpn", "foo",
- },
- expectedNextProto: "foo",
- expectedNextProtoType: alpn,
- resumeSession: true,
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ALPNServer",
- config: Config{
- NextProtos: []string{"foo", "bar", "baz"},
- },
- flags: []string{
- "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
- "-select-alpn", "foo",
- },
- expectedNextProto: "foo",
- expectedNextProtoType: alpn,
- resumeSession: true,
- })
- // Test that the server prefers ALPN over NPN.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ALPNServer-Preferred",
- config: Config{
- NextProtos: []string{"foo", "bar", "baz"},
- },
- flags: []string{
- "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
- "-select-alpn", "foo",
- "-advertise-npn", "\x03foo\x03bar\x03baz",
- },
- expectedNextProto: "foo",
- expectedNextProtoType: alpn,
- resumeSession: true,
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ALPNServer-Preferred-Swapped",
- config: Config{
- NextProtos: []string{"foo", "bar", "baz"},
- Bugs: ProtocolBugs{
- SwapNPNAndALPN: true,
- },
- },
- flags: []string{
- "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
- "-select-alpn", "foo",
- "-advertise-npn", "\x03foo\x03bar\x03baz",
- },
- expectedNextProto: "foo",
- expectedNextProtoType: alpn,
- resumeSession: true,
- })
- var emptyString string
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ALPNClient-EmptyProtocolName",
- config: Config{
- NextProtos: []string{""},
- Bugs: ProtocolBugs{
- // A server returning an empty ALPN protocol
- // should be rejected.
- ALPNProtocol: &emptyString,
- },
- },
- flags: []string{
- "-advertise-alpn", "\x03foo",
- },
- shouldFail: true,
- expectedError: ":PARSE_TLSEXT:",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "ALPNServer-EmptyProtocolName",
- config: Config{
- // A ClientHello containing an empty ALPN protocol
- // should be rejected.
- NextProtos: []string{"foo", "", "baz"},
- },
- flags: []string{
- "-select-alpn", "foo",
- },
- shouldFail: true,
- expectedError: ":PARSE_TLSEXT:",
- })
- // Test that negotiating both NPN and ALPN is forbidden.
- testCases = append(testCases, testCase{
- name: "NegotiateALPNAndNPN",
- config: Config{
- NextProtos: []string{"foo", "bar", "baz"},
- Bugs: ProtocolBugs{
- NegotiateALPNAndNPN: true,
- },
- },
- flags: []string{
- "-advertise-alpn", "\x03foo",
- "-select-next-proto", "foo",
- },
- shouldFail: true,
- expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
- })
- testCases = append(testCases, testCase{
- name: "NegotiateALPNAndNPN-Swapped",
- config: Config{
- NextProtos: []string{"foo", "bar", "baz"},
- Bugs: ProtocolBugs{
- NegotiateALPNAndNPN: true,
- SwapNPNAndALPN: true,
- },
- },
- flags: []string{
- "-advertise-alpn", "\x03foo",
- "-select-next-proto", "foo",
- },
- shouldFail: true,
- expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
- })
- // Resume with a corrupt ticket.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "CorruptTicket",
- config: Config{
- Bugs: ProtocolBugs{
- CorruptTicket: true,
- },
- },
- resumeSession: true,
- expectResumeRejected: true,
- })
- // Test the ticket callback, with and without renewal.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TicketCallback",
- resumeSession: true,
- flags: []string{"-use-ticket-callback"},
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TicketCallback-Renew",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectNewTicket: true,
- },
- },
- flags: []string{"-use-ticket-callback", "-renew-ticket"},
- resumeSession: true,
- })
- // Resume with an oversized session id.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "OversizedSessionId",
- config: Config{
- Bugs: ProtocolBugs{
- OversizedSessionId: true,
- },
- },
- resumeSession: true,
- shouldFail: true,
- expectedError: ":DECODE_ERROR:",
- })
- // Basic DTLS-SRTP tests. Include fake profiles to ensure they
- // are ignored.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "SRTP-Client",
- config: Config{
- SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
- },
- flags: []string{
- "-srtp-profiles",
- "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
- },
- expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
- })
- testCases = append(testCases, testCase{
- protocol: dtls,
- testType: serverTest,
- name: "SRTP-Server",
- config: Config{
- SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
- },
- flags: []string{
- "-srtp-profiles",
- "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
- },
- expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
- })
- // Test that the MKI is ignored.
- testCases = append(testCases, testCase{
- protocol: dtls,
- testType: serverTest,
- name: "SRTP-Server-IgnoreMKI",
- config: Config{
- SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
- Bugs: ProtocolBugs{
- SRTPMasterKeyIdentifer: "bogus",
- },
- },
- flags: []string{
- "-srtp-profiles",
- "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
- },
- expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
- })
- // Test that SRTP isn't negotiated on the server if there were
- // no matching profiles.
- testCases = append(testCases, testCase{
- protocol: dtls,
- testType: serverTest,
- name: "SRTP-Server-NoMatch",
- config: Config{
- SRTPProtectionProfiles: []uint16{100, 101, 102},
- },
- flags: []string{
- "-srtp-profiles",
- "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
- },
- expectedSRTPProtectionProfile: 0,
- })
- // Test that the server returning an invalid SRTP profile is
- // flagged as an error by the client.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "SRTP-Client-NoMatch",
- config: Config{
- Bugs: ProtocolBugs{
- SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
- },
- },
- flags: []string{
- "-srtp-profiles",
- "SRTP_AES128_CM_SHA1_80",
- },
- shouldFail: true,
- expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
- })
- // Test SCT list.
- testCases = append(testCases, testCase{
- name: "SignedCertificateTimestampList-Client",
- testType: clientTest,
- flags: []string{
- "-enable-signed-cert-timestamps",
- "-expect-signed-cert-timestamps",
- base64.StdEncoding.EncodeToString(testSCTList),
- },
- resumeSession: true,
- })
- testCases = append(testCases, testCase{
- name: "SignedCertificateTimestampList-Server",
- testType: serverTest,
- flags: []string{
- "-signed-cert-timestamps",
- base64.StdEncoding.EncodeToString(testSCTList),
- },
- expectedSCTList: testSCTList,
- resumeSession: true,
- })
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "ClientHelloPadding",
- config: Config{
- Bugs: ProtocolBugs{
- RequireClientHelloSize: 512,
- },
- },
- // This hostname just needs to be long enough to push the
- // ClientHello into F5's danger zone between 256 and 511 bytes
- // long.
- flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
- })
-}
-
-func addResumptionVersionTests() {
- for _, sessionVers := range tlsVersions {
- for _, resumeVers := range tlsVersions {
- protocols := []protocol{tls}
- if sessionVers.hasDTLS && resumeVers.hasDTLS {
- protocols = append(protocols, dtls)
- }
- for _, protocol := range protocols {
- suffix := "-" + sessionVers.name + "-" + resumeVers.name
- if protocol == dtls {
- suffix += "-DTLS"
- }
-
- if sessionVers.version == resumeVers.version {
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "Resume-Client" + suffix,
- resumeSession: true,
- config: Config{
- MaxVersion: sessionVers.version,
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- },
- expectedVersion: sessionVers.version,
- expectedResumeVersion: resumeVers.version,
- })
- } else {
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "Resume-Client-Mismatch" + suffix,
- resumeSession: true,
- config: Config{
- MaxVersion: sessionVers.version,
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- },
- expectedVersion: sessionVers.version,
- resumeConfig: &Config{
- MaxVersion: resumeVers.version,
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- Bugs: ProtocolBugs{
- AllowSessionVersionMismatch: true,
- },
- },
- expectedResumeVersion: resumeVers.version,
- shouldFail: true,
- expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
- })
- }
-
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: "Resume-Client-NoResume" + suffix,
- resumeSession: true,
- config: Config{
- MaxVersion: sessionVers.version,
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- },
- expectedVersion: sessionVers.version,
- resumeConfig: &Config{
- MaxVersion: resumeVers.version,
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- },
- newSessionsOnResume: true,
- expectResumeRejected: true,
- expectedResumeVersion: resumeVers.version,
- })
-
- testCases = append(testCases, testCase{
- protocol: protocol,
- testType: serverTest,
- name: "Resume-Server" + suffix,
- resumeSession: true,
- config: Config{
- MaxVersion: sessionVers.version,
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- },
- expectedVersion: sessionVers.version,
- expectResumeRejected: sessionVers.version != resumeVers.version,
- resumeConfig: &Config{
- MaxVersion: resumeVers.version,
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
- },
- expectedResumeVersion: resumeVers.version,
- })
- }
- }
- }
-
- testCases = append(testCases, testCase{
- name: "Resume-Client-CipherMismatch",
- resumeSession: true,
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- },
- resumeConfig: &Config{
- CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
- Bugs: ProtocolBugs{
- SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
- },
- },
- shouldFail: true,
- expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
- })
-}
-
-func addRenegotiationTests() {
- // Servers cannot renegotiate.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-Forbidden",
- renegotiate: true,
- flags: []string{"-reject-peer-renegotiations"},
- shouldFail: true,
- expectedError: ":NO_RENEGOTIATION:",
- expectedLocalError: "remote error: no renegotiation",
- })
- // The server shouldn't echo the renegotiation extension unless
- // requested by the client.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-NoExt",
- config: Config{
- Bugs: ProtocolBugs{
- NoRenegotiationInfo: true,
- RequireRenegotiationInfo: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "renegotiation extension missing",
- })
- // The renegotiation SCSV should be sufficient for the server to echo
- // the extension.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Renegotiate-Server-NoExt-SCSV",
- config: Config{
- Bugs: ProtocolBugs{
- NoRenegotiationInfo: true,
- SendRenegotiationSCSV: true,
- RequireRenegotiationInfo: true,
- },
- },
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client",
- config: Config{
- Bugs: ProtocolBugs{
- FailIfResumeOnRenego: true,
- },
- },
- renegotiate: true,
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-EmptyExt",
- renegotiate: true,
- config: Config{
- Bugs: ProtocolBugs{
- EmptyRenegotiationInfo: true,
- },
- },
- shouldFail: true,
- expectedError: ":RENEGOTIATION_MISMATCH:",
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-BadExt",
- renegotiate: true,
- config: Config{
- Bugs: ProtocolBugs{
- BadRenegotiationInfo: true,
- },
- },
- shouldFail: true,
- expectedError: ":RENEGOTIATION_MISMATCH:",
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-NoExt",
- config: Config{
- Bugs: ProtocolBugs{
- NoRenegotiationInfo: true,
- },
- },
- shouldFail: true,
- expectedError: ":UNSAFE_LEGACY_RENEGOTIATION_DISABLED:",
- flags: []string{"-no-legacy-server-connect"},
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-NoExt-Allowed",
- renegotiate: true,
- config: Config{
- Bugs: ProtocolBugs{
- NoRenegotiationInfo: true,
- },
- },
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-SwitchCiphers",
- renegotiate: true,
- config: Config{
- CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
- },
- renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-SwitchCiphers2",
- renegotiate: true,
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- },
- renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-Client-Forbidden",
- renegotiate: true,
- flags: []string{"-reject-peer-renegotiations"},
- shouldFail: true,
- expectedError: ":NO_RENEGOTIATION:",
- expectedLocalError: "remote error: no renegotiation",
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-SameClientVersion",
- renegotiate: true,
- config: Config{
- MaxVersion: VersionTLS10,
- Bugs: ProtocolBugs{
- RequireSameRenegoClientVersion: true,
- },
- },
- })
- testCases = append(testCases, testCase{
- name: "Renegotiate-FalseStart",
- renegotiate: true,
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
- },
- flags: []string{
- "-false-start",
- "-select-next-proto", "foo",
- },
- shimWritesFirst: true,
- })
-}
-
-func addDTLSReplayTests() {
- // Test that sequence number replays are detected.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "DTLS-Replay",
- messageCount: 200,
- replayWrites: true,
- })
-
- // Test the incoming sequence number skipping by values larger
- // than the retransmit window.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "DTLS-Replay-LargeGaps",
- config: Config{
- Bugs: ProtocolBugs{
- SequenceNumberMapping: func(in uint64) uint64 {
- return in * 127
- },
- },
- },
- messageCount: 200,
- replayWrites: true,
- })
-
- // Test the incoming sequence number changing non-monotonically.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "DTLS-Replay-NonMonotonic",
- config: Config{
- Bugs: ProtocolBugs{
- SequenceNumberMapping: func(in uint64) uint64 {
- return in ^ 31
- },
- },
- },
- messageCount: 200,
- replayWrites: true,
- })
-}
-
-var testHashes = []struct {
- name string
- id uint8
-}{
- {"SHA1", hashSHA1},
- {"SHA224", hashSHA224},
- {"SHA256", hashSHA256},
- {"SHA384", hashSHA384},
- {"SHA512", hashSHA512},
-}
-
-func addSigningHashTests() {
- // Make sure each hash works. Include some fake hashes in the list and
- // ensure they're ignored.
- for _, hash := range testHashes {
- testCases = append(testCases, testCase{
- name: "SigningHash-ClientAuth-" + hash.name,
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, 42},
- {signatureRSA, hash.id},
- {signatureRSA, 255},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- })
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SigningHash-ServerKeyExchange-Sign-" + hash.name,
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, 42},
- {signatureRSA, hash.id},
- {signatureRSA, 255},
- },
- },
- })
- }
-
- // Test that hash resolution takes the signature type into account.
- testCases = append(testCases, testCase{
- name: "SigningHash-ClientAuth-SignatureType",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureECDSA, hashSHA512},
- {signatureRSA, hashSHA384},
- {signatureECDSA, hashSHA1},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- })
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SigningHash-ServerKeyExchange-SignatureType",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- SignatureAndHashes: []signatureAndHash{
- {signatureECDSA, hashSHA512},
- {signatureRSA, hashSHA384},
- {signatureECDSA, hashSHA1},
- },
- },
- })
-
- // Test that, if the list is missing, the peer falls back to SHA-1.
- testCases = append(testCases, testCase{
- name: "SigningHash-ClientAuth-Fallback",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA1},
- },
- Bugs: ProtocolBugs{
- NoSignatureAndHashes: true,
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- })
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SigningHash-ServerKeyExchange-Fallback",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA1},
- },
- Bugs: ProtocolBugs{
- NoSignatureAndHashes: true,
- },
- },
- })
-
- // Test that hash preferences are enforced. BoringSSL defaults to
- // rejecting MD5 signatures.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "SigningHash-ClientAuth-Enforced",
- config: Config{
- Certificates: []Certificate{rsaCertificate},
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashMD5},
- // Advertise SHA-1 so the handshake will
- // proceed, but the shim's preferences will be
- // ignored in CertificateVerify generation, so
- // MD5 will be chosen.
- {signatureRSA, hashSHA1},
- },
- Bugs: ProtocolBugs{
- IgnorePeerSignatureAlgorithmPreferences: true,
- },
- },
- flags: []string{"-require-any-client-certificate"},
- shouldFail: true,
- expectedError: ":WRONG_SIGNATURE_TYPE:",
- })
-
- testCases = append(testCases, testCase{
- name: "SigningHash-ServerKeyExchange-Enforced",
- config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashMD5},
- },
- Bugs: ProtocolBugs{
- IgnorePeerSignatureAlgorithmPreferences: true,
- },
- },
- shouldFail: true,
- expectedError: ":WRONG_SIGNATURE_TYPE:",
- })
-
- // Test that the agreed upon digest respects the client preferences and
- // the server digests.
- testCases = append(testCases, testCase{
- name: "Agree-Digest-Fallback",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA512},
- {signatureRSA, hashSHA1},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- digestPrefs: "SHA256",
- expectedClientCertSignatureHash: hashSHA1,
- })
- testCases = append(testCases, testCase{
- name: "Agree-Digest-SHA256",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA1},
- {signatureRSA, hashSHA256},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- digestPrefs: "SHA256,SHA1",
- expectedClientCertSignatureHash: hashSHA256,
- })
- testCases = append(testCases, testCase{
- name: "Agree-Digest-SHA1",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA1},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- digestPrefs: "SHA512,SHA256,SHA1",
- expectedClientCertSignatureHash: hashSHA1,
- })
- testCases = append(testCases, testCase{
- name: "Agree-Digest-Default",
- config: Config{
- ClientAuth: RequireAnyClientCert,
- SignatureAndHashes: []signatureAndHash{
- {signatureRSA, hashSHA256},
- {signatureECDSA, hashSHA256},
- {signatureRSA, hashSHA1},
- {signatureECDSA, hashSHA1},
- },
- },
- flags: []string{
- "-cert-file", path.Join(*resourceDir, rsaCertificateFile),
- "-key-file", path.Join(*resourceDir, rsaKeyFile),
- },
- expectedClientCertSignatureHash: hashSHA256,
- })
-}
-
-// timeouts is the retransmit schedule for BoringSSL. It doubles and
-// caps at 60 seconds. On the 13th timeout, it gives up.
-var timeouts = []time.Duration{
- 1 * time.Second,
- 2 * time.Second,
- 4 * time.Second,
- 8 * time.Second,
- 16 * time.Second,
- 32 * time.Second,
- 60 * time.Second,
- 60 * time.Second,
- 60 * time.Second,
- 60 * time.Second,
- 60 * time.Second,
- 60 * time.Second,
- 60 * time.Second,
-}
-
-func addDTLSRetransmitTests() {
- // Test that this is indeed the timeout schedule. Stress all
- // four patterns of handshake.
- for i := 1; i < len(timeouts); i++ {
- number := strconv.Itoa(i)
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "DTLS-Retransmit-Client-" + number,
- config: Config{
- Bugs: ProtocolBugs{
- TimeoutSchedule: timeouts[:i],
- },
- },
- resumeSession: true,
- flags: []string{"-async"},
- })
- testCases = append(testCases, testCase{
- protocol: dtls,
- testType: serverTest,
- name: "DTLS-Retransmit-Server-" + number,
- config: Config{
- Bugs: ProtocolBugs{
- TimeoutSchedule: timeouts[:i],
- },
- },
- resumeSession: true,
- flags: []string{"-async"},
- })
- }
-
- // Test that exceeding the timeout schedule hits a read
- // timeout.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "DTLS-Retransmit-Timeout",
- config: Config{
- Bugs: ProtocolBugs{
- TimeoutSchedule: timeouts,
- },
- },
- resumeSession: true,
- flags: []string{"-async"},
- shouldFail: true,
- expectedError: ":READ_TIMEOUT_EXPIRED:",
- })
-
- // Test that timeout handling has a fudge factor, due to API
- // problems.
- testCases = append(testCases, testCase{
- protocol: dtls,
- name: "DTLS-Retransmit-Fudge",
- config: Config{
- Bugs: ProtocolBugs{
- TimeoutSchedule: []time.Duration{
- timeouts[0] - 10*time.Millisecond,
- },
- },
- },
- resumeSession: true,
- flags: []string{"-async"},
- })
-
- // Test that the final Finished retransmitting isn't
- // duplicated if the peer badly fragments everything.
- testCases = append(testCases, testCase{
- testType: serverTest,
- protocol: dtls,
- name: "DTLS-Retransmit-Fragmented",
- config: Config{
- Bugs: ProtocolBugs{
- TimeoutSchedule: []time.Duration{timeouts[0]},
- MaxHandshakeRecordLength: 2,
- },
- },
- flags: []string{"-async"},
- })
-}
-
-func addExportKeyingMaterialTests() {
- for _, vers := range tlsVersions {
- if vers.version == VersionSSL30 {
- continue
- }
- testCases = append(testCases, testCase{
- name: "ExportKeyingMaterial-" + vers.name,
- config: Config{
- MaxVersion: vers.version,
- },
- exportKeyingMaterial: 1024,
- exportLabel: "label",
- exportContext: "context",
- useExportContext: true,
- })
- testCases = append(testCases, testCase{
- name: "ExportKeyingMaterial-NoContext-" + vers.name,
- config: Config{
- MaxVersion: vers.version,
- },
- exportKeyingMaterial: 1024,
- })
- testCases = append(testCases, testCase{
- name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
- config: Config{
- MaxVersion: vers.version,
- },
- exportKeyingMaterial: 1024,
- useExportContext: true,
- })
- testCases = append(testCases, testCase{
- name: "ExportKeyingMaterial-Small-" + vers.name,
- config: Config{
- MaxVersion: vers.version,
- },
- exportKeyingMaterial: 1,
- exportLabel: "label",
- exportContext: "context",
- useExportContext: true,
- })
- }
- testCases = append(testCases, testCase{
- name: "ExportKeyingMaterial-SSL3",
- config: Config{
- MaxVersion: VersionSSL30,
- },
- exportKeyingMaterial: 1024,
- exportLabel: "label",
- exportContext: "context",
- useExportContext: true,
- shouldFail: true,
- expectedError: "failed to export keying material",
- })
-}
-
-func addTLSUniqueTests() {
- for _, isClient := range []bool{false, true} {
- for _, isResumption := range []bool{false, true} {
- for _, hasEMS := range []bool{false, true} {
- var suffix string
- if isResumption {
- suffix = "Resume-"
- } else {
- suffix = "Full-"
- }
-
- if hasEMS {
- suffix += "EMS-"
- } else {
- suffix += "NoEMS-"
- }
-
- if isClient {
- suffix += "Client"
- } else {
- suffix += "Server"
- }
-
- test := testCase{
- name: "TLSUnique-" + suffix,
- testTLSUnique: true,
- config: Config{
- Bugs: ProtocolBugs{
- NoExtendedMasterSecret: !hasEMS,
- },
- },
- }
-
- if isResumption {
- test.resumeSession = true
- test.resumeConfig = &Config{
- Bugs: ProtocolBugs{
- NoExtendedMasterSecret: !hasEMS,
- },
- }
- }
-
- if isResumption && !hasEMS {
- test.shouldFail = true
- test.expectedError = "failed to get tls-unique"
- }
-
- testCases = append(testCases, test)
- }
- }
- }
-}
-
-func addCustomExtensionTests() {
- expectedContents := "custom extension"
- emptyString := ""
-
- for _, isClient := range []bool{false, true} {
- suffix := "Server"
- flag := "-enable-server-custom-extension"
- testType := serverTest
- if isClient {
- suffix = "Client"
- flag = "-enable-client-custom-extension"
- testType = clientTest
- }
-
- testCases = append(testCases, testCase{
- testType: testType,
- name: "CustomExtensions-" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: expectedContents,
- ExpectedCustomExtension: &expectedContents,
- },
- },
- flags: []string{flag},
- })
-
- // If the parse callback fails, the handshake should also fail.
- testCases = append(testCases, testCase{
- testType: testType,
- name: "CustomExtensions-ParseError-" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: expectedContents + "foo",
- ExpectedCustomExtension: &expectedContents,
- },
- },
- flags: []string{flag},
- shouldFail: true,
- expectedError: ":CUSTOM_EXTENSION_ERROR:",
- })
-
- // If the add callback fails, the handshake should also fail.
- testCases = append(testCases, testCase{
- testType: testType,
- name: "CustomExtensions-FailAdd-" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: expectedContents,
- ExpectedCustomExtension: &expectedContents,
- },
- },
- flags: []string{flag, "-custom-extension-fail-add"},
- shouldFail: true,
- expectedError: ":CUSTOM_EXTENSION_ERROR:",
- })
-
- // If the add callback returns zero, no extension should be
- // added.
- skipCustomExtension := expectedContents
- if isClient {
- // For the case where the client skips sending the
- // custom extension, the server must not “echo” it.
- skipCustomExtension = ""
- }
- testCases = append(testCases, testCase{
- testType: testType,
- name: "CustomExtensions-Skip-" + suffix,
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: skipCustomExtension,
- ExpectedCustomExtension: &emptyString,
- },
- },
- flags: []string{flag, "-custom-extension-skip"},
- })
- }
-
- // The custom extension add callback should not be called if the client
- // doesn't send the extension.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "CustomExtensions-NotCalled-Server",
- config: Config{
- Bugs: ProtocolBugs{
- ExpectedCustomExtension: &emptyString,
- },
- },
- flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
- })
-
- // Test an unknown extension from the server.
- testCases = append(testCases, testCase{
- testType: clientTest,
- name: "UnknownExtension-Client",
- config: Config{
- Bugs: ProtocolBugs{
- CustomExtension: expectedContents,
- },
- },
- shouldFail: true,
- expectedError: ":UNEXPECTED_EXTENSION:",
- })
-}
-
-func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
- defer wg.Done()
-
- for test := range c {
- var err error
-
- if *mallocTest < 0 {
- statusChan <- statusMsg{test: test, started: true}
- err = runTest(test, shimPath, -1)
- } else {
- for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
- statusChan <- statusMsg{test: test, started: true}
- if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
- if err != nil {
- fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
- }
- break
- }
- }
- }
- statusChan <- statusMsg{test: test, err: err}
- }
-}
-
-type statusMsg struct {
- test *testCase
- started bool
- err error
-}
-
-func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
- var started, done, failed, lineLen int
-
- testOutput := newTestOutput()
- for msg := range statusChan {
- if !*pipe {
- // Erase the previous status line.
- var erase string
- for i := 0; i < lineLen; i++ {
- erase += "\b \b"
- }
- fmt.Print(erase)
- }
-
- if msg.started {
- started++
- } else {
- done++
-
- if msg.err != nil {
- fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
- failed++
- testOutput.addResult(msg.test.name, "FAIL")
- } else {
- if *pipe {
- // Print each test instead of a status line.
- fmt.Printf("PASSED (%s)\n", msg.test.name)
- }
- testOutput.addResult(msg.test.name, "PASS")
- }
- }
-
- if !*pipe {
- // Print a new status line.
- line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
- lineLen = len(line)
- os.Stdout.WriteString(line)
- }
- }
-
- doneChan <- testOutput
-}
-
-func main() {
- flag.Parse()
- *resourceDir = path.Clean(*resourceDir)
-
- addBasicTests()
- addCipherSuiteTests()
- addBadECDSASignatureTests()
- addCBCPaddingTests()
- addCBCSplittingTests()
- addClientAuthTests()
- addDDoSCallbackTests()
- addVersionNegotiationTests()
- addMinimumVersionTests()
- addD5BugTests()
- addExtensionTests()
- addResumptionVersionTests()
- addExtendedMasterSecretTests()
- addRenegotiationTests()
- addDTLSReplayTests()
- addSigningHashTests()
- addDTLSRetransmitTests()
- addExportKeyingMaterialTests()
- addTLSUniqueTests()
- addCustomExtensionTests()
- for _, async := range []bool{false, true} {
- for _, splitHandshake := range []bool{false, true} {
- for _, protocol := range []protocol{tls, dtls} {
- addStateMachineCoverageTests(async, splitHandshake, protocol)
- }
- }
- }
-
- var wg sync.WaitGroup
-
- statusChan := make(chan statusMsg, *numWorkers)
- testChan := make(chan *testCase, *numWorkers)
- doneChan := make(chan *testOutput)
-
- go statusPrinter(doneChan, statusChan, len(testCases))
-
- for i := 0; i < *numWorkers; i++ {
- wg.Add(1)
- go worker(statusChan, testChan, *shimPath, &wg)
- }
-
- for i := range testCases {
- if len(*testToRun) == 0 || *testToRun == testCases[i].name {
- testChan <- &testCases[i]
- }
- }
-
- close(testChan)
- wg.Wait()
- close(statusChan)
- testOutput := <-doneChan
-
- fmt.Printf("\n")
-
- if *jsonOutput != "" {
- if err := testOutput.writeTo(*jsonOutput); err != nil {
- fmt.Fprintf(os.Stderr, "Error: %s\n", err)
- }
- }
-
- if !testOutput.allPassed {
- os.Exit(1)
- }
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/runner_test.go b/third_party/boringssl/src/ssl/test/runner/runner_test.go
deleted file mode 100644
index 320ff52ebb..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/runner_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package runner
-
-import "testing"
-
-func TestAll(t *testing.T) {
- main()
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/test_output.go b/third_party/boringssl/src/ssl/test/runner/test_output.go
deleted file mode 100644
index 2112092eb9..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/test_output.go
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright (c) 2015, 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. */
-
-package runner
-
-import (
- "encoding/json"
- "os"
- "time"
-)
-
-// testOutput is a representation of Chromium's JSON test result format. See
-// https://www.chromium.org/developers/the-json-test-results-format
-type testOutput struct {
- Version int `json:"version"`
- Interrupted bool `json:"interrupted"`
- PathDelimiter string `json:"path_delimiter"`
- SecondsSinceEpoch float64 `json:"seconds_since_epoch"`
- NumFailuresByType map[string]int `json:"num_failures_by_type"`
- Tests map[string]testResult `json:"tests"`
- allPassed bool
-}
-
-type testResult struct {
- Actual string `json:"actual"`
- Expected string `json:"expected"`
- IsUnexpected bool `json:"is_unexpected"`
-}
-
-func newTestOutput() *testOutput {
- return &testOutput{
- Version: 3,
- PathDelimiter: ".",
- SecondsSinceEpoch: float64(time.Now().UnixNano()) / float64(time.Second/time.Nanosecond),
- NumFailuresByType: make(map[string]int),
- Tests: make(map[string]testResult),
- allPassed: true,
- }
-}
-
-func (t *testOutput) addResult(name, result string) {
- if _, found := t.Tests[name]; found {
- panic(name)
- }
- t.Tests[name] = testResult{
- Actual: result,
- Expected: "PASS",
- IsUnexpected: result != "PASS",
- }
- t.NumFailuresByType[result]++
- if result != "PASS" {
- t.allPassed = false
- }
-}
-
-func (t *testOutput) writeTo(name string) error {
- file, err := os.Create(name)
- if err != nil {
- return err
- }
- defer file.Close()
- out, err := json.MarshalIndent(t, "", " ")
- if err != nil {
- return err
- }
- _, err = file.Write(out)
- return err
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/ticket.go b/third_party/boringssl/src/ssl/test/runner/ticket.go
deleted file mode 100644
index e121c05fb2..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/ticket.go
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runner
-
-import (
- "bytes"
- "crypto/aes"
- "crypto/cipher"
- "crypto/hmac"
- "crypto/sha256"
- "crypto/subtle"
- "errors"
- "io"
-)
-
-// sessionState contains the information that is serialized into a session
-// ticket in order to later resume a connection.
-type sessionState struct {
- vers uint16
- cipherSuite uint16
- masterSecret []byte
- handshakeHash []byte
- certificates [][]byte
- extendedMasterSecret bool
-}
-
-func (s *sessionState) equal(i interface{}) bool {
- s1, ok := i.(*sessionState)
- if !ok {
- return false
- }
-
- if s.vers != s1.vers ||
- s.cipherSuite != s1.cipherSuite ||
- !bytes.Equal(s.masterSecret, s1.masterSecret) ||
- !bytes.Equal(s.handshakeHash, s1.handshakeHash) ||
- s.extendedMasterSecret != s1.extendedMasterSecret {
- return false
- }
-
- if len(s.certificates) != len(s1.certificates) {
- return false
- }
-
- for i := range s.certificates {
- if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
- return false
- }
- }
-
- return true
-}
-
-func (s *sessionState) marshal() []byte {
- length := 2 + 2 + 2 + len(s.masterSecret) + 2 + len(s.handshakeHash) + 2
- for _, cert := range s.certificates {
- length += 4 + len(cert)
- }
- length++
-
- ret := make([]byte, length)
- x := ret
- x[0] = byte(s.vers >> 8)
- x[1] = byte(s.vers)
- x[2] = byte(s.cipherSuite >> 8)
- x[3] = byte(s.cipherSuite)
- x[4] = byte(len(s.masterSecret) >> 8)
- x[5] = byte(len(s.masterSecret))
- x = x[6:]
- copy(x, s.masterSecret)
- x = x[len(s.masterSecret):]
-
- x[0] = byte(len(s.handshakeHash) >> 8)
- x[1] = byte(len(s.handshakeHash))
- x = x[2:]
- copy(x, s.handshakeHash)
- x = x[len(s.handshakeHash):]
-
- x[0] = byte(len(s.certificates) >> 8)
- x[1] = byte(len(s.certificates))
- x = x[2:]
-
- for _, cert := range s.certificates {
- x[0] = byte(len(cert) >> 24)
- x[1] = byte(len(cert) >> 16)
- x[2] = byte(len(cert) >> 8)
- x[3] = byte(len(cert))
- copy(x[4:], cert)
- x = x[4+len(cert):]
- }
-
- if s.extendedMasterSecret {
- x[0] = 1
- }
- x = x[1:]
-
- return ret
-}
-
-func (s *sessionState) unmarshal(data []byte) bool {
- if len(data) < 8 {
- return false
- }
-
- s.vers = uint16(data[0])<<8 | uint16(data[1])
- s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
- masterSecretLen := int(data[4])<<8 | int(data[5])
- data = data[6:]
- if len(data) < masterSecretLen {
- return false
- }
-
- s.masterSecret = data[:masterSecretLen]
- data = data[masterSecretLen:]
-
- if len(data) < 2 {
- return false
- }
-
- handshakeHashLen := int(data[0])<<8 | int(data[1])
- data = data[2:]
- if len(data) < handshakeHashLen {
- return false
- }
-
- s.handshakeHash = data[:handshakeHashLen]
- data = data[handshakeHashLen:]
-
- if len(data) < 2 {
- return false
- }
-
- numCerts := int(data[0])<<8 | int(data[1])
- data = data[2:]
-
- s.certificates = make([][]byte, numCerts)
- for i := range s.certificates {
- if len(data) < 4 {
- return false
- }
- certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
- data = data[4:]
- if certLen < 0 {
- return false
- }
- if len(data) < certLen {
- return false
- }
- s.certificates[i] = data[:certLen]
- data = data[certLen:]
- }
-
- if len(data) < 1 {
- return false
- }
-
- s.extendedMasterSecret = false
- if data[0] == 1 {
- s.extendedMasterSecret = true
- }
- data = data[1:]
-
- if len(data) > 0 {
- return false
- }
-
- return true
-}
-
-func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
- serialized := state.marshal()
- encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size)
- iv := encrypted[:aes.BlockSize]
- macBytes := encrypted[len(encrypted)-sha256.Size:]
-
- if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
- return nil, err
- }
- block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
- if err != nil {
- return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
- }
- cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
-
- mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
- mac.Write(encrypted[:len(encrypted)-sha256.Size])
- mac.Sum(macBytes[:0])
-
- return encrypted, nil
-}
-
-func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
- if len(encrypted) < aes.BlockSize+sha256.Size {
- return nil, false
- }
-
- iv := encrypted[:aes.BlockSize]
- macBytes := encrypted[len(encrypted)-sha256.Size:]
-
- mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
- mac.Write(encrypted[:len(encrypted)-sha256.Size])
- expected := mac.Sum(nil)
-
- if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
- return nil, false
- }
-
- block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
- if err != nil {
- return nil, false
- }
- ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
- plaintext := make([]byte, len(ciphertext))
- cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
-
- state := new(sessionState)
- ok := state.unmarshal(plaintext)
- return state, ok
-}
diff --git a/third_party/boringssl/src/ssl/test/runner/tls.go b/third_party/boringssl/src/ssl/test/runner/tls.go
deleted file mode 100644
index 24f9b1ec8e..0000000000
--- a/third_party/boringssl/src/ssl/test/runner/tls.go
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package tls partially implements TLS 1.2, as specified in RFC 5246.
-package runner
-
-import (
- "crypto"
- "crypto/ecdsa"
- "crypto/rsa"
- "crypto/x509"
- "encoding/pem"
- "errors"
- "io/ioutil"
- "net"
- "strings"
- "time"
-)
-
-// Server returns a new TLS server side connection
-// using conn as the underlying transport.
-// The configuration config must be non-nil and must have
-// at least one certificate.
-func Server(conn net.Conn, config *Config) *Conn {
- c := &Conn{conn: conn, config: config}
- c.init()
- return c
-}
-
-// Client returns a new TLS client side connection
-// using conn as the underlying transport.
-// The config cannot be nil: users must set either ServerHostname or
-// InsecureSkipVerify in the config.
-func Client(conn net.Conn, config *Config) *Conn {
- c := &Conn{conn: conn, config: config, isClient: true}
- c.init()
- return c
-}
-
-// A listener implements a network listener (net.Listener) for TLS connections.
-type listener struct {
- net.Listener
- config *Config
-}
-
-// Accept waits for and returns the next incoming TLS connection.
-// The returned connection c is a *tls.Conn.
-func (l *listener) Accept() (c net.Conn, err error) {
- c, err = l.Listener.Accept()
- if err != nil {
- return
- }
- c = Server(c, l.config)
- return
-}
-
-// NewListener creates a Listener which accepts connections from an inner
-// Listener and wraps each connection with Server.
-// The configuration config must be non-nil and must have
-// at least one certificate.
-func NewListener(inner net.Listener, config *Config) net.Listener {
- l := new(listener)
- l.Listener = inner
- l.config = config
- return l
-}
-
-// Listen creates a TLS listener accepting connections on the
-// given network address using net.Listen.
-// The configuration config must be non-nil and must have
-// at least one certificate.
-func Listen(network, laddr string, config *Config) (net.Listener, error) {
- if config == nil || len(config.Certificates) == 0 {
- return nil, errors.New("tls.Listen: no certificates in configuration")
- }
- l, err := net.Listen(network, laddr)
- if err != nil {
- return nil, err
- }
- return NewListener(l, config), nil
-}
-
-type timeoutError struct{}
-
-func (timeoutError) Error() string { return "tls: DialWithDialer timed out" }
-func (timeoutError) Timeout() bool { return true }
-func (timeoutError) Temporary() bool { return true }
-
-// DialWithDialer connects to the given network address using dialer.Dial and
-// then initiates a TLS handshake, returning the resulting TLS connection. Any
-// timeout or deadline given in the dialer apply to connection and TLS
-// handshake as a whole.
-//
-// DialWithDialer interprets a nil configuration as equivalent to the zero
-// configuration; see the documentation of Config for the defaults.
-func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) {
- // We want the Timeout and Deadline values from dialer to cover the
- // whole process: TCP connection and TLS handshake. This means that we
- // also need to start our own timers now.
- timeout := dialer.Timeout
-
- if !dialer.Deadline.IsZero() {
- deadlineTimeout := dialer.Deadline.Sub(time.Now())
- if timeout == 0 || deadlineTimeout < timeout {
- timeout = deadlineTimeout
- }
- }
-
- var errChannel chan error
-
- if timeout != 0 {
- errChannel = make(chan error, 2)
- time.AfterFunc(timeout, func() {
- errChannel <- timeoutError{}
- })
- }
-
- rawConn, err := dialer.Dial(network, addr)
- if err != nil {
- return nil, err
- }
-
- colonPos := strings.LastIndex(addr, ":")
- if colonPos == -1 {
- colonPos = len(addr)
- }
- hostname := addr[:colonPos]
-
- if config == nil {
- config = defaultConfig()
- }
- // If no ServerName is set, infer the ServerName
- // from the hostname we're connecting to.
- if config.ServerName == "" {
- // Make a copy to avoid polluting argument or default.
- c := *config
- c.ServerName = hostname
- config = &c
- }
-
- conn := Client(rawConn, config)
-
- if timeout == 0 {
- err = conn.Handshake()
- } else {
- go func() {
- errChannel <- conn.Handshake()
- }()
-
- err = <-errChannel
- }
-
- if err != nil {
- rawConn.Close()
- return nil, err
- }
-
- return conn, nil
-}
-
-// Dial connects to the given network address using net.Dial
-// and then initiates a TLS handshake, returning the resulting
-// TLS connection.
-// Dial interprets a nil configuration as equivalent to
-// the zero configuration; see the documentation of Config
-// for the defaults.
-func Dial(network, addr string, config *Config) (*Conn, error) {
- return DialWithDialer(new(net.Dialer), network, addr, config)
-}
-
-// LoadX509KeyPair reads and parses a public/private key pair from a pair of
-// files. The files must contain PEM encoded data.
-func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) {
- certPEMBlock, err := ioutil.ReadFile(certFile)
- if err != nil {
- return
- }
- keyPEMBlock, err := ioutil.ReadFile(keyFile)
- if err != nil {
- return
- }
- return X509KeyPair(certPEMBlock, keyPEMBlock)
-}
-
-// X509KeyPair parses a public/private key pair from a pair of
-// PEM encoded data.
-func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error) {
- var certDERBlock *pem.Block
- for {
- certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
- if certDERBlock == nil {
- break
- }
- if certDERBlock.Type == "CERTIFICATE" {
- cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
- }
- }
-
- if len(cert.Certificate) == 0 {
- err = errors.New("crypto/tls: failed to parse certificate PEM data")
- return
- }
-
- var keyDERBlock *pem.Block
- for {
- keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
- if keyDERBlock == nil {
- err = errors.New("crypto/tls: failed to parse key PEM data")
- return
- }
- if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
- break
- }
- }
-
- cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
- if err != nil {
- return
- }
-
- // We don't need to parse the public key for TLS, but we so do anyway
- // to check that it looks sane and matches the private key.
- x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
- if err != nil {
- return
- }
-
- switch pub := x509Cert.PublicKey.(type) {
- case *rsa.PublicKey:
- priv, ok := cert.PrivateKey.(*rsa.PrivateKey)
- if !ok {
- err = errors.New("crypto/tls: private key type does not match public key type")
- return
- }
- if pub.N.Cmp(priv.N) != 0 {
- err = errors.New("crypto/tls: private key does not match public key")
- return
- }
- case *ecdsa.PublicKey:
- priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
- if !ok {
- err = errors.New("crypto/tls: private key type does not match public key type")
- return
-
- }
- if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
- err = errors.New("crypto/tls: private key does not match public key")
- return
- }
- default:
- err = errors.New("crypto/tls: unknown public key algorithm")
- return
- }
-
- return
-}
-
-// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
-// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
-// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
-func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
- if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
- return key, nil
- }
- if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
- switch key := key.(type) {
- case *rsa.PrivateKey, *ecdsa.PrivateKey:
- return key, nil
- default:
- return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping")
- }
- }
- if key, err := x509.ParseECPrivateKey(der); err == nil {
- return key, nil
- }
-
- return nil, errors.New("crypto/tls: failed to parse private key")
-}
diff --git a/third_party/boringssl/src/ssl/test/scoped_types.h b/third_party/boringssl/src/ssl/test/scoped_types.h
deleted file mode 100644
index 7e92ceeda4..0000000000
--- a/third_party/boringssl/src/ssl/test/scoped_types.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright (c) 2015, 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 OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H
-#define OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H
-
-#include <openssl/ssl.h>
-
-#include "../../crypto/test/scoped_types.h"
-
-
-using ScopedSSL = ScopedOpenSSLType<SSL, SSL_free>;
-using ScopedSSL_CTX = ScopedOpenSSLType<SSL_CTX, SSL_CTX_free>;
-using ScopedSSL_SESSION = ScopedOpenSSLType<SSL_SESSION, SSL_SESSION_free>;
-
-
-#endif // OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H
diff --git a/third_party/boringssl/src/ssl/test/test_config.cc b/third_party/boringssl/src/ssl/test/test_config.cc
deleted file mode 100644
index 1c42b2e40d..0000000000
--- a/third_party/boringssl/src/ssl/test/test_config.cc
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Copyright (c) 2014, 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. */
-
-#include "test_config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <memory>
-
-#include <openssl/base64.h>
-
-namespace {
-
-template <typename T>
-struct Flag {
- const char *flag;
- T TestConfig::*member;
-};
-
-// FindField looks for the flag in |flags| that matches |flag|. If one is found,
-// it returns a pointer to the corresponding field in |config|. Otherwise, it
-// returns NULL.
-template<typename T, size_t N>
-T *FindField(TestConfig *config, const Flag<T> (&flags)[N], const char *flag) {
- for (size_t i = 0; i < N; i++) {
- if (strcmp(flag, flags[i].flag) == 0) {
- return &(config->*(flags[i].member));
- }
- }
- return NULL;
-}
-
-const Flag<bool> kBoolFlags[] = {
- { "-server", &TestConfig::is_server },
- { "-dtls", &TestConfig::is_dtls },
- { "-resume", &TestConfig::resume },
- { "-fallback-scsv", &TestConfig::fallback_scsv },
- { "-require-any-client-certificate",
- &TestConfig::require_any_client_certificate },
- { "-false-start", &TestConfig::false_start },
- { "-async", &TestConfig::async },
- { "-write-different-record-sizes",
- &TestConfig::write_different_record_sizes },
- { "-cbc-record-splitting", &TestConfig::cbc_record_splitting },
- { "-partial-write", &TestConfig::partial_write },
- { "-no-tls12", &TestConfig::no_tls12 },
- { "-no-tls11", &TestConfig::no_tls11 },
- { "-no-tls1", &TestConfig::no_tls1 },
- { "-no-ssl3", &TestConfig::no_ssl3 },
- { "-shim-writes-first", &TestConfig::shim_writes_first },
- { "-tls-d5-bug", &TestConfig::tls_d5_bug },
- { "-expect-session-miss", &TestConfig::expect_session_miss },
- { "-expect-extended-master-secret",
- &TestConfig::expect_extended_master_secret },
- { "-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling },
- { "-enable-signed-cert-timestamps",
- &TestConfig::enable_signed_cert_timestamps },
- { "-implicit-handshake", &TestConfig::implicit_handshake },
- { "-use-early-callback", &TestConfig::use_early_callback },
- { "-fail-early-callback", &TestConfig::fail_early_callback },
- { "-install-ddos-callback", &TestConfig::install_ddos_callback },
- { "-fail-ddos-callback", &TestConfig::fail_ddos_callback },
- { "-fail-second-ddos-callback", &TestConfig::fail_second_ddos_callback },
- { "-handshake-never-done", &TestConfig::handshake_never_done },
- { "-use-export-context", &TestConfig::use_export_context },
- { "-reject-peer-renegotiations", &TestConfig::reject_peer_renegotiations },
- { "-no-legacy-server-connect", &TestConfig::no_legacy_server_connect },
- { "-tls-unique", &TestConfig::tls_unique },
- { "-use-async-private-key", &TestConfig::use_async_private_key },
- { "-expect-ticket-renewal", &TestConfig::expect_ticket_renewal },
- { "-expect-no-session", &TestConfig::expect_no_session },
- { "-use-ticket-callback", &TestConfig::use_ticket_callback },
- { "-renew-ticket", &TestConfig::renew_ticket },
- { "-enable-client-custom-extension",
- &TestConfig::enable_client_custom_extension },
- { "-enable-server-custom-extension",
- &TestConfig::enable_server_custom_extension },
- { "-custom-extension-skip", &TestConfig::custom_extension_skip },
- { "-custom-extension-fail-add", &TestConfig::custom_extension_fail_add },
- { "-check-close-notify", &TestConfig::check_close_notify },
- { "-shim-shuts-down", &TestConfig::shim_shuts_down },
- { "-microsoft-big-sslv3-buffer", &TestConfig::microsoft_big_sslv3_buffer },
- { "-verify-fail", &TestConfig::verify_fail },
- { "-verify-peer", &TestConfig::verify_peer },
- { "-expect-verify-result", &TestConfig::expect_verify_result }
-};
-
-const Flag<std::string> kStringFlags[] = {
- { "-digest-prefs", &TestConfig::digest_prefs },
- { "-key-file", &TestConfig::key_file },
- { "-cert-file", &TestConfig::cert_file },
- { "-expect-server-name", &TestConfig::expected_server_name },
- { "-advertise-npn", &TestConfig::advertise_npn },
- { "-expect-next-proto", &TestConfig::expected_next_proto },
- { "-select-next-proto", &TestConfig::select_next_proto },
- { "-send-channel-id", &TestConfig::send_channel_id },
- { "-host-name", &TestConfig::host_name },
- { "-advertise-alpn", &TestConfig::advertise_alpn },
- { "-expect-alpn", &TestConfig::expected_alpn },
- { "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn },
- { "-select-alpn", &TestConfig::select_alpn },
- { "-psk", &TestConfig::psk },
- { "-psk-identity", &TestConfig::psk_identity },
- { "-srtp-profiles", &TestConfig::srtp_profiles },
- { "-cipher", &TestConfig::cipher },
- { "-cipher-tls10", &TestConfig::cipher_tls10 },
- { "-cipher-tls11", &TestConfig::cipher_tls11 },
- { "-export-label", &TestConfig::export_label },
- { "-export-context", &TestConfig::export_context },
-};
-
-const Flag<std::string> kBase64Flags[] = {
- { "-expect-certificate-types", &TestConfig::expected_certificate_types },
- { "-expect-channel-id", &TestConfig::expected_channel_id },
- { "-expect-ocsp-response", &TestConfig::expected_ocsp_response },
- { "-expect-signed-cert-timestamps",
- &TestConfig::expected_signed_cert_timestamps },
- { "-ocsp-response", &TestConfig::ocsp_response },
- { "-signed-cert-timestamps", &TestConfig::signed_cert_timestamps },
-};
-
-const Flag<int> kIntFlags[] = {
- { "-port", &TestConfig::port },
- { "-min-version", &TestConfig::min_version },
- { "-max-version", &TestConfig::max_version },
- { "-mtu", &TestConfig::mtu },
- { "-export-keying-material", &TestConfig::export_keying_material },
-};
-
-} // namespace
-
-bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
- for (int i = 0; i < argc; i++) {
- bool *bool_field = FindField(out_config, kBoolFlags, argv[i]);
- if (bool_field != NULL) {
- *bool_field = true;
- continue;
- }
-
- std::string *string_field = FindField(out_config, kStringFlags, argv[i]);
- if (string_field != NULL) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "Missing parameter\n");
- return false;
- }
- string_field->assign(argv[i]);
- continue;
- }
-
- std::string *base64_field = FindField(out_config, kBase64Flags, argv[i]);
- if (base64_field != NULL) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "Missing parameter\n");
- return false;
- }
- size_t len;
- if (!EVP_DecodedLength(&len, strlen(argv[i]))) {
- fprintf(stderr, "Invalid base64: %s\n", argv[i]);
- }
- std::unique_ptr<uint8_t[]> decoded(new uint8_t[len]);
- if (!EVP_DecodeBase64(decoded.get(), &len, len,
- reinterpret_cast<const uint8_t *>(argv[i]),
- strlen(argv[i]))) {
- fprintf(stderr, "Invalid base64: %s\n", argv[i]);
- }
- base64_field->assign(reinterpret_cast<const char *>(decoded.get()), len);
- continue;
- }
-
- int *int_field = FindField(out_config, kIntFlags, argv[i]);
- if (int_field) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "Missing parameter\n");
- return false;
- }
- *int_field = atoi(argv[i]);
- continue;
- }
-
- fprintf(stderr, "Unknown argument: %s\n", argv[i]);
- return false;
- }
-
- return true;
-}
diff --git a/third_party/boringssl/src/ssl/test/test_config.h b/third_party/boringssl/src/ssl/test/test_config.h
deleted file mode 100644
index 9dea8e9520..0000000000
--- a/third_party/boringssl/src/ssl/test/test_config.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/* Copyright (c) 2014, 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_TEST_CONFIG
-#define HEADER_TEST_CONFIG
-
-#include <string>
-
-
-struct TestConfig {
- int port = 0;
- bool is_server = false;
- bool is_dtls = false;
- bool resume = false;
- bool fallback_scsv = false;
- std::string digest_prefs;
- std::string key_file;
- std::string cert_file;
- std::string expected_server_name;
- std::string expected_certificate_types;
- bool require_any_client_certificate = false;
- std::string advertise_npn;
- std::string expected_next_proto;
- bool false_start = false;
- std::string select_next_proto;
- bool async = false;
- bool write_different_record_sizes = false;
- bool cbc_record_splitting = false;
- bool partial_write = false;
- bool no_tls12 = false;
- bool no_tls11 = false;
- bool no_tls1 = false;
- bool no_ssl3 = false;
- std::string expected_channel_id;
- std::string send_channel_id;
- bool shim_writes_first = false;
- bool tls_d5_bug = false;
- std::string host_name;
- std::string advertise_alpn;
- std::string expected_alpn;
- std::string expected_advertised_alpn;
- std::string select_alpn;
- bool expect_session_miss = false;
- bool expect_extended_master_secret = false;
- std::string psk;
- std::string psk_identity;
- std::string srtp_profiles;
- bool enable_ocsp_stapling = false;
- std::string expected_ocsp_response;
- bool enable_signed_cert_timestamps = false;
- std::string expected_signed_cert_timestamps;
- int min_version = 0;
- int max_version = 0;
- int mtu = 0;
- bool implicit_handshake = false;
- bool use_early_callback = false;
- bool fail_early_callback = false;
- bool install_ddos_callback = false;
- bool fail_ddos_callback = false;
- bool fail_second_ddos_callback = false;
- std::string cipher;
- std::string cipher_tls10;
- std::string cipher_tls11;
- bool handshake_never_done = false;
- int export_keying_material = 0;
- std::string export_label;
- std::string export_context;
- bool use_export_context = false;
- bool reject_peer_renegotiations = false;
- bool no_legacy_server_connect = false;
- bool tls_unique = false;
- bool use_async_private_key = false;
- bool expect_ticket_renewal = false;
- bool expect_no_session = false;
- bool use_ticket_callback = false;
- bool renew_ticket = false;
- bool enable_client_custom_extension = false;
- bool enable_server_custom_extension = false;
- bool custom_extension_skip = false;
- bool custom_extension_fail_add = false;
- std::string ocsp_response;
- bool check_close_notify = false;
- bool shim_shuts_down = false;
- bool microsoft_big_sslv3_buffer = false;
- bool verify_fail = false;
- bool verify_peer = false;
- bool expect_verify_result = false;
- std::string signed_cert_timestamps;
-};
-
-bool ParseConfig(int argc, char **argv, TestConfig *out_config);
-
-
-#endif // HEADER_TEST_CONFIG