13a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania/* 23a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * Copyright (C) 2017 The Android Open Source Project 33a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * 43a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * Licensed under the Apache License, Version 2.0 (the "License"); 53a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * you may not use this file except in compliance with the License. 63a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * You may obtain a copy of the License at 73a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * 83a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * http://www.apache.org/licenses/LICENSE-2.0 93a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * 103a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * Unless required by applicable law or agreed to in writing, software 113a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * distributed under the License is distributed on an "AS IS" BASIS, 123a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * See the License for the specific language governing permissions and 143a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania * limitations under the License. 153a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania */ 163a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 173a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania//#define LOG_NDEBUG 0 183a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania#define LOG_TAG "HlsSampleDecryptor" 193a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 203a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania#include "HlsSampleDecryptor.h" 213a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 223a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania#include <media/stagefright/foundation/ABuffer.h> 233a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania#include <media/stagefright/foundation/ADebug.h> 243a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania#include <media/stagefright/Utils.h> 253a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 263a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 273a37f3e948b600405e0c70b8a241778fda44168eHassan Shojanianamespace android { 283a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 293a37f3e948b600405e0c70b8a241778fda44168eHassan ShojaniaHlsSampleDecryptor::HlsSampleDecryptor() 303a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania : mValidKeyInfo(false) { 313a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 323a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 333a37f3e948b600405e0c70b8a241778fda44168eHassan ShojaniaHlsSampleDecryptor::HlsSampleDecryptor(const sp<AMessage> &sampleAesKeyItem) 343a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania : mValidKeyInfo(false) { 353a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 363a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania signalNewSampleAesKey(sampleAesKeyItem); 373a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 383a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 393a37f3e948b600405e0c70b8a241778fda44168eHassan Shojaniavoid HlsSampleDecryptor::signalNewSampleAesKey(const sp<AMessage> &sampleAesKeyItem) { 403a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 413a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (sampleAesKeyItem == NULL) { 423a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mValidKeyInfo = false; 433a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGW("signalNewSampleAesKey: sampleAesKeyItem is NULL"); 443a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return; 453a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 463a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 473a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania sp<ABuffer> keyDataBuffer, initVecBuffer; 483a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania sampleAesKeyItem->findBuffer("keyData", &keyDataBuffer); 493a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania sampleAesKeyItem->findBuffer("initVec", &initVecBuffer); 503a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 513a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (keyDataBuffer != NULL && keyDataBuffer->size() == AES_BLOCK_SIZE && 523a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania initVecBuffer != NULL && initVecBuffer->size() == AES_BLOCK_SIZE) { 533a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 543a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("signalNewSampleAesKey: Key: %s IV: %s", 553a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania aesBlockToStr(keyDataBuffer->data()).c_str(), 563a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania aesBlockToStr(initVecBuffer->data()).c_str()); 573a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 583a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania uint8_t KeyData[AES_BLOCK_SIZE]; 593a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memcpy(KeyData, keyDataBuffer->data(), AES_BLOCK_SIZE); 603a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memcpy(mAESInitVec, initVecBuffer->data(), AES_BLOCK_SIZE); 613a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 623a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mValidKeyInfo = (AES_set_decrypt_key(KeyData, 8*AES_BLOCK_SIZE/*128*/, &mAesKey) == 0); 633a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (!mValidKeyInfo) { 643a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGE("signalNewSampleAesKey: failed to set AES decryption key."); 653a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 663a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 673a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } else { 683a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // Media scanner might try extract/parse the TS files without knowing the key. 693a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // Otherwise, shouldn't get here (unless an invalid playlist has swaped SAMPLE-AES with 703a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // NONE method while still sample-encrypted stream is parsed). 713a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 723a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania mValidKeyInfo = false; 733a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGE("signalNewSampleAesKey Can't decrypt; keyDataBuffer: %p(%zu) initVecBuffer: %p(%zu)", 743a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania keyDataBuffer.get(), (keyDataBuffer.get() == NULL)? -1 : keyDataBuffer->size(), 753a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania initVecBuffer.get(), (initVecBuffer.get() == NULL)? -1 : initVecBuffer->size()); 763a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 773a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 783a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 793a37f3e948b600405e0c70b8a241778fda44168eHassan Shojaniasize_t HlsSampleDecryptor::processNal(uint8_t *nalData, size_t nalSize) { 803a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 813a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania unsigned nalType = nalData[0] & 0x1f; 823a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (!mValidKeyInfo) { 833a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processNal[%d]: (%p)/%zu Skipping due to invalid key", nalType, nalData, nalSize); 843a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return nalSize; 853a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 863a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 873a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania bool isEncrypted = (nalSize > VIDEO_CLEAR_LEAD + AES_BLOCK_SIZE); 883a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processNal[%d]: (%p)/%zu isEncrypted: %d", nalType, nalData, nalSize, isEncrypted); 893a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 903a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (isEncrypted) { 913a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // Encrypted NALUs have extra start code emulation prevention that must be 923a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // stripped out before we can decrypt it. 933a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t newSize = unescapeStream(nalData, nalSize); 943a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 953a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processNal:unescapeStream[%d]: %zu -> %zu", nalType, nalSize, newSize); 963a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania nalSize = newSize; 973a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 983a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania //Encrypted_nal_unit () { 993a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // nal_unit_type_byte // 1 byte 1003a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_leader // 31 bytes 1013a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // while (bytes_remaining() > 0) { 1023a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // if (bytes_remaining() > 16) { 1033a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // encrypted_block // 16 bytes 1043a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // } 1053a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_block // MIN(144, bytes_remaining()) bytes 1063a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // } 1073a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania //} 1083a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1093a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t offset = VIDEO_CLEAR_LEAD; 1103a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t remainingBytes = nalSize - VIDEO_CLEAR_LEAD; 1113a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1123a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // a copy of initVec as decryptBlock updates it 1133a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania unsigned char AESInitVec[AES_BLOCK_SIZE]; 1143a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memcpy(AESInitVec, mAESInitVec, AES_BLOCK_SIZE); 1153a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1163a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania while (remainingBytes > 0) { 1173a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // encrypted_block: protected block uses 10% skip encryption 1183a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (remainingBytes > AES_BLOCK_SIZE) { 1193a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania uint8_t *encrypted = nalData + offset; 1203a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania status_t ret = decryptBlock(encrypted, AES_BLOCK_SIZE, AESInitVec); 1213a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (ret != OK) { 1223a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGE("processNal failed with %d", ret); 1233a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return nalSize; // revisit this 1243a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 1253a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1263a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania offset += AES_BLOCK_SIZE; 1273a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania remainingBytes -= AES_BLOCK_SIZE; 1283a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 1293a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1303a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_block 1313a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t clearBytes = std::min(remainingBytes, (size_t)(9 * AES_BLOCK_SIZE)); 1323a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1333a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania offset += clearBytes; 1343a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania remainingBytes -= clearBytes; 1353a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } // while 1363a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1373a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } else { // isEncrypted == false 1383a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processNal[%d]: Unencrypted NALU (%p)/%zu", nalType, nalData, nalSize); 1393a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 1403a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1413a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return nalSize; 1423a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 1433a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1443a37f3e948b600405e0c70b8a241778fda44168eHassan Shojaniavoid HlsSampleDecryptor::processAAC(size_t adtsHdrSize, uint8_t *data, size_t size) { 1453a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1463a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (!mValidKeyInfo) { 1473a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processAAC: (%p)/%zu Skipping due to invalid key", data, size); 1483a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return; 1493a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 1503a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1513a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // ADTS header is included in the size 1523a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t offset = adtsHdrSize; 1533a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t remainingBytes = size - adtsHdrSize; 1543a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1553a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania bool isEncrypted = (remainingBytes >= AUDIO_CLEAR_LEAD + AES_BLOCK_SIZE); 1563a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processAAC: header: %zu data: %p(%zu) isEncrypted: %d", 1573a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania adtsHdrSize, data, size, isEncrypted); 1583a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1593a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania //Encrypted_AAC_Frame () { 1603a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // ADTS_Header // 7 or 9 bytes 1613a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_leader // 16 bytes 1623a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // while (bytes_remaining() >= 16) { 1633a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // encrypted_block // 16 bytes 1643a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // } 1653a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_trailer // 0-15 bytes 1663a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania //} 1673a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1683a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // with lead bytes 1693a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (remainingBytes >= AUDIO_CLEAR_LEAD) { 1703a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania offset += AUDIO_CLEAR_LEAD; 1713a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania remainingBytes -= AUDIO_CLEAR_LEAD; 1723a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1733a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // encrypted_block 1743a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (remainingBytes >= AES_BLOCK_SIZE) { 1753a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1763a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t encryptedBytes = (remainingBytes / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; 1773a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania unsigned char AESInitVec[AES_BLOCK_SIZE]; 1783a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memcpy(AESInitVec, mAESInitVec, AES_BLOCK_SIZE); 1793a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1803a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // decrypting all blocks at once 1813a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania uint8_t *encrypted = data + offset; 1823a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania status_t ret = decryptBlock(encrypted, encryptedBytes, AESInitVec); 1833a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (ret != OK) { 1843a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGE("processAAC: decryptBlock failed with %d", ret); 1853a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return; 1863a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 1873a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1883a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania offset += encryptedBytes; 1893a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania remainingBytes -= encryptedBytes; 1903a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } // encrypted 1913a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1923a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_trailer 1933a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t clearBytes = remainingBytes; 1943a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (clearBytes > 0) { 1953a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania CHECK(clearBytes < AES_BLOCK_SIZE); 1963a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 1973a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 1983a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } else { // without lead bytes 1993a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processAAC: Unencrypted frame (without lead bytes) size %zu = %zu (hdr) + %zu (rem)", 2003a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size, adtsHdrSize, remainingBytes); 2013a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2023a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2033a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 2043a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2053a37f3e948b600405e0c70b8a241778fda44168eHassan Shojaniavoid HlsSampleDecryptor::processAC3(uint8_t *data, size_t size) { 2063a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2073a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (!mValidKeyInfo) { 2083a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processAC3: (%p)/%zu Skipping due to invalid key", data, size); 2093a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return; 2103a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2113a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2123a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania bool isEncrypted = (size >= AUDIO_CLEAR_LEAD + AES_BLOCK_SIZE); 2133a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processAC3 %p(%zu) isEncrypted: %d", data, size, isEncrypted); 2143a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2153a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania //Encrypted_AC3_Frame () { 2163a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_leader // 16 bytes 2173a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // while (bytes_remaining() >= 16) { 2183a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // encrypted_block // 16 bytes 2193a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // } 2203a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_trailer // 0-15 bytes 2213a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania //} 2223a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2233a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (size >= AUDIO_CLEAR_LEAD) { 2243a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_leader 2253a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t offset = AUDIO_CLEAR_LEAD; 2263a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t remainingBytes = size - AUDIO_CLEAR_LEAD; 2273a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2283a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (remainingBytes >= AES_BLOCK_SIZE) { 2293a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2303a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t encryptedBytes = (remainingBytes / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; 2313a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2323a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // encrypted_block 2333a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania unsigned char AESInitVec[AES_BLOCK_SIZE]; 2343a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memcpy(AESInitVec, mAESInitVec, AES_BLOCK_SIZE); 2353a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2363a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // decrypting all blocks at once 2373a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania uint8_t *encrypted = data + offset; 2383a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania status_t ret = decryptBlock(encrypted, encryptedBytes, AESInitVec); 2393a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (ret != OK) { 2403a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGE("processAC3: decryptBlock failed with %d", ret); 2413a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return; 2423a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2433a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2443a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania offset += encryptedBytes; 2453a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania remainingBytes -= encryptedBytes; 2463a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } // encrypted 2473a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2483a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania // unencrypted_trailer 2493a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t clearBytes = remainingBytes; 2503a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (clearBytes > 0) { 2513a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania CHECK(clearBytes < AES_BLOCK_SIZE); 2523a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2533a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2543a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } else { 2553a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("processAC3: Unencrypted frame (without lead bytes) size %zu", size); 2563a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2573a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 2583a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2593a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania// Unescapes data replacing occurrences of [0, 0, 3] with [0, 0] and returns the new size 2603a37f3e948b600405e0c70b8a241778fda44168eHassan Shojaniasize_t HlsSampleDecryptor::unescapeStream(uint8_t *data, size_t limit) const { 2613a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania Vector<size_t> scratchEscapePositions; 2623a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t position = 0; 2633a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2643a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania while (position < limit) { 2653a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania position = findNextUnescapeIndex(data, position, limit); 2663a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (position < limit) { 2673a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania scratchEscapePositions.add(position); 2683a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania position += 3; 2693a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2703a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2713a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2723a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t scratchEscapeCount = scratchEscapePositions.size(); 2733a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t escapedPosition = 0; // The position being read from. 2743a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t unescapedPosition = 0; // The position being written to. 2753a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania for (size_t i = 0; i < scratchEscapeCount; i++) { 2763a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t nextEscapePosition = scratchEscapePositions[i]; 2773a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania //TODO: add 2 and get rid of the later = 0 assignments 2783a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t copyLength = nextEscapePosition - escapedPosition; 2793a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memmove(data+unescapedPosition, data+escapedPosition, copyLength); 2803a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania unescapedPosition += copyLength; 2813a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania data[unescapedPosition++] = 0; 2823a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania data[unescapedPosition++] = 0; 2833a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania escapedPosition += copyLength + 3; 2843a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2853a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2863a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t unescapedLength = limit - scratchEscapeCount; 2873a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania size_t remainingLength = unescapedLength - unescapedPosition; 2883a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania memmove(data+unescapedPosition, data+escapedPosition, remainingLength); 2893a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2903a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return unescapedLength; 2913a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 2923a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 2933a37f3e948b600405e0c70b8a241778fda44168eHassan Shojaniasize_t HlsSampleDecryptor::findNextUnescapeIndex(uint8_t *data, size_t offset, size_t limit) const { 2943a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania for (size_t i = offset; i < limit - 2; i++) { 2953a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania //TODO: speed 2963a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x03) { 2973a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return i; 2983a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 2993a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 3003a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return limit; 3013a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 3023a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3033a37f3e948b600405e0c70b8a241778fda44168eHassan Shojaniastatus_t HlsSampleDecryptor::decryptBlock(uint8_t *buffer, size_t size, 3043a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania uint8_t AESInitVec[AES_BLOCK_SIZE]) { 3053a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (size == 0) { 3063a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return OK; 3073a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 3083a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3093a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if ((size % AES_BLOCK_SIZE) != 0) { 3103a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGE("decryptBlock: size (%zu) not a multiple of block size", size); 3113a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return ERROR_MALFORMED; 3123a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 3133a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3143a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania ALOGV("decryptBlock: %p (%zu)", buffer, size); 3153a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3163a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania AES_cbc_encrypt(buffer, buffer, size, &mAesKey, AESInitVec, AES_DECRYPT); 3173a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3183a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return OK; 3193a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 3203a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3213a37f3e948b600405e0c70b8a241778fda44168eHassan ShojaniaAString HlsSampleDecryptor::aesBlockToStr(uint8_t block[AES_BLOCK_SIZE]) { 3223a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania AString result; 3233a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3243a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania if (block == NULL) { 3253a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania result = AString("null"); 3263a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } else { 3273a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania result = AStringPrintf("0x%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 3283a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania block[0], block[1], block[2], block[3], block[4], block[5], block[6], block[7], 3293a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania block[8], block[9], block[10], block[11], block[12], block[13], block[14], block[15]); 3303a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania } 3313a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3323a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania return result; 3333a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} 3343a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3353a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania 3363a37f3e948b600405e0c70b8a241778fda44168eHassan Shojania} // namespace android 337