• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #include <include/CreatePluginFactories.h>
19 
20 #include <android/hidl/allocator/1.0/IAllocator.h>
21 #include <fuzzer/FuzzedDataProvider.h>
22 #include <hidlmemory/mapping.h>
23 #include <include/ClearKeyDrmProperties.h>
24 #include <include/CryptoFactory.h>
25 #include <include/CryptoPlugin.h>
26 #include <include/DrmPlugin.h>
27 #include <utils/Log.h>
28 #include <utils/String8.h>
29 
30 namespace drm = ::android::hardware::drm;
31 using namespace std;
32 using namespace android;
33 using ::android::sp;
34 using ::android::hardware::hidl_array;
35 using ::android::hardware::hidl_memory;
36 using ::android::hardware::hidl_string;
37 using ::android::hardware::hidl_vec;
38 using ::android::hardware::Return;
39 using ::android::hidl::allocator::V1_0::IAllocator;
40 using ::android::hidl::memory::V1_0::IMemory;
41 using drm::V1_0::BufferType;
42 using drm::V1_0::DestinationBuffer;
43 using drm::V1_0::EventType;
44 using drm::V1_0::ICryptoPlugin;
45 using drm::V1_0::IDrmPlugin;
46 using drm::V1_0::IDrmPluginListener;
47 using drm::V1_0::KeyedVector;
48 using drm::V1_0::KeyStatus;
49 using drm::V1_0::KeyStatusType;
50 using drm::V1_0::KeyType;
51 using drm::V1_0::Mode;
52 using drm::V1_0::Pattern;
53 using drm::V1_0::SecureStop;
54 using drm::V1_0::SharedBuffer;
55 using drm::V1_0::Status;
56 using drm::V1_0::SubSample;
57 using drm::V1_1::DrmMetricGroup;
58 using drm::V1_1::HdcpLevel;
59 using drm::V1_1::SecureStopRelease;
60 using drm::V1_1::SecurityLevel;
61 using drm::V1_2::KeySetId;
62 using drm::V1_2::OfflineLicenseState;
63 using drm::V1_4::clearkey::ICryptoFactory;
64 using drm::V1_4::clearkey::IDrmFactory;
65 using drm::V1_4::clearkey::kAlgorithmsKey;
66 using drm::V1_4::clearkey::kClientIdKey;
67 using drm::V1_4::clearkey::kDeviceIdKey;
68 using drm::V1_4::clearkey::kDrmErrorTestKey;
69 using drm::V1_4::clearkey::kListenerTestSupportKey;
70 using drm::V1_4::clearkey::kMetricsKey;
71 using drm::V1_4::clearkey::kPluginDescriptionKey;
72 using drm::V1_4::clearkey::kVendorKey;
73 using drm::V1_4::clearkey::kVersionKey;
74 
75 typedef ::android::hardware::hidl_vec<uint8_t> SessionId;
76 typedef ::android::hardware::hidl_vec<uint8_t> SecureStopId;
77 
78 static const uint8_t kInvalidUUID[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
79                                        0x70, 0x80, 0x10, 0x20, 0x30, 0x40,
80                                        0x50, 0x60, 0x70, 0x80};
81 
82 static const uint8_t kClearKeyUUID[] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85,
83                                         0xB3, 0xC9, 0x78, 0x1A, 0xB0, 0x30,
84                                         0xAF, 0x78, 0xD3, 0x0E};
85 
86 const SecurityLevel kSecurityLevel[] = {
87     SecurityLevel::UNKNOWN,          SecurityLevel::SW_SECURE_CRYPTO,
88     SecurityLevel::SW_SECURE_DECODE, SecurityLevel::HW_SECURE_CRYPTO,
89     SecurityLevel::HW_SECURE_DECODE, SecurityLevel::HW_SECURE_ALL};
90 
91 const char *kMimeType[] = {
92     "video/mp4",  "video/mpeg",  "video/x-flv",   "video/mj2",    "video/3gp2",
93     "video/3gpp", "video/3gpp2", "audio/mp4",     "audio/mpeg",   "audio/aac",
94     "audio/3gp2", "audio/3gpp",  "audio/3gpp2",   "audio/webm",   "video/webm",
95     "webm",       "cenc",        "video/unknown", "audio/unknown"};
96 
97 const char *kCipherAlgorithm[] = {"AES/CBC/NoPadding", ""};
98 
99 const char *kMacAlgorithm[] = {"HmacSHA256", ""};
100 
101 const char *kRSAAlgorithm[] = {"RSASSA-PSS-SHA1", ""};
102 
103 const std::string kProperty[] = {kVendorKey,
104                                  kVersionKey,
105                                  kPluginDescriptionKey,
106                                  kAlgorithmsKey,
107                                  kListenerTestSupportKey,
108                                  kDrmErrorTestKey,
109                                  kDeviceIdKey,
110                                  kClientIdKey,
111                                  kMetricsKey,
112                                  "placeholder"};
113 
114 const KeyType kKeyType[] = {KeyType::OFFLINE, KeyType::STREAMING,
115                             KeyType::RELEASE};
116 
117 const Mode kCryptoMode[] = {Mode::UNENCRYPTED, Mode::AES_CTR, Mode::AES_CBC_CTS,
118                             Mode::AES_CBC};
119 
120 const hidl_vec<uint8_t> validInitData = {
121     // BMFF box header (4 bytes size + 'pssh')
122     0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
123     // full box header (version = 1 flags = 0)
124     0x01, 0x00, 0x00, 0x00,
125     // system id
126     0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e,
127     0x52, 0xe2, 0xfb, 0x4b,
128     // number of key ids
129     0x00, 0x00, 0x00, 0x01,
130     // key id
131     0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d,
132     0x1e, 0xd0, 0x0d, 0x1e,
133     // size of data, must be zero
134     0x00, 0x00, 0x00, 0x00};
135 
136 const hidl_vec<uint8_t> validKeyResponse = {
137     0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22,
138     0x6b, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c,
139     0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 0x41, 0x59, 0x65,
140     0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41,
141     0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b,
142     0x22, 0x3a, 0x22, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65,
143     0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34,
144     0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
145 
146 const size_t kAESBlockSize = 16;
147 const size_t kMaxStringLength = 100;
148 const size_t kMaxSubSamples = 10;
149 const size_t kMaxNumBytes = 1000;
150 const size_t kSegmentIndex = 0;
151 
152 template <typename T, size_t size>
getValueFromArray(FuzzedDataProvider * fdp,const T (& arr)[size])153 T getValueFromArray(FuzzedDataProvider *fdp, const T (&arr)[size]) {
154   return arr[fdp->ConsumeIntegralInRange<int32_t>(0, size - 1)];
155 }
156 
157 class TestDrmPluginListener : public IDrmPluginListener {
158 public:
TestDrmPluginListener()159   TestDrmPluginListener() {}
~TestDrmPluginListener()160   virtual ~TestDrmPluginListener() {}
161 
sendEvent(EventType,const hidl_vec<uint8_t> &,const hidl_vec<uint8_t> &)162   virtual Return<void> sendEvent(EventType /*eventType*/,
163                                  const hidl_vec<uint8_t> & /*sessionId*/,
164                                  const hidl_vec<uint8_t> & /*data*/) override {
165     return Return<void>();
166   }
167 
168   virtual Return<void>
sendExpirationUpdate(const hidl_vec<uint8_t> &,int64_t)169   sendExpirationUpdate(const hidl_vec<uint8_t> & /*sessionId*/,
170                        int64_t /*expiryTimeInMS*/) override {
171     return Return<void>();
172   }
173 
174   virtual Return<void>
sendKeysChange(const hidl_vec<uint8_t> &,const hidl_vec<KeyStatus> &,bool)175   sendKeysChange(const hidl_vec<uint8_t> & /*sessionId*/,
176                  const hidl_vec<KeyStatus> & /*keyStatusList*/,
177                  bool /*hasNewUsableKey*/) override {
178     return Return<void>();
179   }
180 };
181 
182 class ClearKeyFuzzer {
183 public:
~ClearKeyFuzzer()184   ~ClearKeyFuzzer() { deInit(); }
185   bool init();
186   void process(const uint8_t *data, size_t size);
187 
188 private:
189   void deInit();
190   void invokeDrmPlugin(const uint8_t *data, size_t size);
191   void invokeCryptoPlugin(const uint8_t *data);
192   void invokeDrm(const uint8_t *data, size_t size);
193   void invokeCrypto(const uint8_t *data);
194   void invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size);
195   bool invokeDrmFactory();
196   bool invokeCryptoFactory();
197   void invokeDrmV1_4API();
198   void invokeDrmSetAlgorithmAPI();
199   void invokeDrmPropertyAPI();
200   void invokeDrmSecureStopAPI();
201   void invokeDrmOfflineLicenseAPI(const uint8_t *data, size_t size);
202   SessionId getSessionId();
203   SecureStopRelease makeSecureRelease(const SecureStop &stop);
204   sp<IDrmFactory> mDrmFactory = nullptr;
205   sp<ICryptoFactory> mCryptoFactory = nullptr;
206   sp<IDrmPlugin> mDrmPlugin = nullptr;
207   sp<drm::V1_1::IDrmPlugin> mDrmPluginV1_1 = nullptr;
208   sp<drm::V1_2::IDrmPlugin> mDrmPluginV1_2 = nullptr;
209   sp<drm::V1_4::IDrmPlugin> mDrmPluginV1_4 = nullptr;
210   sp<drm::V1_4::ICryptoPlugin> mCryptoPluginV1_4 = nullptr;
211   sp<ICryptoPlugin> mCryptoPlugin = nullptr;
212   FuzzedDataProvider *mFDP = nullptr;
213   SessionId mSessionId = {};
214   SessionId mSessionIdV1 = {};
215 };
216 
deInit()217 void ClearKeyFuzzer::deInit() {
218   if (mDrmPluginV1_1) {
219     mDrmPluginV1_1->closeSession(mSessionIdV1);
220   }
221   if (mDrmPluginV1_2) {
222     mDrmPluginV1_2->closeSession(mSessionId);
223   }
224   mDrmFactory.clear();
225   mCryptoFactory.clear();
226   mDrmPlugin.clear();
227   mDrmPluginV1_1.clear();
228   mDrmPluginV1_2.clear();
229   mDrmPluginV1_4.clear();
230   mCryptoPlugin.clear();
231   mCryptoPluginV1_4.clear();
232   mSessionId = {};
233   mSessionIdV1 = {};
234 }
235 
invokeDrmV1_4API()236 void ClearKeyFuzzer::invokeDrmV1_4API() {
237   mDrmPluginV1_4->requiresSecureDecoderDefault(
238       getValueFromArray(mFDP, kMimeType));
239   mDrmPluginV1_4->requiresSecureDecoder(
240       getValueFromArray(mFDP, kMimeType),
241       getValueFromArray(mFDP, kSecurityLevel));
242   mDrmPluginV1_4->setPlaybackId(
243       mSessionId, mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str());
244   drm::V1_4::IDrmPlugin::getLogMessages_cb cb =
245       [&]([[maybe_unused]] drm::V1_4::Status status,
246           [[maybe_unused]] hidl_vec<drm::V1_4::LogMessage> logs) {};
247   mDrmPluginV1_4->getLogMessages(cb);
248 }
249 
invokeDrmSetAlgorithmAPI()250 void ClearKeyFuzzer::invokeDrmSetAlgorithmAPI() {
251   const hidl_string cipherAlgo =
252       mFDP->ConsumeBool()
253           ? mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str()
254           : hidl_string(kCipherAlgorithm[mFDP->ConsumeBool()]);
255   mDrmPluginV1_2->setCipherAlgorithm(mSessionId, cipherAlgo);
256 
257   const hidl_string macAlgo =
258       mFDP->ConsumeBool()
259           ? mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str()
260           : hidl_string(kMacAlgorithm[mFDP->ConsumeBool()]);
261   mDrmPluginV1_2->setMacAlgorithm(mSessionId, macAlgo);
262 }
263 
invokeDrmPropertyAPI()264 void ClearKeyFuzzer::invokeDrmPropertyAPI() {
265   mDrmPluginV1_2->setPropertyString(
266       hidl_string(getValueFromArray(mFDP, kProperty)), hidl_string("value"));
267 
268   hidl_string stringValue;
269   mDrmPluginV1_2->getPropertyString(
270       getValueFromArray(mFDP, kProperty),
271       [&](Status status, const hidl_string &hValue) {
272         if (status == Status::OK) {
273           stringValue = hValue;
274         }
275       });
276 
277   hidl_vec<uint8_t> value = {};
278   mDrmPluginV1_2->setPropertyByteArray(
279       hidl_string(getValueFromArray(mFDP, kProperty)), value);
280 
281   hidl_vec<uint8_t> byteValue;
282   mDrmPluginV1_2->getPropertyByteArray(
283       getValueFromArray(mFDP, kProperty),
284       [&](Status status, const hidl_vec<uint8_t> &hValue) {
285         if (status == Status::OK) {
286           byteValue = hValue;
287         }
288       });
289 }
290 
getSessionId()291 SessionId ClearKeyFuzzer::getSessionId() {
292   SessionId emptySessionId = {};
293   return mFDP->ConsumeBool() ? mSessionId : emptySessionId;
294 }
295 
invokeDrmDecryptEncryptAPI(const uint8_t * data,size_t size)296 void ClearKeyFuzzer::invokeDrmDecryptEncryptAPI(const uint8_t *data,
297                                                 size_t size) {
298   uint32_t currSessions, maximumSessions;
299   mDrmPluginV1_2->getNumberOfSessions(
300       [&](Status status, uint32_t hCurrentSessions, uint32_t hMaxSessions) {
301         if (status == Status::OK) {
302           currSessions = hCurrentSessions;
303           maximumSessions = hMaxSessions;
304         }
305       });
306 
307   HdcpLevel connected, maximum;
308   mDrmPluginV1_2->getHdcpLevels([&](Status status,
309                                     const HdcpLevel &hConnectedLevel,
310                                     const HdcpLevel &hMaxLevel) {
311     if (status == Status::OK) {
312       connected = hConnectedLevel;
313       maximum = hMaxLevel;
314     }
315   });
316 
317   drm::V1_2::HdcpLevel connectedV1_2, maximumV1_2;
318   mDrmPluginV1_2->getHdcpLevels_1_2(
319       [&](drm::V1_2::Status status, const drm::V1_2::HdcpLevel &connectedLevel,
320           const drm::V1_2::HdcpLevel &maxLevel) {
321         if (status == drm::V1_2::Status::OK) {
322           connectedV1_2 = connectedLevel;
323           maximumV1_2 = maxLevel;
324         }
325       });
326 
327   SecurityLevel securityLevel;
328   mDrmPluginV1_2->getSecurityLevel(mSessionId,
329                                    [&](Status status, SecurityLevel hLevel) {
330                                      if (status == Status::OK) {
331                                        securityLevel = hLevel;
332                                      }
333                                    });
334 
335   hidl_vec<DrmMetricGroup> metrics;
336   mDrmPluginV1_2->getMetrics(
337       [&](Status status, hidl_vec<DrmMetricGroup> hMetricGroups) {
338         if (status == Status::OK) {
339           metrics = hMetricGroups;
340         }
341       });
342 
343   hidl_string certificateType;
344   hidl_string certificateAuthority;
345   mDrmPluginV1_2->getProvisionRequest(certificateType, certificateAuthority,
346                                       [&]([[maybe_unused]] Status status,
347                                           const hidl_vec<uint8_t> &,
348                                           const hidl_string &) {});
349 
350   mDrmPluginV1_2->getProvisionRequest_1_2(
351       certificateType, certificateAuthority,
352       [&]([[maybe_unused]] drm::V1_2::Status status, const hidl_vec<uint8_t> &,
353           const hidl_string &) {});
354 
355   hidl_vec<uint8_t> response;
356   mDrmPluginV1_2->provideProvisionResponse(
357       response, [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &,
358                     const hidl_vec<uint8_t> &) {});
359 
360   hidl_vec<uint8_t> initData = {};
361   if (mFDP->ConsumeBool()) {
362     initData = validInitData;
363   } else {
364     initData.setToExternal(const_cast<uint8_t *>(data), kAESBlockSize);
365   }
366   hidl_string mimeType = getValueFromArray(mFDP, kMimeType);
367   KeyType keyType = mFDP->ConsumeBool()
368                         ? static_cast<KeyType>(mFDP->ConsumeIntegral<size_t>())
369                         : getValueFromArray(mFDP, kKeyType);
370   KeyedVector optionalParameters;
371   mDrmPluginV1_2->getKeyRequest_1_2(
372       mSessionId, initData, mimeType, keyType, optionalParameters,
373       [&]([[maybe_unused]] drm::V1_2::Status status, const hidl_vec<uint8_t> &,
374           drm::V1_1::KeyRequestType, const hidl_string &) {});
375   mDrmPluginV1_1->getKeyRequest_1_1(
376       mSessionIdV1, initData, mimeType, keyType, optionalParameters,
377       [&]([[maybe_unused]] drm::V1_0::Status status, const hidl_vec<uint8_t> &,
378           drm::V1_1::KeyRequestType, const hidl_string &) {});
379   hidl_vec<uint8_t> emptyInitData = {};
380   mDrmPlugin->getKeyRequest(
381       mSessionId, mFDP->ConsumeBool() ? initData : emptyInitData, mimeType,
382       keyType, optionalParameters,
383       [&]([[maybe_unused]] drm::V1_0::Status status, const hidl_vec<uint8_t> &,
384           drm::V1_0::KeyRequestType, const hidl_string &) {});
385 
386   hidl_vec<uint8_t> keyResponse = {};
387   if (mFDP->ConsumeBool()) {
388     keyResponse = validKeyResponse;
389   } else {
390     keyResponse.setToExternal(const_cast<uint8_t *>(data), size);
391   }
392   hidl_vec<uint8_t> keySetId;
393   hidl_vec<uint8_t> emptyKeyResponse = {};
394   mDrmPluginV1_2->provideKeyResponse(
395       getSessionId(), mFDP->ConsumeBool() ? keyResponse : emptyKeyResponse,
396       [&](Status status, const hidl_vec<uint8_t> &hKeySetId) {
397         if (status == Status::OK) {
398           keySetId = hKeySetId;
399         }
400       });
401 
402   mDrmPluginV1_2->restoreKeys(getSessionId(), keySetId);
403 
404   mDrmPluginV1_2->queryKeyStatus(
405       getSessionId(),
406       [&]([[maybe_unused]] Status status, KeyedVector /* info */) {});
407 
408   hidl_vec<uint8_t> keyId, input, iv;
409   keyId.setToExternal(const_cast<uint8_t *>(data), size);
410   input.setToExternal(const_cast<uint8_t *>(data), size);
411   iv.setToExternal(const_cast<uint8_t *>(data), size);
412   mDrmPluginV1_2->encrypt(
413       getSessionId(), keyId, input, iv,
414       [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
415 
416   mDrmPluginV1_2->decrypt(
417       getSessionId(), keyId, input, iv,
418       [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
419 
420   hidl_vec<uint8_t> message;
421   message.setToExternal(const_cast<uint8_t *>(data), size);
422   mDrmPluginV1_2->sign(
423       getSessionId(), keyId, message,
424       [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
425 
426   hidl_vec<uint8_t> signature;
427   signature.setToExternal(const_cast<uint8_t *>(data), size);
428   mDrmPluginV1_2->verify(getSessionId(), keyId, message, signature,
429                          [&]([[maybe_unused]] Status status, bool) {});
430 
431   hidl_vec<uint8_t> wrappedKey;
432   signature.setToExternal(const_cast<uint8_t *>(data), size);
433   mDrmPluginV1_2->signRSA(
434       getSessionId(), kRSAAlgorithm[mFDP->ConsumeBool()], message, wrappedKey,
435       [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
436 
437   mDrmPluginV1_2->removeKeys(getSessionId());
438 }
439 
440 /**
441  * Helper function to create a secure release message for
442  * a secure stop. The clearkey secure stop release format
443  * is just a count followed by the secure stop opaque data.
444  */
makeSecureRelease(const SecureStop & stop)445 SecureStopRelease ClearKeyFuzzer::makeSecureRelease(const SecureStop &stop) {
446   std::vector<uint8_t> stopData = stop.opaqueData;
447   std::vector<uint8_t> buffer;
448   std::string count = "0001";
449 
450   auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
451   buffer.insert(it + count.size(), stopData.begin(), stopData.end());
452   SecureStopRelease release = {.opaqueData = hidl_vec<uint8_t>(buffer)};
453   return release;
454 }
455 
invokeDrmSecureStopAPI()456 void ClearKeyFuzzer::invokeDrmSecureStopAPI() {
457   SecureStopId ssid;
458   mDrmPluginV1_2->getSecureStop(
459       ssid, [&]([[maybe_unused]] Status status, const SecureStop &) {});
460 
461   mDrmPluginV1_2->getSecureStopIds(
462       [&]([[maybe_unused]] Status status,
463           [[maybe_unused]] const hidl_vec<SecureStopId> &secureStopIds) {});
464 
465   SecureStopRelease release;
466   mDrmPluginV1_2->getSecureStops(
467       [&]([[maybe_unused]] Status status, const hidl_vec<SecureStop> &stops) {
468         if (stops.size() > 0) {
469           release = makeSecureRelease(
470               stops[mFDP->ConsumeIntegralInRange<size_t>(0, stops.size() - 1)]);
471         }
472       });
473 
474   mDrmPluginV1_2->releaseSecureStops(release);
475 
476   mDrmPluginV1_2->removeSecureStop(ssid);
477 
478   mDrmPluginV1_2->removeAllSecureStops();
479 
480   mDrmPluginV1_2->releaseSecureStop(ssid);
481 
482   mDrmPluginV1_2->releaseAllSecureStops();
483 }
484 
invokeDrmOfflineLicenseAPI(const uint8_t * data,size_t size)485 void ClearKeyFuzzer::invokeDrmOfflineLicenseAPI(const uint8_t *data,
486                                                 size_t size) {
487   hidl_vec<KeySetId> keySetIds = {};
488   mDrmPluginV1_2->getOfflineLicenseKeySetIds(
489       [&](Status status, const hidl_vec<KeySetId> &hKeySetIds) {
490         if (status == Status::OK) {
491           keySetIds = hKeySetIds;
492         }
493       });
494 
495   OfflineLicenseState licenseState;
496   KeySetId keySetId = {};
497   if (keySetIds.size() > 0) {
498     keySetId = keySetIds[mFDP->ConsumeIntegralInRange<size_t>(
499         0, keySetIds.size() - 1)];
500   } else {
501     keySetId.setToExternal(const_cast<uint8_t *>(data), size);
502   }
503   mDrmPluginV1_2->getOfflineLicenseState(
504       keySetId, [&](Status status, OfflineLicenseState hLicenseState) {
505         if (status == Status::OK) {
506           licenseState = hLicenseState;
507         }
508       });
509 
510   mDrmPluginV1_2->removeOfflineLicense(keySetId);
511 }
512 
invokeDrmPlugin(const uint8_t * data,size_t size)513 void ClearKeyFuzzer::invokeDrmPlugin(const uint8_t *data, size_t size) {
514   SecurityLevel secLevel =
515       mFDP->ConsumeBool()
516           ? getValueFromArray(mFDP, kSecurityLevel)
517           : static_cast<SecurityLevel>(mFDP->ConsumeIntegral<uint32_t>());
518   mDrmPluginV1_1->openSession_1_1(
519       secLevel, [&]([[maybe_unused]] Status status, const SessionId &id) {
520         mSessionIdV1 = id;
521       });
522   mDrmPluginV1_2->openSession([&]([[maybe_unused]] Status status,
523                                   const SessionId &id) { mSessionId = id; });
524 
525   sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
526   mDrmPluginV1_2->setListener(listener);
527   const hidl_vec<KeyStatus> keyStatusList = {
528       {{1}, KeyStatusType::USABLE},
529       {{2}, KeyStatusType::EXPIRED},
530       {{3}, KeyStatusType::OUTPUTNOTALLOWED},
531       {{4}, KeyStatusType::STATUSPENDING},
532       {{5}, KeyStatusType::INTERNALERROR},
533   };
534   mDrmPluginV1_2->sendKeysChange(mSessionId, keyStatusList, true);
535 
536   invokeDrmV1_4API();
537   invokeDrmSetAlgorithmAPI();
538   invokeDrmPropertyAPI();
539   invokeDrmDecryptEncryptAPI(data, size);
540   invokeDrmSecureStopAPI();
541   invokeDrmOfflineLicenseAPI(data, size);
542 }
543 
invokeCryptoPlugin(const uint8_t * data)544 void ClearKeyFuzzer::invokeCryptoPlugin(const uint8_t *data) {
545   mCryptoPlugin->requiresSecureDecoderComponent(
546       getValueFromArray(mFDP, kMimeType));
547 
548   const uint32_t width = mFDP->ConsumeIntegral<uint32_t>();
549   const uint32_t height = mFDP->ConsumeIntegral<uint32_t>();
550   mCryptoPlugin->notifyResolution(width, height);
551 
552   mCryptoPlugin->setMediaDrmSession(mSessionId);
553 
554   size_t totalSize = 0;
555   const size_t numSubSamples =
556       mFDP->ConsumeIntegralInRange<size_t>(1, kMaxSubSamples);
557 
558   const Pattern pattern = {0, 0};
559   hidl_vec<SubSample> subSamples;
560   subSamples.resize(numSubSamples);
561 
562   for (size_t i = 0; i < numSubSamples; ++i) {
563     const uint32_t clearBytes =
564         mFDP->ConsumeIntegralInRange<uint32_t>(0, kMaxNumBytes);
565     const uint32_t encryptedBytes =
566         mFDP->ConsumeIntegralInRange<uint32_t>(0, kMaxNumBytes);
567     subSamples[i].numBytesOfClearData = clearBytes;
568     subSamples[i].numBytesOfEncryptedData = encryptedBytes;
569     totalSize += subSamples[i].numBytesOfClearData;
570     totalSize += subSamples[i].numBytesOfEncryptedData;
571   }
572 
573   // The first totalSize bytes of shared memory is the encrypted
574   // input, the second totalSize bytes is the decrypted output.
575   size_t memoryBytes = totalSize * 2;
576 
577   sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
578   if (!ashmemAllocator.get()) {
579     return;
580   }
581 
582   hidl_memory hidlMemory;
583   ashmemAllocator->allocate(memoryBytes, [&]([[maybe_unused]] bool success,
584                                              const hidl_memory &memory) {
585     mCryptoPlugin->setSharedBufferBase(memory, kSegmentIndex);
586     hidlMemory = memory;
587   });
588 
589   sp<IMemory> mappedMemory = mapMemory(hidlMemory);
590   if (!mappedMemory.get()) {
591     return;
592   }
593   mCryptoPlugin->setSharedBufferBase(hidlMemory, kSegmentIndex);
594 
595   uint32_t srcBufferId =
596       mFDP->ConsumeBool() ? kSegmentIndex : mFDP->ConsumeIntegral<uint32_t>();
597   const SharedBuffer sourceBuffer = {
598       .bufferId = srcBufferId, .offset = 0, .size = totalSize};
599 
600   BufferType type = mFDP->ConsumeBool() ? BufferType::SHARED_MEMORY
601                                         : BufferType::NATIVE_HANDLE;
602   uint32_t destBufferId =
603       mFDP->ConsumeBool() ? kSegmentIndex : mFDP->ConsumeIntegral<uint32_t>();
604   const DestinationBuffer destBuffer = {
605       .type = type,
606       {.bufferId = destBufferId, .offset = totalSize, .size = totalSize},
607       .secureMemory = nullptr};
608 
609   const uint64_t offset = 0;
610   uint32_t bytesWritten = 0;
611   hidl_array<uint8_t, kAESBlockSize> keyId =
612       hidl_array<uint8_t, kAESBlockSize>(data);
613   hidl_array<uint8_t, kAESBlockSize> iv =
614       hidl_array<uint8_t, kAESBlockSize>(data);
615   Mode mode = getValueFromArray(mFDP, kCryptoMode);
616   mCryptoPlugin->decrypt(
617       mFDP->ConsumeBool(), keyId, iv, mode, pattern, subSamples, sourceBuffer,
618       offset, destBuffer,
619       [&]([[maybe_unused]] Status status, uint32_t count,
620           [[maybe_unused]] string detailedError) { bytesWritten = count; });
621   drm::V1_4::IDrmPlugin::getLogMessages_cb cb =
622       [&]([[maybe_unused]] drm::V1_4::Status status,
623           [[maybe_unused]] hidl_vec<drm::V1_4::LogMessage> logs) {};
624   mCryptoPluginV1_4->getLogMessages(cb);
625 }
626 
invokeDrmFactory()627 bool ClearKeyFuzzer::invokeDrmFactory() {
628   hidl_string packageName(
629       mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str());
630   hidl_string mimeType(getValueFromArray(mFDP, kMimeType));
631   SecurityLevel securityLevel =
632       mFDP->ConsumeBool()
633           ? getValueFromArray(mFDP, kSecurityLevel)
634           : static_cast<SecurityLevel>(mFDP->ConsumeIntegral<uint32_t>());
635   const hidl_array<uint8_t, 16> uuid =
636       mFDP->ConsumeBool() ? kClearKeyUUID : kInvalidUUID;
637   mDrmFactory->isCryptoSchemeSupported_1_2(uuid, mimeType, securityLevel);
638   mDrmFactory->createPlugin(
639       uuid, packageName, [&](Status status, const sp<IDrmPlugin> &plugin) {
640         if (status == Status::OK) {
641           mDrmPlugin = plugin.get();
642           mDrmPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mDrmPlugin);
643           mDrmPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mDrmPlugin);
644           mDrmPluginV1_4 = drm::V1_4::IDrmPlugin::castFrom(mDrmPlugin);
645         }
646       });
647 
648   std::vector<hidl_array<uint8_t, 16>> supportedSchemes;
649   mDrmFactory->getSupportedCryptoSchemes(
650       [&](const hidl_vec<hidl_array<uint8_t, 16>> &schemes) {
651         for (const auto &scheme : schemes) {
652           supportedSchemes.push_back(scheme);
653         }
654       });
655 
656   if (!(mDrmPlugin && mDrmPluginV1_1 && mDrmPluginV1_2 && mDrmPluginV1_4)) {
657     return false;
658   }
659   return true;
660 }
661 
invokeCryptoFactory()662 bool ClearKeyFuzzer::invokeCryptoFactory() {
663   const hidl_array<uint8_t, 16> uuid =
664       mFDP->ConsumeBool() ? kClearKeyUUID : kInvalidUUID;
665   mCryptoFactory->createPlugin(
666       uuid, mSessionId, [this](Status status, const sp<ICryptoPlugin> &plugin) {
667         if (status == Status::OK) {
668           mCryptoPlugin = plugin;
669           mCryptoPluginV1_4 = drm::V1_4::ICryptoPlugin::castFrom(mCryptoPlugin);
670         }
671       });
672 
673   if (!mCryptoPlugin && !mCryptoPluginV1_4) {
674     return false;
675   }
676   return true;
677 }
678 
invokeDrm(const uint8_t * data,size_t size)679 void ClearKeyFuzzer::invokeDrm(const uint8_t *data, size_t size) {
680   if (!invokeDrmFactory()) {
681     return;
682   }
683   invokeDrmPlugin(data, size);
684 }
685 
invokeCrypto(const uint8_t * data)686 void ClearKeyFuzzer::invokeCrypto(const uint8_t *data) {
687   if (!invokeCryptoFactory()) {
688     return;
689   }
690   invokeCryptoPlugin(data);
691 }
692 
process(const uint8_t * data,size_t size)693 void ClearKeyFuzzer::process(const uint8_t *data, size_t size) {
694   mFDP = new FuzzedDataProvider(data, size);
695   invokeDrm(data, size);
696   invokeCrypto(data);
697   delete mFDP;
698 }
699 
init()700 bool ClearKeyFuzzer::init() {
701   mCryptoFactory =
702       android::hardware::drm::V1_4::clearkey::createCryptoFactory();
703   mDrmFactory = android::hardware::drm::V1_4::clearkey::createDrmFactory();
704   if (!mDrmFactory && !mCryptoFactory) {
705     return false;
706   }
707   return true;
708 }
709 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)710 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
711   if (size < kAESBlockSize) {
712     return 0;
713   }
714   ClearKeyFuzzer clearKeyFuzzer;
715   if (clearKeyFuzzer.init()) {
716     clearKeyFuzzer.process(data, size);
717   }
718   return 0;
719 }
720