• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 "ClearKeyCasPlugin"
19 
20 #include "ClearKeyFetcher.h"
21 #include "ecm.h"
22 #include "ClearKeyLicenseFetcher.h"
23 #include "ClearKeyCasPlugin.h"
24 #include "ClearKeySessionLibrary.h"
25 #include <media/stagefright/foundation/ABuffer.h>
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <media/stagefright/foundation/hexdump.h>
28 #include <media/stagefright/MediaErrors.h>
29 #include <utils/Log.h>
30 
createCasFactory()31 android::CasFactory* createCasFactory() {
32     return new android::clearkeycas::ClearKeyCasFactory();
33 }
34 
createDescramblerFactory()35 android::DescramblerFactory *createDescramblerFactory()
36 {
37     return new android::clearkeycas::ClearKeyDescramblerFactory();
38 }
39 
40 namespace android {
41 namespace clearkeycas {
42 
43 static const int32_t sClearKeySystemId = 0xF6D8;
44 
isSystemIdSupported(int32_t CA_system_id) const45 bool ClearKeyCasFactory::isSystemIdSupported(int32_t CA_system_id) const {
46     return CA_system_id == sClearKeySystemId;
47 }
48 
queryPlugins(std::vector<CasPluginDescriptor> * descriptors) const49 status_t ClearKeyCasFactory::queryPlugins(
50         std::vector<CasPluginDescriptor> *descriptors) const {
51     descriptors->clear();
52     descriptors->push_back({sClearKeySystemId, String8("Clear Key CAS")});
53     return OK;
54 }
55 
createPlugin(int32_t CA_system_id,uint64_t appData,CasPluginCallback callback,CasPlugin ** plugin)56 status_t ClearKeyCasFactory::createPlugin(
57         int32_t CA_system_id,
58         uint64_t appData,
59         CasPluginCallback callback,
60         CasPlugin **plugin) {
61     if (!isSystemIdSupported(CA_system_id)) {
62         return BAD_VALUE;
63     }
64 
65     *plugin = new ClearKeyCasPlugin(appData, callback);
66     return OK;
67 }
68 ///////////////////////////////////////////////////////////////////////////////
isSystemIdSupported(int32_t CA_system_id) const69 bool ClearKeyDescramblerFactory::isSystemIdSupported(
70         int32_t CA_system_id) const {
71     return CA_system_id == sClearKeySystemId;
72 }
73 
createPlugin(int32_t CA_system_id,DescramblerPlugin ** plugin)74 status_t ClearKeyDescramblerFactory::createPlugin(
75         int32_t CA_system_id, DescramblerPlugin** plugin) {
76     if (!isSystemIdSupported(CA_system_id)) {
77         return BAD_VALUE;
78     }
79 
80     *plugin = new ClearKeyDescramblerPlugin();
81     return OK;
82 }
83 
84 ///////////////////////////////////////////////////////////////////////////////
ClearKeyCasPlugin(uint64_t appData,CasPluginCallback callback)85 ClearKeyCasPlugin::ClearKeyCasPlugin(
86         uint64_t appData, CasPluginCallback callback)
87     : mCallback(callback), mAppData(appData) {
88     ALOGV("CTOR");
89 }
90 
~ClearKeyCasPlugin()91 ClearKeyCasPlugin::~ClearKeyCasPlugin() {
92     ALOGV("DTOR");
93     ClearKeySessionLibrary::get()->destroyPlugin(this);
94 }
95 
setPrivateData(const CasData &)96 status_t ClearKeyCasPlugin::setPrivateData(const CasData &/*data*/) {
97     ALOGV("setPrivateData");
98 
99     return OK;
100 }
101 
sessionIdToString(const std::vector<uint8_t> & array)102 static String8 sessionIdToString(const std::vector<uint8_t> &array) {
103     String8 result;
104     for (size_t i = 0; i < array.size(); i++) {
105         result.appendFormat("%02x ", array[i]);
106     }
107     if (result.isEmpty()) {
108         result.append("(null)");
109     }
110     return result;
111 }
112 
openSession(CasSessionId * sessionId)113 status_t ClearKeyCasPlugin::openSession(CasSessionId* sessionId) {
114     ALOGV("openSession");
115 
116     return ClearKeySessionLibrary::get()->addSession(this, sessionId);
117 }
118 
closeSession(const CasSessionId & sessionId)119 status_t ClearKeyCasPlugin::closeSession(const CasSessionId &sessionId) {
120     ALOGV("closeSession: sessionId=%s", sessionIdToString(sessionId).string());
121     std::shared_ptr<ClearKeyCasSession> session =
122             ClearKeySessionLibrary::get()->findSession(sessionId);
123     if (session.get() == nullptr) {
124         return ERROR_CAS_SESSION_NOT_OPENED;
125     }
126 
127     ClearKeySessionLibrary::get()->destroySession(sessionId);
128     return OK;
129 }
130 
setSessionPrivateData(const CasSessionId & sessionId,const CasData &)131 status_t ClearKeyCasPlugin::setSessionPrivateData(
132         const CasSessionId &sessionId, const CasData & /*data*/) {
133     ALOGV("setSessionPrivateData: sessionId=%s",
134             sessionIdToString(sessionId).string());
135     std::shared_ptr<ClearKeyCasSession> session =
136             ClearKeySessionLibrary::get()->findSession(sessionId);
137     if (session.get() == nullptr) {
138         return ERROR_CAS_SESSION_NOT_OPENED;
139     }
140     return OK;
141 }
142 
processEcm(const CasSessionId & sessionId,const CasEcm & ecm)143 status_t ClearKeyCasPlugin::processEcm(
144         const CasSessionId &sessionId, const CasEcm& ecm) {
145     ALOGV("processEcm: sessionId=%s", sessionIdToString(sessionId).string());
146     std::shared_ptr<ClearKeyCasSession> session =
147             ClearKeySessionLibrary::get()->findSession(sessionId);
148     if (session.get() == nullptr) {
149         return ERROR_CAS_SESSION_NOT_OPENED;
150     }
151 
152     Mutex::Autolock lock(mKeyFetcherLock);
153 
154     return session->updateECM(mKeyFetcher.get(), (void*)ecm.data(), ecm.size());
155 }
156 
processEmm(const CasEmm &)157 status_t ClearKeyCasPlugin::processEmm(const CasEmm& /*emm*/) {
158     ALOGV("processEmm");
159     Mutex::Autolock lock(mKeyFetcherLock);
160 
161     return OK;
162 }
163 
sendEvent(int32_t event,int32_t arg,const CasData & eventData)164 status_t ClearKeyCasPlugin::sendEvent(
165         int32_t event, int32_t arg, const CasData &eventData) {
166     ALOGV("sendEvent: event=%d, arg=%d", event, arg);
167     // Echo the received event to the callback.
168     // Clear key plugin doesn't use any event, echo'ing for testing only.
169     if (mCallback != NULL) {
170         mCallback((void*)mAppData, event, arg, (uint8_t*)eventData.data(), eventData.size());
171     }
172     return OK;
173 }
174 
provision(const String8 & str)175 status_t ClearKeyCasPlugin::provision(const String8 &str) {
176     ALOGV("provision: provisionString=%s", str.string());
177     Mutex::Autolock lock(mKeyFetcherLock);
178 
179     std::unique_ptr<ClearKeyLicenseFetcher> license_fetcher;
180     license_fetcher.reset(new ClearKeyLicenseFetcher());
181     status_t err = license_fetcher->Init(str.string());
182     if (err != OK) {
183         ALOGE("provision: failed to init ClearKeyLicenseFetcher (err=%d)", err);
184         return err;
185     }
186 
187     std::unique_ptr<ClearKeyFetcher> key_fetcher;
188     key_fetcher.reset(new ClearKeyFetcher(std::move(license_fetcher)));
189     err = key_fetcher->Init();
190     if (err != OK) {
191         ALOGE("provision: failed to init ClearKeyFetcher (err=%d)", err);
192         return err;
193     }
194 
195     ALOGV("provision: using ClearKeyFetcher");
196     mKeyFetcher = std::move(key_fetcher);
197 
198     return OK;
199 }
200 
refreshEntitlements(int32_t refreshType,const CasData &)201 status_t ClearKeyCasPlugin::refreshEntitlements(
202         int32_t refreshType, const CasData &/*refreshData*/) {
203     ALOGV("refreshEntitlements: refreshType=%d", refreshType);
204     Mutex::Autolock lock(mKeyFetcherLock);
205 
206     return OK;
207 }
208 
209 ///////////////////////////////////////////////////////////////////////
210 
211 // AES-128 CBC-CTS decrypt optimized for Transport Packets. |key| is the AES
212 // key (odd key or even key), |length| is the data size, and |buffer| is the
213 // ciphertext to be decrypted in place.
TpBlockCtsDecrypt(const AES_KEY & key,size_t length,char * buffer)214 status_t TpBlockCtsDecrypt(const AES_KEY& key, size_t length, char* buffer) {
215     CHECK(buffer);
216 
217     // Invariant: Packet must be at least 16 bytes.
218     CHECK(length >= AES_BLOCK_SIZE);
219 
220     // OpenSSL uses unsigned char.
221     unsigned char* data = reinterpret_cast<unsigned char*>(buffer);
222 
223     // Start with zero-filled initialization vector.
224     unsigned char iv[AES_BLOCK_SIZE];
225     memset(iv, 0, AES_BLOCK_SIZE);
226 
227     // Size of partial last block handled via CTS.
228     int cts_byte_count = length % AES_BLOCK_SIZE;
229 
230     // If there no is no partial last block, then process using normal CBC.
231     if (cts_byte_count == 0) {
232         AES_cbc_encrypt(data, data, length, &key, iv, 0);
233         return OK;
234     }
235 
236     // Cipher text stealing (CTS) - Schneier Figure 9.5 p 196.
237     // In CTS mode, the last two blocks have been swapped. Block[n-1] is really
238     // the original block[n] combined with the low-order bytes of the original
239     // block[n-1], while block[n] is the high-order bytes of the original
240     // block[n-1] padded with zeros.
241 
242     // Block[0] - block[n-2] are handled with normal CBC.
243     int cbc_byte_count = length - cts_byte_count - AES_BLOCK_SIZE;
244     if (cbc_byte_count > 0) {
245         AES_cbc_encrypt(data, data, cbc_byte_count, &key, iv, 0);
246         // |data| points to block[n-1].
247         data += cbc_byte_count;
248     }
249 
250     // Save block[n] to use as IV when decrypting block[n-1].
251     unsigned char block_n[AES_BLOCK_SIZE];
252     memset(block_n, 0, AES_BLOCK_SIZE);
253     memcpy(block_n, data + AES_BLOCK_SIZE, cts_byte_count);
254 
255     // Decrypt block[n-1] using block[n] as IV, consistent with the original
256     // block order.
257     AES_cbc_encrypt(data, data, AES_BLOCK_SIZE, &key, block_n, 0);
258 
259     // Return the stolen ciphertext: swap the high-order bytes of block[n]
260     // and block[n-1].
261     for (int i = 0; i < cts_byte_count; i++) {
262         unsigned char temp = *(data + i);
263         *(data + i) = *(data + AES_BLOCK_SIZE + i);
264         *(data + AES_BLOCK_SIZE + i) = temp;
265     }
266 
267     // Decrypt block[n-1] using previous IV.
268     AES_cbc_encrypt(data, data, AES_BLOCK_SIZE, &key, iv, 0);
269     return OK;
270 }
271 
272 // PES header and ECM stream header layout
273 //
274 // processECM() receives the data_byte portion from the transport packet.
275 // Below is the layout of the first 16 bytes of the ECM PES packet. Here
276 // we don't parse them, we skip them and go to the ECM container directly.
277 // The layout is included here only for reference.
278 //
279 // 0-2:   0x00 00 01 = start code prefix.
280 // 3:     0xf0 = stream type (90 = ECM).
281 // 4-5:   0x00 00 = PES length (filled in later, this is the length of the
282 //                  PES header (16) plus the length of the ECM container).
283 // 6-7:   0x00 00 = ECM major version.
284 // 8-9:   0x00 01 = ECM minor version.
285 // 10-11: 0x00 00 = Crypto period ID (filled in later).
286 // 12-13: 0x00 00 = ECM container length (filled in later, either 84 or
287 // 166).
288 // 14-15: 0x00 00 = offset = 0.
289 
290 const static size_t kEcmHeaderLength = 16;
291 const static size_t kUserKeyLength = 16;
292 
updateECM(KeyFetcher * keyFetcher,void * ecm,size_t size)293 status_t ClearKeyCasSession::updateECM(
294         KeyFetcher *keyFetcher, void *ecm, size_t size) {
295     if (keyFetcher == nullptr) {
296         return ERROR_CAS_NOT_PROVISIONED;
297     }
298 
299     if (size < kEcmHeaderLength) {
300         ALOGE("updateECM: invalid ecm size %zu", size);
301         return BAD_VALUE;
302     }
303 
304     Mutex::Autolock _lock(mKeyLock);
305 
306     if (mEcmBuffer != NULL && mEcmBuffer->capacity() == size
307             && !memcmp(mEcmBuffer->base(), ecm, size)) {
308         return OK;
309     }
310 
311     mEcmBuffer = ABuffer::CreateAsCopy(ecm, size);
312     mEcmBuffer->setRange(kEcmHeaderLength, size - kEcmHeaderLength);
313 
314     uint64_t asset_id;
315     std::vector<KeyFetcher::KeyInfo> keys;
316     status_t err = keyFetcher->ObtainKey(mEcmBuffer, &asset_id, &keys);
317     if (err != OK) {
318         ALOGE("updateECM: failed to obtain key (err=%d)", err);
319         return err;
320     }
321 
322     ALOGV("updateECM: %zu key(s) found", keys.size());
323     for (size_t keyIndex = 0; keyIndex < keys.size(); keyIndex++) {
324         String8 str;
325 
326         const sp<ABuffer>& keyBytes = keys[keyIndex].key_bytes;
327         CHECK(keyBytes->size() == kUserKeyLength);
328 
329         int result = AES_set_decrypt_key(
330                 reinterpret_cast<const uint8_t*>(keyBytes->data()),
331                 AES_BLOCK_SIZE * 8, &mKeyInfo[keyIndex].contentKey);
332         mKeyInfo[keyIndex].valid = (result == 0);
333         if (!mKeyInfo[keyIndex].valid) {
334             ALOGE("updateECM: failed to set key %zu, key_id=%d",
335                     keyIndex, keys[keyIndex].key_id);
336         }
337     }
338     return OK;
339 }
340 
341 // Decryption of a set of sub-samples
decrypt(bool secure,DescramblerPlugin::ScramblingControl scramblingControl,size_t numSubSamples,const DescramblerPlugin::SubSample * subSamples,const void * srcPtr,void * dstPtr,AString *)342 ssize_t ClearKeyCasSession::decrypt(
343         bool secure, DescramblerPlugin::ScramblingControl scramblingControl,
344         size_t numSubSamples, const DescramblerPlugin::SubSample *subSamples,
345         const void *srcPtr, void *dstPtr, AString * /* errorDetailMsg */) {
346     if (secure) {
347         return ERROR_CAS_CANNOT_HANDLE;
348     }
349 
350     AES_KEY contentKey;
351 
352     if (scramblingControl != DescramblerPlugin::kScrambling_Unscrambled) {
353         // Hold lock to get the key only to avoid contention for decryption
354         Mutex::Autolock _lock(mKeyLock);
355 
356         int32_t keyIndex = (scramblingControl & 1);
357         if (!mKeyInfo[keyIndex].valid) {
358             ALOGE("decrypt: key %d is invalid", keyIndex);
359             return ERROR_CAS_DECRYPT;
360         }
361         contentKey = mKeyInfo[keyIndex].contentKey;
362     }
363 
364     uint8_t *src = (uint8_t*)srcPtr;
365     uint8_t *dst = (uint8_t*)dstPtr;
366 
367     for (size_t i = 0; i < numSubSamples; i++) {
368         size_t numBytesinSubSample = subSamples[i].mNumBytesOfClearData
369                 + subSamples[i].mNumBytesOfEncryptedData;
370         if (src != dst) {
371             memcpy(dst, src, numBytesinSubSample);
372         }
373         status_t err = OK;
374         // Don't decrypt if len < AES_BLOCK_SIZE.
375         // The last chunk shorter than AES_BLOCK_SIZE is not encrypted.
376         if (scramblingControl != DescramblerPlugin::kScrambling_Unscrambled
377                 && subSamples[i].mNumBytesOfEncryptedData >= AES_BLOCK_SIZE) {
378             err = decryptPayload(
379                     contentKey,
380                     numBytesinSubSample,
381                     subSamples[i].mNumBytesOfClearData,
382                     (char *)dst);
383         }
384 
385         dst += numBytesinSubSample;
386         src += numBytesinSubSample;
387     }
388     return dst - (uint8_t *)dstPtr;
389 }
390 
391 // Decryption of a TS payload
decryptPayload(const AES_KEY & key,size_t length,size_t offset,char * buffer) const392 status_t ClearKeyCasSession::decryptPayload(
393         const AES_KEY& key, size_t length, size_t offset, char* buffer) const {
394     CHECK(buffer);
395 
396     // Invariant: only call decryptPayload with TS packets with at least 16
397     // bytes of payload (AES_BLOCK_SIZE).
398 
399     CHECK(length >= offset + AES_BLOCK_SIZE);
400 
401     return TpBlockCtsDecrypt(key, length - offset, buffer + offset);
402 }
403 
404 ///////////////////////////////////////////////////////////////////////////
405 #undef LOG_TAG
406 #define LOG_TAG "ClearKeyDescramblerPlugin"
407 
requiresSecureDecoderComponent(const char * mime) const408 bool ClearKeyDescramblerPlugin::requiresSecureDecoderComponent(
409         const char *mime) const {
410     ALOGV("requiresSecureDecoderComponent: mime=%s", mime);
411     return false;
412 }
413 
setMediaCasSession(const CasSessionId & sessionId)414 status_t ClearKeyDescramblerPlugin::setMediaCasSession(
415         const CasSessionId &sessionId) {
416     ALOGV("setMediaCasSession: sessionId=%s", sessionIdToString(sessionId).string());
417 
418     std::shared_ptr<ClearKeyCasSession> session =
419             ClearKeySessionLibrary::get()->findSession(sessionId);
420 
421     if (session.get() == nullptr) {
422         ALOGE("ClearKeyDescramblerPlugin: session not found");
423         return ERROR_CAS_SESSION_NOT_OPENED;
424     }
425 
426     std::atomic_store(&mCASSession, session);
427     return OK;
428 }
429 
descramble(bool secure,ScramblingControl scramblingControl,size_t numSubSamples,const SubSample * subSamples,const void * srcPtr,int32_t srcOffset,void * dstPtr,int32_t dstOffset,AString * errorDetailMsg)430 ssize_t ClearKeyDescramblerPlugin::descramble(
431         bool secure,
432         ScramblingControl scramblingControl,
433         size_t numSubSamples,
434         const SubSample *subSamples,
435         const void *srcPtr,
436         int32_t srcOffset,
437         void *dstPtr,
438         int32_t dstOffset,
439         AString *errorDetailMsg) {
440 
441     ALOGV("descramble: secure=%d, sctrl=%d, subSamples=%s, "
442             "srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d",
443           (int)secure, (int)scramblingControl,
444           subSamplesToString(subSamples, numSubSamples).string(),
445           srcPtr, dstPtr, srcOffset, dstOffset);
446 
447     std::shared_ptr<ClearKeyCasSession> session = std::atomic_load(&mCASSession);
448 
449     if (session.get() == nullptr) {
450         ALOGE("Uninitialized CAS session!");
451         return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED;
452     }
453 
454     return session->decrypt(
455             secure, scramblingControl,
456             numSubSamples, subSamples,
457             (uint8_t*)srcPtr + srcOffset,
458             dstPtr == NULL ? NULL : ((uint8_t*)dstPtr + dstOffset),
459             errorDetailMsg);
460 }
461 
462 // Conversion utilities
arrayToString(uint8_t const * array,size_t len) const463 String8 ClearKeyDescramblerPlugin::arrayToString(
464         uint8_t const *array, size_t len) const
465 {
466     String8 result("{ ");
467     for (size_t i = 0; i < len; i++) {
468         result.appendFormat("0x%02x ", array[i]);
469     }
470     result += "}";
471     return result;
472 }
473 
subSamplesToString(SubSample const * subSamples,size_t numSubSamples) const474 String8 ClearKeyDescramblerPlugin::subSamplesToString(
475         SubSample const *subSamples, size_t numSubSamples) const
476 {
477     String8 result;
478     for (size_t i = 0; i < numSubSamples; i++) {
479         result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i,
480                             subSamples[i].mNumBytesOfClearData,
481                             subSamples[i].mNumBytesOfEncryptedData);
482     }
483     return result;
484 }
485 
486 } // namespace clearkeycas
487 } // namespace android
488