Initial import of Widevine Common Encryption DRM engine
Builds libwvmdrmengine.so, which is loaded by the new MediaDrm APIs to support playback of Widevine/CENC protected content. Change-Id: I6f57dd37083dfd96c402cb9dd137c7d74edc8f1c
This commit is contained in:
106
libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp
Normal file
106
libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||
//
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "WVCdm"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "WVCryptoPlugin.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "utils/Errors.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace wvdrm {
|
||||
|
||||
using namespace android;
|
||||
using namespace std;
|
||||
using namespace wvcdm;
|
||||
|
||||
WVCryptoPlugin::WVCryptoPlugin(const void* data, size_t size,
|
||||
WvContentDecryptionModule* cdm)
|
||||
: mCDM(cdm),
|
||||
mSessionId(static_cast<const char*>(data), size) {}
|
||||
|
||||
bool WVCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const {
|
||||
// TODO: Determine if we are using L1 or L3 and return an appropriate value.
|
||||
// For Demo 2, we are always L3.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns negative values for error code and
|
||||
// positive values for the size of decrypted data. In theory, the output size
|
||||
// can be larger than the input size, but in practice this should never happen
|
||||
// for AES-CTR.
|
||||
ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
||||
const uint8_t iv[KEY_IV_SIZE], Mode mode,
|
||||
const void* srcPtr, const SubSample* subSamples,
|
||||
size_t numSubSamples, void* dstPtr,
|
||||
AString *errorDetailMsg) {
|
||||
if (mode != kMode_Unencrypted && mode != kMode_AES_CTR) {
|
||||
return BAD_TYPE;
|
||||
}
|
||||
|
||||
if (secure) {
|
||||
// TODO: Can't do secure in the Demo 2 milestone
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
// Convert parameters to the form the CDM wishes to consume them in.
|
||||
const KeyId keyId(reinterpret_cast<const char*>(key), KEY_ID_SIZE);
|
||||
const vector<uint8_t> ivVector(iv, iv + KEY_IV_SIZE);
|
||||
const uint8_t* const source = static_cast<const uint8_t*>(srcPtr);
|
||||
uint8_t* const dest = static_cast<uint8_t*>(dstPtr);
|
||||
|
||||
// Iterate through subsamples, sending them to the CDM serially.
|
||||
size_t offset = 0;
|
||||
|
||||
for (size_t i = 0; i < numSubSamples; ++i) {
|
||||
const SubSample &subSample = subSamples[i];
|
||||
|
||||
if (mode == kMode_Unencrypted && subSample.mNumBytesOfEncryptedData != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// "Decrypt" any unencrypted data. Per the ISO-CENC standard, clear data
|
||||
// comes before encrypted data.
|
||||
if (subSample.mNumBytesOfClearData != 0) {
|
||||
CdmResponseType res = mCDM->Decrypt(mSessionId, false, keyId,
|
||||
source + offset,
|
||||
subSample.mNumBytesOfClearData,
|
||||
ivVector, offset % 16, dest + offset);
|
||||
|
||||
if (res != wvcdm::NO_ERROR) {
|
||||
ALOGE("Decrypt error result in session %s during unencrypted block: %d",
|
||||
mSessionId.c_str(), res);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offset += subSample.mNumBytesOfClearData;
|
||||
}
|
||||
|
||||
// Decrypt any encrypted data. Per the ISO-CENC standard, encrypted data
|
||||
// comes after clear data.
|
||||
if (subSample.mNumBytesOfEncryptedData != 0) {
|
||||
CdmResponseType res = mCDM->Decrypt(mSessionId, true, keyId,
|
||||
source + offset,
|
||||
subSample.mNumBytesOfEncryptedData,
|
||||
ivVector, offset % 16, dest + offset);
|
||||
|
||||
if (res != wvcdm::NO_ERROR) {
|
||||
ALOGE("Decrypt error result in session %s during encrypted block: %d",
|
||||
mSessionId.c_str(), res);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offset += subSample.mNumBytesOfEncryptedData;
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<ssize_t>(offset);
|
||||
}
|
||||
|
||||
} // namespace wvdrm
|
||||
Reference in New Issue
Block a user