Ayushi Khopkar | a858324 | 2020-12-03 16:05:34 +0530 | [diff] [blame^] | 1 | /****************************************************************************** |
| 2 | * |
| 3 | * Copyright (C) 2020 The Android Open Source Project |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at: |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | * |
| 17 | ***************************************************************************** |
| 18 | * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
| 19 | */ |
| 20 | |
| 21 | #include <binder/MemoryDealer.h> |
| 22 | #include <hidlmemory/FrameworkUtils.h> |
| 23 | #include <mediadrm/CryptoHal.h> |
| 24 | #include <mediadrm/DrmHal.h> |
| 25 | #include <utils/String8.h> |
| 26 | #include "fuzzer/FuzzedDataProvider.h" |
| 27 | |
| 28 | #define AES_BLOCK_SIZE 16 |
| 29 | #define UNUSED_PARAM __attribute__((unused)) |
| 30 | |
| 31 | using namespace std; |
| 32 | using namespace android; |
| 33 | using android::hardware::fromHeap; |
| 34 | using ::android::os::PersistableBundle; |
| 35 | using drm::V1_0::BufferType; |
| 36 | |
| 37 | enum { |
| 38 | INVALID_UUID = 0, |
| 39 | PSSH_BOX_UUID, |
| 40 | CLEARKEY_UUID, |
| 41 | }; |
| 42 | |
| 43 | static const uint8_t kInvalidUUID[16] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, |
| 44 | 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80}; |
| 45 | |
| 46 | static const uint8_t kCommonPsshBoxUUID[16] = {0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, |
| 47 | 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B}; |
| 48 | |
| 49 | static const uint8_t kClearKeyUUID[16] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9, |
| 50 | 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E}; |
| 51 | |
| 52 | static const uint32_t kUUID[] = {INVALID_UUID, PSSH_BOX_UUID, CLEARKEY_UUID}; |
| 53 | |
| 54 | const DrmPlugin::SecurityLevel kSecurityLevel[] = { |
| 55 | DrmPlugin::kSecurityLevelUnknown, DrmPlugin::kSecurityLevelMax, |
| 56 | DrmPlugin::kSecurityLevelSwSecureCrypto, DrmPlugin::kSecurityLevelSwSecureDecode, |
| 57 | DrmPlugin::kSecurityLevelHwSecureCrypto, DrmPlugin::kSecurityLevelHwSecureDecode, |
| 58 | DrmPlugin::kSecurityLevelHwSecureAll}; |
| 59 | |
| 60 | const char *kMimeType[] = {"video/mp4", "video/mpeg", "video/x-flv", "video/mj2", |
| 61 | "video/3gp2", "video/3gpp", "video/3gpp2", "audio/mp4", |
| 62 | "audio/mpeg", "audio/aac", "audio/3gp2", "audio/3gpp", |
| 63 | "audio/3gpp2", "video/unknown", "audio/unknown"}; |
| 64 | |
| 65 | const DrmPlugin::KeyType kKeyType[] = {DrmPlugin::kKeyType_Offline, DrmPlugin::kKeyType_Streaming, |
| 66 | DrmPlugin::kKeyType_Release}; |
| 67 | |
| 68 | const CryptoPlugin::Mode kCryptoMode[] = {CryptoPlugin::kMode_Unencrypted, |
| 69 | CryptoPlugin::kMode_AES_CTR, CryptoPlugin::kMode_AES_WV, |
| 70 | CryptoPlugin::kMode_AES_CBC}; |
| 71 | |
| 72 | const char *kCipherAlgorithm[] = {"AES/CBC/NoPadding", ""}; |
| 73 | const char *kMacAlgorithm[] = {"HmacSHA256", ""}; |
| 74 | const char *kRSAAlgorithm[] = {"RSASSA-PSS-SHA1", ""}; |
| 75 | const size_t kNumSecurityLevel = size(kSecurityLevel); |
| 76 | const size_t kNumMimeType = size(kMimeType); |
| 77 | const size_t kNumKeyType = size(kKeyType); |
| 78 | const size_t kNumCryptoMode = size(kCryptoMode); |
| 79 | const size_t kNumUUID = size(kUUID); |
| 80 | const size_t kMaxStringLength = 100; |
| 81 | const size_t kMaxSubSamples = 10; |
| 82 | const size_t kMaxNumBytes = 1000; |
| 83 | |
| 84 | struct DrmListener : virtual public IDrmClient { |
| 85 | public: |
| 86 | void sendEvent(DrmPlugin::EventType eventType UNUSED_PARAM, |
| 87 | const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM, |
| 88 | const hardware::hidl_vec<uint8_t> &data UNUSED_PARAM) override {} |
| 89 | |
| 90 | void sendExpirationUpdate(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM, |
| 91 | int64_t expiryTimeInMS UNUSED_PARAM) override {} |
| 92 | |
| 93 | void sendKeysChange(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM, |
| 94 | const std::vector<DrmKeyStatus> &keyStatusList UNUSED_PARAM, |
| 95 | bool hasNewUsableKey UNUSED_PARAM) override {} |
| 96 | |
| 97 | void sendSessionLostState(const hardware::hidl_vec<uint8_t> &) override {} |
| 98 | DrmListener() {} |
| 99 | |
| 100 | private: |
| 101 | DISALLOW_EVIL_CONSTRUCTORS(DrmListener); |
| 102 | }; |
| 103 | |
| 104 | class DrmFuzzer { |
| 105 | public: |
| 106 | void process(const uint8_t *data, size_t size); |
| 107 | |
| 108 | private: |
| 109 | void invokeDrm(const uint8_t *data, size_t size); |
| 110 | bool initDrm(); |
| 111 | void invokeDrmCreatePlugin(); |
| 112 | void invokeDrmOpenSession(); |
| 113 | void invokeDrmSetListener(); |
| 114 | void invokeDrmSetAlgorithmAPI(); |
| 115 | void invokeDrmPropertyAPI(); |
| 116 | void invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size); |
| 117 | void invokeDrmSecureStopAPI(); |
| 118 | void invokeDrmOfflineLicenseAPI(); |
| 119 | void invokeDrmCloseSession(); |
| 120 | void invokeDrmDestroyPlugin(); |
| 121 | void invokeCrypto(const uint8_t *data); |
| 122 | bool initCrypto(); |
| 123 | void invokeCryptoCreatePlugin(); |
| 124 | void invokeCryptoDecrypt(const uint8_t *data); |
| 125 | void invokeCryptoDestroyPlugin(); |
| 126 | sp<DrmHal> mDrm = nullptr; |
| 127 | sp<CryptoHal> mCrypto = nullptr; |
| 128 | Vector<uint8_t> mSessionId = {}; |
| 129 | FuzzedDataProvider *mFuzzedDataProvider = nullptr; |
| 130 | }; |
| 131 | |
| 132 | bool DrmFuzzer::initDrm() { |
| 133 | mDrm = new DrmHal(); |
| 134 | if (!mDrm) { |
| 135 | return false; |
| 136 | } |
| 137 | return true; |
| 138 | } |
| 139 | |
| 140 | void DrmFuzzer::invokeDrmCreatePlugin() { |
| 141 | mDrm->initCheck(); |
| 142 | String8 packageName(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str()); |
| 143 | uint32_t uuidEnum = kUUID[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumUUID - 1)]; |
| 144 | switch (uuidEnum) { |
| 145 | case INVALID_UUID: |
| 146 | mDrm->createPlugin(kInvalidUUID, packageName); |
| 147 | break; |
| 148 | case PSSH_BOX_UUID: |
| 149 | mDrm->createPlugin(kCommonPsshBoxUUID, packageName); |
| 150 | break; |
| 151 | case CLEARKEY_UUID: |
| 152 | mDrm->createPlugin(kClearKeyUUID, packageName); |
| 153 | break; |
| 154 | default: |
| 155 | break; |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | void DrmFuzzer::invokeDrmDestroyPlugin() { mDrm->destroyPlugin(); } |
| 160 | |
| 161 | void DrmFuzzer::invokeDrmOpenSession() { |
| 162 | DrmPlugin::SecurityLevel securityLevel; |
| 163 | bool shouldPassRandomSecurityLevel = mFuzzedDataProvider->ConsumeBool(); |
| 164 | if (shouldPassRandomSecurityLevel) { |
| 165 | securityLevel = |
| 166 | static_cast<DrmPlugin::SecurityLevel>(mFuzzedDataProvider->ConsumeIntegral<size_t>()); |
| 167 | } else { |
| 168 | securityLevel = kSecurityLevel[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>( |
| 169 | 0, kNumSecurityLevel - 1)]; |
| 170 | } |
| 171 | mDrm->openSession(securityLevel, mSessionId); |
| 172 | } |
| 173 | |
| 174 | void DrmFuzzer::invokeDrmCloseSession() { mDrm->closeSession(mSessionId); } |
| 175 | |
| 176 | void DrmFuzzer::invokeDrmSetListener() { |
| 177 | sp<DrmListener> listener = new DrmListener(); |
| 178 | mDrm->setListener(listener); |
| 179 | } |
| 180 | |
| 181 | void DrmFuzzer::invokeDrmSetAlgorithmAPI() { |
| 182 | mDrm->setCipherAlgorithm(mSessionId, |
| 183 | String8(kCipherAlgorithm[mFuzzedDataProvider->ConsumeBool()])); |
| 184 | mDrm->setMacAlgorithm(mSessionId, String8(kMacAlgorithm[mFuzzedDataProvider->ConsumeBool()])); |
| 185 | } |
| 186 | |
| 187 | void DrmFuzzer::invokeDrmPropertyAPI() { |
| 188 | mDrm->setPropertyString(String8("property"), String8("value")); |
| 189 | String8 stringValue; |
| 190 | mDrm->getPropertyString(String8("property"), stringValue); |
| 191 | Vector<uint8_t> value = {}; |
| 192 | mDrm->setPropertyByteArray(String8("property"), value); |
| 193 | Vector<uint8_t> byteValue; |
| 194 | mDrm->getPropertyByteArray(String8("property"), byteValue); |
| 195 | } |
| 196 | |
| 197 | void DrmFuzzer::invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size) { |
| 198 | uint32_t openSessions = 0; |
| 199 | uint32_t maxSessions = 0; |
| 200 | mDrm->getNumberOfSessions(&openSessions, &maxSessions); |
| 201 | |
| 202 | DrmPlugin::HdcpLevel connected; |
| 203 | DrmPlugin::HdcpLevel max; |
| 204 | mDrm->getHdcpLevels(&connected, &max); |
| 205 | |
| 206 | DrmPlugin::SecurityLevel securityLevel; |
| 207 | mDrm->getSecurityLevel(mSessionId, &securityLevel); |
| 208 | |
| 209 | // isCryptoSchemeSupported() shall fill isSupported |
| 210 | bool isSupported; |
| 211 | String8 mimeType( |
| 212 | kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]); |
| 213 | mDrm->isCryptoSchemeSupported(kClearKeyUUID, mimeType, securityLevel, &isSupported); |
| 214 | |
| 215 | // getProvisionRequest() shall fill legacyRequest and legacyDefaultUrl |
| 216 | String8 certificateType( |
| 217 | mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str()); |
| 218 | String8 certAuthority(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str()); |
| 219 | Vector<uint8_t> legacyRequest = {}; |
| 220 | String8 legacyDefaultUrl; |
| 221 | mDrm->getProvisionRequest(certificateType, certAuthority, legacyRequest, legacyDefaultUrl); |
| 222 | |
| 223 | // provideProvisionResponse() shall fill certificate and wrappedKey |
| 224 | Vector<uint8_t> provisionResponse = {}; |
| 225 | Vector<uint8_t> certificate = {}; |
| 226 | Vector<uint8_t> wrappedKey = {}; |
| 227 | mDrm->provideProvisionResponse(provisionResponse, certificate, wrappedKey); |
| 228 | |
| 229 | // getKeyRequest() shall fill keyRequest, defaultUrl and keyRequestType |
| 230 | Vector<uint8_t> initData = {}; |
| 231 | initData.appendArray(data, size); |
| 232 | DrmPlugin::KeyType keyType; |
| 233 | bool shouldPassRandomKeyType = mFuzzedDataProvider->ConsumeBool(); |
| 234 | if (shouldPassRandomKeyType) { |
| 235 | keyType = static_cast<DrmPlugin::KeyType>(mFuzzedDataProvider->ConsumeIntegral<size_t>()); |
| 236 | } else { |
| 237 | keyType = kKeyType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumKeyType - 1)]; |
| 238 | } |
| 239 | KeyedVector<String8, String8> mdOptionalParameters = {}; |
| 240 | Vector<uint8_t> keyRequest = {}; |
| 241 | String8 defaultUrl; |
| 242 | DrmPlugin::KeyRequestType keyRequestType; |
| 243 | mDrm->getKeyRequest(mSessionId, initData, mimeType, keyType, mdOptionalParameters, keyRequest, |
| 244 | defaultUrl, &keyRequestType); |
| 245 | |
| 246 | // provideKeyResponse() shall fill keySetId |
| 247 | Vector<uint8_t> keyResponse = {}; |
| 248 | keyResponse.appendArray(data, size); |
| 249 | Vector<uint8_t> keySetId = {}; |
| 250 | mDrm->provideKeyResponse(mSessionId, keyResponse, keySetId); |
| 251 | |
| 252 | // restoreKeys |
| 253 | mDrm->restoreKeys(mSessionId, keySetId); |
| 254 | |
| 255 | // queryKeyStatus() shall fill infoMap |
| 256 | KeyedVector<String8, String8> infoMap = {}; |
| 257 | mDrm->queryKeyStatus(mSessionId, infoMap); |
| 258 | |
| 259 | // decrypt() shall fill outputVec |
| 260 | Vector<uint8_t> keyIdVec = {}; |
| 261 | keyIdVec.appendArray(data, size); |
| 262 | |
| 263 | Vector<uint8_t> inputVec = {}; |
| 264 | inputVec.appendArray(data, size); |
| 265 | |
| 266 | Vector<uint8_t> ivVec = {}; |
| 267 | ivVec.appendArray(data, size); |
| 268 | |
| 269 | Vector<uint8_t> outputVec = {}; |
| 270 | mDrm->decrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec); |
| 271 | |
| 272 | // encrypt() shall fill outputVec |
| 273 | mDrm->encrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec); |
| 274 | |
| 275 | // sign() shall fill signature |
| 276 | Vector<uint8_t> message = {}; |
| 277 | message.appendArray(data, size); |
| 278 | Vector<uint8_t> signature = {}; |
| 279 | mDrm->sign(mSessionId, keyIdVec, message, signature); |
| 280 | |
| 281 | // verify() shall fill match |
| 282 | bool match; |
| 283 | mDrm->verify(mSessionId, keyIdVec, message, signature, match); |
| 284 | |
| 285 | // signRSA() shall fill signature |
| 286 | mDrm->signRSA(mSessionId, String8(kRSAAlgorithm[mFuzzedDataProvider->ConsumeBool()]), message, |
| 287 | wrappedKey, signature); |
| 288 | |
| 289 | mDrm->removeKeys(mSessionId); |
| 290 | } |
| 291 | |
| 292 | void DrmFuzzer::invokeDrmSecureStopAPI() { |
| 293 | // getSecureStops() shall fill secureStops |
| 294 | List<Vector<uint8_t>> secureStops = {}; |
| 295 | mDrm->getSecureStops(secureStops); |
| 296 | |
| 297 | // getSecureStopIds() shall fill secureStopIds |
| 298 | List<Vector<uint8_t>> secureStopIds = {}; |
| 299 | mDrm->getSecureStopIds(secureStopIds); |
| 300 | |
| 301 | // getSecureStop() shall fill secureStop |
| 302 | Vector<uint8_t> ssid = {}; |
| 303 | Vector<uint8_t> secureStop = {}; |
| 304 | mDrm->getSecureStop(ssid, secureStop); |
| 305 | |
| 306 | mDrm->removeSecureStop(ssid); |
| 307 | |
| 308 | mDrm->releaseSecureStops(ssid); |
| 309 | |
| 310 | mDrm->removeAllSecureStops(); |
| 311 | } |
| 312 | |
| 313 | void DrmFuzzer::invokeDrmOfflineLicenseAPI() { |
| 314 | // getOfflineLicenseKeySetIds() shall keySetIds |
| 315 | List<Vector<uint8_t>> keySetIds = {}; |
| 316 | mDrm->getOfflineLicenseKeySetIds(keySetIds); |
| 317 | |
| 318 | // getOfflineLicenseState() shall fill state |
| 319 | Vector<uint8_t> const keySetIdOfflineLicense = {}; |
| 320 | DrmPlugin::OfflineLicenseState state; |
| 321 | mDrm->getOfflineLicenseState(keySetIdOfflineLicense, &state); |
| 322 | |
| 323 | mDrm->removeOfflineLicense(keySetIdOfflineLicense); |
| 324 | } |
| 325 | |
| 326 | bool DrmFuzzer::initCrypto() { |
| 327 | mCrypto = new CryptoHal(); |
| 328 | if (!mCrypto) { |
| 329 | return false; |
| 330 | } |
| 331 | return true; |
| 332 | } |
| 333 | |
| 334 | void DrmFuzzer::invokeCryptoCreatePlugin() { |
| 335 | mCrypto->initCheck(); |
| 336 | |
| 337 | mCrypto->isCryptoSchemeSupported(kClearKeyUUID); |
| 338 | mCrypto->createPlugin(kClearKeyUUID, NULL, 0); |
| 339 | } |
| 340 | |
| 341 | void DrmFuzzer::invokeCryptoDestroyPlugin() { mCrypto->destroyPlugin(); } |
| 342 | |
| 343 | void DrmFuzzer::invokeCryptoDecrypt(const uint8_t *data) { |
| 344 | mCrypto->requiresSecureDecoderComponent( |
| 345 | kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]); |
| 346 | |
| 347 | uint32_t width = mFuzzedDataProvider->ConsumeIntegral<uint32_t>(); |
| 348 | uint32_t height = mFuzzedDataProvider->ConsumeIntegral<uint32_t>(); |
| 349 | mCrypto->notifyResolution(width, height); |
| 350 | |
| 351 | mCrypto->setMediaDrmSession(mSessionId); |
| 352 | |
| 353 | const CryptoPlugin::Pattern pattern = {0, 0}; |
| 354 | |
| 355 | size_t totalSize = 0; |
| 356 | size_t numSubSamples = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxSubSamples); |
| 357 | |
| 358 | CryptoPlugin::SubSample subSamples[numSubSamples]; |
| 359 | |
| 360 | for (size_t i = 0; i < numSubSamples; ++i) { |
| 361 | uint32_t clearBytes = |
| 362 | mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes); |
| 363 | uint32_t encryptedBytes = |
| 364 | mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes); |
| 365 | subSamples[i].mNumBytesOfClearData = clearBytes; |
| 366 | subSamples[i].mNumBytesOfEncryptedData = encryptedBytes; |
| 367 | totalSize += subSamples[i].mNumBytesOfClearData; |
| 368 | totalSize += subSamples[i].mNumBytesOfEncryptedData; |
| 369 | } |
| 370 | |
| 371 | size_t heapSize = totalSize * 2; |
| 372 | sp<MemoryDealer> dealer = new MemoryDealer(heapSize, "DrmFuzzerMemory"); |
| 373 | if (!dealer) { |
| 374 | return; |
| 375 | } |
| 376 | |
| 377 | sp<HidlMemory> heap = fromHeap(dealer->getMemoryHeap()); |
| 378 | if (!heap) { |
| 379 | return; |
| 380 | } |
| 381 | int heapSeqNum = mCrypto->setHeap(heap); |
| 382 | if (heapSeqNum < 0) { |
| 383 | return; |
| 384 | } |
| 385 | |
| 386 | const size_t segmentIndex = 0; |
| 387 | const uint8_t keyId[AES_BLOCK_SIZE] = {}; |
| 388 | memcpy((void *)keyId, data, AES_BLOCK_SIZE); |
| 389 | |
| 390 | const uint8_t iv[AES_BLOCK_SIZE] = {}; |
| 391 | memset((void *)iv, 0, AES_BLOCK_SIZE); |
| 392 | |
| 393 | const SharedBuffer sourceBuffer = {.bufferId = segmentIndex, .offset = 0, .size = totalSize}; |
| 394 | |
| 395 | const DestinationBuffer destBuffer = { |
| 396 | .type = BufferType::SHARED_MEMORY, |
| 397 | {.bufferId = segmentIndex, .offset = totalSize, .size = totalSize}, |
| 398 | .secureMemory = nullptr}; |
| 399 | |
| 400 | const uint64_t offset = 0; |
| 401 | AString *errorDetailMsg = nullptr; |
| 402 | CryptoPlugin::Mode mode; |
| 403 | bool shouldPassRandomCryptoMode = mFuzzedDataProvider->ConsumeBool(); |
| 404 | if (shouldPassRandomCryptoMode) { |
| 405 | mode = static_cast<CryptoPlugin::Mode>(mFuzzedDataProvider->ConsumeIntegral<size_t>()); |
| 406 | } else { |
| 407 | mode = |
| 408 | kCryptoMode[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumCryptoMode - 1)]; |
| 409 | } |
| 410 | mCrypto->decrypt(keyId, iv, mode, pattern, sourceBuffer, offset, subSamples, numSubSamples, |
| 411 | destBuffer, errorDetailMsg); |
| 412 | |
| 413 | if (heapSeqNum >= 0) { |
| 414 | mCrypto->unsetHeap(heapSeqNum); |
| 415 | } |
| 416 | heap.clear(); |
| 417 | } |
| 418 | |
| 419 | void DrmFuzzer::invokeDrm(const uint8_t *data, size_t size) { |
| 420 | if (!initDrm()) { |
| 421 | return; |
| 422 | } |
| 423 | invokeDrmCreatePlugin(); |
| 424 | invokeDrmOpenSession(); |
| 425 | invokeDrmSetAlgorithmAPI(); |
| 426 | invokeDrmSetListener(); |
| 427 | invokeDrmPropertyAPI(); |
| 428 | invokeDrmDecryptEncryptAPI(data, size); |
| 429 | invokeDrmSecureStopAPI(); |
| 430 | invokeDrmOfflineLicenseAPI(); |
| 431 | invokeDrmCloseSession(); |
| 432 | invokeDrmDestroyPlugin(); |
| 433 | } |
| 434 | |
| 435 | void DrmFuzzer::invokeCrypto(const uint8_t *data) { |
| 436 | if (!initCrypto()) { |
| 437 | return; |
| 438 | } |
| 439 | invokeCryptoCreatePlugin(); |
| 440 | invokeCryptoDecrypt(data); |
| 441 | invokeCryptoDestroyPlugin(); |
| 442 | } |
| 443 | |
| 444 | void DrmFuzzer::process(const uint8_t *data, size_t size) { |
| 445 | mFuzzedDataProvider = new FuzzedDataProvider(data, size); |
| 446 | invokeDrm(data, size); |
| 447 | invokeCrypto(data); |
| 448 | delete mFuzzedDataProvider; |
| 449 | } |
| 450 | |
| 451 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
| 452 | if (size < AES_BLOCK_SIZE) { |
| 453 | return 0; |
| 454 | } |
| 455 | DrmFuzzer drmFuzzer; |
| 456 | drmFuzzer.process(data, size); |
| 457 | return 0; |
| 458 | } |