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