Move OEMCrypto Mock files to Clear Key Library
In order to match the other implementations of CDM, we are going to replace the android OEMCrypto mockup with the one in the cdm repository. This would be disruptive to the clear key library because it relies on the current implementation of the mockup. In order to prevent that, I am moving the current mockup into the same directory as the clear key library. Then, we can put the new mockup under the directory libwvdrmengine. This mockup will then be deleted when the clear key library is deleted. Change-Id: I89ee23f249dacd18241ae5ca499329e620bf5a2c
This commit is contained in:
@@ -1,827 +0,0 @@
|
||||
/*********************************************************************
|
||||
* OEMCryptoDASH.h
|
||||
*
|
||||
* (c) Copyright 2011-2012 Google, Inc.
|
||||
*
|
||||
* Reference APIs needed to support Widevine's crypto algorithms.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef OEMCRYPTO_DASH_H_
|
||||
#define OEMCRYPTO_DASH_H_
|
||||
|
||||
#include<stdint.h>
|
||||
|
||||
// 12/20/2012 - changes from 4.3 to 4.4:
|
||||
// 1. Added key id length.
|
||||
// 2. Renamed fields in DestBufferDesc.
|
||||
// 12/11/2012 - changes from 4.2 to 4.3:
|
||||
// 1. Include stdint.h. Change base types.
|
||||
// 2. Allow NULL for mac_key in OEMCrypto_LoadKeys() (doc-only change).
|
||||
// 3. Allow NULL for key_control_block in OEMCrypto_RefreshKeys() (doc-only
|
||||
// change).
|
||||
// 12/05/2012 - changes from 4.1 to 4.2:
|
||||
// 1. Change OEMCrypto_GenerateDerivedkeys() to pass in two context strings
|
||||
// for the derived key computation - one for the mac key and one for the
|
||||
// encryption key.
|
||||
// 12/04/2012 - changes from 4.0 to 4.1:
|
||||
// 1. Change 'unsigned long' back to 'unsigned int'.
|
||||
// 2. Add struct OEMCrypto_DestBufferDesc for OEMCrypto_DecryptCTR()
|
||||
// output param.
|
||||
// 3. Change OEMCrypto_KeyObject to use 'const OEMCrypto_UINT8*'
|
||||
// 4. Change OEMCrypto_KeyRefreshObject to use 'const OEMCrypto_UINT8*'
|
||||
// 5. Change enc_mac params of OEMCrypto_LoadKeys() to
|
||||
// to use const OEMCrypto_UINT8*'.
|
||||
// 6. Add OEMCrypto_SelectKey().
|
||||
// 7. Add OEMCrypto_DestBufferDesc param to OEMCrypto_DecryptCTR().
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OEMCRYPTO_VERSION "4.4"
|
||||
static const char oec_version[] = OEMCRYPTO_VERSION;
|
||||
|
||||
typedef uint32_t OEMCrypto_SESSION;
|
||||
|
||||
typedef enum OEMCryptoResult {
|
||||
OEMCrypto_SUCCESS = 0,
|
||||
OEMCrypto_ERROR_INIT_FAILED = 1,
|
||||
OEMCrypto_ERROR_TERMINATE_FAILED = 2,
|
||||
OEMCrypto_ERROR_OPEN_FAILURE = 3,
|
||||
OEMCrypto_ERROR_CLOSE_FAILURE = 4,
|
||||
OEMCrypto_ERROR_ENTER_SECURE_PLAYBACK_FAILED = 5,
|
||||
OEMCrypto_ERROR_EXIT_SECURE_PLAYBACK_FAILED = 6,
|
||||
OEMCrypto_ERROR_SHORT_BUFFER = 7,
|
||||
OEMCrypto_ERROR_NO_DEVICE_KEY = 8,
|
||||
OEMCrypto_ERROR_NO_ASSET_KEY = 9,
|
||||
OEMCrypto_ERROR_KEYBOX_INVALID = 10,
|
||||
OEMCrypto_ERROR_NO_KEYDATA = 11,
|
||||
OEMCrypto_ERROR_NO_CW = 12,
|
||||
OEMCrypto_ERROR_DECRYPT_FAILED = 13,
|
||||
OEMCrypto_ERROR_WRITE_KEYBOX = 14,
|
||||
OEMCrypto_ERROR_WRAP_KEYBOX = 15,
|
||||
OEMCrypto_ERROR_BAD_MAGIC = 16,
|
||||
OEMCrypto_ERROR_BAD_CRC = 17,
|
||||
OEMCrypto_ERROR_NO_DEVICEID = 18,
|
||||
OEMCrypto_ERROR_RNG_FAILED = 19,
|
||||
OEMCrypto_ERROR_RNG_NOT_SUPPORTED = 20,
|
||||
OEMCrypto_ERROR_SETUP = 21,
|
||||
OEMCrypto_ERROR_OPEN_SESSION_FAILED = 22,
|
||||
OEMCrypto_ERROR_CLOSE_SESSION_FAILED = 23,
|
||||
OEMCrypto_ERROR_INVALID_SESSION = 24,
|
||||
OEMCrypto_ERROR_NOT_IMPLEMENTED = 25,
|
||||
OEMCrypto_ERROR_NO_CONTENT_KEY = 26,
|
||||
OEMCrypto_ERROR_CONTROL_INVALID = 27,
|
||||
OEMCrypto_ERROR_UNKNOWN_FAILURE = 28,
|
||||
OEMCrypto_ERROR_INVALID_CONTEXT = 29,
|
||||
OEMCrypto_ERROR_SIGNATURE_FAILURE = 30,
|
||||
OEMCrypto_ERROR_TOO_MANY_SESSIONS = 31,
|
||||
OEMCrypto_ERROR_INVALID_NONCE = 32,
|
||||
OEMCrypto_ERROR_TOO_MANY_KEYS = 33
|
||||
} OEMCryptoResult;
|
||||
|
||||
/*
|
||||
* OEMCrypto_DestBufferDesc
|
||||
* Describes the type and access information for the memory to receive
|
||||
* decrypted data.
|
||||
*
|
||||
* The OEMCrypto API supports a range of client device architectures.
|
||||
* Different architectures have different methods for acquiring and securing
|
||||
* buffers that will hold portions of the audio or video stream after
|
||||
* decryption. Three basic strategies are recognized for handling decrypted
|
||||
* stream data:
|
||||
* 1. Return the decrypted data in the clear into normal user memory
|
||||
* (ClearBuffer). The caller uses normal memory allocation methods to
|
||||
* acquire a buffer, and supplies the memory address of the buffer in the
|
||||
* descriptor.
|
||||
* 2. Place the decrypted data into protected memory (SecureBuffer). The
|
||||
* caller uses a platform-specific method to acquire the protected buffer
|
||||
* and a user-memory handle that references it. The handle is supplied
|
||||
* to the decrypt call in the descriptor.
|
||||
* 3. Place the decrypted data directly into the audio or video decoder fifo
|
||||
* (Direct). The caller will use platform-specific methods to initialize
|
||||
* the fifo and the decoders. The decrypted stream data is not accessible
|
||||
* to the caller.
|
||||
*
|
||||
* Specific fields are as follows:
|
||||
*
|
||||
* (type == OEMCrypto_BufferType_Clear)
|
||||
* address - Address of start of user memory buffer.
|
||||
* max_length - Size of user memory buffer.
|
||||
* (type == OEMCrypto_BufferType_Secure)
|
||||
* buffer - handle to a platform-specific secure buffer.
|
||||
* max_length - Size of platform-specific secure buffer.
|
||||
* (type == OEMCrypto_BufferType_Direct)
|
||||
* is_video - If true, decrypted bytes are routed to the video
|
||||
* decoder. If false, decrypted bytes are routed to the
|
||||
* audio decoder.
|
||||
*/
|
||||
typedef enum OEMCryptoBufferType {
|
||||
OEMCrypto_BufferType_Clear,
|
||||
OEMCrypto_BufferType_Secure,
|
||||
OEMCrypto_BufferType_Direct
|
||||
} OEMCrytoBufferType;
|
||||
|
||||
typedef struct {
|
||||
OEMCryptoBufferType type;
|
||||
union {
|
||||
struct { // type == OEMCrypto_BufferType_Clear
|
||||
uint8_t* address;
|
||||
size_t max_length;
|
||||
} clear;
|
||||
struct { // type == OEMCrypto_BufferType_Secure
|
||||
void* handle;
|
||||
size_t max_length;
|
||||
} secure;
|
||||
struct { // type == OEMCrypto_BufferType_Direct
|
||||
bool is_video;
|
||||
} direct;
|
||||
} buffer;
|
||||
} OEMCrypto_DestBufferDesc;
|
||||
|
||||
/*
|
||||
* OEMCrypto_KeyObject
|
||||
* Points to the relevant fields for a content key. The fields are extracted
|
||||
* from the License Response message offered to OEMCrypto_LoadKeys(). Each
|
||||
* field points to one of the components of the key. All fields are 128 bits
|
||||
* (16 bytes):
|
||||
* key_id - the unique id of this key.
|
||||
* key_data_iv - the IV for performing AES-128-CBC decryption of the
|
||||
* key_data field.
|
||||
* key_data - the key data. It is encrypted (AES-128-CBC) with the
|
||||
* session's derived encrypt key and the key_data_iv.
|
||||
* key_control_iv - the IV for performing AES-128-CBC decryption of the
|
||||
* key_control field.
|
||||
* key_control - the key control block. It is encrypted (AES-128-CBC) with
|
||||
* the content key from the key_data field.
|
||||
*
|
||||
* The memory for the OEMCrypto_KeyObject fields is allocated and freed
|
||||
* by the caller of OEMCrypto_LoadKeys().
|
||||
*/
|
||||
typedef struct {
|
||||
const uint8_t* key_id;
|
||||
size_t key_id_length;
|
||||
const uint8_t* key_data_iv;
|
||||
const uint8_t* key_data;
|
||||
const uint8_t* key_control_iv;
|
||||
const uint8_t* key_control;
|
||||
} OEMCrypto_KeyObject;
|
||||
|
||||
/*
|
||||
* OEMCrypto_KeyRefreshObject
|
||||
* Points to the relevant fields for renewing a content key. The fields are
|
||||
* extracted from the License Renewal Response message offered to
|
||||
* OEMCrypto_RefreshKeys(). Each field points to one of the components of
|
||||
* the key. All fields are 128 bits (16 bytes):
|
||||
* key_id - the unique id of this key.
|
||||
* key_control_iv - the IV for performing AES-128-CBC decryption of the
|
||||
* key_control field.
|
||||
* key_control - the key control block. It is encrypted (AES-128-CBC) with
|
||||
* the content key from the key_data field.
|
||||
*
|
||||
* The key_data is unchanged from the original OEMCrypto_LoadKeys() call. Some
|
||||
* Key Control Block fields, especially those related to key lifetime, may
|
||||
* change.
|
||||
*
|
||||
* The memory for the OEMCrypto_KeyRefreshObject fields is allocated and freed
|
||||
* by the caller of OEMCrypto_RefreshKeys().
|
||||
*/
|
||||
typedef struct {
|
||||
const uint8_t* key_id;
|
||||
size_t key_id_length;
|
||||
const uint8_t* key_control_iv;
|
||||
const uint8_t* key_control;
|
||||
} OEMCrypto_KeyRefreshObject;
|
||||
|
||||
#define OEMCrypto_Initialize _oec01
|
||||
#define OEMCrypto_Terminate _oec02
|
||||
#define OEMCrypto_SetEntitlementKey _oec03
|
||||
#define OEMCrypto_DeriveControlWord _oec04
|
||||
#define OEMCrypto_DecryptVideo _oec05
|
||||
#define OEMCrypto_DecryptAudio _oec06
|
||||
#define OEMCrypto_InstallKeybox _oec07
|
||||
#define OEMCrypto_GetKeyData _oec08
|
||||
#define OEMCrypto_IsKeyboxValid _oec09
|
||||
#define OEMCrypto_GetRandom _oec10
|
||||
#define OEMCrypto_GetDeviceID _oec11
|
||||
#define OEMCrypto_EnterSecurePlayback _oec12
|
||||
#define OEMCrypto_ExitSecurePlayback _oec13
|
||||
#define OEMCrypto_WrapKeybox _oec14
|
||||
#define OEMCrypto_OpenSession _oec15
|
||||
#define OEMCrypto_CloseSession _oec16
|
||||
#define OEMCrypto_SetContentKey _oec17
|
||||
#define OEMCrypto_DecryptCTR _oec18
|
||||
#define OEMCrypto_DecryptCTS _oec19
|
||||
#define OEMCrypto_GenerateDerivedKeys _oec20
|
||||
#define OEMCrypto_GenerateSignature _oec21
|
||||
#define OEMCrypto_GenerateNonce _oec22
|
||||
#define OEMCrypto_LoadKeys _oec23
|
||||
#define OEMCrypto_RefreshKeys _oec24
|
||||
#define OEMCrypto_SelectKey _oec25
|
||||
|
||||
/*
|
||||
* OEMCrypto_Initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the crypto firmware/hardware.
|
||||
*
|
||||
* Parameters:
|
||||
* N/A
|
||||
*
|
||||
* Threading:
|
||||
* No other function calls will be made while this function is running. This
|
||||
* function will not be called again before OEMCrypto_Terminate.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_INIT_FAILED failed to initialize crypto hardware
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_Initialize(void);
|
||||
|
||||
/*
|
||||
* OEMCrypto_Terminate
|
||||
*
|
||||
* Description:
|
||||
* The API closes the crypto operation and releases all resources used.
|
||||
*
|
||||
* Parameters:
|
||||
* N/A
|
||||
*
|
||||
* Threading:
|
||||
* No other OEMCrypto calls are made while this function is running. After
|
||||
* this function is called, no other OEMCrypto calls will be made until another
|
||||
* call to OEMCrypto_Initialize is made.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_TERMINATE_FAILED failed to de-initialize crypto hardware
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_Terminate(void);
|
||||
|
||||
/*
|
||||
* OEMCrypto_OpenSession
|
||||
*
|
||||
* Description:
|
||||
* The API provides for session based crypto initialization for AES CTR mode.
|
||||
*
|
||||
* Parameters:
|
||||
* session (out) - pointer to crypto session identifier.
|
||||
*
|
||||
* Threading:
|
||||
* No other Open/Close session calls will be made while this function is
|
||||
* running. Functions on existing sessions may be called while this function
|
||||
* is active.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_TOO_MANY_SESSIONS failed because too many sessions are open
|
||||
* OEMCrypto_ERROR_OPEN_SESSION_FAILED failed to initialize the crypto session
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION *session);
|
||||
|
||||
/*
|
||||
* OEMCrypto_CloseSession
|
||||
*
|
||||
* Description:
|
||||
* The API provides for session based crypto termination for AES CTR mode.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
*
|
||||
* Threading:
|
||||
* No other Open/Close session calls will be made while this function is
|
||||
* running. Functions on existing sessions may be called while this function
|
||||
* is active.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_INVALID_SESSION no open session with that id.
|
||||
* OEMCrypto_ERROR_CLOSE_SESSION_FAILED failed to terminate the crypto session
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session);
|
||||
|
||||
/*
|
||||
* OEMCrypto_GenerateDerivedKeys
|
||||
*
|
||||
* Description:
|
||||
* Generates a pair of secondary keys, mac_key and encrypt_key, for handling
|
||||
* signing and content key decryption under the license server protocol
|
||||
* for AES CTR mode.
|
||||
*
|
||||
* Refer to document "OEMCrypto Changes for V2 License Protocol" for details.
|
||||
* This function computes the AES-128-CMAC of the enc_key_context and stores
|
||||
* it in secure memory as the encrypt_key.
|
||||
* It then computes two cycles of AES-128-CMAC of the mac_key_context and
|
||||
* stores it in the mac_key. These two keys will be stored until the next
|
||||
* call to LoadKeys.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
* mac_key_context (in) - pointer to memory containing context data for
|
||||
* computing the HMAC generation key.
|
||||
* mac_key_context_length (in) - length of the HMAC key context data.
|
||||
* enc_key_context (in) - pointer to memory containing context data for
|
||||
* computing the encryption key.
|
||||
* enc_key_context_length (in) - length of the encryption key context data.
|
||||
*
|
||||
* Results:
|
||||
* mac_key: the 256 bit mac key is generated and stored in secure memory.
|
||||
* enc_key: the 128 bit encryption key is generated and stored in secure memory.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||
* OEMCrypto_ERROR_INVALID_SESSION
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* OEMCrypto_GenerateNonce
|
||||
*
|
||||
* Description:
|
||||
* Generates a 32-bit nonce to detect possible replay attack on the key
|
||||
* control block. The nonce is stored in secure memory and will be used
|
||||
* for the next call to LoadKeys.
|
||||
*
|
||||
* Refer to documents "OEMCrypto Changes for V2 License Protocol" and "Key
|
||||
* Control Block Definition" for details.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
* nonce (out) - pointer to memory to received the computed nonce.
|
||||
*
|
||||
* Results:
|
||||
* nonce: the nonce is also stored in secure memory.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||
* OEMCrypto_ERROR_INVALID_SESSION
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GenerateNonce(
|
||||
OEMCrypto_SESSION session,
|
||||
uint32_t* nonce);
|
||||
|
||||
/*
|
||||
* OEMCrypto_GenerateSignature
|
||||
*
|
||||
* Description:
|
||||
* Generates a HMAC-SHA256 signature for license request signing under the
|
||||
* license server protocol for AES CTR mode.
|
||||
*
|
||||
* NOTE: OEMCrypto_GenerateDerivedKeys() must be called first to establish the
|
||||
* mac_key
|
||||
*
|
||||
* Refer to document "OEMCrypto Changes for V2 License Protocol" for details.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
* message (in) - pointer to memory containing message to be signed.
|
||||
* message_length (in) - length of the message.
|
||||
* signature (out) - pointer to memory to received the computed signature.
|
||||
* signature_length (in/out) - (in) length of the signature buffer.
|
||||
* (out) actual length of the signature
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||
* OEMCrypto_ERROR_INVALID_SESSION
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GenerateSignature(
|
||||
OEMCrypto_SESSION session,
|
||||
const uint8_t* message,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length);
|
||||
|
||||
/*
|
||||
* OEMCrypto_LoadKeys
|
||||
*
|
||||
* Description:
|
||||
* Installs a set of keys for performing decryption in the current session.
|
||||
*
|
||||
* The relevant fields have been extracted from the License Response protocol
|
||||
* message, but the entire message and associated signature are provided so
|
||||
* the message can be verified (using HMAC-SHA256 with the derived mac_key).
|
||||
* If the signature verification fails, ignore all other arguments and return
|
||||
* OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add the keys to the session
|
||||
* context.
|
||||
*
|
||||
* The keys will be decrypted using the current encrypt_key (AES-128-CBC) and
|
||||
* the IV given in the KeyObject. Each key control block will be decrypted
|
||||
* using the corresponding content key (AES-128-CBC) and the IV given in the
|
||||
* KeyObject.
|
||||
*
|
||||
* If any key's control block does not have valid verification fields, return
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT and do not install any keys.
|
||||
*
|
||||
* If any key's control block requires a nonce, and the nonce in the control
|
||||
* block is different from the current nonce, return
|
||||
* OEMCrypto_ERROR_INVALID_NONCE. In that case, do not install any keys.
|
||||
*
|
||||
* The new mac_key is decrypted with the current encrypt_key and the offered
|
||||
* IV. It replaces the current mac_key.
|
||||
*
|
||||
* The mac_key and encrypt_key were generated and stored by the previous call
|
||||
* to OEMCrypto_GenerateDerivedKeys(). The nonce was generated and stored by
|
||||
* the previous call to OEMCrypto_GenerateNonce().
|
||||
*
|
||||
* NOTE: OEMCrypto_GenerateDerivedKeys() must be called first to establish the
|
||||
* mac_key and encrypt_key.
|
||||
*
|
||||
* Refer to document "OEMCrypto Changes for V2 License Protocol" for details.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
* message (in) - pointer to memory containing message to be verified.
|
||||
* message_length (in) - length of the message.
|
||||
* signature (in) - pointer to memory containing the signature.
|
||||
* signature_length (in) - length of the signature.
|
||||
* enc_mac_key_iv (in) - IV for decrypting new mac_key. Size is 128 bits.
|
||||
* enc_mac_key (in) - encrypted mac_key for generating new mac_key. Size is
|
||||
* 256 bits.
|
||||
* num_keys (in) - number of keys present.
|
||||
* key_array (in) - set of keys to be installed.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||
* OEMCrypto_ERROR_INVALID_SESSION
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* OEMCrypto_ERROR_SIGNATURE_FAILURE
|
||||
* OEMCrypto_ERROR_INVALID_NONCE
|
||||
* OEMCrypto_ERROR_TOO_MANY_KEYS
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* OEMCrypto_RefreshKeys
|
||||
*
|
||||
* Description:
|
||||
* Updates an existing set of keys for continuing decryption in the
|
||||
* current session.
|
||||
*
|
||||
* The relevant fields have been extracted from the Renewal Response protocol
|
||||
* message, but the entire message and associated signature are provided so
|
||||
* the message can be verified (using HMAC-SHA256 with the current mac_key).
|
||||
* If the signature verification fails, ignore all other arguments and return
|
||||
* OEMCrypto_ERROR_SIGNATURE_FAILURE. Otherwise, add the keys to the session
|
||||
* context.
|
||||
*
|
||||
* NOTE: OEMCrypto_GenerateDerivedKeys() or OEMCrypto_LoadKeys() must be called
|
||||
* first to establish the mac_key
|
||||
*
|
||||
* Refer to document OEMCrypto Changes for V2 License Protocol for details.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
* message (in) - pointer to memory containing message to be verified.
|
||||
* message_length (in) - length of the message.
|
||||
* signature (in) - pointer to memory containing the signature.
|
||||
* signature_length (in) - length of the signature.
|
||||
* num_keys (in) - number of keys present.
|
||||
* key_array (in) - set of keys to be installed.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||
* OEMCrypto_ERROR_INVALID_SESSION
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* OEMCrypto_ERROR_SIGNATURE_FAILURE
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* OEMCrypto_SelectKey
|
||||
*
|
||||
* Description:
|
||||
* Select a content key and install it in the hardware key ladder for
|
||||
* subsequent decryption operations (OEMCrypto_DecryptCTR()) for this session.
|
||||
* The specified key must have been previously "installed" via
|
||||
* OEMCrypto_LoadKeys() or OEMCrypto_RefreshKeys().
|
||||
*
|
||||
* A key control block is associated with the key and the session, and is used
|
||||
* to configure the session context. The Key Control data is documented in
|
||||
* "Key Control Block Definition".
|
||||
*
|
||||
* Step 1: Lookup the content key data via the offered key_id. The key data
|
||||
* includes the key value, the content key IV, the key control
|
||||
* block, and the key control block IV.
|
||||
*
|
||||
* Step 2: Latch the content key into the hardware key ladder. Set
|
||||
* permission flags and timers based on the key's control block.
|
||||
*
|
||||
* Step 3: use the latched content key to decrypt (AES-128-CTR)
|
||||
* to decrypt buffers passed in via OEMCrypto_DecryptCTR(). Continue
|
||||
* to use this key until OEMCrypto_SelectKey() is called again, or
|
||||
* until OEMCrypto_CloseSession() is called.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier
|
||||
* key_id (in) - pointer to the Key ID
|
||||
* key_id_length (in) - length of the Key ID in bytes
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_INVALID_SESSION crypto session ID invalid or not open
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY failed to decrypt device key
|
||||
* OEMCrypto_ERROR_NO_CONTENT_KEY failed to decrypt content key
|
||||
* OEMCrypto_ERROR_CONTROL_INVALID invalid or unsupported control input
|
||||
* OEMCrypto_ERROR_KEYBOX_INVALID cannot decrypt and read from Keybox
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_SelectKey(const OEMCrypto_SESSION session,
|
||||
const uint8_t* key_id,
|
||||
size_t key_id_length);
|
||||
|
||||
/*
|
||||
* OEMCrypto_DecryptCTR
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* The API decrypts (AES-CTR) the payload in the buffer referenced by
|
||||
* the buffer_addr parameter into an internal buffer, using the key
|
||||
* identified by key_id.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
* data_addr (in) - An unaligned pointer to this segment of the stream.
|
||||
* data_length (in) - The length of this segment of the stream.
|
||||
* is_encrypted (in) - True if the buffer described by data_addr,
|
||||
* data_length is encrypted. If is_encrypted is false, only the
|
||||
* data_addr and data_length parameters are used. The iv and offset
|
||||
* arguments are ignored.
|
||||
* iv (in) - The initial value block to be used for content decryption.
|
||||
* This is discussed further below.
|
||||
* offset (in) - If non-zero, the decryption block boundary is different
|
||||
* from the start of the data. offset should be subtracted from
|
||||
* data_addr to compute the starting address of the first decrypted
|
||||
* block. The bytes between the decryption block start address and
|
||||
* data_addr are discarded after decryption.
|
||||
* out_buffer (in) - A caller-owned descriptor that specifies the
|
||||
* handling of the decrypted byte stream. See OEMCrypto_DestbufferDesc
|
||||
* for details.
|
||||
*
|
||||
* AES CTR is a stream cipher. The stream may be composed of arbitrary-
|
||||
* length clear and encrypted segments. The encrypted portions of a sample
|
||||
* are collectively treated as a continuous sequence of decryption
|
||||
* block-sized blocks even though the sequence is interrupted by clear blocks.
|
||||
* This means a given encrypted segment may not start or end on a decryption
|
||||
* block boundary.
|
||||
*
|
||||
* If data_addr is not aligned with a decryption block boundary (offset != 0),
|
||||
* the additional offset bytes before data_addr (pre-padding) are included in
|
||||
* the decrypt operation, and they are dropped after decryption. If
|
||||
* data_length + offset is not a multiple of the decryption block size, the
|
||||
* extra bytes in the final decryption block (post-padding) are also dropped
|
||||
* after decryption. The caller is responsible for guaranteeing that all
|
||||
* memory addresses from (data-addr - pre-padding) to (data-addr +
|
||||
* data-length + post-padding) are valid memory addresses.
|
||||
*
|
||||
* After decrypting the entire buffer including any pre-padding and
|
||||
* post-padding, send data_length bytes starting at data_addr to the decoder.
|
||||
*
|
||||
* NOTES:
|
||||
* IV points to the counter value to be used for the initial
|
||||
* encrypted block of the input buffer. The IV length is the AES
|
||||
* block size. For subsequent encrypted AES blocks the IV is
|
||||
* calculated by incrementing the lower 64 bits (byte 8-15) of the
|
||||
* IV value used for the previous block. The counter rolls over to
|
||||
* zero when it reaches its maximum value (0xFFFFFFFFFFFFFFFF).
|
||||
* The upper 64 bits (byte 0-7) of the IV do not change.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||
* OEMCrypto_ERROR_INVALID_SESSION
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
* OEMCrypto_ERROR_INVALID_CONTEXT
|
||||
* OEMCrypto_ERROR_DECRYPT_FAILED
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* OEMCrypto_InstallKeybox
|
||||
*
|
||||
* Description:
|
||||
* Unwrap and store the keybox to persistent memory.
|
||||
* The device key must be stored securely. The device key will be decrypted
|
||||
* and latched into hardware key ladder by OEMCrypto_SetEntitlementKey.
|
||||
*
|
||||
* This function is used once to load the keybox onto the device at
|
||||
* provisioning time.
|
||||
*
|
||||
* Parameters:
|
||||
* keybox (in) - Pointer to clear keybox data. Must have been originally
|
||||
* wrapped with OEMCrypto_WrapKeybox.
|
||||
* keyboxLength (in) - Length of the keybox data in bytes.
|
||||
*
|
||||
* Threading:
|
||||
* This function is not called simultaneously with any other functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_WRITE_KEYBOX failed to handle and store Keybox
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_InstallKeybox(uint8_t *keybox,
|
||||
size_t keyBoxLength);
|
||||
|
||||
/*
|
||||
* OEMCrypto_IsKeyboxValid
|
||||
*
|
||||
* Description:
|
||||
* Validate the Widevine Keybox stored on the device.
|
||||
*
|
||||
* The API performs two verification steps on the Keybox. It first verifies
|
||||
* the MAGIC field contains a valid signature (must be 'kbox'). The API then
|
||||
* computes the CRC using CRC-32 (Posix 1003.2 standard) and compares the
|
||||
* checksum to the CRC stored in the Keybox. The CRC is computed over the
|
||||
* entire Keybox excluding the 4 CRC bytes (i.e. Keybox[0..123]).
|
||||
*
|
||||
* Parameters:
|
||||
* none
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any session functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_BAD_MAGIC
|
||||
* OEMCrypto_ERROR_BAD_CRC
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_IsKeyboxValid(void);
|
||||
|
||||
/*
|
||||
* OEMCrypto_GetDeviceID
|
||||
*
|
||||
* Description:
|
||||
* Retrieve the device's unique identifier from the Keybox.
|
||||
*
|
||||
* Parameters:
|
||||
* deviceId (out) - pointer to the buffer that receives the Device ID
|
||||
* idLength (in/out) - on input, size of the caller's device ID buffer.
|
||||
* On output, the number of bytes written into the buffer.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any session functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_SHORT_BUFFER buffer is too small to return the device ID
|
||||
* OEMCrypto_ERROR_NO_DEVICEID failed to return Device Id
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
||||
size_t *idLength);
|
||||
|
||||
/*
|
||||
* OEMCrypto_GetKeyData
|
||||
*
|
||||
* Description:
|
||||
* Returns the Key Data field from the Keybox. The Key Data field does not
|
||||
* need to be encrypted by an OEM root key, but may be if desired.
|
||||
*
|
||||
* If the Key Data field was encrypted with an OEM root key when the Keybox
|
||||
* was stored on the device, then this function should decrypt it and return
|
||||
* the clear Key Data. If the Key Data was not encrypted, then this function
|
||||
* should just access and return the clear Key data.
|
||||
*
|
||||
* Parameters:
|
||||
* keyData (out) - pointer to a caller-managed buffer to hold the Key Data
|
||||
* field from the Keybox
|
||||
* dataLength (in/out) - on input, the allocated buffer size. On output,
|
||||
* the number of bytes in KeyData.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any session functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_SHORT_BUFFER the buffer is too small to return the KeyData
|
||||
* OEMCrypto_ERROR_NO_KEYDATA failed to return KeyData
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
||||
size_t *keyDataLength);
|
||||
|
||||
/*
|
||||
* OEMCrypto_GetRandom
|
||||
*
|
||||
* Description:
|
||||
* Return a buffer filled with hardware-generated random bytes. If the
|
||||
* hardware feature does not exist, return OEMCrypto_ERROR_RNG_NOT_SUPPORTED.
|
||||
*
|
||||
* Parameters:
|
||||
* randomData (out) - Pointer to caller-manager buffer that will receive the
|
||||
* random data.
|
||||
* dataLength (in) - Length of the random data buffer in bytes.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any session functions.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_RNG_FAILED failed to generate random number
|
||||
* OEMCrypto_ERROR_RNG_NOT_SUPPORTED function not supported
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
||||
size_t dataLength);
|
||||
|
||||
/*
|
||||
* OEMCrypto_WrapKeybox
|
||||
*
|
||||
* Description:
|
||||
* Wrap the Keybox with a key derived for the device key. If transportKey
|
||||
* is not NULL, the input keybox is encrypted with transportKey. If so,
|
||||
* decrypt the input keybox before wrapping it, using transportKey in AES-CBC
|
||||
* mode with an IV of all zeroes. This function is only needed if the
|
||||
* provisioning method involves saving the keybox to the file system.
|
||||
*
|
||||
* Parameters:
|
||||
* keybox (in) - Pointer to keybox data.
|
||||
* keyboxLength - Length of the Keybox data in bytes
|
||||
* wrappedKeybox (out) - Pointer to wrapped keybox
|
||||
* wrappedKeyboxLength (out) - Pointer to the length of the wrapped keybox in
|
||||
* bytes
|
||||
* transportKey (in) - An optional AES transport key. If provided, the input
|
||||
* keybox is encrypted with this transport key with AES-CBC
|
||||
* and a null IV.
|
||||
* transportKeyLength - number of bytes in the transportKey
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_WRAP_KEYBOX failed to wrap Keybox
|
||||
* OEMCrypto_ERROR_NOT_IMPLEMENTED
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_WrapKeybox(uint8_t *keybox,
|
||||
size_t keyBoxLength,
|
||||
uint8_t *wrappedKeybox,
|
||||
size_t *wrappedKeyBoxLength,
|
||||
uint8_t *transportKey,
|
||||
size_t transportKeyLength);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OEMCRYPTO_DASH_H_
|
||||
@@ -1,28 +0,0 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
LOCAL_SRC_FILES := MockOEMCrypto.cpp \
|
||||
OEMCryptoWrapper.cpp \
|
||||
wvcrc.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES += vendor/widevine/libwvdrmengine/oemcrypto/include \
|
||||
external/openssl/include \
|
||||
external/openssh
|
||||
|
||||
LOCAL_MODULE := libmockoemcrypto
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libstlport \
|
||||
liblog \
|
||||
libcorkscrew \
|
||||
libutils \
|
||||
libz \
|
||||
libcutils \
|
||||
libcrypto \
|
||||
libdl
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -1,419 +0,0 @@
|
||||
/*********************************************************************
|
||||
* MockOEMCrypto.cpp
|
||||
*
|
||||
* (c) Copyright 2011-2012 Google, Inc.
|
||||
*
|
||||
* Mock implementation of OEMCryptoDASH.h used for testing.
|
||||
*********************************************************************/
|
||||
|
||||
#define LOG_TAG "WV.MockOEMCrypto"
|
||||
#include <utils/Log.h>
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include "OEMCryptoDASH.h"
|
||||
#include "MockOEMCrypto.h"
|
||||
|
||||
#include "openssl/rand.h"
|
||||
#include "openssl/aes.h"
|
||||
#include "openssl/cmac.h"
|
||||
#include "openssl/hmac.h"
|
||||
|
||||
#include "wvcrc32.h"
|
||||
|
||||
#include "arpa/inet.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
namespace wvdrm {
|
||||
|
||||
MockOEMCrypto* MockOEMCrypto::sSingleton = NULL;
|
||||
|
||||
static struct BinaryKeybox kDefaultKeybox = {
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID
|
||||
0x74, 0x65, 0x73, 0x74, 0x69, 0x64, 0x00, 0x00, // testid..
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
}, {
|
||||
// key
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}, {
|
||||
// data
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78
|
||||
}, {
|
||||
// Crc
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
}
|
||||
};
|
||||
|
||||
MockOEMCrypto::MockOEMCrypto(BinaryKeybox *keybox) {
|
||||
if (keybox == NULL) keybox = &kDefaultKeybox;
|
||||
memcpy(&mKeybox, keybox, sizeof(BinaryKeybox));
|
||||
mInitialized = false;
|
||||
mClearKeys = true; // XXX -- default to clear keys for initial demo.
|
||||
mMaxId = 0;
|
||||
}
|
||||
|
||||
MockOEMCrypto::~MockOEMCrypto() {
|
||||
}
|
||||
|
||||
OEMCryptoResult MockOEMCrypto::initialize(void) {
|
||||
if (mInitialized) {
|
||||
ALOGE( "[OEMCrypto_Initialize(): failed -- already initialized]\n" );
|
||||
return OEMCrypto_ERROR_INIT_FAILED;
|
||||
}
|
||||
mInitialized = true;
|
||||
ALOGV( "[OEMCrypto_Initialize(): success]\n" );
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockOEMCrypto::terminate(void) {
|
||||
if (!mInitialized) {
|
||||
ALOGE( "[OEMCrypto_Terminate(): failed - not initialized]\n" );
|
||||
return OEMCrypto_ERROR_TERMINATE_FAILED;
|
||||
}
|
||||
mInitialized = false;
|
||||
ALOGV( "[OEMCrypto_Terminate(): success]\n" );
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockOEMCrypto::openSession(OEMCrypto_SESSION *session) {
|
||||
mMaxId++;
|
||||
MockSession *s = new MockSession(mMaxId);
|
||||
Mutex::Autolock lock(mSessionListMutex);
|
||||
mSessions.add(mMaxId, s);
|
||||
*session = mMaxId;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockOEMCrypto::closeSession(OEMCrypto_SESSION session) {
|
||||
Mutex::Autolock lock(mSessionListMutex);
|
||||
ssize_t index = mSessions.indexOfKey(session);
|
||||
if (index < 0) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
mSessions.removeItem(session);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
MockSession *MockOEMCrypto::findSession(OEMCrypto_SESSION session) {
|
||||
Mutex::Autolock lock(mSessionListMutex);
|
||||
ssize_t index = mSessions.indexOfKey(session);
|
||||
if (index < 0) return NULL;
|
||||
return mSessions.valueAt(index).get();
|
||||
}
|
||||
|
||||
MockSession::MockSession(OEMCrypto_SESSION id) {
|
||||
mId = id;
|
||||
mCurrentKey = NULL;
|
||||
mNoKeyLoaded = true;
|
||||
}
|
||||
|
||||
MockSession::~MockSession() {
|
||||
}
|
||||
|
||||
static void aes_128_cmac(const uint8_t key[16], const uint8_t *data, size_t len, uint8_t *dest) {
|
||||
// Quote from openssl tutorial:
|
||||
// "Check out the function print_cmac_gen in the file fips/cmac/fips_cmactest.c"
|
||||
CMAC_CTX *cmac_ctx = CMAC_CTX_new();
|
||||
|
||||
CMAC_Init(cmac_ctx, key, 16, EVP_aes_128_cbc(), 0);
|
||||
CMAC_Update(cmac_ctx, data, len);
|
||||
size_t reslen;
|
||||
unsigned char res[128];
|
||||
if (!CMAC_Final(cmac_ctx, res, &reslen)) {
|
||||
ALOGE("Error calculating CMAC\n");
|
||||
} else if (16 != reslen) {
|
||||
ALOGE("Parameter error, CMAC length = %d\n", reslen);
|
||||
} else {
|
||||
memcpy(dest, res, 16);
|
||||
}
|
||||
CMAC_CTX_free(cmac_ctx);
|
||||
}
|
||||
|
||||
OEMCryptoResult MockSession::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) {
|
||||
uint8_t enc_buffer[enc_key_context_length + 1];
|
||||
memcpy( enc_buffer+1, enc_key_context, enc_key_context_length);
|
||||
enc_buffer[0] = 0x01;
|
||||
aes_128_cmac(MockOEMCrypto::sSingleton->mKeybox.mKey,
|
||||
enc_buffer, enc_key_context_length+1, mEncryptKey);
|
||||
|
||||
uint8_t mac_buffer[mac_key_context_length + 1];
|
||||
memcpy( mac_buffer+1, mac_key_context, mac_key_context_length);
|
||||
mac_buffer[0] = 0x01;
|
||||
aes_128_cmac(MockOEMCrypto::sSingleton->mKeybox.mKey,
|
||||
mac_buffer, mac_key_context_length+1, mMacKey);
|
||||
mac_buffer[0] = 0x02;
|
||||
aes_128_cmac(MockOEMCrypto::sSingleton->mKeybox.mKey,
|
||||
mac_buffer, mac_key_context_length+1, mMacKey+16);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockSession::generateNonce(uint32_t* nonce) {
|
||||
RAND_bytes((uint8_t *)nonce, 4);
|
||||
mNonce = *nonce;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockSession::generateSignature(const uint8_t* message,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length) {
|
||||
if (*signature_length < 32) {
|
||||
*signature_length = 32;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
if ( HMAC( EVP_sha256(), mMacKey, 32, message, message_length,
|
||||
signature, signature_length) ) {
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockSession::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) {
|
||||
|
||||
uint8_t computed_signature[32];
|
||||
if ( ! HMAC( EVP_sha256(), mMacKey, 32, message, message_length,
|
||||
computed_signature, &signature_length) ) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (signature_length != 32 || memcmp(signature, computed_signature, 32)) {
|
||||
ALOGE("Computed signature does not match.");
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
}
|
||||
|
||||
mKeys.clear();
|
||||
mKeys.setCapacity(num_keys);
|
||||
AES_KEY aes_encrypt_key;
|
||||
AES_set_decrypt_key( mEncryptKey, 128, &aes_encrypt_key);
|
||||
OEMCryptoResult result = OEMCrypto_SUCCESS;
|
||||
uint8_t iv[16]; // read/write temporary buffer.
|
||||
for(size_t i=0; i < num_keys; i++) {
|
||||
mKeys.add();
|
||||
mKeys.editItemAt(i).mKeyId.insertArrayAt( key_array[i].key_id, 0, key_array[i].key_id_length);
|
||||
memcpy( iv, key_array[i].key_data_iv, 16);
|
||||
AES_cbc_encrypt(key_array[i].key_data, mKeys.editItemAt(i).mKeyData, 16,
|
||||
&aes_encrypt_key, iv, AES_DECRYPT);
|
||||
|
||||
AES_KEY aes_content_key;
|
||||
AES_set_decrypt_key( mKeys.editItemAt(i).mKeyData, 128, &aes_content_key);
|
||||
memcpy( iv, key_array[i].key_control_iv, 16);
|
||||
AES_cbc_encrypt(key_array[i].key_control, (uint8_t *) &(mKeys.editItemAt(i).mControl), 16,
|
||||
&aes_content_key, iv, AES_DECRYPT);
|
||||
mKeys.editItemAt(i).mControl.mDuration = ntohl(mKeys[i].mControl.mDuration);
|
||||
mKeys.editItemAt(i).mControl.mControl = ntohl(mKeys[i].mControl.mControl);
|
||||
|
||||
ALOGV("Control Flags are 0x%08x", mKeys[i].mControl.mControl);
|
||||
ALOGV("Duration is %d", mKeys[i].mControl.mDuration);
|
||||
|
||||
if (memcmp( mKeys[i].mControl.mVerification, "kctl", 4)) {
|
||||
ALOGE("Key Control block %d verification = 0x%08X, expected kctl=0x%08X", i,
|
||||
*((uint32_t *)(mKeys[i].mControl.mVerification)),
|
||||
*((uint32_t *)("kctl")));
|
||||
result = OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (mKeys[i].mControl.mControl & (1<<3)) { // Nonce enabled.
|
||||
if (mKeys[i].mControl.mNonce != mNonce) {
|
||||
ALOGE("NONCE ERROR for key %d: got: %08X, expected: %08X", i,
|
||||
mKeys[i].mControl.mNonce, mNonce);
|
||||
result = OEMCrypto_ERROR_INVALID_NONCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
mKeys.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy( iv, enc_mac_key_iv, 16);
|
||||
AES_cbc_encrypt(enc_mac_key, mMacKey, 32,
|
||||
&aes_encrypt_key, iv, AES_DECRYPT);
|
||||
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockSession::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) {
|
||||
// XXX
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockSession::selectKey(const uint8_t* key_id,
|
||||
size_t key_id_length) {
|
||||
|
||||
// TODO: handle key_id=0 case. Does that mean following data is not encrypted?
|
||||
// This is the demo version:
|
||||
if (MockOEMCrypto::sSingleton->mClearKeys) {
|
||||
mCurrentKey = &mClearKey;
|
||||
if (mNoKeyLoaded
|
||||
|| mClearKey.mKeyId.size() != 16
|
||||
|| (memcmp(mClearKey.mKeyId.array(), key_id, 16) != 0)) { // Copy it once.
|
||||
|
||||
mClearKey.mKeyId.clear();
|
||||
mClearKey.mKeyId.insertArrayAt( key_id, 0, key_id_length);
|
||||
memcpy(mClearKey.mKeyData, key_id, 16);
|
||||
memcpy(mClearKey.mControl.mVerification, "kctl",4);
|
||||
mClearKey.mControl.mDuration = 0;
|
||||
mClearKey.mControl.mNonce = 0XABACAB00;
|
||||
mClearKey.mControl.mDuration = 0;
|
||||
if (AES_set_encrypt_key(mClearKey.mKeyData, 128, &mClearKey.mKey) < 0) {
|
||||
ALOGE("Could not set encryption key.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
mNoKeyLoaded = false;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
} else {
|
||||
for(size_t i=0; i< mKeys.size(); i++) {
|
||||
if (key_id_length == mKeys[i].mKeyId.size()
|
||||
&& memcmp(key_id, mKeys[i].mKeyId.array(), key_id_length)) {
|
||||
mCurrentKey = &mKeys.editItemAt(i);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
}
|
||||
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
OEMCryptoResult MockSession::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) {
|
||||
if (mCurrentKey == NULL) {
|
||||
ALOGE("SelectKey was not called.");
|
||||
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||
}
|
||||
if (mCurrentKey->mControl.mControl & (1<<4)) { // secure only
|
||||
if (out_buffer->type == OEMCrypto_BufferType_Clear) {
|
||||
ALOGE("Key type is secure only, but buffer is not secure.");
|
||||
return OEMCrypto_ERROR_CONTROL_INVALID;
|
||||
}
|
||||
}
|
||||
uint8_t *dest;
|
||||
if (out_buffer->type == OEMCrypto_BufferType_Direct) {
|
||||
ALOGV("Buffer type is direct. No work to do.");
|
||||
return OEMCrypto_SUCCESS; // XXX -- send directdly to video.
|
||||
} else if (out_buffer->type == OEMCrypto_BufferType_Direct) {
|
||||
dest = (uint8_t *)out_buffer->buffer.secure.handle;
|
||||
if (data_length > out_buffer->buffer.secure.max_length) {
|
||||
ALOGE("Secure Buffer is %d long, but wanted %d.",
|
||||
out_buffer->buffer.secure.max_length, data_length);
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
} else {
|
||||
dest = out_buffer->buffer.clear.address;
|
||||
if (data_length > out_buffer->buffer.clear.max_length) {
|
||||
ALOGE("Buffer is %d long, but wanted %d.",
|
||||
out_buffer->buffer.clear.max_length, data_length);
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
}
|
||||
if (! is_encrypted) {
|
||||
memcpy(dest, data_addr, data_length);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t buffer[offset + data_length];
|
||||
|
||||
unsigned int num = 0;
|
||||
uint8_t ivec[AES_BLOCK_SIZE];
|
||||
uint8_t ecount[AES_BLOCK_SIZE];
|
||||
memset(ecount, 0, AES_BLOCK_SIZE);
|
||||
memcpy(ivec, iv, AES_BLOCK_SIZE);
|
||||
|
||||
AES_ctr128_encrypt(data_addr+(-offset), buffer, data_length+offset,
|
||||
&(mCurrentKey->mKey), ivec, ecount, &num);
|
||||
memcpy(dest, buffer+offset, data_length);
|
||||
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockOEMCrypto::installKeybox(uint8_t *keybox,
|
||||
size_t keyBoxLength) {
|
||||
ALOGV("OEMCryptoResult OEMCrypto_InstallKeybox\n");
|
||||
if (keyBoxLength != 128) { /* 128 = sizeof(struct Debug_Keybox). */
|
||||
ALOGE("The keybox has the wrong length = %d.\n", keyBoxLength);
|
||||
return OEMCrypto_ERROR_WRITE_KEYBOX;
|
||||
}
|
||||
memcpy( & mKeybox, keybox, keyBoxLength);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockOEMCrypto::isKeyboxValid(void) {
|
||||
ALOGV("OEMCryptoResult OEMCrypto_IsKeyboxValid\n");
|
||||
if (strncmp((char*)mKeybox.mMagic, "kbox", 4) != 0) {
|
||||
ALOGE("Magic is not 'kbox'=0x%08x, it is '%4.4s'=0x%08x\n",
|
||||
*((uint32_t *)("kbox")),
|
||||
mKeybox.mMagic, *((uint32_t *)(mKeybox.mMagic)));
|
||||
return OEMCrypto_ERROR_BAD_MAGIC;
|
||||
}
|
||||
uint32_t crc_computed;
|
||||
uint32_t *crc_stored = (uint32_t *)mKeybox.mCrc;
|
||||
// XXX -------------------------------------------------------------------
|
||||
// XXX TODO: verify that CRC in keybox is in network byte order.
|
||||
// XXX -------------------------------------------------------------------
|
||||
crc_computed = ntohl(wvcrc32( mKeybox.mDeviceId, 124));
|
||||
if (crc_computed != *crc_stored) {
|
||||
ALOGE("CRC problem: computed = %08x, stored = %08x.\n", crc_computed, *crc_stored);
|
||||
return OEMCrypto_ERROR_BAD_CRC;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockOEMCrypto::getDeviceID(uint8_t* deviceID,
|
||||
size_t *idLength) {
|
||||
ALOGV("OEMCryptoResult OEMCrypto_GetDeviceID -> %s\n", mKeybox.mDeviceId);
|
||||
size_t size = strnlen( (char *)mKeybox.mDeviceId, 31) + 1;
|
||||
if (*idLength < size) {
|
||||
*idLength = size;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
*idLength = size;
|
||||
memcpy( deviceID, mKeybox.mDeviceId, size );
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult MockOEMCrypto::getKeyData(uint8_t* keyData,
|
||||
size_t *keyDataLength) {
|
||||
ALOGV("OEMCryptoResult OEMCrypto_GetKeyData\n");
|
||||
if (*keyDataLength < sizeof(mKeybox.mData)) {
|
||||
*keyDataLength = sizeof(mKeybox.mData);
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
*keyDataLength = sizeof(mKeybox.mData);
|
||||
memcpy( keyData, mKeybox.mData, sizeof(mKeybox.mData));
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
}; // namespace wvdrm
|
||||
@@ -1,146 +0,0 @@
|
||||
/*********************************************************************
|
||||
* 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_
|
||||
@@ -1,239 +0,0 @@
|
||||
/*********************************************************************
|
||||
* 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;
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*********************************************************************
|
||||
* wvcrc32.cpp
|
||||
*
|
||||
* (c) Copyright 2011-2012 Google, Inc.
|
||||
*
|
||||
* Compte CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
*********************************************************************/
|
||||
|
||||
#include "wvcrc32.h"
|
||||
|
||||
#define INIT_CRC32 0xffffffff
|
||||
|
||||
uint32_t wvrunningcrc32(uint8_t* p_begin, int i_count, uint32_t i_crc) {
|
||||
static uint32_t CRC32[256] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
|
||||
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
||||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
||||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
|
||||
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
|
||||
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
||||
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
||||
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
|
||||
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
|
||||
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
||||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
||||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
||||
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
|
||||
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
|
||||
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
||||
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
||||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
||||
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
|
||||
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
|
||||
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
||||
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
||||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
||||
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
|
||||
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
|
||||
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
||||
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
||||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
||||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
|
||||
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
|
||||
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
||||
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
||||
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
|
||||
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
|
||||
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
||||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
||||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
||||
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
|
||||
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
|
||||
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
||||
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
||||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
||||
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
|
||||
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
|
||||
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
||||
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
||||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
||||
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
|
||||
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
|
||||
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
||||
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
||||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
/* Calculate the CRC */
|
||||
while (i_count > 0) {
|
||||
i_crc = (i_crc << 8) ^ CRC32[(i_crc >> 24) ^ ((uint32_t) * p_begin) ];
|
||||
p_begin++;
|
||||
i_count--;
|
||||
}
|
||||
|
||||
return(i_crc);
|
||||
}
|
||||
|
||||
uint32_t wvcrc32(uint8_t* p_begin, int i_count) {
|
||||
return(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/*********************************************************************
|
||||
* wvcrc32.h
|
||||
*
|
||||
* (c) Copyright 2011-2012 Google, Inc.
|
||||
*
|
||||
* Compte CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef WV_CRC_32_H_
|
||||
#define WV_CRC_32_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t wvcrc32(uint8_t* p_begin, int i_count);
|
||||
|
||||
#endif // WV_MOCK_OEMCRYPTO_H_
|
||||
@@ -1,37 +0,0 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
TestOEMCrypto.cpp
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
bionic \
|
||||
vendor/widevine/libwvdrmengine/oemcrypto/include \
|
||||
vendor/widevine/libwvdrmengine/oemcrypto/mock \
|
||||
external/gtest/include \
|
||||
external/openssl/include \
|
||||
external/stlport/stlport \
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libgtest \
|
||||
libgtest_main \
|
||||
libmockoemcrypto # This is used before a real OEMCrypto library exists.
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libstlport \
|
||||
liblog \
|
||||
libutils \
|
||||
libz \
|
||||
libcutils \
|
||||
libdl \
|
||||
libcrypto \
|
||||
|
||||
LOCAL_MODULE:=test-oemcrypto
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
# Sublibraries Needed:
|
||||
include vendor/widevine/libwvdrmengine/oemcrypto/mock/Android.mk
|
||||
@@ -1,528 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Google, Inc. All Rights Reserved
|
||||
* Requires gtest "mm $ANDROID/external/gtest" before mm in this directory.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <termio.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
#define LOG_TAG "WV.TestOEMCrypto"
|
||||
#include <utils/Log.h>
|
||||
#include <openssl/aes.h>
|
||||
|
||||
#include "OEMCryptoDASH.h" // Unit Test 1: The header file must compile.
|
||||
#include "MockOEMCrypto.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace wvdrm;
|
||||
|
||||
// Make an array of bytes from the string in Hexidecimal.
|
||||
uint8_t * makeArray(const char *hex, size_t *length=NULL) {
|
||||
size_t hex_length = strlen(hex);
|
||||
uint8_t* array = new uint8_t[hex_length/2];
|
||||
size_t hex_index = 0;
|
||||
size_t array_index = 0;
|
||||
while( hex_index < hex_length) {
|
||||
// skip spaces and dashes.
|
||||
if ((hex[hex_index] == '-') || (hex[hex_index] == ' ')) {
|
||||
hex_index++;
|
||||
} else {
|
||||
unsigned int value;
|
||||
sscanf(hex +hex_index, "%02x", &value);
|
||||
array[array_index] = value;
|
||||
hex_index += 2;
|
||||
array_index += 1;
|
||||
}
|
||||
}
|
||||
if (length != NULL) *length = array_index;
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
class OEMCryptoTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize())
|
||||
<< "OEMCrypto_Initialize failed.";
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Terminate())
|
||||
<< "OEMCrypto_Terminate failed.";
|
||||
}
|
||||
public:
|
||||
};
|
||||
|
||||
TEST_F(OEMCryptoTest, MockOEMCrypto_isKeyboxValid) {
|
||||
ASSERT_EQ(OEMCrypto_IsKeyboxValid(), OEMCrypto_SUCCESS);
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoTest, MockOEMCrypto_GenerateDerivedKeys) {
|
||||
OEMCrypto_SESSION session;
|
||||
|
||||
// This is the Eureka test key.
|
||||
static const uint8_t device_key[16] = {
|
||||
0x89, 0xc0, 0x85, 0x0c, 0xbd, 0xcd, 0xa9, 0x62,
|
||||
0xdc, 0x33, 0x2f, 0x96, 0x0e, 0x11, 0xcc, 0x67,
|
||||
};
|
||||
memcpy(MockOEMCrypto::sSingleton->mKeybox.mKey, device_key, 16);
|
||||
|
||||
// This data was captured from a successful licence request using the Eureka
|
||||
// test data. I'm just going to borrow it.
|
||||
uint32_t mac_length = 0;
|
||||
const uint8_t *mac_context = makeArray("41555448454e5449434154494f4e00" // AUTHENTICATION
|
||||
"0a4c0800124800000002000001241f34"
|
||||
"4db9dff087f01d917910f39b60dc7797"
|
||||
"cd97789ee82516dc07a478cb70b8c08c"
|
||||
"299293150aa8e01d2dc9808c98daa16e"
|
||||
"40a0e55dfe3618c7584dd3c7be42122c"
|
||||
"122a0a10303132333435363738394142"
|
||||
"4344454610011a146d79436f6f6c5265"
|
||||
"71756573742c20447564652118012000"
|
||||
"00000100", &mac_length);
|
||||
|
||||
uint32_t enc_length = 0;
|
||||
const uint8_t *enc_context = makeArray("454e4352595054494f4e00" // ENCRYPTION
|
||||
"0a4c0800124800000002000001241f34"
|
||||
"4db9dff087f01d917910f39b60dc7797"
|
||||
"cd97789ee82516dc07a478cb70b8c08c"
|
||||
"299293150aa8e01d2dc9808c98daa16e"
|
||||
"40a0e55dfe3618c7584dd3c7be42122c"
|
||||
"122a0a10303132333435363738394142"
|
||||
"4344454610011a146d79436f6f6c5265"
|
||||
"71756573742c20447564652118012000"
|
||||
"00000080",
|
||||
&enc_length);
|
||||
|
||||
uint32_t key_length = 0;
|
||||
const uint8_t* mac_key = makeArray("d53c018d4a4d2cdb19685d1764845a87"
|
||||
"7474dc020a2d19225d385ce2176bd61c",
|
||||
&key_length);
|
||||
EXPECT_EQ(32, (int)key_length) << "The mac key has the wrong length.";
|
||||
|
||||
const uint8_t* enc_key = makeArray("9713d57529b9f0a84fa06371af92b791",
|
||||
&key_length);
|
||||
EXPECT_EQ(16, (int)key_length) << "The encrypt key has the wrong length";
|
||||
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session))
|
||||
<< "OpenSession not successful.";
|
||||
MockSession* ms = MockOEMCrypto::sSingleton->findSession(session);
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GenerateDerivedKeys(session, mac_context, mac_length,
|
||||
enc_context, enc_length))
|
||||
<< "GenerateDerivedKeys failed.";
|
||||
|
||||
EXPECT_EQ(0, memcmp(ms->mEncryptKey, enc_key, 16));
|
||||
EXPECT_EQ(0, memcmp(ms->mMacKey, mac_key, 32));
|
||||
// printf("\n--------------------------\n");
|
||||
// printf("enc is: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", ms->encrypt_key[i]);
|
||||
// printf("\n");
|
||||
// printf("should: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", enc_key[i]);
|
||||
// printf("\n");
|
||||
// printf("\n--------------------------\n");
|
||||
// printf("mac is: ");
|
||||
// for(int i=0; i < 32; i++) printf(" %02x", ms->mac_key[i]);
|
||||
// printf("\n");
|
||||
// printf("should: ");
|
||||
// for(int i=0; i < 32; i++) printf(" %02x", mac_key[i]);
|
||||
// printf("\n");
|
||||
// printf("\n--------------------------\n");
|
||||
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(session))
|
||||
<< "OEMCrypto_CloseSesion failed.";
|
||||
EXPECT_EQ(OEMCrypto_ERROR_INVALID_SESSION, OEMCrypto_CloseSession(session))
|
||||
<< "Can only close session once. ";
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OEMCryptoTest, MockOEMCrypto_GenerateSignature) {
|
||||
OEMCrypto_SESSION session;
|
||||
// session = 0xdeadbeef;
|
||||
|
||||
size_t message_length = 0;
|
||||
const uint8_t* message = makeArray("0a300a146d79436f6f6c526571756573"
|
||||
"742c2044756465211208ec2316261123"
|
||||
"b47c1a0a507572636861736573212001"
|
||||
"28001204080118011a3612103cb829f7"
|
||||
"c0241dc1434982d9e059ae0d1a20015f"
|
||||
"6157446481b9a32823c2657c9c464fe2"
|
||||
"e6115e96963f1d3c484ce95bff1e2001"
|
||||
"1a2e0a066b657920696412104e793f3b"
|
||||
"ef67bc83f7deacfbf1e9d3851a101308"
|
||||
"fb0835bda16782f902f5c49644d52002"
|
||||
"209580ff8505", &message_length);
|
||||
|
||||
uint8_t signature[32];
|
||||
uint32_t signature_length = 32;
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session));
|
||||
|
||||
// MockSession *ms = MockOEMCrypto::sSingleton->findSession(session);
|
||||
// TODO: enter some test vectors.
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GenerateSignature(session, message, message_length,
|
||||
signature, &signature_length))
|
||||
<< "Generate signature failed.";
|
||||
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(session))
|
||||
<< "OEMCrypto_CloseSesion failed.";
|
||||
delete [] message;
|
||||
|
||||
}
|
||||
|
||||
/* Test a single call to decryptCTR. */
|
||||
TEST_F(OEMCryptoTest, MockOEMCrypto_DecryptContent) {
|
||||
|
||||
|
||||
OEMCrypto_SESSION session;
|
||||
// session = 0xdeadbeef;
|
||||
|
||||
|
||||
// This is the test content from iStreamPlanet.
|
||||
size_t keyid_length = 0;
|
||||
const uint8_t* keyid = makeArray("60061e01-7e57-5e57-ce57-d00d1ed00d1e",
|
||||
&keyid_length);
|
||||
EXPECT_EQ(16, (int)keyid_length) << "Key ID setup incorrectly.";
|
||||
|
||||
size_t key_length = 0;
|
||||
const uint8_t* key = makeArray("1a 8a 20 95 e4 de b2 d2 9e c8 16 ac 7b ae 20 82",
|
||||
&keyid_length);
|
||||
EXPECT_EQ(16, (int)keyid_length) << "Key setup incorrectly.";
|
||||
|
||||
uint8_t * iv = makeArray("000102030405060708090a0b0c0d0e0f");
|
||||
uint8_t ecount[16];
|
||||
uint8_t ivec[16];
|
||||
unsigned int num = 0;
|
||||
memset(ecount, 0, 16);
|
||||
memcpy(ivec, iv, 16);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(key, 128, &aes_key);
|
||||
|
||||
int bytes_read, bytes_written;
|
||||
|
||||
const size_t count = 751; // a nice big number, but not too round.
|
||||
|
||||
unsigned char indata[count];
|
||||
unsigned char outdata[count];
|
||||
memset(indata, 0xAA, count);
|
||||
|
||||
AES_ctr128_encrypt(indata, outdata, count, &aes_key, ivec, ecount, &num);
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session))
|
||||
<< "OEMCrypto_OpenSession failed.";
|
||||
|
||||
// TODO: turn on clear keys. Or rather, allow clear keys to be turned off.
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_SelectKey(session, key, keyid_length))
|
||||
<< "OEMCrypto_SelectKey failed.";
|
||||
|
||||
OEMCrypto_DestBufferDesc out_buffer;
|
||||
out_buffer.type = OEMCrypto_BufferType_Clear;
|
||||
out_buffer.buffer.clear.address = new uint8_t[count];
|
||||
out_buffer.buffer.clear.max_length = count;
|
||||
memset(out_buffer.buffer.clear.address, 0, count);
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_DecryptCTR(session, outdata, count, true, iv,
|
||||
0, // offset=0
|
||||
&out_buffer)) << "OEMCrypto_DecryptCTR";
|
||||
|
||||
EXPECT_EQ(0, memcmp(indata,out_buffer.buffer.clear.address, count))
|
||||
<< "Final result was wrong.";
|
||||
|
||||
// printf("\n--------------------------\n");
|
||||
// printf("ivec : ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", ivec[i]);
|
||||
// printf("\n");
|
||||
// printf("count: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", ecount[i]);
|
||||
// printf(" num=%d\n", num);
|
||||
// printf("Input: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", indata[i]);
|
||||
// printf("\n");
|
||||
// printf("Outpt: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", out_buffer.buffer.clear.address[i]);
|
||||
// printf("\n");
|
||||
// printf("Encry: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", outdata[i]);
|
||||
// printf("\n");
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(session))
|
||||
<< "OEMCrypto_CloseSesion failed.";
|
||||
|
||||
delete [] out_buffer.buffer.clear.address;
|
||||
delete [] keyid;
|
||||
delete [] key;
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OEMCryptoTest, MockOEMCrypto_LoadKeys) {
|
||||
|
||||
|
||||
OEMCrypto_SESSION session;
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session));
|
||||
MockSession* ms = MockOEMCrypto::sSingleton->findSession(session);
|
||||
|
||||
uint32_t key_length = 0;
|
||||
const uint8_t* mac_key = makeArray("d53c018d4a4d2cdb19685d1764845a87"
|
||||
"7474dc020a2d19225d385ce2176bd61c",
|
||||
&key_length);
|
||||
EXPECT_EQ(32, (int)key_length);
|
||||
|
||||
const uint8_t* enc_key = makeArray("9713d57529b9f0a84fa06371af92b791",
|
||||
&key_length);
|
||||
EXPECT_EQ(16, (int)key_length);
|
||||
|
||||
memcpy(ms->mEncryptKey, enc_key, 16);
|
||||
memcpy(ms->mMacKey, mac_key, 32);
|
||||
|
||||
|
||||
uint32_t message_length = 0;
|
||||
const uint8_t* message = makeArray("0a300a146d79436f6f6c526571756573"
|
||||
"742c2044756465211208ec2316261123"
|
||||
"b47c1a0a507572636861736573212001"
|
||||
"28001204080118011a3612103cb829f7"
|
||||
"c0241dc1434982d9e059ae0d1a20015f"
|
||||
"6157446481b9a32823c2657c9c464fe2"
|
||||
"e6115e96963f1d3c484ce95bff1e2001"
|
||||
"1a2e0a066b657920696412104e793f3b"
|
||||
"ef67bc83f7deacfbf1e9d3851a101308"
|
||||
"fb0835bda16782f902f5c49644d52002"
|
||||
"209580ff8505",
|
||||
&message_length);
|
||||
|
||||
uint32_t signature_length = 0;
|
||||
const uint8_t* signature = makeArray("7941857a3a42dd46992dc585e8e3ac01"
|
||||
"5ff491bd190921e5f4212074795575fd",
|
||||
&signature_length);
|
||||
|
||||
uint8_t* enc_mac_key_iv = makeArray("3cb829f7c0241dc1434982d9e059ae0d",
|
||||
&key_length);
|
||||
EXPECT_EQ(16, (int)key_length);
|
||||
|
||||
uint8_t* enc_mac_key = makeArray("015f6157446481b9a32823c2657c9c46"
|
||||
"4fe2e6115e96963f1d3c484ce95bff1e",
|
||||
&key_length);
|
||||
EXPECT_EQ(32, (int)key_length);
|
||||
|
||||
uint8_t* content_key = makeArray("30313233343536373839616263646566",
|
||||
&key_length);
|
||||
uint32_t num_keys = 1;
|
||||
OEMCrypto_KeyObject key_array[1];
|
||||
OEMCrypto_KeyControl control;
|
||||
memcpy( control.mVerification, "kctl", 4);
|
||||
control.mDuration = htonl(60*60*24); // 1 day.
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GenerateNonce(session, &control.mNonce))
|
||||
<< "OEMCrypto_GenerateNonce";
|
||||
control.mControl = htonl(0);
|
||||
|
||||
EXPECT_EQ(16, (int)sizeof(control));
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key( content_key, 128, &aes_key);
|
||||
uint8_t iv[16];
|
||||
uint8_t enc_key_control[16];
|
||||
memset( iv, 0, 16);
|
||||
AES_cbc_encrypt((uint8_t *) &control, enc_key_control, 16, &aes_key,
|
||||
iv, AES_ENCRYPT);
|
||||
|
||||
memset( iv, 0, 16);
|
||||
key_array[0].key_id = makeArray("00000000000000000000000000000000",
|
||||
&(key_array[0].key_id_length));
|
||||
key_array[0].key_data_iv = makeArray("4e793f3bef67bc83f7deacfbf1e9d385"); // given.
|
||||
key_array[0].key_data = makeArray("1308fb0835bda16782f902f5c49644d5"); // given.
|
||||
key_array[0].key_control_iv = iv;
|
||||
key_array[0].key_control = enc_key_control;
|
||||
|
||||
// printf("\n--------------------------\n");
|
||||
// printf(" iv: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", key_array[0].key_control_iv[i]);
|
||||
// printf("\n");
|
||||
// printf(" con: ");
|
||||
// uint8_t *buffer = (uint8_t *) &control;
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", buffer[i]);
|
||||
// printf("\n");
|
||||
// printf("e con: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", key_array[0].key_control[i]);
|
||||
// printf("\n");
|
||||
// printf("u key: ");
|
||||
// for(int i=0; i < 16; i++) printf(" %02x", content_key[i]);
|
||||
// printf("\n");
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadKeys(session, message, message_length,
|
||||
signature, signature_length,
|
||||
enc_mac_key_iv, enc_mac_key, num_keys, key_array))
|
||||
<< "OEMCrypto_LoadKeys";
|
||||
|
||||
uint8_t* new_mac_key = makeArray("faa85bcdd67395e65566c4b891f8a2f0"
|
||||
"2ff983dbad9a4cb44518e8235a4dbb5f",
|
||||
&key_length);
|
||||
EXPECT_EQ(0, memcmp(ms->mMacKey, new_mac_key, 32))
|
||||
<< "New Mac key was not decrypted.";
|
||||
|
||||
// printf("\n--------------------------\n");
|
||||
// printf(" mac: ");
|
||||
// for(int i=0; i < 32; i++) printf(" %02x", ms->mac_key[i]);
|
||||
// printf("\n");
|
||||
// printf("new mac: ");
|
||||
// for(int i=0; i < 32; i++) printf(" %02x", new_mac_key[i]);
|
||||
// printf("\n");
|
||||
|
||||
|
||||
EXPECT_EQ(1, (int)ms->mKeys.size());
|
||||
if (ms->mKeys.size() > 0) {
|
||||
EXPECT_EQ(0, memcmp( ms->mKeys[0].mKeyData, content_key, 16))
|
||||
<< "Key data was not loaded correctly";
|
||||
}
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(session))
|
||||
<< "OEMCrypto_CloseSesion failed.";
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoTest, MockOEMCrypto_RefreshKeys) {
|
||||
|
||||
|
||||
OEMCrypto_SESSION session;
|
||||
// session = 0xdeadbeef;
|
||||
|
||||
const uint8_t* message = NULL;
|
||||
uint32_t message_length = 0;
|
||||
const uint8_t* signature = NULL;
|
||||
uint32_t signature_length = 0;
|
||||
uint32_t num_keys = 0;
|
||||
const OEMCrypto_KeyRefreshObject* key_array = NULL;
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session));
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_RefreshKeys(session, message, message_length,
|
||||
signature, signature_length,
|
||||
num_keys, key_array))
|
||||
<< "OEMCrypto_RefreshKeys";
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(session))
|
||||
<< "OEMCrypto_CloseSesion failed.";
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/***********************************************************************/
|
||||
// TODO: This test is just a stub. We will fix it in a future CL.
|
||||
/***********************************************************************/
|
||||
/***********************************************************************/
|
||||
TEST_F(OEMCryptoTest, MockOEMCrypto_FullVideoTest) {
|
||||
|
||||
uint8_t *keybox = (uint8_t*)"pointer to some valid keybox data";
|
||||
uint32_t keyBoxLength = strlen((char*)keybox);
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_InstallKeybox(keybox, keyBoxLength));
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
|
||||
|
||||
uint8_t deviceID[32] = "0123456789012345";
|
||||
uint32_t idLength = 16;
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetDeviceID(deviceID, &idLength));
|
||||
|
||||
for (uint32_t i = 0; i < idLength; i++)
|
||||
printf("%c", deviceID[i]);
|
||||
printf("\n");
|
||||
|
||||
|
||||
uint8_t* keyData;
|
||||
uint32_t keyDataLength = 72;
|
||||
|
||||
|
||||
|
||||
|
||||
keyData = (uint8_t*)malloc(keyDataLength); //not really but we will malloc it for the stub work
|
||||
|
||||
memset(keyData, 0, keyDataLength);
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetKeyData(keyData, &keyDataLength));
|
||||
|
||||
for (uint32_t i = 0; i < keyDataLength; i++) {
|
||||
if ((i % 15) == 0)
|
||||
printf("\n");
|
||||
printf("0x%02x ", keyData[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
||||
|
||||
printf("request an EMM\n");
|
||||
delete keyData;
|
||||
|
||||
OEMCrypto_SESSION session;
|
||||
// session = 0xdeadbeef;
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session));
|
||||
|
||||
// EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_EnterSecurePlayback());
|
||||
|
||||
|
||||
const uint8_t* emmKey = (const uint8_t*)"0123456789012345";
|
||||
const uint32_t emmKeyLength = 16;
|
||||
|
||||
// EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_SetEntitlementKey(emmKey, emmKeyLength));
|
||||
|
||||
|
||||
const uint8_t* ecm = (const uint8_t*)"01234567890123450123456789012345";
|
||||
const uint32_t length = 32;
|
||||
uint32_t flags;
|
||||
|
||||
// EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_DeriveControlWord(ecm, length, &flags));
|
||||
|
||||
|
||||
|
||||
|
||||
const uint8_t* contentKey = (const uint8_t*)"0123456789012345";
|
||||
const uint32_t contentKeyLength = 16;
|
||||
const uint8_t* control = (const uint8_t*)"abcd";
|
||||
const uint32_t controlLength = 4;
|
||||
|
||||
// EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_SetContentKey(session, contentKey, contentKeyLength, control, controlLength));
|
||||
|
||||
{
|
||||
const uint8_t* iv = (const uint8_t*)"0123456789012345";
|
||||
const uint8_t* input = (const uint8_t*)"some nicely encrypted video data";
|
||||
const uint32_t inputLength = strlen((char*)input);
|
||||
uint32_t output_handle = 0xdeadbeef;
|
||||
uint32_t output_offset = 0;
|
||||
uint32_t outputLength;
|
||||
|
||||
// EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_DecryptVideo(iv, input, inputLength, output_handle, output_offset, &outputLength));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
const uint8_t* iv = (const uint8_t*)"0123456789012345";
|
||||
const uint8_t* input = (const uint8_t*)"some nicely encrypted audio data";
|
||||
const uint32_t inputLength = strlen((char*)input);
|
||||
uint8_t *output;
|
||||
uint32_t outputLength;
|
||||
|
||||
// EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_DecryptAudio(iv, input, inputLength, output, &outputLength));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_ExitSecurePlayback());
|
||||
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(session))
|
||||
<< "OEMCrypto_CloseSesion failed.";
|
||||
}
|
||||
Reference in New Issue
Block a user