Initial Clear Key DRM Engine

Adds the initial pieces of a sample DRM Engine that accepts keys in the clear
through the decrypt call instead of using the DrmClientPlugin and its key
ladder.  This is to help unblock teams writing code that consumes DRM Engines
while Widevine continues working their real DRM engine.  This is based on the
in-progress Widevine DRM Engine.

This change contains the DRM Engine glue pieces (.so entry point,
DrmPluginFactory, etc.) and a CryptoPlugin implementation.  However, said
CryptoPlugin will not work until an implementation of OEMCrypto is provided
in a future checkin and the CryptoPlugin is hooked up to it.

For ease of loading, this library also implements the old CryptoFactory
interface and entry point.

If asked to create a CryptoPlugin with no data, it will defer to the old
Widevine Crypto Plugin.

Change-Id: I0bfbec7e32439a50a2956488dd970284f0075e61
This commit is contained in:
John "Juce" Bruce
2012-12-10 13:54:43 -08:00
committed by Jeff Tinker
parent d5aa1e41d3
commit 04bfbb0198
18 changed files with 1546 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
/*
* Copyright 2012 Google Inc. All Rights Reserved.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "wv_clear_key"
#include <utils/Log.h>
#include "WVCryptoPlugin.h"
namespace wvclearkey {
WVCryptoPlugin::WVCryptoPlugin() {
OEMCryptoResult res = OEMCrypto_OpenSession(&mSession);
if (res != OEMCrypto_SUCCESS) {
ALOGE("OEMCrypto_OpenSession error result: %d", res);
}
}
WVCryptoPlugin::~WVCryptoPlugin() {
OEMCryptoResult res = OEMCrypto_CloseSession(mSession);
if (res != OEMCrypto_SUCCESS) {
ALOGE("OEMCrypto_OpenSession error result: %d", res);
}
}
// Returns negative values for error codes and positive values for the size of
// the decrypted data.
ssize_t WVCryptoPlugin::decrypt(
bool secure,
const uint8_t key[16],
const uint8_t iv[16],
Mode mode,
const void *srcPtr,
const SubSample *subSamples, size_t numSubSamples,
void *dstPtr,
android::AString *errorDetailMsg) {
if (mode != kMode_Unencrypted && mode != kMode_AES_CTR) {
return android::BAD_TYPE;
}
const uint8_t *const source = static_cast<const uint8_t*>(srcPtr);
uint8_t *const dest = static_cast<uint8_t*>(dstPtr);
if (secure) {
// Can't do secure on this implementation
return -EPERM;
}
// For this special clear-key version of OEMCrypto ONLY, SelectKey actually
// has the meaning "use this key, passed in the clear." This is only the
// case for libclearkeydrmengine and not any other OEMCrypto.
OEMCryptoResult res = OEMCrypto_SelectKey(mSession, key, 16);
if (res != OEMCrypto_SUCCESS) {
ALOGE("Key selection error in session %d: %d", mSession, res);
return -EINVAL;
}
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. By convention,
// (see frameworks/av/include/media/stagefright/MetaData.h)
// clear data comes before encrypted data.
if (subSample.mNumBytesOfClearData != 0) {
OEMCrypto_DestBufferDesc output;
output.type = OEMCrypto_BufferType_Clear;
output.buffer.clear.address = dest + offset;
output.buffer.clear.max_length = subSample.mNumBytesOfClearData;
res = OEMCrypto_DecryptCTR(
mSession,
source + offset, subSample.mNumBytesOfClearData,
false,
iv,
offset % 16,
&output);
if (res != OEMCrypto_SUCCESS) {
ALOGE("Decrypt error result in session %d: %d", mSession, res);
return -EINVAL;
}
offset += subSample.mNumBytesOfClearData;
}
// Decrypt any encrypted data.
if (subSample.mNumBytesOfEncryptedData != 0) {
OEMCrypto_DestBufferDesc output;
output.type = OEMCrypto_BufferType_Clear;
output.buffer.clear.address = dest + offset;
output.buffer.clear.max_length = subSample.mNumBytesOfEncryptedData;
res = OEMCrypto_DecryptCTR(
mSession,
source + offset, subSample.mNumBytesOfEncryptedData,
true,
iv,
offset % 16,
&output);
if (res != OEMCrypto_SUCCESS) {
ALOGE("Decrypt error result in session %d: %d", mSession, res);
return -EINVAL;
}
offset += subSample.mNumBytesOfEncryptedData;
}
}
return static_cast<ssize_t>(offset);
}
} // namespace wvclearkey