diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
index 40c225fc..12b895cc 100644
--- a/fuzzer/Android.bp
+++ b/fuzzer/Android.bp
@@ -80,9 +80,15 @@ cc_fuzz {
name: "system_id_extractor_fuzzer",
srcs: ["system_id_extractor_fuzzer.cpp"],
defaults: ["libcdm_fuzzer_defaults"],
-
+}
cc_fuzz{
name: "service_certificate_fuzzer",
srcs: ["service_certificate_fuzzer.cpp"],
defaults: ["libcdm_fuzzer_defaults"]
}
+
+cc_fuzz {
+ name: "policy_timers_fuzzer",
+ srcs: ["policy_timers_fuzzer.cpp"],
+ defaults: ["libcdm_fuzzer_defaults"],
+}
diff --git a/fuzzer/README.md b/fuzzer/README.md
index 684e2012..4e483db5 100644
--- a/fuzzer/README.md
+++ b/fuzzer/README.md
@@ -5,6 +5,7 @@
+ [content_decryption_fuzzer](#ContentDecryption)
+ [system_id_extractor_fuzzer](#SystemIdExtractor)
+ [service_certificate_fuzzer](#ServiceCertificate)
++ [policy_timers_fuzzer](#PolicyTimers)
# Fuzzer for PolicyEngine
@@ -53,6 +54,7 @@ ContentDecryption supports the following parameters:
$ adb sync data
$ adb shell /data/fuzz/arm64/content_decryption_fuzzer/vendor/content_decryption_fuzzer
```
+
# Fuzzer for SystemIdExtractor
SystemIdExtractor supports the following parameters:
@@ -76,6 +78,7 @@ SystemIdExtractor supports the following parameters:
$ adb sync data
$ adb shell /data/fuzz/arm64/system_id_extractor_fuzzer/vendor/system_id_extractor_fuzzer
```
+
# Fuzzer for ServiceCertificate
ServiceCertificate supports the following parameters:
@@ -99,3 +102,24 @@ ServiceCertificate supports the following parameters:
$ adb sync data
$ adb shell /data/fuzz/arm64/service_certificate_fuzzer/vendor/service_certificate_fuzzer
```
+
+# Fuzzer for PolicyTimers
+
+PolicyTimers supports the following parameters:
+1. Seconds Since Last Played (parameter name: "secondsSinceLastPlayed")
+2. Expiry Time (parameter name: "expiryTime")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`secondsSinceLastPlayed`| `Integer` |Value obtained from FuzzedDataProvider|
+|`expiryTime`| `Interger` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) policy_timers_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/policy_timers_fuzzer/vendor/policy_timers_fuzzer
diff --git a/fuzzer/policy_timers_fuzzer.cpp b/fuzzer/policy_timers_fuzzer.cpp
new file mode 100644
index 00000000..fda9054c
--- /dev/null
+++ b/fuzzer/policy_timers_fuzzer.cpp
@@ -0,0 +1,186 @@
+/*
+ * 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 "policy_timers.h"
+#include "policy_timers_v16.h"
+#include "policy_timers_v18.h"
+#include "wv_cdm_event_listener.h"
+#include
+
+using namespace wvcdm;
+using namespace video_widevine;
+
+class PolicyTimersFuzzer {
+public:
+ PolicyTimersFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {};
+ void process();
+
+private:
+ FuzzedDataProvider mFdp;
+ License mLicense;
+ void setUp();
+};
+
+void policySetBool(std::function function,
+ FuzzedDataProvider *fdp) {
+ if (fdp->ConsumeBool()) {
+ function(fdp->ConsumeBool());
+ }
+}
+void policySetInt64(std::function function,
+ FuzzedDataProvider *fdp) {
+ if (fdp->ConsumeBool()) {
+ function(fdp->ConsumeIntegral());
+ }
+}
+
+void PolicyTimersFuzzer::setUp() {
+ License_Policy* policy = mLicense.mutable_policy();
+ policySetBool(
+ std::bind(&License_Policy::set_can_renew, policy, std::placeholders::_1),
+ &mFdp);
+ policySetInt64(std::bind(&License_Policy::set_renewal_delay_seconds, policy,
+ std::placeholders::_1),
+ &mFdp);
+ policySetBool(std::bind(&License_Policy::set_soft_enforce_playback_duration,
+ policy, std::placeholders::_1),
+ &mFdp);
+ policySetInt64(std::bind(&License_Policy::set_renewal_retry_interval_seconds,
+ policy, std::placeholders::_1),
+ &mFdp);
+ policySetInt64(std::bind(&License_Policy::set_license_duration_seconds,
+ policy, std::placeholders::_1),
+ &mFdp);
+ if (mFdp.ConsumeBool()) {
+ video_widevine::License::Policy::TimerDelayBase timeDelayBase =
+ (video_widevine::License::Policy::TimerDelayBase)
+ mFdp.ConsumeIntegralInRange(
+ License_Policy_TimerDelayBase_TIMER_DELAY_BASE_UNSPECIFIED,
+ License_Policy_TimerDelayBase_FIRST_DECRYPT);
+ policy->set_initial_renewal_delay_base(timeDelayBase);
+ }
+ if (mFdp.ConsumeBool()) {
+ policy->set_playback_duration_seconds(mFdp.ConsumeIntegral());
+ }
+ if (mFdp.ConsumeBool()) {
+ policy->set_rental_duration_seconds(mFdp.ConsumeIntegral());
+ }
+ if (mFdp.ConsumeBool()) {
+ policy->set_renewal_recovery_duration_seconds(mFdp.ConsumeIntegral());
+ }
+ if (mFdp.ConsumeBool()) {
+ policy->set_soft_enforce_rental_duration(mFdp.ConsumeBool());
+ }
+ if (mFdp.ConsumeBool()) {
+ policy->set_can_play(mFdp.ConsumeBool());
+ }
+ mLicense.set_license_start_time(mFdp.ConsumeIntegral());
+}
+
+void PolicyTimersFuzzer::process() {
+ std::unique_ptr policyTimers;
+ if (mFdp.ConsumeBool()) {
+ policyTimers = std::make_unique();
+ }
+ else {
+ policyTimers = std::make_unique();
+ }
+
+ while (mFdp.remaining_bytes()) {
+ auto invokePolicyTimersAPI =
+ mFdp.PickValueInArray>({
+ [&]() {
+ setUp();
+ },
+ [&]() {
+ policyTimers->SetLicense(mLicense);
+ },
+ [&]() {
+ policyTimers->BeginDecryption(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ policyTimers->DecryptionEvent(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ policyTimers->RestorePlaybackTimes(
+ mFdp.ConsumeIntegral() /*current_time*/,
+ mFdp.ConsumeIntegral() /*playback_start_time*/,
+ mFdp.ConsumeIntegral() /*last_playback_time*/,
+ mFdp.ConsumeIntegral() /* grace_period_end_time */);
+ },
+ [&]() {
+ policyTimers->GetLicenseOrRentalOrPlaybackDurationRemaining(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ policyTimers->GetPlaybackDurationRemaining(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ int64_t secondsSinceLastPlayed = mFdp.ConsumeIntegral();
+ policyTimers->GetSecondsSinceStarted(
+ mFdp.ConsumeIntegral() /*current_time*/,
+ mFdp.ConsumeBool() ? &secondsSinceLastPlayed : nullptr);
+ },
+ [&]() {
+ int64_t secondsSinceLastPlayed = mFdp.ConsumeIntegral();
+ policyTimers->GetSecondsSinceLastPlayed(
+ mFdp.ConsumeIntegral() /*current_time*/,
+ mFdp.ConsumeBool() ? &secondsSinceLastPlayed : nullptr);
+ },
+ [&]() {
+ policyTimers->IsLicenseForFuture(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ int64_t expiryTime = mFdp.ConsumeIntegral();
+ policyTimers->UpdateExpirationTime(
+ mFdp.ConsumeIntegral() /*current_time*/,
+ mFdp.ConsumeBool() ? &expiryTime : nullptr);
+ },
+ [&]() {
+ policyTimers->HasRenewalRetryIntervalExpired(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ policyTimers->UpdateRenewalRequest(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ policyTimers->HasRenewalRecoveryDurationExpired(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ policyTimers->HasRenewalDelayExpired(
+ mFdp.ConsumeIntegral() /*current_time*/);
+ },
+ [&]() {
+ policyTimers->UpdateLicense(
+ mFdp.ConsumeIntegral() /*current_time*/, mLicense);
+ },
+ });
+ invokePolicyTimersAPI();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) {
+ PolicyTimersFuzzer policyTimersFuzzer(data, size);
+ policyTimersFuzzer.process();
+ return 0;
+}