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
147 lines
5.5 KiB
C++
147 lines
5.5 KiB
C++
/*********************************************************************
|
||
* MockOEMCrypto.h
|
||
*
|
||
* (c) Copyright 2011-2012 Google, Inc.
|
||
*
|
||
* Mock implementation of OEMCrypto.h used for testing.
|
||
*********************************************************************/
|
||
|
||
#ifndef WV_MOCK_OEMCRYPTO_H_
|
||
#define WV_MOCK_OEMCRYPTO_H_
|
||
|
||
#include "OEMCryptoDASH.h"
|
||
#include <openssl/aes.h>
|
||
#include <stdint.h>
|
||
#include <utils/KeyedVector.h>
|
||
#include <utils/Mutex.h>
|
||
#include <utils/RefBase.h>
|
||
#include <utils/SortedVector.h>
|
||
#include <utils/String8.h>
|
||
#include <utils/Vector.h>
|
||
#include <media/stagefright/foundation/ABase.h>
|
||
|
||
namespace wvdrm {
|
||
|
||
// Widevine keybox.
|
||
struct BinaryKeybox { // 128 bytes total.
|
||
uint8_t mDeviceId[32]; // C character string identifying the device. Null terminated.
|
||
uint8_t mKey[16]; // 128 bit AES key assigned to device. Generated by Widevine.
|
||
uint8_t mData[72]; // Key Data. Encrypted data.
|
||
uint8_t mMagic[4]; // Constant code used to recognize a valid keybox "kbox" = 0x6b626f78.
|
||
uint8_t mCrc[4]; // The CRC checksum of the first 124 bytes of the keybox.
|
||
};
|
||
|
||
struct OEMCrypto_KeyControl {
|
||
uint8_t mVerification[4]; // Known pattern to verify decryption is
|
||
// successful = ‘kctl’
|
||
uint32_t mDuration; // Maximum number of seconds during which the key
|
||
// can be used after being set. Interpret 0 as
|
||
// unlimited. (Network Byte Order)
|
||
uint32_t mNonce;
|
||
uint32_t mControl; // Bit field. (Network Byte Order)
|
||
// bit 4: data path type: 0 normal, 1 = secure only.
|
||
// bit 3: nonce enabled. 0 = ignore, 1 = requre nonce.
|
||
// bit 2: HDCP: 0 = not required, 1 = required.
|
||
// bit 1:0 CGMS control: 0 = copy freely, 2= copy once. 3= copy never.
|
||
};
|
||
|
||
enum KeyType {
|
||
SIGNING = 1,
|
||
CONTENT_ANY = 2,
|
||
CONTENT_AUDIO = 3,
|
||
CONTENT_VIDEO = 4
|
||
};
|
||
|
||
struct ControlledKey {
|
||
android::Vector<uint8_t> mKeyId;
|
||
OEMCrypto_KeyControl mControl;
|
||
uint8_t mKeyData[16];
|
||
AES_KEY mKey;
|
||
};
|
||
|
||
class MockSession : public android::RefBase {
|
||
public:
|
||
OEMCrypto_SESSION mId;
|
||
android::Vector<ControlledKey> mKeys;
|
||
ControlledKey *mCurrentKey;
|
||
|
||
bool mNoKeyLoaded;
|
||
ControlledKey mClearKey; // Stores a single key, for clear key demo.
|
||
|
||
uint8_t mMacKey[32];
|
||
uint8_t mEncryptKey[16];
|
||
uint32_t mNonce;
|
||
|
||
MockSession(OEMCrypto_SESSION id);
|
||
~MockSession();
|
||
|
||
OEMCryptoResult generateDerivedKeys(const uint8_t *mac_key_context,
|
||
uint32_t mac_key_context_length,
|
||
const uint8_t *enc_key_context,
|
||
uint32_t enc_key_context_length);
|
||
OEMCryptoResult generateNonce(uint32_t* nonce);
|
||
OEMCryptoResult generateSignature(const uint8_t* message,
|
||
size_t message_length,
|
||
uint8_t* signature,
|
||
size_t* signature_length);
|
||
OEMCryptoResult loadKeys(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);
|
||
OEMCryptoResult refreshKeys(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);
|
||
OEMCryptoResult selectKey(const uint8_t* key_id,
|
||
size_t key_id_length);
|
||
OEMCryptoResult decryptCTR(const uint8_t *data_addr,
|
||
size_t data_length,
|
||
bool is_encrypted,
|
||
const uint8_t *iv,
|
||
size_t offset,
|
||
const OEMCrypto_DestBufferDesc* out_buffer);
|
||
|
||
DISALLOW_EVIL_CONSTRUCTORS(MockSession);
|
||
};
|
||
|
||
class MockOEMCrypto : public android::RefBase {
|
||
public:
|
||
static MockOEMCrypto *sSingleton;
|
||
|
||
bool mInitialized;
|
||
BinaryKeybox mKeybox;
|
||
OEMCrypto_SESSION mMaxId;
|
||
android::KeyedVector<OEMCrypto_SESSION, android::sp<MockSession> > mSessions;
|
||
android::Mutex mSessionListMutex; // This locks list access only, not the items in the list.
|
||
// TODO: max sessions.
|
||
// TODO max keys.
|
||
bool mClearKeys;
|
||
|
||
MockOEMCrypto(BinaryKeybox *keybox = NULL);
|
||
virtual OEMCryptoResult initialize(void);
|
||
virtual OEMCryptoResult terminate(void);
|
||
virtual OEMCryptoResult openSession(OEMCrypto_SESSION *session);
|
||
virtual OEMCryptoResult closeSession(OEMCrypto_SESSION session);
|
||
virtual MockSession *findSession(OEMCrypto_SESSION id);
|
||
virtual OEMCryptoResult installKeybox(uint8_t *keybox,
|
||
size_t keyBoxLength);
|
||
virtual OEMCryptoResult isKeyboxValid(void);
|
||
virtual OEMCryptoResult getDeviceID(uint8_t* deviceID,
|
||
size_t* idLength);
|
||
virtual OEMCryptoResult getKeyData(uint8_t* keyData,
|
||
size_t* keyDataLength);
|
||
|
||
virtual ~MockOEMCrypto();
|
||
DISALLOW_EVIL_CONSTRUCTORS(MockOEMCrypto);
|
||
};
|
||
|
||
}
|
||
|
||
#endif // _WV_MOCK_OEMCRYPTO_H_
|