Changes from Widevine CDM repo
Squashed commit of these CLs from the widevine cdm repo: Update YT CP server URI to point to the UAT server https://widevine-internal-review.googlesource.com/#/c/9327/ OEMCrypto Version 9 API https://widevine-internal-review.googlesource.com/#/c/9142/ Correct Device ID length in OEMCrypto reference version https://widevine-internal-review.googlesource.com/#/c/8723/ Modify tests to prevent intermittent failures https://widevine-internal-review.googlesource.com/#/c/8982/ Generate a unique license request ID https://widevine-internal-review.googlesource.com/#/c/8721/ Re-enable android timer mechanisms https://widevine-internal-review.googlesource.com/#/c/8833/ Do not close CDM session on removeKeys https://widevine-internal-review.googlesource.com/#/c/8703/ And numerous changes required by Eureka, Steel, and CTE versions of Widevine CDM, as highlighted here: https://widevine-internal-review.googlesource.com/#/c/8596/ https://widevine-internal-review.googlesource.com/#/c/8955/ https://widevine-internal-review.googlesource.com/#/c/8922/ https://widevine-internal-review.googlesource.com/#/c/8890/ https://widevine-internal-review.googlesource.com/#/c/8871/ https://widevine-internal-review.googlesource.com/#/c/8706/ https://widevine-internal-review.googlesource.com/#/c/8425/ Change-Id: Iafd33905227e74eb2132c240b929d2282ab68042
This commit is contained in:
@@ -192,7 +192,8 @@ typedef enum OEMCrypto_Algorithm {
|
||||
#define OEMCrypto_FirstSubsample 1
|
||||
#define OEMCrypto_LastSubsample 2
|
||||
|
||||
/* OEMCrypto_Usage_Entry_Status.
|
||||
/*
|
||||
* OEMCrypto_Usage_Entry_Status.
|
||||
* Valid values for status in the usage table.
|
||||
*/
|
||||
typedef enum OEMCrypto_Usage_Entry_Status {
|
||||
@@ -215,7 +216,8 @@ typedef struct {
|
||||
uint8_t pst[];
|
||||
} OEMCrypto_PST_Report;
|
||||
|
||||
/* OEMCrypto_Clock_Security_Level.
|
||||
/*
|
||||
* OEMCrypto_Clock_Security_Level.
|
||||
* Valid values for clock_security_level in OEMCrypto_PST_Report.
|
||||
*/
|
||||
typedef enum OEMCrypto_Clock_Security_Level {
|
||||
@@ -231,7 +233,9 @@ typedef enum RSA_Padding_Scheme {
|
||||
} RSA_Padding_Scheme;
|
||||
|
||||
|
||||
/* Obfuscation Renames. */
|
||||
/*
|
||||
* Obfuscation Renames.
|
||||
*/
|
||||
#define OEMCrypto_Initialize _oecc01
|
||||
#define OEMCrypto_Terminate _oecc02
|
||||
#define OEMCrypto_InstallKeybox _oecc03
|
||||
@@ -270,23 +274,22 @@ typedef enum RSA_Padding_Scheme {
|
||||
/*
|
||||
* OEMCrypto_Initialize
|
||||
*
|
||||
|
||||
Initializes the crypto hardware.
|
||||
|
||||
Parameters:
|
||||
None
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS success
|
||||
OEMCrypto_ERROR_INIT_FAILED failed to initialize crypto hardware
|
||||
|
||||
Threading:
|
||||
No other function calls will be made while this function is running. This
|
||||
function will not be called again before OEMCrypto_Terminate().
|
||||
|
||||
Version:
|
||||
This method is supported by all API versions.
|
||||
|
||||
* 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
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_Initialize(void);
|
||||
|
||||
@@ -428,8 +431,12 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
|
||||
*
|
||||
* Because the nonce will be used to prevent replay attacks, it is desirable
|
||||
* that a rogue application cannot rapidly call this function until a
|
||||
* repeated nonce is created randomly. With this in mind, we require that
|
||||
* creation of more than 20 nonces will take at least one full second.
|
||||
* repeated nonce is created randomly. With this in mind, if more than 20
|
||||
* nonces are requested within one second, OEMCrypto will return an error
|
||||
* after the 20th and not generate any more nonces for the rest of the
|
||||
* second. After an error, if the application waits at least one second
|
||||
* before requesting more nonces, then OEMCrypto will reset the error
|
||||
* condition and generate valid nonces again.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - crypto session identifier.
|
||||
@@ -1028,52 +1035,52 @@ OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t *keybox,
|
||||
/*
|
||||
* OEMCrypto_IsKeyboxValid
|
||||
*
|
||||
Validates the Widevine Keybox loaded into the security processor device. This
|
||||
method verifies two fields in the keybox:
|
||||
|
||||
Verify the MAGIC field contains a valid signature (such as, ‘k’’b’’o’’x’).
|
||||
|
||||
Compute the CRC using CRC-32-POSIX-1003.2 standard and compare the checksum
|
||||
to the CRC stored in the Keybox. The CRC is computed over the entire Keybox
|
||||
excluding the 4 bytes of the CRC (for example, Keybox[0..123]). For a
|
||||
description of the fields stored in the keybox, see Keybox Definition.
|
||||
|
||||
Parameters:
|
||||
none
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS
|
||||
OEMCrypto_ERROR_BAD_MAGIC
|
||||
OEMCrypto_ERROR_BAD_CRC
|
||||
|
||||
Threading:
|
||||
This function may be called simultaneously with any session functions.
|
||||
|
||||
Version:
|
||||
This method is supported in all API versions.
|
||||
* 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
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_IsKeyboxValid(void);
|
||||
|
||||
/*
|
||||
* OEMCrypto_GetDeviceID
|
||||
*
|
||||
Retrieve DeviceID from the Keybox.
|
||||
|
||||
Parameters:
|
||||
[out] deviceId - pointer to the buffer that receives the Device ID
|
||||
[in/out] idLength – on input, size of the caller’s device ID buffer. On
|
||||
output, the number of bytes written into the buffer.
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS success
|
||||
OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small to return device ID
|
||||
OEMCrypto_ERROR_NO_DEVICEID failed to return Device Id
|
||||
|
||||
Threading:
|
||||
This function may be called simultaneously with any session functions.
|
||||
|
||||
Version:
|
||||
This method is supported in all API versions.
|
||||
* 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
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
||||
size_t *idLength);
|
||||
@@ -1081,24 +1088,31 @@ OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
||||
/*
|
||||
* OEMCrypto_GetKeyData
|
||||
*
|
||||
Return the Key Data field from the Keybox.
|
||||
|
||||
Parameters:
|
||||
[out] keyData - pointer to the buffer to hold the Key Data field from the
|
||||
Keybox
|
||||
[in/out] keyDataLength – on input, the allocated buffer size. On output, the
|
||||
number of bytes in Key Data
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS success
|
||||
OEMCrypto_ERROR_SHORT_BUFFER if the buffer is too small to return KeyData
|
||||
OEMCrypto_ERROR_NO_KEYDATA
|
||||
|
||||
Threading:
|
||||
This function may be called simultaneously with any session functions.
|
||||
|
||||
Version:
|
||||
This method is supported in all API versions.
|
||||
* 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
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
||||
size_t *keyDataLength);
|
||||
@@ -1106,23 +1120,25 @@ OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
||||
/*
|
||||
* OEMCrypto_GetRandom
|
||||
*
|
||||
Returns a buffer filled with hardware-generated random bytes, if supported by
|
||||
the hardware.
|
||||
|
||||
Parameters:
|
||||
[out] randomData - pointer to the buffer that receives random data
|
||||
[in] dataLength - length of the random data buffer in bytes
|
||||
|
||||
Returns:
|
||||
OEMCrypto_SUCCESS success
|
||||
OEMCrypto_ERROR_RNG_FAILED failed to generate random number
|
||||
OEMCrypto_ERROR_RNG_NOT_SUPPORTED function not supported
|
||||
|
||||
Threading:
|
||||
This function may be called simultaneously with any session functions.
|
||||
|
||||
Version:
|
||||
This method is supported in all API versions.
|
||||
* 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
|
||||
*
|
||||
* Version:
|
||||
* This method is supported by all API versions.
|
||||
*/
|
||||
OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
||||
size_t dataLength);
|
||||
@@ -1263,8 +1279,6 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session,
|
||||
* - padding. This is the wrapped key generated
|
||||
* - by OEMCrypto_RewrapDeviceRSAKey.
|
||||
* wrapped_rsa_key_length (in) - length of the wrapped key buffer, in bytes.
|
||||
* wrapped_rsa_key_iv (in) - The initialization vector used to encrypt
|
||||
* - wrapped_rsa_key.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
@@ -1546,41 +1560,25 @@ bool OEMCrypto_SupportsUsageTable();
|
||||
* that entry is “inactive”, then return OEMCrypto_ERROR_INVALID_SESSION.
|
||||
*
|
||||
* Parameters:
|
||||
* current (out) - this is the current HDCP version, based on the device itself,
|
||||
* and the display to which it is connected.
|
||||
* maximum (out) - this is the maximum supported HDCP version for the device,
|
||||
* ignoring any attached device.
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any other functions.
|
||||
* session (in) - crypto session identifier.
|
||||
* in_buffer (in) - pointer to memory containing data to be encrypted.
|
||||
* buffer_length (in) - length of the buffer, in bytes.
|
||||
* iv (in) - IV for encrypting data. Size is specified by the algorithm.
|
||||
* algorithm (in) - Specifies which encryption algorithm to use. See
|
||||
* OEMCrypto_Algorithm for valid values.
|
||||
* out_buffer (out) - pointer to buffer in which encrypted data should be stored.
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
*
|
||||
* Version:
|
||||
* This method changed in API version 9.
|
||||
*/
|
||||
typedef uint8_t OEMCrypto_HDCP_Capability;
|
||||
OEMCryptoResult OEMCrypto_GetHDCPCapability(OEMCrypto_HDCP_Capability *current,
|
||||
OEMCrypto_HDCP_Capability *maximum);
|
||||
|
||||
/*
|
||||
* OEMCrypto_SupportsUsageTable()
|
||||
*
|
||||
* Description:
|
||||
* This is used to determine if the device can support a usage table. Since this
|
||||
* function is spoofable, it is not relied on for security purposes. It is for
|
||||
* information only. The usage table is described in the section above.
|
||||
*
|
||||
* Parameters:
|
||||
* none
|
||||
* OEMCrypto_SUCCESS success
|
||||
* OEMCrypto_ERROR_KEY_EXPIRED
|
||||
* OEMCrypto_ERROR_NO_DEVICE_KEY
|
||||
* OEMCrypto_ERROR_INVALID_SESSION
|
||||
* OEMCrypto_ERROR_INSUFFICIENT_RESOURCES
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
*
|
||||
* Threading:
|
||||
* This function may be called simultaneously with any other functions.
|
||||
*
|
||||
* Returns:
|
||||
* Returns true if the device can maintain a usage table. Returns false otherwise.
|
||||
* This function may be called simultaneously with functions on other sessions,
|
||||
* but not with other functions on this session.
|
||||
*
|
||||
* Version:
|
||||
* This method changed in API version 9.
|
||||
|
||||
@@ -125,7 +125,7 @@ OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t *signature_length,
|
||||
RSA_Padding_Scheme algorithm);
|
||||
RSA_Padding_Scheme padding_scheme);
|
||||
OEMCryptoResult Level3_DeriveKeysFromSessionKey(OEMCrypto_SESSION session,
|
||||
const uint8_t* enc_session_key,
|
||||
size_t enc_session_key_length,
|
||||
|
||||
@@ -31,8 +31,9 @@
|
||||
static const int kPssSaltLength = 20;
|
||||
|
||||
namespace {
|
||||
// Increment counter for AES-CTR
|
||||
void ctr128_inc(uint8_t* counter) {
|
||||
// Increment counter for AES-CTR. The CENC spec specifies we increment only
|
||||
// the low 64 bits of the IV counter, and leave the high 64 bits alone.
|
||||
void ctr128_inc64(uint8_t* counter) {
|
||||
uint32_t n = 16;
|
||||
do {
|
||||
if (++counter[--n] != 0) return;
|
||||
@@ -899,11 +900,11 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
|
||||
const uint8_t* cipher_data,
|
||||
size_t cipher_data_length,
|
||||
bool is_encrypted,
|
||||
void* clear_data,
|
||||
uint8_t* clear_data,
|
||||
BufferType buffer_type) {
|
||||
|
||||
// If the data is clear, we do not need a current key selected.
|
||||
if (!is_encrypted) {
|
||||
if (!is_encrypted && buffer_type != kBufferTypeDirect) {
|
||||
memcpy(reinterpret_cast<uint8_t*>(clear_data),
|
||||
cipher_data, cipher_data_length);
|
||||
return true;
|
||||
@@ -961,20 +962,20 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
|
||||
|
||||
// Encrypt the IV.
|
||||
uint8_t ecount_buf[AES_BLOCK_SIZE];
|
||||
if (block_offset != 0) {
|
||||
// The context is needed only when not starting a new block.
|
||||
AES_encrypt(aes_iv, ecount_buf, &aes_key);
|
||||
ctr128_inc(aes_iv);
|
||||
}
|
||||
|
||||
// Decryption.
|
||||
unsigned int block_offset_cur = block_offset;
|
||||
AES_ctr128_encrypt(
|
||||
cipher_data, reinterpret_cast<uint8_t*>(clear_data), cipher_data_length,
|
||||
&aes_key, aes_iv, ecount_buf, &block_offset_cur);
|
||||
if (block_offset_cur != ((block_offset + cipher_data_length) % AES_BLOCK_SIZE)) {
|
||||
LOGE("[DecryptCTR(): FAILURE: byte offset wrong.]");
|
||||
return false;
|
||||
// The CENC spec specifies we increment only the low 64 bits of the IV
|
||||
// counter, and leave the high 64 bits alone. This is different from the
|
||||
// OpenSSL implementation, which increments the entire 128 bit iv. That is
|
||||
// why we implement the CTR loop ourselves.
|
||||
size_t l = 0;
|
||||
while (l < cipher_data_length) {
|
||||
AES_encrypt(aes_iv, ecount_buf, &aes_key);
|
||||
for (int n = block_offset; n < AES_BLOCK_SIZE && l < cipher_data_length;
|
||||
++n, ++l) {
|
||||
clear_data[l] = cipher_data[l] ^ ecount_buf[n];
|
||||
}
|
||||
ctr128_inc64(aes_iv);
|
||||
block_offset = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ class CryptoEngine {
|
||||
const uint8_t* cipher_data,
|
||||
size_t cipher_data_length,
|
||||
bool is_encrypted,
|
||||
void* clear_data,
|
||||
uint8_t* clear_data,
|
||||
BufferType buffer_type);
|
||||
|
||||
private:
|
||||
|
||||
@@ -95,8 +95,10 @@ bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
|
||||
|
||||
const WidevineKeybox* keybox
|
||||
= reinterpret_cast<const WidevineKeybox*>(buffer);
|
||||
size_t device_id_length
|
||||
= strnlen(reinterpret_cast<const char*>(keybox->device_id_), 32);
|
||||
device_id_.assign(keybox->device_id_,
|
||||
keybox->device_id_ + sizeof(keybox->device_id_));
|
||||
keybox->device_id_ + device_id_length);
|
||||
device_key_.setValue(reinterpret_cast<const char*>(keybox->device_key_),
|
||||
sizeof(keybox->device_key_));
|
||||
device_key_.setType(KEYTYPE_DEVICE);
|
||||
|
||||
@@ -895,7 +895,7 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length,
|
||||
RSA_Padding_Scheme algorithm) {
|
||||
RSA_Padding_Scheme padding_scheme) {
|
||||
if (trace_all_calls) {
|
||||
printf("-- OEMCryptoResult OEMCrypto_GenerateRSASignature()\n");
|
||||
dump_hex("message", message, message_length);
|
||||
@@ -928,7 +928,7 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session,
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
if (algorithm != kSign_RSASSA_PSS) {
|
||||
if (padding_scheme != kSign_RSASSA_PSS) {
|
||||
LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_NOT_IMPLEMENTED]");
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ const size_t kNumKeys = 4;
|
||||
const size_t kBufferMaxLength = 256;
|
||||
#if defined(TEST_SPEED_MULTIPLIER) // Can slow test time limits when
|
||||
// debugging is slowing everything.
|
||||
const int kSpeedMultiplier = TEST_SPEED_MULTIPLIER1;
|
||||
const int kSpeedMultiplier = TEST_SPEED_MULTIPLIER;
|
||||
#else
|
||||
const int kSpeedMultiplier = 1;
|
||||
#endif
|
||||
@@ -910,29 +910,39 @@ class Session {
|
||||
OEMCrypto_GenerateNonce(session_id(), nonce));
|
||||
}
|
||||
|
||||
void GenerateDerivedKeys() {
|
||||
GenerateNonce(&nonce_);
|
||||
vector<uint8_t> mac_context = wvcdm::a2b_hex(
|
||||
void FillDefaultContext(vector<uint8_t>* mac_context,
|
||||
vector<uint8_t>* enc_context) {
|
||||
/* These context strings are normally created by the CDM layer above from
|
||||
a license request message. */
|
||||
*mac_context = wvcdm::a2b_hex(
|
||||
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
|
||||
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
|
||||
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
|
||||
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
|
||||
"34333231180120002a0c31383836373837343035000000000100");
|
||||
vector<uint8_t> enc_context = wvcdm::a2b_hex(
|
||||
"34333231180120002a0c31383836373837343035000000000200");
|
||||
*enc_context = wvcdm::a2b_hex(
|
||||
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
|
||||
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
|
||||
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
|
||||
"0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231"
|
||||
"180120002a0c31383836373837343035000000000080");
|
||||
|
||||
}
|
||||
|
||||
void GenerateDerivedKeys() {
|
||||
GenerateNonce(&nonce_);
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
FillDefaultContext(&mac_context, &enc_context);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GenerateDerivedKeys(
|
||||
session_id(),
|
||||
&mac_context[0], mac_context.size(),
|
||||
&enc_context[0], enc_context.size()));
|
||||
mac_key_server_ = wvcdm::a2b_hex(
|
||||
"9D41F0A77A76E071841C33B06104D106641421E651FBE55F0AED453CDA7713AC");
|
||||
"3CFD60254786AF350B353B4FBB700AB382558400356866BA16C256BCD8C502BF");
|
||||
mac_key_client_ = wvcdm::a2b_hex(
|
||||
"125283F299AF42C191E1A989846B388BB16A6E50B2F67D4F876A3C1F662CD5C8");
|
||||
"A9DE7B3E4E199ED8D1FBC29CD6B4C772CC4538C8B0D3E208B3E76F2EC0FD6F47");
|
||||
enc_key_ = wvcdm::a2b_hex("D0BFC35DA9E33436E81C4229E78CB9F4");
|
||||
}
|
||||
|
||||
@@ -1309,28 +1319,13 @@ class Session {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GenerateRSASessionKey(vector<uint8_t>* enc_session_key,
|
||||
vector<uint8_t>* mac_context,
|
||||
vector<uint8_t>* enc_context) {
|
||||
bool GenerateRSASessionKey(vector<uint8_t>* enc_session_key) {
|
||||
if (!public_rsa_) {
|
||||
cout << "No public RSA key loaded in test code.\n";
|
||||
return false;
|
||||
}
|
||||
vector<uint8_t> session_key = wvcdm::a2b_hex(
|
||||
"6fa479c731d2770b6a61a5d1420bb9d1");
|
||||
*mac_context = wvcdm::a2b_hex(
|
||||
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
|
||||
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
|
||||
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
|
||||
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
|
||||
"34333231180120002a0c31383836373837343035000000000100");
|
||||
*enc_context = wvcdm::a2b_hex(
|
||||
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
|
||||
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
|
||||
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
|
||||
"0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231"
|
||||
"180120002a0c31383836373837343035000000000080");
|
||||
|
||||
enc_session_key->assign(RSA_size(public_rsa_), 0);
|
||||
int status = RSA_public_encrypt(session_key.size(),
|
||||
&session_key[0],
|
||||
@@ -1350,13 +1345,12 @@ class Session {
|
||||
wrapped_rsa_key.size()));
|
||||
GenerateNonce(&nonce_);
|
||||
vector<uint8_t> enc_session_key;
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
ASSERT_TRUE(PreparePublicKey(kTestRSAPublicKey2_2048,
|
||||
sizeof(kTestRSAPublicKey2_2048)));
|
||||
ASSERT_TRUE(GenerateRSASessionKey(&enc_session_key, &mac_context,
|
||||
&enc_context));
|
||||
|
||||
ASSERT_TRUE(GenerateRSASessionKey(&enc_session_key));
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
FillDefaultContext(&mac_context, &enc_context);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_DeriveKeysFromSessionKey(
|
||||
session_id(), &enc_session_key[0], enc_session_key.size(),
|
||||
@@ -1364,9 +1358,9 @@ class Session {
|
||||
&enc_context[0], enc_context.size()));
|
||||
|
||||
mac_key_server_ = wvcdm::a2b_hex(
|
||||
"B09CB4482675123B66F7A8303D803F6042F43404ED3DE020811CFC13BCDF4C65");
|
||||
"1E451E59CB663DA1646194DD28880788ED8ED2EFF913CBD6A0D535D1D5A90381");
|
||||
mac_key_client_ = wvcdm::a2b_hex(
|
||||
"B09CB4482675123B66F7A8303D803F6042F43404ED3DE020811CFC13BCDF4C65");
|
||||
"F9AAE74690909F2207B53B13307FCA096CA8C49CC6DFE3659873CB952889A74B");
|
||||
enc_key_ = wvcdm::a2b_hex("CB477D09014D72C9B8DCE76C33EA43B3");
|
||||
}
|
||||
|
||||
@@ -1553,24 +1547,22 @@ TEST_F(OEMCryptoClientTest, GetDeviceIdShortBuffer) {
|
||||
|
||||
OEMCryptoResult sts;
|
||||
uint8_t dev_id[128];
|
||||
uint32_t req_len = 11;
|
||||
uint32_t req_len = 0;
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
dev_id[i] = 0x55;
|
||||
}
|
||||
dev_id[127] = '\0';
|
||||
size_t dev_id_len = req_len;
|
||||
sts = OEMCrypto_GetDeviceID(dev_id, &dev_id_len);
|
||||
// cout << "GetDeviceIdShortBuffer: sts = " << (int)sts << " request = "
|
||||
// << req_len << " required = " << dev_id_len << endl;
|
||||
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
||||
|
||||
// On short buffer error, function should return minimum buffer length
|
||||
ASSERT_TRUE(dev_id_len > req_len);
|
||||
|
||||
// cout << "NormalGetDeviceId: dev_id = " << dev_id
|
||||
// << " len = " << dev_id_len << endl;
|
||||
|
||||
// Should also return short buffer if passed a zero length and a null buffer.
|
||||
dev_id_len = req_len;
|
||||
sts = OEMCrypto_GetDeviceID(NULL, &dev_id_len);
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
||||
// On short buffer error, function should return minimum buffer length
|
||||
ASSERT_TRUE(dev_id_len > req_len);
|
||||
testTearDown();
|
||||
}
|
||||
|
||||
@@ -2578,6 +2570,98 @@ TEST_F(DISABLED_TestKeybox, DecryptWithOffset) {
|
||||
testTearDown();
|
||||
}
|
||||
|
||||
// Increment counter for AES-CTR. The CENC spec specifies we increment only
|
||||
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This is
|
||||
// different from the OpenSSL implementation, so we implement the CTR loop
|
||||
// ourselves.
|
||||
void ctr128_inc64(uint8_t* counter) {
|
||||
uint32_t n = 16;
|
||||
do {
|
||||
if (++counter[--n] != 0) return;
|
||||
} while (n>8);
|
||||
}
|
||||
vector<uint8_t> EncryptCTR(const vector<uint8_t> &key,
|
||||
const vector<uint8_t> &iv,
|
||||
const vector<uint8_t> &in, size_t block_offset) {
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&key[0], AES_BLOCK_SIZE * 8, &aes_key);
|
||||
|
||||
uint8_t aes_iv[AES_BLOCK_SIZE];
|
||||
memcpy(aes_iv, &iv[0], AES_BLOCK_SIZE);
|
||||
|
||||
// Encrypt the IV.
|
||||
uint8_t ecount_buf[AES_BLOCK_SIZE];
|
||||
|
||||
vector<uint8_t> out( in.size());
|
||||
|
||||
size_t cipher_data_length = in.size();
|
||||
size_t l = 0;
|
||||
while (l < cipher_data_length) {
|
||||
AES_encrypt(aes_iv, ecount_buf, &aes_key);
|
||||
for (int n = block_offset; n < AES_BLOCK_SIZE && l < cipher_data_length;
|
||||
++n, ++l) {
|
||||
out[l] = in[l] ^ ecount_buf[n];
|
||||
}
|
||||
ctr128_inc64(aes_iv);
|
||||
block_offset = 0;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
TEST_F(DISABLED_TestKeybox, DecryptWithNearWrap) {
|
||||
OEMCryptoResult sts;
|
||||
testSetUp();
|
||||
InstallKeybox(kDefaultKeybox, true);
|
||||
Session& s = createSession("ONE");
|
||||
s.open();
|
||||
|
||||
s.GenerateDerivedKeys();
|
||||
s.LoadTestKeys(kDuration, 0, 0);
|
||||
|
||||
// Select the key (from FillSimpleMessage)
|
||||
vector<uint8_t> keyId = wvcdm::a2b_hex("000000000000000000000000");
|
||||
sts = OEMCrypto_SelectKey(s.session_id(),
|
||||
&keyId[0],
|
||||
keyId.size());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
|
||||
// Set up our expected input and output
|
||||
vector<uint8_t> key = wvcdm::a2b_hex("39AD33E5719656069F9EDE9EBBA7A77D");
|
||||
vector<uint8_t> encryptionIv = wvcdm::a2b_hex(
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE");
|
||||
vector<uint8_t> unencryptedData = wvcdm::a2b_hex(
|
||||
"f344d9cfe336c94cf4e3ea9e3446d1427bc02d2debe6dec5b272b8"
|
||||
"a4004b696c4b37e01d7418510abf32bb071f9a4bc0d2ad7e874b648e50bd0e4f"
|
||||
"7085b70bf9ad2c7f37025dd45f93e90304739b1ce098a52e7b99a90f92544a9b"
|
||||
"dca6f49e0006c80a0cfa018600523ad30e483141fe720d045394815d5c875ad4"
|
||||
"b4387b8d09b6119bd0943e51b0b9103034496b3a83ba593f79baa188aeb6e08f"
|
||||
"f6475933e9ce1bb95fbb526424e7966e25830c20da73c65c6fbff110b08e4def"
|
||||
"eae94f98296770275b0d738207a8217cd6118f6ebc6e393428f2268cfedf800e"
|
||||
"a7ebc606471b9a9dfccd1589e86d88fde508261eaf190efd20554ce9e14ff3c9");
|
||||
size_t block_offset = 5;
|
||||
vector<uint8_t> encryptedData = EncryptCTR(key, encryptionIv, unencryptedData,
|
||||
block_offset) ;
|
||||
|
||||
// Describe the output
|
||||
uint8_t outputBuffer[256];
|
||||
OEMCrypto_DestBufferDesc destBuffer;
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = outputBuffer;
|
||||
destBuffer.buffer.clear.max_length = sizeof(outputBuffer);
|
||||
|
||||
// Decrypt the data
|
||||
sts = OEMCrypto_DecryptCTR(s.session_id(), &encryptedData[0],
|
||||
encryptedData.size(), true, &encryptionIv[0],
|
||||
block_offset, &destBuffer,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_EQ(0, memcmp(&unencryptedData[0], outputBuffer,
|
||||
unencryptedData.size()));
|
||||
|
||||
s.close();
|
||||
testTearDown();
|
||||
}
|
||||
|
||||
TEST_F(DISABLED_TestKeybox, DecryptUnencrypted) {
|
||||
OEMCryptoResult sts;
|
||||
testSetUp();
|
||||
@@ -3378,7 +3462,7 @@ class DISABLED_GenericDRMTest : public DISABLED_TestKeybox {
|
||||
uint8_t signature[SHA256_DIGEST_LENGTH];
|
||||
SignBuffer(key_index, clear_buffer_, signature);
|
||||
if( alter_data ) {
|
||||
signature[0] = 43;
|
||||
signature[0] ^= 42;
|
||||
}
|
||||
|
||||
sts = OEMCrypto_SelectKey(s.session_id(),
|
||||
|
||||
Reference in New Issue
Block a user