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