/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include #include #include using namespace wvcdm; using namespace wvutil; using namespace wvcdm::metrics; static constexpr int32_t kMinByte = 0; static constexpr int32_t kMaxByte = 256; static constexpr int32_t kMaxEnum = 4; static constexpr int32_t kMinEnum = 0; static constexpr int32_t kMaxRequestedSecurityLevel = 1; static constexpr int32_t kMinRequestedSecurityLevel = 0; class FuzzDeviceFiles : public DeviceFiles { public: FuzzDeviceFiles(wvutil::FileSystem *fs, FuzzedDataProvider *fdp) : DeviceFiles(fs), fdp_(fdp) {} bool Init(CdmSecurityLevel) override { return fdp_->ConsumeBool(); } DeviceFiles::CertificateState RetrieveOemCertificate( std::string *certificate, CryptoWrappedKey * /*wrapped_private_key*/) override { *certificate = fdp_->ConsumeRandomLengthString(kMaxByte); return (DeviceFiles::CertificateState)fdp_->ConsumeIntegralInRange( kMinEnum, kMaxEnum); } private: FuzzedDataProvider *fdp_; }; class FuzzFile : public File { public: FuzzFile(FuzzedDataProvider *fdp) : fdp_(fdp) {} ssize_t Read(char *buffer, size_t bytes) { std::vector init_data = fdp_->ConsumeBytes( fdp_->ConsumeIntegralInRange(kMinByte, bytes)); buffer = init_data.data(); return init_data.size(); }; ssize_t Write(const char * /* buffer*/, size_t bytes) { return fdp_->ConsumeIntegralInRange(kMinByte, bytes); }; private: FuzzedDataProvider *fdp_; }; class FuzzFileSystem : public FileSystem { public: FuzzFileSystem(FuzzedDataProvider *fdp) : fdp_(fdp) {} std::unique_ptr Open(const std::string &, int) { return std::unique_ptr(new FuzzFile(fdp_)); } bool Exists(const std::string &) { return fdp_->ConsumeBool(); } bool Remove(const std::string &) { return fdp_->ConsumeBool(); } ssize_t FileSize(const std::string &) { return fdp_->ConsumeIntegralInRange(kMinByte, kMaxByte); } bool List(const std::string &, std::vector *) { return fdp_->ConsumeBool(); } private: FuzzedDataProvider *fdp_; }; class FuzzCryptoSession : public CryptoSession { public: FuzzCryptoSession(metrics::CryptoMetrics *metrics, FuzzedDataProvider *fdp) : CryptoSession(metrics) { fdp_ = fdp; } ~FuzzCryptoSession() override {} bool IsOpen() override { return fdp_->ConsumeBool(); } bool GetCachedSystemId(uint32_t * /*system_id*/) override { return fdp_->ConsumeBool(); } void SetSystemId(uint32_t /*system_id*/) override {} CdmSecurityLevel GetSecurityLevel(RequestedSecurityLevel /*level*/) override { return (CdmSecurityLevel)fdp_->ConsumeIntegralInRange(kMinEnum, kMaxEnum); } CdmResponseType GetProvisioningMethod( RequestedSecurityLevel /*level*/, CdmClientTokenType *token_type) override { *token_type = (CdmClientTokenType)fdp_->ConsumeIntegralInRange(kMinEnum, kMaxEnum); return CdmResponseType( fdp_->PickValueInArray(kCdmResponseEnums)); } CdmResponseType GetTokenFromKeybox(RequestedSecurityLevel /*level*/, std::string *key_data) override { *key_data = fdp_->ConsumeRandomLengthString(kMaxByte); return CdmResponseType( fdp_->PickValueInArray(kCdmResponseEnums)); } CdmResponseType GetTokenFromOemCert(RequestedSecurityLevel /*level*/, std::string *oem_cert) override { *oem_cert = fdp_->ConsumeRandomLengthString(kMaxByte); return CdmResponseType( fdp_->PickValueInArray(kCdmResponseEnums)); } void SetSystemIdBase(uint32_t /* system_id*/) {} private: FuzzedDataProvider *fdp_; }; class SystemIdExtractorFuzzer { public: SystemIdExtractorFuzzer(const uint8_t *data, size_t size) : fdp_(data, size){}; void Process(); private: FuzzedDataProvider fdp_; }; void SystemIdExtractorFuzzer::Process() { FuzzFileSystem fuzz_file_system(&fdp_); metrics::CryptoMetrics crypto_metrics; FuzzDeviceFiles device_files(&fuzz_file_system, &fdp_); RequestedSecurityLevel security_level = (RequestedSecurityLevel)fdp_.ConsumeIntegralInRange( kMinRequestedSecurityLevel, kMaxRequestedSecurityLevel); std::unique_ptr crypto_sessions = std::make_unique(&crypto_metrics, &fdp_); std::unique_ptr system_id_extractor = std::make_unique(security_level, crypto_sessions.get(), &fuzz_file_system); while (fdp_.remaining_bytes()) { auto invoke_system_id_extractor_API = fdp_.PickValueInArray>({ [&]() { uint32_t system_id; system_id = fdp_.ConsumeIntegralInRange(kMinByte, kMaxByte); system_id_extractor->ExtractSystemId(&system_id); }, [&]() { uint32_t system_id; system_id = fdp_.ConsumeIntegralInRange(kMinByte, kMaxByte); const std::string key_data = fdp_.ConsumeRandomLengthString(kMaxByte); system_id_extractor->ExtractSystemIdFromKeyboxData(key_data, &system_id); }, [&]() { uint32_t system_id; system_id = fdp_.ConsumeIntegralInRange(kMinByte, kMaxByte); const std::string oem_cert = fdp_.ConsumeRandomLengthString(kMaxByte); system_id_extractor->ExtractSystemIdFromOemCert(oem_cert, &system_id); }, [&]() { system_id_extractor->SetDeviceFilesForTesting(&device_files); }, }); invoke_system_id_extractor_API(); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { SystemIdExtractorFuzzer system_id_extractor_fuzzer(data, size); system_id_extractor_fuzzer.Process(); return 0; }