Merge "Enable OEMCrypto Unit Tests"
This commit is contained in:
committed by
Android (Google) Code Review
commit
4d6ec2ac4c
@@ -37,9 +37,6 @@ class Properties {
|
|||||||
static inline bool oem_crypto_use_userspace_buffers() {
|
static inline bool oem_crypto_use_userspace_buffers() {
|
||||||
return oem_crypto_use_userspace_buffers_;
|
return oem_crypto_use_userspace_buffers_;
|
||||||
}
|
}
|
||||||
static inline bool oem_crypto_require_usage_tables() {
|
|
||||||
return oem_crypto_require_usage_tables_;
|
|
||||||
}
|
|
||||||
static inline bool use_certificates_as_identification() {
|
static inline bool use_certificates_as_identification() {
|
||||||
return use_certificates_as_identification_;
|
return use_certificates_as_identification_;
|
||||||
}
|
}
|
||||||
@@ -83,9 +80,6 @@ class Properties {
|
|||||||
static void set_oem_crypto_use_userspace_buffers(bool flag) {
|
static void set_oem_crypto_use_userspace_buffers(bool flag) {
|
||||||
oem_crypto_use_userspace_buffers_ = flag;
|
oem_crypto_use_userspace_buffers_ = flag;
|
||||||
}
|
}
|
||||||
static void set_oem_crypto_require_usage_tables(bool flag) {
|
|
||||||
oem_crypto_require_usage_tables_ = flag;
|
|
||||||
}
|
|
||||||
static void set_use_certificates_as_identification(bool flag) {
|
static void set_use_certificates_as_identification(bool flag) {
|
||||||
use_certificates_as_identification_ = flag;
|
use_certificates_as_identification_ = flag;
|
||||||
}
|
}
|
||||||
@@ -107,7 +101,6 @@ class Properties {
|
|||||||
static bool oem_crypto_use_secure_buffers_;
|
static bool oem_crypto_use_secure_buffers_;
|
||||||
static bool oem_crypto_use_fifo_;
|
static bool oem_crypto_use_fifo_;
|
||||||
static bool oem_crypto_use_userspace_buffers_;
|
static bool oem_crypto_use_userspace_buffers_;
|
||||||
static bool oem_crypto_require_usage_tables_;
|
|
||||||
static bool use_certificates_as_identification_;
|
static bool use_certificates_as_identification_;
|
||||||
static bool security_level_path_backward_compatibility_support_;
|
static bool security_level_path_backward_compatibility_support_;
|
||||||
static scoped_ptr<CdmClientPropertySetMap> session_property_set_;
|
static scoped_ptr<CdmClientPropertySetMap> session_property_set_;
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ typedef OEMCryptoResult (*L1_RewrapDeviceRSAKey_t)(
|
|||||||
typedef OEMCryptoResult (*L1_LoadDeviceRSAKey_t)(OEMCrypto_SESSION session,
|
typedef OEMCryptoResult (*L1_LoadDeviceRSAKey_t)(OEMCrypto_SESSION session,
|
||||||
const uint8_t* wrapped_rsa_key,
|
const uint8_t* wrapped_rsa_key,
|
||||||
size_t wrapped_rsa_key_length);
|
size_t wrapped_rsa_key_length);
|
||||||
|
typedef OEMCryptoResult (*L1_LoadTestRSAKey_t)();
|
||||||
typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(
|
typedef OEMCryptoResult (*L1_GenerateRSASignature_t)(
|
||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
uint8_t* signature, size_t* signature_length,
|
uint8_t* signature, size_t* signature_length,
|
||||||
@@ -178,6 +179,7 @@ struct FunctionPointers {
|
|||||||
L1_GetRandom_t GetRandom;
|
L1_GetRandom_t GetRandom;
|
||||||
L1_RewrapDeviceRSAKey_t RewrapDeviceRSAKey;
|
L1_RewrapDeviceRSAKey_t RewrapDeviceRSAKey;
|
||||||
L1_LoadDeviceRSAKey_t LoadDeviceRSAKey;
|
L1_LoadDeviceRSAKey_t LoadDeviceRSAKey;
|
||||||
|
L1_LoadTestRSAKey_t LoadTestRSAKey;
|
||||||
L1_GenerateRSASignature_t GenerateRSASignature;
|
L1_GenerateRSASignature_t GenerateRSASignature;
|
||||||
L1_DeriveKeysFromSessionKey_t DeriveKeysFromSessionKey;
|
L1_DeriveKeysFromSessionKey_t DeriveKeysFromSessionKey;
|
||||||
L1_APIVersion_t APIVersion;
|
L1_APIVersion_t APIVersion;
|
||||||
@@ -317,6 +319,8 @@ class Adapter {
|
|||||||
if (level1_.version == 9) {
|
if (level1_.version == 9) {
|
||||||
LOOKUP(GetHDCPCapability_V9, OEMCrypto_GetHDCPCapability_V9);
|
LOOKUP(GetHDCPCapability_V9, OEMCrypto_GetHDCPCapability_V9);
|
||||||
} else {
|
} else {
|
||||||
|
LOOKUP(LoadTestKeybox, OEMCrypto_LoadTestKeybox);
|
||||||
|
LOOKUP(LoadTestRSAKey, OEMCrypto_LoadTestRSAKey);
|
||||||
LOOKUP(QueryKeyControl, OEMCrypto_QueryKeyControl);
|
LOOKUP(QueryKeyControl, OEMCrypto_QueryKeyControl);
|
||||||
LOOKUP(CopyBuffer, OEMCrypto_CopyBuffer);
|
LOOKUP(CopyBuffer, OEMCrypto_CopyBuffer);
|
||||||
LOOKUP(GetHDCPCapability, OEMCrypto_GetHDCPCapability);
|
LOOKUP(GetHDCPCapability, OEMCrypto_GetHDCPCapability);
|
||||||
@@ -329,6 +333,22 @@ class Adapter {
|
|||||||
if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) {
|
if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
uint8_t buffer[1];
|
||||||
|
size_t buffer_size = 0;
|
||||||
|
if (OEMCrypto_ERROR_NOT_IMPLEMENTED == level1_.GetKeyData(buffer,
|
||||||
|
&buffer_size)){
|
||||||
|
// If GetKeyData is not implemented, then the device should only use a
|
||||||
|
// baked in certificate as identification. We will assume that a device
|
||||||
|
// with a bad keybox returns a different error code.
|
||||||
|
if (!wvcdm::Properties::use_certificates_as_identification()) {
|
||||||
|
// If OEMCrypto does not support a keybox, but the CDM code expects
|
||||||
|
// one, things will not work well at all. This is not a fatal error
|
||||||
|
// because we still want to test OEMCrypto in that configuration.
|
||||||
|
LOGE("OEMCrypto uses cert as identification, but cdm does not!");
|
||||||
|
LOGE("This will not work on a production device.");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
wvcdm::File file;
|
wvcdm::File file;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
if (!wvcdm::Properties::GetFactoryKeyboxPath(&filename)) {
|
if (!wvcdm::Properties::GetFactoryKeyboxPath(&filename)) {
|
||||||
@@ -377,6 +397,7 @@ class Adapter {
|
|||||||
level3_.GetRandom = Level3_GetRandom;
|
level3_.GetRandom = Level3_GetRandom;
|
||||||
level3_.RewrapDeviceRSAKey = Level3_RewrapDeviceRSAKey;
|
level3_.RewrapDeviceRSAKey = Level3_RewrapDeviceRSAKey;
|
||||||
level3_.LoadDeviceRSAKey = Level3_LoadDeviceRSAKey;
|
level3_.LoadDeviceRSAKey = Level3_LoadDeviceRSAKey;
|
||||||
|
level3_.LoadTestRSAKey = Level3_LoadTestRSAKey;
|
||||||
level3_.GenerateRSASignature = Level3_GenerateRSASignature;
|
level3_.GenerateRSASignature = Level3_GenerateRSASignature;
|
||||||
level3_.DeriveKeysFromSessionKey = Level3_DeriveKeysFromSessionKey;
|
level3_.DeriveKeysFromSessionKey = Level3_DeriveKeysFromSessionKey;
|
||||||
level3_.APIVersion = Level3_APIVersion;
|
level3_.APIVersion = Level3_APIVersion;
|
||||||
@@ -746,6 +767,14 @@ extern "C" OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
|
|||||||
return OEMCrypto_InstallKeybox(keybox, keyBoxLength, kLevelDefault);
|
return OEMCrypto_InstallKeybox(keybox, keyBoxLength, kLevelDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_LoadTestKeybox() {
|
||||||
|
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
const FunctionPointers* fcn = kAdapter->get(kLevelDefault);
|
||||||
|
if (!fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
|
if (fcn->version < 10) return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
return fcn->LoadTestKeybox();
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_IsKeyboxValid() {
|
extern "C" OEMCryptoResult OEMCrypto_IsKeyboxValid() {
|
||||||
return OEMCrypto_IsKeyboxValid(kLevelDefault);
|
return OEMCrypto_IsKeyboxValid(kLevelDefault);
|
||||||
}
|
}
|
||||||
@@ -793,6 +822,14 @@ extern "C" OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(
|
|||||||
wrapped_rsa_key_length);
|
wrapped_rsa_key_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_LoadTestRSAKey() {
|
||||||
|
if (!kAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
const FunctionPointers* fcn = kAdapter->get(kLevelDefault);
|
||||||
|
if (!fcn) return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
|
if (fcn->version < 10) return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
return fcn->LoadTestRSAKey();
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
uint8_t* signature, size_t* signature_length,
|
uint8_t* signature, size_t* signature_length,
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ namespace wvcdm {
|
|||||||
bool Properties::oem_crypto_use_secure_buffers_;
|
bool Properties::oem_crypto_use_secure_buffers_;
|
||||||
bool Properties::oem_crypto_use_fifo_;
|
bool Properties::oem_crypto_use_fifo_;
|
||||||
bool Properties::oem_crypto_use_userspace_buffers_;
|
bool Properties::oem_crypto_use_userspace_buffers_;
|
||||||
bool Properties::oem_crypto_require_usage_tables_;
|
|
||||||
bool Properties::use_certificates_as_identification_;
|
bool Properties::use_certificates_as_identification_;
|
||||||
bool Properties::security_level_path_backward_compatibility_support_;
|
bool Properties::security_level_path_backward_compatibility_support_;
|
||||||
scoped_ptr<CdmClientPropertySetMap> Properties::session_property_set_;
|
scoped_ptr<CdmClientPropertySetMap> Properties::session_property_set_;
|
||||||
@@ -21,7 +20,6 @@ void Properties::Init() {
|
|||||||
oem_crypto_use_secure_buffers_ = kPropertyOemCryptoUseSecureBuffers;
|
oem_crypto_use_secure_buffers_ = kPropertyOemCryptoUseSecureBuffers;
|
||||||
oem_crypto_use_fifo_ = kPropertyOemCryptoUseFifo;
|
oem_crypto_use_fifo_ = kPropertyOemCryptoUseFifo;
|
||||||
oem_crypto_use_userspace_buffers_ = kPropertyOemCryptoUseUserSpaceBuffers;
|
oem_crypto_use_userspace_buffers_ = kPropertyOemCryptoUseUserSpaceBuffers;
|
||||||
oem_crypto_require_usage_tables_ = kPropertyOemCryptoRequireUsageTable;
|
|
||||||
use_certificates_as_identification_ =
|
use_certificates_as_identification_ =
|
||||||
kPropertyUseCertificatesAsIdentification;
|
kPropertyUseCertificatesAsIdentification;
|
||||||
security_level_path_backward_compatibility_support_ =
|
security_level_path_backward_compatibility_support_ =
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ const bool kPropertyOemCryptoUseSecureBuffers = true;
|
|||||||
const bool kPropertyOemCryptoUseFifo = false;
|
const bool kPropertyOemCryptoUseFifo = false;
|
||||||
const bool kPropertyOemCryptoUseUserSpaceBuffers = false;
|
const bool kPropertyOemCryptoUseUserSpaceBuffers = false;
|
||||||
|
|
||||||
// If true, the unit tests require OEMCrypto to support usage tables.
|
|
||||||
const bool kPropertyOemCryptoRequireUsageTable = true;
|
|
||||||
|
|
||||||
// If false, keyboxes will be used as client identification
|
// If false, keyboxes will be used as client identification
|
||||||
// and passed as the token in the license request
|
// and passed as the token in the license request
|
||||||
const bool kPropertyUseCertificatesAsIdentification = true;
|
const bool kPropertyUseCertificatesAsIdentification = true;
|
||||||
|
|||||||
@@ -294,6 +294,7 @@ typedef enum OEMCrypto_HDCP_Capability {
|
|||||||
#define OEMCrypto_LoadTestKeybox _oecc42
|
#define OEMCrypto_LoadTestKeybox _oecc42
|
||||||
#define OEMCrypto_ForceDeleteUsageEntry _oecc43
|
#define OEMCrypto_ForceDeleteUsageEntry _oecc43
|
||||||
#define OEMCrypto_GetHDCPCapability _oecc44
|
#define OEMCrypto_GetHDCPCapability _oecc44
|
||||||
|
#define OEMCrypto_LoadTestRSAKey _oecc45
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1471,6 +1472,36 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session,
|
|||||||
const uint8_t* wrapped_rsa_key,
|
const uint8_t* wrapped_rsa_key,
|
||||||
size_t wrapped_rsa_key_length);
|
size_t wrapped_rsa_key_length);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OEMCrypto_LoadTestRSAKey
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
|
||||||
|
* Temporarily use the standard test RSA key. This function is only required
|
||||||
|
* for platforms that do not use a keybox, but have an RSA certificate baked
|
||||||
|
* in. This allows a standard suite of unit tests to be run on a production
|
||||||
|
* device without permanently changing the certificate. This RSA key will
|
||||||
|
* persist until the next call to OEMCrypto_Terminate or
|
||||||
|
* OEMCrypto_Initialize.
|
||||||
|
*
|
||||||
|
* The test RSA key can be found in the reference implementation.
|
||||||
|
*
|
||||||
|
* Parameters
|
||||||
|
* none
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* OEMCrypto_SUCCESS success
|
||||||
|
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||||
|
*
|
||||||
|
* Threading
|
||||||
|
* This function is not called simultaneously with any other functions.
|
||||||
|
* It will be called just after OEMCrypto_Initialize().
|
||||||
|
*
|
||||||
|
* Version
|
||||||
|
* This method is added in API version 10.
|
||||||
|
*/
|
||||||
|
OEMCryptoResult OEMCrypto_LoadTestRSAKey();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OEMCrypto_GenerateRSASignature
|
* OEMCrypto_GenerateRSASignature
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ namespace wvoec3 {
|
|||||||
#define Level3_QueryKeyControl _lcc41
|
#define Level3_QueryKeyControl _lcc41
|
||||||
#define Level3_LoadTestKeybox _lcc42
|
#define Level3_LoadTestKeybox _lcc42
|
||||||
#define Level3_ForceDeleteUsageEntry _lcc43
|
#define Level3_ForceDeleteUsageEntry _lcc43
|
||||||
|
#define Level3_LoadTestRSAKey _lcc45
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
@@ -144,6 +145,7 @@ OEMCryptoResult Level3_RewrapDeviceRSAKey(OEMCrypto_SESSION session,
|
|||||||
OEMCryptoResult Level3_LoadDeviceRSAKey(OEMCrypto_SESSION session,
|
OEMCryptoResult Level3_LoadDeviceRSAKey(OEMCrypto_SESSION session,
|
||||||
const uint8_t* wrapped_rsa_key,
|
const uint8_t* wrapped_rsa_key,
|
||||||
size_t wrapped_rsa_key_length);
|
size_t wrapped_rsa_key_length);
|
||||||
|
OEMCryptoResult Level3_LoadTestRSAKey();
|
||||||
OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session,
|
OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session,
|
||||||
const uint8_t* message,
|
const uint8_t* message,
|
||||||
size_t message_length,
|
size_t message_length,
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ bool CryptoEngine::supports_storage() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if the client uses a keybox as the root of trust.
|
||||||
|
bool CryptoEngine::supports_keybox() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns false for mock library to indicate the client does not support
|
// Returns false for mock library to indicate the client does not support
|
||||||
// anti-rollback hardware.
|
// anti-rollback hardware.
|
||||||
bool CryptoEngine::is_anti_rollback_hw_present() {
|
bool CryptoEngine::is_anti_rollback_hw_present() {
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ bool CryptoEngine::supports_storage() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if the client uses a keybox as the root of trust.
|
||||||
|
bool CryptoEngine::supports_keybox() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true to indicate the client does support anti-rollback hardware.
|
// Returns true to indicate the client does support anti-rollback hardware.
|
||||||
bool CryptoEngine::is_anti_rollback_hw_present() {
|
bool CryptoEngine::is_anti_rollback_hw_present() {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Mock implementation of OEMCrypto APIs
|
||||||
|
//
|
||||||
|
// This file contains oemcrypto engine properties that would be for a
|
||||||
|
// level 2 device that does not have persistant storage or a keybox.
|
||||||
|
// Note: this is for illustration only. Production devices are rarely level 2.
|
||||||
|
#include "oemcrypto_engine_mock.h"
|
||||||
|
|
||||||
|
namespace wvoec_mock {
|
||||||
|
|
||||||
|
// If local_display() returns true, we pretend we are using a built-in display,
|
||||||
|
// instead of HDMI or WiFi output.
|
||||||
|
bool CryptoEngine::local_display() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A closed platform is permitted to use clear buffers.
|
||||||
|
bool CryptoEngine::closed_platform() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the HDCP version currently in use.
|
||||||
|
OEMCrypto_HDCP_Capability CryptoEngine::current_hdcp_capability() {
|
||||||
|
return local_display() ? HDCP_NO_DIGITAL_OUTPUT : HDCP_V1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the max HDCP version supported.
|
||||||
|
OEMCrypto_HDCP_Capability CryptoEngine::maximum_hdcp_capability() {
|
||||||
|
return HDCP_NO_DIGITAL_OUTPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the client supports persistent storage of
|
||||||
|
// offline usage table information.
|
||||||
|
bool CryptoEngine::supports_storage() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the client uses a keybox as the root of trust.
|
||||||
|
bool CryptoEngine::supports_keybox() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true to indicate the client does support anti-rollback hardware.
|
||||||
|
bool CryptoEngine::is_anti_rollback_hw_present() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns "L3" for a software only library. L1 is for hardware protected keys
|
||||||
|
// and data paths. L2 is for hardware protected keys but no data path
|
||||||
|
// protection.
|
||||||
|
const char* CryptoEngine::security_level() {
|
||||||
|
return "L2";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace wvoec_mock
|
||||||
@@ -45,6 +45,162 @@ void dump_openssl_error() {
|
|||||||
err, ERR_error_string(err, buffer));
|
err, ERR_error_string(err, buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format
|
||||||
|
// This is the RSA Test Key.
|
||||||
|
static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
|
||||||
|
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30,
|
||||||
|
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||||
|
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||||
|
0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01,
|
||||||
|
0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa7, 0x00,
|
||||||
|
0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a,
|
||||||
|
0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f,
|
||||||
|
0x94, 0x58, 0xdd, 0xde, 0xa7, 0x1f, 0x3c, 0x2c,
|
||||||
|
0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e,
|
||||||
|
0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a,
|
||||||
|
0x2a, 0xaa, 0x9d, 0xb4, 0x4e, 0xfa, 0xa7, 0x6a,
|
||||||
|
0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3,
|
||||||
|
0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f,
|
||||||
|
0x28, 0xda, 0x3f, 0xce, 0x31, 0x7b, 0xfd, 0x06,
|
||||||
|
0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb,
|
||||||
|
0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3,
|
||||||
|
0x29, 0xf2, 0x73, 0x9e, 0x39, 0xd8, 0xf6, 0x6f,
|
||||||
|
0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4,
|
||||||
|
0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04,
|
||||||
|
0xcd, 0x9a, 0x13, 0x8b, 0x54, 0x73, 0x54, 0x25,
|
||||||
|
0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda,
|
||||||
|
0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67,
|
||||||
|
0x98, 0x56, 0x57, 0x54, 0x71, 0xcd, 0x12, 0x7f,
|
||||||
|
0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03,
|
||||||
|
0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53,
|
||||||
|
0xc9, 0x83, 0x06, 0x51, 0x5a, 0x88, 0x65, 0x13,
|
||||||
|
0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b,
|
||||||
|
0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e,
|
||||||
|
0x2d, 0x5f, 0xf8, 0x12, 0x7f, 0xa2, 0xfc, 0xbb,
|
||||||
|
0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01,
|
||||||
|
0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87,
|
||||||
|
0x82, 0x46, 0x0b, 0x3a, 0x77, 0x8f, 0xc0, 0x72,
|
||||||
|
0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed,
|
||||||
|
0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44,
|
||||||
|
0xd3, 0x5b, 0x3d, 0xdb, 0x9c, 0x5e, 0x1b, 0x7b,
|
||||||
|
0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb,
|
||||||
|
0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03,
|
||||||
|
0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x5e,
|
||||||
|
0x79, 0x65, 0x49, 0xa5, 0x76, 0x79, 0xf9, 0x05,
|
||||||
|
0x45, 0x0f, 0xf4, 0x03, 0xbd, 0xa4, 0x7d, 0x29,
|
||||||
|
0xd5, 0xde, 0x33, 0x63, 0xd8, 0xb8, 0xac, 0x97,
|
||||||
|
0xeb, 0x3f, 0x5e, 0x55, 0xe8, 0x7d, 0xf3, 0xe7,
|
||||||
|
0x3b, 0x5c, 0x2d, 0x54, 0x67, 0x36, 0xd6, 0x1d,
|
||||||
|
0x46, 0xf5, 0xca, 0x2d, 0x8b, 0x3a, 0x7e, 0xdc,
|
||||||
|
0x45, 0x38, 0x79, 0x7e, 0x65, 0x71, 0x5f, 0x1c,
|
||||||
|
0x5e, 0x79, 0xb1, 0x40, 0xcd, 0xfe, 0xc5, 0xe1,
|
||||||
|
0xc1, 0x6b, 0x78, 0x04, 0x4e, 0x8e, 0x79, 0xf9,
|
||||||
|
0x0a, 0xfc, 0x79, 0xb1, 0x5e, 0xb3, 0x60, 0xe3,
|
||||||
|
0x68, 0x7b, 0xc6, 0xef, 0xcb, 0x71, 0x4c, 0xba,
|
||||||
|
0xa7, 0x79, 0x5c, 0x7a, 0x81, 0xd1, 0x71, 0xe7,
|
||||||
|
0x00, 0x21, 0x13, 0xe2, 0x55, 0x69, 0x0e, 0x75,
|
||||||
|
0xbe, 0x09, 0xc3, 0x4f, 0xa9, 0xc9, 0x68, 0x22,
|
||||||
|
0x0e, 0x97, 0x8d, 0x89, 0x6e, 0xf1, 0xe8, 0x88,
|
||||||
|
0x7a, 0xd1, 0xd9, 0x09, 0x5d, 0xd3, 0x28, 0x78,
|
||||||
|
0x25, 0x0b, 0x1c, 0x47, 0x73, 0x25, 0xcc, 0x21,
|
||||||
|
0xb6, 0xda, 0xc6, 0x24, 0x5a, 0xd0, 0x37, 0x14,
|
||||||
|
0x46, 0xc7, 0x94, 0x69, 0xe4, 0x43, 0x6f, 0x47,
|
||||||
|
0xde, 0x00, 0x33, 0x4d, 0x8f, 0x95, 0x72, 0xfa,
|
||||||
|
0x68, 0x71, 0x17, 0x66, 0x12, 0x1a, 0x87, 0x27,
|
||||||
|
0xf7, 0xef, 0x7e, 0xe0, 0x35, 0x58, 0xf2, 0x4d,
|
||||||
|
0x6f, 0x35, 0x01, 0xaa, 0x96, 0xe2, 0x3d, 0x51,
|
||||||
|
0x13, 0x86, 0x9c, 0x79, 0xd0, 0xb7, 0xb6, 0x64,
|
||||||
|
0xe8, 0x86, 0x65, 0x50, 0xbf, 0xcc, 0x27, 0x53,
|
||||||
|
0x1f, 0x51, 0xd4, 0xca, 0xbe, 0xf5, 0xdd, 0x77,
|
||||||
|
0x70, 0x98, 0x0f, 0xee, 0xa8, 0x96, 0x07, 0x5f,
|
||||||
|
0x45, 0x6a, 0x7a, 0x0d, 0x03, 0x9c, 0x4f, 0x29,
|
||||||
|
0xf6, 0x06, 0xf3, 0x5d, 0x58, 0x6c, 0x47, 0xd0,
|
||||||
|
0x96, 0xa9, 0x03, 0x17, 0xbb, 0x4e, 0xc9, 0x21,
|
||||||
|
0xe0, 0xac, 0xcd, 0x78, 0x78, 0xb2, 0xfe, 0x81,
|
||||||
|
0xb2, 0x51, 0x53, 0xa6, 0x1f, 0x98, 0x45, 0x02,
|
||||||
|
0x81, 0x81, 0x00, 0xcf, 0x73, 0x8c, 0xbe, 0x6d,
|
||||||
|
0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75,
|
||||||
|
0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9,
|
||||||
|
0x64, 0x60, 0x8c, 0x43, 0xeb, 0x85, 0xab, 0x04,
|
||||||
|
0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda,
|
||||||
|
0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4,
|
||||||
|
0xde, 0x51, 0x4b, 0xb6, 0x51, 0x86, 0x7b, 0xd0,
|
||||||
|
0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f,
|
||||||
|
0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13,
|
||||||
|
0x93, 0xd7, 0x9c, 0x27, 0x80, 0xb7, 0x1e, 0x64,
|
||||||
|
0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8,
|
||||||
|
0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96,
|
||||||
|
0x90, 0x8f, 0xa2, 0x16, 0x22, 0x6a, 0xcc, 0x48,
|
||||||
|
0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44,
|
||||||
|
0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27,
|
||||||
|
0x33, 0x85, 0x26, 0x60, 0x48, 0x16, 0xcb, 0xef,
|
||||||
|
0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce,
|
||||||
|
0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87,
|
||||||
|
0xc3, 0x41, 0x45, 0x97, 0xb1, 0x49, 0xc2, 0x19,
|
||||||
|
0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28,
|
||||||
|
0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb,
|
||||||
|
0xbb, 0xdb, 0xfd, 0x11, 0x9d, 0x17, 0x68, 0x78,
|
||||||
|
0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3,
|
||||||
|
0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54,
|
||||||
|
0x91, 0x99, 0xe5, 0x91, 0x32, 0x2d, 0xeb, 0x3f,
|
||||||
|
0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41,
|
||||||
|
0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42,
|
||||||
|
0x58, 0xf4, 0xd0, 0xb2, 0x74, 0x1d, 0x8e, 0x87,
|
||||||
|
0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd,
|
||||||
|
0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53,
|
||||||
|
0xda, 0xfb, 0xed, 0x83, 0x51, 0x67, 0xa9, 0x55,
|
||||||
|
0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17,
|
||||||
|
0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02,
|
||||||
|
0x81, 0x80, 0x67, 0x9c, 0x32, 0x83, 0x39, 0x57,
|
||||||
|
0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0,
|
||||||
|
0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97,
|
||||||
|
0xf3, 0x90, 0x9a, 0xab, 0x9b, 0x0b, 0x1b, 0x43,
|
||||||
|
0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c,
|
||||||
|
0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80,
|
||||||
|
0xb8, 0xe1, 0xb3, 0xa1, 0x6c, 0x25, 0x92, 0xe4,
|
||||||
|
0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f,
|
||||||
|
0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81,
|
||||||
|
0x20, 0x82, 0xa1, 0x48, 0x2c, 0x2d, 0x45, 0xdc,
|
||||||
|
0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41,
|
||||||
|
0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54,
|
||||||
|
0xc8, 0x28, 0x10, 0x1e, 0x08, 0x71, 0x16, 0xd8,
|
||||||
|
0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5,
|
||||||
|
0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf,
|
||||||
|
0x35, 0x95, 0x41, 0x29, 0x40, 0x19, 0x83, 0x35,
|
||||||
|
0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b,
|
||||||
|
0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae,
|
||||||
|
0x50, 0x76, 0x63, 0x94, 0x49, 0x4c, 0xad, 0x10,
|
||||||
|
0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8,
|
||||||
|
0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b,
|
||||||
|
0x8a, 0xa2, 0xb9, 0x8f, 0xce, 0xec, 0x5e, 0x61,
|
||||||
|
0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a,
|
||||||
|
0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69,
|
||||||
|
0xe4, 0x8b, 0x01, 0x06, 0x59, 0x22, 0xfa, 0x34,
|
||||||
|
0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a,
|
||||||
|
0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26,
|
||||||
|
0x6c, 0xfa, 0x2b, 0xd9, 0x83, 0x5a, 0x2d, 0x0c,
|
||||||
|
0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a,
|
||||||
|
0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3,
|
||||||
|
0x66, 0xff, 0x1c, 0x1b, 0xc8, 0x96, 0x76, 0xe8,
|
||||||
|
0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8,
|
||||||
|
0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80,
|
||||||
|
0x2c, 0x7c, 0xad, 0x1e, 0x75, 0xf6, 0x69, 0x1d,
|
||||||
|
0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65,
|
||||||
|
0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57,
|
||||||
|
0xae, 0xb7, 0x65, 0x2c, 0x52, 0xf9, 0xe4, 0xc7,
|
||||||
|
0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33,
|
||||||
|
0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50,
|
||||||
|
0x75, 0x61, 0x96, 0x86, 0x4b, 0xb6, 0x2b, 0xad,
|
||||||
|
0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35,
|
||||||
|
0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a,
|
||||||
|
0xd3, 0x29, 0x23, 0x02, 0x60, 0xf7, 0xab, 0x30,
|
||||||
|
0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4,
|
||||||
|
0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18,
|
||||||
|
0xf4, 0xd4, 0x52, 0x95, 0x00, 0xae, 0x84, 0x6b,
|
||||||
|
0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde,
|
||||||
|
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18,
|
||||||
|
0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03
|
||||||
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace wvoec_mock {
|
namespace wvoec_mock {
|
||||||
@@ -85,6 +241,10 @@ void SessionKeyTable::UpdateDuration(const KeyControlBlock& control) {
|
|||||||
|
|
||||||
SessionContext::~SessionContext() {
|
SessionContext::~SessionContext() {
|
||||||
if (usage_entry_) usage_entry_->set_session(NULL);
|
if (usage_entry_) usage_entry_->set_session(NULL);
|
||||||
|
if (rsa_key_ && rsa_key_ != ce_->rsa_key()) {
|
||||||
|
RSA_free(rsa_key_);
|
||||||
|
rsa_key_ = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal utility function to derive key using CMAC-128
|
// Internal utility function to derive key using CMAC-128
|
||||||
@@ -999,7 +1159,8 @@ bool SessionContext::IsUsageEntryValid() {
|
|||||||
void SessionContext::ReleaseUsageEntry() { usage_entry_ = NULL; }
|
void SessionContext::ReleaseUsageEntry() { usage_entry_ = NULL; }
|
||||||
|
|
||||||
CryptoEngine::CryptoEngine()
|
CryptoEngine::CryptoEngine()
|
||||||
: current_session_(NULL), usage_table_(new UsageTable(this)) {
|
: current_session_(NULL), use_test_keybox_(false),
|
||||||
|
usage_table_(new UsageTable(this)), rsa_key_(NULL) {
|
||||||
ERR_load_crypto_strings();
|
ERR_load_crypto_strings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1012,13 +1173,73 @@ CryptoEngine::~CryptoEngine() {
|
|||||||
void CryptoEngine::Terminate() {
|
void CryptoEngine::Terminate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboxError CryptoEngine::ValidateKeybox() { return keybox_.Validate(); }
|
KeyboxError CryptoEngine::ValidateKeybox() { return keybox().Validate(); }
|
||||||
|
|
||||||
|
bool CryptoEngine::LoadTestRSAKey() {
|
||||||
|
if (rsa_key_) {
|
||||||
|
RSA_free(rsa_key_);
|
||||||
|
rsa_key_ = NULL;
|
||||||
|
}
|
||||||
|
uint8_t *pkcs8_rsa_key
|
||||||
|
= const_cast<uint8_t *>(kTestRSAPKCS8PrivateKeyInfo2_2048);
|
||||||
|
size_t rsa_key_length = sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048);
|
||||||
|
BIO *bio = BIO_new_mem_buf(pkcs8_rsa_key, rsa_key_length);
|
||||||
|
if ( bio == NULL ) {
|
||||||
|
LOGE("[LoadTestRSAKey(): Could not allocate bio buffer]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool success = true;
|
||||||
|
PKCS8_PRIV_KEY_INFO *pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL);
|
||||||
|
if (pkcs8_pki == NULL) {
|
||||||
|
LOGE("d2i_PKCS8_PRIV_KEY_INFO_bio returned NULL.");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
EVP_PKEY *evp = NULL;
|
||||||
|
if (success) {
|
||||||
|
evp = EVP_PKCS82PKEY(pkcs8_pki);
|
||||||
|
if (evp == NULL) {
|
||||||
|
LOGE("EVP_PKCS82PKEY returned NULL.");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
rsa_key_ = EVP_PKEY_get1_RSA(evp);
|
||||||
|
if (rsa_key_ == NULL) {
|
||||||
|
LOGE("PrivateKeyInfo did not contain an RSA key.");
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (evp != NULL) {
|
||||||
|
EVP_PKEY_free(evp);
|
||||||
|
}
|
||||||
|
if (pkcs8_pki != NULL) {
|
||||||
|
PKCS8_PRIV_KEY_INFO_free(pkcs8_pki);
|
||||||
|
}
|
||||||
|
BIO_free(bio);
|
||||||
|
if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (RSA_check_key(rsa_key_)) {
|
||||||
|
case 1: // valid.
|
||||||
|
return true;
|
||||||
|
case 0: // not valid.
|
||||||
|
LOGE("[LoadTestRSAKey(): rsa key not valid]");
|
||||||
|
dump_openssl_error();
|
||||||
|
return false;
|
||||||
|
default: // -1 == check failed.
|
||||||
|
LOGE("[LoadTestRSAKey(): error checking rsa key]");
|
||||||
|
dump_openssl_error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
SessionId CryptoEngine::CreateSession() {
|
SessionId CryptoEngine::CreateSession() {
|
||||||
wvcdm::AutoLock lock(session_table_lock_);
|
wvcdm::AutoLock lock(session_table_lock_);
|
||||||
static int unique_id = 1;
|
static int unique_id = 1;
|
||||||
SessionId sid = (SessionId)++unique_id;
|
SessionId sid = (SessionId)++unique_id;
|
||||||
SessionContext* sctx = new SessionContext(this, sid);
|
SessionContext* sctx = new SessionContext(this, sid, this->rsa_key_);
|
||||||
sessions_[sid] = sctx;
|
sessions_[sid] = sctx;
|
||||||
return sid;
|
return sid;
|
||||||
}
|
}
|
||||||
@@ -1124,11 +1345,6 @@ OEMCryptoResult SessionContext::DecryptCTR(
|
|||||||
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||||
}
|
}
|
||||||
const uint8_t* key_u8 = &content_key[0];
|
const uint8_t* key_u8 = &content_key[0];
|
||||||
AES_KEY aes_key;
|
|
||||||
if (AES_set_encrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) {
|
|
||||||
LOGE("[DecryptCTR(): FAILURE]");
|
|
||||||
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer_type == OEMCrypto_BufferType_Direct) {
|
if (buffer_type == OEMCrypto_BufferType_Direct) {
|
||||||
// For reference implementation, we quietly drop the decrypted direct video.
|
// For reference implementation, we quietly drop the decrypted direct video.
|
||||||
@@ -1144,15 +1360,21 @@ OEMCryptoResult SessionContext::DecryptCTR(
|
|||||||
uint8_t aes_iv[AES_BLOCK_SIZE];
|
uint8_t aes_iv[AES_BLOCK_SIZE];
|
||||||
memcpy(aes_iv, &iv[0], AES_BLOCK_SIZE);
|
memcpy(aes_iv, &iv[0], AES_BLOCK_SIZE);
|
||||||
|
|
||||||
// Encrypt the IV.
|
|
||||||
uint8_t ecount_buf[AES_BLOCK_SIZE];
|
|
||||||
|
|
||||||
// The CENC spec specifies we increment only the low 64 bits of the IV
|
// 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
|
// counter, and leave the high 64 bits alone. This is different from the
|
||||||
// OpenSSL implementation, which increments the entire 128 bit iv. That is
|
// OpenSSL implementation, which increments the entire 128 bit iv. That is
|
||||||
// why we implement the CTR loop ourselves.
|
// why we implement the CTR loop ourselves.
|
||||||
size_t l = 0;
|
size_t l = 0;
|
||||||
while (l < cipher_data_length) {
|
if (block_offset > 0 && l < cipher_data_length) {
|
||||||
|
|
||||||
|
// Encrypt the IV.
|
||||||
|
uint8_t ecount_buf[AES_BLOCK_SIZE];
|
||||||
|
|
||||||
|
AES_KEY aes_key;
|
||||||
|
if (AES_set_encrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) {
|
||||||
|
LOGE("[DecryptCTR(): FAILURE]");
|
||||||
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||||
|
}
|
||||||
AES_encrypt(aes_iv, ecount_buf, &aes_key);
|
AES_encrypt(aes_iv, ecount_buf, &aes_key);
|
||||||
for (int n = block_offset; n < AES_BLOCK_SIZE && l < cipher_data_length;
|
for (int n = block_offset; n < AES_BLOCK_SIZE && l < cipher_data_length;
|
||||||
++n, ++l) {
|
++n, ++l) {
|
||||||
@@ -1161,6 +1383,55 @@ OEMCryptoResult SessionContext::DecryptCTR(
|
|||||||
ctr128_inc64(aes_iv);
|
ctr128_inc64(aes_iv);
|
||||||
block_offset = 0;
|
block_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t remaining = cipher_data_length - l;
|
||||||
|
int out_len = 0;
|
||||||
|
|
||||||
|
while (remaining) {
|
||||||
|
EVP_CIPHER_CTX ctx;
|
||||||
|
EVP_CIPHER_CTX_init(&ctx);
|
||||||
|
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
||||||
|
if (!EVP_DecryptInit_ex(&ctx, EVP_aes_128_ctr(), NULL, key_u8, aes_iv)) {
|
||||||
|
LOGE("[DecryptCTR(): EVP_INIT ERROR]");
|
||||||
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the MSB of the counter portion of the initialization vector. If the
|
||||||
|
// value is 0xFF the counter is near wrapping. In this case we calculate
|
||||||
|
// the number of bytes we can safely decrypt before the counter wraps.
|
||||||
|
uint64_t decrypt_length = 0;
|
||||||
|
if (aes_iv[8] == 0xFF) {
|
||||||
|
uint64_t bytes_before_iv_wrap = (~wvcdm::ntohll64(
|
||||||
|
*reinterpret_cast<uint64_t*>(&aes_iv[8])) + 1) * AES_BLOCK_SIZE;
|
||||||
|
decrypt_length =
|
||||||
|
bytes_before_iv_wrap < remaining ? bytes_before_iv_wrap : remaining;
|
||||||
|
} else {
|
||||||
|
decrypt_length = remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EVP_DecryptUpdate(&ctx, &clear_data[l], &out_len, &cipher_data[l],
|
||||||
|
decrypt_length)) {
|
||||||
|
LOGE("[DecryptCTR(): EVP_UPDATE_ERROR]");
|
||||||
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||||
|
}
|
||||||
|
l += decrypt_length;
|
||||||
|
remaining = cipher_data_length - l;
|
||||||
|
|
||||||
|
int final;
|
||||||
|
if (!EVP_DecryptFinal_ex(&ctx, &clear_data[cipher_data_length - remaining],
|
||||||
|
&final)) {
|
||||||
|
LOGE("[DecryptCTR(): EVP_FINAL_ERROR]");
|
||||||
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||||
|
}
|
||||||
|
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||||
|
|
||||||
|
// If remaining is not zero, reset the iv before the second pass.
|
||||||
|
if (remaining) {
|
||||||
|
memcpy(aes_iv, &iv[0], AES_BLOCK_SIZE);
|
||||||
|
memset(&aes_iv[8], 0, AES_BLOCK_SIZE / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,12 +76,12 @@ class SessionContext {
|
|||||||
SessionContext() {}
|
SessionContext() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SessionContext(CryptoEngine* ce, SessionId sid)
|
explicit SessionContext(CryptoEngine* ce, SessionId sid, RSA* rsa_key)
|
||||||
: valid_(true),
|
: valid_(true),
|
||||||
ce_(ce),
|
ce_(ce),
|
||||||
id_(sid),
|
id_(sid),
|
||||||
current_content_key_(NULL),
|
current_content_key_(NULL),
|
||||||
rsa_key_(NULL),
|
rsa_key_(rsa_key),
|
||||||
allowed_schemes_(kSign_RSASSA_PSS),
|
allowed_schemes_(kSign_RSASSA_PSS),
|
||||||
usage_entry_(NULL) {}
|
usage_entry_(NULL) {}
|
||||||
~SessionContext();
|
~SessionContext();
|
||||||
@@ -225,7 +225,11 @@ class CryptoEngine {
|
|||||||
void Terminate();
|
void Terminate();
|
||||||
|
|
||||||
KeyboxError ValidateKeybox();
|
KeyboxError ValidateKeybox();
|
||||||
WvKeybox& keybox() { return keybox_; }
|
WvKeybox& keybox() { return use_test_keybox_ ? test_keybox_ : keybox_; }
|
||||||
|
WvKeybox& real_keybox() { return keybox_; }
|
||||||
|
void UseTestKeybox() { use_test_keybox_ = true; }
|
||||||
|
RSA* rsa_key() { return rsa_key_; }
|
||||||
|
bool LoadTestRSAKey();
|
||||||
|
|
||||||
SessionId CreateSession();
|
SessionId CreateSession();
|
||||||
|
|
||||||
@@ -252,6 +256,7 @@ class CryptoEngine {
|
|||||||
bool local_display();
|
bool local_display();
|
||||||
bool closed_platform();
|
bool closed_platform();
|
||||||
bool supports_storage();
|
bool supports_storage();
|
||||||
|
bool supports_keybox();
|
||||||
bool is_anti_rollback_hw_present();
|
bool is_anti_rollback_hw_present();
|
||||||
const char* security_level();
|
const char* security_level();
|
||||||
|
|
||||||
@@ -259,8 +264,11 @@ class CryptoEngine {
|
|||||||
SessionContext* current_session_;
|
SessionContext* current_session_;
|
||||||
ActiveSessions sessions_;
|
ActiveSessions sessions_;
|
||||||
WvKeybox keybox_;
|
WvKeybox keybox_;
|
||||||
|
WvTestKeybox test_keybox_;
|
||||||
wvcdm::Lock session_table_lock_;
|
wvcdm::Lock session_table_lock_;
|
||||||
UsageTable* usage_table_;
|
UsageTable* usage_table_;
|
||||||
|
bool use_test_keybox_;
|
||||||
|
RSA* rsa_key_; // If no keybox, this is baked in certificate.
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,42 @@
|
|||||||
|
|
||||||
namespace wvoec_mock {
|
namespace wvoec_mock {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const WidevineKeybox kTestKeybox = {
|
||||||
|
// Sample keybox used for test vectors
|
||||||
|
{
|
||||||
|
// deviceID
|
||||||
|
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey01
|
||||||
|
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||||
|
}, {
|
||||||
|
// key
|
||||||
|
0xfb, 0xda, 0x04, 0x89, 0xa1, 0x58, 0x16, 0x0e,
|
||||||
|
0xa4, 0x02, 0xe9, 0x29, 0xe3, 0xb6, 0x8f, 0x04,
|
||||||
|
}, {
|
||||||
|
// data
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
||||||
|
0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1,
|
||||||
|
0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd,
|
||||||
|
0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2, 0xd8,
|
||||||
|
0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64,
|
||||||
|
0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8,
|
||||||
|
0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14, 0xa8,
|
||||||
|
0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64,
|
||||||
|
0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39,
|
||||||
|
}, {
|
||||||
|
// magic
|
||||||
|
0x6b, 0x62, 0x6f, 0x78,
|
||||||
|
}, {
|
||||||
|
// Crc
|
||||||
|
0x0a, 0x7a, 0x2c, 0x35,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
WvKeybox::WvKeybox() {
|
WvKeybox::WvKeybox() {
|
||||||
valid_ = Prepare();
|
valid_ = Prepare();
|
||||||
}
|
}
|
||||||
@@ -66,4 +102,9 @@ bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WvTestKeybox::WvTestKeybox() {
|
||||||
|
InstallKeybox(reinterpret_cast<const uint8_t*>(&kTestKeybox),
|
||||||
|
sizeof(kTestKeybox));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvoec_mock
|
} // namespace wvoec_mock
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ class WvKeybox {
|
|||||||
uint8_t crc_[4];
|
uint8_t crc_[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WvTestKeybox : public WvKeybox {
|
||||||
|
public:
|
||||||
|
WvTestKeybox();
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace wvoec_mock
|
} // namespace wvoec_mock
|
||||||
|
|
||||||
#endif // OEMCRYPTO_KEYBOX_MOCK_H_
|
#endif // OEMCRYPTO_KEYBOX_MOCK_H_
|
||||||
|
|||||||
@@ -9,35 +9,37 @@ namespace wvoec_mock {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
// Note: this is a valid keybox, but it is not accepted by production servers.
|
||||||
|
// However, it is different from the one used for most of the unit tests.
|
||||||
const WidevineKeybox kKeybox = {
|
const WidevineKeybox kKeybox = {
|
||||||
// Sample keybox used for test vectors
|
// Sample keybox used for test vectors
|
||||||
{
|
{
|
||||||
// deviceID
|
// deviceID
|
||||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey01
|
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey02
|
||||||
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
0x32, 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, // ........
|
||||||
}, {
|
}, {
|
||||||
// key
|
// key
|
||||||
0xfb, 0xda, 0x04, 0x89, 0xa1, 0x58, 0x16, 0x0e,
|
0x76, 0x5d, 0xce, 0x01, 0x04, 0x89, 0xb3, 0xd0,
|
||||||
0xa4, 0x02, 0xe9, 0x29, 0xe3, 0xb6, 0x8f, 0x04,
|
0xdf, 0xce, 0x54, 0x8a, 0x49, 0xda, 0xdc, 0xb6,
|
||||||
}, {
|
}, {
|
||||||
// data
|
// data
|
||||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
||||||
0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1,
|
0x92, 0x27, 0x0b, 0x1f, 0x1a, 0xd5, 0xc6, 0x93,
|
||||||
0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd,
|
0x19, 0x3f, 0xaa, 0x74, 0x1f, 0xdd, 0x5f, 0xb4,
|
||||||
0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2, 0xd8,
|
0xe9, 0x40, 0x2f, 0x34, 0xa4, 0x92, 0xf4, 0xae,
|
||||||
0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64,
|
0x9a, 0x52, 0x39, 0xbc, 0xb7, 0x24, 0x38, 0x13,
|
||||||
0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8,
|
0xab, 0xf4, 0x92, 0x96, 0xc4, 0x81, 0x60, 0x33,
|
||||||
0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14, 0xa8,
|
0xd8, 0xb8, 0x09, 0xc7, 0x55, 0x0e, 0x12, 0xfa,
|
||||||
0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64,
|
0xa8, 0x98, 0x62, 0x8a, 0xec, 0xea, 0x74, 0x8a,
|
||||||
0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39,
|
0x4b, 0xfa, 0x5a, 0x9e, 0xb6, 0x49, 0x0d, 0x80,
|
||||||
}, {
|
}, {
|
||||||
// magic
|
// magic
|
||||||
0x6b, 0x62, 0x6f, 0x78,
|
0x6b, 0x62, 0x6f, 0x78,
|
||||||
}, {
|
}, {
|
||||||
// Crc
|
// Crc
|
||||||
0x0a, 0x7a, 0x2c, 0x35,
|
0x2a, 0x3b, 0x3e, 0xe4,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,9 @@ OEMCryptoResult OEMCrypto_GenerateDerivedKeys(OEMCrypto_SESSION session,
|
|||||||
(size_t)enc_key_context_length);
|
(size_t)enc_key_context_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_keybox()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
if (NO_ERROR != crypto_engine->ValidateKeybox()) {
|
if (NO_ERROR != crypto_engine->ValidateKeybox()) {
|
||||||
LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]");
|
LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]");
|
||||||
return OEMCrypto_ERROR_KEYBOX_INVALID;
|
return OEMCrypto_ERROR_KEYBOX_INVALID;
|
||||||
@@ -219,11 +222,6 @@ OEMCryptoResult OEMCrypto_GenerateSignature(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NO_ERROR != crypto_engine->ValidateKeybox()) {
|
|
||||||
LOGE("[OEMCrypto_GenerateSignature(): ERROR_KEYBOX_INVALID]");
|
|
||||||
return OEMCrypto_ERROR_KEYBOX_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*signature_length < SHA256_DIGEST_LENGTH) {
|
if (*signature_length < SHA256_DIGEST_LENGTH) {
|
||||||
*signature_length = SHA256_DIGEST_LENGTH;
|
*signature_length = SHA256_DIGEST_LENGTH;
|
||||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||||
@@ -631,6 +629,9 @@ OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox,
|
|||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
LOGI("-- OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox,\n");
|
LOGI("-- OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox,\n");
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_keybox()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
if (!keybox || !wrappedKeybox || !wrappedKeyBoxLength
|
if (!keybox || !wrappedKeybox || !wrappedKeyBoxLength
|
||||||
|| (keyBoxLength != *wrappedKeyBoxLength)) {
|
|| (keyBoxLength != *wrappedKeyBoxLength)) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
@@ -647,17 +648,35 @@ OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
|
|||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
LOGI("-- OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t *keybox,\n");
|
LOGI("-- OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t *keybox,\n");
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_keybox()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
if (crypto_engine->keybox().InstallKeybox(keybox, keyBoxLength)) {
|
if (crypto_engine->keybox().InstallKeybox(keybox, keyBoxLength)) {
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
return OEMCrypto_ERROR_WRITE_KEYBOX;
|
return OEMCrypto_ERROR_WRITE_KEYBOX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
OEMCryptoResult OEMCrypto_LoadTestKeybox() {
|
||||||
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
|
LOGI("-- OEMCryptoResult OEMCrypto_LoadTestKeybox()\n");
|
||||||
|
}
|
||||||
|
if (!crypto_engine->supports_keybox()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
crypto_engine->UseTestKeybox();
|
||||||
|
return OEMCrypto_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {
|
OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {
|
||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
LOGI("-- OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {\n");
|
LOGI("-- OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {\n");
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_keybox()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
switch(crypto_engine->ValidateKeybox()) {
|
switch(crypto_engine->ValidateKeybox()) {
|
||||||
case NO_ERROR: return OEMCrypto_SUCCESS;
|
case NO_ERROR: return OEMCrypto_SUCCESS;
|
||||||
case BAD_CRC: return OEMCrypto_ERROR_BAD_CRC;
|
case BAD_CRC: return OEMCrypto_ERROR_BAD_CRC;
|
||||||
@@ -673,6 +692,8 @@ OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
|||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
LOGI("-- OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,\n");
|
LOGI("-- OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,\n");
|
||||||
}
|
}
|
||||||
|
// Devices that do not support a keybox should use some other method to
|
||||||
|
// store the device id.
|
||||||
std::vector<uint8_t> dev_id_string = crypto_engine->keybox().device_id();
|
std::vector<uint8_t> dev_id_string = crypto_engine->keybox().device_id();
|
||||||
if (dev_id_string.empty()) {
|
if (dev_id_string.empty()) {
|
||||||
LOGE("[OEMCrypto_GetDeviceId(): Keybox Invalid]");
|
LOGE("[OEMCrypto_GetDeviceId(): Keybox Invalid]");
|
||||||
@@ -700,12 +721,23 @@ OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
|||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
LOGI("-- OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,\n");
|
LOGI("-- OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,\n");
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_keybox()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
size_t length = crypto_engine->keybox().key_data_length();
|
size_t length = crypto_engine->keybox().key_data_length();
|
||||||
|
if (keyDataLength == NULL) {
|
||||||
|
LOGE("[OEMCrypto_GetKeyData(): null pointer. ERROR_UNKNOWN_FAILURE]");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
if (*keyDataLength < length) {
|
if (*keyDataLength < length) {
|
||||||
*keyDataLength = length;
|
*keyDataLength = length;
|
||||||
LOGE("[OEMCrypto_GetKeyData(): ERROR_SHORT_BUFFER]");
|
LOGE("[OEMCrypto_GetKeyData(): ERROR_SHORT_BUFFER]");
|
||||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||||
}
|
}
|
||||||
|
if (keyData == NULL) {
|
||||||
|
LOGE("[OEMCrypto_GetKeyData(): null pointer. ERROR_UNKNOWN_FAILURE]");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
memset(keyData, 0, *keyDataLength);
|
memset(keyData, 0, *keyDataLength);
|
||||||
memcpy(keyData, crypto_engine->keybox().key_data(), length);
|
memcpy(keyData, crypto_engine->keybox().key_data(), length);
|
||||||
*keyDataLength = length;
|
*keyDataLength = length;
|
||||||
@@ -754,6 +786,9 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session,
|
|||||||
dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvcdm::KEY_IV_SIZE);
|
dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvcdm::KEY_IV_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_keybox()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
if (wrapped_rsa_key_length == NULL) {
|
if (wrapped_rsa_key_length == NULL) {
|
||||||
LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
@@ -890,6 +925,9 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session,
|
|||||||
LOGE("[OEMCrypto_LoadDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
LOGE("[OEMCrypto_LoadDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_keybox()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
const WrappedRSAKey* wrapped
|
const WrappedRSAKey* wrapped
|
||||||
= reinterpret_cast<const WrappedRSAKey*>(wrapped_rsa_key);
|
= reinterpret_cast<const WrappedRSAKey*>(wrapped_rsa_key);
|
||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
@@ -949,6 +987,15 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
OEMCryptoResult OEMCrypto_LoadTestRSAKey() {
|
||||||
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
|
LOGI("-- OEMCryptoResult OEMCrypto_LoadTestRSAKey()\n");
|
||||||
|
}
|
||||||
|
if (crypto_engine->LoadTestRSAKey()) return OEMCrypto_SUCCESS;
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
||||||
OEMCrypto_SESSION session,
|
OEMCrypto_SESSION session,
|
||||||
@@ -1298,6 +1345,9 @@ OEMCryptoResult OEMCrypto_UpdateUsageTable() {
|
|||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
LOGI("-- OEMCryptoResult OEMCrypto_UpdateUsageTable();\n");
|
LOGI("-- OEMCryptoResult OEMCrypto_UpdateUsageTable();\n");
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_storage()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
return crypto_engine->usage_table()->UpdateTable();
|
return crypto_engine->usage_table()->UpdateTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1310,6 +1360,9 @@ OEMCryptoResult OEMCrypto_DeactivateUsageEntry(const uint8_t *pst,
|
|||||||
dump_hex("pst", pst, pst_length);
|
dump_hex("pst", pst, pst_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_storage()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
std::vector<uint8_t> pstv(pst, pst + pst_length);
|
std::vector<uint8_t> pstv(pst, pst + pst_length);
|
||||||
return crypto_engine->usage_table()->DeactivateEntry(pstv);
|
return crypto_engine->usage_table()->DeactivateEntry(pstv);
|
||||||
}
|
}
|
||||||
@@ -1326,6 +1379,9 @@ OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
|
|||||||
dump_hex("pst", pst, pst_length);
|
dump_hex("pst", pst, pst_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_storage()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||||
if (!session_ctx || !session_ctx->isValid()) {
|
if (!session_ctx || !session_ctx->isValid()) {
|
||||||
LOGE("[OEMCrypto_ReportUsage(): ERROR_INVALID_SESSION]");
|
LOGE("[OEMCrypto_ReportUsage(): ERROR_INVALID_SESSION]");
|
||||||
@@ -1365,6 +1421,9 @@ OEMCryptoResult OEMCrypto_DeleteUsageEntry(OEMCrypto_SESSION session,
|
|||||||
dump_hex("signature", signature, signature_length);
|
dump_hex("signature", signature, signature_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_storage()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||||
if (!session_ctx || !session_ctx->isValid()) {
|
if (!session_ctx || !session_ctx->isValid()) {
|
||||||
LOGE("[OEMCrypto_DeleteUsageEntry(): ERROR_INVALID_SESSION]");
|
LOGE("[OEMCrypto_DeleteUsageEntry(): ERROR_INVALID_SESSION]");
|
||||||
@@ -1401,6 +1460,9 @@ OEMCryptoResult OEMCrypto_ForceDeleteUsageEntry(const uint8_t* pst,
|
|||||||
dump_hex("pst", pst, pst_length);
|
dump_hex("pst", pst, pst_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_storage()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
std::vector<uint8_t> pstv(pst, pst + pst_length);
|
std::vector<uint8_t> pstv(pst, pst + pst_length);
|
||||||
if (crypto_engine->usage_table()->DeleteEntry(pstv)) {
|
if (crypto_engine->usage_table()->DeleteEntry(pstv)) {
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
@@ -1413,6 +1475,9 @@ OEMCryptoResult OEMCrypto_DeleteUsageTable() {
|
|||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
LOGI("-- OEMCryptoResult OEMCrypto_DeleteUsageTable()\n");
|
LOGI("-- OEMCryptoResult OEMCrypto_DeleteUsageTable()\n");
|
||||||
}
|
}
|
||||||
|
if (!crypto_engine->supports_storage()) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
crypto_engine->usage_table()->Clear();
|
crypto_engine->usage_table()->Clear();
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
|||||||
file.Close();
|
file.Close();
|
||||||
|
|
||||||
// First, verify the signature of the usage table file.
|
// First, verify the signature of the usage table file.
|
||||||
std::vector<uint8_t> &key = ce_->keybox().device_key();
|
std::vector<uint8_t> &key = ce_->real_keybox().device_key();
|
||||||
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
|
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
|
||||||
unsigned int sig_length = sizeof(computed_signature);
|
unsigned int sig_length = sizeof(computed_signature);
|
||||||
if (!HMAC(EVP_sha256(), &key[0], key.size(),
|
if (!HMAC(EVP_sha256(), &key[0], key.size(),
|
||||||
@@ -275,7 +275,7 @@ bool UsageTable::SaveToFile() {
|
|||||||
|
|
||||||
// This should be encrypted and signed with a device specific key.
|
// This should be encrypted and signed with a device specific key.
|
||||||
// For the reference implementation, I'm just going to use the keybox key.
|
// For the reference implementation, I'm just going to use the keybox key.
|
||||||
std::vector<uint8_t> &key = ce_->keybox().device_key();
|
std::vector<uint8_t> &key = ce_->real_keybox().device_key();
|
||||||
|
|
||||||
// Encrypt the table.
|
// Encrypt the table.
|
||||||
RAND_bytes(encrypted_table->iv, wvcdm::KEY_IV_SIZE);
|
RAND_bytes(encrypted_table->iv, wvcdm::KEY_IV_SIZE);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ LOCAL_PATH:= $(call my-dir)
|
|||||||
LOCAL_SRC_FILES:= \
|
LOCAL_SRC_FILES:= \
|
||||||
oemcrypto_test.cpp \
|
oemcrypto_test.cpp \
|
||||||
oemcrypto_test_android.cpp \
|
oemcrypto_test_android.cpp \
|
||||||
|
oemcrypto_test_main.cpp \
|
||||||
|
|
||||||
LOCAL_C_INCLUDES += \
|
LOCAL_C_INCLUDES += \
|
||||||
external/gtest/include \
|
external/gtest/include \
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
41
libwvdrmengine/oemcrypto/test/oemcrypto_test.h
Normal file
41
libwvdrmengine/oemcrypto/test/oemcrypto_test.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef CDM_OEMCRYPTO_TEST_H_
|
||||||
|
#define CDM_OEMCRYPTO_TEST_H_
|
||||||
|
|
||||||
|
#include "OEMCryptoCENC.h"
|
||||||
|
#include "wv_keybox.h"
|
||||||
|
|
||||||
|
namespace wvoec {
|
||||||
|
|
||||||
|
class DeviceFeatures {
|
||||||
|
public:
|
||||||
|
enum DeriveMethod { // Method to use derive session keys.
|
||||||
|
NO_METHOD, // Cannot derive known session keys.
|
||||||
|
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
|
||||||
|
LOAD_TEST_RSA_KEY, // Call LoadTestRSAKey before deriving keys.
|
||||||
|
EXISTING_TEST_KEYBOX, // Keybox is already the test keybox.
|
||||||
|
FORCE_TEST_KEYBOX, // User requested calling InstallKeybox.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DeriveMethod derive_key_method;
|
||||||
|
bool uses_keybox; // Device uses a keybox to derive session keys.
|
||||||
|
bool uses_certificate; // Device uses a certificate to derive session keys.
|
||||||
|
bool loads_certificate; // Device can load a certificate from the server.
|
||||||
|
bool generic_crypto; // Device supports generic crypto.
|
||||||
|
bool cast_receiver; // Device supports alternate rsa signature padding.
|
||||||
|
bool usage_table; // Device saves usage information.
|
||||||
|
uint32_t api_version;
|
||||||
|
|
||||||
|
void Initialize(bool is_cast_receiver, bool force_load_test_keybox);
|
||||||
|
std::string RestrictFilter(const std::string& initial_filter);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PickDerivedKey();
|
||||||
|
bool IsTestKeyboxInstalled();
|
||||||
|
void FilterOut(std::string* current_filter, const std::string& new_filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DeviceFeatures global_features;
|
||||||
|
|
||||||
|
} // namespace wvoec
|
||||||
|
|
||||||
|
#endif // CDM_OEMCRYPTO_TEST_H_
|
||||||
@@ -75,7 +75,6 @@ TEST_F(OEMCryptoAndroidLMPTest, GenericCryptoImplemented) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(OEMCryptoAndroidLMPTest, SupportsUsageTable) {
|
TEST_F(OEMCryptoAndroidLMPTest, SupportsUsageTable) {
|
||||||
// TODO(fredgc): maybe remove Properties::oem_crypto_require_usage_tables?
|
|
||||||
ASSERT_TRUE(OEMCrypto_SupportsUsageTable());
|
ASSERT_TRUE(OEMCrypto_SupportsUsageTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
43
libwvdrmengine/oemcrypto/test/oemcrypto_test_main.cpp
Normal file
43
libwvdrmengine/oemcrypto/test/oemcrypto_test_main.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "oemcrypto_test.h"
|
||||||
|
#include "OEMCryptoCENC.h"
|
||||||
|
#include "properties.h"
|
||||||
|
|
||||||
|
static void acknowledge_cast() {
|
||||||
|
std::cout
|
||||||
|
<< "==================================================================\n"
|
||||||
|
<< "= This device is expected to load x509 certs as a cast receiver. =\n"
|
||||||
|
<< "==================================================================\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
wvcdm::Properties::Init();
|
||||||
|
wvcdm::g_cutoff = wvcdm::LOG_INFO;
|
||||||
|
bool is_cast_receiver = false;
|
||||||
|
bool force_load_test_keybox = false;
|
||||||
|
bool filter_tests = true;
|
||||||
|
for(int i=0; i < argc; i++) {
|
||||||
|
if (!strcmp(argv[i], "--cast")) {
|
||||||
|
acknowledge_cast();
|
||||||
|
is_cast_receiver = true;
|
||||||
|
}
|
||||||
|
if (!strcmp(argv[i], "--force_load_test_keybox")) {
|
||||||
|
force_load_test_keybox = true;
|
||||||
|
}
|
||||||
|
if (!strcmp(argv[i], "--no_filter")) {
|
||||||
|
filter_tests = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wvoec::global_features.Initialize(is_cast_receiver, force_load_test_keybox);
|
||||||
|
// If the user requests --no_filter, we don't change the filter, otherwise, we
|
||||||
|
// filter out features that are not supported.
|
||||||
|
if (filter_tests) {
|
||||||
|
::testing::GTEST_FLAG(filter)
|
||||||
|
= wvoec::global_features.RestrictFilter(::testing::GTEST_FLAG(filter));
|
||||||
|
}
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user