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