diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
index a44a711e..81231400 100644
--- a/fuzzer/Android.bp
+++ b/fuzzer/Android.bp
@@ -128,3 +128,9 @@ cc_fuzz {
srcs: ["certificate_provisioning_fuzzer.cpp"],
defaults: ["libcdm_fuzzer_defaults"],
}
+
+cc_fuzz {
+ name: "device_files_fuzzer",
+ srcs: ["device_files_fuzzer.cpp"],
+ defaults: ["libcdm_fuzzer_defaults"],
+}
diff --git a/fuzzer/README.md b/fuzzer/README.md
index 9ab1e445..d313f2f0 100644
--- a/fuzzer/README.md
+++ b/fuzzer/README.md
@@ -12,6 +12,7 @@
+ [buffer_reader_fuzzer](#BufferReader)
+ [cdm_engine_fuzzer](#CdmEngine)
+ [certificate_provisioning_fuzzer](#CertificateProvisioning)
++ [device_files_fuzzer](#DeviceFile)
# Fuzzer for PolicyEngine
@@ -283,3 +284,23 @@ CertificateProvisioning supports the following parameters:
$ adb sync data
$ adb shell /data/fuzz/arm64/certificate_provisioning_fuzzer/vendor/certificate_provisioning_fuzzer
```
+
+# Fuzzer for DeviceFile
+
+DeviceFile supports the following parameters:
+1. AtscModeEnabled (parameter name: "atsc_mode_enabled")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`AtscModeEnabled`| `Bool` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) device_files_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/device_files_fuzzer/vendor/device_files_fuzzer
+```
diff --git a/fuzzer/device_files_fuzzer.cpp b/fuzzer/device_files_fuzzer.cpp
new file mode 100644
index 00000000..d511bc47
--- /dev/null
+++ b/fuzzer/device_files_fuzzer.cpp
@@ -0,0 +1,508 @@
+/*
+ * 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
+
+using namespace wvcdm;
+using namespace wvutil;
+using namespace video_widevine;
+
+static constexpr uint16_t kMaxByte = 256;
+static constexpr uint16_t kMaxVectorSize = 1000;
+static constexpr uint8_t kMinVectorSize = 0;
+static constexpr uint8_t kMinKeySetId = 0;
+static constexpr uint8_t kMaxKeySetId = 100;
+
+class DeviceFilesFuzzer {
+public:
+ DeviceFilesFuzzer(const uint8_t *data, size_t size) : mFdp(data, size){};
+ void process();
+
+private:
+ FuzzedDataProvider mFdp;
+};
+
+void createLicenseData(DeviceFiles::CdmLicenseData &licenseData,
+ FuzzedDataProvider &mFdp) {
+ std::map appParameters;
+ appParameters[mFdp.ConsumeBytesAsString(kMaxByte)] =
+ mFdp.ConsumeBytesAsString(kMaxByte);
+
+ licenseData.key_set_id = std::to_string(
+ mFdp.ConsumeIntegralInRange(kMinKeySetId, kMaxKeySetId));
+ licenseData.state =
+ (CdmOfflineLicenseState)mFdp.ConsumeIntegralInRange(
+ kLicenseStateActive, kLicenseStateUnknown);
+ licenseData.pssh_data = mFdp.ConsumeRandomLengthString(kMaxByte);
+ licenseData.license_request = mFdp.ConsumeRandomLengthString(kMaxByte);
+ licenseData.license = mFdp.ConsumeRandomLengthString(kMaxByte);
+ licenseData.license_renewal_request =
+ mFdp.ConsumeRandomLengthString(kMaxByte);
+ licenseData.license_renewal = mFdp.ConsumeRandomLengthString(kMaxByte);
+ licenseData.release_server_url = mFdp.ConsumeRandomLengthString(kMaxByte);
+ licenseData.playback_start_time = mFdp.ConsumeIntegral();
+ licenseData.last_playback_time = mFdp.ConsumeIntegral();
+ licenseData.grace_period_end_time = mFdp.ConsumeIntegral();
+ licenseData.app_parameters = appParameters;
+ licenseData.usage_entry = mFdp.ConsumeRandomLengthString(kMaxByte);
+ licenseData.usage_entry_index = mFdp.ConsumeIntegral();
+ licenseData.drm_certificate = mFdp.ConsumeRandomLengthString(kMaxByte);
+ licenseData.wrapped_private_key = CryptoWrappedKey(
+ (CryptoWrappedKey::Type)mFdp.ConsumeIntegralInRange(
+ CryptoWrappedKey::Type::kUninitialized, CryptoWrappedKey::Type::kEcc),
+ mFdp.ConsumeRandomLengthString(kMaxByte));
+}
+
+void createUsageData(DeviceFiles::CdmUsageData &usageData,
+ FuzzedDataProvider &mFdp) {
+ usageData.provider_session_token = mFdp.ConsumeRandomLengthString(kMaxByte);
+ usageData.license_request = mFdp.ConsumeRandomLengthString(kMaxByte);
+ usageData.license = mFdp.ConsumeRandomLengthString(kMaxByte);
+ usageData.key_set_id = std::to_string(
+ mFdp.ConsumeIntegralInRange(kMinKeySetId, kMaxKeySetId));
+ usageData.usage_entry = mFdp.ConsumeRandomLengthString(kMaxByte);
+ usageData.usage_entry_index = mFdp.ConsumeIntegral();
+ usageData.drm_certificate = mFdp.ConsumeRandomLengthString(kMaxByte);
+ usageData.wrapped_private_key = CryptoWrappedKey(
+ (CryptoWrappedKey::Type)mFdp.ConsumeIntegralInRange(
+ CryptoWrappedKey::Type::kUninitialized, CryptoWrappedKey::Type::kEcc),
+ mFdp.ConsumeRandomLengthString(kMaxByte));
+}
+
+void createCertificateAndKey(std::string &certificate, CryptoWrappedKey &key,
+ FuzzedDataProvider &mFdp) {
+ DrmCertificate drmCertificate;
+ drmCertificate.set_type(
+ (DrmCertificate_Type)mFdp.ConsumeIntegralInRange(
+ DrmCertificate_Type::DrmCertificate_Type_ROOT,
+ DrmCertificate_Type::DrmCertificate_Type_PROVISIONER));
+ drmCertificate.set_serial_number(
+ std::to_string(mFdp.ConsumeIntegral()));
+ drmCertificate.set_system_id(mFdp.ConsumeIntegral());
+ drmCertificate.set_creation_time_seconds(mFdp.ConsumeIntegral());
+ drmCertificate.set_expiration_time_seconds(mFdp.ConsumeIntegral());
+ std::string setDrmCertificate;
+ drmCertificate.SerializeToString(&setDrmCertificate);
+
+ SignedDrmCertificate signedDrmCertificate;
+ if (mFdp.ConsumeBool()) {
+ signedDrmCertificate.set_drm_certificate(setDrmCertificate);
+ }
+
+ signedDrmCertificate.SerializeToString(&certificate);
+
+ key = CryptoWrappedKey(
+ (CryptoWrappedKey::Type)mFdp.ConsumeIntegralInRange(
+ CryptoWrappedKey::Type::kUninitialized, CryptoWrappedKey::Type::kEcc),
+ mFdp.ConsumeBytesAsString(kMaxByte));
+}
+
+void DeviceFilesFuzzer::process() {
+ FileSystem fileSystem;
+ DeviceFiles deviceFiles(mFdp.ConsumeBool() ? &fileSystem : nullptr);
+ deviceFiles.Reset((CdmSecurityLevel)mFdp.ConsumeIntegralInRange(
+ kSecurityLevelUninitialized, kSecurityLevelUnknown));
+
+ while (mFdp.remaining_bytes()) {
+ auto invokeDeviceFilesAPI = mFdp.PickValueInArray<
+ const std::function>(
+ {[&]() {
+ std::string certificate;
+ CryptoWrappedKey wrappedPrivateKey;
+ createCertificateAndKey(certificate, wrappedPrivateKey, mFdp);
+ deviceFiles.StoreCertificate(mFdp.ConsumeBool() ? certificate : "",
+ wrappedPrivateKey);
+ },
+
+ [&]() {
+ bool AtscModeEnabled = mFdp.ConsumeBool();
+ std::string certificate;
+ CryptoWrappedKey privateKey;
+ std::string serialNumber;
+ uint32_t systemId;
+
+ deviceFiles.RetrieveCertificate(
+ AtscModeEnabled, mFdp.ConsumeBool() ? &certificate : nullptr,
+ &privateKey, mFdp.ConsumeBool() ? &serialNumber : nullptr,
+ mFdp.ConsumeBool() ? &systemId : nullptr);
+ },
+
+ [&]() {
+ std::string certificate;
+ CryptoWrappedKey privateKey;
+ std::string serialNumber;
+ uint32_t systemId;
+
+ deviceFiles.RetrieveLegacyCertificate(&certificate, &privateKey,
+ &serialNumber, &systemId);
+ },
+
+ [&]() { deviceFiles.RemoveCertificate(); },
+
+ [&]() {
+ std::string certificate;
+ CryptoWrappedKey wrappedPrivateKey;
+ createCertificateAndKey(certificate, wrappedPrivateKey, mFdp);
+
+ deviceFiles.StoreOemCertificate(
+ mFdp.ConsumeBool() ? certificate : "", wrappedPrivateKey);
+ },
+
+ [&]() {
+ std::string certificate;
+ CryptoWrappedKey privateKey;
+
+ deviceFiles.RetrieveOemCertificate(&certificate, &privateKey);
+ },
+
+ [&]() { deviceFiles.HasOemCertificate(); },
+
+ [&]() { deviceFiles.RemoveOemCertificate(); },
+
+ [&]() {
+ DeviceFiles::CdmLicenseData licenseData;
+ createLicenseData(licenseData, mFdp);
+ DeviceFiles::ResponseType result;
+ deviceFiles.StoreLicense(licenseData,
+ mFdp.ConsumeBool() ? &result : nullptr);
+ },
+
+ [&]() {
+ DeviceFiles::CdmLicenseData licenseData;
+ DeviceFiles::ResponseType result;
+
+ deviceFiles.RetrieveLicense(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* key_set_id */
+ mFdp.ConsumeBool() ? &licenseData : nullptr,
+ mFdp.ConsumeBool() ? &result : nullptr);
+ },
+
+ [&]() {
+ deviceFiles.StoreAtscLicense(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* key_set_id */
+ mFdp.ConsumeRandomLengthString(
+ kMaxByte) /* serialized_license_data */
+ );
+ },
+
+ [&]() {
+ deviceFiles.DeleteLicense(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)) /* key_set_id */
+ );
+ },
+
+ [&]() {
+ std::vector keySetIds;
+
+ deviceFiles.ListLicenses(&keySetIds);
+ },
+
+ [&]() { deviceFiles.DeleteAllFiles(); },
+
+ [&]() { deviceFiles.DeleteAllLicenses(); },
+
+ [&]() {
+ deviceFiles.LicenseExists(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)) /* key_set_id */
+ );
+ },
+
+ [&]() {
+ deviceFiles.ReserveLicenseId(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)) /* key_set_id */
+ );
+ },
+
+ [&]() {
+ deviceFiles.UnreserveLicenseId(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)) /* key_set_id */
+ );
+ },
+
+ [&]() {
+ deviceFiles.StoreUsageInfo(
+ mFdp.ConsumeRandomLengthString(
+ kMaxByte), /* provider_session_token */
+ mFdp.ConsumeRandomLengthString(kMaxByte), /* key_request */
+ mFdp.ConsumeRandomLengthString(kMaxByte), /* key_response */
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* key_set_id */
+ mFdp.ConsumeRandomLengthString(kMaxByte), /* usage_entry */
+ mFdp.ConsumeIntegral(), /* usage_entry_index */
+ mFdp.ConsumeRandomLengthString(kMaxByte), /* drm_certificate */
+ CryptoWrappedKey(
+ (CryptoWrappedKey::Type)mFdp.ConsumeIntegralInRange(
+ CryptoWrappedKey::Type::kUninitialized,
+ CryptoWrappedKey::Type::kEcc), /* type */
+ mFdp.ConsumeRandomLengthString(kMaxByte) /* key */
+ ) /* wrapped_private_key */
+ );
+ },
+
+ [&]() {
+ std::vector keySetIds;
+ std::vector providerSessionTokens;
+
+ deviceFiles.ListUsageIds(
+ mFdp.ConsumeRandomLengthString(kMaxByte), /* app_id */
+ mFdp.ConsumeBool() ? &keySetIds : nullptr,
+ mFdp.ConsumeBool() ? &providerSessionTokens : nullptr);
+ },
+
+ [&]() {
+ std::string providerSessionToken;
+
+ deviceFiles.GetProviderSessionToken(
+ mFdp.ConsumeRandomLengthString(kMaxByte), /* app_id */
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* key_set_id */
+ &providerSessionToken);
+ },
+
+ [&]() {
+ deviceFiles.DeleteUsageInfo(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)) /* key_set_id */
+ );
+ },
+
+ [&]() {
+ uint32_t keySetIdsSize = mFdp.ConsumeIntegralInRange(
+ kMinVectorSize, kMaxVectorSize);
+ std::vector keySetIds;
+ for (int i = 0; i < keySetIdsSize; ++i)
+ keySetIds.push_back(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)) /* key_set_id */
+ );
+
+ deviceFiles.DeleteMultipleUsageInfoByKeySetIds(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ keySetIds);
+ },
+
+ [&]() {
+ std::vector providerSessionTokens;
+
+ deviceFiles.DeleteAllUsageInfoForApp(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ &providerSessionTokens);
+ },
+
+ [&]() { deviceFiles.DeleteAllUsageInfo(); },
+
+ [&]() {
+ CdmKeyMessage licenseRequest;
+ CdmKeyResponse license;
+ UsageEntry usageEntry;
+ UsageEntryIndex usageEntryIndex;
+ std::string drmCertificate;
+ CryptoWrappedKey wrappedPrivateKey;
+
+ deviceFiles.RetrieveUsageInfo(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* provider_session_token */
+ &licenseRequest, &license, &usageEntry, &usageEntryIndex,
+ &drmCertificate, &wrappedPrivateKey);
+ },
+
+ [&]() {
+ std::string providerSessionToken;
+ CdmKeyMessage licenseRequest;
+ CdmKeyResponse license;
+ UsageEntry usageEntry;
+ UsageEntryIndex usageEntryIndex;
+ std::string drmCertificate;
+ CryptoWrappedKey wrappedPrivateKey;
+
+ deviceFiles.RetrieveUsageInfoByKeySetId(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* key_set_id */
+ &providerSessionToken, &licenseRequest, &license, &usageEntry,
+ &usageEntryIndex, &drmCertificate, &wrappedPrivateKey);
+ },
+
+ [&]() {
+ std::vector usageInfoFileNames;
+
+ deviceFiles.ListUsageInfoFiles(&usageInfoFileNames);
+ },
+
+ [&]() {
+ std::vector usageData;
+
+ deviceFiles.RetrieveUsageInfo(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ &usageData);
+ },
+
+ [&]() {
+ std::string providerSessionToken =
+ mFdp.ConsumeRandomLengthString(kMaxByte);
+ DeviceFiles::CdmUsageData usageData;
+
+ deviceFiles.RetrieveUsageInfo(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ providerSessionToken, &usageData);
+ },
+
+ [&]() {
+ uint32_t usageDataSize = mFdp.ConsumeIntegralInRange(
+ kMinVectorSize, kMaxVectorSize);
+ std::vector usageData;
+ for (int i = 0; i < usageDataSize; ++i) {
+ DeviceFiles::CdmUsageData unit;
+ createUsageData(unit, mFdp);
+ usageData.push_back(unit);
+ }
+
+ deviceFiles.StoreUsageInfo(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ usageData);
+ },
+
+ [&]() {
+ DeviceFiles::CdmUsageData usageData;
+ createUsageData(usageData, mFdp);
+ deviceFiles.UpdateUsageInfo(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* usage_info_file_name */
+ usageData);
+ },
+
+ [&]() {
+ uint32_t mediaSegmentIvSize = mFdp.ConsumeIntegralInRange(
+ kMinVectorSize, kMaxVectorSize);
+ std::vector mediaSegmentIv;
+ for (int i = 0; i < mediaSegmentIvSize; ++i)
+ mediaSegmentIv.push_back(mFdp.ConsumeIntegral());
+
+ deviceFiles.StoreHlsAttributes(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* key_set_id */
+ (CdmHlsMethod)mFdp.ConsumeIntegralInRange(
+ kHlsMethodNone, kHlsMethodSampleAes), /* method */
+ mediaSegmentIv);
+ },
+
+ [&]() {
+ CdmHlsMethod method;
+ std::vector mediaSegmentIv;
+
+ deviceFiles.RetrieveHlsAttributes(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)), /* key_set_id */
+ &method, &mediaSegmentIv);
+ },
+
+ [&]() {
+ deviceFiles.DeleteHlsAttributes(
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId)) /* key_set_id */
+ );
+ },
+
+ [&]() {
+ uint32_t usageEntryInfoListSize =
+ mFdp.ConsumeIntegralInRange(kMinVectorSize,
+ kMaxVectorSize);
+ std::vector usageEntryInfoList;
+ for (int i = 0; i < usageEntryInfoListSize; ++i) {
+ CdmUsageEntryInfo unit;
+
+ unit.storage_type =
+ (CdmUsageEntryStorageType)mFdp.ConsumeIntegralInRange(
+ kStorageLicense, kStorageTypeUnknown);
+ unit.key_set_id = mFdp.ConsumeRandomLengthString(kMaxByte);
+ unit.usage_info_file_name =
+ std::to_string(mFdp.ConsumeIntegralInRange(
+ kMinKeySetId, kMaxKeySetId));
+ unit.last_use_time = mFdp.ConsumeIntegral();
+ unit.offline_license_expiry_time = mFdp.ConsumeIntegral();
+ usageEntryInfoList.push_back(unit);
+ }
+
+ deviceFiles.StoreUsageTableInfo(
+ mFdp.ConsumeRandomLengthString(
+ kMaxByte), /* usage_table_header */
+ usageEntryInfoList);
+ },
+
+ [&]() {
+ UsageTableHeader usageTableHeader;
+ std::vector usageEntryInfoList;
+ bool lruUpgrade;
+
+ deviceFiles.RetrieveUsageTableInfo(&usageTableHeader,
+ &usageEntryInfoList, &lruUpgrade);
+ },
+
+ [&]() { deviceFiles.DeleteUsageTableInfo(); },
+
+ [&]() {
+ okp::SystemFallbackInfo info;
+ info.SetState((okp::SystemState)mFdp.ConsumeIntegralInRange(
+ (int)okp::SystemState::kUnknown,
+ (int)okp::SystemState::kProvisioned));
+ info.SetFirstCheckedTime(mFdp.ConsumeIntegral());
+ info.SetBackoffStartTime(mFdp.ConsumeIntegral());
+ info.SetBackoffDuration(mFdp.ConsumeIntegral());
+ info.SetProvisioningTime(mFdp.ConsumeIntegral());
+
+ deviceFiles.StoreOkpInfo(info);
+ },
+
+ [&]() {
+ okp::SystemFallbackInfo info;
+
+ deviceFiles.RetrieveOkpInfo(&info);
+ },
+
+ [&]() { deviceFiles.DeleteOkpInfo(); }});
+
+ invokeDeviceFilesAPI();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ DeviceFilesFuzzer deviceFilesFuzzer(data, size);
+ deviceFilesFuzzer.process();
+ return 0;
+}