From d6f390bd6435ad8d602c6ba9f4d7d1221fd892e8 Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Mon, 13 Feb 2017 20:31:22 +0100 Subject: Bug 1338620 - Derive tls-client fuzzer configuration from input data r=franziskus Differential Revision: https://nss-review.dev.mozaws.net/D205 --- fuzz/fuzz.gyp | 1 + fuzz/tls_client_config.cc | 35 +++++++++++++++++++++++++++++++++++ fuzz/tls_client_config.h | 24 ++++++++++++++++++++++++ fuzz/tls_client_target.cc | 39 +++++++++++++++++++++++++++------------ 4 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 fuzz/tls_client_config.cc create mode 100644 fuzz/tls_client_config.h (limited to 'fuzz') diff --git a/fuzz/fuzz.gyp b/fuzz/fuzz.gyp index 9e0444100..a51be799a 100644 --- a/fuzz/fuzz.gyp +++ b/fuzz/fuzz.gyp @@ -248,6 +248,7 @@ 'target_name': 'nssfuzz-tls-client', 'type': 'executable', 'sources': [ + 'tls_client_config.cc', 'tls_client_socket.cc', 'tls_client_target.cc', ], diff --git a/fuzz/tls_client_config.cc b/fuzz/tls_client_config.cc new file mode 100644 index 000000000..78ab591e3 --- /dev/null +++ b/fuzz/tls_client_config.cc @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "tls_client_config.h" + +const uint64_t CONFIG_FAIL_CERT_AUTH = 1; +const uint64_t CONFIG_ENABLE_EXTENDED_MS = 2; +const uint64_t CONFIG_REQUIRE_DH_NAMED_GROUPS = 4; +const uint64_t CONFIG_ENABLE_FALSE_START = 8; + +// XOR 64-bit chunks of data to build a bitmap of config options derived from +// the fuzzing input. This seems the only way to fuzz various options while +// still maintaining compatibility with BoringSSL or OpenSSL fuzzers. +ClientConfig::ClientConfig(const uint8_t* data, size_t len) { + for (size_t i = 0; i < len; i++) { + config_ ^= static_cast(data[i]) << (8 * (i % 8)); + } +} + +bool ClientConfig::FailCertificateAuthentication() { + return config_ & CONFIG_FAIL_CERT_AUTH; +} + +bool ClientConfig::EnableExtendedMasterSecret() { + return config_ & CONFIG_ENABLE_EXTENDED_MS; +} + +bool ClientConfig::RequireDhNamedGroups() { + return config_ & CONFIG_REQUIRE_DH_NAMED_GROUPS; +} + +bool ClientConfig::EnableFalseStart() { + return config_ & CONFIG_ENABLE_FALSE_START; +} diff --git a/fuzz/tls_client_config.h b/fuzz/tls_client_config.h new file mode 100644 index 000000000..9cf3cf208 --- /dev/null +++ b/fuzz/tls_client_config.h @@ -0,0 +1,24 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef tls_client_config_h__ +#define tls_client_config_h__ + +#include +#include + +class ClientConfig { + public: + ClientConfig(const uint8_t* data, size_t len); + + bool FailCertificateAuthentication(); + bool EnableExtendedMasterSecret(); + bool RequireDhNamedGroups(); + bool EnableFalseStart(); + + private: + uint64_t config_; +}; + +#endif // tls_client_config_h__ diff --git a/fuzz/tls_client_target.cc b/fuzz/tls_client_target.cc index 4d8ed9ee9..fdc447916 100644 --- a/fuzz/tls_client_target.cc +++ b/fuzz/tls_client_target.cc @@ -11,6 +11,7 @@ #include "ssl.h" #include "shared.h" +#include "tls_client_config.h" #include "tls_client_socket.h" static PRStatus EnableAllProtocolVersions() { @@ -27,24 +28,26 @@ static PRStatus EnableAllProtocolVersions() { static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checksig, PRBool isServer) { - return SECSuccess; + assert(!isServer); + auto config = reinterpret_cast(arg); + return config->FailCertificateAuthentication() ? SECFailure : SECSuccess; } -static void SetSocketOptions(PRFileDesc* fd) { +static void SetSocketOptions(PRFileDesc* fd, + std::unique_ptr& config) { // Disable session cache for now. SECStatus rv = SSL_OptionSet(fd, SSL_NO_CACHE, true); assert(rv == SECSuccess); - rv = SSL_OptionSet(fd, SSL_ENABLE_EXTENDED_MASTER_SECRET, true); - assert(rv == SECSuccess); - - rv = SSL_OptionSet(fd, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, true); + rv = SSL_OptionSet(fd, SSL_ENABLE_EXTENDED_MASTER_SECRET, + config->EnableExtendedMasterSecret()); assert(rv == SECSuccess); - rv = SSL_OptionSet(fd, SSL_ENABLE_FALLBACK_SCSV, true); + rv = SSL_OptionSet(fd, SSL_REQUIRE_DH_NAMED_GROUPS, + config->RequireDhNamedGroups()); assert(rv == SECSuccess); - rv = SSL_OptionSet(fd, SSL_ENABLE_ALPN, true); + rv = SSL_OptionSet(fd, SSL_ENABLE_FALSE_START, config->EnableFalseStart()); assert(rv == SECSuccess); rv = @@ -59,8 +62,19 @@ static void EnableAllCipherSuites(PRFileDesc* fd) { } } -static void SetupAuthCertificateHook(PRFileDesc* fd) { - SECStatus rv = SSL_AuthCertificateHook(fd, AuthCertificateHook, nullptr); +// This is only called when we set SSL_ENABLE_FALSE_START=1, +// so we can always just set *canFalseStart=true. +static SECStatus CanFalseStartCallback(PRFileDesc* fd, void* arg, + PRBool* canFalseStart) { + *canFalseStart = true; + return SECSuccess; +} + +static void SetupCallbacks(PRFileDesc* fd, ClientConfig* config) { + SECStatus rv = SSL_AuthCertificateHook(fd, AuthCertificateHook, config); + assert(rv == SECSuccess); + + rv = SSL_SetCanFalseStartCallback(fd, CanFalseStartCallback, nullptr); assert(rv == SECSuccess); } @@ -89,6 +103,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { assert(db != nullptr); EnableAllProtocolVersions(); + std::unique_ptr config(new ClientConfig(data, len)); // Reset the RNG state. SECStatus rv = RNG_ResetForFuzzing(); @@ -104,9 +119,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t len) { // Probably not too important for clients. SSL_SetURL(ssl_fd, "server"); - SetSocketOptions(ssl_fd); + SetSocketOptions(ssl_fd, config); EnableAllCipherSuites(ssl_fd); - SetupAuthCertificateHook(ssl_fd); + SetupCallbacks(ssl_fd, config.get()); DoHandshake(ssl_fd); return 0; -- cgit v1.2.1