• 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 "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