/* * 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 "license.h" #include "privacy_crypto.h" #include "properties.h" #include "vendor_widevine_fuzz_helper.h" #include "wv_cdm_constants.h" #include using namespace wvcdm; using namespace video_widevine; using video_widevine::DrmCertificate; using video_widevine::SignedDrmCertificate; constexpr int32_t kMaxByte = 256; constexpr int32_t kMinFirstComponent = 0; constexpr int32_t kMaxFirstComponent = 2; constexpr int32_t kMinSecondComponent = 0; constexpr int32_t kMaxSecondComponent = 39; constexpr int32_t kMinNumComponent = 0; constexpr int32_t kMaxNumComponent = 10; class PrivacyCryptoFuzzer { public: PrivacyCryptoFuzzer(const uint8_t *data, size_t size) : mFdp(data, size){}; void process(); std::string createOid() { std::string oid; int32_t firstComponent = mFdp.ConsumeIntegralInRange( kMinFirstComponent, kMaxFirstComponent); oid += std::to_string(firstComponent); oid += '.'; uint32_t temp = 0; if (firstComponent != 2) { temp = mFdp.ConsumeIntegralInRange(kMinSecondComponent, kMaxSecondComponent); } else { temp = mFdp.ConsumeIntegral(); } oid += std::to_string(temp); int32_t numComponent = mFdp.ConsumeIntegralInRange( kMinNumComponent, kMaxNumComponent); for (int32_t i = 0; i < numComponent; ++i) { oid += '.'; oid += std::to_string(mFdp.ConsumeIntegral()); } return oid; } private: FuzzedDataProvider mFdp; }; void PrivacyCryptoFuzzer::process() { AesCbcKey aesCbcKey; RsaPublicKey rsaPubKey; while (mFdp.remaining_bytes()) { auto privacyCrptoApi = mFdp.PickValueInArray>({ [&]() { /** * This Implementation is required to initialize RSA-public_key * correctly. */ FuzzCdmClientPropertySet propertySet(&mFdp); propertySet.enable_privacy_mode(); propertySet.set_service_certificate(kTestSignedCertificate); PropertiesTestPeer::ForceReinit(); PropertiesTestPeer::AddSessionPropertySet(kTestSessionId1, &propertySet); std::string rawServiceCertificate; PropertiesTestPeer::GetServiceCertificate(kTestSessionId1, &rawServiceCertificate); SignedDrmCertificate signedRootCertificate; std::string rootCertStr( reinterpret_cast(&kRootCertForProd[0]), sizeof(kRootCertForProd)); signedRootCertificate.ParseFromString(rootCertStr); DrmCertificate rootCert; rootCert.ParseFromString(signedRootCertificate.drm_certificate()); rsaPubKey.Init(mFdp.ConsumeBool() ? rootCert.public_key() : mFdp.ConsumeRandomLengthString(kMaxByte)); }, [&]() { std::string cipherText; std::string message = mFdp.ConsumeRandomLengthString(kMaxByte); rsaPubKey.Encrypt(message, &cipherText); }, [&]() { rsaPubKey.VerifySignature( mFdp.ConsumeRandomLengthString(kMaxByte) /* message */, mFdp.ConsumeRandomLengthString(kMaxByte) /* signature */); }, [&]() { std::string key = mFdp.ConsumeRandomLengthString(SERVICE_KEY_SIZE); if (mFdp.ConsumeBool()) { key.resize(SERVICE_KEY_SIZE, '0'); } aesCbcKey.Init(key); }, [&]() { std::string encId; std::string iv = mFdp.ConsumeRandomLengthString(KEY_IV_SIZE); if (mFdp.ConsumeBool()) { iv.resize(KEY_IV_SIZE, '0'); } aesCbcKey.Encrypt(mFdp.ConsumeRandomLengthString(kMaxByte), mFdp.ConsumeBool() ? &encId : nullptr, mFdp.ConsumeBool() ? &iv : nullptr); }, [&]() { std::string data = mFdp.ConsumeRandomLengthString(kMaxByte); Md5Hash(data); }, [&]() { std::string data = mFdp.ConsumeRandomLengthString(kMaxByte); Sha256Hash(data); }, [&]() { size_t certIndex = mFdp.ConsumeBool() ? mFdp.ConsumeIntegral() : kOemCertSystemIdIndex; uint32_t value = 0; std::string oid = createOid(); ExtractExtensionValueFromCertificate( mFdp.ConsumeBool() ? kOemCertStr : mFdp.ConsumeRandomLengthString(kMaxByte), oid, certIndex, &value); }, }); privacyCrptoApi(); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { PrivacyCryptoFuzzer privacyCryptoFuzzer(data, size); privacyCryptoFuzzer.process(); return 0; }