ClearKeyCasPlugin.cpp revision a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bb
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
31android::CasFactory* createCasFactory() {
32    return new android::clearkeycas::ClearKeyCasFactory();
33}
34
35android::DescramblerFactory *createDescramblerFactory()
36{
37    return new android::clearkeycas::ClearKeyDescramblerFactory();
38}
39
40namespace android {
41namespace clearkeycas {
42
43static const int32_t sClearKeySystemId = 0xF6D8;
44
45bool ClearKeyCasFactory::isSystemIdSupported(int32_t CA_system_id) const {
46    return CA_system_id == sClearKeySystemId;
47}
48
49status_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
56status_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///////////////////////////////////////////////////////////////////////////////
69bool ClearKeyDescramblerFactory::isSystemIdSupported(
70        int32_t CA_system_id) const {
71    return CA_system_id == sClearKeySystemId;
72}
73
74status_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///////////////////////////////////////////////////////////////////////////////
85ClearKeyCasPlugin::ClearKeyCasPlugin(
86        uint64_t appData, CasPluginCallback callback)
87    : mCallback(callback), mAppData(appData) {
88    ALOGV("CTOR");
89}
90
91ClearKeyCasPlugin::~ClearKeyCasPlugin() {
92    ALOGV("DTOR");
93    ClearKeySessionLibrary::get()->destroyPlugin(this);
94}
95
96status_t ClearKeyCasPlugin::setPrivateData(const CasData &/*data*/) {
97    ALOGV("setPrivateData");
98
99    return OK;
100}
101
102static 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
113status_t ClearKeyCasPlugin::openSession(CasSessionId* sessionId) {
114    ALOGV("openSession");
115
116    return ClearKeySessionLibrary::get()->addSession(this, sessionId);
117}
118
119status_t ClearKeyCasPlugin::closeSession(const CasSessionId &sessionId) {
120    ALOGV("closeSession: sessionId=%s", sessionIdToString(sessionId).string());
121    sp<ClearKeyCasSession> session =
122            ClearKeySessionLibrary::get()->findSession(sessionId);
123    if (session == NULL) {
124        return ERROR_DRM_SESSION_NOT_OPENED;
125    }
126
127    ClearKeySessionLibrary::get()->destroySession(sessionId);
128    return OK;
129}
130
131status_t ClearKeyCasPlugin::setSessionPrivateData(
132        const CasSessionId &sessionId, const CasData & /*data*/) {
133    ALOGV("setSessionPrivateData: sessionId=%s",
134            sessionIdToString(sessionId).string());
135    sp<ClearKeyCasSession> session =
136            ClearKeySessionLibrary::get()->findSession(sessionId);
137    if (session == NULL) {
138        return ERROR_DRM_SESSION_NOT_OPENED;
139    }
140    return OK;
141}
142
143status_t ClearKeyCasPlugin::processEcm(
144        const CasSessionId &sessionId, const CasEcm& ecm) {
145    ALOGV("processEcm: sessionId=%s", sessionIdToString(sessionId).string());
146    sp<ClearKeyCasSession> session =
147            ClearKeySessionLibrary::get()->findSession(sessionId);
148    if (session == NULL) {
149        return ERROR_DRM_SESSION_NOT_OPENED;
150    }
151
152    Mutex::Autolock lock(mKeyFetcherLock);
153
154    return session->updateECM(mKeyFetcher.get(), (void*)ecm.data(), ecm.size());
155}
156
157status_t ClearKeyCasPlugin::processEmm(const CasEmm& /*emm*/) {
158    ALOGV("processEmm");
159    Mutex::Autolock lock(mKeyFetcherLock);
160
161    return OK;
162}
163
164status_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
175status_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
201status_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.
214status_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
290const static size_t kEcmHeaderLength = 16;
291const static size_t kUserKeyLength = 16;
292
293status_t ClearKeyCasSession::updateECM(
294        KeyFetcher *keyFetcher, void *ecm, size_t size) {
295    if (keyFetcher == nullptr) {
296        return ERROR_DRM_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
342ssize_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_DRM_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_DRM_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
392status_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
408bool ClearKeyDescramblerPlugin::requiresSecureDecoderComponent(
409        const char *mime) const {
410    ALOGV("requiresSecureDecoderComponent: mime=%s", mime);
411    return false;
412}
413
414status_t ClearKeyDescramblerPlugin::setMediaCasSession(
415        const CasSessionId &sessionId) {
416    ALOGV("setMediaCasSession: sessionId=%s", sessionIdToString(sessionId).string());
417
418    sp<ClearKeyCasSession> session =
419            ClearKeySessionLibrary::get()->findSession(sessionId);
420
421    if (session == NULL) {
422        ALOGE("ClearKeyDescramblerPlugin: session not found");
423        return ERROR_DRM_SESSION_NOT_OPENED;
424    }
425
426    mCASSession = session;
427    return OK;
428}
429
430ssize_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    if (mCASSession == NULL) {
448        ALOGE("Uninitialized CAS session!");
449        return ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED;
450    }
451
452    return mCASSession->decrypt(
453            secure, scramblingControl,
454            numSubSamples, subSamples,
455            (uint8_t*)srcPtr + srcOffset,
456            dstPtr == NULL ? NULL : ((uint8_t*)dstPtr + dstOffset),
457            errorDetailMsg);
458}
459
460// Conversion utilities
461String8 ClearKeyDescramblerPlugin::arrayToString(
462        uint8_t const *array, size_t len) const
463{
464    String8 result("{ ");
465    for (size_t i = 0; i < len; i++) {
466        result.appendFormat("0x%02x ", array[i]);
467    }
468    result += "}";
469    return result;
470}
471
472String8 ClearKeyDescramblerPlugin::subSamplesToString(
473        SubSample const *subSamples, size_t numSubSamples) const
474{
475    String8 result;
476    for (size_t i = 0; i < numSubSamples; i++) {
477        result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i,
478                            subSamples[i].mNumBytesOfClearData,
479                            subSamples[i].mNumBytesOfEncryptedData);
480    }
481    return result;
482}
483
484} // namespace clearkeycas
485} // namespace android
486