diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
index 17cc0be2..2553b5bc 100644
--- a/fuzzer/Android.bp
+++ b/fuzzer/Android.bp
@@ -116,3 +116,9 @@ cc_fuzz {
srcs: ["buffer_reader_fuzzer.cpp"],
defaults: ["libcdm_fuzzer_defaults"],
}
+
+cc_fuzz {
+ name: "cdm_engine_fuzzer",
+ srcs: ["cdm_engine_fuzzer.cpp"],
+ defaults: ["libcdm_fuzzer_defaults"],
+}
diff --git a/fuzzer/README.md b/fuzzer/README.md
index a7497964..9a6f74df 100644
--- a/fuzzer/README.md
+++ b/fuzzer/README.md
@@ -10,6 +10,7 @@
+ [cdm_license_fuzzer](#CdmLicense)
+ [crypto_session_fuzzer](#CryptoSession)
+ [buffer_reader_fuzzer](#BufferReader)
++ [cdm_engine_fuzzer](#CdmEngine)
# Fuzzer for PolicyEngine
@@ -232,3 +233,29 @@ BufferReader supports the following parameters:
$ adb sync data
$ adb shell /data/fuzz/arm64/buffer_reader_fuzzer/vendor/buffer_reader_fuzzer
```
+
+# Fuzzer for CdmEngine
+
+CdmEngine supports the following parameters:
+1. Key System (parameter name: "keySystem")
+2. Level (parameter name: "level")
+3. Frame Number (parameter name: "frameNum")
+4. Spoid (parameter name: "spoid")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`keySystem`| `String` |Value obtained from FuzzedDataProvider|
+|`level`| `int32_t` |Value obtained from FuzzedDataProvider|
+|`frameNum`| `unit32_t` |Value obtained from FuzzedDataProvider|
+|`spoid`| `String` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) cdm_engine_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell LD_LIBRARY_PATH=/vendor/lib64 /data/fuzz/arm64/cdm_engine_fuzzer/vendor/cdm_engine_fuzzer
+```
diff --git a/fuzzer/cdm_engine_fuzzer.cpp b/fuzzer/cdm_engine_fuzzer.cpp
new file mode 100644
index 00000000..2d6557e8
--- /dev/null
+++ b/fuzzer/cdm_engine_fuzzer.cpp
@@ -0,0 +1,501 @@
+/*
+ * 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 "vendor_widevine_fuzz_helper.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+const int32_t kMinByte = 0;
+const int32_t kMaxByte = 256;
+const int32_t kMinEnum = 0;
+const int32_t kMaxEnum = 4;
+const int32_t kMinValue = 0;
+const int32_t kMaxValue = 1;
+const int32_t kMinKey = 10;
+const int32_t kMaxKey = 1000;
+const int32_t kMinSize = 1;
+const int32_t kMaxSize = 100;
+const char* kKeySystem = "widevine";
+const char* kKeySetIdPrefix = "ksid";
+const char* kEmptyString = "";
+const std::string kUsageFilePrefixL1 = "/data/vendor/mediadrm/IDM0/L1/";
+const std::string kUsageFilePrefixL3 = "/data/vendor/mediadrm/IDM0/L3/";
+const std::string kCertFile = kUsageFilePrefixL3 + "cert.bin";
+const std::string kCertFile1 = kUsageFilePrefixL3 + "cert1.bin";
+
+using namespace wvutil;
+using namespace wvcdm::metrics;
+using namespace drm_metrics;
+using namespace wvcdm;
+
+std::string kQueryToken[] = {QUERY_KEY_SECURITY_LEVEL,
+ QUERY_KEY_PLAY_ALLOWED,
+ QUERY_KEY_CURRENT_HDCP_LEVEL,
+ QUERY_KEY_MAX_HDCP_LEVEL,
+ QUERY_KEY_USAGE_SUPPORT,
+ QUERY_KEY_NUMBER_OF_OPEN_SESSIONS,
+ QUERY_KEY_MAX_NUMBER_OF_SESSIONS,
+ QUERY_KEY_OEMCRYPTO_API_VERSION,
+ QUERY_KEY_CURRENT_SRM_VERSION,
+ QUERY_KEY_SRM_UPDATE_SUPPORT,
+ QUERY_KEY_WVCDM_VERSION,
+ QUERY_KEY_RESOURCE_RATING_TIER,
+ QUERY_KEY_OEMCRYPTO_BUILD_INFORMATION,
+ QUERY_KEY_DECRYPT_HASH_SUPPORT,
+ QUERY_KEY_PROVISIONING_MODEL,
+ QUERY_KEY_MAX_USAGE_TABLE_ENTRIES,
+ QUERY_KEY_OEMCRYPTO_API_MINOR_VERSION,
+ QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES,
+ QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT,
+ QUERY_KEY_WATERMARKING_SUPPORT,
+ QUERY_KEY_PRODUCTION_READY,
+ QUERY_KEY_SYSTEM_ID,
+ QUERY_KEY_DEBUG_BOOT_CERTIFICATE_CHAIN,
+ QUERY_KEY_DEVICE_ID,
+ QUERY_KEY_PROVISIONING_ID};
+
+std::string kInitType[] = {ISO_BMFF_VIDEO_MIME_TYPE, WEBM_VIDEO_MIME_TYPE,
+ HLS_INIT_DATA_FORMAT, CENC_INIT_DATA_FORMAT,
+ ISO_BMFF_AUDIO_MIME_TYPE, WEBM_AUDIO_MIME_TYPE,
+ WEBM_INIT_DATA_FORMAT};
+
+class FuzzWvCdmEventListener : public WvCdmEventListener {
+public:
+ void OnSessionRenewalNeeded(const CdmSessionId & /*session_id*/) {}
+ void OnSessionKeysChange(const CdmSessionId & /*session_id*/,
+ const CdmKeyStatusMap & /*keys_status*/,
+ bool /*has_new_usable_key*/) {}
+ void OnExpirationUpdate(const CdmSessionId & /*session_id*/,
+ int64_t /*new_expiry_time_seconds*/) {}
+};
+
+class CdmEngineFuzzer {
+public:
+ CdmEngineFuzzer(const uint8_t *data, size_t size) : mFdp(data, size){};
+ void process();
+ void init(CdmEngine *cdmEngine);
+ void createUsageFile(std::string mAppId);
+ std::vector createVector(bool enableKeySetId);
+
+private:
+ FuzzedDataProvider mFdp;
+ std::ofstream mOutCertFile1;
+ std::ofstream mOutCertFile2;
+ std::ofstream mOutUsageFile1;
+ std::ofstream mOutUsageFile2;
+ std::string mAppId;
+ std::string mKeyId;
+ std::string mSign;
+ std::string mDefaultUrl;
+ std::unique_ptr mFileSystem =
+ std::make_unique();
+ std::unique_ptr mFuzzCdmClientPropertySet =
+ std::make_unique(&mFdp);
+ CdmSessionId mSessionId;
+ CdmKeySystem mKeySystem;
+ CdmKeySetId mKeySetId;
+};
+
+void CdmEngineFuzzer::createUsageFile(std::string mAppId) {
+ /**
+ * These files are being fetched by the GetUsageInfo() &
+ * RemoveAllUsageInfo() APIs, since they were not created
+ * by any other API calls in the fuzzer, we are creating them.
+ */
+ DeviceFiles deviceFiles(mFileSystem.get());
+ std::string fileName = deviceFiles.GetUsageInfoFileName(mAppId);
+ std::string createFile1 = kUsageFilePrefixL1 + fileName;
+ std::string createFile2 = kUsageFilePrefixL3 + fileName;
+ mOutUsageFile1.open(createFile1.c_str());
+ mOutUsageFile2.open(createFile2.c_str());
+}
+
+std::vector CdmEngineFuzzer::createVector(bool enableKeySetId) {
+ int32_t size = mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize);
+ std::vector vector;
+ for (int i = 0; i < size; ++i) {
+ vector.push_back(enableKeySetId ? mKeySetId
+ : mFdp.ConsumeRandomLengthString(kMaxByte));
+ }
+ return vector;
+}
+
+void CdmEngineFuzzer::init(CdmEngine *cdmEngine) {
+ mAppId =
+ std::to_string(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+ mKeyId =
+ std::to_string(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+ mSign = mFdp.ConsumeRandomLengthString(kMaxByte);
+
+ mKeySystem = mFdp.ConsumeBool() ? kKeySystem
+ : mFdp.ConsumeRandomLengthString(kMaxByte);
+
+ FuzzWvCdmEventListener fuzzWvCdmEventListener;
+ cdmEngine->OpenSession(
+ mKeySystem,
+ mFdp.ConsumeBool() ? mFuzzCdmClientPropertySet.get() : nullptr,
+ mFdp.ConsumeBool() ? &fuzzWvCdmEventListener : nullptr, &mSessionId);
+
+ std::string request;
+ mDefaultUrl = mFdp.ConsumeRandomLengthString(kMaxByte);
+ cdmEngine->GetProvisioningRequest(
+ (CdmCertificateType)mFdp.ConsumeIntegralInRange(kMinValue,
+ kMaxValue),
+ mFdp.ConsumeRandomLengthString(kMaxByte) /* cert_authority */,
+ mFdp.ConsumeRandomLengthString(kMaxByte) /* service_certificate */,
+ (RequestedSecurityLevel)mFdp.ConsumeIntegralInRange(kMinValue,
+ kMaxValue),
+ mFdp.ConsumeBool() ? &request : nullptr, &mDefaultUrl);
+
+ std::string cert;
+ std::string wrappedKey;
+ CdmProvisioningResponse responseMessage =
+ mFdp.ConsumeRandomLengthString(kMaxByte);
+ cdmEngine->HandleProvisioningResponse(
+ responseMessage,
+ (RequestedSecurityLevel)mFdp.ConsumeIntegralInRange(kMinValue,
+ kMaxValue),
+ mFdp.ConsumeBool() ? &cert : nullptr,
+ mFdp.ConsumeBool() ? &wrappedKey : nullptr);
+
+ CdmAppParameterMap appParameters;
+ appParameters.insert({mFdp.ConsumeRandomLengthString(kMaxByte),
+ mFdp.ConsumeRandomLengthString(kMaxByte)});
+ CdmInitData data = mFdp.ConsumeRandomLengthString(kMaxByte);
+ const std::string oecVersion =
+ std::to_string(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+ InitializationData init_data(mFdp.PickValueInArray(kInitType),
+ data, oecVersion);
+
+ mKeySetId =
+ kKeySetIdPrefix +
+ std::to_string(mFdp.ConsumeIntegralInRange(kMinKey, kMaxKey));
+
+ CdmLicenseType generateLicType =
+ static_cast(mFdp.ConsumeIntegralInRange(
+ static_cast(CdmLicenseType::kLicenseTypeOffline),
+ static_cast(CdmLicenseType::kLicenseTypeEmbeddedKeyData)));
+ CdmKeyRequest keyRequest;
+ keyRequest.message = mFdp.ConsumeRandomLengthString(kMaxByte);
+ keyRequest.type = static_cast(mFdp.ConsumeIntegralInRange(
+ static_cast(CdmKeyRequestType::kKeyRequestTypeUnknown),
+ static_cast(CdmKeyRequestType::kKeyRequestTypeUpdate)));
+ keyRequest.url = mFdp.ConsumeBool()
+ ? mDefaultUrl
+ : mFdp.ConsumeRandomLengthString(kMaxByte);
+ cdmEngine->GenerateKeyRequest(mSessionId,
+ mFdp.ConsumeBool() ? mKeySetId : kEmptyString,
+ init_data, generateLicType, appParameters,
+ mFdp.ConsumeBool() ? &keyRequest : nullptr);
+
+ CdmLicenseType addLicType =
+ static_cast(mFdp.ConsumeIntegralInRange(
+ static_cast(CdmLicenseType::kLicenseTypeOffline),
+ static_cast(CdmLicenseType::kLicenseTypeEmbeddedKeyData)));
+ CdmKeyResponse keyData =
+ std::to_string(mFdp.ConsumeIntegralInRange(kMinKey, kMaxKey));
+ cdmEngine->AddKey(mSessionId, mFdp.ConsumeBool() ? keyData : kEmptyString,
+ &addLicType, &mKeySetId);
+}
+
+void CdmEngineFuzzer::process() {
+ CdmEngine *cdmEngine = CdmEngineFactory::CreateCdmEngine(mFileSystem.get());
+
+ CdmEngineFuzzer::init(cdmEngine);
+
+ while (mFdp.remaining_bytes()) {
+ auto invokeCdmEngineAPI = mFdp.PickValueInArray<
+ const std::function>({
+ [&]() { cdmEngine->OnTimerEvent(); },
+ [&]() { cdmEngine->IsOpenSession(mSessionId); },
+ [&]() { cdmEngine->SetDefaultOtaKeyboxFallbackDurationRules(); },
+ [&]() { cdmEngine->SetFastOtaKeyboxFallbackDurationRules(); },
+ [&]() {
+ cdmEngine->OpenSession(
+ mKeySystem, nullptr /* property_set */,
+ mFdp.ConsumeRandomLengthString(kMaxByte) /* forced_session_id */,
+ nullptr /* event_listener */);
+ },
+ [&]() {
+ cdmEngine->StoreAtscLicense(
+ static_cast(mFdp.ConsumeIntegralInRange(
+ static_cast(RequestedSecurityLevel::kLevelDefault),
+ static_cast(RequestedSecurityLevel::kLevel3))),
+ mKeySetId,
+ mFdp.ConsumeRandomLengthString(
+ kMaxByte) /* serialized_license_data */);
+ },
+ [&]() { cdmEngine->RestoreKey(mSessionId, mKeySetId); },
+ [&]() {
+ cdmEngine->SetSessionServiceCertificate(
+ mSessionId, mFdp.ConsumeRandomLengthString(
+ kMaxByte) /* service_certificate */);
+ },
+ [&]() {
+ std::string queryResponse;
+ cdmEngine->QueryStatus(
+ static_cast(mFdp.ConsumeIntegralInRange(
+ static_cast(RequestedSecurityLevel::kLevelDefault),
+ static_cast(RequestedSecurityLevel::kLevel3))),
+ mFdp.PickValueInArray(kQueryToken),
+ mFdp.ConsumeBool() ? &queryResponse : nullptr);
+ },
+ [&]() {
+ CdmQueryMap queryResponse;
+ cdmEngine->QuerySessionStatus(mSessionId, &queryResponse);
+ },
+ [&]() {
+ CdmKeyRequest keyRequest;
+ keyRequest.message = mFdp.ConsumeRandomLengthString(kMaxByte);
+ keyRequest.type =
+ static_cast(mFdp.ConsumeIntegralInRange(
+ static_cast(
+ CdmKeyRequestType::kKeyRequestTypeUnknown),
+ static_cast(
+ CdmKeyRequestType::kKeyRequestTypeUpdate)));
+ keyRequest.url = mDefaultUrl;
+
+ cdmEngine->GenerateRenewalRequest(
+ mSessionId, mFdp.ConsumeBool() ? &keyRequest : nullptr);
+
+ CdmKeyResponse keyData =
+ mFdp.ConsumeBool()
+ ? std::to_string(
+ mFdp.ConsumeIntegralInRange(kMinKey, kMaxKey))
+ : kEmptyString;
+ cdmEngine->RenewKey(mSessionId, keyData);
+ },
+ [&]() { cdmEngine->IsReleaseSession(mSessionId); },
+ [&]() { cdmEngine->IsOfflineSession(mSessionId); },
+ [&]() {
+ mOutCertFile1.open(kCertFile.c_str());
+ mOutCertFile2.open(kCertFile1.c_str());
+ cdmEngine->RemoveOfflineLicense(
+ mKeySetId,
+ static_cast(mFdp.ConsumeIntegralInRange(
+ static_cast(
+ CdmSecurityLevel::kSecurityLevelUninitialized),
+ static_cast(
+ CdmSecurityLevel::kSecurityLevelUnknown))));
+ },
+ [&]() {
+ CdmQueryMap queryResponse;
+ cdmEngine->QueryKeyStatus(mSessionId, &queryResponse);
+ },
+ [&]() {
+ cdmEngine->IsSecurityLevelSupported(
+ (CdmSecurityLevel)mFdp.ConsumeIntegralInRange(kMinEnum,
+ kMaxEnum));
+ },
+ [&]() {
+ CdmKeyAllowedUsage keyUsage;
+ cdmEngine->QueryKeyAllowedUsage(
+ mSessionId, mKeyId, mFdp.ConsumeBool() ? &keyUsage : nullptr);
+ },
+ [&]() {
+ CdmKeyAllowedUsage keyUsage;
+ cdmEngine->QueryKeyAllowedUsage(mKeyId, mFdp.ConsumeBool() ? &keyUsage
+ : nullptr);
+ },
+ [&]() {
+ CdmQueryMap queryResponse;
+ cdmEngine->QueryOemCryptoSessionId(mSessionId, &queryResponse);
+ },
+ [&]() {
+ std::vector keySetIds = createVector(true);
+ cdmEngine->ListStoredLicenses(
+ (CdmSecurityLevel)mFdp.ConsumeIntegralInRange(kMinEnum,
+ kMaxEnum),
+ mFdp.ConsumeBool() ? &keySetIds : nullptr);
+ },
+ [&]() {
+ std::vector keySetIds = createVector(true);
+ std::vector providerSessionTokens = createVector(false);
+
+ cdmEngine->ListUsageIds(
+ mAppId,
+ (CdmSecurityLevel)mFdp.ConsumeIntegralInRange(kMinEnum,
+ kMaxEnum),
+ mFdp.ConsumeBool() ? &keySetIds : nullptr,
+ mFdp.ConsumeBool() ? &providerSessionTokens : nullptr);
+ },
+ [&]() {
+ cdmEngine->DeleteUsageRecord(
+ mAppId,
+ (CdmSecurityLevel)mFdp.ConsumeIntegralInRange(kMinEnum,
+ kMaxEnum),
+ mKeySetId);
+ },
+ [&]() {
+ CdmOfflineLicenseState licenseState =
+ static_cast(mFdp.ConsumeIntegralInRange(
+ static_cast(
+ CdmOfflineLicenseState::kLicenseStateActive),
+ static_cast(
+ CdmOfflineLicenseState::kLicenseStateUnknown)));
+ cdmEngine->GetOfflineLicenseState(
+ mKeySetId,
+ (CdmSecurityLevel)mFdp.ConsumeIntegralInRange(kMinEnum,
+ kMaxEnum),
+ mFdp.ConsumeBool() ? &licenseState : nullptr);
+ },
+ [&]() {
+ cdmEngine->SetPlaybackId(mSessionId,
+ mFdp.ConsumeRandomLengthString(kMaxByte));
+ },
+ [&]() {
+ CdmUsageReport usageReport;
+ createUsageFile(mAppId);
+ int errorDetail;
+ cdmEngine->GetUsageInfo(mAppId,
+ mFdp.ConsumeBool() ? &errorDetail : nullptr,
+ mFdp.ConsumeBool() ? &usageReport : nullptr);
+ },
+ [&]() {
+ createUsageFile(mAppId);
+ cdmEngine->RemoveAllUsageInfo(mAppId);
+ },
+ [&]() {
+ cdmEngine->ReleaseUsageInfo(
+ mFdp.ConsumeRandomLengthString(kMaxByte) /* message */);
+ },
+ [&]() {
+ std::string releaseMessage = mFdp.ConsumeRandomLengthString(kMaxByte);
+ cdmEngine->LoadUsageSession(
+ mKeySetId, mFdp.ConsumeBool() ? &releaseMessage : nullptr);
+ },
+ [&]() {
+ CdmDecryptionParametersV16 parameters(mKeyId);
+ cdmEngine->DecryptV16(mSessionId, parameters);
+ },
+ [&]() {
+ std::string out = mFdp.ConsumeRandomLengthString(kMaxByte);
+ std::string ivGE = mFdp.ConsumeRandomLengthString(kMaxByte);
+ cdmEngine->GenericEncrypt(
+ mSessionId, mFdp.ConsumeRandomLengthString(kMaxByte), mKeyId,
+ ivGE,
+ (CdmEncryptionAlgorithm)mFdp.ConsumeIntegralInRange(
+ kMinValue, kMaxValue),
+ mFdp.ConsumeBool() ? &out : nullptr);
+ },
+ [&]() {
+ std::string out = mFdp.ConsumeRandomLengthString(kMaxByte);
+ std::string ivGE = mFdp.ConsumeRandomLengthString(kMaxByte);
+ cdmEngine->GenericDecrypt(
+ mSessionId, mFdp.ConsumeRandomLengthString(kMaxByte), mKeyId,
+ ivGE,
+ (CdmEncryptionAlgorithm)mFdp.ConsumeIntegralInRange(
+ kMinValue, kMaxValue),
+ mFdp.ConsumeBool() ? &out : nullptr);
+ },
+ [&]() {
+ cdmEngine->GenericSign(
+ mSessionId, mFdp.ConsumeRandomLengthString(kMaxByte), mKeyId,
+ (CdmSigningAlgorithm)mFdp.ConsumeIntegralInRange(
+ kMinValue, kMaxValue),
+ mFdp.ConsumeBool() ? &mSign : nullptr);
+
+ cdmEngine->GenericVerify(
+ mSessionId, mFdp.ConsumeRandomLengthString(kMaxByte), mKeyId,
+ (CdmSigningAlgorithm)mFdp.ConsumeIntegralInRange(
+ kMinValue, kMaxValue),
+ mSign);
+ },
+ [&]() {
+ cdmEngine->SetDebugIgnoreKeyboxCount(
+ mFdp.ConsumeIntegral());
+ },
+ [&]() { cdmEngine->SetAllowTestKeybox(mFdp.ConsumeBool()); },
+ [&]() {
+ std::string sessId = mFdp.ConsumeRandomLengthString(kMaxByte);
+ std::string hash;
+ std::string hashString =
+ mFdp.ConsumeRandomLengthString(kMaxByte) + "," +
+ mFdp.ConsumeRandomLengthString(kMaxByte) + "," +
+ mFdp.ConsumeRandomLengthString(kMaxByte);
+ uint32_t frameNum = mFdp.ConsumeIntegral();
+ cdmEngine->ParseDecryptHashString(
+ hashString, mFdp.ConsumeBool() ? &sessId : nullptr,
+ mFdp.ConsumeBool() ? &frameNum : nullptr,
+ mFdp.ConsumeBool() ? &hash : nullptr);
+
+ cdmEngine->SetDecryptHash(mSessionId,
+ mFdp.ConsumeIntegral(), hash);
+
+ std::string hashError;
+ cdmEngine->GetDecryptHashError(
+ mSessionId, mFdp.ConsumeBool() ? &hashError : nullptr);
+ },
+ [&]() {
+ std::string mSessionId = mFdp.ConsumeRandomLengthString(kMaxByte);
+ cdmEngine->FindSessionForKey(mKeyId, mFdp.ConsumeBool() ? &mSessionId
+ : nullptr);
+ },
+ [&]() {
+ cdmEngine->NotifyResolution(
+ mSessionId, mFdp.ConsumeIntegral() /* width */,
+ mFdp.ConsumeIntegral() /* height */);
+ },
+ [&]() {
+ cdmEngine->ValidateServiceCertificate(
+ mFdp.ConsumeRandomLengthString(kMaxByte) /* cert */);
+ },
+ [&]() {
+ CdmUsageReport usageReport;
+ createUsageFile(mAppId);
+ CdmSecureStopId ssid = mFdp.ConsumeRandomLengthString(kMaxByte);
+ int errorDetail = mFdp.ConsumeIntegral();
+ cdmEngine->GetUsageInfo(mAppId, ssid,
+ mFdp.ConsumeBool() ? &errorDetail : nullptr,
+ mFdp.ConsumeBool() ? &usageReport : nullptr);
+ },
+ [&]() {
+ CdmSecureStopId ssid = mFdp.ConsumeRandomLengthString(kMaxByte);
+ cdmEngine->RemoveUsageInfo(mAppId, ssid);
+ },
+ [&]() { cdmEngine->RemoveLicense(mSessionId); },
+ [&]() { cdmEngine->IsKeyLoaded(mKeyId); },
+ });
+ invokeCdmEngineAPI();
+ }
+
+ cdmEngine->Unprovision((CdmSecurityLevel)mFdp.ConsumeIntegralInRange(
+ kMinEnum, kMaxEnum));
+
+ cdmEngine->RemoveKeys(mSessionId);
+
+ mOutCertFile1.close();
+ mOutCertFile2.close();
+ mOutUsageFile1.close();
+ mOutUsageFile2.close();
+
+ delete cdmEngine;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ CdmEngineFuzzer cdmEngineFuzzer(data, size);
+ cdmEngineFuzzer.process();
+ return 0;
+}