• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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