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