| // Copyright 2023 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <algorithm> |
| #include <memory> |
| #include <random> |
| #include <string> |
| #include <tuple> |
| |
| #include <base/command_line.h> |
| #include <base/files/scoped_temp_dir.h> |
| #include <base/logging.h> |
| #include <fuzzer/FuzzedDataProvider.h> |
| #include <gmock/gmock.h> |
| #include <libcrossystem/crossystem.h> |
| #include <libcrossystem/crossystem_fake.h> |
| #include <libstorage/platform/mock_platform.h> |
| #include <openssl/rand.h> |
| #include <tpm_manager/proto_bindings/tpm_manager.pb.h> |
| #include <tpm_manager-client-test/tpm_manager/dbus-proxy-mocks.h> |
| #include <trunks/fuzzed_command_transceiver.h> |
| #include <trunks/hmac_session_impl.h> |
| #include <trunks/password_authorization_delegate.h> |
| #include <trunks/policy_session_impl.h> |
| #include <trunks/session_manager_impl.h> |
| #include <trunks/tpm_state_impl.h> |
| #include <trunks/trunks_dbus_proxy.h> |
| #include <trunks/trunks_factory_impl.h> |
| |
| #include "libhwsec/backend/mock_backend.h" |
| #include "libhwsec/backend/tpm2/backend.h" |
| #include "libhwsec/error/tpm_retry_action.h" |
| #include "libhwsec/fuzzed/attestation.h" |
| #include "libhwsec/fuzzed/basic_objects.h" |
| #include "libhwsec/fuzzed/config.h" |
| #include "libhwsec/fuzzed/da_mitigation.h" |
| #include "libhwsec/fuzzed/encryption.h" |
| #include "libhwsec/fuzzed/event_management.h" |
| #include "libhwsec/fuzzed/hwsec_objects.h" |
| #include "libhwsec/fuzzed/key_management.h" |
| #include "libhwsec/fuzzed/middleware.h" |
| #include "libhwsec/fuzzed/pinweaver.h" |
| #include "libhwsec/fuzzed/pinweaver_manager.h" |
| #include "libhwsec/fuzzed/protobuf.h" |
| #include "libhwsec/fuzzed/recovery_crypto.h" |
| #include "libhwsec/fuzzed/sealing.h" |
| #include "libhwsec/fuzzed/signature_sealing.h" |
| #include "libhwsec/fuzzed/signing.h" |
| #include "libhwsec/fuzzed/storage.h" |
| #include "libhwsec/fuzzed/u2f.h" |
| #include "libhwsec/fuzzed/vendor.h" |
| #include "libhwsec/fuzzers/backend_command_list.h" |
| #include "libhwsec/middleware/middleware.h" |
| #include "libhwsec/middleware/middleware_owner.h" |
| #include "libhwsec/structures/threading_mode.h" |
| #include "trunks/tpm_generated.h" |
| |
| using testing::_; |
| using testing::DoAll; |
| using testing::Return; |
| using testing::SetArgPointee; |
| |
| namespace hwsec { |
| namespace { |
| |
| constexpr int kMaxCommandCount = 10; |
| constexpr uint32_t kVendorIdGsc = 0x43524f53; |
| |
| template <typename Origin> |
| class FuzzedAuthorizationDelegate : public Origin { |
| public: |
| template <typename... Args> |
| FuzzedAuthorizationDelegate(FuzzedDataProvider& data_provider, Args&&... args) |
| : Origin(std::forward<Args>(args)...), data_provider_(data_provider) {} |
| |
| bool GetCommandAuthorization(const std::string& command_hash, |
| bool is_command_parameter_encryption_possible, |
| bool is_response_parameter_encryption_possible, |
| std::string* authorization) override { |
| if (data_provider_.ConsumeBool()) { |
| return data_provider_.ConsumeBool(); |
| } |
| |
| return Origin::GetCommandAuthorization( |
| command_hash, is_command_parameter_encryption_possible, |
| is_response_parameter_encryption_possible, authorization); |
| } |
| |
| bool CheckResponseAuthorization(const std::string& response_hash, |
| const std::string& authorization) override { |
| if (data_provider_.ConsumeBool()) { |
| return data_provider_.ConsumeBool(); |
| } |
| |
| return Origin::CheckResponseAuthorization(response_hash, authorization); |
| } |
| |
| bool EncryptCommandParameter(std::string* parameter) override { |
| if (data_provider_.ConsumeBool()) { |
| return data_provider_.ConsumeBool(); |
| } |
| |
| return Origin::EncryptCommandParameter(parameter); |
| } |
| |
| bool DecryptResponseParameter(std::string* parameter) override { |
| if (data_provider_.ConsumeBool()) { |
| return data_provider_.ConsumeBool(); |
| } |
| |
| return Origin::DecryptResponseParameter(parameter); |
| } |
| |
| private: |
| FuzzedDataProvider& data_provider_; |
| }; |
| |
| template <typename Origin> |
| class FuzzedSession : public Origin { |
| public: |
| template <typename... Args> |
| FuzzedSession(FuzzedDataProvider& data_provider, Args&&... args) |
| : Origin(std::forward<Args>(args)...), |
| data_provider_(data_provider), |
| delegate_(data_provider, "") {} |
| |
| trunks::TPM_RC StartBoundSession(trunks::TPMI_DH_ENTITY bind_entity, |
| const std::string& bind_authorization_value, |
| bool salted, |
| bool enable_encryption) override { |
| if (data_provider_.ConsumeBool()) { |
| return trunks::TPM_RC_SUCCESS; |
| } |
| |
| return Origin::StartBoundSession(bind_entity, bind_authorization_value, |
| salted, enable_encryption); |
| } |
| |
| trunks::TPM_RC StartUnboundSession(bool salted, |
| bool enable_encryption) override { |
| if (data_provider_.ConsumeBool()) { |
| return trunks::TPM_RC_SUCCESS; |
| } |
| |
| return Origin::StartUnboundSession(salted, enable_encryption); |
| } |
| |
| trunks::AuthorizationDelegate* GetDelegate() override { |
| if (data_provider_.ConsumeBool()) { |
| return &delegate_; |
| } |
| |
| return Origin::GetDelegate(); |
| } |
| |
| private: |
| FuzzedDataProvider& data_provider_; |
| FuzzedAuthorizationDelegate<trunks::PasswordAuthorizationDelegate> delegate_; |
| }; |
| |
| class FuzzedTpmState : public trunks::TpmStateImpl { |
| public: |
| FuzzedTpmState(FuzzedDataProvider& data_provider, |
| const trunks::TrunksFactory& factory) |
| : trunks::TpmStateImpl(factory), data_provider_(data_provider) {} |
| trunks::TPM_RC Initialize() override { |
| if (!use_real_.has_value()) { |
| use_real_ = data_provider_.ConsumeBool(); |
| } |
| if (*use_real_) { |
| return trunks::TpmStateImpl::Initialize(); |
| } |
| return trunks::TPM_RC_SUCCESS; |
| } |
| |
| trunks::TPM_RC Refresh() override { |
| if (!use_real_.has_value()) { |
| use_real_ = data_provider_.ConsumeBool(); |
| } |
| if (*use_real_) { |
| return trunks::TpmStateImpl::Refresh(); |
| } |
| return trunks::TPM_RC_SUCCESS; |
| } |
| |
| #define FUZZED_COMMAND(type, command) \ |
| type command() override { \ |
| CHECK(use_real_.has_value()); \ |
| if (*use_real_) { \ |
| return trunks::TpmStateImpl::command(); \ |
| } \ |
| return FuzzedObject<type>()(data_provider_); \ |
| } |
| |
| FUZZED_COMMAND(bool, IsOwnerPasswordSet); |
| FUZZED_COMMAND(bool, IsEndorsementPasswordSet); |
| FUZZED_COMMAND(bool, IsLockoutPasswordSet); |
| FUZZED_COMMAND(bool, IsOwned); |
| FUZZED_COMMAND(bool, IsInLockout); |
| FUZZED_COMMAND(bool, IsPlatformHierarchyEnabled); |
| FUZZED_COMMAND(bool, IsStorageHierarchyEnabled); |
| FUZZED_COMMAND(bool, IsEndorsementHierarchyEnabled); |
| FUZZED_COMMAND(bool, IsEnabled); |
| FUZZED_COMMAND(bool, WasShutdownOrderly); |
| FUZZED_COMMAND(bool, IsRSASupported); |
| FUZZED_COMMAND(bool, IsECCSupported); |
| FUZZED_COMMAND(uint32_t, GetLockoutCounter); |
| FUZZED_COMMAND(uint32_t, GetLockoutThreshold); |
| FUZZED_COMMAND(uint32_t, GetLockoutInterval); |
| FUZZED_COMMAND(uint32_t, GetLockoutRecovery); |
| FUZZED_COMMAND(uint32_t, GetMaxNVSize); |
| FUZZED_COMMAND(uint32_t, GetTpmFamily); |
| FUZZED_COMMAND(uint32_t, GetSpecificationLevel); |
| FUZZED_COMMAND(uint32_t, GetSpecificationRevision); |
| FUZZED_COMMAND(uint32_t, GetManufacturer); |
| FUZZED_COMMAND(uint32_t, GetTpmModel); |
| FUZZED_COMMAND(uint64_t, GetFirmwareVersion); |
| FUZZED_COMMAND(std::string, GetVendorIDString); |
| |
| #undef FUZZED_COMMAND |
| |
| bool GetTpmProperty(trunks::TPM_PT property, uint32_t* value) override { |
| CHECK(use_real_.has_value()); |
| if (*use_real_) { |
| return trunks::TpmStateImpl::GetTpmProperty(property, value); |
| } |
| if (value) { |
| if (property == trunks::TPM_PT_MANUFACTURER && |
| data_provider_.ConsumeBool()) { |
| *value = kVendorIdGsc; |
| return true; |
| } |
| *value = data_provider_.ConsumeIntegral<uint32_t>(); |
| } |
| return true; |
| } |
| |
| bool GetAlgorithmProperties(trunks::TPM_ALG_ID algorithm, |
| trunks::TPMA_ALGORITHM* properties) override { |
| CHECK(use_real_.has_value()); |
| if (*use_real_) { |
| return trunks::TpmStateImpl::GetAlgorithmProperties(algorithm, |
| properties); |
| } |
| if (properties) { |
| *properties = data_provider_.ConsumeIntegral<trunks::TPMA_ALGORITHM>(); |
| } |
| return true; |
| } |
| |
| private: |
| FuzzedDataProvider& data_provider_; |
| std::optional<bool> use_real_; |
| }; |
| |
| class FuzzedTrunksFactory : public trunks::TrunksFactoryImpl { |
| public: |
| FuzzedTrunksFactory(FuzzedDataProvider& data_provider, |
| trunks::CommandTransceiver* transceiver) |
| : trunks::TrunksFactoryImpl(transceiver), |
| data_provider_(data_provider), |
| tpm_state_(std::make_unique<FuzzedTpmState>(data_provider_, *this)) { |
| CHECK(Initialize()); |
| } |
| |
| trunks::TpmState* GetTpmState() const override { return tpm_state_.get(); } |
| |
| std::unique_ptr<trunks::AuthorizationDelegate> GetPasswordAuthorization( |
| const std::string& password) const override { |
| return std::make_unique< |
| FuzzedAuthorizationDelegate<trunks::PasswordAuthorizationDelegate>>( |
| data_provider_, password); |
| } |
| |
| std::unique_ptr<trunks::HmacSession> GetHmacSession() const override { |
| return std::make_unique<FuzzedSession<trunks::HmacSessionImpl>>( |
| data_provider_, *this); |
| } |
| |
| std::unique_ptr<trunks::PolicySession> GetPolicySession() const override { |
| return std::make_unique<FuzzedSession<trunks::PolicySessionImpl>>( |
| data_provider_, *this, trunks::TPM_SE_POLICY); |
| } |
| |
| std::unique_ptr<trunks::PolicySession> GetTrialSession() const override { |
| return std::make_unique<FuzzedSession<trunks::PolicySessionImpl>>( |
| data_provider_, *this, trunks::TPM_SE_TRIAL); |
| } |
| |
| private: |
| FuzzedDataProvider& data_provider_; |
| std::unique_ptr<FuzzedTpmState> tpm_state_; |
| }; |
| |
| class Tpm2BackendFuzzerProxy : public Proxy { |
| public: |
| explicit Tpm2BackendFuzzerProxy(FuzzedDataProvider& data_provider) |
| : data_provider_(data_provider), |
| command_transceiver_(&data_provider_, 2048), |
| trunks_factory_(data_provider_, &command_transceiver_), |
| crossystem_(std::make_unique<crossystem::fake::CrossystemFake>()) { |
| auto fuzzed_result = [this](auto&&, auto* reply, auto&&, auto&&) { |
| using ReplyType = std::remove_pointer_t<decltype(reply)>; |
| *reply = FuzzedObject<ReplyType>()(data_provider_); |
| return FuzzedObject<bool>()(data_provider_); |
| }; |
| |
| ON_CALL(tpm_manager_, GetTpmNonsensitiveStatus(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_manager_, GetTpmStatus(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_manager_, GetVersionInfo(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_manager_, GetSupportedFeatures(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_manager_, GetDictionaryAttackInfo(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_manager_, GetRoVerificationStatus(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_manager_, ResetDictionaryAttackLock(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_manager_, RemoveOwnerDependency(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_manager_, ClearStoredOwnerPassword(_, _, _, _)) |
| .WillByDefault(fuzzed_result); |
| ON_CALL(tpm_nvram_, DefineSpace(_, _, _, _)).WillByDefault(fuzzed_result); |
| ON_CALL(tpm_nvram_, DestroySpace(_, _, _, _)).WillByDefault(fuzzed_result); |
| ON_CALL(tpm_nvram_, WriteSpace(_, _, _, _)).WillByDefault(fuzzed_result); |
| ON_CALL(tpm_nvram_, ReadSpace(_, _, _, _)).WillByDefault(fuzzed_result); |
| ON_CALL(tpm_nvram_, LockSpace(_, _, _, _)).WillByDefault(fuzzed_result); |
| ON_CALL(tpm_nvram_, GetSpaceInfo(_, _, _, _)).WillByDefault(fuzzed_result); |
| ON_CALL(tpm_nvram_, ListSpaces(_, _, _, _)) |
| .WillByDefault([this](auto&&, auto* reply, auto&&, auto&&) { |
| using ReplyType = std::remove_pointer_t<decltype(reply)>; |
| |
| if (data_provider_.ConsumeBool()) { |
| *reply = FuzzedObject<ReplyType>()(data_provider_); |
| return FuzzedObject<bool>()(data_provider_); |
| } |
| |
| *reply = ReplyType(); |
| reply->set_result(tpm_manager::NvramResult::NVRAM_RESULT_SUCCESS); |
| for (uint32_t index : |
| {0x100a, 0x9da5b0, 0x800004, 0x9da5b2, 0x800006, 0x100e}) { |
| if (data_provider_.ConsumeBool()) { |
| reply->add_index_list(index); |
| } |
| } |
| return true; |
| }); |
| |
| ON_CALL(platform_, ReadFileToString(_, _)) |
| .WillByDefault([this](auto&&, std::string* result) { |
| if (data_provider_.ConsumeBool()) { |
| *result = FuzzedObject<std::string>()(data_provider_); |
| return true; |
| } |
| return false; |
| }); |
| |
| Proxy::SetTrunksCommandTransceiver(&command_transceiver_); |
| Proxy::SetTrunksFactory(&trunks_factory_); |
| Proxy::SetTpmManager(&tpm_manager_); |
| Proxy::SetTpmNvram(&tpm_nvram_); |
| Proxy::SetCrossystem(&crossystem_); |
| Proxy::SetPlatform(&platform_); |
| } |
| |
| ~Tpm2BackendFuzzerProxy() override = default; |
| |
| private: |
| FuzzedDataProvider& data_provider_; |
| trunks::FuzzedCommandTransceiver command_transceiver_; |
| FuzzedTrunksFactory trunks_factory_; |
| testing::NiceMock<org::chromium::TpmManagerProxyMock> tpm_manager_; |
| testing::NiceMock<org::chromium::TpmNvramProxyMock> tpm_nvram_; |
| crossystem::Crossystem crossystem_; |
| testing::NiceMock<libstorage::MockPlatform> platform_; |
| }; |
| |
| // A variable |T| that need to be initialized & destructed manually. |
| template <typename T> |
| class ManualVariable { |
| public: |
| T* ptr() { return reinterpret_cast<T*>(storage_); } |
| |
| private: |
| alignas(T) uint8_t storage_[sizeof(T)]; |
| }; |
| |
| // Call the |Command| with fuzzed arguments synchronously. |
| template <auto Command, typename TupleType, std::size_t... I> |
| void FuzzCallSync(FuzzedDataProvider& data_provider, |
| Middleware middleware, |
| std::index_sequence<I...>) { |
| // According to the C++ spec, the execution order of function is unspecified. |
| // We will need to generated the input parameters one by one, otherwise the |
| // data_provider would be consumed with the unspecified order. |
| std::tuple<ManualVariable<std::tuple_element_t<I, TupleType>>...> data; |
| |
| // Create fuzzed objects in order on the stack. |
| ( |
| [&]() { |
| using Arg = std::tuple_element_t<I, TupleType>; |
| new (std::get<I>(data).ptr()) Arg(FuzzedObject<Arg>()(data_provider)); |
| }(), |
| ...); |
| |
| middleware.CallSync<Command>(std::move(*std::get<I>(data).ptr())...).ok(); |
| |
| // Cleanup fuzzed objects in reverse order on the stack. |
| ( |
| [&]() { |
| using Arg = std::tuple_element_t<sizeof...(I) - I - 1, TupleType>; |
| std::get<sizeof...(I) - I - 1>(data).ptr()->~Arg(); |
| }(), |
| ...); |
| } |
| |
| // A helper to get the input argument types from the |Func|. |
| template <auto Command, typename Func, typename = void> |
| struct FuzzCommandHelper { |
| static_assert(sizeof(Func) == -1, "Unknown member function"); |
| }; |
| |
| // Fuzz command helper for the synchronous backend call. |
| template <auto Command, typename R, typename S, typename... Args> |
| requires(std::convertible_to<Status, R>) |
| struct FuzzCommandHelper<Command, R (S::*)(Args...)> { |
| void Fuzz(FuzzedDataProvider& data_provider, Middleware middleware) { |
| FuzzCallSync< |
| Command, |
| std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>>( |
| data_provider, middleware, std::make_index_sequence<sizeof...(Args)>()); |
| } |
| }; |
| |
| // Fuzz command helper for the asynchronous backend call. |
| template <auto Command, typename R, typename S, typename... Args> |
| requires(std::convertible_to<Status, R>) |
| struct FuzzCommandHelper<Command, |
| void (S::*)(base::OnceCallback<void(R)>, Args...)> { |
| void Fuzz(FuzzedDataProvider& data_provider, Middleware middleware) { |
| FuzzCallSync< |
| Command, |
| std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>>( |
| data_provider, middleware, std::make_index_sequence<sizeof...(Args)>()); |
| } |
| }; |
| |
| // Call the |Command| on |middleware| with fuzzed arguments from |data_provider| |
| // . |
| template <auto Command> |
| void RunCommand(FuzzedDataProvider& data_provider, Middleware middleware) { |
| FuzzCommandHelper<Command, decltype(Command)>().Fuzz(data_provider, |
| middleware); |
| } |
| |
| // Run the nth command from the |CmdList| and index_sequence to enumerate the |
| // index. |
| template <typename CmdList, std::size_t... I> |
| void RunNthCommandListSeq(size_t n, |
| FuzzedDataProvider& data_provider, |
| Middleware middleware, |
| std::index_sequence<I...>) { |
| // fold expression with , operator. |
| ( |
| [&]() { |
| if (n == I) { |
| RunCommand<CmdList::template Get<I>()>(data_provider, middleware); |
| } |
| }(), |
| ...); |
| } |
| |
| // Run the nth command from the |CmdList|. |
| template <typename CmdList> |
| void RunNthCommandList(size_t n, |
| FuzzedDataProvider& data_provider, |
| Middleware middleware) { |
| RunNthCommandListSeq<CmdList>(n, data_provider, middleware, |
| std::make_index_sequence<CmdList::size>()); |
| } |
| |
| void FuzzMain(FuzzedDataProvider& data_provider) { |
| Tpm2BackendFuzzerProxy proxy(data_provider); |
| base::ScopedTempDir tmp_dir_; |
| CHECK(tmp_dir_.CreateUniqueTempDir()); |
| auto backend = std::make_unique<BackendTpm2>(proxy, MiddlewareDerivative{}, |
| tmp_dir_.GetPath(), nullptr); |
| BackendTpm2* backend_ptr = backend.get(); |
| auto middleware_owner = std::make_unique<MiddlewareOwner>( |
| std::move(backend), ThreadingMode::kCurrentThread); |
| // We are testing the backend, so we should not call set_data_provider here. |
| backend_ptr->set_middleware_derivative_for_test(middleware_owner->Derive()); |
| Middleware middleware(middleware_owner->Derive()); |
| |
| int command_count = data_provider.ConsumeIntegralInRange(1, kMaxCommandCount); |
| for (int i = 0; i < command_count; i++) { |
| if (data_provider.remaining_bytes() == 0) { |
| break; |
| } |
| size_t command_index = data_provider.ConsumeIntegralInRange( |
| static_cast<size_t>(0), FuzzCommandList::size - 1); |
| RunNthCommandList<FuzzCommandList>(command_index, data_provider, |
| middleware); |
| } |
| } |
| |
| FuzzedDataProvider* g_data_provider; |
| std::independent_bits_engine<std::mt19937, CHAR_BIT, unsigned char> g_engine; |
| |
| // Generating too much low entropy random data will cause the fuzzer stuck |
| // in the RSA keygen, we should not waste time for that kind of case. |
| uint32_t g_low_entropy_rand_count = 0; |
| |
| enum class RandByteType { |
| kQuick, |
| kConsume, |
| kZero, |
| kOne, |
| kMaxValue = kOne, |
| }; |
| |
| int FuzzRandBytes(unsigned char* buf, int num) { |
| if (g_data_provider == nullptr) { |
| return 0; |
| } |
| |
| if (g_low_entropy_rand_count > 4096) { |
| std::generate(buf, buf + num, std::ref(g_engine)); |
| return 1; |
| } |
| |
| switch (g_data_provider->ConsumeEnum<RandByteType>()) { |
| case RandByteType::kQuick: { |
| std::generate(buf, buf + num, std::ref(g_engine)); |
| break; |
| } |
| case RandByteType::kConsume: |
| // Reset the buffer first, because we may not have enough data in data |
| // provider. |
| memset(buf, 0, num); |
| g_data_provider->ConsumeData(buf, num); |
| break; |
| case RandByteType::kZero: |
| memset(buf, 0, num); |
| g_low_entropy_rand_count++; |
| break; |
| case RandByteType::kOne: |
| memset(buf, 0xff, num); |
| g_low_entropy_rand_count++; |
| break; |
| } |
| |
| return 1; |
| } |
| |
| int FuzzRandAdd(const void* buf, int num, double randomness) { |
| return 1; |
| } |
| |
| int FuzzRandSeed(const void* buf, int num) { |
| return 1; |
| } |
| |
| int FuzzRandStatus(void) { |
| return g_data_provider != nullptr; |
| } |
| |
| bool StaticInit() { |
| static RAND_METHOD rand_method = { |
| .seed = FuzzRandSeed, |
| .bytes = FuzzRandBytes, |
| .cleanup = nullptr, |
| .add = FuzzRandAdd, |
| .pseudorand = FuzzRandBytes, |
| .status = FuzzRandStatus, |
| }; |
| |
| base::CommandLine::Init(0, nullptr); |
| |
| CHECK(RAND_set_rand_method(&rand_method)); |
| |
| // Suppress log spam from the code-under-test. |
| logging::SetMinLogLevel(logging::LOGGING_FATAL); |
| return true; |
| } |
| |
| [[maybe_unused]] bool static_init = StaticInit(); |
| |
| } // namespace |
| } // namespace hwsec |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| FuzzedDataProvider data_provider(data, size); |
| hwsec::g_data_provider = &data_provider; |
| hwsec::g_engine.seed(0); |
| hwsec::g_low_entropy_rand_count = 0; |
| |
| hwsec::FuzzMain(data_provider); |
| return 0; |
| } |