Enable OEMCrypto Unit Tests
This is a merge from the widevine repository of http://go/wvgerrit/13923 Switch openssl to use the EVP interface for aes-ctr-128 http://go/wvgerrit/13979 Add Test Certificate to OEMCrypto Mock http://go/wvgerrit/13978 Add Test Keybox to Level 3 OEMCrypto http://go/wvgerrit/13873 Enable OEMCrypto Unit Tests This CL adds a main program to oemcrypto_test.cpp, which filters out tests that are not supported on the specified platform. It also adds LoadTestKeybox to the mock. This allows oemcrypto unit tests to be run on devices that have production keybox. It also allows the same set of unit tests to work on Android and on non-Android platforms. b/18962381 Use test certificate (partial fix) b/19867990 Separate cast receiver tests Change-Id: If89c31530103ed85aa37d7379bd5b4dc2a927f38
This commit is contained in:
@@ -294,6 +294,7 @@ typedef enum OEMCrypto_HDCP_Capability {
|
||||
#define OEMCrypto_LoadTestKeybox _oecc42
|
||||
#define OEMCrypto_ForceDeleteUsageEntry _oecc43
|
||||
#define OEMCrypto_GetHDCPCapability _oecc44
|
||||
#define OEMCrypto_LoadTestRSAKey _oecc45
|
||||
|
||||
|
||||
/*
|
||||
@@ -1471,6 +1472,36 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session,
|
||||
const uint8_t* wrapped_rsa_key,
|
||||
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
|
||||
*
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace wvoec3 {
|
||||
#define Level3_QueryKeyControl _lcc41
|
||||
#define Level3_LoadTestKeybox _lcc42
|
||||
#define Level3_ForceDeleteUsageEntry _lcc43
|
||||
#define Level3_LoadTestRSAKey _lcc45
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -144,6 +145,7 @@ OEMCryptoResult Level3_RewrapDeviceRSAKey(OEMCrypto_SESSION session,
|
||||
OEMCryptoResult Level3_LoadDeviceRSAKey(OEMCrypto_SESSION session,
|
||||
const uint8_t* wrapped_rsa_key,
|
||||
size_t wrapped_rsa_key_length);
|
||||
OEMCryptoResult Level3_LoadTestRSAKey();
|
||||
OEMCryptoResult Level3_GenerateRSASignature(OEMCrypto_SESSION session,
|
||||
const uint8_t* message,
|
||||
size_t message_length,
|
||||
|
||||
@@ -33,6 +33,11 @@ bool CryptoEngine::supports_storage() {
|
||||
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
|
||||
// anti-rollback hardware.
|
||||
bool CryptoEngine::is_anti_rollback_hw_present() {
|
||||
|
||||
@@ -35,6 +35,11 @@ bool CryptoEngine::supports_storage() {
|
||||
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.
|
||||
bool CryptoEngine::is_anti_rollback_hw_present() {
|
||||
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));
|
||||
}
|
||||
}
|
||||
// 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 wvoec_mock {
|
||||
@@ -85,6 +241,10 @@ void SessionKeyTable::UpdateDuration(const KeyControlBlock& control) {
|
||||
|
||||
SessionContext::~SessionContext() {
|
||||
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
|
||||
@@ -999,7 +1159,8 @@ bool SessionContext::IsUsageEntryValid() {
|
||||
void SessionContext::ReleaseUsageEntry() { usage_entry_ = NULL; }
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -1012,13 +1173,73 @@ CryptoEngine::~CryptoEngine() {
|
||||
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() {
|
||||
wvcdm::AutoLock lock(session_table_lock_);
|
||||
static int unique_id = 1;
|
||||
SessionId sid = (SessionId)++unique_id;
|
||||
SessionContext* sctx = new SessionContext(this, sid);
|
||||
SessionContext* sctx = new SessionContext(this, sid, this->rsa_key_);
|
||||
sessions_[sid] = sctx;
|
||||
return sid;
|
||||
}
|
||||
@@ -1124,11 +1345,6 @@ OEMCryptoResult SessionContext::DecryptCTR(
|
||||
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||
}
|
||||
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) {
|
||||
// For reference implementation, we quietly drop the decrypted direct video.
|
||||
@@ -1144,23 +1360,78 @@ OEMCryptoResult SessionContext::DecryptCTR(
|
||||
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];
|
||||
|
||||
// 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) {
|
||||
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);
|
||||
for (int n = block_offset; n < AES_BLOCK_SIZE && l < cipher_data_length;
|
||||
++n, ++l) {
|
||||
++n, ++l) {
|
||||
clear_data[l] = cipher_data[l] ^ ecount_buf[n];
|
||||
}
|
||||
ctr128_inc64(aes_iv);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,12 +76,12 @@ class SessionContext {
|
||||
SessionContext() {}
|
||||
|
||||
public:
|
||||
explicit SessionContext(CryptoEngine* ce, SessionId sid)
|
||||
explicit SessionContext(CryptoEngine* ce, SessionId sid, RSA* rsa_key)
|
||||
: valid_(true),
|
||||
ce_(ce),
|
||||
id_(sid),
|
||||
current_content_key_(NULL),
|
||||
rsa_key_(NULL),
|
||||
rsa_key_(rsa_key),
|
||||
allowed_schemes_(kSign_RSASSA_PSS),
|
||||
usage_entry_(NULL) {}
|
||||
~SessionContext();
|
||||
@@ -225,7 +225,11 @@ class CryptoEngine {
|
||||
void Terminate();
|
||||
|
||||
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();
|
||||
|
||||
@@ -252,6 +256,7 @@ class CryptoEngine {
|
||||
bool local_display();
|
||||
bool closed_platform();
|
||||
bool supports_storage();
|
||||
bool supports_keybox();
|
||||
bool is_anti_rollback_hw_present();
|
||||
const char* security_level();
|
||||
|
||||
@@ -259,8 +264,11 @@ class CryptoEngine {
|
||||
SessionContext* current_session_;
|
||||
ActiveSessions sessions_;
|
||||
WvKeybox keybox_;
|
||||
WvTestKeybox test_keybox_;
|
||||
wvcdm::Lock session_table_lock_;
|
||||
UsageTable* usage_table_;
|
||||
bool use_test_keybox_;
|
||||
RSA* rsa_key_; // If no keybox, this is baked in certificate.
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
||||
};
|
||||
|
||||
@@ -14,6 +14,42 @@
|
||||
|
||||
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() {
|
||||
valid_ = Prepare();
|
||||
}
|
||||
@@ -66,4 +102,9 @@ bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
|
||||
return true;
|
||||
}
|
||||
|
||||
WvTestKeybox::WvTestKeybox() {
|
||||
InstallKeybox(reinterpret_cast<const uint8_t*>(&kTestKeybox),
|
||||
sizeof(kTestKeybox));
|
||||
}
|
||||
|
||||
} // namespace wvoec_mock
|
||||
|
||||
@@ -41,6 +41,11 @@ class WvKeybox {
|
||||
uint8_t crc_[4];
|
||||
};
|
||||
|
||||
class WvTestKeybox : public WvKeybox {
|
||||
public:
|
||||
WvTestKeybox();
|
||||
};
|
||||
|
||||
} // namespace wvoec_mock
|
||||
|
||||
#endif // OEMCRYPTO_KEYBOX_MOCK_H_
|
||||
|
||||
@@ -9,35 +9,37 @@ namespace wvoec_mock {
|
||||
|
||||
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 = {
|
||||
// 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, // ........
|
||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey02
|
||||
0x32, 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,
|
||||
0x76, 0x5d, 0xce, 0x01, 0x04, 0x89, 0xb3, 0xd0,
|
||||
0xdf, 0xce, 0x54, 0x8a, 0x49, 0xda, 0xdc, 0xb6,
|
||||
}, {
|
||||
// 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,
|
||||
0x92, 0x27, 0x0b, 0x1f, 0x1a, 0xd5, 0xc6, 0x93,
|
||||
0x19, 0x3f, 0xaa, 0x74, 0x1f, 0xdd, 0x5f, 0xb4,
|
||||
0xe9, 0x40, 0x2f, 0x34, 0xa4, 0x92, 0xf4, 0xae,
|
||||
0x9a, 0x52, 0x39, 0xbc, 0xb7, 0x24, 0x38, 0x13,
|
||||
0xab, 0xf4, 0x92, 0x96, 0xc4, 0x81, 0x60, 0x33,
|
||||
0xd8, 0xb8, 0x09, 0xc7, 0x55, 0x0e, 0x12, 0xfa,
|
||||
0xa8, 0x98, 0x62, 0x8a, 0xec, 0xea, 0x74, 0x8a,
|
||||
0x4b, 0xfa, 0x5a, 0x9e, 0xb6, 0x49, 0x0d, 0x80,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
if (!crypto_engine->supports_keybox()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if (NO_ERROR != crypto_engine->ValidateKeybox()) {
|
||||
LOGE("[OEMCrypto_GenerateDerivedKeys(): 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) {
|
||||
*signature_length = SHA256_DIGEST_LENGTH;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
@@ -631,6 +629,9 @@ OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t* keybox,
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
LOGI("-- OEMCryptoResult OEMCrypto_WrapKeybox(const uint8_t *keybox,\n");
|
||||
}
|
||||
if (!crypto_engine->supports_keybox()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if (!keybox || !wrappedKeybox || !wrappedKeyBoxLength
|
||||
|| (keyBoxLength != *wrappedKeyBoxLength)) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
@@ -647,17 +648,35 @@ OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
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)) {
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
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"
|
||||
OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
LOGI("-- OEMCryptoResult OEMCrypto_IsKeyboxValid(void) {\n");
|
||||
}
|
||||
if (!crypto_engine->supports_keybox()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
switch(crypto_engine->ValidateKeybox()) {
|
||||
case NO_ERROR: return OEMCrypto_SUCCESS;
|
||||
case BAD_CRC: return OEMCrypto_ERROR_BAD_CRC;
|
||||
@@ -673,6 +692,8 @@ OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID,
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
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();
|
||||
if (dev_id_string.empty()) {
|
||||
LOGE("[OEMCrypto_GetDeviceId(): Keybox Invalid]");
|
||||
@@ -700,12 +721,23 @@ OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
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();
|
||||
if (keyDataLength == NULL) {
|
||||
LOGE("[OEMCrypto_GetKeyData(): null pointer. ERROR_UNKNOWN_FAILURE]");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (*keyDataLength < length) {
|
||||
*keyDataLength = length;
|
||||
LOGE("[OEMCrypto_GetKeyData(): 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);
|
||||
memcpy(keyData, crypto_engine->keybox().key_data(), 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);
|
||||
}
|
||||
}
|
||||
if (!crypto_engine->supports_keybox()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if (wrapped_rsa_key_length == NULL) {
|
||||
LOGE("[OEMCrypto_RewrapDeviceRSAKey(): 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]");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (!crypto_engine->supports_keybox()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
const WrappedRSAKey* wrapped
|
||||
= reinterpret_cast<const WrappedRSAKey*>(wrapped_rsa_key);
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
@@ -949,6 +987,15 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session,
|
||||
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"
|
||||
OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
||||
OEMCrypto_SESSION session,
|
||||
@@ -1298,6 +1345,9 @@ OEMCryptoResult OEMCrypto_UpdateUsageTable() {
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
LOGI("-- OEMCryptoResult OEMCrypto_UpdateUsageTable();\n");
|
||||
}
|
||||
if (!crypto_engine->supports_storage()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return crypto_engine->usage_table()->UpdateTable();
|
||||
}
|
||||
|
||||
@@ -1310,6 +1360,9 @@ OEMCryptoResult OEMCrypto_DeactivateUsageEntry(const uint8_t *pst,
|
||||
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);
|
||||
return crypto_engine->usage_table()->DeactivateEntry(pstv);
|
||||
}
|
||||
@@ -1326,6 +1379,9 @@ OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
|
||||
dump_hex("pst", pst, pst_length);
|
||||
}
|
||||
}
|
||||
if (!crypto_engine->supports_storage()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (!session_ctx || !session_ctx->isValid()) {
|
||||
LOGE("[OEMCrypto_ReportUsage(): ERROR_INVALID_SESSION]");
|
||||
@@ -1365,6 +1421,9 @@ OEMCryptoResult OEMCrypto_DeleteUsageEntry(OEMCrypto_SESSION session,
|
||||
dump_hex("signature", signature, signature_length);
|
||||
}
|
||||
}
|
||||
if (!crypto_engine->supports_storage()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (!session_ctx || !session_ctx->isValid()) {
|
||||
LOGE("[OEMCrypto_DeleteUsageEntry(): ERROR_INVALID_SESSION]");
|
||||
@@ -1401,6 +1460,9 @@ OEMCryptoResult OEMCrypto_ForceDeleteUsageEntry(const uint8_t* pst,
|
||||
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);
|
||||
if (crypto_engine->usage_table()->DeleteEntry(pstv)) {
|
||||
return OEMCrypto_SUCCESS;
|
||||
@@ -1413,6 +1475,9 @@ OEMCryptoResult OEMCrypto_DeleteUsageTable() {
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
LOGI("-- OEMCryptoResult OEMCrypto_DeleteUsageTable()\n");
|
||||
}
|
||||
if (!crypto_engine->supports_storage()) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
crypto_engine->usage_table()->Clear();
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
file.Close();
|
||||
|
||||
// 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];
|
||||
unsigned int sig_length = sizeof(computed_signature);
|
||||
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.
|
||||
// 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.
|
||||
RAND_bytes(encrypted_table->iv, wvcdm::KEY_IV_SIZE);
|
||||
|
||||
@@ -3,6 +3,7 @@ LOCAL_PATH:= $(call my-dir)
|
||||
LOCAL_SRC_FILES:= \
|
||||
oemcrypto_test.cpp \
|
||||
oemcrypto_test_android.cpp \
|
||||
oemcrypto_test_main.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
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) {
|
||||
// TODO(fredgc): maybe remove Properties::oem_crypto_require_usage_tables?
|
||||
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