Files
android/fuzzer/policy_engine_fuzzer.cpp
Kunal Rai f3c22ff3f1 Updated policy_engine_fuzzer
Implemented google c++ code style changes for policy_engine_fuzzer

execs/s: 71
Test: ./policy_engine_fuzzer
Bug: 312374669

Change-Id: I8320f360f0c58c4fd3309a9f159ca49568da2abc
2023-11-21 09:53:58 +00:00

352 lines
14 KiB
C++

/*
* 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_engine.h"
#include "wv_cdm_event_listener.h"
#include <fuzzer/FuzzedDataProvider.h>
using namespace wvcdm;
using namespace wvcdm::metrics;
using namespace video_widevine;
static constexpr int32_t kLicenseIdVersion = 1;
static constexpr int32_t kMaxByte = 256;
static constexpr int32_t kMinResolution = 1;
static constexpr int32_t kMaxResolution = 1024;
static constexpr int32_t kMaxEntitledKey = 5;
const KeyId kSigningKeyId = "signing_key";
const KeyId kEntitlementKeyId = "entitlementkeyid";
const char *kRenewalServerUrl =
"https://test.google.com/license/GetCencLicense";
class FuzzWvCdmEventListener : public WvCdmEventListener {
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 PolicyEngineFuzzer {
public:
PolicyEngineFuzzer(const uint8_t *data, size_t size) : fdp_(data, size){};
void Process();
private:
FuzzedDataProvider fdp_;
KeyId key_id_;
License license_;
void SetUp();
};
void PolicySetBool(std::function<void(bool)> function,
FuzzedDataProvider *fdp) {
if (fdp->ConsumeBool()) {
function(fdp->ConsumeBool());
}
}
void PolicySetInt64(std::function<void(int64_t)> function,
FuzzedDataProvider *fdp) {
if (fdp->ConsumeBool()) {
function(fdp->ConsumeIntegral<int64_t>());
}
}
void PolicyEngineFuzzer::SetUp() {
License::KeyContainer *key = license_.add_key();
int32_t key_type = fdp_.ConsumeIntegralInRange<uint8_t>(
License::KeyContainer::SIGNING, License::KeyContainer::ENTITLEMENT);
key->set_type((License_KeyContainer_KeyType)key_type);
key_id_ = fdp_.ConsumeRandomLengthString(kMaxByte);
LicenseIdentification *id = license_.mutable_id();
if (fdp_.ConsumeBool()) {
id->set_version(kLicenseIdVersion);
}
if (fdp_.ConsumeBool()) {
id->set_type(fdp_.ConsumeBool() ? STREAMING : OFFLINE);
}
if (fdp_.ConsumeBool()) {
id->set_provider_session_token(fdp_.ConsumeRandomLengthString(kMaxByte));
}
if (fdp_.ConsumeBool()) {
license_.set_license_start_time(fdp_.ConsumeIntegral<int64_t>());
}
if (fdp_.ConsumeBool()) {
License_KeyContainer_OutputProtection *output_protection =
key->mutable_required_protection();
License_KeyContainer_OutputProtection_HDCP hdcp_level =
(License_KeyContainer_OutputProtection_HDCP)fdp_
.ConsumeIntegralInRange<uint8_t>(HDCP_NONE, HDCP_NO_DIGITAL_OUTPUT);
output_protection->set_hdcp(hdcp_level);
}
if (fdp_.ConsumeBool()) {
const std::string iv_string = fdp_.ConsumeRandomLengthString(kMaxByte);
key->set_iv(iv_string);
}
switch (key_type) {
case License::KeyContainer::SIGNING: {
if (fdp_.ConsumeBool()) {
key_id_ = fdp_.ConsumeBool() ? kSigningKeyId : key_id_;
key->set_id(key_id_);
}
break;
}
case License::KeyContainer::CONTENT: {
if (fdp_.ConsumeBool()) {
key->set_id(key_id_);
}
if (fdp_.ConsumeBool()) {
int32_t level = fdp_.ConsumeIntegralInRange<uint8_t>(
License::KeyContainer::SW_SECURE_CRYPTO,
License::KeyContainer::HW_SECURE_ALL);
key->set_level((License_KeyContainer_SecurityLevel)level);
}
License_Policy *policy = license_.mutable_policy();
PolicySetBool(
std::bind(&License_Policy::set_can_play, policy, std::placeholders::_1),
&fdp_);
PolicySetBool(std::bind(&License_Policy::set_can_persist, policy,
std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License_Policy::set_can_renew, policy,
std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License_Policy::set_renew_with_usage, policy,
std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License_Policy::set_soft_enforce_rental_duration,
policy, std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License_Policy::set_soft_enforce_playback_duration,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_rental_duration_seconds,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_playback_duration_seconds,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_license_duration_seconds,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_renewal_recovery_duration_seconds,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_renewal_retry_interval_seconds, policy,
std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_renewal_delay_seconds, policy,
std::placeholders::_1), &fdp_);
if (fdp_.ConsumeBool()) {
video_widevine::License::Policy::TimerDelayBase time_delay_base =
(video_widevine::License::Policy::TimerDelayBase)
fdp_.ConsumeIntegralInRange<uint8_t>(
License_Policy_TimerDelayBase_TIMER_DELAY_BASE_UNSPECIFIED,
License_Policy_TimerDelayBase_FIRST_DECRYPT);
policy->set_initial_renewal_delay_base(time_delay_base);
}
if (fdp_.ConsumeBool()) {
std::string serverUrl = fdp_.ConsumeBool()
? kRenewalServerUrl
: fdp_.ConsumeRandomLengthString(kMaxByte);
policy->set_renewal_server_url(serverUrl);
}
break;
}
case License::KeyContainer::KEY_CONTROL: {
key->set_type(License::KeyContainer::KEY_CONTROL);
// No control bits for this type of key container used for license
break;
}
case License::KeyContainer::OPERATOR_SESSION: {
key->set_type(License::KeyContainer::OPERATOR_SESSION);
if (fdp_.ConsumeBool()) {
key->set_id(key_id_);
}
if (fdp_.ConsumeBool()) {
int32_t level = fdp_.ConsumeIntegralInRange<uint8_t>(
License::KeyContainer::SW_SECURE_CRYPTO,
License::KeyContainer::HW_SECURE_ALL);
key->set_level((License_KeyContainer_SecurityLevel)level);
}
if (fdp_.ConsumeBool()) {
PolicySetBool(std::bind(&License_Policy::set_can_persist,license_.mutable_policy(),
std::placeholders::_1),&fdp_);
}
License::KeyContainer::OperatorSessionKeyPermissions *permissions =
key->mutable_operator_session_key_permissions();
PolicySetBool(
std::bind(&License::KeyContainer::OperatorSessionKeyPermissions::
set_allow_encrypt,
permissions, std::placeholders::_1), &fdp_);
PolicySetBool(
std::bind(&License::KeyContainer::OperatorSessionKeyPermissions::
set_allow_decrypt,
permissions, std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License::KeyContainer::
OperatorSessionKeyPermissions::set_allow_sign,
permissions, std::placeholders::_1), &fdp_);
PolicySetBool(
std::bind(&License::KeyContainer::OperatorSessionKeyPermissions::
set_allow_signature_verify,
permissions, std::placeholders::_1), &fdp_);
break;
}
case License::KeyContainer::ENTITLEMENT:
default: {
if (fdp_.ConsumeBool()) {
key_id_ = fdp_.ConsumeBool() ? kEntitlementKeyId : key_id_;
key->set_id(key_id_);
}
if (fdp_.ConsumeBool()) {
int32_t level = fdp_.ConsumeIntegralInRange<uint8_t>(
License::KeyContainer::SW_SECURE_CRYPTO,
License::KeyContainer::HW_SECURE_ALL);
key->set_level((License_KeyContainer_SecurityLevel)level);
}
License_Policy *policy = license_.mutable_policy();
PolicySetBool(
std::bind(&License_Policy::set_can_play, policy, std::placeholders::_1),
&fdp_);
PolicySetBool(std::bind(&License_Policy::set_can_persist, policy,
std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License_Policy::set_can_renew, policy,
std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License_Policy::set_renew_with_usage, policy,
std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License_Policy::set_soft_enforce_rental_duration,
policy, std::placeholders::_1), &fdp_);
PolicySetBool(std::bind(&License_Policy::set_soft_enforce_playback_duration,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_rental_duration_seconds,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_playback_duration_seconds,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(std::bind(&License_Policy::set_license_duration_seconds,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(
std::bind(&License_Policy::set_renewal_recovery_duration_seconds,
policy, std::placeholders::_1), &fdp_);
PolicySetInt64(
std::bind(&License_Policy::set_renewal_retry_interval_seconds, policy,
std::placeholders::_1), &fdp_);
PolicySetInt64(
std::bind(&License_Policy::set_renewal_delay_seconds, policy,
std::placeholders::_1), &fdp_);
if (fdp_.ConsumeBool()) {
video_widevine::License::Policy::TimerDelayBase time_delay_base =
(video_widevine::License::Policy::TimerDelayBase)
fdp_.ConsumeIntegralInRange<uint8_t>(
License_Policy_TimerDelayBase_TIMER_DELAY_BASE_UNSPECIFIED,
License_Policy_TimerDelayBase_FIRST_DECRYPT);
policy->set_initial_renewal_delay_base(time_delay_base);
}
break;
}
}
}
void PolicyEngineFuzzer::Process() {
SetUp();
FuzzWvCdmEventListener fuzz_wv_cdm_event_listener;
CdmSessionId session_id = fdp_.ConsumeRandomLengthString(kMaxByte);
metrics::CryptoMetrics crypto_metrics;
std::unique_ptr<CryptoSession> cryptoSession(
wvcdm::CryptoSession::MakeCryptoSession(&crypto_metrics));
std::unique_ptr<PolicyEngine> policy_engine(new PolicyEngine(
session_id, &fuzz_wv_cdm_event_listener, cryptoSession.get()));
while (fdp_.remaining_bytes()) {
auto invokePolicyEngineAPI =
fdp_.PickValueInArray<const std::function<void()>>({
[&]() { policy_engine->CanDecryptContent(key_id_); },
[&]() { policy_engine->CanUseKeyForSecurityLevel(key_id_); },
[&]() { policy_engine->OnTimerEvent(); },
[&]() {
policy_engine->SetLicense(
license_, fdp_.ConsumeBool() /*defer_license_state_update**/);
},
[&]() {
int32_t max_entitled_key=
fdp_.ConsumeIntegralInRange<uint8_t>(1, kMaxEntitledKey);
std::vector<WidevinePsshData_EntitledKey> entitled_keys(
max_entitled_key);
for (int i = 0; i < max_entitled_key; ++i) {
entitled_keys[i].set_entitlement_key_id(
fdp_.ConsumeRandomLengthString(kMaxByte));
entitled_keys[i].set_key_id(
fdp_.ConsumeBool()
? fdp_.ConsumeRandomLengthString(kMaxByte)
: key_id_);
}
policy_engine->SetEntitledLicenseKeys(entitled_keys);
},
[&]() { policy_engine->SetLicenseForRelease(license_); },
[&]() { policy_engine->BeginDecryption(); },
[&]() { policy_engine->DecryptionEvent(); },
[&]() {
policy_engine->UpdateLicense(
license_, fdp_.ConsumeBool() /*defer_license_state_update*/);
},
[&]() {
policy_engine->UpdateLicenseState(
fdp_.ConsumeIntegral<int64_t>() /*current_time*/);
},
[&]() {
int32_t width = fdp_.ConsumeIntegralInRange<int32_t>(
kMinResolution, kMaxResolution);
int32_t height = fdp_.ConsumeIntegralInRange<int32_t>(
kMinResolution, kMaxResolution);
policy_engine->NotifyResolution(width, height);
},
[&]() { policy_engine->NotifySessionExpiration(); },
[&]() {
CdmQueryMap query_info;
policy_engine->Query(&query_info);
},
[&]() {
CdmKeyAllowedUsage key_usage;
policy_engine->QueryKeyAllowedUsage(
key_id_, (fdp_.ConsumeBool() ? nullptr : &key_usage));
},
[&]() {
policy_engine->RestorePlaybackTimes(
fdp_.ConsumeIntegral<int64_t>() /*playback_start_time*/,
fdp_.ConsumeIntegral<int64_t>() /*last_playback_time*/,
fdp_.ConsumeIntegral<int64_t>() /*grace_period_end_time*/);
},
[&]() {
policy_engine->HasLicenseOrRentalOrPlaybackDurationExpired(
fdp_.ConsumeIntegral<int64_t>());
},
});
invokePolicyEngineAPI();
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
PolicyEngineFuzzer policy_engine_fuzzer(data, size);
policy_engine_fuzzer.Process();
return 0;
}