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