1 /*
2 * Copyright (C) 2013 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MockDrmCryptoPlugin"
19 #include <utils/Log.h>
20
21
22 #include "media/drm/DrmAPI.h"
23 #include "MockDrmCryptoPlugin.h"
24 #include "media/stagefright/MediaErrors.h"
25
26 using namespace android;
27
28 // Shared library entry point
createDrmFactory()29 DrmFactory *createDrmFactory()
30 {
31 return new MockDrmFactory();
32 }
33
34 // Shared library entry point
createCryptoFactory()35 CryptoFactory *createCryptoFactory()
36 {
37 return new MockCryptoFactory();
38 }
39
40 const uint8_t mock_uuid[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
41 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
42
43 namespace android {
44
45 // MockDrmFactory
isCryptoSchemeSupported(const uint8_t uuid[16])46 bool MockDrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16])
47 {
48 return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
49 }
50
isContentTypeSupported(const String8 & mimeType)51 bool MockDrmFactory::isContentTypeSupported(const String8 &mimeType)
52 {
53 if (mimeType != "video/mp4") {
54 return false;
55 }
56 return true;
57 }
58
createDrmPlugin(const uint8_t[16],DrmPlugin ** plugin)59 status_t MockDrmFactory::createDrmPlugin(const uint8_t /* uuid */[16],
60 DrmPlugin **plugin)
61 {
62 *plugin = new MockDrmPlugin();
63 return OK;
64 }
65
66 // MockCryptoFactory
isCryptoSchemeSupported(const uint8_t uuid[16]) const67 bool MockCryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const
68 {
69 return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
70 }
71
createPlugin(const uint8_t[16],const void *,size_t,CryptoPlugin ** plugin)72 status_t MockCryptoFactory::createPlugin(const uint8_t /* uuid */[16],
73 const void * /* data */,
74 size_t /* size */, CryptoPlugin **plugin)
75 {
76 *plugin = new MockCryptoPlugin();
77 return OK;
78 }
79
80
81 // MockDrmPlugin methods
82
openSession(Vector<uint8_t> & sessionId)83 status_t MockDrmPlugin::openSession(Vector<uint8_t> &sessionId)
84 {
85 const size_t kSessionIdSize = 8;
86
87 Mutex::Autolock lock(mLock);
88 for (size_t i = 0; i < kSessionIdSize / sizeof(long); i++) {
89 long r = random();
90 sessionId.appendArray((uint8_t *)&r, sizeof(long));
91 }
92 mSessions.add(sessionId);
93
94 ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string());
95 return OK;
96 }
97
closeSession(Vector<uint8_t> const & sessionId)98 status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId)
99 {
100 Mutex::Autolock lock(mLock);
101 ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string());
102 ssize_t index = findSession(sessionId);
103 if (index == kNotFound) {
104 ALOGD("Invalid sessionId");
105 return BAD_VALUE;
106 }
107 mSessions.removeAt(index);
108 return OK;
109 }
110
111
getKeyRequest(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & initData,String8 const & mimeType,KeyType keyType,KeyedVector<String8,String8> const & optionalParameters,Vector<uint8_t> & request,String8 & defaultUrl,KeyRequestType * keyRequestType)112 status_t MockDrmPlugin::getKeyRequest(Vector<uint8_t> const &sessionId,
113 Vector<uint8_t> const &initData,
114 String8 const &mimeType, KeyType keyType,
115 KeyedVector<String8, String8> const &optionalParameters,
116 Vector<uint8_t> &request, String8 &defaultUrl,
117 KeyRequestType *keyRequestType)
118 {
119 Mutex::Autolock lock(mLock);
120 ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s"
121 ", keyType=%d, optionalParameters=%s))",
122 vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(),
123 keyType, stringMapToString(optionalParameters).string());
124
125 ssize_t index = findSession(sessionId);
126 if (index == kNotFound) {
127 ALOGD("Invalid sessionId");
128 return BAD_VALUE;
129 }
130
131 // Properties used in mock test, set by mock plugin and verifed cts test app
132 // byte[] initData -> mock-initdata
133 // string mimeType -> mock-mimetype
134 // string keyType -> mock-keytype
135 // string optionalParameters -> mock-optparams formatted as {key1,value1},{key2,value2}
136
137 mByteArrayProperties.add(String8("mock-initdata"), initData);
138 mStringProperties.add(String8("mock-mimetype"), mimeType);
139
140 String8 keyTypeStr;
141 keyTypeStr.appendFormat("%d", (int)keyType);
142 mStringProperties.add(String8("mock-keytype"), keyTypeStr);
143
144 String8 params;
145 for (size_t i = 0; i < optionalParameters.size(); i++) {
146 params.appendFormat("%s{%s,%s}", i ? "," : "",
147 optionalParameters.keyAt(i).string(),
148 optionalParameters.valueAt(i).string());
149 }
150 mStringProperties.add(String8("mock-optparams"), params);
151
152 // Properties used in mock test, set by cts test app returned from mock plugin
153 // byte[] mock-request -> request
154 // string mock-default-url -> defaultUrl
155 // string mock-keyRequestType -> keyRequestType
156
157 index = mByteArrayProperties.indexOfKey(String8("mock-request"));
158 if (index < 0) {
159 ALOGD("Missing 'mock-request' parameter for mock");
160 return BAD_VALUE;
161 } else {
162 request = mByteArrayProperties.valueAt(index);
163 }
164
165 index = mStringProperties.indexOfKey(String8("mock-defaultUrl"));
166 if (index < 0) {
167 ALOGD("Missing 'mock-defaultUrl' parameter for mock");
168 return BAD_VALUE;
169 } else {
170 defaultUrl = mStringProperties.valueAt(index);
171 }
172
173 index = mStringProperties.indexOfKey(String8("mock-keyRequestType"));
174 if (index < 0) {
175 ALOGD("Missing 'mock-keyRequestType' parameter for mock");
176 return BAD_VALUE;
177 } else {
178 *keyRequestType = static_cast<KeyRequestType>(
179 atoi(mStringProperties.valueAt(index).string()));
180 }
181
182 return OK;
183 }
184
provideKeyResponse(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & response,Vector<uint8_t> & keySetId)185 status_t MockDrmPlugin::provideKeyResponse(Vector<uint8_t> const &sessionId,
186 Vector<uint8_t> const &response,
187 Vector<uint8_t> &keySetId)
188 {
189 Mutex::Autolock lock(mLock);
190 ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)",
191 vectorToString(sessionId).string(), vectorToString(response).string());
192 ssize_t index = findSession(sessionId);
193 if (index == kNotFound) {
194 ALOGD("Invalid sessionId");
195 return BAD_VALUE;
196 }
197 if (response.size() == 0) {
198 return BAD_VALUE;
199 }
200
201 // Properties used in mock test, set by mock plugin and verifed cts test app
202 // byte[] response -> mock-response
203 mByteArrayProperties.add(String8("mock-response"), response);
204
205 const size_t kKeySetIdSize = 8;
206
207 for (size_t i = 0; i < kKeySetIdSize / sizeof(long); i++) {
208 long r = random();
209 keySetId.appendArray((uint8_t *)&r, sizeof(long));
210 }
211 mKeySets.add(keySetId);
212
213 return OK;
214 }
215
removeKeys(Vector<uint8_t> const & keySetId)216 status_t MockDrmPlugin::removeKeys(Vector<uint8_t> const &keySetId)
217 {
218 Mutex::Autolock lock(mLock);
219 ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)",
220 vectorToString(keySetId).string());
221
222 ssize_t index = findKeySet(keySetId);
223 if (index == kNotFound) {
224 ALOGD("Invalid keySetId");
225 return BAD_VALUE;
226 }
227 mKeySets.removeAt(index);
228
229 return OK;
230 }
231
restoreKeys(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keySetId)232 status_t MockDrmPlugin::restoreKeys(Vector<uint8_t> const &sessionId,
233 Vector<uint8_t> const &keySetId)
234 {
235 Mutex::Autolock lock(mLock);
236 ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)",
237 vectorToString(sessionId).string(),
238 vectorToString(keySetId).string());
239 ssize_t index = findSession(sessionId);
240 if (index == kNotFound) {
241 ALOGD("Invalid sessionId");
242 return BAD_VALUE;
243 }
244
245 index = findKeySet(keySetId);
246 if (index == kNotFound) {
247 ALOGD("Invalid keySetId");
248 return BAD_VALUE;
249 }
250
251 return OK;
252 }
253
queryKeyStatus(Vector<uint8_t> const & sessionId,KeyedVector<String8,String8> & infoMap) const254 status_t MockDrmPlugin::queryKeyStatus(Vector<uint8_t> const &sessionId,
255 KeyedVector<String8, String8> &infoMap) const
256 {
257 ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)",
258 vectorToString(sessionId).string());
259
260 ssize_t index = findSession(sessionId);
261 if (index == kNotFound) {
262 ALOGD("Invalid sessionId");
263 return BAD_VALUE;
264 }
265
266 infoMap.add(String8("purchaseDuration"), String8("1000"));
267 infoMap.add(String8("licenseDuration"), String8("100"));
268 return OK;
269 }
270
getProvisionRequest(String8 const &,String8 const &,Vector<uint8_t> & request,String8 & defaultUrl)271 status_t MockDrmPlugin::getProvisionRequest(String8 const & /* certType */,
272 String8 const & /* certAuthority */,
273 Vector<uint8_t> &request,
274 String8 &defaultUrl)
275 {
276 Mutex::Autolock lock(mLock);
277 ALOGD("MockDrmPlugin::getProvisionRequest()");
278
279 // Properties used in mock test, set by cts test app returned from mock plugin
280 // byte[] mock-request -> request
281 // string mock-default-url -> defaultUrl
282
283 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-request"));
284 if (index < 0) {
285 ALOGD("Missing 'mock-request' parameter for mock");
286 return BAD_VALUE;
287 } else {
288 request = mByteArrayProperties.valueAt(index);
289 }
290
291 index = mStringProperties.indexOfKey(String8("mock-defaultUrl"));
292 if (index < 0) {
293 ALOGD("Missing 'mock-defaultUrl' parameter for mock");
294 return BAD_VALUE;
295 } else {
296 defaultUrl = mStringProperties.valueAt(index);
297 }
298 return OK;
299 }
300
provideProvisionResponse(Vector<uint8_t> const & response,Vector<uint8_t> &,Vector<uint8_t> &)301 status_t MockDrmPlugin::provideProvisionResponse(Vector<uint8_t> const &response,
302 Vector<uint8_t> & /* certificate */,
303 Vector<uint8_t> & /* wrappedKey */)
304 {
305 Mutex::Autolock lock(mLock);
306 ALOGD("MockDrmPlugin::provideProvisionResponse(%s)",
307 vectorToString(response).string());
308
309 // Properties used in mock test, set by mock plugin and verifed cts test app
310 // byte[] response -> mock-response
311
312 mByteArrayProperties.add(String8("mock-response"), response);
313 return OK;
314 }
315
getSecureStop(Vector<uint8_t> const &,Vector<uint8_t> & secureStop)316 status_t MockDrmPlugin::getSecureStop(Vector<uint8_t> const & /* ssid */,
317 Vector<uint8_t> & secureStop)
318 {
319 Mutex::Autolock lock(mLock);
320 ALOGD("MockDrmPlugin::getSecureStop()");
321
322 // Properties used in mock test, set by cts test app returned from mock plugin
323 // byte[] mock-secure-stop -> first secure stop in list
324
325 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop"));
326 if (index < 0) {
327 ALOGD("Missing 'mock-secure-stop' parameter for mock");
328 return BAD_VALUE;
329 } else {
330 secureStop = mByteArrayProperties.valueAt(index);
331 }
332 return OK;
333 }
334
getSecureStops(List<Vector<uint8_t>> & secureStops)335 status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops)
336 {
337 Mutex::Autolock lock(mLock);
338 ALOGD("MockDrmPlugin::getSecureStops()");
339
340 // Properties used in mock test, set by cts test app returned from mock plugin
341 // byte[] mock-secure-stop1 -> first secure stop in list
342 // byte[] mock-secure-stop2 -> second secure stop in list
343
344 Vector<uint8_t> ss1, ss2;
345 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop1"));
346 if (index < 0) {
347 ALOGD("Missing 'mock-secure-stop1' parameter for mock");
348 return BAD_VALUE;
349 } else {
350 ss1 = mByteArrayProperties.valueAt(index);
351 }
352
353 index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop2"));
354 if (index < 0) {
355 ALOGD("Missing 'mock-secure-stop2' parameter for mock");
356 return BAD_VALUE;
357 } else {
358 ss2 = mByteArrayProperties.valueAt(index);
359 }
360
361 secureStops.push_back(ss1);
362 secureStops.push_back(ss2);
363 return OK;
364 }
365
releaseSecureStops(Vector<uint8_t> const & ssRelease)366 status_t MockDrmPlugin::releaseSecureStops(Vector<uint8_t> const &ssRelease)
367 {
368 Mutex::Autolock lock(mLock);
369 ALOGD("MockDrmPlugin::releaseSecureStops(%s)",
370 vectorToString(ssRelease).string());
371
372 // Properties used in mock test, set by mock plugin and verifed cts test app
373 // byte[] secure-stop-release -> mock-ssrelease
374 mByteArrayProperties.add(String8("mock-ssrelease"), ssRelease);
375
376 return OK;
377 }
378
releaseAllSecureStops()379 status_t MockDrmPlugin::releaseAllSecureStops()
380 {
381 Mutex::Autolock lock(mLock);
382 ALOGD("MockDrmPlugin::releaseAllSecureStops()");
383 return OK;
384 }
385
getPropertyString(String8 const & name,String8 & value) const386 status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const
387 {
388 ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string());
389 ssize_t index = mStringProperties.indexOfKey(name);
390 if (index < 0) {
391 ALOGD("no property for '%s'", name.string());
392 return BAD_VALUE;
393 }
394 value = mStringProperties.valueAt(index);
395 return OK;
396 }
397
getPropertyByteArray(String8 const & name,Vector<uint8_t> & value) const398 status_t MockDrmPlugin::getPropertyByteArray(String8 const &name,
399 Vector<uint8_t> &value) const
400 {
401 ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string());
402 ssize_t index = mByteArrayProperties.indexOfKey(name);
403 if (index < 0) {
404 ALOGD("no property for '%s'", name.string());
405 return BAD_VALUE;
406 }
407 value = mByteArrayProperties.valueAt(index);
408 return OK;
409 }
410
setPropertyString(String8 const & name,String8 const & value)411 status_t MockDrmPlugin::setPropertyString(String8 const &name,
412 String8 const &value)
413 {
414 Mutex::Autolock lock(mLock);
415 ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)",
416 name.string(), value.string());
417
418 if (name == "mock-send-event") {
419 unsigned code, extra;
420 sscanf(value.string(), "%d %d", &code, &extra);
421 DrmPlugin::EventType eventType = (DrmPlugin::EventType)code;
422
423 Vector<uint8_t> const *pSessionId = NULL;
424 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
425 if (index >= 0) {
426 pSessionId = &mByteArrayProperties[index];
427 }
428
429 Vector<uint8_t> const *pData = NULL;
430 index = mByteArrayProperties.indexOfKey(String8("mock-event-data"));
431 if (index >= 0) {
432 pData = &mByteArrayProperties[index];
433 }
434 ALOGD("sending event from mock drm plugin: %d %d %s %s",
435 (int)code, extra, pSessionId ? vectorToString(*pSessionId) : "{}",
436 pData ? vectorToString(*pData) : "{}");
437
438 sendEvent(eventType, extra, pSessionId, pData);
439 } else if (name == "mock-send-expiration-update") {
440 int64_t expiryTimeMS;
441 sscanf(value.string(), "%jd", &expiryTimeMS);
442
443 Vector<uint8_t> const *pSessionId = NULL;
444 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
445 if (index >= 0) {
446 pSessionId = &mByteArrayProperties[index];
447 }
448
449 ALOGD("sending expiration-update from mock drm plugin: %jd %s",
450 expiryTimeMS, pSessionId ? vectorToString(*pSessionId) : "{}");
451
452 sendExpirationUpdate(pSessionId, expiryTimeMS);
453 } else if (name == "mock-send-keys-change") {
454 Vector<uint8_t> const *pSessionId = NULL;
455 ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
456 if (index >= 0) {
457 pSessionId = &mByteArrayProperties[index];
458 }
459
460 ALOGD("sending keys-change from mock drm plugin: %s",
461 pSessionId ? vectorToString(*pSessionId) : "{}");
462
463 Vector<DrmPlugin::KeyStatus> keyStatusList;
464 DrmPlugin::KeyStatus keyStatus;
465 uint8_t keyId1[] = {'k', 'e', 'y', '1'};
466 keyStatus.mKeyId.clear();
467 keyStatus.mKeyId.appendArray(keyId1, sizeof(keyId1));
468 keyStatus.mType = DrmPlugin::kKeyStatusType_Usable;
469 keyStatusList.add(keyStatus);
470
471 uint8_t keyId2[] = {'k', 'e', 'y', '2'};
472 keyStatus.mKeyId.clear();
473 keyStatus.mKeyId.appendArray(keyId2, sizeof(keyId2));
474 keyStatus.mType = DrmPlugin::kKeyStatusType_Expired;
475 keyStatusList.add(keyStatus);
476
477 uint8_t keyId3[] = {'k', 'e', 'y', '3'};
478 keyStatus.mKeyId.clear();
479 keyStatus.mKeyId.appendArray(keyId3, sizeof(keyId3));
480 keyStatus.mType = DrmPlugin::kKeyStatusType_OutputNotAllowed;
481 keyStatusList.add(keyStatus);
482
483 uint8_t keyId4[] = {'k', 'e', 'y', '4'};
484 keyStatus.mKeyId.clear();
485 keyStatus.mKeyId.appendArray(keyId4, sizeof(keyId4));
486 keyStatus.mType = DrmPlugin::kKeyStatusType_StatusPending;
487 keyStatusList.add(keyStatus);
488
489 uint8_t keyId5[] = {'k', 'e', 'y', '5'};
490 keyStatus.mKeyId.clear();
491 keyStatus.mKeyId.appendArray(keyId5, sizeof(keyId5));
492 keyStatus.mType = DrmPlugin::kKeyStatusType_InternalError;
493 keyStatusList.add(keyStatus);
494
495 sendKeysChange(pSessionId, &keyStatusList, true);
496 } else {
497 mStringProperties.add(name, value);
498 }
499 return OK;
500 }
501
setPropertyByteArray(String8 const & name,Vector<uint8_t> const & value)502 status_t MockDrmPlugin::setPropertyByteArray(String8 const &name,
503 Vector<uint8_t> const &value)
504 {
505 Mutex::Autolock lock(mLock);
506 ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)",
507 name.string(), vectorToString(value).string());
508 mByteArrayProperties.add(name, value);
509 return OK;
510 }
511
setCipherAlgorithm(Vector<uint8_t> const & sessionId,String8 const & algorithm)512 status_t MockDrmPlugin::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
513 String8 const &algorithm)
514 {
515 Mutex::Autolock lock(mLock);
516
517 ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)",
518 vectorToString(sessionId).string(), algorithm.string());
519
520 ssize_t index = findSession(sessionId);
521 if (index == kNotFound) {
522 ALOGD("Invalid sessionId");
523 return BAD_VALUE;
524 }
525
526 if (algorithm == "AES/CBC/NoPadding") {
527 return OK;
528 }
529 return BAD_VALUE;
530 }
531
setMacAlgorithm(Vector<uint8_t> const & sessionId,String8 const & algorithm)532 status_t MockDrmPlugin::setMacAlgorithm(Vector<uint8_t> const &sessionId,
533 String8 const &algorithm)
534 {
535 Mutex::Autolock lock(mLock);
536
537 ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)",
538 vectorToString(sessionId).string(), algorithm.string());
539
540 ssize_t index = findSession(sessionId);
541 if (index == kNotFound) {
542 ALOGD("Invalid sessionId");
543 return BAD_VALUE;
544 }
545
546 if (algorithm == "HmacSHA256") {
547 return OK;
548 }
549 return BAD_VALUE;
550 }
551
encrypt(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & input,Vector<uint8_t> const & iv,Vector<uint8_t> & output)552 status_t MockDrmPlugin::encrypt(Vector<uint8_t> const &sessionId,
553 Vector<uint8_t> const &keyId,
554 Vector<uint8_t> const &input,
555 Vector<uint8_t> const &iv,
556 Vector<uint8_t> &output)
557 {
558 Mutex::Autolock lock(mLock);
559 ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
560 vectorToString(sessionId).string(),
561 vectorToString(keyId).string(),
562 vectorToString(input).string(),
563 vectorToString(iv).string());
564
565 ssize_t index = findSession(sessionId);
566 if (index == kNotFound) {
567 ALOGD("Invalid sessionId");
568 return BAD_VALUE;
569 }
570
571 // Properties used in mock test, set by mock plugin and verifed cts test app
572 // byte[] keyId -> mock-keyid
573 // byte[] input -> mock-input
574 // byte[] iv -> mock-iv
575 mByteArrayProperties.add(String8("mock-keyid"), keyId);
576 mByteArrayProperties.add(String8("mock-input"), input);
577 mByteArrayProperties.add(String8("mock-iv"), iv);
578
579 // Properties used in mock test, set by cts test app returned from mock plugin
580 // byte[] mock-output -> output
581 index = mByteArrayProperties.indexOfKey(String8("mock-output"));
582 if (index < 0) {
583 ALOGD("Missing 'mock-request' parameter for mock");
584 return BAD_VALUE;
585 } else {
586 output = mByteArrayProperties.valueAt(index);
587 }
588 return OK;
589 }
590
decrypt(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & input,Vector<uint8_t> const & iv,Vector<uint8_t> & output)591 status_t MockDrmPlugin::decrypt(Vector<uint8_t> const &sessionId,
592 Vector<uint8_t> const &keyId,
593 Vector<uint8_t> const &input,
594 Vector<uint8_t> const &iv,
595 Vector<uint8_t> &output)
596 {
597 Mutex::Autolock lock(mLock);
598 ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
599 vectorToString(sessionId).string(),
600 vectorToString(keyId).string(),
601 vectorToString(input).string(),
602 vectorToString(iv).string());
603
604 ssize_t index = findSession(sessionId);
605 if (index == kNotFound) {
606 ALOGD("Invalid sessionId");
607 return BAD_VALUE;
608 }
609
610 // Properties used in mock test, set by mock plugin and verifed cts test app
611 // byte[] keyId -> mock-keyid
612 // byte[] input -> mock-input
613 // byte[] iv -> mock-iv
614 mByteArrayProperties.add(String8("mock-keyid"), keyId);
615 mByteArrayProperties.add(String8("mock-input"), input);
616 mByteArrayProperties.add(String8("mock-iv"), iv);
617
618 // Properties used in mock test, set by cts test app returned from mock plugin
619 // byte[] mock-output -> output
620 index = mByteArrayProperties.indexOfKey(String8("mock-output"));
621 if (index < 0) {
622 ALOGD("Missing 'mock-request' parameter for mock");
623 return BAD_VALUE;
624 } else {
625 output = mByteArrayProperties.valueAt(index);
626 }
627 return OK;
628 }
629
sign(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & message,Vector<uint8_t> & signature)630 status_t MockDrmPlugin::sign(Vector<uint8_t> const &sessionId,
631 Vector<uint8_t> const &keyId,
632 Vector<uint8_t> const &message,
633 Vector<uint8_t> &signature)
634 {
635 Mutex::Autolock lock(mLock);
636 ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)",
637 vectorToString(sessionId).string(),
638 vectorToString(keyId).string(),
639 vectorToString(message).string());
640
641 ssize_t index = findSession(sessionId);
642 if (index == kNotFound) {
643 ALOGD("Invalid sessionId");
644 return BAD_VALUE;
645 }
646
647 // Properties used in mock test, set by mock plugin and verifed cts test app
648 // byte[] keyId -> mock-keyid
649 // byte[] message -> mock-message
650 mByteArrayProperties.add(String8("mock-keyid"), keyId);
651 mByteArrayProperties.add(String8("mock-message"), message);
652
653 // Properties used in mock test, set by cts test app returned from mock plugin
654 // byte[] mock-signature -> signature
655 index = mByteArrayProperties.indexOfKey(String8("mock-signature"));
656 if (index < 0) {
657 ALOGD("Missing 'mock-request' parameter for mock");
658 return BAD_VALUE;
659 } else {
660 signature = mByteArrayProperties.valueAt(index);
661 }
662 return OK;
663 }
664
verify(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & message,Vector<uint8_t> const & signature,bool & match)665 status_t MockDrmPlugin::verify(Vector<uint8_t> const &sessionId,
666 Vector<uint8_t> const &keyId,
667 Vector<uint8_t> const &message,
668 Vector<uint8_t> const &signature,
669 bool &match)
670 {
671 Mutex::Autolock lock(mLock);
672 ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)",
673 vectorToString(sessionId).string(),
674 vectorToString(keyId).string(),
675 vectorToString(message).string(),
676 vectorToString(signature).string());
677
678 ssize_t index = findSession(sessionId);
679 if (index == kNotFound) {
680 ALOGD("Invalid sessionId");
681 return BAD_VALUE;
682 }
683
684 // Properties used in mock test, set by mock plugin and verifed cts test app
685 // byte[] keyId -> mock-keyid
686 // byte[] message -> mock-message
687 // byte[] signature -> mock-signature
688 mByteArrayProperties.add(String8("mock-keyid"), keyId);
689 mByteArrayProperties.add(String8("mock-message"), message);
690 mByteArrayProperties.add(String8("mock-signature"), signature);
691
692 // Properties used in mock test, set by cts test app returned from mock plugin
693 // String mock-match "1" or "0" -> match
694 index = mStringProperties.indexOfKey(String8("mock-match"));
695 if (index < 0) {
696 ALOGD("Missing 'mock-request' parameter for mock");
697 return BAD_VALUE;
698 } else {
699 match = atol(mStringProperties.valueAt(index).string());
700 }
701 return OK;
702 }
703
signRSA(Vector<uint8_t> const & sessionId,String8 const & algorithm,Vector<uint8_t> const & message,Vector<uint8_t> const & wrappedKey,Vector<uint8_t> & signature)704 status_t MockDrmPlugin::signRSA(Vector<uint8_t> const &sessionId,
705 String8 const &algorithm,
706 Vector<uint8_t> const &message,
707 Vector<uint8_t> const &wrappedKey,
708 Vector<uint8_t> &signature)
709 {
710 Mutex::Autolock lock(mLock);
711 ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, "
712 "message=%s, signature=%s)",
713 vectorToString(sessionId).string(),
714 algorithm.string(),
715 vectorToString(message).string(),
716 vectorToString(wrappedKey).string(),
717 vectorToString(signature).string());
718
719 // Properties used in mock test, set by mock plugin and verifed cts test app
720 // byte[] wrappedKey -> mock-wrappedkey
721 // byte[] message -> mock-message
722 // byte[] signature -> mock-signature
723 mByteArrayProperties.add(String8("mock-sessionid"), sessionId);
724 mStringProperties.add(String8("mock-algorithm"), algorithm);
725 mByteArrayProperties.add(String8("mock-message"), message);
726 mByteArrayProperties.add(String8("mock-wrappedkey"), wrappedKey);
727 mByteArrayProperties.add(String8("mock-signature"), signature);
728 return OK;
729 }
730
findSession(Vector<uint8_t> const & sessionId) const731 ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const
732 {
733 ALOGD("findSession: nsessions=%zu, size=%zu", mSessions.size(), sessionId.size());
734 for (size_t i = 0; i < mSessions.size(); ++i) {
735 if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) {
736 return i;
737 }
738 }
739 return kNotFound;
740 }
741
findKeySet(Vector<uint8_t> const & keySetId) const742 ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const
743 {
744 ALOGD("findKeySet: nkeySets=%zu, size=%zu", mKeySets.size(), keySetId.size());
745 for (size_t i = 0; i < mKeySets.size(); ++i) {
746 if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) {
747 return i;
748 }
749 }
750 return kNotFound;
751 }
752
753
754 // Conversion utilities
vectorToString(Vector<uint8_t> const & vector) const755 String8 MockDrmPlugin::vectorToString(Vector<uint8_t> const &vector) const
756 {
757 return arrayToString(vector.array(), vector.size());
758 }
759
arrayToString(uint8_t const * array,size_t len) const760 String8 MockDrmPlugin::arrayToString(uint8_t const *array, size_t len) const
761 {
762 String8 result("{ ");
763 for (size_t i = 0; i < len; i++) {
764 result.appendFormat("0x%02x ", array[i]);
765 }
766 result += "}";
767 return result;
768 }
769
stringMapToString(const KeyedVector<String8,String8> & map) const770 String8 MockDrmPlugin::stringMapToString(const KeyedVector<String8, String8>& map) const
771 {
772 String8 result("{ ");
773 for (size_t i = 0; i < map.size(); i++) {
774 result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "",
775 map.keyAt(i).string(), map.valueAt(i).string());
776 }
777 return result + " }";
778 }
779
operator <(Vector<uint8_t> const & lhs,Vector<uint8_t> const & rhs)780 bool operator<(Vector<uint8_t> const &lhs, Vector<uint8_t> const &rhs) {
781 return lhs.size() < rhs.size() || (memcmp(lhs.array(), rhs.array(), lhs.size()) < 0);
782 }
783
784 //
785 // Crypto Plugin
786 //
787
requiresSecureDecoderComponent(const char * mime) const788 bool MockCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const
789 {
790 ALOGD("MockCryptoPlugin::requiresSecureDecoderComponent(mime=%s)", mime);
791 return false;
792 }
793
794 ssize_t
decrypt(bool secure,const uint8_t key[DECRYPT_KEY_SIZE],const uint8_t iv[DECRYPT_KEY_SIZE],Mode mode,const Pattern & pattern,const void * srcPtr,const SubSample * subSamples,size_t numSubSamples,void * dstPtr,AString *)795 MockCryptoPlugin::decrypt(bool secure, const uint8_t key[DECRYPT_KEY_SIZE],
796 const uint8_t iv[DECRYPT_KEY_SIZE], Mode mode,
797 const Pattern &pattern, const void *srcPtr,
798 const SubSample *subSamples, size_t numSubSamples,
799 void *dstPtr, AString * /* errorDetailMsg */)
800 {
801 ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, "
802 "pattern:{encryptBlocks=%d, skipBlocks=%d} src=%p, "
803 "subSamples=%s, dst=%p)",
804 (int)secure,
805 arrayToString(key, DECRYPT_KEY_SIZE).string(),
806 arrayToString(iv, DECRYPT_KEY_SIZE).string(),
807 (int)mode, pattern.mEncryptBlocks, pattern.mSkipBlocks, srcPtr,
808 subSamplesToString(subSamples, numSubSamples).string(),
809 dstPtr);
810 return OK;
811 }
812
813 // Conversion utilities
arrayToString(uint8_t const * array,size_t len) const814 String8 MockCryptoPlugin::arrayToString(uint8_t const *array, size_t len) const
815 {
816 String8 result("{ ");
817 for (size_t i = 0; i < len; i++) {
818 result.appendFormat("0x%02x ", array[i]);
819 }
820 result += "}";
821 return result;
822 }
823
subSamplesToString(SubSample const * subSamples,size_t numSubSamples) const824 String8 MockCryptoPlugin::subSamplesToString(SubSample const *subSamples,
825 size_t numSubSamples) const
826 {
827 String8 result;
828 for (size_t i = 0; i < numSubSamples; i++) {
829 result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i,
830 subSamples[i].mNumBytesOfClearData,
831 subSamples[i].mNumBytesOfEncryptedData);
832 }
833 return result;
834 }
835
836 };
837