From ab6407594b6c44ea730fbfb51a3d64d25a869d54 Mon Sep 17 00:00:00 2001 From: Alex Chau <alexchau@chromium.org> Date: Thu, 9 Jul 2020 15:43:49 +0000 Subject: [PATCH] Add Fuzzer targets for UKEY2 Bug: 1037793 Change-Id: Ia8148e61569e8b16cf6ae67dd136081c150b08ef Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2278059 Reviewed-by: Andrew Grieve <agrieve@chromium.org> Reviewed-by: danakj <danakj@chromium.org> Reviewed-by: Himanshu Jaju <himanshujaju@chromium.org> Reviewed-by: Alex Gough <ajgo@chromium.org> Commit-Queue: Alex Chau <alexchau@chromium.org> Cr-Commit-Position: refs/heads/master@{#786757} --- BUILD.gn | 1 + third_party/ukey2/fuzzers/BUILD.gn | 59 +++++++++++++ third_party/ukey2/fuzzers/DEPS | 3 + .../d2d_connection_context_client_fuzzer.cc | 43 ++++++++++ .../fuzzers/d2d_connection_context_factory.cc | 85 +++++++++++++++++++ .../fuzzers/d2d_connection_context_factory.h | 20 +++++ .../d2d_connection_context_server_fuzzer.cc | 43 ++++++++++ .../ukey2_handshake_client_finish_fuzzer.cc | 58 +++++++++++++ .../ukey2_handshake_client_init_fuzzer.cc | 40 +++++++++ .../ukey2_handshake_server_init_fuzzer.cc | 45 ++++++++++ 10 files changed, 397 insertions(+) create mode 100644 third_party/ukey2/fuzzers/BUILD.gn create mode 100644 third_party/ukey2/fuzzers/DEPS create mode 100644 third_party/ukey2/fuzzers/d2d_connection_context_client_fuzzer.cc create mode 100644 third_party/ukey2/fuzzers/d2d_connection_context_factory.cc create mode 100644 third_party/ukey2/fuzzers/d2d_connection_context_factory.h create mode 100644 third_party/ukey2/fuzzers/d2d_connection_context_server_fuzzer.cc create mode 100644 third_party/ukey2/fuzzers/ukey2_handshake_client_finish_fuzzer.cc create mode 100644 third_party/ukey2/fuzzers/ukey2_handshake_client_init_fuzzer.cc create mode 100644 third_party/ukey2/fuzzers/ukey2_handshake_server_init_fuzzer.cc diff --git a/BUILD.gn b/BUILD.gn index 75e360a159c93..801a0a0d0a0d3 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -765,6 +765,7 @@ group("gn_all") { "//third_party/grpc:fuzzers", "//third_party/icu/fuzzers", "//third_party/qcms:fuzzers", + "//third_party/ukey2/fuzzers", "//third_party/zlib/contrib/tests/fuzzers", ] diff --git a/third_party/ukey2/fuzzers/BUILD.gn b/third_party/ukey2/fuzzers/BUILD.gn new file mode 100644 index 0000000000000..1aba40637eefa --- /dev/null +++ b/third_party/ukey2/fuzzers/BUILD.gn @@ -0,0 +1,59 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//testing/libfuzzer/fuzzer_test.gni") + +# root BUILD depends on this target. Needed for package discovery +group("fuzzers") { +} + +fuzzer_test("d2d_connection_context_server_fuzzer") { + sources = [ + "d2d_connection_context_factory.cc", + "d2d_connection_context_factory.h", + "d2d_connection_context_server_fuzzer.cc", + ] + deps = [ + "//base", + "//third_party/protobuf:protobuf_lite", + "//third_party/ukey2", + ] +} + +fuzzer_test("d2d_connection_context_client_fuzzer") { + sources = [ + "d2d_connection_context_client_fuzzer.cc", + "d2d_connection_context_factory.cc", + "d2d_connection_context_factory.h", + ] + deps = [ + "//base", + "//third_party/protobuf:protobuf_lite", + "//third_party/ukey2", + ] +} + +fuzzer_test("ukey2_handshake_client_init_fuzzer") { + sources = [ "ukey2_handshake_client_init_fuzzer.cc" ] + deps = [ + "//base", + "//third_party/ukey2", + ] +} + +fuzzer_test("ukey2_handshake_server_init_fuzzer") { + sources = [ "ukey2_handshake_server_init_fuzzer.cc" ] + deps = [ + "//base", + "//third_party/ukey2", + ] +} + +fuzzer_test("ukey2_handshake_client_finish_fuzzer") { + sources = [ "ukey2_handshake_client_finish_fuzzer.cc" ] + deps = [ + "//base", + "//third_party/ukey2", + ] +} diff --git a/third_party/ukey2/fuzzers/DEPS b/third_party/ukey2/fuzzers/DEPS new file mode 100644 index 0000000000000..5cd0867c848de --- /dev/null +++ b/third_party/ukey2/fuzzers/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+base", +] diff --git a/third_party/ukey2/fuzzers/d2d_connection_context_client_fuzzer.cc b/third_party/ukey2/fuzzers/d2d_connection_context_client_fuzzer.cc new file mode 100644 index 0000000000000..a413c2dab9498 --- /dev/null +++ b/third_party/ukey2/fuzzers/d2d_connection_context_client_fuzzer.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> +#include <iostream> +#include <memory> +#include <string> + +#include "base/check.h" +#include "base/logging.h" +#include "base/no_destructor.h" +#include "third_party/protobuf/src/google/protobuf/stubs/logging.h" +#include "third_party/ukey2/fuzzers/d2d_connection_context_factory.h" + +// Disable noisy logging in protobuf. +google::protobuf::LogSilencer log_silencer; + +struct Environment { + Environment() { + // Disable noisy logging as per "libFuzzer in Chrome" documentation: + // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging. + logging::SetMinLogLevel(logging::LOG_FATAL); + // Disable noisy logging in securemessage. + std::cerr.setstate(std::ios_base::failbit); + + // Create instance once to be reused between fuzzing rounds. + client_context = securegcm::CreateClientContext(); + CHECK(client_context); + } + + std::unique_ptr<securegcm::D2DConnectionContextV1> client_context; +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static base::NoDestructor<Environment> environment; + + std::string buffer(data, data + size); + environment->client_context->DecodeMessageFromPeer(buffer); + + return 0; +} diff --git a/third_party/ukey2/fuzzers/d2d_connection_context_factory.cc b/third_party/ukey2/fuzzers/d2d_connection_context_factory.cc new file mode 100644 index 0000000000000..28b21a0d96ba2 --- /dev/null +++ b/third_party/ukey2/fuzzers/d2d_connection_context_factory.cc @@ -0,0 +1,85 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/ukey2/fuzzers/d2d_connection_context_factory.h" + +#include <string> + +#include "base/check.h" +#include "third_party/ukey2/src/src/main/cpp/include/securegcm/ukey2_handshake.h" + +namespace securegcm { + +namespace { + +const securegcm::UKey2Handshake::HandshakeCipher kCipher = + securegcm::UKey2Handshake::HandshakeCipher::P256_SHA512; +// Arbitrary chosen length as verification string is discarded regardless. +const int32_t kMaxUkey2VerificationStringLength = 32; + +void PerformHandshake(UKey2Handshake* server, UKey2Handshake* client) { + std::unique_ptr<std::string> client_init = client->GetNextHandshakeMessage(); + CHECK(client_init) << client->GetLastError(); + + UKey2Handshake::ParseResult parse_result = + server->ParseHandshakeMessage(*client_init); + CHECK(parse_result.success) << server->GetLastError(); + + std::unique_ptr<std::string> server_init = server->GetNextHandshakeMessage(); + CHECK(server_init) << server->GetLastError(); + + client->ParseHandshakeMessage(*server_init); + CHECK(parse_result.success) << client->GetLastError(); + + std::unique_ptr<std::string> client_finish = + client->GetNextHandshakeMessage(); + CHECK(client_finish) << client->GetLastError(); + + parse_result = server->ParseHandshakeMessage(*client_finish); + CHECK(parse_result.success) << server->GetLastError(); +} + +} // namespace + +std::unique_ptr<D2DConnectionContextV1> CreateServerContext() { + std::unique_ptr<UKey2Handshake> server = + UKey2Handshake::ForResponder(kCipher); + CHECK(server); + + std::unique_ptr<UKey2Handshake> client = + UKey2Handshake::ForInitiator(kCipher); + CHECK(client); + + PerformHandshake(server.get(), client.get()); + + std::unique_ptr<std::string> verification_string = + server->GetVerificationString(kMaxUkey2VerificationStringLength); + CHECK(verification_string) << server->GetLastError(); + + bool verify_result = server->VerifyHandshake(); + CHECK(verify_result) << server->GetLastError(); + + return server->ToConnectionContext(); +} + +std::unique_ptr<D2DConnectionContextV1> CreateClientContext() { + auto server = UKey2Handshake::ForResponder(kCipher); + CHECK(server); + + auto client = UKey2Handshake::ForInitiator(kCipher); + CHECK(client); + + PerformHandshake(server.get(), client.get()); + + std::unique_ptr<std::string> verification_string = + client->GetVerificationString(kMaxUkey2VerificationStringLength); + CHECK(verification_string) << client->GetLastError(); + + bool verify_result = client->VerifyHandshake(); + CHECK(verify_result) << client->GetLastError(); + + return client->ToConnectionContext(); +} + +} // namespace securegcm diff --git a/third_party/ukey2/fuzzers/d2d_connection_context_factory.h b/third_party/ukey2/fuzzers/d2d_connection_context_factory.h new file mode 100644 index 0000000000000..82789f09f1aae --- /dev/null +++ b/third_party/ukey2/fuzzers/d2d_connection_context_factory.h @@ -0,0 +1,20 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_UKEY2_D2D_CONNECTION_CONTEXT_FACTORY_H_ +#define THIRD_PARTY_UKEY2_D2D_CONNECTION_CONTEXT_FACTORY_H_ + +#include <memory> + +#include "third_party/ukey2/src/src/main/cpp/include/securegcm/d2d_connection_context_v1.h" + +namespace securegcm { + +std::unique_ptr<securegcm::D2DConnectionContextV1> CreateServerContext(); + +std::unique_ptr<securegcm::D2DConnectionContextV1> CreateClientContext(); + +} // namespace securegcm + +#endif // THIRD_PARTY_UKEY2_D2D_CONNECTION_CONTEXT_FACTORY_H_ diff --git a/third_party/ukey2/fuzzers/d2d_connection_context_server_fuzzer.cc b/third_party/ukey2/fuzzers/d2d_connection_context_server_fuzzer.cc new file mode 100644 index 0000000000000..f96e5005193d0 --- /dev/null +++ b/third_party/ukey2/fuzzers/d2d_connection_context_server_fuzzer.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> +#include <iostream> +#include <memory> +#include <string> + +#include "base/check.h" +#include "base/logging.h" +#include "base/no_destructor.h" +#include "third_party/protobuf/src/google/protobuf/stubs/logging.h" +#include "third_party/ukey2/fuzzers/d2d_connection_context_factory.h" + +// Disable noisy logging in protobuf. +google::protobuf::LogSilencer log_silencer; + +struct Environment { + Environment() { + // Disable noisy logging as per "libFuzzer in Chrome" documentation: + // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging. + logging::SetMinLogLevel(logging::LOG_FATAL); + // Disable noisy logging in securemessage. + std::cerr.setstate(std::ios_base::failbit); + + // Create instance once to be reused between fuzzing rounds. + server_context = securegcm::CreateServerContext(); + CHECK(server_context); + } + + std::unique_ptr<securegcm::D2DConnectionContextV1> server_context; +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static base::NoDestructor<Environment> environment; + + std::string buffer(data, data + size); + environment->server_context->DecodeMessageFromPeer(buffer); + + return 0; +} diff --git a/third_party/ukey2/fuzzers/ukey2_handshake_client_finish_fuzzer.cc b/third_party/ukey2/fuzzers/ukey2_handshake_client_finish_fuzzer.cc new file mode 100644 index 0000000000000..74066aae0b4fd --- /dev/null +++ b/third_party/ukey2/fuzzers/ukey2_handshake_client_finish_fuzzer.cc @@ -0,0 +1,58 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/ukey2/src/src/main/cpp/include/securegcm/ukey2_handshake.h" + +#include <stddef.h> +#include <stdint.h> +#include <memory> +#include <string> + +#include "base/check.h" +#include "base/logging.h" +#include "base/no_destructor.h" + +const securegcm::UKey2Handshake::HandshakeCipher kCipher = + securegcm::UKey2Handshake::HandshakeCipher::P256_SHA512; + +struct Environment { + Environment() { + // Disable noisy logging as per "libFuzzer in Chrome" documentation: + // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging. + logging::SetMinLogLevel(logging::LOG_FATAL); + + // Create instance once to be reused between fuzzing rounds. + server = securegcm::UKey2Handshake::ForResponder(kCipher); + CHECK(server); + + // Advance server to parse client init, generate serer init, then wait for + // client finish. + std::unique_ptr<securegcm::UKey2Handshake> client = + securegcm::UKey2Handshake::ForInitiator(kCipher); + CHECK(client); + + std::unique_ptr<std::string> client_init = + client->GetNextHandshakeMessage(); + CHECK(client_init) << client->GetLastError(); + + securegcm::UKey2Handshake::ParseResult parse_result = + server->ParseHandshakeMessage(*client_init); + CHECK(parse_result.success) << server->GetLastError(); + + std::unique_ptr<std::string> server_init = + server->GetNextHandshakeMessage(); + CHECK(server_init) << server->GetLastError(); + } + + std::unique_ptr<securegcm::UKey2Handshake> server; +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static base::NoDestructor<Environment> environment; + + std::string buffer(data, data + size); + environment->server->ParseHandshakeMessage(buffer); + + return 0; +} diff --git a/third_party/ukey2/fuzzers/ukey2_handshake_client_init_fuzzer.cc b/third_party/ukey2/fuzzers/ukey2_handshake_client_init_fuzzer.cc new file mode 100644 index 0000000000000..3236be8925527 --- /dev/null +++ b/third_party/ukey2/fuzzers/ukey2_handshake_client_init_fuzzer.cc @@ -0,0 +1,40 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/ukey2/src/src/main/cpp/include/securegcm/ukey2_handshake.h" + +#include <stddef.h> +#include <stdint.h> +#include <memory> +#include <string> + +#include "base/check.h" +#include "base/logging.h" +#include "base/no_destructor.h" + +const securegcm::UKey2Handshake::HandshakeCipher kCipher = + securegcm::UKey2Handshake::HandshakeCipher::P256_SHA512; + +struct Environment { + Environment() { + // Disable noisy logging as per "libFuzzer in Chrome" documentation: + // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging. + logging::SetMinLogLevel(logging::LOG_FATAL); + + // Create instance once to be reused between fuzzing rounds. + server = securegcm::UKey2Handshake::ForResponder(kCipher); + CHECK(server); + } + + std::unique_ptr<securegcm::UKey2Handshake> server; +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static base::NoDestructor<Environment> environment; + + std::string buffer(data, data + size); + environment->server->ParseHandshakeMessage(buffer); + + return 0; +} diff --git a/third_party/ukey2/fuzzers/ukey2_handshake_server_init_fuzzer.cc b/third_party/ukey2/fuzzers/ukey2_handshake_server_init_fuzzer.cc new file mode 100644 index 0000000000000..25cbba94df65a --- /dev/null +++ b/third_party/ukey2/fuzzers/ukey2_handshake_server_init_fuzzer.cc @@ -0,0 +1,45 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/ukey2/src/src/main/cpp/include/securegcm/ukey2_handshake.h" + +#include <stddef.h> +#include <stdint.h> +#include <memory> +#include <string> + +#include "base/check.h" +#include "base/logging.h" +#include "base/no_destructor.h" + +const securegcm::UKey2Handshake::HandshakeCipher kCipher = + securegcm::UKey2Handshake::HandshakeCipher::P256_SHA512; + +struct Environment { + Environment() { + // Disable noisy logging as per "libFuzzer in Chrome" documentation: + // testing/libfuzzer/getting_started.md#Disable-noisy-error-message-logging. + logging::SetMinLogLevel(logging::LOG_FATAL); + + // Create instance once to be reused between fuzzing rounds. + client = securegcm::UKey2Handshake::ForInitiator(kCipher); + CHECK(client); + + // Advance client to generate client init, then wait for server init. + std::unique_ptr<std::string> client_init = + client->GetNextHandshakeMessage(); + CHECK(client_init) << client->GetLastError(); + } + + std::unique_ptr<securegcm::UKey2Handshake> client; +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + static base::NoDestructor<Environment> environment; + + std::string buffer(data, data + size); + environment->client->ParseHandshakeMessage(buffer); + + return 0; +}