2015-04-02 23:08:27 +03:00
|
|
|
/*
|
|
|
|
* Copyright 2015, Mozilla Foundation and contributors
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
2014-09-24 02:04:49 +04:00
|
|
|
|
2017-01-11 23:52:05 +03:00
|
|
|
#include <string.h>
|
|
|
|
#include <vector>
|
|
|
|
|
2017-01-14 00:23:31 +03:00
|
|
|
#include "ClearKeyDecryptionManager.h"
|
|
|
|
#include "psshparser/PsshParser.h"
|
|
|
|
#include "gmp-api/gmp-decryption.h"
|
|
|
|
#include <assert.h>
|
2014-09-24 02:04:49 +04:00
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
class ClearKeyDecryptor : public RefCounted
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
|
|
|
public:
|
2015-04-02 23:08:27 +03:00
|
|
|
ClearKeyDecryptor();
|
2014-09-24 02:04:49 +04:00
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
void InitKey(const Key& aKey);
|
|
|
|
bool HasKey() const { return !!mKey.size(); }
|
2014-09-24 02:04:49 +04:00
|
|
|
|
2017-01-14 00:23:31 +03:00
|
|
|
GMPErr Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
|
2015-12-01 08:13:58 +03:00
|
|
|
const CryptoMetaData& aMetadata);
|
2014-09-24 02:04:49 +04:00
|
|
|
|
2014-12-18 23:54:34 +03:00
|
|
|
const Key& DecryptionKey() const { return mKey; }
|
|
|
|
|
2014-09-24 02:04:49 +04:00
|
|
|
private:
|
2015-01-12 10:15:55 +03:00
|
|
|
~ClearKeyDecryptor();
|
2014-09-24 02:04:49 +04:00
|
|
|
|
|
|
|
Key mKey;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-01-14 00:23:31 +03:00
|
|
|
/* static */ ClearKeyDecryptionManager* ClearKeyDecryptionManager::sInstance = nullptr;
|
2014-09-24 02:04:49 +04:00
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
/* static */ ClearKeyDecryptionManager*
|
|
|
|
ClearKeyDecryptionManager::Get()
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2015-01-12 10:15:55 +03:00
|
|
|
if (!sInstance) {
|
|
|
|
sInstance = new ClearKeyDecryptionManager();
|
|
|
|
}
|
|
|
|
return sInstance;
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptionManager::ClearKeyDecryptionManager()
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2015-01-12 10:15:55 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptionManager::ClearKeyDecryptionManager");
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptionManager::~ClearKeyDecryptionManager()
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2015-01-12 10:15:55 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptionManager::~ClearKeyDecryptionManager");
|
2014-12-18 23:54:34 +03:00
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
sInstance = nullptr;
|
2014-12-18 23:54:34 +03:00
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
for (auto it = mDecryptors.begin(); it != mDecryptors.end(); it++) {
|
|
|
|
it->second->Release();
|
2014-12-18 23:54:34 +03:00
|
|
|
}
|
2015-01-12 10:15:55 +03:00
|
|
|
mDecryptors.clear();
|
2014-12-18 23:54:34 +03:00
|
|
|
}
|
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
bool
|
|
|
|
ClearKeyDecryptionManager::HasSeenKeyId(const KeyId& aKeyId) const
|
2014-12-18 23:54:34 +03:00
|
|
|
{
|
2017-01-14 00:23:31 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptionManager::SeenKeyId %s", mDecryptors.find(aKeyId) != mDecryptors.end() ? "t" : "f");
|
2015-01-12 10:15:55 +03:00
|
|
|
return mDecryptors.find(aKeyId) != mDecryptors.end();
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
bool
|
|
|
|
ClearKeyDecryptionManager::IsExpectingKeyForKeyId(const KeyId& aKeyId) const
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2017-01-14 00:23:31 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptionManager::IsExpectingKeyForId %08x...", *(uint32_t*)&aKeyId[0]);
|
2015-01-12 10:15:55 +03:00
|
|
|
const auto& decryptor = mDecryptors.find(aKeyId);
|
|
|
|
return decryptor != mDecryptors.end() && !decryptor->second->HasKey();
|
2014-12-18 23:54:34 +03:00
|
|
|
}
|
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
bool
|
|
|
|
ClearKeyDecryptionManager::HasKeyForKeyId(const KeyId& aKeyId) const
|
2014-12-18 23:54:34 +03:00
|
|
|
{
|
2015-01-12 10:15:55 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptionManager::HasKeyForKeyId");
|
|
|
|
const auto& decryptor = mDecryptors.find(aKeyId);
|
|
|
|
return decryptor != mDecryptors.end() && decryptor->second->HasKey();
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
const Key&
|
|
|
|
ClearKeyDecryptionManager::GetDecryptionKey(const KeyId& aKeyId)
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2015-04-02 23:08:27 +03:00
|
|
|
assert(HasKeyForKeyId(aKeyId));
|
2015-01-12 10:15:55 +03:00
|
|
|
return mDecryptors[aKeyId]->DecryptionKey();
|
2014-12-18 23:54:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptionManager::InitKey(KeyId aKeyId, Key aKey)
|
2014-12-18 23:54:34 +03:00
|
|
|
{
|
2017-01-14 00:23:31 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptionManager::InitKey %08x...", *(uint32_t*)&aKeyId[0]);
|
2015-01-12 10:15:55 +03:00
|
|
|
if (IsExpectingKeyForKeyId(aKeyId)) {
|
|
|
|
mDecryptors[aKeyId]->InitKey(aKey);
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptionManager::ExpectKeyId(KeyId aKeyId)
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2017-01-14 00:23:31 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptionManager::ExpectKeyId %08x...", *(uint32_t*)&aKeyId[0]);
|
2015-01-12 10:15:55 +03:00
|
|
|
if (!HasSeenKeyId(aKeyId)) {
|
|
|
|
mDecryptors[aKeyId] = new ClearKeyDecryptor();
|
2014-12-18 23:54:34 +03:00
|
|
|
}
|
2015-01-12 10:15:55 +03:00
|
|
|
mDecryptors[aKeyId]->AddRef();
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptionManager::ReleaseKeyId(KeyId aKeyId)
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2015-01-12 10:15:55 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptionManager::ReleaseKeyId");
|
2015-11-27 07:13:35 +03:00
|
|
|
assert(HasSeenKeyId(aKeyId));
|
2015-01-27 08:35:36 +03:00
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptor* decryptor = mDecryptors[aKeyId];
|
|
|
|
if (!decryptor->Release()) {
|
|
|
|
mDecryptors.erase(aKeyId);
|
|
|
|
}
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2017-01-14 00:23:31 +03:00
|
|
|
GMPErr
|
2015-12-01 08:13:58 +03:00
|
|
|
ClearKeyDecryptionManager::Decrypt(std::vector<uint8_t>& aBuffer,
|
|
|
|
const CryptoMetaData& aMetadata)
|
|
|
|
{
|
|
|
|
return Decrypt(&aBuffer[0], aBuffer.size(), aMetadata);
|
|
|
|
}
|
|
|
|
|
2017-01-14 00:23:31 +03:00
|
|
|
GMPErr
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptionManager::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
|
2015-12-01 08:13:58 +03:00
|
|
|
const CryptoMetaData& aMetadata)
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
|
|
|
CK_LOGD("ClearKeyDecryptionManager::Decrypt");
|
2015-12-01 08:13:58 +03:00
|
|
|
if (!HasKeyForKeyId(aMetadata.mKeyId)) {
|
2017-01-14 00:23:31 +03:00
|
|
|
return GMPNoKeyErr;
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2017-01-14 00:23:31 +03:00
|
|
|
return mDecryptors[aMetadata.mKeyId]->Decrypt(aBuffer, aBufferSize, aMetadata);
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptor::ClearKeyDecryptor()
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2015-01-12 10:15:55 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptor ctor");
|
|
|
|
}
|
2014-09-24 02:04:49 +04:00
|
|
|
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptor::~ClearKeyDecryptor()
|
|
|
|
{
|
2016-10-07 13:40:34 +03:00
|
|
|
if (HasKey()) {
|
2017-01-14 00:23:31 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptor dtor; key = %08x...", *(uint32_t*)&mKey[0]);
|
2016-10-07 13:40:34 +03:00
|
|
|
} else {
|
|
|
|
CK_LOGD("ClearKeyDecryptor dtor");
|
|
|
|
}
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptor::InitKey(const Key& aKey)
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2015-01-12 10:15:55 +03:00
|
|
|
mKey = aKey;
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2017-01-14 00:23:31 +03:00
|
|
|
GMPErr
|
2015-01-12 10:15:55 +03:00
|
|
|
ClearKeyDecryptor::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize,
|
2015-12-01 08:13:58 +03:00
|
|
|
const CryptoMetaData& aMetadata)
|
2014-09-24 02:04:49 +04:00
|
|
|
{
|
2015-01-12 10:15:55 +03:00
|
|
|
CK_LOGD("ClearKeyDecryptor::Decrypt");
|
2014-09-24 02:04:49 +04:00
|
|
|
// If the sample is split up into multiple encrypted subsamples, we need to
|
|
|
|
// stitch them into one continuous buffer for decryption.
|
2015-01-12 10:15:55 +03:00
|
|
|
std::vector<uint8_t> tmp(aBufferSize);
|
2014-09-24 02:04:49 +04:00
|
|
|
|
2015-12-01 08:13:58 +03:00
|
|
|
if (aMetadata.NumSubsamples()) {
|
2014-09-24 02:04:49 +04:00
|
|
|
// Take all encrypted parts of subsamples and stitch them into one
|
|
|
|
// continuous encrypted buffer.
|
2015-12-01 08:13:58 +03:00
|
|
|
uint8_t* data = aBuffer;
|
|
|
|
uint8_t* iter = &tmp[0];
|
|
|
|
for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) {
|
|
|
|
data += aMetadata.mClearBytes[i];
|
|
|
|
uint32_t cipherBytes = aMetadata.mCipherBytes[i];
|
2016-05-26 20:46:40 +03:00
|
|
|
if (data + cipherBytes > aBuffer + aBufferSize) {
|
|
|
|
// Trying to read past the end of the buffer!
|
2017-01-14 00:23:31 +03:00
|
|
|
return GMPCryptoErr;
|
2016-05-26 20:46:40 +03:00
|
|
|
}
|
2014-09-24 02:04:49 +04:00
|
|
|
|
|
|
|
memcpy(iter, data, cipherBytes);
|
|
|
|
|
|
|
|
data += cipherBytes;
|
|
|
|
iter += cipherBytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp.resize((size_t)(iter - &tmp[0]));
|
|
|
|
} else {
|
2015-01-12 10:15:55 +03:00
|
|
|
memcpy(&tmp[0], aBuffer, aBufferSize);
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2015-12-01 08:13:58 +03:00
|
|
|
assert(aMetadata.mIV.size() == 8 || aMetadata.mIV.size() == 16);
|
|
|
|
std::vector<uint8_t> iv(aMetadata.mIV);
|
2016-10-07 01:14:04 +03:00
|
|
|
iv.insert(iv.end(), CENC_KEY_LEN - aMetadata.mIV.size(), 0);
|
2014-09-24 02:04:49 +04:00
|
|
|
|
|
|
|
ClearKeyUtils::DecryptAES(mKey, tmp, iv);
|
|
|
|
|
2015-12-01 08:13:58 +03:00
|
|
|
if (aMetadata.NumSubsamples()) {
|
2014-09-24 02:04:49 +04:00
|
|
|
// Take the decrypted buffer, split up into subsamples, and insert those
|
|
|
|
// subsamples back into their original position in the original buffer.
|
2015-12-01 08:13:58 +03:00
|
|
|
uint8_t* data = aBuffer;
|
|
|
|
uint8_t* iter = &tmp[0];
|
|
|
|
for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) {
|
|
|
|
data += aMetadata.mClearBytes[i];
|
|
|
|
uint32_t cipherBytes = aMetadata.mCipherBytes[i];
|
2014-09-24 02:04:49 +04:00
|
|
|
|
|
|
|
memcpy(data, iter, cipherBytes);
|
|
|
|
|
|
|
|
data += cipherBytes;
|
|
|
|
iter += cipherBytes;
|
|
|
|
}
|
|
|
|
} else {
|
2015-01-12 10:15:55 +03:00
|
|
|
memcpy(aBuffer, &tmp[0], aBufferSize);
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|
|
|
|
|
2017-01-14 00:23:31 +03:00
|
|
|
return GMPNoErr;
|
2014-09-24 02:04:49 +04:00
|
|
|
}
|