diff options
Diffstat (limited to 'third_party/boringssl/src/ssl/test')
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 |