This is a software only implementation of the OEMCrypto library for testing the rest of the DRM code. It currently implements the OEMCrypto_DecrtyptCTR function using a clear key. I've included the license request code so the rest of the group can play with it, but I have only tested part of it. This patch also has some makefiles and an integration testing. You should be able to generate the shared library libclearkeydrmengine.so with cd vendor/widevine/libclearkeydrmengine; mm You can create some unit test and integration test programs from the directories: vendor/widevine/libwvdrmengine/oemcrypto/test vendor/widevine/libclearkeydrmengine/test vendor/widevine/libclearkeydrmengine/inttest vendor/widevine/libclearkeydrmengine/crypto/test This change also addresses some comments about comments in OEMCryptoDASH.h which were made in https://googleplex-android-review.googlesource.com/257323 Change-Id: Id6899b9f8d2f09e09be2ea493baa83a6b929073b
240 lines
8.8 KiB
C++
240 lines
8.8 KiB
C++
/*********************************************************************
|
|
* OEMCryptoWrapper.cpp
|
|
*
|
|
* (c) Copyright 2011-2012 Google, Inc.
|
|
*
|
|
* OEMCryptoDASH fuctions wrapped around a Mock OEMCrypto object.
|
|
*********************************************************************/
|
|
|
|
#define LOG_TAG "WV.MockOEMCrypto"
|
|
#include <utils/Log.h>
|
|
#include <utils/String8.h>
|
|
|
|
#include "OEMCryptoDASH.h"
|
|
#include "MockOEMCrypto.h"
|
|
#include "openssl/rand.h"
|
|
|
|
using namespace android;
|
|
using namespace wvdrm;
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_Initialize(void) {
|
|
if (MockOEMCrypto::sSingleton == NULL) MockOEMCrypto::sSingleton = new MockOEMCrypto();
|
|
return MockOEMCrypto::sSingleton->initialize();
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_Terminate(void) {
|
|
if (!MockOEMCrypto::sSingleton) {
|
|
ALOGE( "[OEMCrypto_Terminate(): failed - not initialized, no engine]\n" );
|
|
return OEMCrypto_ERROR_TERMINATE_FAILED;
|
|
}
|
|
return MockOEMCrypto::sSingleton->terminate();
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION *session) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_OPEN_SESSION_FAILED;
|
|
}
|
|
return MockOEMCrypto::sSingleton->openSession(session);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_TERMINATE_FAILED;
|
|
}
|
|
return MockOEMCrypto::sSingleton->closeSession(session);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session,
|
|
const uint8_t *mac_key_context,
|
|
uint32_t mac_key_context_length,
|
|
const uint8_t *enc_key_context,
|
|
uint32_t enc_key_context_length) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
MockSession *s = MockOEMCrypto::sSingleton->findSession(session);
|
|
if (!s) {
|
|
ALOGE("OEMCrypto no session for id %d", session);
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
return s->generateDerivedKeys(mac_key_context,mac_key_context_length,
|
|
enc_key_context, enc_key_context_length);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
|
uint32_t* nonce) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
MockSession *s = MockOEMCrypto::sSingleton->findSession(session);
|
|
if (!s) {
|
|
ALOGE("OEMCrypto no session for id %d", session);
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
return s->generateNonce(nonce);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_GenerateSignature(OEMCrypto_SESSION session,
|
|
const uint8_t* message,
|
|
size_t message_length,
|
|
uint8_t* signature,
|
|
size_t* signature_length) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
MockSession *s = MockOEMCrypto::sSingleton->findSession(session);
|
|
if (!s) {
|
|
ALOGE("OEMCrypto no session for id %d", session);
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
return s->generateSignature(message, message_length,
|
|
signature, signature_length);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,
|
|
const uint8_t* message,
|
|
size_t message_length,
|
|
const uint8_t* signature,
|
|
size_t signature_length,
|
|
const uint8_t* enc_mac_key_iv,
|
|
const uint8_t* enc_mac_key,
|
|
size_t num_keys,
|
|
const OEMCrypto_KeyObject* key_array) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
MockSession *s = MockOEMCrypto::sSingleton->findSession(session);
|
|
if (!s) {
|
|
ALOGE("OEMCrypto no session for id %d", session);
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
return s->loadKeys(message, message_length, signature, signature_length,
|
|
enc_mac_key_iv, enc_mac_key,
|
|
num_keys, key_array);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult
|
|
OEMCrypto_RefreshKeys(OEMCrypto_SESSION session,
|
|
const uint8_t* message,
|
|
size_t message_length,
|
|
const uint8_t* signature,
|
|
size_t signature_length,
|
|
size_t num_keys,
|
|
const OEMCrypto_KeyRefreshObject* key_array) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
MockSession *s = MockOEMCrypto::sSingleton->findSession(session);
|
|
if (!s) {
|
|
ALOGE("OEMCrypto no session for id %d", session);
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
return s->refreshKeys(message, message_length, signature,
|
|
signature_length, num_keys, key_array);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session,
|
|
const uint8_t* key_id,
|
|
size_t key_id_length) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
MockSession *s = MockOEMCrypto::sSingleton->findSession(session);
|
|
if (!s) {
|
|
ALOGE("OEMCrypto no session for id %d", session);
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
return s->selectKey(key_id, key_id_length);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_DecryptCTR(OEMCrypto_SESSION session,
|
|
const uint8_t *data_addr,
|
|
size_t data_length,
|
|
bool is_encrypted,
|
|
const uint8_t *iv,
|
|
size_t offset,
|
|
const OEMCrypto_DestBufferDesc* out_buffer) {
|
|
if (! MockOEMCrypto::sSingleton) {
|
|
ALOGE("OEMCrypto not initialized");
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
MockSession *s = MockOEMCrypto::sSingleton->findSession(session);
|
|
if (!s) {
|
|
ALOGE("OEMCrypto no session for id %d", session);
|
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
|
}
|
|
return s->decryptCTR(data_addr, data_length, is_encrypted,
|
|
iv, offset, out_buffer);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_InstallKeybox(uint8_t *keybox,
|
|
size_t keyBoxLength) {
|
|
if (!MockOEMCrypto::sSingleton) {
|
|
MockOEMCrypto::sSingleton = new MockOEMCrypto(NULL);
|
|
}
|
|
return MockOEMCrypto::sSingleton->installKeybox(keybox, keyBoxLength);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {
|
|
if (!MockOEMCrypto::sSingleton) {
|
|
MockOEMCrypto::sSingleton = new MockOEMCrypto(NULL);
|
|
}
|
|
return MockOEMCrypto::sSingleton->isKeyboxValid();
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
|
size_t *idLength) {
|
|
if (MockOEMCrypto::sSingleton == NULL) MockOEMCrypto::sSingleton = new MockOEMCrypto();
|
|
return MockOEMCrypto::sSingleton->getDeviceID(deviceID, idLength);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
|
size_t *keyDataLength) {
|
|
if (MockOEMCrypto::sSingleton == NULL) MockOEMCrypto::sSingleton = new MockOEMCrypto();
|
|
return MockOEMCrypto::sSingleton->getKeyData(keyData, keyDataLength);
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
|
size_t dataLength) {
|
|
ALOGV("OEMCryptoResult OEMCrypto_GetRandom\n");
|
|
if (RAND_bytes(randomData, dataLength)) {
|
|
return OEMCrypto_SUCCESS;
|
|
} else {
|
|
return OEMCrypto_ERROR_RNG_FAILED;
|
|
}
|
|
}
|
|
|
|
extern "C"
|
|
OEMCryptoResult OEMCrypto_WrapKeybox(uint8_t *keybox,
|
|
size_t keyBoxLength,
|
|
uint8_t *wrappedKeybox,
|
|
size_t *wrappedKeyBoxLength,
|
|
uint8_t *transportKey,
|
|
size_t transportKeyLength) {
|
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
|
}
|