Unit tests and reference code for v15
This CL updates the unit tests and reference code to support OEMCrypto API v15.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -170,13 +170,10 @@ OEMCryptoResult Level3_GenerateSignature(OEMCrypto_SESSION session,
|
|||||||
size_t message_length,
|
size_t message_length,
|
||||||
uint8_t* signature,
|
uint8_t* signature,
|
||||||
size_t* signature_length);
|
size_t* signature_length);
|
||||||
OEMCryptoResult Level3_RefreshKeys(OEMCrypto_SESSION session,
|
OEMCryptoResult Level3_RefreshKeys(
|
||||||
const uint8_t* message,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
size_t message_length,
|
const uint8_t* signature, size_t signature_length, size_t num_keys,
|
||||||
const uint8_t* signature,
|
const OEMCrypto_KeyRefreshObject_V14* key_array);
|
||||||
size_t signature_length,
|
|
||||||
size_t num_keys,
|
|
||||||
const OEMCrypto_KeyRefreshObject* key_array);
|
|
||||||
OEMCryptoResult Level3_QueryKeyControl(OEMCrypto_SESSION session,
|
OEMCryptoResult Level3_QueryKeyControl(OEMCrypto_SESSION session,
|
||||||
const uint8_t* key_id,
|
const uint8_t* key_id,
|
||||||
size_t key_id_length,
|
size_t key_id_length,
|
||||||
@@ -347,27 +344,20 @@ OEMCryptoResult Level3_CreateOldUsageEntry(uint64_t time_since_license_received,
|
|||||||
const uint8_t* pst,
|
const uint8_t* pst,
|
||||||
size_t pst_length);
|
size_t pst_length);
|
||||||
uint32_t Level3_GetAnalogOutputFlags();
|
uint32_t Level3_GetAnalogOutputFlags();
|
||||||
OEMCryptoResult Level3_LoadTestKeybox(const uint8_t *buffer, size_t length);
|
OEMCryptoResult Level3_LoadTestKeybox(const uint8_t* buffer, size_t length);
|
||||||
OEMCryptoResult Level3_LoadEntitledContentKeys(OEMCrypto_SESSION session,
|
OEMCryptoResult Level3_LoadEntitledContentKeys(
|
||||||
size_t num_keys,
|
OEMCrypto_SESSION session, size_t num_keys,
|
||||||
const OEMCrypto_EntitledContentKeyObject* key_array);
|
const OEMCrypto_EntitledContentKeyObject_V14* key_array);
|
||||||
OEMCryptoResult Level3_SelectKey(const OEMCrypto_SESSION session,
|
OEMCryptoResult Level3_SelectKey(const OEMCrypto_SESSION session,
|
||||||
const uint8_t* key_id,
|
const uint8_t* key_id, size_t key_id_length,
|
||||||
size_t key_id_length,
|
|
||||||
OEMCryptoCipherMode cipher_mode);
|
OEMCryptoCipherMode cipher_mode);
|
||||||
OEMCryptoResult Level3_LoadKeys(OEMCrypto_SESSION session,
|
OEMCryptoResult Level3_LoadKeys(
|
||||||
const uint8_t* message,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
size_t message_length,
|
const uint8_t* signature, size_t signature_length,
|
||||||
const uint8_t* signature,
|
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_key, size_t num_keys,
|
||||||
size_t signature_length,
|
const OEMCrypto_KeyObject_V14* key_array, const uint8_t* pst,
|
||||||
const uint8_t* enc_mac_key_iv,
|
size_t pst_length, const uint8_t* srm_requirement,
|
||||||
const uint8_t* enc_mac_key,
|
OEMCrypto_LicenseType license_type);
|
||||||
size_t num_keys,
|
|
||||||
const OEMCrypto_KeyObject* key_array,
|
|
||||||
const uint8_t* pst,
|
|
||||||
size_t pst_length,
|
|
||||||
const uint8_t* srm_requirement,
|
|
||||||
OEMCrypto_LicenseType license_type);
|
|
||||||
/*
|
/*
|
||||||
* Level3_GetInitializationState
|
* Level3_GetInitializationState
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const uint32_t kControlObserveDataPath = (1<<31);
|
|||||||
const uint32_t kControlObserveHDCP = (1<<30);
|
const uint32_t kControlObserveHDCP = (1<<30);
|
||||||
const uint32_t kControlObserveCGMS = (1<<29);
|
const uint32_t kControlObserveCGMS = (1<<29);
|
||||||
const uint32_t kControlRequireAntiRollbackHardware = (1<<28);
|
const uint32_t kControlRequireAntiRollbackHardware = (1<<28);
|
||||||
|
const uint32_t kControlAllowHashVerification = (1<<24);
|
||||||
const uint32_t kSharedLicense = (1<<23);
|
const uint32_t kSharedLicense = (1<<23);
|
||||||
const uint32_t kControlSRMVersionRequired = (1<<22);
|
const uint32_t kControlSRMVersionRequired = (1<<22);
|
||||||
const uint32_t kControlDisableAnalogOutput = (1<<21);
|
const uint32_t kControlDisableAnalogOutput = (1<<21);
|
||||||
|
|||||||
@@ -4,378 +4,320 @@
|
|||||||
|
|
||||||
namespace wvoec_ref {
|
namespace wvoec_ref {
|
||||||
|
|
||||||
extern const uint32_t kOEMSystemId_Prod = 7346;
|
const uint32_t kOEMSystemId_Prod = 7913;
|
||||||
|
|
||||||
extern const uint8_t kOEMPrivateKey_Prod[] = {
|
// From file test_rsa_key_2_carmichael.pk8 in team shared drive.
|
||||||
0x30, 0x82, 0x06, 0xfe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
// Size is 1216.
|
||||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
const uint8_t kOEMPrivateKey_Prod[] = {
|
||||||
0x06, 0xe8, 0x30, 0x82, 0x06, 0xe4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
|
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||||
0x81, 0x00, 0xf5, 0x09, 0x64, 0x4a, 0x26, 0xfe, 0xc0, 0x98, 0x55, 0x6a,
|
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||||
0x1d, 0x5d, 0x1c, 0xc7, 0x38, 0xaf, 0xfd, 0x49, 0x9e, 0x85, 0x3f, 0xd6,
|
0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
|
||||||
0x45, 0x0e, 0x99, 0x09, 0x85, 0x69, 0x84, 0x3c, 0xfe, 0x72, 0xa5, 0x56,
|
0x01, 0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a,
|
||||||
0xfa, 0x11, 0x4f, 0x6b, 0x7d, 0x32, 0x2b, 0x0c, 0xbf, 0x8f, 0xac, 0x47,
|
0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f, 0x94, 0x58, 0xdd, 0xde,
|
||||||
0x96, 0x22, 0x82, 0x3d, 0xf5, 0x64, 0x74, 0x7e, 0x62, 0x68, 0x74, 0xcd,
|
0xa7, 0x1f, 0x3c, 0x2c, 0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e,
|
||||||
0x0a, 0xec, 0x84, 0xc5, 0x15, 0x06, 0x0e, 0x5a, 0x2f, 0x20, 0xe3, 0xc9,
|
0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a, 0x2a, 0xaa, 0x9d, 0xb4,
|
||||||
0x67, 0xcd, 0xdd, 0x01, 0xb8, 0xb3, 0x18, 0x87, 0x8c, 0xa9, 0x58, 0x86,
|
0x4e, 0xfa, 0xa7, 0x6a, 0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3,
|
||||||
0x0f, 0xb6, 0xc3, 0x42, 0x7e, 0x87, 0x48, 0x5e, 0x10, 0x49, 0xc7, 0xd7,
|
0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f, 0x28, 0xda, 0x3f, 0xce,
|
||||||
0xb7, 0xb8, 0xa6, 0x34, 0x08, 0x0c, 0x94, 0xf4, 0xbb, 0x2a, 0x06, 0xa4,
|
0x31, 0x7b, 0xfd, 0x06, 0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb,
|
||||||
0x4f, 0xec, 0xbc, 0xc4, 0x37, 0xbe, 0x99, 0x10, 0x23, 0x37, 0x24, 0xb1,
|
0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3, 0x29, 0xf2, 0x73, 0x9e,
|
||||||
0xdf, 0xcb, 0xe6, 0x3f, 0xc1, 0xf0, 0x0f, 0x04, 0x03, 0xc8, 0xb0, 0x1e,
|
0x39, 0xd8, 0xf6, 0x6f, 0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4,
|
||||||
0xd6, 0xb8, 0xae, 0x77, 0xe1, 0x4d, 0x6d, 0x97, 0x69, 0x6d, 0x8a, 0x73,
|
0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04, 0xcd, 0x9a, 0x13, 0x8b,
|
||||||
0x66, 0x32, 0x57, 0x6f, 0xcf, 0xea, 0x1e, 0x7b, 0x87, 0x03, 0x75, 0xb1,
|
0x54, 0x73, 0x54, 0x25, 0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda,
|
||||||
0xef, 0x83, 0x64, 0x26, 0xf1, 0x3f, 0xbf, 0xe6, 0x28, 0x03, 0x72, 0x57,
|
0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67, 0x98, 0x56, 0x57, 0x54,
|
||||||
0xbf, 0x47, 0x29, 0x99, 0x8f, 0x74, 0x1d, 0x01, 0x16, 0xad, 0xb2, 0xdf,
|
0x71, 0xcd, 0x12, 0x7f, 0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03,
|
||||||
0x80, 0xa4, 0xd3, 0x8b, 0xeb, 0x61, 0xd1, 0x40, 0x68, 0xb9, 0xa2, 0xa5,
|
0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53, 0xc9, 0x83, 0x06, 0x51,
|
||||||
0xef, 0x2b, 0xe5, 0x78, 0xe8, 0x28, 0x88, 0x87, 0xb7, 0x53, 0x49, 0xbb,
|
0x5a, 0x88, 0x65, 0x13, 0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b,
|
||||||
0xe4, 0xea, 0x0d, 0x5e, 0x96, 0xa5, 0xdd, 0x1f, 0x0b, 0x25, 0x8b, 0xb5,
|
0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e, 0x2d, 0x5f, 0xf8, 0x12,
|
||||||
0x95, 0x46, 0xe7, 0xba, 0xb8, 0xc4, 0x0a, 0x36, 0xb1, 0x89, 0xeb, 0x27,
|
0x7f, 0xa2, 0xfc, 0xbb, 0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01,
|
||||||
0x5d, 0xd9, 0x97, 0x24, 0x59, 0xa3, 0x9b, 0xb0, 0x23, 0x0b, 0xd2, 0xec,
|
0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87, 0x82, 0x46, 0x0b, 0x3a,
|
||||||
0x65, 0x91, 0xf9, 0xf0, 0xa0, 0x74, 0x5f, 0xb4, 0xce, 0x22, 0x27, 0x18,
|
0x77, 0x8f, 0xc0, 0x72, 0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed,
|
||||||
0x37, 0xe2, 0x4b, 0xfc, 0x91, 0xf9, 0x09, 0x15, 0xe6, 0xdb, 0x06, 0x9b,
|
0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44, 0xd3, 0x5b, 0x3d, 0xdb,
|
||||||
0x4d, 0x82, 0xdc, 0x36, 0x14, 0x48, 0xc6, 0xd5, 0x87, 0xca, 0xec, 0x5a,
|
0x9c, 0x5e, 0x1b, 0x7b, 0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb,
|
||||||
0xa2, 0x29, 0x33, 0xef, 0x22, 0x0c, 0x4b, 0xbf, 0xe7, 0x2f, 0x95, 0xe1,
|
0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
|
||||||
0xd3, 0xa5, 0xd8, 0xaa, 0x44, 0x77, 0x29, 0xa3, 0x20, 0x33, 0xd2, 0x51,
|
0x82, 0x01, 0x00, 0x0a, 0xf9, 0x4a, 0x19, 0x72, 0x88, 0x1b, 0x4e, 0xd8,
|
||||||
0xa2, 0xf9, 0x4a, 0x6f, 0xf7, 0x3e, 0xf7, 0x0b, 0x8a, 0xec, 0xc1, 0x99,
|
0x2f, 0xef, 0x99, 0x93, 0x32, 0xda, 0x51, 0x21, 0x2e, 0x14, 0x06, 0xf4,
|
||||||
0x1d, 0x47, 0xf3, 0x74, 0x02, 0x04, 0xab, 0x8e, 0x62, 0x4c, 0x9e, 0x00,
|
0xe9, 0x65, 0x1c, 0xf9, 0xd4, 0xcf, 0x1a, 0x51, 0x53, 0xcd, 0x48, 0x33,
|
||||||
0xc2, 0x84, 0xd7, 0xd0, 0xf8, 0xe4, 0x1c, 0x9d, 0x98, 0x15, 0xa8, 0x8f,
|
0x8c, 0x30, 0xed, 0xdd, 0x53, 0x6f, 0x29, 0x82, 0xf9, 0xe0, 0x74, 0xde,
|
||||||
0x08, 0x98, 0x4e, 0x5a, 0xfa, 0xd6, 0x60, 0x87, 0x12, 0xdc, 0x8e, 0xfd,
|
0xb1, 0x13, 0x01, 0x88, 0x8f, 0xce, 0x14, 0xc1, 0x3b, 0x90, 0xb7, 0xcc,
|
||||||
0xcb, 0xb3, 0x13, 0x97, 0x7a, 0xa8, 0x8c, 0x56, 0x2e, 0x49, 0x26, 0x60,
|
0x6c, 0xdf, 0x35, 0xa1, 0xf2, 0x1a, 0x3d, 0xbe, 0x19, 0xd7, 0x0a, 0xe4,
|
||||||
0xe9, 0x4a, 0xdc, 0xec, 0x3f, 0xf0, 0x94, 0xcd, 0x90, 0x8e, 0x7c, 0x21,
|
0x67, 0x75, 0xbb, 0xfa, 0x87, 0xf4, 0x03, 0xb5, 0x7f, 0x69, 0xe4, 0x0b,
|
||||||
0x3f, 0x80, 0x14, 0x33, 0xdd, 0xb0, 0x00, 0xe2, 0x09, 0x37, 0x06, 0xdd,
|
0x6a, 0xdc, 0x92, 0x82, 0x54, 0x64, 0x1a, 0x94, 0x2d, 0xe4, 0x63, 0x40,
|
||||||
0x17, 0x69, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x81, 0x00,
|
0xb2, 0xb4, 0x85, 0x6b, 0xc8, 0x34, 0xba, 0xa2, 0x14, 0x30, 0x47, 0x1a,
|
||||||
0xa1, 0xc9, 0x44, 0xad, 0x6d, 0x17, 0xd1, 0x04, 0x03, 0x89, 0x5f, 0xbf,
|
0xeb, 0x90, 0x62, 0x30, 0x43, 0x44, 0x02, 0xc7, 0x0c, 0x30, 0xc0, 0x7f,
|
||||||
0xe5, 0xcb, 0x68, 0x13, 0x52, 0xf2, 0x33, 0xb7, 0x19, 0x12, 0x19, 0x60,
|
0xa9, 0x47, 0xae, 0xde, 0x68, 0x27, 0x92, 0xaa, 0x11, 0x95, 0xf5, 0x6f,
|
||||||
0x6d, 0x0d, 0x0b, 0x48, 0x42, 0xe6, 0x9e, 0xbe, 0x05, 0x8a, 0xea, 0xeb,
|
0xfc, 0x19, 0x8b, 0x49, 0xa0, 0x77, 0x9d, 0xc6, 0x13, 0x5d, 0x73, 0xff,
|
||||||
0x58, 0xfb, 0xc8, 0x9a, 0xc2, 0x2f, 0xd5, 0x9f, 0x40, 0x09, 0xb8, 0x08,
|
0x45, 0xa2, 0x4c, 0x3b, 0xf3, 0xe1, 0x2d, 0xd7, 0xc4, 0x70, 0xe2, 0x6c,
|
||||||
0x2a, 0xe4, 0x4b, 0xcc, 0xba, 0xd9, 0xe3, 0x91, 0xc2, 0x64, 0xcb, 0x6c,
|
0x37, 0x99, 0x4c, 0x7a, 0xa9, 0x27, 0xf8, 0x3a, 0xd6, 0xfd, 0xc5, 0xd8,
|
||||||
0xa4, 0xb1, 0x17, 0x93, 0x7b, 0x10, 0x72, 0x83, 0x8d, 0xc2, 0xa2, 0x46,
|
0xfa, 0x2d, 0x0e, 0x71, 0x4b, 0x85, 0x7e, 0xce, 0xcb, 0x1c, 0x79, 0x71,
|
||||||
0x1b, 0x41, 0x12, 0xb9, 0x35, 0x5d, 0xf2, 0x32, 0xb1, 0xdf, 0x3a, 0x2a,
|
0xbd, 0xff, 0x63, 0x03, 0x6b, 0x58, 0x68, 0xe0, 0x14, 0xca, 0x5e, 0x85,
|
||||||
0xda, 0xbb, 0x61, 0x9d, 0x62, 0xdb, 0xb0, 0x77, 0x76, 0x7a, 0x68, 0xb4,
|
0xfd, 0xd0, 0xb7, 0xe0, 0x68, 0x14, 0xff, 0x2c, 0x82, 0x22, 0x26, 0x8a,
|
||||||
0x83, 0x10, 0x61, 0xac, 0x25, 0x01, 0x7d, 0x3e, 0x5f, 0x4a, 0x47, 0xf7,
|
0x3f, 0xbf, 0xb0, 0x2a, 0x90, 0xff, 0xc7, 0x72, 0xfc, 0x66, 0x51, 0x3e,
|
||||||
0x30, 0x1f, 0x82, 0x0a, 0xd7, 0x36, 0xff, 0x79, 0x5e, 0x42, 0x0f, 0x58,
|
0x51, 0x9f, 0x82, 0x68, 0x0e, 0xf3, 0x65, 0x74, 0x88, 0xab, 0xb7, 0xe5,
|
||||||
0xaa, 0x3a, 0xb8, 0x8b, 0x0e, 0xef, 0x00, 0xac, 0x96, 0x14, 0x96, 0x83,
|
0x97, 0x5f, 0x0f, 0x3e, 0xe5, 0x3a, 0xbc, 0xa4, 0xa1, 0x50, 0xdd, 0x5c,
|
||||||
0x33, 0xb6, 0xb5, 0x4c, 0x91, 0x2a, 0x62, 0x92, 0xcf, 0xd2, 0x27, 0xcc,
|
0x94, 0x4b, 0x0c, 0x70, 0x71, 0x48, 0x4e, 0xd0, 0xec, 0x46, 0x8f, 0xdf,
|
||||||
0xdf, 0x4c, 0x55, 0x03, 0xe8, 0x82, 0x78, 0xff, 0x80, 0xcb, 0x2e, 0x30,
|
0xa2, 0x9a, 0xfe, 0xd8, 0x35, 0x1a, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xcf,
|
||||||
0x1b, 0x85, 0x56, 0xce, 0x57, 0x9e, 0xd8, 0x16, 0x86, 0x7d, 0x87, 0x2e,
|
0x73, 0x8c, 0xbe, 0x6d, 0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75,
|
||||||
0xae, 0x39, 0xd4, 0xac, 0xbe, 0xa5, 0xc4, 0x5a, 0x85, 0x7a, 0xea, 0x8e,
|
0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9, 0x64, 0x60, 0x8c, 0x43,
|
||||||
0x69, 0x9a, 0xbd, 0x9c, 0x45, 0x33, 0xf8, 0xb1, 0x70, 0xc1, 0x8c, 0xaa,
|
0xeb, 0x85, 0xab, 0x04, 0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda,
|
||||||
0xad, 0x3d, 0x76, 0x08, 0x5b, 0x7d, 0x12, 0x93, 0x03, 0x70, 0xe6, 0x5f,
|
0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4, 0xde, 0x51, 0x4b, 0xb6,
|
||||||
0xb2, 0xac, 0x78, 0xae, 0xbe, 0xc5, 0x31, 0xc8, 0x6d, 0x2c, 0x1c, 0x2f,
|
0x51, 0x86, 0x7b, 0xd0, 0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f,
|
||||||
0x41, 0x37, 0xf6, 0x88, 0xd3, 0x80, 0x93, 0xed, 0x55, 0xb1, 0xaa, 0x49,
|
0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13, 0x93, 0xd7, 0x9c, 0x27,
|
||||||
0xe8, 0x42, 0xd0, 0x19, 0x20, 0x58, 0xe7, 0x2d, 0x10, 0xf2, 0x69, 0x49,
|
0x80, 0xb7, 0x1e, 0x64, 0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8,
|
||||||
0xe9, 0x47, 0x95, 0xbb, 0xce, 0xa7, 0xe9, 0x86, 0x46, 0x1c, 0xd1, 0x1f,
|
0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96, 0x90, 0x8f, 0xa2, 0x16,
|
||||||
0xd4, 0xa9, 0xeb, 0x28, 0x57, 0x78, 0x6c, 0xc6, 0x6f, 0x84, 0x3b, 0xb4,
|
0x22, 0x6a, 0xcc, 0x48, 0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44,
|
||||||
0x8c, 0xe5, 0xd3, 0x23, 0x8b, 0xbe, 0x83, 0x75, 0x5e, 0xea, 0xcd, 0x93,
|
0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27, 0x33, 0x85, 0x26, 0x60,
|
||||||
0xd2, 0x42, 0x86, 0xfd, 0x2b, 0x67, 0x72, 0xe0, 0x46, 0x9c, 0xf7, 0xc1,
|
0x48, 0x16, 0xcb, 0xef, 0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce,
|
||||||
0xe9, 0x5d, 0xad, 0xac, 0xcb, 0x57, 0xb4, 0xe7, 0x87, 0x25, 0x7d, 0x5a,
|
0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87, 0xc3, 0x41, 0x45, 0x97,
|
||||||
0x43, 0x90, 0xa3, 0x2e, 0xbf, 0x36, 0xbd, 0x4c, 0xba, 0xec, 0x0f, 0x21,
|
0xb1, 0x49, 0xc2, 0x19, 0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28,
|
||||||
0x51, 0xda, 0x66, 0xb8, 0x1e, 0xac, 0x33, 0xeb, 0xa1, 0x3e, 0x72, 0x15,
|
0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb, 0xbb, 0xdb, 0xfd, 0x11,
|
||||||
0x10, 0x45, 0xc0, 0xe4, 0xdb, 0x04, 0x6d, 0xaf, 0x66, 0xc2, 0xfc, 0x35,
|
0x9d, 0x17, 0x68, 0x78, 0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3,
|
||||||
0x04, 0x60, 0x7d, 0x2f, 0x5e, 0x9e, 0x83, 0xf6, 0x72, 0x92, 0x6a, 0x9f,
|
0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54, 0x91, 0x99, 0xe5, 0x91,
|
||||||
0xba, 0x94, 0x97, 0x33, 0xe1, 0x1d, 0x42, 0xda, 0xad, 0xa5, 0x8b, 0xad,
|
0x32, 0x2d, 0xeb, 0x3f, 0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41,
|
||||||
0x2f, 0x2f, 0x32, 0x16, 0x88, 0x54, 0x88, 0xb2, 0x85, 0xe2, 0x33, 0x08,
|
0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42, 0x58, 0xf4, 0xd0, 0xb2,
|
||||||
0x43, 0xc8, 0x68, 0x69, 0xaa, 0xea, 0x9a, 0xbf, 0x41, 0x12, 0xe6, 0xf1,
|
0x74, 0x1d, 0x8e, 0x87, 0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd,
|
||||||
0x02, 0x81, 0xc1, 0x00, 0xfe, 0x96, 0xe7, 0xc8, 0x89, 0x61, 0x2b, 0x58,
|
0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53, 0xda, 0xfb, 0xed, 0x83,
|
||||||
0xaa, 0xcd, 0x37, 0x46, 0x13, 0xa1, 0x2a, 0xc8, 0x1b, 0x76, 0xde, 0x4c,
|
0x51, 0x67, 0xa9, 0x55, 0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17,
|
||||||
0xb3, 0x00, 0x4f, 0x6b, 0x02, 0xc0, 0x10, 0xef, 0x87, 0xe2, 0x6d, 0x7f,
|
0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02, 0x81, 0x80, 0x67, 0x9c,
|
||||||
0x10, 0x57, 0xec, 0xde, 0x70, 0x60, 0xb5, 0x8f, 0x6d, 0x17, 0x35, 0xbd,
|
0x32, 0x83, 0x39, 0x57, 0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0,
|
||||||
0xfd, 0x6a, 0x2c, 0xbb, 0xf0, 0x48, 0x5b, 0x32, 0x41, 0xf6, 0xc0, 0x62,
|
0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97, 0xf3, 0x90, 0x9a, 0xab,
|
||||||
0x3a, 0x88, 0xc5, 0x41, 0x83, 0x85, 0x56, 0xa7, 0x11, 0xf4, 0xd2, 0xa9,
|
0x9b, 0x0b, 0x1b, 0x43, 0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c,
|
||||||
0xb3, 0xa3, 0xcb, 0xae, 0xca, 0xee, 0x1c, 0x52, 0x7f, 0x04, 0x34, 0x61,
|
0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80, 0xb8, 0xe1, 0xb3, 0xa1,
|
||||||
0xb9, 0x8d, 0xa3, 0x26, 0x88, 0xce, 0x3d, 0xdb, 0x9c, 0xbf, 0xcc, 0xc4,
|
0x6c, 0x25, 0x92, 0xe4, 0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f,
|
||||||
0x38, 0x8b, 0xf2, 0xe4, 0x7e, 0xcc, 0x46, 0x86, 0x7a, 0x3c, 0xb7, 0x95,
|
0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81, 0x20, 0x82, 0xa1, 0x48,
|
||||||
0x3f, 0xbd, 0x81, 0x45, 0xc3, 0x1d, 0xbb, 0xf8, 0x56, 0x6e, 0xa5, 0x88,
|
0x2c, 0x2d, 0x45, 0xdc, 0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41,
|
||||||
0x2d, 0xff, 0x78, 0xc0, 0xc2, 0x4a, 0x4f, 0xea, 0xb8, 0x81, 0xf3, 0x96,
|
0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54, 0xc8, 0x28, 0x10, 0x1e,
|
||||||
0x5e, 0xd8, 0xcb, 0x96, 0x42, 0xa3, 0x21, 0x03, 0xc8, 0x00, 0xbf, 0x95,
|
0x08, 0x71, 0x16, 0xd8, 0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5,
|
||||||
0xc7, 0x83, 0x80, 0xc6, 0xc2, 0x38, 0xe4, 0xaf, 0xb2, 0x0e, 0x80, 0x92,
|
0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf, 0x35, 0x95, 0x41, 0x29,
|
||||||
0x97, 0x21, 0x16, 0xce, 0x39, 0xd3, 0x95, 0xb7, 0xc3, 0x78, 0xe1, 0x1c,
|
0x40, 0x19, 0x83, 0x35, 0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b,
|
||||||
0xc0, 0x5a, 0xbc, 0x9b, 0x68, 0x3f, 0xd6, 0x42, 0xcd, 0xca, 0x0b, 0x6d,
|
0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae, 0x50, 0x76, 0x63, 0x94,
|
||||||
0x9f, 0xde, 0x6b, 0x98, 0x3b, 0x47, 0x57, 0xb9, 0x2d, 0x92, 0x52, 0x29,
|
0x49, 0x4c, 0xad, 0x10, 0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8,
|
||||||
0xc5, 0xed, 0xb5, 0x0d, 0x02, 0x81, 0xc1, 0x00, 0xf6, 0x64, 0xef, 0xef,
|
0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b, 0x8a, 0xa2, 0xb9, 0x8f,
|
||||||
0x57, 0xdb, 0x06, 0xae, 0x36, 0x86, 0x11, 0xaf, 0x96, 0xb9, 0xb1, 0x29,
|
0xce, 0xec, 0x5e, 0x61, 0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a,
|
||||||
0x53, 0xce, 0x24, 0x60, 0x96, 0x8f, 0xd0, 0xb7, 0x4b, 0x60, 0x1e, 0xb3,
|
0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69, 0xe4, 0x8b, 0x01, 0x06,
|
||||||
0x1f, 0xae, 0x15, 0x41, 0xf1, 0x56, 0xd6, 0xf3, 0x07, 0xf8, 0xd7, 0xdd,
|
0x59, 0x22, 0xfa, 0x34, 0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a,
|
||||||
0x1c, 0x82, 0xe8, 0xe0, 0xff, 0xb3, 0x41, 0x0d, 0x41, 0x96, 0x0d, 0xf2,
|
0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26, 0x6c, 0xfa, 0x2b, 0xd9,
|
||||||
0x03, 0xb0, 0x68, 0xed, 0xda, 0x8b, 0x83, 0x18, 0x4d, 0xae, 0xaf, 0x72,
|
0x83, 0x5a, 0x2d, 0x0c, 0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a,
|
||||||
0xa1, 0x82, 0xe5, 0x5a, 0xdc, 0x2a, 0x5f, 0x93, 0x29, 0xc7, 0x24, 0xa0,
|
0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3, 0x66, 0xff, 0x1c, 0x1b,
|
||||||
0x8e, 0x32, 0x4c, 0x0e, 0xca, 0x6d, 0x14, 0x69, 0x5b, 0x61, 0xc5, 0xdc,
|
0xc8, 0x96, 0x76, 0xe8, 0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8,
|
||||||
0x0e, 0x50, 0x0c, 0x14, 0x84, 0x8b, 0xee, 0x9e, 0x1e, 0x8c, 0x3d, 0xdb,
|
0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80, 0x2c, 0x7c, 0xad, 0x1e,
|
||||||
0x24, 0xe7, 0x99, 0x6d, 0x3c, 0xaf, 0xe6, 0x3b, 0xaa, 0xb4, 0xe4, 0x42,
|
0x75, 0xf6, 0x69, 0x1d, 0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65,
|
||||||
0x13, 0x53, 0x3e, 0x02, 0x47, 0x0d, 0x3a, 0x2b, 0x97, 0x71, 0x9f, 0x1b,
|
0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57, 0xae, 0xb7, 0x65, 0x2c,
|
||||||
0x76, 0x2d, 0xe5, 0x9c, 0x5e, 0x46, 0x5f, 0x36, 0xbf, 0x18, 0xb1, 0x1d,
|
0x52, 0xf9, 0xe4, 0xc7, 0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33,
|
||||||
0x9a, 0xeb, 0x4d, 0x5e, 0x83, 0xd5, 0x3e, 0x5f, 0xf2, 0x6a, 0x56, 0x79,
|
0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50, 0x75, 0x61, 0x96, 0x86,
|
||||||
0x0f, 0x54, 0xec, 0x41, 0xc0, 0xdc, 0x29, 0x42, 0x45, 0xae, 0x47, 0x1c,
|
0x4b, 0xb6, 0x2b, 0xad, 0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35,
|
||||||
0x7a, 0xd5, 0xb7, 0x92, 0x1e, 0x66, 0xb8, 0x1a, 0x2f, 0x53, 0xd2, 0x6d,
|
0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a, 0xd3, 0x29, 0x23, 0x02,
|
||||||
0x42, 0x3c, 0x6c, 0x02, 0x01, 0x03, 0x9e, 0x9a, 0x95, 0x35, 0x81, 0x21,
|
0x60, 0xf7, 0xab, 0x30, 0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4,
|
||||||
0x53, 0x53, 0x16, 0xda, 0x8a, 0x80, 0x8c, 0xcd, 0x02, 0x81, 0xc1, 0x00,
|
0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18, 0xf4, 0xd4, 0x52, 0x95,
|
||||||
0xd5, 0xba, 0x05, 0xf7, 0x7a, 0x2d, 0x52, 0xe0, 0x6a, 0xf3, 0x40, 0xd5,
|
0x00, 0xae, 0x84, 0x6b, 0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde,
|
||||||
0xd9, 0xa0, 0xd1, 0x73, 0x90, 0x6a, 0xe8, 0x10, 0x67, 0xad, 0x78, 0xfe,
|
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28,
|
||||||
0x93, 0x1e, 0x7e, 0x99, 0x37, 0xf0, 0x44, 0x90, 0x09, 0x3e, 0x67, 0x22,
|
0x33, 0xe0, 0xdb, 0x03
|
||||||
0x0e, 0x21, 0x82, 0x0a, 0x58, 0x40, 0xc5, 0xe3, 0x2b, 0x9d, 0x38, 0xd4,
|
|
||||||
0xc5, 0xd1, 0x58, 0x8e, 0x06, 0x86, 0x89, 0xd7, 0x6c, 0xe0, 0x69, 0x08,
|
|
||||||
0xa8, 0xcb, 0x05, 0x85, 0xd8, 0x33, 0x39, 0xaf, 0x31, 0x99, 0xee, 0x62,
|
|
||||||
0x5d, 0x06, 0x2c, 0x4c, 0xad, 0x48, 0xf0, 0x58, 0xa2, 0x17, 0x5f, 0xc1,
|
|
||||||
0xf7, 0xd3, 0x7c, 0x66, 0xa3, 0x5e, 0xf9, 0x1e, 0x39, 0x82, 0x73, 0x74,
|
|
||||||
0x93, 0x66, 0x16, 0x46, 0xca, 0xd3, 0xb2, 0x22, 0xdf, 0x91, 0xcd, 0xb6,
|
|
||||||
0xad, 0x28, 0x87, 0x26, 0xe2, 0x18, 0x9d, 0x6a, 0x87, 0x83, 0x12, 0xf2,
|
|
||||||
0x6f, 0xa9, 0x47, 0x11, 0xfb, 0xb7, 0x4c, 0xb1, 0x0e, 0x0a, 0xde, 0x4e,
|
|
||||||
0xd4, 0xbe, 0x71, 0xf6, 0xe4, 0xae, 0x8c, 0x27, 0xc7, 0x88, 0x84, 0x51,
|
|
||||||
0x57, 0xb7, 0xbf, 0x74, 0x27, 0xfc, 0xb8, 0xbf, 0x57, 0x94, 0x75, 0xba,
|
|
||||||
0xc7, 0x1c, 0xf3, 0x71, 0x83, 0xee, 0x34, 0xbd, 0x98, 0x56, 0x14, 0x44,
|
|
||||||
0x3a, 0xee, 0x6c, 0x87, 0x44, 0x8f, 0xbb, 0xac, 0x5a, 0x2b, 0xb5, 0x13,
|
|
||||||
0xe5, 0x9f, 0xec, 0xeb, 0x0e, 0x70, 0xe9, 0xfd, 0x1b, 0xa6, 0x84, 0xf9,
|
|
||||||
0x02, 0x81, 0xc0, 0x4e, 0x82, 0x26, 0xf9, 0x6a, 0x52, 0xfd, 0xb3, 0xf0,
|
|
||||||
0xe7, 0x93, 0x27, 0x11, 0xad, 0xa5, 0x47, 0x77, 0xce, 0x8d, 0x44, 0xc1,
|
|
||||||
0x74, 0x9d, 0x9a, 0x69, 0xc7, 0xfc, 0xc0, 0x32, 0x6d, 0xf3, 0x94, 0x09,
|
|
||||||
0x64, 0x14, 0x25, 0x67, 0xfa, 0xe0, 0x3d, 0x31, 0xe2, 0x7c, 0x75, 0x84,
|
|
||||||
0xc4, 0x07, 0x0c, 0x44, 0x43, 0x9d, 0xb9, 0xe9, 0x77, 0x02, 0x58, 0x17,
|
|
||||||
0x74, 0xb0, 0x96, 0xc3, 0xd9, 0xcf, 0x49, 0x85, 0x31, 0x02, 0x07, 0x8b,
|
|
||||||
0x73, 0x6c, 0xf4, 0xa5, 0x31, 0x30, 0xf8, 0x7f, 0x96, 0x83, 0x29, 0x8b,
|
|
||||||
0x52, 0x6a, 0x58, 0x8f, 0xa7, 0x7d, 0xb5, 0xfa, 0x51, 0x83, 0x27, 0xde,
|
|
||||||
0x7b, 0xff, 0xd2, 0x1e, 0x05, 0xad, 0x87, 0xf0, 0x20, 0x63, 0x80, 0xac,
|
|
||||||
0xff, 0x97, 0x2a, 0x97, 0xdf, 0xff, 0x83, 0x16, 0x49, 0x45, 0xce, 0xcf,
|
|
||||||
0xf8, 0xe4, 0xfa, 0x12, 0xcd, 0x3f, 0x57, 0x2e, 0xb6, 0xbd, 0x1c, 0xaf,
|
|
||||||
0xe5, 0x58, 0x5d, 0x47, 0x52, 0x84, 0xcc, 0xdc, 0x19, 0xf1, 0x93, 0x16,
|
|
||||||
0x0a, 0x92, 0x4f, 0x5c, 0x1c, 0x89, 0xe5, 0x14, 0xff, 0x88, 0x30, 0x03,
|
|
||||||
0x55, 0xa3, 0x47, 0xdc, 0x90, 0x05, 0x54, 0x8b, 0xc7, 0x21, 0x30, 0xcb,
|
|
||||||
0xc3, 0x0b, 0x12, 0x3c, 0xd6, 0x46, 0x8c, 0x4d, 0xb8, 0x96, 0xe9, 0xa4,
|
|
||||||
0x8d, 0x14, 0xb2, 0x48, 0xac, 0xbd, 0xb2, 0x72, 0xac, 0x5c, 0xf1, 0xd1,
|
|
||||||
0x83, 0xd8, 0x59, 0x02, 0x81, 0xc0, 0x2d, 0x65, 0xc1, 0xc7, 0x0f, 0xca,
|
|
||||||
0xbc, 0x5d, 0xa1, 0x30, 0x28, 0x27, 0x51, 0xcc, 0xc9, 0x6c, 0x7b, 0x76,
|
|
||||||
0x43, 0xa9, 0x77, 0xd8, 0x29, 0xa3, 0x80, 0x57, 0x3b, 0xe9, 0x72, 0x1c,
|
|
||||||
0x51, 0x37, 0xc2, 0x0b, 0x74, 0xb7, 0xaa, 0x63, 0xd5, 0xe2, 0x9b, 0x3a,
|
|
||||||
0x3c, 0x78, 0x50, 0xcb, 0x88, 0x1a, 0xd6, 0x59, 0xdc, 0xb3, 0x05, 0xbf,
|
|
||||||
0xe5, 0xc5, 0xb5, 0xe3, 0x9b, 0xba, 0xe7, 0xbb, 0x4d, 0x45, 0xb3, 0x4c,
|
|
||||||
0xf2, 0x48, 0x65, 0xe7, 0x6b, 0xee, 0x12, 0xc8, 0xd5, 0xea, 0xf0, 0x89,
|
|
||||||
0xf9, 0x03, 0xa3, 0xd9, 0x5f, 0x62, 0x2d, 0x1a, 0x55, 0x51, 0x5d, 0xf6,
|
|
||||||
0xca, 0x6e, 0x5f, 0xf0, 0x66, 0x02, 0xf4, 0x20, 0xe6, 0xe9, 0xc4, 0xd7,
|
|
||||||
0x36, 0x8d, 0x00, 0xce, 0x23, 0xfd, 0x90, 0xd4, 0x19, 0x5c, 0xe9, 0xcb,
|
|
||||||
0x23, 0xe2, 0x2c, 0xf5, 0xe1, 0x6f, 0x9d, 0xb5, 0xdf, 0xea, 0x51, 0xdd,
|
|
||||||
0x02, 0xd8, 0x40, 0xd6, 0x7f, 0x4b, 0xdb, 0x0e, 0xe2, 0x27, 0x4d, 0x0d,
|
|
||||||
0x9b, 0x2e, 0xf7, 0xc8, 0x22, 0xca, 0x63, 0x3c, 0x2c, 0xe5, 0xa8, 0x42,
|
|
||||||
0x26, 0xd9, 0xfc, 0xdc, 0x42, 0xc8, 0x07, 0x64, 0xa2, 0x98, 0xae, 0xb4,
|
|
||||||
0x57, 0x02, 0x02, 0xb2, 0x2d, 0xc8, 0x59, 0x73, 0x9b, 0xee, 0xc0, 0x9a,
|
|
||||||
0x42, 0x9a, 0xef, 0xc2, 0x27, 0x24, 0x2b, 0x20, 0x92, 0xad, 0x50, 0xfe,
|
|
||||||
0x2c, 0x2d, 0xb6, 0xb6, 0xb5, 0xba
|
|
||||||
};
|
};
|
||||||
extern const size_t kOEMPrivateKeySize_Prod = 1794;
|
|
||||||
|
|
||||||
extern const uint8_t kOEMPublicCert_Prod[] = {
|
const size_t kOEMPrivateKeySize_Prod = sizeof(kOEMPrivateKey_Prod);
|
||||||
0x30, 0x82, 0x09, 0xf7, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
|
||||||
0x01, 0x07, 0x02, 0xa0, 0x82, 0x09, 0xe8, 0x30, 0x82, 0x09, 0xe4, 0x02,
|
// From the team shared drive file
|
||||||
0x01, 0x01, 0x31, 0x00, 0x30, 0x0f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
// oem-7913-leaf-and-intermediate-certs-test-key-2-carmichael.p7b, size 2353.
|
||||||
0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x02, 0x04, 0x00, 0xa0, 0x82, 0x09,
|
const uint8_t kOEMPublicCert_Prod[] = {
|
||||||
0xc8, 0x30, 0x82, 0x04, 0x1a, 0x30, 0x82, 0x03, 0x02, 0xa0, 0x03, 0x02,
|
0x30, 0x82, 0x09, 0x2d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||||
0x01, 0x02, 0x02, 0x11, 0x00, 0xf2, 0xa1, 0x08, 0xdf, 0x12, 0x84, 0xb9,
|
0x01, 0x07, 0x02, 0xa0, 0x82, 0x09, 0x1e, 0x30, 0x82, 0x09, 0x1a, 0x02,
|
||||||
0x73, 0x6c, 0x23, 0x73, 0xe1, 0x1f, 0xf3, 0xac, 0x7a, 0x30, 0x0d, 0x06,
|
0x01, 0x01, 0x31, 0x00, 0x30, 0x0f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
||||||
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
|
0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x02, 0x04, 0x00, 0xa0, 0x82, 0x08,
|
||||||
0x30, 0x81, 0x8b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
|
0xfe, 0x30, 0x82, 0x03, 0x71, 0x30, 0x82, 0x02, 0x59, 0xa0, 0x03, 0x02,
|
||||||
0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
|
0x01, 0x02, 0x02, 0x11, 0x00, 0xc2, 0x8d, 0x20, 0x22, 0x82, 0x8b, 0x9e,
|
||||||
0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f,
|
0x63, 0x9d, 0x15, 0x89, 0x2c, 0xa9, 0x8f, 0xd9, 0x5d, 0x30, 0x0d, 0x06,
|
||||||
0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08,
|
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
|
||||||
0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d,
|
0x30, 0x6b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
|
||||||
0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
|
0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08,
|
||||||
0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08,
|
0x0c, 0x02, 0x57, 0x41, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
|
||||||
0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, 0x30, 0x30, 0x2e,
|
0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31,
|
||||||
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x27, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
|
0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f,
|
||||||
0x65, 0x20, 0x4f, 0x45, 0x4d, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x44,
|
0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
|
||||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x3b, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
|
0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31,
|
||||||
0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, 0x37, 0x33, 0x34, 0x36, 0x30, 0x1e,
|
0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x73, 0x79,
|
||||||
0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30,
|
0x73, 0x74, 0x65, 0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, 0x37, 0x39, 0x31,
|
||||||
0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x32, 0x30, 0x38, 0x30,
|
0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x31, 0x31, 0x31, 0x31,
|
||||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x6d, 0x31, 0x12, 0x30, 0x10,
|
0x33, 0x32, 0x36, 0x32, 0x32, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31,
|
||||||
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x37, 0x33, 0x34, 0x36, 0x2d,
|
0x30, 0x36, 0x31, 0x33, 0x32, 0x36, 0x32, 0x32, 0x5a, 0x30, 0x65, 0x31,
|
||||||
0x6c, 0x65, 0x61, 0x66, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x37, 0x39,
|
||||||
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
|
0x31, 0x33, 0x2d, 0x6c, 0x65, 0x61, 0x66, 0x31, 0x0b, 0x30, 0x09, 0x06,
|
||||||
0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74,
|
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09,
|
||||||
0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
|
0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x11, 0x30,
|
||||||
0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30,
|
0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b,
|
||||||
0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
|
0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04,
|
||||||
0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
|
0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30,
|
||||||
0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x30, 0x82, 0x01,
|
0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65,
|
||||||
0xa2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
|
0x76, 0x69, 0x6e, 0x65, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
|
||||||
0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x8f, 0x00, 0x30, 0x82, 0x01,
|
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
|
||||||
0x8a, 0x02, 0x82, 0x01, 0x81, 0x00, 0xf5, 0x09, 0x64, 0x4a, 0x26, 0xfe,
|
0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
|
||||||
0xc0, 0x98, 0x55, 0x6a, 0x1d, 0x5d, 0x1c, 0xc7, 0x38, 0xaf, 0xfd, 0x49,
|
0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a, 0x40,
|
||||||
0x9e, 0x85, 0x3f, 0xd6, 0x45, 0x0e, 0x99, 0x09, 0x85, 0x69, 0x84, 0x3c,
|
0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f, 0x94, 0x58, 0xdd, 0xde, 0xa7,
|
||||||
0xfe, 0x72, 0xa5, 0x56, 0xfa, 0x11, 0x4f, 0x6b, 0x7d, 0x32, 0x2b, 0x0c,
|
0x1f, 0x3c, 0x2c, 0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e, 0x56,
|
||||||
0xbf, 0x8f, 0xac, 0x47, 0x96, 0x22, 0x82, 0x3d, 0xf5, 0x64, 0x74, 0x7e,
|
0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a, 0x2a, 0xaa, 0x9d, 0xb4, 0x4e,
|
||||||
0x62, 0x68, 0x74, 0xcd, 0x0a, 0xec, 0x84, 0xc5, 0x15, 0x06, 0x0e, 0x5a,
|
0xfa, 0xa7, 0x6a, 0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3, 0x34,
|
||||||
0x2f, 0x20, 0xe3, 0xc9, 0x67, 0xcd, 0xdd, 0x01, 0xb8, 0xb3, 0x18, 0x87,
|
0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f, 0x28, 0xda, 0x3f, 0xce, 0x31,
|
||||||
0x8c, 0xa9, 0x58, 0x86, 0x0f, 0xb6, 0xc3, 0x42, 0x7e, 0x87, 0x48, 0x5e,
|
0x7b, 0xfd, 0x06, 0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb, 0x3e,
|
||||||
0x10, 0x49, 0xc7, 0xd7, 0xb7, 0xb8, 0xa6, 0x34, 0x08, 0x0c, 0x94, 0xf4,
|
0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3, 0x29, 0xf2, 0x73, 0x9e, 0x39,
|
||||||
0xbb, 0x2a, 0x06, 0xa4, 0x4f, 0xec, 0xbc, 0xc4, 0x37, 0xbe, 0x99, 0x10,
|
0xd8, 0xf6, 0x6f, 0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4, 0xf2,
|
||||||
0x23, 0x37, 0x24, 0xb1, 0xdf, 0xcb, 0xe6, 0x3f, 0xc1, 0xf0, 0x0f, 0x04,
|
0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04, 0xcd, 0x9a, 0x13, 0x8b, 0x54,
|
||||||
0x03, 0xc8, 0xb0, 0x1e, 0xd6, 0xb8, 0xae, 0x77, 0xe1, 0x4d, 0x6d, 0x97,
|
0x73, 0x54, 0x25, 0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda, 0xb3,
|
||||||
0x69, 0x6d, 0x8a, 0x73, 0x66, 0x32, 0x57, 0x6f, 0xcf, 0xea, 0x1e, 0x7b,
|
0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67, 0x98, 0x56, 0x57, 0x54, 0x71,
|
||||||
0x87, 0x03, 0x75, 0xb1, 0xef, 0x83, 0x64, 0x26, 0xf1, 0x3f, 0xbf, 0xe6,
|
0xcd, 0x12, 0x7f, 0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03, 0x96,
|
||||||
0x28, 0x03, 0x72, 0x57, 0xbf, 0x47, 0x29, 0x99, 0x8f, 0x74, 0x1d, 0x01,
|
0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53, 0xc9, 0x83, 0x06, 0x51, 0x5a,
|
||||||
0x16, 0xad, 0xb2, 0xdf, 0x80, 0xa4, 0xd3, 0x8b, 0xeb, 0x61, 0xd1, 0x40,
|
0x88, 0x65, 0x13, 0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b, 0x4c,
|
||||||
0x68, 0xb9, 0xa2, 0xa5, 0xef, 0x2b, 0xe5, 0x78, 0xe8, 0x28, 0x88, 0x87,
|
0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e, 0x2d, 0x5f, 0xf8, 0x12, 0x7f,
|
||||||
0xb7, 0x53, 0x49, 0xbb, 0xe4, 0xea, 0x0d, 0x5e, 0x96, 0xa5, 0xdd, 0x1f,
|
0xa2, 0xfc, 0xbb, 0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01, 0xca,
|
||||||
0x0b, 0x25, 0x8b, 0xb5, 0x95, 0x46, 0xe7, 0xba, 0xb8, 0xc4, 0x0a, 0x36,
|
0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87, 0x82, 0x46, 0x0b, 0x3a, 0x77,
|
||||||
0xb1, 0x89, 0xeb, 0x27, 0x5d, 0xd9, 0x97, 0x24, 0x59, 0xa3, 0x9b, 0xb0,
|
0x8f, 0xc0, 0x72, 0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed, 0x27,
|
||||||
0x23, 0x0b, 0xd2, 0xec, 0x65, 0x91, 0xf9, 0xf0, 0xa0, 0x74, 0x5f, 0xb4,
|
0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44, 0xd3, 0x5b, 0x3d, 0xdb, 0x9c,
|
||||||
0xce, 0x22, 0x27, 0x18, 0x37, 0xe2, 0x4b, 0xfc, 0x91, 0xf9, 0x09, 0x15,
|
0x5e, 0x1b, 0x7b, 0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb, 0x2c,
|
||||||
0xe6, 0xdb, 0x06, 0x9b, 0x4d, 0x82, 0xdc, 0x36, 0x14, 0x48, 0xc6, 0xd5,
|
0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x16,
|
||||||
0x87, 0xca, 0xec, 0x5a, 0xa2, 0x29, 0x33, 0xef, 0x22, 0x0c, 0x4b, 0xbf,
|
0x30, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6,
|
||||||
0xe7, 0x2f, 0x95, 0xe1, 0xd3, 0xa5, 0xd8, 0xaa, 0x44, 0x77, 0x29, 0xa3,
|
0x79, 0x04, 0x01, 0x01, 0x04, 0x04, 0x02, 0x02, 0x1e, 0xe9, 0x30, 0x0d,
|
||||||
0x20, 0x33, 0xd2, 0x51, 0xa2, 0xf9, 0x4a, 0x6f, 0xf7, 0x3e, 0xf7, 0x0b,
|
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
|
||||||
0x8a, 0xec, 0xc1, 0x99, 0x1d, 0x47, 0xf3, 0x74, 0x02, 0x04, 0xab, 0x8e,
|
0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x88, 0x95, 0xec, 0xcd, 0x8b, 0xa7,
|
||||||
0x62, 0x4c, 0x9e, 0x00, 0xc2, 0x84, 0xd7, 0xd0, 0xf8, 0xe4, 0x1c, 0x9d,
|
0x51, 0xda, 0x74, 0x81, 0xa5, 0x39, 0x62, 0x1a, 0x0e, 0x2e, 0xde, 0x3c,
|
||||||
0x98, 0x15, 0xa8, 0x8f, 0x08, 0x98, 0x4e, 0x5a, 0xfa, 0xd6, 0x60, 0x87,
|
0x37, 0xea, 0xad, 0x7c, 0xee, 0x9b, 0x26, 0x8e, 0xe2, 0xd6, 0x34, 0xcd,
|
||||||
0x12, 0xdc, 0x8e, 0xfd, 0xcb, 0xb3, 0x13, 0x97, 0x7a, 0xa8, 0x8c, 0x56,
|
0xb7, 0x70, 0xba, 0xbf, 0xa0, 0xa3, 0xfe, 0xb3, 0x4b, 0xbc, 0xf4, 0x1c,
|
||||||
0x2e, 0x49, 0x26, 0x60, 0xe9, 0x4a, 0xdc, 0xec, 0x3f, 0xf0, 0x94, 0xcd,
|
0x72, 0x66, 0x81, 0xd5, 0x09, 0x33, 0x78, 0x0c, 0x61, 0x21, 0xa8, 0xf1,
|
||||||
0x90, 0x8e, 0x7c, 0x21, 0x3f, 0x80, 0x14, 0x33, 0xdd, 0xb0, 0x00, 0xe2,
|
0xe2, 0xc9, 0xe2, 0x83, 0xc2, 0x19, 0x02, 0xf2, 0xe8, 0xab, 0x17, 0x36,
|
||||||
0x09, 0x37, 0x06, 0xdd, 0x17, 0x69, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
|
0x3a, 0x0b, 0x20, 0xaf, 0x0f, 0xae, 0x2e, 0x73, 0x68, 0xac, 0x15, 0xee,
|
||||||
0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
|
0x9c, 0xc0, 0x92, 0x03, 0x7e, 0x95, 0x63, 0xaa, 0xad, 0x15, 0x96, 0x43,
|
||||||
0xd6, 0x79, 0x04, 0x01, 0x01, 0x04, 0x04, 0x02, 0x02, 0x1c, 0xb2, 0x30,
|
0x20, 0x3b, 0xe5, 0x9b, 0x1f, 0xca, 0x02, 0xba, 0xf0, 0x07, 0x76, 0x80,
|
||||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
|
0xd7, 0xa3, 0x1a, 0xeb, 0xc8, 0xdb, 0x03, 0x7b, 0x43, 0x56, 0xe5, 0x96,
|
||||||
0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x8e, 0x2d, 0x13, 0x1e, 0x60,
|
0x6b, 0x86, 0xfe, 0x08, 0x58, 0x8a, 0x84, 0xbd, 0xe9, 0x47, 0x18, 0xee,
|
||||||
0xaa, 0xda, 0x52, 0x53, 0x55, 0x64, 0x3a, 0xdc, 0xb6, 0x7a, 0xc0, 0xba,
|
0xb2, 0xa8, 0x05, 0x7b, 0xf0, 0xfd, 0xaa, 0xb9, 0x85, 0xcd, 0x7a, 0x0e,
|
||||||
0xfa, 0xeb, 0x20, 0xab, 0xb6, 0x63, 0xcf, 0xcd, 0x9b, 0xdb, 0x71, 0xf3,
|
0x6b, 0x6c, 0x9f, 0xc6, 0x75, 0xd2, 0x2a, 0xfe, 0x5b, 0xf3, 0xb7, 0x31,
|
||||||
0xa0, 0xd6, 0x91, 0xbf, 0x0c, 0xc1, 0xae, 0x8f, 0x02, 0x18, 0x00, 0x54,
|
0x6c, 0xac, 0xe3, 0x00, 0x9f, 0xe7, 0xdd, 0xe3, 0x81, 0xc1, 0x36, 0xc3,
|
||||||
0xfb, 0x49, 0x03, 0x34, 0x8d, 0x92, 0x9d, 0x5d, 0x8d, 0xa8, 0x1c, 0x20,
|
0x1c, 0x5f, 0xdf, 0xf2, 0xc3, 0x5e, 0xfa, 0x55, 0x32, 0xd8, 0x5c, 0xa8,
|
||||||
0x0f, 0x85, 0x60, 0xf9, 0xf6, 0x8b, 0xbb, 0x2b, 0x82, 0xce, 0xb3, 0xe2,
|
0xe5, 0xcc, 0xb6, 0x4a, 0xe9, 0xe2, 0xcc, 0x38, 0x44, 0x07, 0x46, 0x59,
|
||||||
0x91, 0xe7, 0xbd, 0x91, 0x61, 0x52, 0x36, 0x40, 0x9f, 0x2f, 0x5e, 0xa6,
|
0x34, 0x84, 0x79, 0xf9, 0xee, 0x3c, 0x4b, 0x48, 0x90, 0xab, 0x73, 0xb0,
|
||||||
0x5d, 0x2f, 0xb3, 0x81, 0xe7, 0xf1, 0x87, 0xbe, 0xc5, 0x9d, 0x67, 0x5a,
|
0xa1, 0x92, 0xc3, 0xd6, 0x83, 0x87, 0x81, 0xca, 0x12, 0x81, 0xd6, 0x5d,
|
||||||
0xf7, 0x41, 0x1e, 0x73, 0xb0, 0x1e, 0xdc, 0x4f, 0x8d, 0x53, 0x21, 0x38,
|
0xf7, 0x6f, 0x7a, 0x35, 0x5e, 0x4f, 0x02, 0x66, 0x8a, 0x47, 0x88, 0x82,
|
||||||
0x1b, 0xfd, 0x92, 0x43, 0x68, 0x83, 0x03, 0xd0, 0x9a, 0xca, 0x92, 0x14,
|
0xab, 0xf0, 0x12, 0x1d, 0xb9, 0x75, 0x3b, 0x7b, 0xa8, 0x36, 0x15, 0xef,
|
||||||
0x73, 0x04, 0x94, 0x2a, 0x93, 0x22, 0x60, 0x5e, 0xee, 0xb6, 0xec, 0x0f,
|
0xa8, 0x12, 0x0e, 0x53, 0xb4, 0x83, 0x78, 0x53, 0xc0, 0x52, 0xae, 0xa6,
|
||||||
0xb0, 0xc8, 0x92, 0x97, 0xfb, 0x5d, 0xed, 0x1f, 0xa0, 0x5f, 0xe4, 0x98,
|
0x0a, 0xa0, 0x53, 0xdc, 0x1c, 0x15, 0x22, 0xdd, 0x17, 0x98, 0x30, 0x82,
|
||||||
0x2f, 0xf6, 0x13, 0x78, 0x99, 0xec, 0xb3, 0xf1, 0x0d, 0x27, 0xaa, 0x19,
|
0x05, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
|
||||||
0x95, 0x39, 0xdb, 0xb0, 0x7b, 0x96, 0x74, 0x03, 0x5e, 0x51, 0xf5, 0x15,
|
0x10, 0x03, 0xb1, 0xf7, 0x58, 0xdf, 0x1d, 0xe3, 0x25, 0x00, 0x0b, 0x10,
|
||||||
0x27, 0xce, 0xca, 0x0b, 0x2a, 0x0d, 0x43, 0xb3, 0x68, 0x17, 0x1e, 0x11,
|
0x3d, 0xd5, 0xe6, 0xe4, 0x64, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||||
0x60, 0xd9, 0x84, 0x9b, 0xc3, 0x53, 0xce, 0xbd, 0xf4, 0x61, 0x51, 0x4b,
|
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x7e, 0x31, 0x0b,
|
||||||
0x41, 0x00, 0x7e, 0xe1, 0x5f, 0x69, 0xb3, 0x4a, 0x89, 0x7e, 0x47, 0x67,
|
0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
|
||||||
0xfd, 0x76, 0xf8, 0x94, 0x2f, 0x72, 0xb6, 0x14, 0x08, 0x2c, 0x16, 0x4e,
|
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61,
|
||||||
0x9d, 0x37, 0x62, 0xbf, 0x11, 0x67, 0xc0, 0x70, 0x71, 0xec, 0x55, 0x51,
|
0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f,
|
||||||
0x4e, 0x46, 0x76, 0xb4, 0xc3, 0xeb, 0x52, 0x06, 0x17, 0x06, 0xce, 0x61,
|
0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c,
|
||||||
0x43, 0xce, 0x26, 0x80, 0x68, 0xb6, 0x2d, 0x57, 0xba, 0x8c, 0x7d, 0xb7,
|
0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a,
|
||||||
0xc5, 0x05, 0x2c, 0xf8, 0xa3, 0x69, 0xf8, 0x96, 0xad, 0xac, 0xd1, 0x30,
|
0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f,
|
||||||
0x82, 0x05, 0xa6, 0x30, 0x82, 0x03, 0x8e, 0xa0, 0x03, 0x02, 0x01, 0x02,
|
0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65, 0x76,
|
||||||
0x02, 0x10, 0x73, 0xd1, 0xe1, 0x1d, 0xa9, 0x75, 0xfd, 0x0c, 0xda, 0x7f,
|
0x69, 0x6e, 0x65, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||||
0xfa, 0x43, 0x3c, 0x26, 0xbd, 0x3d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
|
0x0c, 0x1a, 0x77, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x2e, 0x63,
|
||||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x7e, 0x31,
|
0x6f, 0x6d, 0x2f, 0x6f, 0x65, 0x6d, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d,
|
||||||
0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
|
0x70, 0x72, 0x6f, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x31, 0x31,
|
||||||
0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57,
|
0x31, 0x38, 0x30, 0x31, 0x31, 0x33, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x32,
|
||||||
0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x11, 0x30,
|
0x37, 0x31, 0x31, 0x31, 0x38, 0x30, 0x31, 0x31, 0x33, 0x31, 0x33, 0x5a,
|
||||||
0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b,
|
0x30, 0x6b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
|
||||||
0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04,
|
0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08,
|
||||||
0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30,
|
0x0c, 0x02, 0x57, 0x41, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
|
||||||
0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65,
|
0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31,
|
||||||
0x76, 0x69, 0x6e, 0x65, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04,
|
0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f,
|
||||||
0x03, 0x0c, 0x1a, 0x77, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x2e,
|
0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
|
||||||
0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x65, 0x6d, 0x2d, 0x72, 0x6f, 0x6f, 0x74,
|
0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31,
|
||||||
0x2d, 0x70, 0x72, 0x6f, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30,
|
0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x73, 0x79,
|
||||||
0x33, 0x31, 0x34, 0x30, 0x33, 0x30, 0x32, 0x34, 0x31, 0x5a, 0x17, 0x0d,
|
0x73, 0x74, 0x65, 0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, 0x37, 0x39, 0x31,
|
||||||
0x32, 0x37, 0x30, 0x33, 0x31, 0x34, 0x30, 0x33, 0x30, 0x32, 0x34, 0x31,
|
0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||||
0x5a, 0x30, 0x81, 0x8b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
|
||||||
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
|
0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xae, 0xc8,
|
||||||
0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74,
|
0x71, 0xae, 0x08, 0x0c, 0x06, 0x06, 0x2d, 0x81, 0x7c, 0xa9, 0x8b, 0xb3,
|
||||||
0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
|
0xd6, 0x66, 0xe4, 0xf6, 0x08, 0x5e, 0x5a, 0x75, 0xe8, 0x74, 0x61, 0x7a,
|
||||||
0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30,
|
0x88, 0xca, 0x85, 0x14, 0x0d, 0x58, 0xa4, 0x09, 0x19, 0x6c, 0x60, 0xc9,
|
||||||
0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
|
0xad, 0x91, 0x1c, 0xbf, 0x04, 0xb3, 0x47, 0x10, 0x63, 0x7f, 0x02, 0x58,
|
||||||
0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
|
0xc2, 0x1e, 0xbd, 0xcc, 0x07, 0x77, 0xaa, 0x7e, 0x14, 0xa8, 0xc2, 0x01,
|
||||||
0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, 0x30, 0x30,
|
0xcd, 0xe8, 0x46, 0x60, 0x53, 0x6f, 0x2f, 0xda, 0x17, 0x2d, 0x4d, 0x9d,
|
||||||
0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x27, 0x47, 0x6f, 0x6f, 0x67,
|
0x0e, 0x5d, 0xb5, 0x50, 0x95, 0xae, 0xab, 0x6e, 0x43, 0xe3, 0xb0, 0x00,
|
||||||
0x6c, 0x65, 0x20, 0x4f, 0x45, 0x4d, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20,
|
0x12, 0xb4, 0x05, 0x82, 0x4a, 0x2b, 0x14, 0x63, 0x0d, 0x1f, 0x06, 0x12,
|
||||||
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x3b, 0x20, 0x73, 0x79, 0x73, 0x74,
|
0xaa, 0xe1, 0x9d, 0xe7, 0xba, 0xda, 0xe3, 0xfc, 0x7c, 0x6c, 0x73, 0xae,
|
||||||
0x65, 0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, 0x37, 0x33, 0x34, 0x36, 0x30,
|
0x56, 0xf8, 0xab, 0xf7, 0x51, 0x93, 0x31, 0xef, 0x8f, 0xe4, 0xb6, 0x01,
|
||||||
0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
0x2c, 0xeb, 0x7b, 0xe4, 0xd8, 0xb3, 0xea, 0x70, 0x37, 0x89, 0x05, 0xa9,
|
||||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
|
0x51, 0x57, 0x72, 0x98, 0x9e, 0xa8, 0x46, 0xdb, 0xeb, 0x7a, 0x38, 0x2b,
|
||||||
0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0x45, 0x13, 0xf2,
|
0x2f, 0xc0, 0x27, 0xb7, 0xc2, 0xe1, 0x9a, 0x17, 0xdf, 0xf5, 0xd6, 0x9c,
|
||||||
0xb2, 0xcb, 0x4b, 0x0f, 0xb4, 0x44, 0x25, 0x9c, 0x8a, 0x68, 0x54, 0xd5,
|
0xd5, 0x8c, 0xb8, 0x66, 0x42, 0xd5, 0x04, 0x1e, 0x7c, 0x36, 0x4c, 0x1e,
|
||||||
0x45, 0x1e, 0x15, 0x89, 0x5b, 0xb8, 0xce, 0xda, 0x5a, 0x42, 0xe6, 0x9a,
|
0x3e, 0x45, 0x51, 0x4d, 0x41, 0x72, 0x22, 0x53, 0x3d, 0xf4, 0x57, 0x7c,
|
||||||
0x8c, 0xc1, 0xcb, 0xe8, 0xc5, 0xf5, 0x8f, 0x49, 0x0e, 0x02, 0xef, 0x5e,
|
0x6c, 0x33, 0x34, 0x24, 0x45, 0xdf, 0x84, 0x87, 0x4a, 0xa6, 0xcb, 0x7c,
|
||||||
0x97, 0x1a, 0x91, 0xa4, 0x94, 0xc3, 0x50, 0x13, 0xe5, 0x13, 0xb7, 0x7f,
|
0x03, 0xa3, 0xaa, 0x8e, 0x2d, 0x82, 0x01, 0x27, 0x87, 0x74, 0x82, 0x1a,
|
||||||
0x26, 0x53, 0x19, 0xb0, 0x37, 0xa5, 0xef, 0xe6, 0x2a, 0x39, 0xdc, 0x93,
|
0xbc, 0x0f, 0x76, 0x69, 0xab, 0xe0, 0x4e, 0x70, 0xbe, 0x37, 0xfc, 0xc8,
|
||||||
0x37, 0xe2, 0x3d, 0x7f, 0xcb, 0x4b, 0x93, 0xa2, 0xc3, 0x69, 0x78, 0xc9,
|
0x2c, 0x91, 0x17, 0x4f, 0xd5, 0x26, 0x3b, 0x7b, 0x90, 0xb5, 0x2d, 0x64,
|
||||||
0x01, 0xfa, 0x68, 0x3b, 0xe0, 0xe2, 0x22, 0x6c, 0xeb, 0xe4, 0x8a, 0xa8,
|
0xba, 0xf7, 0xd2, 0x8a, 0xb4, 0x8f, 0x38, 0x9d, 0x8e, 0xba, 0xe7, 0x5c,
|
||||||
0x3e, 0xf5, 0x20, 0x82, 0xa8, 0x62, 0x68, 0x59, 0x78, 0x24, 0xde, 0xef,
|
0x52, 0xf1, 0x0a, 0xb8, 0xc0, 0x1b, 0xb6, 0xb1, 0x70, 0x7e, 0x47, 0x59,
|
||||||
0x47, 0x43, 0xb1, 0x6c, 0x38, 0x29, 0xd3, 0x69, 0x3f, 0xae, 0x35, 0x57,
|
0x94, 0x59, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x10, 0x30,
|
||||||
0x75, 0x80, 0xc9, 0x21, 0xe7, 0x01, 0xb9, 0x54, 0x8b, 0x6e, 0x4e, 0x2e,
|
0x82, 0x01, 0x0c, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01,
|
||||||
0x5a, 0x5b, 0x77, 0xa4, 0x22, 0xc2, 0x7b, 0x95, 0xb9, 0x39, 0x2c, 0xbd,
|
0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30,
|
||||||
0xc2, 0x1e, 0x02, 0xa6, 0xb2, 0xbc, 0x0f, 0x7a, 0xcb, 0xdc, 0xbc, 0xbc,
|
0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
|
||||||
0x90, 0x66, 0xe3, 0xca, 0x46, 0x53, 0x3e, 0x98, 0xff, 0x2e, 0x78, 0x9f,
|
0x02, 0x02, 0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
|
||||||
0xd3, 0xa1, 0x12, 0x93, 0x66, 0x7d, 0xcc, 0x94, 0x6b, 0xec, 0x19, 0x0e,
|
0x04, 0x14, 0x4b, 0xcb, 0xdf, 0xaa, 0x02, 0xde, 0x8d, 0xc3, 0xe7, 0xe5,
|
||||||
0x20, 0x45, 0x22, 0x57, 0x6d, 0x9e, 0xd0, 0x89, 0xf2, 0xa9, 0x34, 0xdc,
|
0x85, 0xdb, 0x2e, 0x8a, 0xbe, 0x75, 0x6b, 0x8a, 0x67, 0x58, 0x30, 0x81,
|
||||||
0xab, 0xa5, 0x73, 0x47, 0x38, 0xe3, 0x7f, 0x98, 0x3a, 0x61, 0xae, 0x6c,
|
0xb2, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xaa, 0x30, 0x81, 0xa7,
|
||||||
0x4d, 0xf2, 0x31, 0x90, 0xcb, 0x83, 0xc1, 0xee, 0xb4, 0xf2, 0x9a, 0x28,
|
0x80, 0x14, 0x04, 0x94, 0x66, 0xaa, 0xf9, 0x61, 0x89, 0xb6, 0xdb, 0xb5,
|
||||||
0x5f, 0xbb, 0x7d, 0x89, 0xdf, 0xa2, 0x31, 0xb6, 0x1d, 0x39, 0x2b, 0x70,
|
0xf7, 0x13, 0x38, 0x3d, 0x62, 0x84, 0xb8, 0x18, 0x0a, 0x8f, 0xa1, 0x81,
|
||||||
0xbf, 0x1e, 0xad, 0xe1, 0x74, 0x94, 0x1d, 0xf8, 0xc5, 0x1a, 0x8d, 0x13,
|
0x83, 0xa4, 0x81, 0x80, 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
|
||||||
0x45, 0xf0, 0x6a, 0x80, 0x0c, 0x5d, 0xbb, 0x46, 0x8a, 0x43, 0xd0, 0xff,
|
0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06,
|
||||||
0x21, 0x39, 0x57, 0x53, 0x5b, 0x51, 0xf8, 0xa2, 0x8f, 0x7f, 0x27, 0xc7,
|
0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e,
|
||||||
0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x10, 0x30, 0x82, 0x01,
|
0x67, 0x74, 0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
|
||||||
0x0c, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
|
0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31,
|
||||||
0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06,
|
0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f,
|
||||||
0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02,
|
0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
|
||||||
0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
|
0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31,
|
||||||
0xe8, 0xe9, 0xac, 0x16, 0x5c, 0x5e, 0xb2, 0xe8, 0xeb, 0xff, 0x57, 0x27,
|
0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, 0x77, 0x69,
|
||||||
0x20, 0x08, 0x72, 0x63, 0x9b, 0xe5, 0xb5, 0x16, 0x30, 0x81, 0xb2, 0x06,
|
0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f,
|
||||||
0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xaa, 0x30, 0x81, 0xa7, 0x80, 0x14,
|
0x65, 0x6d, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x72, 0x6f, 0x64,
|
||||||
0x04, 0x94, 0x66, 0xaa, 0xf9, 0x61, 0x89, 0xb6, 0xdb, 0xb5, 0xf7, 0x13,
|
0x82, 0x09, 0x00, 0xdf, 0x86, 0x05, 0x31, 0x01, 0xbe, 0x9a, 0x9a, 0x30,
|
||||||
0x38, 0x3d, 0x62, 0x84, 0xb8, 0x18, 0x0a, 0x8f, 0xa1, 0x81, 0x83, 0xa4,
|
0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x04, 0x01,
|
||||||
0x81, 0x80, 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
0x01, 0x04, 0x04, 0x02, 0x02, 0x1e, 0xe9, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||||
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
|
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82,
|
||||||
0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74,
|
0x02, 0x01, 0x00, 0x61, 0x3f, 0x2f, 0x43, 0xe4, 0xbe, 0x66, 0x34, 0xef,
|
||||||
0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
|
0x92, 0x06, 0xe9, 0x88, 0xba, 0x6a, 0x1d, 0x4f, 0x54, 0x5a, 0x97, 0xb1,
|
||||||
0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30,
|
0x75, 0xd7, 0x93, 0xf8, 0x45, 0xc6, 0x83, 0x92, 0x36, 0xfd, 0x55, 0xa9,
|
||||||
0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
|
0x21, 0x0b, 0xdc, 0xf6, 0xae, 0x11, 0xdc, 0x62, 0x21, 0x44, 0xbd, 0x04,
|
||||||
0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
|
0x1d, 0x58, 0x2c, 0x03, 0xf8, 0xe4, 0xe2, 0x1e, 0xba, 0xe6, 0xdd, 0x19,
|
||||||
0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, 0x23, 0x30,
|
0xdd, 0x56, 0xfd, 0xce, 0x06, 0x73, 0x5f, 0x94, 0x1e, 0xb6, 0x03, 0xdb,
|
||||||
0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, 0x77, 0x69, 0x64, 0x65,
|
0x3d, 0x7b, 0xab, 0xab, 0x72, 0x64, 0x7b, 0xde, 0x7d, 0x4d, 0xcf, 0x7e,
|
||||||
0x76, 0x69, 0x6e, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x65, 0x6d,
|
0xf0, 0x91, 0x29, 0xc1, 0x77, 0x13, 0xc2, 0x6f, 0x80, 0xab, 0x7a, 0xa8,
|
||||||
0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x72, 0x6f, 0x64, 0x82, 0x09,
|
0xce, 0xb0, 0x1c, 0x2a, 0xc5, 0x9c, 0xfb, 0x0b, 0xe5, 0x9f, 0x9c, 0x1b,
|
||||||
0x00, 0xdf, 0x86, 0x05, 0x31, 0x01, 0xbe, 0x9a, 0x9a, 0x30, 0x12, 0x06,
|
0xc9, 0x4b, 0x58, 0xdf, 0x96, 0x18, 0xf7, 0x67, 0x67, 0x89, 0xa4, 0xe9,
|
||||||
0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x04, 0x01, 0x01, 0x04,
|
0x14, 0x48, 0xac, 0xfa, 0x9d, 0x86, 0x2a, 0xeb, 0x75, 0x2c, 0x2b, 0xbf,
|
||||||
0x04, 0x02, 0x02, 0x1c, 0xb2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
0x63, 0x7d, 0xc7, 0x4e, 0x7e, 0xad, 0x39, 0x2d, 0xb4, 0x7c, 0x07, 0xa5,
|
||||||
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01,
|
0x5a, 0xe8, 0x3a, 0xd4, 0xf5, 0x0c, 0x4f, 0xf3, 0xa2, 0x9c, 0x3c, 0x32,
|
||||||
0x00, 0x25, 0xce, 0xd2, 0x02, 0x48, 0xbb, 0xbe, 0xfc, 0xb6, 0xa4, 0x87,
|
0xed, 0x9d, 0x4b, 0x49, 0x05, 0xbc, 0x1f, 0xa0, 0x13, 0xe6, 0xdd, 0x82,
|
||||||
0x87, 0xe0, 0x21, 0x7d, 0xfa, 0x23, 0xc3, 0x0d, 0x73, 0x8f, 0x46, 0xe7,
|
0x79, 0x06, 0x31, 0x3b, 0xc6, 0x97, 0xec, 0x8d, 0xaa, 0x4f, 0xef, 0x14,
|
||||||
0x09, 0x59, 0xda, 0x2e, 0x55, 0x59, 0xff, 0x3c, 0x1b, 0xf6, 0xf8, 0x9a,
|
0x3c, 0x21, 0xf6, 0x72, 0xb2, 0x09, 0x42, 0xc7, 0x74, 0xfe, 0xef, 0x70,
|
||||||
0xc4, 0x1c, 0xf7, 0xac, 0xca, 0xe7, 0x63, 0xf2, 0xc7, 0xd6, 0x0c, 0x2d,
|
0xbd, 0xe9, 0x85, 0x41, 0x30, 0x0b, 0xb3, 0x6b, 0x59, 0x0c, 0x0f, 0x11,
|
||||||
0xa6, 0xad, 0x55, 0xf4, 0x10, 0x0e, 0xa8, 0x82, 0x0f, 0x88, 0xb5, 0x44,
|
0x75, 0xd4, 0xbb, 0xb1, 0xdf, 0xb1, 0xdf, 0xb3, 0xfa, 0xb3, 0x3a, 0x43,
|
||||||
0xe8, 0x8e, 0x84, 0x08, 0xf7, 0xdd, 0xe7, 0x10, 0xce, 0x71, 0x56, 0x57,
|
0x17, 0x7d, 0x8a, 0x82, 0xae, 0xa2, 0x07, 0xf8, 0x83, 0x51, 0xfb, 0x16,
|
||||||
0x3f, 0xed, 0x48, 0xee, 0xe2, 0x5d, 0x08, 0x0a, 0x58, 0xe4, 0xfe, 0xbc,
|
0xfb, 0x64, 0xb6, 0x46, 0xda, 0xbe, 0x32, 0x2b, 0xc0, 0xee, 0x78, 0x2a,
|
||||||
0x8c, 0x27, 0x1a, 0x46, 0x3f, 0xd5, 0x2d, 0xdb, 0x0b, 0x71, 0x73, 0xd1,
|
0x84, 0xa9, 0x54, 0x0a, 0xf9, 0x2d, 0x61, 0x65, 0xde, 0xa5, 0x97, 0x66,
|
||||||
0x49, 0xf3, 0x5c, 0x86, 0x4d, 0x0a, 0xe1, 0xeb, 0x53, 0x21, 0x38, 0x4f,
|
0x79, 0x02, 0xf8, 0x97, 0x17, 0xe2, 0xd4, 0x9f, 0x9e, 0xac, 0xcc, 0xae,
|
||||||
0xec, 0x1e, 0xc2, 0x68, 0x1f, 0x7d, 0xa6, 0x33, 0xe9, 0xa5, 0x37, 0x2a,
|
0x99, 0x9a, 0x03, 0x04, 0xbb, 0x45, 0xfe, 0xb2, 0xf5, 0x80, 0xba, 0xbf,
|
||||||
0xef, 0xcd, 0x78, 0x56, 0xb3, 0x39, 0x60, 0xf4, 0xa5, 0xf9, 0x2b, 0x85,
|
0xdd, 0x24, 0xe5, 0xe6, 0x1e, 0x5d, 0x36, 0xa5, 0x87, 0x0c, 0xdf, 0x60,
|
||||||
0xcf, 0xe6, 0x1c, 0x7c, 0x8a, 0x5d, 0xe8, 0x26, 0x02, 0xcf, 0x7a, 0x56,
|
0x81, 0x6f, 0xb7, 0x5f, 0xb9, 0x1f, 0xca, 0x75, 0x3c, 0x1a, 0x63, 0xb0,
|
||||||
0x1f, 0xae, 0x0d, 0x71, 0x20, 0xee, 0xec, 0x3b, 0xae, 0x95, 0x25, 0x15,
|
0xeb, 0xe6, 0x95, 0x86, 0x0d, 0xae, 0xa6, 0xc9, 0x2a, 0x94, 0xf1, 0xd0,
|
||||||
0xc8, 0xf6, 0x92, 0x5d, 0xb8, 0x9b, 0xc2, 0xb4, 0x95, 0x33, 0x13, 0x76,
|
0xbe, 0x75, 0xc8, 0xf8, 0x07, 0xd7, 0x88, 0xff, 0xec, 0xf9, 0xcd, 0x49,
|
||||||
0x45, 0xbe, 0x21, 0xe2, 0x3a, 0x69, 0x66, 0xd7, 0xff, 0x22, 0x00, 0x89,
|
0xc6, 0xfe, 0x4d, 0x7f, 0x44, 0x1e, 0xd8, 0xaf, 0xa9, 0x72, 0x27, 0x98,
|
||||||
0xc9, 0x44, 0xb6, 0x54, 0x38, 0x1f, 0x33, 0xe4, 0xda, 0x7b, 0x87, 0xf3,
|
0xe2, 0x5a, 0x08, 0xea, 0x55, 0xd3, 0xb3, 0xea, 0xdc, 0x76, 0x69, 0x51,
|
||||||
0x23, 0xed, 0xf5, 0x16, 0x08, 0xbe, 0x4b, 0xea, 0x91, 0x8f, 0x91, 0x8b,
|
0x10, 0x01, 0x46, 0x7d, 0x33, 0x94, 0x9c, 0x94, 0xef, 0xfe, 0x76, 0x1c,
|
||||||
0x4e, 0xd1, 0x02, 0x06, 0xa2, 0x77, 0x15, 0x03, 0x46, 0x11, 0x7d, 0x5b,
|
0xc6, 0xd7, 0x15, 0x53, 0x3e, 0x8d, 0x3d, 0x29, 0x9a, 0x58, 0x6a, 0xf1,
|
||||||
0xea, 0x7a, 0xf6, 0x86, 0x7d, 0x96, 0xb7, 0x73, 0x9b, 0x5b, 0x32, 0xc3,
|
0x75, 0x9e, 0xea, 0x1b, 0x4c, 0xf0, 0x47, 0x76, 0xac, 0xc6, 0xa2, 0x32,
|
||||||
0xf8, 0x92, 0x36, 0xe3, 0xe3, 0x2f, 0xe8, 0xf1, 0x72, 0xec, 0x0d, 0x50,
|
0x44, 0x40, 0xdf, 0xfe, 0xff, 0x9d, 0xf4, 0xe2, 0xc2, 0xfa, 0xa1, 0x5f,
|
||||||
0xd4, 0x86, 0xc5, 0x62, 0x83, 0xf1, 0x2a, 0x4c, 0xd1, 0xbf, 0x76, 0x62,
|
0x2e, 0x66, 0xe9, 0x97, 0xcb, 0x27, 0x26, 0x6e, 0x53, 0xe4, 0xe8, 0x86,
|
||||||
0xd4, 0x21, 0x11, 0x68, 0xb2, 0xd6, 0x8d, 0xc4, 0xf8, 0xe4, 0x70, 0x85,
|
0x2c, 0xea, 0xd3, 0x69, 0x6c, 0x61, 0x4f, 0xfe, 0xc1, 0xc9, 0x8b, 0x05,
|
||||||
0x19, 0xa7, 0x82, 0x27, 0x2c, 0x24, 0x21, 0x7a, 0x3b, 0xad, 0x8a, 0xd3,
|
0x92, 0x6f, 0x47, 0x96, 0xce, 0xf0, 0x33, 0xfa, 0x7c, 0x78, 0x24, 0x9b,
|
||||||
0xae, 0xda, 0x78, 0x3c, 0x6c, 0xab, 0xa2, 0xaa, 0x36, 0xf0, 0x1c, 0x58,
|
0xd7, 0x8d, 0x36, 0x56, 0x37, 0x86, 0xbc, 0x72, 0x5a, 0xf9, 0xb9, 0xb0,
|
||||||
0xd4, 0x72, 0x5e, 0xe8, 0x8b, 0x41, 0x08, 0xf5, 0x85, 0xdd, 0xee, 0x99,
|
0x93, 0xf0, 0x81, 0x78, 0x10, 0xf2, 0xb0, 0xc2, 0x79, 0x91, 0x5e, 0xcf,
|
||||||
0x12, 0xf4, 0xd6, 0x41, 0x83, 0x69, 0xe7, 0x79, 0x19, 0xa3, 0x74, 0xc4,
|
0xbc, 0x8c, 0xf2, 0x32, 0x0f, 0xf7, 0x2d, 0x30, 0xd8, 0x13, 0x77, 0x4f,
|
||||||
0x34, 0x2a, 0x8a, 0x7e, 0x4d, 0xbb, 0x2c, 0x49, 0x19, 0xf7, 0x98, 0x98,
|
0x78, 0x9e, 0x40, 0x8d, 0xe6, 0x3a, 0x98, 0xb2, 0xaa, 0x13, 0x4d, 0x25,
|
||||||
0xfc, 0x81, 0xf7, 0x9b, 0x7f, 0xff, 0xd9, 0x66, 0xf4, 0x51, 0x14, 0x29,
|
0x49, 0x34, 0x6c, 0x80, 0x9e, 0x19, 0x03, 0xdb, 0xcd, 0xf5, 0xb1, 0x54,
|
||||||
0x2a, 0x14, 0x1d, 0x4f, 0xbd, 0x91, 0xba, 0x6f, 0x32, 0x34, 0x3c, 0x40,
|
0x74, 0x1b, 0x67, 0x3c, 0x46, 0xac, 0x3e, 0x5d, 0xa2, 0xd9, 0x13, 0x83,
|
||||||
0x28, 0x6c, 0x97, 0xf8, 0x6d, 0x38, 0xcd, 0xa3, 0x7b, 0x18, 0xc8, 0x77,
|
0x30, 0xeb, 0x82, 0x3b, 0x06, 0xab, 0x3c, 0x39, 0x7d, 0xd0, 0x68, 0x31,
|
||||||
0x58, 0x4d, 0x53, 0x30, 0x7f, 0x4d, 0x89, 0xca, 0x95, 0x6e, 0xb5, 0xb8,
|
0x00
|
||||||
0x8e, 0xc8, 0x2d, 0x18, 0x2f, 0x52, 0x2a, 0xde, 0xac, 0x56, 0x8d, 0x8c,
|
|
||||||
0x67, 0x14, 0xf6, 0xb9, 0xf1, 0x65, 0xd3, 0x22, 0x43, 0xa3, 0x98, 0x42,
|
|
||||||
0x20, 0x43, 0x4c, 0xdf, 0xf2, 0xeb, 0x31, 0x8c, 0x0e, 0x53, 0x5b, 0x99,
|
|
||||||
0x82, 0xc3, 0x48, 0x04, 0x53, 0xad, 0x96, 0xb6, 0x9f, 0x52, 0xcc, 0x01,
|
|
||||||
0xc8, 0xb3, 0x87, 0x6b, 0x9e, 0xea, 0xa9, 0xeb, 0xda, 0xac, 0xf9, 0x6f,
|
|
||||||
0xde, 0xa1, 0x44, 0x32, 0x52, 0x49, 0x47, 0xff, 0x65, 0x79, 0x1e, 0xc5,
|
|
||||||
0x73, 0x17, 0xb3, 0x36, 0xfc, 0x45, 0xca, 0x90, 0x37, 0x59, 0x1e, 0x16,
|
|
||||||
0xab, 0x09, 0x69, 0xcf, 0xda, 0x56, 0x51, 0xfd, 0xeb, 0xcf, 0xcb, 0x8f,
|
|
||||||
0xb1, 0xc3, 0x45, 0x2b, 0x7c, 0x0a, 0xa5, 0x9c, 0x0d, 0x2c, 0xad, 0x1c,
|
|
||||||
0xd3, 0x33, 0xdd, 0xfe, 0x93, 0x69, 0xa2, 0x4b, 0x4b, 0xcf, 0x1d, 0x20,
|
|
||||||
0x98, 0x4a, 0x4f, 0x5b, 0xe9, 0x24, 0xca, 0xfa, 0x18, 0x11, 0x81, 0x8b,
|
|
||||||
0x7a, 0xb4, 0x5a, 0xc8, 0xdf, 0x6f, 0x5f, 0x21, 0x07, 0x31, 0x00
|
|
||||||
};
|
};
|
||||||
extern const size_t kOEMPublicCertSize_Prod = 2555;
|
|
||||||
|
const size_t kOEMPublicCertSize_Prod = sizeof(kOEMPublicCert_Prod);
|
||||||
|
|
||||||
// Refer to the following in main modules.
|
// Refer to the following in main modules.
|
||||||
// This level of indirection is present so new OEM Certificates can be
|
// This level of indirection is present so new OEM Certificates can be
|
||||||
|
|||||||
@@ -13,12 +13,14 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <openssl/aes.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "oemcrypto_key_ref.h"
|
#include "oemcrypto_key_ref.h"
|
||||||
#include "oemcrypto_rsa_key_shared.h"
|
#include "oemcrypto_rsa_key_shared.h"
|
||||||
|
#include "string_conversions.h"
|
||||||
|
|
||||||
namespace wvoec_ref {
|
namespace wvoec_ref {
|
||||||
|
|
||||||
@@ -84,6 +86,105 @@ SessionContext* CryptoEngine::FindSession(SessionId sid) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t CryptoEngine::OnlineTime() {
|
||||||
|
// Use the monotonic clock for times that don't have to be stable across
|
||||||
|
// device boots.
|
||||||
|
timespec current_time;
|
||||||
|
int gettime_result = clock_gettime(CLOCK_MONOTONIC, ¤t_time);
|
||||||
|
if (gettime_result == 0) {
|
||||||
|
return current_time.tv_sec;
|
||||||
|
} else {
|
||||||
|
// Can't use monotonic clock, use roll back time.
|
||||||
|
return RollbackCorrectedOfflineTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t CryptoEngine::RollbackCorrectedOfflineTime() {
|
||||||
|
struct TimeInfo {
|
||||||
|
// The max time recorded through this function call.
|
||||||
|
time_t previous_time;
|
||||||
|
// If the wall time is rollbacked to before the previous_time, this member
|
||||||
|
// is updated to reflect the offset.
|
||||||
|
time_t rollback_offset;
|
||||||
|
// Pad the struct so that TimeInfo is a multiple of 16.
|
||||||
|
uint8_t padding[16 - (2 * sizeof(time_t)) % 16];
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<uint8_t> encrypted_buffer(sizeof(TimeInfo));
|
||||||
|
std::vector<uint8_t> clear_buffer(sizeof(TimeInfo));
|
||||||
|
TimeInfo time_info;
|
||||||
|
memset(&time_info, 0, sizeof(time_info));
|
||||||
|
// Use the device key for encrypt/decrypt.
|
||||||
|
const std::vector<uint8_t>& key = DeviceRootKey();
|
||||||
|
|
||||||
|
wvcdm::File* file;
|
||||||
|
std::string path;
|
||||||
|
// Note: this path is OK for a real implementation, but using security level 1
|
||||||
|
// would be better.
|
||||||
|
// TODO(fredgc, jfore): Address how this property is presented to the ref.
|
||||||
|
// For now, the path is empty.
|
||||||
|
/*if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
|
||||||
|
&path)) {
|
||||||
|
LOGE("RollbackCorrectedOfflineTime: Unable to get base path");
|
||||||
|
}*/
|
||||||
|
std::string filename = path + "StoredUsageTime.dat";
|
||||||
|
|
||||||
|
wvcdm::FileSystem* file_system = file_system_.get();
|
||||||
|
if (file_system->Exists(filename)) {
|
||||||
|
// Load time info from previous call to this function.
|
||||||
|
file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
|
||||||
|
if (!file) {
|
||||||
|
LOGE("RollbackCorrectedOfflineTime: File open failed: %s",
|
||||||
|
filename.c_str());
|
||||||
|
return time(NULL);
|
||||||
|
}
|
||||||
|
file->Read(reinterpret_cast<char*>(&encrypted_buffer[0]), sizeof(TimeInfo));
|
||||||
|
file->Close();
|
||||||
|
// Decrypt the encrypted TimeInfo buffer.
|
||||||
|
AES_KEY aes_key;
|
||||||
|
AES_set_decrypt_key(&key[0], 128, &aes_key);
|
||||||
|
std::vector<uint8_t> iv(wvoec::KEY_IV_SIZE, 0);
|
||||||
|
AES_cbc_encrypt(&encrypted_buffer[0], &clear_buffer[0], sizeof(TimeInfo),
|
||||||
|
&aes_key, iv.data(), AES_DECRYPT);
|
||||||
|
memcpy(&time_info, &clear_buffer[0], sizeof(TimeInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t current_time;
|
||||||
|
// Add any time offsets in the past to the current time.
|
||||||
|
current_time = time(NULL) + time_info.rollback_offset;
|
||||||
|
if (time_info.previous_time > current_time) {
|
||||||
|
// Time has been rolled back.
|
||||||
|
// Update the rollback offset.
|
||||||
|
time_info.rollback_offset += time_info.previous_time - current_time;
|
||||||
|
// Keep current time at previous recorded time.
|
||||||
|
current_time = time_info.previous_time;
|
||||||
|
}
|
||||||
|
// The new previous_time will either stay the same or move forward.
|
||||||
|
time_info.previous_time = current_time;
|
||||||
|
|
||||||
|
// Copy updated data and encrypt the buffer.
|
||||||
|
memcpy(&clear_buffer[0], &time_info, sizeof(TimeInfo));
|
||||||
|
AES_KEY aes_key;
|
||||||
|
AES_set_encrypt_key(&key[0], 128, &aes_key);
|
||||||
|
std::vector<uint8_t> iv(wvoec::KEY_IV_SIZE, 0);
|
||||||
|
AES_cbc_encrypt(&clear_buffer[0], &encrypted_buffer[0], sizeof(TimeInfo),
|
||||||
|
&aes_key, iv.data(), AES_ENCRYPT);
|
||||||
|
|
||||||
|
// Write the encrypted buffer to disk.
|
||||||
|
file = file_system->Open(
|
||||||
|
filename, wvcdm::FileSystem::kCreate | wvcdm::FileSystem::kTruncate);
|
||||||
|
if (!file) {
|
||||||
|
LOGE("RollbackCorrectedOfflineTime: File open failed: %s",
|
||||||
|
filename.c_str());
|
||||||
|
return time(NULL);
|
||||||
|
}
|
||||||
|
file->Write(reinterpret_cast<char*>(&encrypted_buffer[0]), sizeof(TimeInfo));
|
||||||
|
file->Close();
|
||||||
|
|
||||||
|
// Return time with offset.
|
||||||
|
return current_time;
|
||||||
|
}
|
||||||
|
|
||||||
OEMCrypto_HDCP_Capability CryptoEngine::config_current_hdcp_capability() {
|
OEMCrypto_HDCP_Capability CryptoEngine::config_current_hdcp_capability() {
|
||||||
return config_local_display_only() ? HDCP_NO_DIGITAL_OUTPUT : HDCP_V1;
|
return config_local_display_only() ? HDCP_NO_DIGITAL_OUTPUT : HDCP_V1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ class CryptoEngine {
|
|||||||
return kMaxSupportedOEMCryptoSessions;
|
return kMaxSupportedOEMCryptoSessions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t OnlineTime();
|
||||||
|
|
||||||
|
time_t RollbackCorrectedOfflineTime();
|
||||||
|
|
||||||
// Returns the HDCP version currently in use.
|
// Returns the HDCP version currently in use.
|
||||||
virtual OEMCrypto_HDCP_Capability config_current_hdcp_capability();
|
virtual OEMCrypto_HDCP_Capability config_current_hdcp_capability();
|
||||||
|
|
||||||
@@ -144,6 +148,7 @@ class CryptoEngine {
|
|||||||
virtual uint8_t config_security_patch_level() { return 0; }
|
virtual uint8_t config_security_patch_level() { return 0; }
|
||||||
|
|
||||||
// If 0 no restriction, otherwise it's the max buffer for DecryptCENC.
|
// If 0 no restriction, otherwise it's the max buffer for DecryptCENC.
|
||||||
|
// This is the same as the max subsample size, not the sample or frame size.
|
||||||
virtual size_t max_buffer_size() { return 1024 * 100; } // 100 KiB.
|
virtual size_t max_buffer_size() { return 1024 * 100; } // 100 KiB.
|
||||||
|
|
||||||
virtual bool srm_update_supported() { return false; }
|
virtual bool srm_update_supported() { return false; }
|
||||||
@@ -170,6 +175,8 @@ class CryptoEngine {
|
|||||||
// size is unlimited -- or limited only by memory size.
|
// size is unlimited -- or limited only by memory size.
|
||||||
virtual size_t max_usage_table_size() { return 0; }
|
virtual size_t max_usage_table_size() { return 0; }
|
||||||
|
|
||||||
|
virtual uint32_t resource_rating() { return 1; }
|
||||||
|
|
||||||
// Set destination pointer based on the output destination description.
|
// Set destination pointer based on the output destination description.
|
||||||
OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description,
|
OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description,
|
||||||
size_t data_length, uint8_t subsample_flags);
|
size_t data_length, uint8_t subsample_flags);
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ bool KeyControlBlock::Validate() {
|
|||||||
memcmp(verification_, "kc11", 4) && // add in version 11 api
|
memcmp(verification_, "kc11", 4) && // add in version 11 api
|
||||||
memcmp(verification_, "kc12", 4) && // add in version 12 api
|
memcmp(verification_, "kc12", 4) && // add in version 12 api
|
||||||
memcmp(verification_, "kc13", 4) && // add in version 13 api
|
memcmp(verification_, "kc13", 4) && // add in version 13 api
|
||||||
memcmp(verification_, "kc14", 4)) { // add in version 14 api
|
memcmp(verification_, "kc14", 4) && // add in version 14 api
|
||||||
|
memcmp(verification_, "kc15", 4)) { // add in version 15 api
|
||||||
LOGE("KCB: BAD verification string: %4.4s", verification_);
|
LOGE("KCB: BAD verification string: %4.4s", verification_);
|
||||||
valid_ = false;
|
valid_ = false;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -31,16 +31,21 @@
|
|||||||
|
|
||||||
namespace wvoec_ref {
|
namespace wvoec_ref {
|
||||||
|
|
||||||
OldUsageTableEntry::OldUsageTableEntry(const std::vector<uint8_t> &pst_hash)
|
OldUsageTableEntry::OldUsageTableEntry(OldUsageTable *old_usage_table,
|
||||||
|
const std::vector<uint8_t> &pst_hash)
|
||||||
: pst_hash_(pst_hash),
|
: pst_hash_(pst_hash),
|
||||||
time_of_license_received_(time(NULL)),
|
old_usage_table_(old_usage_table),
|
||||||
|
time_of_license_received_(
|
||||||
|
old_usage_table_->ce_->RollbackCorrectedOfflineTime()),
|
||||||
time_of_first_decrypt_(0),
|
time_of_first_decrypt_(0),
|
||||||
time_of_last_decrypt_(0),
|
time_of_last_decrypt_(0),
|
||||||
status_(kUnused) {}
|
status_(kUnused) {}
|
||||||
|
|
||||||
OldUsageTableEntry::~OldUsageTableEntry() {}
|
OldUsageTableEntry::~OldUsageTableEntry() {}
|
||||||
|
|
||||||
OldUsageTableEntry::OldUsageTableEntry(const OldStoredUsageEntry *buffer) {
|
OldUsageTableEntry::OldUsageTableEntry(OldUsageTable *old_usage_table,
|
||||||
|
const OldStoredUsageEntry *buffer)
|
||||||
|
: old_usage_table_(old_usage_table) {
|
||||||
pst_hash_.assign(buffer->pst_hash, buffer->pst_hash + SHA256_DIGEST_LENGTH);
|
pst_hash_.assign(buffer->pst_hash, buffer->pst_hash + SHA256_DIGEST_LENGTH);
|
||||||
time_of_license_received_ = buffer->time_of_license_received;
|
time_of_license_received_ = buffer->time_of_license_received;
|
||||||
time_of_first_decrypt_ = buffer->time_of_first_decrypt;
|
time_of_first_decrypt_ = buffer->time_of_first_decrypt;
|
||||||
@@ -95,6 +100,11 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
|
|||||||
// 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.
|
||||||
const std::vector<uint8_t> &key = ce_->DeviceRootKey();
|
const std::vector<uint8_t> &key = ce_->DeviceRootKey();
|
||||||
|
if (key.empty()) {
|
||||||
|
LOGE("OldUsageTable: DeviceRootKey is unexpectedly empty.");
|
||||||
|
table_.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@@ -152,7 +162,7 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
|
|||||||
// entries.
|
// entries.
|
||||||
for (uint64_t i = 0; i < stored_table->count; i++) {
|
for (uint64_t i = 0; i < stored_table->count; i++) {
|
||||||
OldUsageTableEntry *entry =
|
OldUsageTableEntry *entry =
|
||||||
new OldUsageTableEntry(&stored_table->entries[i].entry);
|
new OldUsageTableEntry(this, &stored_table->entries[i].entry);
|
||||||
table_[entry->pst_hash()] = entry;
|
table_[entry->pst_hash()] = entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +193,7 @@ OldUsageTableEntry *OldUsageTable::CreateEntry(
|
|||||||
LOGE("OldUsageTable: Could not compute hash of pst.");
|
LOGE("OldUsageTable: Could not compute hash of pst.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
OldUsageTableEntry *entry = new OldUsageTableEntry(pst_hash);
|
OldUsageTableEntry *entry = new OldUsageTableEntry(this, pst_hash);
|
||||||
wvcdm::AutoLock lock(lock_);
|
wvcdm::AutoLock lock(lock_);
|
||||||
table_[pst_hash] = entry;
|
table_[pst_hash] = entry;
|
||||||
return entry;
|
return entry;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
namespace wvoec_ref {
|
namespace wvoec_ref {
|
||||||
|
|
||||||
class CryptoEngine;
|
class CryptoEngine;
|
||||||
|
class OldUsageTable;
|
||||||
class UsagetTableEntry;
|
class UsagetTableEntry;
|
||||||
|
|
||||||
struct OldStoredUsageEntry {
|
struct OldStoredUsageEntry {
|
||||||
@@ -51,13 +52,16 @@ struct OldStoredUsageTable {
|
|||||||
|
|
||||||
class OldUsageTableEntry {
|
class OldUsageTableEntry {
|
||||||
public:
|
public:
|
||||||
OldUsageTableEntry(const std::vector<uint8_t> &pst_hash);
|
OldUsageTableEntry(OldUsageTable *old_usage_table,
|
||||||
OldUsageTableEntry(const OldStoredUsageEntry *buffer);
|
const std::vector<uint8_t> &pst_hash);
|
||||||
|
OldUsageTableEntry(OldUsageTable *old_usage_table,
|
||||||
|
const OldStoredUsageEntry *buffer);
|
||||||
~OldUsageTableEntry();
|
~OldUsageTableEntry();
|
||||||
const std::vector<uint8_t> &pst_hash() const { return pst_hash_; }
|
const std::vector<uint8_t> &pst_hash() const { return pst_hash_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<uint8_t> pst_hash_;
|
std::vector<uint8_t> pst_hash_;
|
||||||
|
const OldUsageTable *old_usage_table_;
|
||||||
int64_t time_of_license_received_;
|
int64_t time_of_license_received_;
|
||||||
int64_t time_of_first_decrypt_;
|
int64_t time_of_first_decrypt_;
|
||||||
int64_t time_of_last_decrypt_;
|
int64_t time_of_last_decrypt_;
|
||||||
@@ -88,6 +92,8 @@ class OldUsageTable {
|
|||||||
wvcdm::Lock lock_;
|
wvcdm::Lock lock_;
|
||||||
int64_t generation_;
|
int64_t generation_;
|
||||||
CryptoEngine *ce_;
|
CryptoEngine *ce_;
|
||||||
|
|
||||||
|
friend class OldUsageTableEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wvoec_ref
|
} // namespace wvoec_ref
|
||||||
|
|||||||
@@ -74,6 +74,11 @@ extern "C" OEMCryptoResult OEMCrypto_Initialize(void) {
|
|||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_SetSandbox(const uint8_t* /*sandbox_id*/,
|
||||||
|
size_t /*sandbox_id_length*/) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_Terminate(void) {
|
extern "C" OEMCryptoResult OEMCrypto_Terminate(void) {
|
||||||
if (!crypto_engine) {
|
if (!crypto_engine) {
|
||||||
LOGE("[OEMCrypto_Terminate(): not initialized]");
|
LOGE("[OEMCrypto_Terminate(): not initialized]");
|
||||||
@@ -238,12 +243,21 @@ bool RangeCheck(const uint8_t* message, uint32_t message_length,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RangeCheck(uint32_t message_length, const OEMCrypto_Substring& substring,
|
||||||
|
bool allow_null) {
|
||||||
|
if (!substring.length) return allow_null;
|
||||||
|
if (substring.offset > message_length) return false;
|
||||||
|
if (substring.offset + substring.length > message_length) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
const uint8_t* signature, size_t signature_length,
|
const uint8_t* signature, size_t signature_length,
|
||||||
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_keys, size_t num_keys,
|
OEMCrypto_Substring enc_mac_keys_iv, OEMCrypto_Substring enc_mac_keys,
|
||||||
const OEMCrypto_KeyObject* key_array, const uint8_t* pst, size_t pst_length,
|
size_t num_keys, const OEMCrypto_KeyObject* key_array,
|
||||||
const uint8_t* srm_requirement, OEMCrypto_LicenseType license_type) {
|
OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data,
|
||||||
|
OEMCrypto_LicenseType license_type) {
|
||||||
if (!crypto_engine) {
|
if (!crypto_engine) {
|
||||||
LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized.");
|
LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized.");
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
@@ -262,20 +276,12 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
|||||||
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
// Later on, we use pst_length to verify the the pst is valid. This makes
|
|
||||||
// sure that we aren't given a null string but told it has postiive length.
|
|
||||||
if (pst == NULL && pst_length > 0) {
|
|
||||||
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_ONCTEXT - null pst.]");
|
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Range check
|
// Range check
|
||||||
if (!RangeCheck(message, message_length, enc_mac_keys, 2 * wvoec::MAC_KEY_SIZE,
|
if (!RangeCheck(message_length, enc_mac_keys_iv, true) ||
|
||||||
true) ||
|
!RangeCheck(message_length, enc_mac_keys, true) ||
|
||||||
!RangeCheck(message, message_length, enc_mac_key_iv, wvoec::KEY_IV_SIZE, true) ||
|
!RangeCheck(message_length, pst, true) ||
|
||||||
!RangeCheck(message, message_length, pst, pst_length, true) ||
|
!RangeCheck(message_length, srm_restriction_data, true)) {
|
||||||
!RangeCheck(message, message_length, srm_requirement,
|
|
||||||
wvoec::SRM_REQUIREMENT_SIZE, true)) {
|
|
||||||
LOGE(
|
LOGE(
|
||||||
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - range "
|
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - range "
|
||||||
"check.]");
|
"check.]");
|
||||||
@@ -283,16 +289,11 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < num_keys; i++) {
|
for (unsigned int i = 0; i < num_keys; i++) {
|
||||||
if (!RangeCheck(message, message_length, key_array[i].key_id,
|
if (!RangeCheck(message_length, key_array[i].key_id, false) ||
|
||||||
key_array[i].key_id_length, false) ||
|
!RangeCheck(message_length, key_array[i].key_data, false) ||
|
||||||
!RangeCheck(message, message_length, key_array[i].key_data,
|
!RangeCheck(message_length, key_array[i].key_data_iv, false) ||
|
||||||
key_array[i].key_data_length, false) ||
|
!RangeCheck(message_length, key_array[i].key_control, false) ||
|
||||||
!RangeCheck(message, message_length, key_array[i].key_data_iv,
|
!RangeCheck(message_length, key_array[i].key_control_iv, false)) {
|
||||||
wvoec::KEY_IV_SIZE, false) ||
|
|
||||||
!RangeCheck(message, message_length, key_array[i].key_control,
|
|
||||||
wvoec::KEY_CONTROL_SIZE, false) ||
|
|
||||||
!RangeCheck(message, message_length, key_array[i].key_control_iv,
|
|
||||||
wvoec::KEY_IV_SIZE, false)) {
|
|
||||||
LOGE(
|
LOGE(
|
||||||
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT -range "
|
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT -range "
|
||||||
"check %d]",
|
"check %d]",
|
||||||
@@ -301,14 +302,14 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return session_ctx->LoadKeys(message, message_length, signature,
|
return session_ctx->LoadKeys(message, message_length, signature,
|
||||||
signature_length, enc_mac_key_iv, enc_mac_keys,
|
signature_length, enc_mac_keys_iv, enc_mac_keys,
|
||||||
num_keys, key_array, pst, pst_length,
|
num_keys, key_array, pst, srm_restriction_data,
|
||||||
srm_requirement, license_type);
|
license_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
|
extern "C" OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
|
||||||
OEMCrypto_SESSION session, size_t num_keys,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
const OEMCrypto_EntitledContentKeyObject* key_array) {
|
size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array) {
|
||||||
if (num_keys == 0) {
|
if (num_keys == 0) {
|
||||||
LOGE("[OEMCrypto_LoadEntitledContentKeys(): key_array is empty.");
|
LOGE("[OEMCrypto_LoadEntitledContentKeys(): key_array is empty.");
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
@@ -326,8 +327,22 @@ extern "C" OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
|
|||||||
LOGE("[OEMCrypto_LoadEntitledContentKeys(): ERROR_INVALID_SESSION]");
|
LOGE("[OEMCrypto_LoadEntitledContentKeys(): ERROR_INVALID_SESSION]");
|
||||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
}
|
}
|
||||||
|
for (unsigned int i = 0; i < num_keys; i++) {
|
||||||
|
if (!RangeCheck(message_length, key_array[i].entitlement_key_id, false) ||
|
||||||
|
!RangeCheck(message_length, key_array[i].content_key_id, false) ||
|
||||||
|
!RangeCheck(message_length, key_array[i].content_key_data_iv, false) ||
|
||||||
|
!RangeCheck(message_length, key_array[i].content_key_data, false)) {
|
||||||
|
LOGE(
|
||||||
|
"[OEMCrypto_LoadEntitledContentKeys(): "
|
||||||
|
"OEMCrypto_ERROR_INVALID_CONTEXT -range "
|
||||||
|
"check %d]",
|
||||||
|
i);
|
||||||
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return session_ctx->LoadEntitledContentKeys(num_keys, key_array);
|
return session_ctx->LoadEntitledContentKeys(message, message_length, num_keys,
|
||||||
|
key_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
|
extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
|
||||||
@@ -358,12 +373,9 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
|
|||||||
|
|
||||||
// Range check
|
// Range check
|
||||||
for (unsigned int i = 0; i < num_keys; i++) {
|
for (unsigned int i = 0; i < num_keys; i++) {
|
||||||
if (!RangeCheck(message, message_length, key_array[i].key_id,
|
if (!RangeCheck(message_length, key_array[i].key_id, true) ||
|
||||||
key_array[i].key_id_length, true) ||
|
!RangeCheck(message_length, key_array[i].key_control, false) ||
|
||||||
!RangeCheck(message, message_length, key_array[i].key_control,
|
!RangeCheck(message_length, key_array[i].key_control_iv, true)) {
|
||||||
wvoec::KEY_CONTROL_SIZE, false) ||
|
|
||||||
!RangeCheck(message, message_length, key_array[i].key_control_iv,
|
|
||||||
wvoec::KEY_IV_SIZE, true)) {
|
|
||||||
LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i);
|
LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i);
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
@@ -382,24 +394,28 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
|
|||||||
std::vector<uint8_t> key_control;
|
std::vector<uint8_t> key_control;
|
||||||
std::vector<uint8_t> key_control_iv;
|
std::vector<uint8_t> key_control_iv;
|
||||||
for (unsigned int i = 0; i < num_keys; i++) {
|
for (unsigned int i = 0; i < num_keys; i++) {
|
||||||
if (key_array[i].key_id != NULL) {
|
if (key_array[i].key_id.length != 0) {
|
||||||
key_id.assign(key_array[i].key_id,
|
key_id.assign(
|
||||||
key_array[i].key_id + key_array[i].key_id_length);
|
message + key_array[i].key_id.offset,
|
||||||
key_control.assign(key_array[i].key_control,
|
message + key_array[i].key_id.offset + key_array[i].key_id.length);
|
||||||
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
|
key_control.assign(
|
||||||
if (key_array[i].key_control_iv == NULL) {
|
message + key_array[i].key_control.offset,
|
||||||
|
message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE);
|
||||||
|
if (key_array[i].key_control_iv.length == 0) {
|
||||||
key_control_iv.clear();
|
key_control_iv.clear();
|
||||||
} else {
|
} else {
|
||||||
key_control_iv.assign(key_array[i].key_control_iv,
|
key_control_iv.assign(
|
||||||
key_array[i].key_control_iv + wvoec::KEY_IV_SIZE);
|
message + key_array[i].key_control_iv.offset,
|
||||||
|
message + key_array[i].key_control_iv.offset + wvoec::KEY_IV_SIZE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// key_id could be null if special control key type
|
// key_id could be null if special control key type
|
||||||
// key_control is not encrypted in this case
|
// key_control is not encrypted in this case
|
||||||
key_id.clear();
|
key_id.clear();
|
||||||
key_control_iv.clear();
|
key_control_iv.clear();
|
||||||
key_control.assign(key_array[i].key_control,
|
key_control.assign(
|
||||||
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
|
message + key_array[i].key_control.offset,
|
||||||
|
message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = session_ctx->RefreshKey(key_id, key_control, key_control_iv);
|
status = session_ctx->RefreshKey(key_id, key_control, key_control_iv);
|
||||||
@@ -522,7 +538,7 @@ extern "C" OEMCryptoResult OEMCrypto_DecryptCENC(
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_CopyBuffer(
|
extern "C" OEMCryptoResult OEMCrypto_CopyBuffer(
|
||||||
const uint8_t* data_addr, size_t data_length,
|
OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length,
|
||||||
OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags) {
|
OEMCrypto_DestBufferDesc* out_buffer, uint8_t subsample_flags) {
|
||||||
if (!crypto_engine) {
|
if (!crypto_engine) {
|
||||||
LOGE("OEMCrypto_CopyBuffer: OEMCrypto Not Initialized.");
|
LOGE("OEMCrypto_CopyBuffer: OEMCrypto Not Initialized.");
|
||||||
@@ -714,6 +730,10 @@ extern "C" OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData,
|
|||||||
|
|
||||||
extern "C" OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
extern "C" OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
||||||
size_t dataLength) {
|
size_t dataLength) {
|
||||||
|
if (!crypto_engine) {
|
||||||
|
LOGE("OEMCrypto_GetRandom: OEMCrypto Not Initialized.");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
if (!randomData) {
|
if (!randomData) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -1114,7 +1134,7 @@ extern "C" OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
|
|||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" uint32_t OEMCrypto_APIVersion() { return 14; }
|
extern "C" uint32_t OEMCrypto_APIVersion() { return 15; }
|
||||||
|
|
||||||
extern "C" uint8_t OEMCrypto_Security_Patch_Level() {
|
extern "C" uint8_t OEMCrypto_Security_Patch_Level() {
|
||||||
uint8_t security_patch_level = crypto_engine->config_security_patch_level();
|
uint8_t security_patch_level = crypto_engine->config_security_patch_level();
|
||||||
@@ -1147,6 +1167,18 @@ extern "C" uint32_t OEMCrypto_GetAnalogOutputFlags() {
|
|||||||
return crypto_engine->analog_output_flags();
|
return crypto_engine->analog_output_flags();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" const char* OEMCrypto_BuildInformation() {
|
||||||
|
return "OEMCrypto Ref Code " __DATE__ " " __TIME__;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" uint32_t OEMCrypto_ResourceRatingTier(){
|
||||||
|
if (!crypto_engine) {
|
||||||
|
LOGE("OEMCrypto_ResourceRatingTier: OEMCrypto Not Initialized.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return crypto_engine->resource_rating();
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" bool OEMCrypto_SupportsUsageTable() {
|
extern "C" bool OEMCrypto_SupportsUsageTable() {
|
||||||
if (!crypto_engine) {
|
if (!crypto_engine) {
|
||||||
LOGE("OEMCrypto_SupportsUsageTable: OEMCrypto Not Initialized.");
|
LOGE("OEMCrypto_SupportsUsageTable: OEMCrypto Not Initialized.");
|
||||||
@@ -1584,4 +1616,52 @@ extern "C" OEMCryptoResult OEMCrypto_CreateOldUsageEntry(
|
|||||||
pst_length);
|
pst_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" uint32_t OEMCrypto_SupportsDecryptHash() {
|
||||||
|
return OEMCrypto_CRC_Clear_Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_InitializeDecryptHash(
|
||||||
|
OEMCrypto_SESSION session) {
|
||||||
|
if (!crypto_engine) {
|
||||||
|
LOGE("OEMCrypto_InitializeDecryptHash: OEMCrypto Not Initialized.");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
|
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||||
|
if (!session_ctx || !session_ctx->isValid()) {
|
||||||
|
LOGE("[OEMCrypto_InitializeDecryptHash(): ERROR_INVALID_SESSION]");
|
||||||
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
|
}
|
||||||
|
return session_ctx->InitializeDecryptHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_SetDecryptHash(OEMCrypto_SESSION session,
|
||||||
|
uint32_t frame_number,
|
||||||
|
const uint8_t* hash,
|
||||||
|
size_t hash_length) {
|
||||||
|
if (!crypto_engine) {
|
||||||
|
LOGE("OEMCrypto_SetDecryptHash: OEMCrypto Not Initialized.");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
|
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||||
|
if (!session_ctx || !session_ctx->isValid()) {
|
||||||
|
LOGE("[OEMCrypto_SetDecryptHash(): ERROR_INVALID_SESSION]");
|
||||||
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
|
}
|
||||||
|
return session_ctx->SetDecryptHash(frame_number, hash, hash_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" OEMCryptoResult OEMCrypto_GetHashErrorCode(
|
||||||
|
OEMCrypto_SESSION session, uint32_t* failed_frame_number) {
|
||||||
|
if (!crypto_engine) {
|
||||||
|
LOGE("OEMCrypto_GetHashErrorCode: OEMCrypto Not Initialized.");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
|
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||||
|
if (!session_ctx || !session_ctx->isValid()) {
|
||||||
|
LOGE("[OEMCrypto_GetHashErrorCode(): ERROR_INVALID_SESSION]");
|
||||||
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
|
}
|
||||||
|
return session_ctx->GetHashErrorCode(failed_frame_number);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvoec_ref
|
} // namespace wvoec_ref
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "oemcrypto_types.h"
|
#include "oemcrypto_types.h"
|
||||||
#include "disallow_copy_and_assign.h"
|
#include "disallow_copy_and_assign.h"
|
||||||
#include "string_conversions.h"
|
#include "string_conversions.h"
|
||||||
|
#include "wvcrc32.h"
|
||||||
|
|
||||||
static const int kPssSaltLength = 20;
|
static const int kPssSaltLength = 20;
|
||||||
|
|
||||||
@@ -483,19 +484,20 @@ OEMCryptoResult SessionContext::CheckNonceOrEntry(
|
|||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionContext::StartTimer() { timer_start_ = time(NULL); }
|
void SessionContext::StartTimer() { timer_start_ = ce_->OnlineTime(); }
|
||||||
|
|
||||||
uint32_t SessionContext::CurrentTimer() {
|
uint32_t SessionContext::CurrentTimer() {
|
||||||
time_t now = time(NULL);
|
time_t now = ce_->OnlineTime();
|
||||||
return now - timer_start_;
|
return now - timer_start_;
|
||||||
}
|
}
|
||||||
|
|
||||||
OEMCryptoResult SessionContext::LoadKeys(
|
OEMCryptoResult SessionContext::LoadKeys(
|
||||||
const uint8_t* message, size_t message_length, const uint8_t* signature,
|
const uint8_t* message, size_t message_length, const uint8_t* signature,
|
||||||
size_t signature_length, const uint8_t* enc_mac_key_iv,
|
size_t signature_length, OEMCrypto_Substring enc_mac_keys_iv,
|
||||||
const uint8_t* enc_mac_keys, size_t num_keys,
|
OEMCrypto_Substring enc_mac_keys, size_t num_keys,
|
||||||
const OEMCrypto_KeyObject* key_array, const uint8_t* pst, size_t pst_length,
|
const OEMCrypto_KeyObject* key_array, OEMCrypto_Substring pst,
|
||||||
const uint8_t* srm_requirement, OEMCrypto_LicenseType license_type) {
|
OEMCrypto_Substring srm_restriction_data,
|
||||||
|
OEMCrypto_LicenseType license_type) {
|
||||||
// Validate message signature
|
// Validate message signature
|
||||||
if (!ValidateMessage(message, message_length, signature, signature_length)) {
|
if (!ValidateMessage(message, message_length, signature, signature_length)) {
|
||||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||||
@@ -522,16 +524,16 @@ OEMCryptoResult SessionContext::LoadKeys(
|
|||||||
|
|
||||||
StartTimer();
|
StartTimer();
|
||||||
|
|
||||||
if (srm_requirement) {
|
if (srm_restriction_data.length != 0) {
|
||||||
const std::string kSRMVerificationString = "HDCPDATA";
|
const std::string kSRMVerificationString = "HDCPDATA";
|
||||||
if (memcmp(srm_requirement, kSRMVerificationString.c_str(),
|
if (memcmp(message + srm_restriction_data.offset,
|
||||||
kSRMVerificationString.size())) {
|
kSRMVerificationString.c_str(), kSRMVerificationString.size())) {
|
||||||
LOGE("SRM Requirement Data has bad verification string: %8s",
|
LOGE("SRM Requirement Data has bad verification string: %8s",
|
||||||
srm_requirement);
|
message + srm_restriction_data.offset);
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
uint32_t minimum_version =
|
uint32_t minimum_version = htonl(*reinterpret_cast<const uint32_t*>(
|
||||||
htonl(*reinterpret_cast<const uint32_t*>(srm_requirement + 8));
|
message + srm_restriction_data.offset + 8));
|
||||||
uint16_t current_version = 0;
|
uint16_t current_version = 0;
|
||||||
if (OEMCrypto_SUCCESS != ce_->current_srm_version(¤t_version)) {
|
if (OEMCrypto_SUCCESS != ce_->current_srm_version(¤t_version)) {
|
||||||
LOGW("[LoadKeys: SRM Version not available.");
|
LOGW("[LoadKeys: SRM Version not available.");
|
||||||
@@ -563,20 +565,25 @@ OEMCryptoResult SessionContext::LoadKeys(
|
|||||||
std::vector<uint8_t> key_control;
|
std::vector<uint8_t> key_control;
|
||||||
std::vector<uint8_t> key_control_iv;
|
std::vector<uint8_t> key_control_iv;
|
||||||
for (unsigned int i = 0; i < num_keys; i++) {
|
for (unsigned int i = 0; i < num_keys; i++) {
|
||||||
key_id.assign(key_array[i].key_id,
|
key_id.assign(
|
||||||
key_array[i].key_id + key_array[i].key_id_length);
|
message + key_array[i].key_id.offset,
|
||||||
enc_key_data.assign(key_array[i].key_data,
|
message + key_array[i].key_id.offset + key_array[i].key_id.length);
|
||||||
key_array[i].key_data + key_array[i].key_data_length);
|
enc_key_data.assign(
|
||||||
key_data_iv.assign(key_array[i].key_data_iv,
|
message + key_array[i].key_data.offset,
|
||||||
key_array[i].key_data_iv + wvoec::KEY_IV_SIZE);
|
message + key_array[i].key_data.offset + key_array[i].key_data.length);
|
||||||
if (key_array[i].key_control == NULL) {
|
key_data_iv.assign(
|
||||||
|
message + key_array[i].key_data_iv.offset,
|
||||||
|
message + key_array[i].key_data_iv.offset + wvoec::KEY_IV_SIZE);
|
||||||
|
if (key_array[i].key_control.length == 0) {
|
||||||
status = OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
status = OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
key_control.assign(key_array[i].key_control,
|
key_control.assign(
|
||||||
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
|
message + key_array[i].key_control.offset,
|
||||||
key_control_iv.assign(key_array[i].key_control_iv,
|
message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE);
|
||||||
key_array[i].key_control_iv + wvoec::KEY_IV_SIZE);
|
key_control_iv.assign(
|
||||||
|
message + key_array[i].key_control_iv.offset,
|
||||||
|
message + key_array[i].key_control_iv.offset + wvoec::KEY_IV_SIZE);
|
||||||
|
|
||||||
OEMCryptoResult result =
|
OEMCryptoResult result =
|
||||||
InstallKey(key_id, enc_key_data, key_data_iv, key_control,
|
InstallKey(key_id, enc_key_data, key_data_iv, key_control,
|
||||||
@@ -590,12 +597,14 @@ OEMCryptoResult SessionContext::LoadKeys(
|
|||||||
if (status != OEMCrypto_SUCCESS) return status;
|
if (status != OEMCrypto_SUCCESS) return status;
|
||||||
|
|
||||||
// enc_mac_key can be NULL if license renewal is not supported
|
// enc_mac_key can be NULL if license renewal is not supported
|
||||||
if (enc_mac_keys != NULL) {
|
if (enc_mac_keys.length != 0) {
|
||||||
// V2.1 license protocol: update mac keys after processing license response
|
// V2.1 license protocol: update mac keys after processing license response
|
||||||
const std::vector<uint8_t> enc_mac_keys_str = std::vector<uint8_t>(
|
const std::vector<uint8_t> enc_mac_keys_str = std::vector<uint8_t>(
|
||||||
enc_mac_keys, enc_mac_keys + 2 * wvoec::MAC_KEY_SIZE);
|
message + enc_mac_keys.offset,
|
||||||
|
message + enc_mac_keys.offset + 2 * wvoec::MAC_KEY_SIZE);
|
||||||
const std::vector<uint8_t> enc_mac_key_iv_str = std::vector<uint8_t>(
|
const std::vector<uint8_t> enc_mac_key_iv_str = std::vector<uint8_t>(
|
||||||
enc_mac_key_iv, enc_mac_key_iv + wvoec::KEY_IV_SIZE);
|
message + enc_mac_keys_iv.offset,
|
||||||
|
message + enc_mac_keys_iv.offset + wvoec::KEY_IV_SIZE);
|
||||||
|
|
||||||
if (!UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) {
|
if (!UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) {
|
||||||
LOGE("Failed to update mac keys.\n");
|
LOGE("Failed to update mac keys.\n");
|
||||||
@@ -606,13 +615,13 @@ OEMCryptoResult SessionContext::LoadKeys(
|
|||||||
OEMCryptoResult result = OEMCrypto_SUCCESS;
|
OEMCryptoResult result = OEMCrypto_SUCCESS;
|
||||||
switch (usage_entry_status_) {
|
switch (usage_entry_status_) {
|
||||||
case kNoUsageEntry:
|
case kNoUsageEntry:
|
||||||
if (pst_length > 0) {
|
if (pst.length > 0) {
|
||||||
LOGE("LoadKeys: PST specified but no usage entry loaded.");
|
LOGE("LoadKeys: PST specified but no usage entry loaded.");
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
break; // no extra check.
|
break; // no extra check.
|
||||||
case kUsageEntryNew:
|
case kUsageEntryNew:
|
||||||
result = usage_entry_->SetPST(pst, pst_length);
|
result = usage_entry_->SetPST(message + pst.offset, pst.length);
|
||||||
if (result != OEMCrypto_SUCCESS) {
|
if (result != OEMCrypto_SUCCESS) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -622,7 +631,7 @@ OEMCryptoResult SessionContext::LoadKeys(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kUsageEntryLoaded:
|
case kUsageEntryLoaded:
|
||||||
if (!usage_entry_->VerifyPST(pst, pst_length)) {
|
if (!usage_entry_->VerifyPST(message + pst.offset, pst.length)) {
|
||||||
return OEMCrypto_ERROR_WRONG_PST;
|
return OEMCrypto_ERROR_WRONG_PST;
|
||||||
}
|
}
|
||||||
if (!usage_entry_->VerifyMacKeys(mac_key_server_, mac_key_client_)) {
|
if (!usage_entry_->VerifyMacKeys(mac_key_server_, mac_key_client_)) {
|
||||||
@@ -637,7 +646,8 @@ OEMCryptoResult SessionContext::LoadKeys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
||||||
size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array) {
|
const uint8_t* message, size_t message_length, size_t num_keys,
|
||||||
|
const OEMCrypto_EntitledContentKeyObject* key_array) {
|
||||||
if (!key_array) {
|
if (!key_array) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -647,9 +657,9 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
|||||||
for (size_t i = 0; i < num_keys; ++i) {
|
for (size_t i = 0; i < num_keys; ++i) {
|
||||||
const OEMCrypto_EntitledContentKeyObject* key_data = &key_array[i];
|
const OEMCrypto_EntitledContentKeyObject* key_data = &key_array[i];
|
||||||
std::vector<uint8_t> entitlement_key_id;
|
std::vector<uint8_t> entitlement_key_id;
|
||||||
entitlement_key_id.assign(
|
entitlement_key_id.assign(message + key_data->entitlement_key_id.offset,
|
||||||
key_data->entitlement_key_id,
|
message + key_data->entitlement_key_id.offset +
|
||||||
key_data->entitlement_key_id + key_data->entitlement_key_id_length);
|
key_data->entitlement_key_id.length);
|
||||||
|
|
||||||
const std::vector<uint8_t>* entitlement_key = NULL;
|
const std::vector<uint8_t>* entitlement_key = NULL;
|
||||||
if (!session_keys_->GetEntitlementKey(entitlement_key_id,
|
if (!session_keys_->GetEntitlementKey(entitlement_key_id,
|
||||||
@@ -661,14 +671,14 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
|||||||
std::vector<uint8_t> encrypted_content_key;
|
std::vector<uint8_t> encrypted_content_key;
|
||||||
std::vector<uint8_t> content_key_id;
|
std::vector<uint8_t> content_key_id;
|
||||||
|
|
||||||
iv.assign(key_data->content_key_data_iv,
|
iv.assign(message + key_data->content_key_data_iv.offset,
|
||||||
key_data->content_key_data_iv + 16);
|
message + key_data->content_key_data_iv.offset + 16);
|
||||||
encrypted_content_key.assign(
|
encrypted_content_key.assign(message + key_data->content_key_data.offset,
|
||||||
key_data->content_key_data,
|
message + key_data->content_key_data.offset +
|
||||||
key_data->content_key_data + key_data->content_key_data_length);
|
key_data->content_key_data.length);
|
||||||
content_key_id.assign(
|
content_key_id.assign(message + key_data->content_key_id.offset,
|
||||||
key_data->content_key_id,
|
message + key_data->content_key_id.offset +
|
||||||
key_data->content_key_id + key_data->content_key_id_length);
|
key_data->content_key_id.length);
|
||||||
if (!DecryptMessage(*entitlement_key, iv, encrypted_content_key,
|
if (!DecryptMessage(*entitlement_key, iv, encrypted_content_key,
|
||||||
&content_key, 256 /* key size */)) {
|
&content_key, 256 /* key size */)) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
@@ -809,7 +819,7 @@ OEMCryptoResult SessionContext::RefreshKey(
|
|||||||
|
|
||||||
if (NULL == content_key) {
|
if (NULL == content_key) {
|
||||||
LOGE("Key ID not found.");
|
LOGE("Key ID not found.");
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_control.empty()) {
|
if (key_control.empty()) {
|
||||||
@@ -1156,8 +1166,9 @@ OEMCryptoResult SessionContext::SelectContentKey(
|
|||||||
Key* content_key = session_keys_->Find(key_id);
|
Key* content_key = session_keys_->Find(key_id);
|
||||||
if (NULL == content_key) {
|
if (NULL == content_key) {
|
||||||
LOGE("No key matches key id");
|
LOGE("No key matches key id");
|
||||||
return OEMCrypto_KEY_NOT_LOADED;
|
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||||
}
|
}
|
||||||
|
compute_hash_ = false;
|
||||||
content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR);
|
content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR);
|
||||||
current_content_key_ = content_key;
|
current_content_key_ = content_key;
|
||||||
const KeyControlBlock& control = current_content_key()->control();
|
const KeyControlBlock& control = current_content_key()->control();
|
||||||
@@ -1275,6 +1286,29 @@ OEMCryptoResult SessionContext::DecryptCENC(
|
|||||||
const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data,
|
const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data,
|
||||||
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
||||||
OEMCryptoBufferType buffer_type) {
|
OEMCryptoBufferType buffer_type) {
|
||||||
|
OEMCryptoResult result =
|
||||||
|
ChooseDecrypt(iv, block_offset, pattern, cipher_data, cipher_data_length,
|
||||||
|
is_encrypted, clear_data, buffer_type);
|
||||||
|
if (compute_hash_) {
|
||||||
|
if (current_content_key() == NULL ||
|
||||||
|
(current_content_key()->control().control_bits() &
|
||||||
|
wvoec::kControlAllowHashVerification) == 0) {
|
||||||
|
// This should not happen: this check should already have occured in
|
||||||
|
// InitializeDecryptHash or the hash should have been discarded in
|
||||||
|
// SelectContentKey. But it doesn't hurt to double check.
|
||||||
|
LOGE("[DecryptCENC(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
|
current_hash_ = wvcrc32Cont(clear_data, cipher_data_length, current_hash_);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult SessionContext::ChooseDecrypt(
|
||||||
|
const uint8_t* iv, size_t block_offset,
|
||||||
|
const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data,
|
||||||
|
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
||||||
|
OEMCryptoBufferType buffer_type) {
|
||||||
// If the data is clear, we do not need a current key selected.
|
// If the data is clear, we do not need a current key selected.
|
||||||
if (!is_encrypted) {
|
if (!is_encrypted) {
|
||||||
if (buffer_type != OEMCrypto_BufferType_Direct) {
|
if (buffer_type != OEMCrypto_BufferType_Direct) {
|
||||||
@@ -1492,4 +1526,62 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8,
|
|||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult SessionContext::InitializeDecryptHash() {
|
||||||
|
// Check there is a content key, and it is allowed.
|
||||||
|
if (current_content_key() == NULL ||
|
||||||
|
(current_content_key()->control().control_bits() &
|
||||||
|
wvoec::kControlAllowHashVerification) == 0) {
|
||||||
|
LOGE("[InitializeDecryptHash(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||||
|
compute_hash_ = false;
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
|
compute_hash_ = true;
|
||||||
|
current_hash_ = wvcrc32Init();
|
||||||
|
return OEMCrypto_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult SessionContext::SetDecryptHash(uint32_t frame_number,
|
||||||
|
const uint8_t* hash,
|
||||||
|
size_t hash_length) {
|
||||||
|
// Check there is a content key, and it is allowed.
|
||||||
|
if (current_content_key() == NULL ||
|
||||||
|
(current_content_key()->control().control_bits() &
|
||||||
|
wvoec::kControlAllowHashVerification) == 0) {
|
||||||
|
LOGE("[SetDecryptHash(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
|
if (!compute_hash_) {
|
||||||
|
// This would happen if somebody computes the hash, and then changes keys.
|
||||||
|
LOGE("[SetDecryptHash(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||||
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
}
|
||||||
|
compute_hash_ = false;
|
||||||
|
if (hash_length < sizeof(uint32_t)) {
|
||||||
|
LOGE("[SetDecryptHash(): short buffer]");
|
||||||
|
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||||
|
}
|
||||||
|
if (hash_length > sizeof(uint32_t)) {
|
||||||
|
LOGE("[SetDecryptHash(): long buffer]");
|
||||||
|
return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
|
||||||
|
}
|
||||||
|
uint32_t given_hash = *reinterpret_cast<const uint32_t*>(hash);
|
||||||
|
if (current_hash_ != given_hash) {
|
||||||
|
LOGE("CRC for frame %d is %08x, should be %08x\n", frame_number,
|
||||||
|
current_hash_, given_hash);
|
||||||
|
// Update bad_frame_number_ only if this is the first bad frame.
|
||||||
|
if (hash_error_ == OEMCrypto_SUCCESS) bad_frame_number_ = frame_number;
|
||||||
|
hash_error_ = OEMCrypto_ERROR_BAD_HASH;
|
||||||
|
}
|
||||||
|
// Return success if the hash was compared, even if there was an error.
|
||||||
|
return OEMCrypto_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult SessionContext::GetHashErrorCode(
|
||||||
|
uint32_t* failed_frame_number) {
|
||||||
|
if (failed_frame_number == NULL) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
|
if (hash_error_ != OEMCrypto_SUCCESS)
|
||||||
|
*failed_frame_number = bad_frame_number_;
|
||||||
|
return hash_error_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvoec_ref
|
} // namespace wvoec_ref
|
||||||
|
|||||||
@@ -73,7 +73,11 @@ class SessionContext {
|
|||||||
allowed_schemes_(kSign_RSASSA_PSS),
|
allowed_schemes_(kSign_RSASSA_PSS),
|
||||||
usage_entry_(NULL),
|
usage_entry_(NULL),
|
||||||
srm_requirements_status_(NoSRMVersion),
|
srm_requirements_status_(NoSRMVersion),
|
||||||
usage_entry_status_(kNoUsageEntry) {}
|
usage_entry_status_(kNoUsageEntry),
|
||||||
|
compute_hash_(false),
|
||||||
|
current_hash_(0),
|
||||||
|
bad_frame_number_(0),
|
||||||
|
hash_error_(OEMCrypto_SUCCESS) {}
|
||||||
virtual ~SessionContext();
|
virtual ~SessionContext();
|
||||||
|
|
||||||
bool isValid() { return valid_; }
|
bool isValid() { return valid_; }
|
||||||
@@ -119,13 +123,14 @@ class SessionContext {
|
|||||||
uint32_t CurrentTimer(); // (seconds).
|
uint32_t CurrentTimer(); // (seconds).
|
||||||
virtual OEMCryptoResult LoadKeys(
|
virtual OEMCryptoResult LoadKeys(
|
||||||
const uint8_t* message, size_t message_length, const uint8_t* signature,
|
const uint8_t* message, size_t message_length, const uint8_t* signature,
|
||||||
size_t signature_length, const uint8_t* enc_mac_key_iv,
|
size_t signature_length, OEMCrypto_Substring enc_mac_keys_iv,
|
||||||
const uint8_t* enc_mac_keys, size_t num_keys,
|
OEMCrypto_Substring enc_mac_keys, size_t num_keys,
|
||||||
const OEMCrypto_KeyObject* key_array, const uint8_t* pst,
|
const OEMCrypto_KeyObject* key_array, OEMCrypto_Substring pst,
|
||||||
size_t pst_length, const uint8_t* srm_requirement,
|
OEMCrypto_Substring srm_restriction_data,
|
||||||
OEMCrypto_LicenseType license_type);
|
OEMCrypto_LicenseType license_type);
|
||||||
OEMCryptoResult LoadEntitledContentKeys(
|
OEMCryptoResult LoadEntitledContentKeys(
|
||||||
size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array);
|
const uint8_t* message, size_t message_length, size_t num_keys,
|
||||||
|
const OEMCrypto_EntitledContentKeyObject* key_array);
|
||||||
virtual OEMCryptoResult InstallKey(const KeyId& key_id,
|
virtual OEMCryptoResult InstallKey(const KeyId& key_id,
|
||||||
const std::vector<uint8_t>& key_data,
|
const std::vector<uint8_t>& key_data,
|
||||||
const std::vector<uint8_t>& key_data_iv,
|
const std::vector<uint8_t>& key_data_iv,
|
||||||
@@ -147,6 +152,11 @@ class SessionContext {
|
|||||||
virtual bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
|
virtual bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
|
||||||
virtual OEMCryptoResult SelectContentKey(const KeyId& key_id,
|
virtual OEMCryptoResult SelectContentKey(const KeyId& key_id,
|
||||||
OEMCryptoCipherMode cipher_mode);
|
OEMCryptoCipherMode cipher_mode);
|
||||||
|
virtual OEMCryptoResult InitializeDecryptHash();
|
||||||
|
virtual OEMCryptoResult SetDecryptHash(uint32_t frame_number,
|
||||||
|
const uint8_t* hash,
|
||||||
|
size_t hash_length);
|
||||||
|
virtual OEMCryptoResult GetHashErrorCode(uint32_t* failed_frame_number);
|
||||||
const Key* current_content_key(void) { return current_content_key_; }
|
const Key* current_content_key(void) { return current_content_key_; }
|
||||||
void set_mac_key_server(const std::vector<uint8_t>& mac_key_server) {
|
void set_mac_key_server(const std::vector<uint8_t>& mac_key_server) {
|
||||||
mac_key_server_ = mac_key_server;
|
mac_key_server_ = mac_key_server;
|
||||||
@@ -199,6 +209,12 @@ class SessionContext {
|
|||||||
OEMCryptoResult CheckStatusOnline(uint32_t nonce, uint32_t control);
|
OEMCryptoResult CheckStatusOnline(uint32_t nonce, uint32_t control);
|
||||||
// Check that the usage entry status is valid for offline use.
|
// Check that the usage entry status is valid for offline use.
|
||||||
OEMCryptoResult CheckStatusOffline(uint32_t nonce, uint32_t control);
|
OEMCryptoResult CheckStatusOffline(uint32_t nonce, uint32_t control);
|
||||||
|
OEMCryptoResult ChooseDecrypt(const uint8_t* iv, size_t block_offset,
|
||||||
|
const OEMCrypto_CENCEncryptPatternDesc* pattern,
|
||||||
|
const uint8_t* cipher_data,
|
||||||
|
size_t cipher_data_length, bool is_encrypted,
|
||||||
|
uint8_t* clear_data,
|
||||||
|
OEMCryptoBufferType buffer_type);
|
||||||
OEMCryptoResult DecryptCBC(const uint8_t* key, const uint8_t* iv,
|
OEMCryptoResult DecryptCBC(const uint8_t* key, const uint8_t* iv,
|
||||||
const OEMCrypto_CENCEncryptPatternDesc* pattern,
|
const OEMCrypto_CENCEncryptPatternDesc* pattern,
|
||||||
const uint8_t* cipher_data,
|
const uint8_t* cipher_data,
|
||||||
@@ -238,6 +254,13 @@ class SessionContext {
|
|||||||
kUsageEntryLoaded, // After loading entry or loading keys.
|
kUsageEntryLoaded, // After loading entry or loading keys.
|
||||||
};
|
};
|
||||||
UsageEntryStatus usage_entry_status_;
|
UsageEntryStatus usage_entry_status_;
|
||||||
|
|
||||||
|
// These are used when doing full decrypt path testing.
|
||||||
|
bool compute_hash_; // True if the current frame needs a hash.
|
||||||
|
uint32_t current_hash_; // Running CRC hash of frame.
|
||||||
|
uint32_t bad_frame_number_; // Frame number with bad hash.
|
||||||
|
OEMCryptoResult hash_error_; // Error code for first bad frame.
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext);
|
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -69,16 +69,17 @@ UsageTableEntry::~UsageTableEntry() { usage_table_->ReleaseEntry(data_.index); }
|
|||||||
OEMCryptoResult UsageTableEntry::SetPST(const uint8_t* pst, size_t pst_length) {
|
OEMCryptoResult UsageTableEntry::SetPST(const uint8_t* pst, size_t pst_length) {
|
||||||
if (pst_length > kMaxPSTLength) return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
|
if (pst_length > kMaxPSTLength) return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
|
||||||
data_.pst_length = pst_length;
|
data_.pst_length = pst_length;
|
||||||
if (!pst) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
if (!pst || !pst_length) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
memcpy(data_.pst, pst, pst_length);
|
memcpy(data_.pst, pst, pst_length);
|
||||||
data_.time_of_license_received = time(NULL);
|
data_.time_of_license_received =
|
||||||
|
usage_table_->ce_->RollbackCorrectedOfflineTime();
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UsageTableEntry::VerifyPST(const uint8_t* pst, size_t pst_length) {
|
bool UsageTableEntry::VerifyPST(const uint8_t* pst, size_t pst_length) {
|
||||||
if (pst_length > kMaxPSTLength) return false;
|
if (pst_length > kMaxPSTLength) return false;
|
||||||
if (data_.pst_length != pst_length) return false;
|
if (data_.pst_length != pst_length) return false;
|
||||||
if (!pst) return false;
|
if (!pst || !pst_length) return false;
|
||||||
return 0 == memcmp(pst, data_.pst, pst_length);
|
return 0 == memcmp(pst, data_.pst, pst_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +106,8 @@ bool UsageTableEntry::CheckForUse() {
|
|||||||
recent_decrypt_ = true;
|
recent_decrypt_ = true;
|
||||||
if (data_.status == kUnused) {
|
if (data_.status == kUnused) {
|
||||||
data_.status = kActive;
|
data_.status = kActive;
|
||||||
data_.time_of_first_decrypt = time(NULL);
|
data_.time_of_first_decrypt =
|
||||||
|
usage_table_->ce_->RollbackCorrectedOfflineTime();
|
||||||
data_.generation_number++;
|
data_.generation_number++;
|
||||||
usage_table_->IncrementGeneration();
|
usage_table_->IncrementGeneration();
|
||||||
}
|
}
|
||||||
@@ -149,7 +151,7 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
|
|||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
wvcdm::Unpacked_PST_Report pst_report(buffer);
|
wvcdm::Unpacked_PST_Report pst_report(buffer);
|
||||||
int64_t now = time(NULL);
|
int64_t now = usage_table_->ce_->RollbackCorrectedOfflineTime();
|
||||||
pst_report.set_seconds_since_license_received(now -
|
pst_report.set_seconds_since_license_received(now -
|
||||||
data_.time_of_license_received);
|
data_.time_of_license_received);
|
||||||
pst_report.set_seconds_since_first_decrypt(now - data_.time_of_first_decrypt);
|
pst_report.set_seconds_since_first_decrypt(now - data_.time_of_first_decrypt);
|
||||||
@@ -170,7 +172,8 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
|
|||||||
|
|
||||||
void UsageTableEntry::UpdateAndIncrement() {
|
void UsageTableEntry::UpdateAndIncrement() {
|
||||||
if (recent_decrypt_) {
|
if (recent_decrypt_) {
|
||||||
data_.time_of_last_decrypt = time(NULL);
|
data_.time_of_last_decrypt =
|
||||||
|
usage_table_->ce_->RollbackCorrectedOfflineTime();
|
||||||
recent_decrypt_ = false;
|
recent_decrypt_ = false;
|
||||||
}
|
}
|
||||||
data_.generation_number++;
|
data_.generation_number++;
|
||||||
@@ -197,6 +200,10 @@ OEMCryptoResult UsageTableEntry::SaveData(CryptoEngine* ce,
|
|||||||
// 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.
|
||||||
const std::vector<uint8_t>& key = ce->DeviceRootKey();
|
const std::vector<uint8_t>& key = ce->DeviceRootKey();
|
||||||
|
if (key.empty()) {
|
||||||
|
LOGE("SaveUsageEntry: DeviceRootKey is unexpectedly empty.");
|
||||||
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
// Encrypt the entry.
|
// Encrypt the entry.
|
||||||
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
|
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
|
||||||
@@ -235,6 +242,10 @@ OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
|
|||||||
// 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.
|
||||||
const std::vector<uint8_t>& key = ce->DeviceRootKey();
|
const std::vector<uint8_t>& key = ce->DeviceRootKey();
|
||||||
|
if (key.empty()) {
|
||||||
|
LOGE("LoadUsageEntry: DeviceRootKey is unexpectedly empty.");
|
||||||
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
// Verify the signature of the usage entry. Sign encrypted into clear buffer.
|
// Verify the signature of the usage entry. Sign encrypted into clear buffer.
|
||||||
unsigned int sig_length = SHA256_DIGEST_LENGTH;
|
unsigned int sig_length = SHA256_DIGEST_LENGTH;
|
||||||
@@ -494,6 +505,10 @@ OEMCryptoResult UsageTable::SaveUsageTableHeader(uint8_t* signed_buffer,
|
|||||||
// 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.
|
||||||
const std::vector<uint8_t>& key = ce_->DeviceRootKey();
|
const std::vector<uint8_t>& key = ce_->DeviceRootKey();
|
||||||
|
if (key.empty()) {
|
||||||
|
LOGE("SaveUsageTableHeader: DeviceRootKey is unexpectedly empty.");
|
||||||
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
// Encrypt the entry.
|
// Encrypt the entry.
|
||||||
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
|
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
|
||||||
@@ -537,6 +552,10 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader(
|
|||||||
// 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.
|
||||||
const std::vector<uint8_t>& key = ce_->DeviceRootKey();
|
const std::vector<uint8_t>& key = ce_->DeviceRootKey();
|
||||||
|
if (key.empty()) {
|
||||||
|
LOGE("LoadUsageTableHeader: DeviceRootKey is unexpectedly empty.");
|
||||||
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
|
}
|
||||||
|
|
||||||
// Verify the signature of the usage entry. Sign encrypted into clear buffer.
|
// Verify the signature of the usage entry. Sign encrypted into clear buffer.
|
||||||
unsigned int sig_length = SHA256_DIGEST_LENGTH;
|
unsigned int sig_length = SHA256_DIGEST_LENGTH;
|
||||||
@@ -741,7 +760,7 @@ OEMCryptoResult UsageTable::CreateOldUsageEntry(
|
|||||||
std::vector<uint8_t> pstv(pst, pst + pst_length);
|
std::vector<uint8_t> pstv(pst, pst + pst_length);
|
||||||
OldUsageTableEntry* old_entry = old_table_->CreateEntry(pstv);
|
OldUsageTableEntry* old_entry = old_table_->CreateEntry(pstv);
|
||||||
|
|
||||||
int64_t now = time(NULL);
|
int64_t now = ce_->RollbackCorrectedOfflineTime();
|
||||||
old_entry->time_of_license_received_ = now - time_since_license_received;
|
old_entry->time_of_license_received_ = now - time_since_license_received;
|
||||||
old_entry->time_of_first_decrypt_ = now - time_since_first_decrypt;
|
old_entry->time_of_first_decrypt_ = now - time_since_first_decrypt;
|
||||||
old_entry->time_of_last_decrypt_ = now - time_since_last_decrypt;
|
old_entry->time_of_last_decrypt_ = now - time_since_last_decrypt;
|
||||||
|
|||||||
@@ -129,6 +129,8 @@ class UsageTable {
|
|||||||
std::vector<int64_t> generation_numbers_;
|
std::vector<int64_t> generation_numbers_;
|
||||||
std::vector<SessionContext*> sessions_;
|
std::vector<SessionContext*> sessions_;
|
||||||
OldUsageTable* old_table_;
|
OldUsageTable* old_table_;
|
||||||
|
|
||||||
|
friend class UsageTableEntry;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wvoec_ref
|
} // namespace wvoec_ref
|
||||||
|
|||||||
@@ -91,6 +91,14 @@ uint32_t wvcrc32(const uint8_t* p_begin, int i_count) {
|
|||||||
return(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
return(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t wvcrc32Init() {
|
||||||
|
return INIT_CRC32;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t wvcrc32Cont(const uint8_t* p_begin, int i_count, uint32_t prev_crc) {
|
||||||
|
return(wvrunningcrc32(p_begin, i_count, prev_crc));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count) {
|
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count) {
|
||||||
return htonl(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
return htonl(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
uint32_t wvcrc32(const uint8_t* p_begin, int i_count);
|
uint32_t wvcrc32(const uint8_t* p_begin, int i_count);
|
||||||
|
uint32_t wvcrc32Init();
|
||||||
|
uint32_t wvcrc32Cont(const uint8_t* p_begin, int i_count, uint32_t prev_crc);
|
||||||
|
|
||||||
// Convert to network byte order
|
// Convert to network byte order
|
||||||
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count);
|
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
|
|||||||
supports_rsa_3072 = false;
|
supports_rsa_3072 = false;
|
||||||
api_version = 0;
|
api_version = 0;
|
||||||
derive_key_method = NO_METHOD;
|
derive_key_method = NO_METHOD;
|
||||||
|
OEMCrypto_SetSandbox(kTestSandbox, sizeof(kTestSandbox));
|
||||||
if (OEMCrypto_SUCCESS != OEMCrypto_Initialize()) {
|
if (OEMCrypto_SUCCESS != OEMCrypto_Initialize()) {
|
||||||
printf("OEMCrypto_Initialize failed. All tests will fail.\n");
|
printf("OEMCrypto_Initialize failed. All tests will fail.\n");
|
||||||
return;
|
return;
|
||||||
@@ -94,6 +95,19 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("cast_receiver = %s.\n", cast_receiver ? "true" : "false");
|
printf("cast_receiver = %s.\n", cast_receiver ? "true" : "false");
|
||||||
|
resource_rating = OEMCrypto_ResourceRatingTier();
|
||||||
|
printf("resource_rating = %d, security leve %s.\n", resource_rating,
|
||||||
|
OEMCrypto_SecurityLevel());
|
||||||
|
uint32_t decrypt_hash_type = OEMCrypto_SupportsDecryptHash();
|
||||||
|
supports_crc = (decrypt_hash_type == OEMCrypto_CRC_Clear_Buffer);
|
||||||
|
if (supports_crc) {
|
||||||
|
printf("Decrypt hashes will be tested.\n");
|
||||||
|
} else {
|
||||||
|
printf("Decrypt hashes will not be tested -- %s.\n",
|
||||||
|
decrypt_hash_type == OEMCrypto_Hash_Not_Supported
|
||||||
|
? "not supported"
|
||||||
|
: "partner defined hash");
|
||||||
|
}
|
||||||
switch (derive_key_method) {
|
switch (derive_key_method) {
|
||||||
case NO_METHOD:
|
case NO_METHOD:
|
||||||
printf("NO_METHOD: Cannot derive known session keys.\n");
|
printf("NO_METHOD: Cannot derive known session keys.\n");
|
||||||
@@ -110,9 +124,6 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
|
|||||||
case LOAD_TEST_RSA_KEY:
|
case LOAD_TEST_RSA_KEY:
|
||||||
printf("LOAD_TEST_RSA_KEY: Call LoadTestRSAKey before deriving keys.\n");
|
printf("LOAD_TEST_RSA_KEY: Call LoadTestRSAKey before deriving keys.\n");
|
||||||
break;
|
break;
|
||||||
case EXISTING_TEST_KEYBOX:
|
|
||||||
printf("EXISTING_TEST_KEYBOX: Keybox is already the test keybox.\n");
|
|
||||||
break;
|
|
||||||
case FORCE_TEST_KEYBOX:
|
case FORCE_TEST_KEYBOX:
|
||||||
printf("FORCE_TEST_KEYBOX: User requested calling InstallKeybox.\n");
|
printf("FORCE_TEST_KEYBOX: User requested calling InstallKeybox.\n");
|
||||||
break;
|
break;
|
||||||
@@ -120,6 +131,11 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
|
|||||||
printf("TEST_PROVISION_30: Device provisioed with OEM Cert.\n");
|
printf("TEST_PROVISION_30: Device provisioed with OEM Cert.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
std::string security_level = OEMCrypto_SecurityLevel();
|
||||||
|
supports_level_1 = (security_level == "L1");
|
||||||
|
printf("SecurityLevel is %s (%s)",
|
||||||
|
supports_level_1 ? "Level 1" : "Not Level 1",
|
||||||
|
security_level.c_str());
|
||||||
OEMCrypto_Terminate();
|
OEMCrypto_Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,32 +199,12 @@ void DeviceFeatures::PickDerivedKey() {
|
|||||||
// If device uses a keybox, try to load the test keybox.
|
// If device uses a keybox, try to load the test keybox.
|
||||||
if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestKeybox(NULL, 0)) {
|
if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestKeybox(NULL, 0)) {
|
||||||
derive_key_method = LOAD_TEST_KEYBOX;
|
derive_key_method = LOAD_TEST_KEYBOX;
|
||||||
} else if (IsTestKeyboxInstalled()) {
|
|
||||||
derive_key_method = EXISTING_TEST_KEYBOX;
|
|
||||||
}
|
}
|
||||||
} else if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestRSAKey()) {
|
} else if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestRSAKey()) {
|
||||||
derive_key_method = LOAD_TEST_RSA_KEY;
|
derive_key_method = LOAD_TEST_RSA_KEY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceFeatures::IsTestKeyboxInstalled() {
|
|
||||||
uint8_t key_data[256];
|
|
||||||
size_t key_data_len = sizeof(key_data);
|
|
||||||
if (OEMCrypto_GetKeyData(key_data, &key_data_len) != OEMCrypto_SUCCESS)
|
|
||||||
return false;
|
|
||||||
if (key_data_len != sizeof(kValidKeybox01.data_)) return false;
|
|
||||||
if (memcmp(key_data, kValidKeybox01.data_, key_data_len)) return false;
|
|
||||||
uint8_t dev_id[128] = {0};
|
|
||||||
size_t dev_id_len = 128;
|
|
||||||
if (OEMCrypto_GetDeviceID(dev_id, &dev_id_len) != OEMCrypto_SUCCESS)
|
|
||||||
return false;
|
|
||||||
// We use strncmp instead of memcmp because we don't really care about the
|
|
||||||
// multiple '\0' characters at the end of the device id.
|
|
||||||
return 0 == strncmp(reinterpret_cast<const char*>(dev_id),
|
|
||||||
reinterpret_cast<const char*>(kValidKeybox01.device_id_),
|
|
||||||
sizeof(kValidKeybox01.device_id_));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceFeatures::FilterOut(std::string* current_filter,
|
void DeviceFeatures::FilterOut(std::string* current_filter,
|
||||||
const std::string& new_filter) {
|
const std::string& new_filter) {
|
||||||
if (current_filter->find('-') == std::string::npos) {
|
if (current_filter->find('-') == std::string::npos) {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ class DeviceFeatures {
|
|||||||
NO_METHOD, // Cannot derive known session keys.
|
NO_METHOD, // Cannot derive known session keys.
|
||||||
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
|
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
|
||||||
LOAD_TEST_RSA_KEY, // Call LoadTestRSAKey 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.
|
FORCE_TEST_KEYBOX, // User requested calling InstallKeybox.
|
||||||
TEST_PROVISION_30, // Device has OEM Certificate installed.
|
TEST_PROVISION_30, // Device has OEM Certificate installed.
|
||||||
};
|
};
|
||||||
@@ -27,6 +26,9 @@ class DeviceFeatures {
|
|||||||
bool cast_receiver; // Device supports alternate rsa signature padding.
|
bool cast_receiver; // Device supports alternate rsa signature padding.
|
||||||
bool usage_table; // Device saves usage information.
|
bool usage_table; // Device saves usage information.
|
||||||
bool supports_rsa_3072; // Device supports 3072 bit RSA keys.
|
bool supports_rsa_3072; // Device supports 3072 bit RSA keys.
|
||||||
|
bool supports_level_1; // Device supports Level 1 security.
|
||||||
|
uint32_t resource_rating; // Device's resource rating tier.
|
||||||
|
bool supports_crc; // Supported decrypt hash type CRC.
|
||||||
uint32_t api_version;
|
uint32_t api_version;
|
||||||
OEMCrypto_ProvisioningMethod provisioning_method;
|
OEMCrypto_ProvisioningMethod provisioning_method;
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENC.h"
|
||||||
@@ -96,6 +97,26 @@ class boringssl_ptr {
|
|||||||
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
|
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
OEMCrypto_Substring GetSubstring(const std::string& message,
|
||||||
|
const std::string& field, bool set_zero) {
|
||||||
|
OEMCrypto_Substring substring;
|
||||||
|
if (set_zero || field.empty() || message.empty()) {
|
||||||
|
substring.offset = 0;
|
||||||
|
substring.length = 0;
|
||||||
|
} else {
|
||||||
|
size_t pos = message.find(field);
|
||||||
|
if (pos == std::string::npos) {
|
||||||
|
LOGW("GetSubstring : Cannot find offset for %s", field.c_str());
|
||||||
|
substring.offset = 0;
|
||||||
|
substring.length = 0;
|
||||||
|
} else {
|
||||||
|
substring.offset = pos;
|
||||||
|
substring.length = field.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return substring;
|
||||||
|
}
|
||||||
|
|
||||||
Session::Session()
|
Session::Session()
|
||||||
: open_(false),
|
: open_(false),
|
||||||
forced_session_id_(false),
|
forced_session_id_(false),
|
||||||
@@ -253,129 +274,149 @@ void Session::GenerateDerivedKeysFromSessionKey() {
|
|||||||
DeriveKeys(&session_key[0], mac_context, enc_context);
|
DeriveKeys(&session_key[0], mac_context, enc_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
void Session::LoadTestKeys(const std::string& provider_session_token,
|
||||||
uint8_t* pst_ptr = NULL;
|
bool new_mac_keys) {
|
||||||
if (pst.length() > 0) {
|
std::string message =
|
||||||
pst_ptr = encrypted_license().pst;
|
wvcdm::BytesToString(message_ptr(), sizeof(MessageData));
|
||||||
}
|
OEMCrypto_Substring pst = GetSubstring(message, provider_session_token);
|
||||||
|
OEMCrypto_Substring enc_mac_keys_iv = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(encrypted_license().mac_key_iv,
|
||||||
|
sizeof(encrypted_license().mac_key_iv)));
|
||||||
|
OEMCrypto_Substring enc_mac_keys = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(encrypted_license().mac_keys,
|
||||||
|
sizeof(encrypted_license().mac_keys)));
|
||||||
if (new_mac_keys) {
|
if (new_mac_keys) {
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
OEMCrypto_LoadKeys(
|
||||||
&signature_[0], signature_.size(),
|
session_id(), message_ptr(), message_size_, &signature_[0],
|
||||||
encrypted_license().mac_key_iv,
|
signature_.size(), enc_mac_keys_iv, enc_mac_keys, num_keys_,
|
||||||
encrypted_license().mac_keys, num_keys_,
|
key_array_, pst, GetSubstring(), OEMCrypto_ContentLicense));
|
||||||
key_array_, pst_ptr, pst.length(), NULL,
|
|
||||||
OEMCrypto_ContentLicense));
|
|
||||||
// Update new generated keys.
|
// Update new generated keys.
|
||||||
memcpy(&mac_key_server_[0], license_.mac_keys, MAC_KEY_SIZE);
|
memcpy(&mac_key_server_[0], license_.mac_keys, MAC_KEY_SIZE);
|
||||||
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE,
|
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE, MAC_KEY_SIZE);
|
||||||
MAC_KEY_SIZE);
|
|
||||||
} else {
|
} else {
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_SUCCESS,
|
OEMCrypto_LoadKeys(
|
||||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
session_id(), message_ptr(), message_size_, &signature_[0],
|
||||||
&signature_[0], signature_.size(), NULL, NULL,
|
signature_.size(), GetSubstring(), GetSubstring(), num_keys_,
|
||||||
num_keys_, key_array_, pst_ptr, pst.length(), NULL,
|
key_array_, pst, GetSubstring(), OEMCrypto_ContentLicense));
|
||||||
OEMCrypto_ContentLicense));
|
|
||||||
}
|
}
|
||||||
VerifyTestKeys();
|
VerifyTestKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::LoadEnitlementTestKeys(const std::string& pst,
|
void Session::LoadEntitlementTestKeys(const std::string& provider_session_token,
|
||||||
bool new_mac_keys,
|
bool new_mac_keys,
|
||||||
OEMCryptoResult expected_sts) {
|
OEMCryptoResult expected_sts) {
|
||||||
uint8_t* pst_ptr = NULL;
|
std::string message =
|
||||||
if (pst.length() > 0) {
|
wvcdm::BytesToString(message_ptr(), sizeof(MessageData));
|
||||||
pst_ptr = encrypted_license().pst;
|
OEMCrypto_Substring pst = GetSubstring(message, provider_session_token);
|
||||||
}
|
OEMCrypto_Substring enc_mac_keys_iv = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(encrypted_license().mac_key_iv,
|
||||||
|
sizeof(encrypted_license().mac_key_iv)));
|
||||||
|
OEMCrypto_Substring enc_mac_keys = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(encrypted_license().mac_keys,
|
||||||
|
sizeof(encrypted_license().mac_keys)));
|
||||||
if (new_mac_keys) {
|
if (new_mac_keys) {
|
||||||
ASSERT_EQ(expected_sts,
|
ASSERT_EQ(
|
||||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
expected_sts,
|
||||||
&signature_[0], signature_.size(),
|
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||||
encrypted_license().mac_key_iv,
|
&signature_[0], signature_.size(), enc_mac_keys_iv,
|
||||||
encrypted_license().mac_keys, num_keys_,
|
enc_mac_keys, num_keys_, key_array_, pst,
|
||||||
key_array_, pst_ptr, pst.length(), NULL,
|
GetSubstring(), OEMCrypto_EntitlementLicense));
|
||||||
OEMCrypto_EntitlementLicense));
|
|
||||||
// Update new generated keys.
|
// Update new generated keys.
|
||||||
memcpy(&mac_key_server_[0], license_.mac_keys, MAC_KEY_SIZE);
|
memcpy(&mac_key_server_[0], license_.mac_keys, MAC_KEY_SIZE);
|
||||||
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE,
|
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE, MAC_KEY_SIZE);
|
||||||
MAC_KEY_SIZE);
|
|
||||||
} else {
|
} else {
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(
|
||||||
expected_sts,
|
expected_sts,
|
||||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||||
&signature_[0], signature_.size(), NULL, NULL,
|
&signature_[0], signature_.size(), GetSubstring(),
|
||||||
num_keys_, key_array_, pst_ptr, pst.length(), NULL,
|
GetSubstring(), num_keys_, key_array_, pst,
|
||||||
OEMCrypto_EntitlementLicense));
|
GetSubstring(), OEMCrypto_EntitlementLicense));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::FillEntitledKeyArray() {
|
void Session::FillEntitledKeyArray() {
|
||||||
|
int offset = 0;
|
||||||
|
entitled_message_.clear();
|
||||||
for (size_t i = 0; i < num_keys_; ++i) {
|
for (size_t i = 0; i < num_keys_; ++i) {
|
||||||
EntitledContentKeyData* key_data = &entitled_key_data_[i];
|
EntitledContentKeyData* key_data = &entitled_key_data_[i];
|
||||||
|
|
||||||
entitled_key_array_[i].entitlement_key_id = key_array_[i].key_id;
|
entitled_key_array_[i].entitlement_key_id.offset = offset;
|
||||||
entitled_key_array_[i].entitlement_key_id_length =
|
entitled_key_array_[i].entitlement_key_id.length =
|
||||||
key_array_[i].key_id_length;
|
key_array_[i].key_id.length;
|
||||||
|
offset += key_array_[i].key_id.length;
|
||||||
|
entitled_message_ +=
|
||||||
|
wvcdm::BytesToString(message_ptr() + key_array_[i].key_id.offset,
|
||||||
|
key_array_[i].key_id.length);
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(1, GetRandBytes(key_data->content_key_id,
|
||||||
1, GetRandBytes(key_data->content_key_id,
|
sizeof(key_data->content_key_id)));
|
||||||
sizeof(key_data->content_key_id)));
|
entitled_key_array_[i].content_key_id.offset = offset;
|
||||||
entitled_key_array_[i].content_key_id = key_data->content_key_id;
|
entitled_key_array_[i].content_key_id.length =
|
||||||
entitled_key_array_[i].content_key_id_length =
|
|
||||||
sizeof(key_data->content_key_id);
|
sizeof(key_data->content_key_id);
|
||||||
|
offset += sizeof(key_data->content_key_id);
|
||||||
|
entitled_message_ += wvcdm::BytesToString(key_data->content_key_id,
|
||||||
|
sizeof(key_data->content_key_id));
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(1, GetRandBytes(key_data->content_key_data,
|
||||||
1, GetRandBytes(key_data->content_key_data,
|
sizeof(key_data->content_key_data)));
|
||||||
sizeof(key_data->content_key_data)));
|
entitled_key_array_[i].content_key_data.offset = offset;
|
||||||
entitled_key_array_[i].content_key_data = key_data->content_key_data;
|
entitled_key_array_[i].content_key_data.length =
|
||||||
entitled_key_array_[i].content_key_data_length =
|
|
||||||
sizeof(key_data->content_key_data);
|
sizeof(key_data->content_key_data);
|
||||||
|
offset += sizeof(key_data->content_key_data);
|
||||||
|
entitled_message_ += wvcdm::BytesToString(
|
||||||
|
key_data->content_key_data, sizeof(key_data->content_key_data));
|
||||||
|
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(1, GetRandBytes(key_data[i].content_key_data_iv,
|
||||||
1, GetRandBytes(entitled_key_data_[i].content_key_data_iv,
|
sizeof(key_data[i].content_key_data_iv)));
|
||||||
sizeof(entitled_key_data_[i].content_key_data_iv)));
|
entitled_key_array_[i].content_key_data_iv.offset = offset;
|
||||||
entitled_key_array_[i].content_key_data_iv = key_data->content_key_data_iv;
|
entitled_key_array_[i].content_key_data_iv.length =
|
||||||
|
sizeof(key_data->content_key_data_iv);
|
||||||
|
offset += sizeof(key_data->content_key_data_iv);
|
||||||
|
entitled_message_ += wvcdm::BytesToString(
|
||||||
|
key_data->content_key_data_iv, sizeof(key_data->content_key_data_iv));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::LoadEntitledContentKeys(OEMCryptoResult expected_sts) {
|
void Session::LoadEntitledContentKeys(OEMCryptoResult expected_sts) {
|
||||||
// Create a copy of the stored |entitled_key_array_|.
|
encrypted_entitled_message_ = entitled_message_;
|
||||||
std::vector<OEMCrypto_EntitledContentKeyObject> encrypted_entitled_key_array;
|
std::vector<OEMCrypto_EntitledContentKeyObject> encrypted_entitled_key_array;
|
||||||
encrypted_entitled_key_array.resize(num_keys_);
|
encrypted_entitled_key_array.resize(num_keys_);
|
||||||
memcpy(&encrypted_entitled_key_array[0], &entitled_key_array_[0],
|
memcpy(&encrypted_entitled_key_array[0], &entitled_key_array_[0],
|
||||||
sizeof(OEMCrypto_EntitledContentKeyObject) * num_keys_);
|
sizeof(OEMCrypto_EntitledContentKeyObject) * num_keys_);
|
||||||
|
|
||||||
// Create a encrypted version of all of the content keys stored in
|
|
||||||
// |entitled_key_array_|.
|
|
||||||
std::vector<std::vector<uint8_t> > encrypted_content_keys;
|
|
||||||
encrypted_content_keys.resize(num_keys_);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < num_keys_; ++i) {
|
for (size_t i = 0; i < num_keys_; ++i) {
|
||||||
// Load the entitlement key from |key_array_|.
|
// Load the entitlement key from |key_array_|.
|
||||||
AES_KEY aes_key;
|
AES_KEY aes_key;
|
||||||
AES_set_encrypt_key(&key_array_[i].key_data[0], 256, &aes_key);
|
AES_set_encrypt_key(message_ptr() + key_array_[i].key_data.offset, 256,
|
||||||
encrypted_content_keys[i].resize(
|
&aes_key);
|
||||||
encrypted_entitled_key_array[i].content_key_data_length);
|
|
||||||
|
|
||||||
// Encrypt the content key with the entitlement key.
|
// Encrypt the content key with the entitlement key.
|
||||||
uint8_t iv[16];
|
uint8_t iv[16];
|
||||||
memcpy(&iv[0], &encrypted_entitled_key_array[i].content_key_data[0], 16);
|
const uint8_t* content_key_data = reinterpret_cast<const uint8_t*>(
|
||||||
AES_cbc_encrypt(
|
entitled_message_.data() +
|
||||||
&entitled_key_array_[i].content_key_data[0],
|
entitled_key_array_[i].content_key_data.offset);
|
||||||
const_cast<uint8_t*>(
|
const uint8_t* encrypted_content_key_data =
|
||||||
&encrypted_entitled_key_array[i].content_key_data[0]),
|
reinterpret_cast<const uint8_t*>(
|
||||||
encrypted_entitled_key_array[i].content_key_data_length,
|
encrypted_entitled_message_.data() +
|
||||||
&aes_key, iv, AES_ENCRYPT);
|
encrypted_entitled_key_array[i].content_key_data.offset);
|
||||||
|
memcpy(&iv[0],
|
||||||
// Set the |encrypted_entitled_key_array| to point to the encrypted copy
|
message_ptr() +
|
||||||
// of the content key.
|
encrypted_entitled_key_array[i].content_key_data_iv.offset,
|
||||||
encrypted_entitled_key_array[i].content_key_data =
|
16);
|
||||||
encrypted_content_keys[i].data();
|
AES_cbc_encrypt(content_key_data,
|
||||||
|
const_cast<uint8_t*>(encrypted_content_key_data),
|
||||||
|
encrypted_entitled_key_array[i].content_key_data.length,
|
||||||
|
&aes_key, iv, AES_ENCRYPT);
|
||||||
}
|
}
|
||||||
ASSERT_EQ(expected_sts,
|
ASSERT_EQ(
|
||||||
OEMCrypto_LoadEntitledContentKeys(
|
expected_sts,
|
||||||
session_id(), num_keys_, &encrypted_entitled_key_array[0]));
|
OEMCrypto_LoadEntitledContentKeys(
|
||||||
|
session_id(),
|
||||||
|
reinterpret_cast<const uint8_t*>(encrypted_entitled_message_.data()),
|
||||||
|
encrypted_entitled_message_.size(), num_keys_,
|
||||||
|
&encrypted_entitled_key_array[0]));
|
||||||
if (expected_sts != OEMCrypto_SUCCESS) {
|
if (expected_sts != OEMCrypto_SUCCESS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -408,9 +449,12 @@ void Session::VerifyEntitlementTestKeys() {
|
|||||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||||
KeyControlBlock block;
|
KeyControlBlock block;
|
||||||
size_t size = sizeof(block);
|
size_t size = sizeof(block);
|
||||||
|
const uint8_t* content_key_id =
|
||||||
|
reinterpret_cast<const uint8_t*>(entitled_message_.data());
|
||||||
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
|
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
|
||||||
session_id(), entitled_key_array_[i].content_key_id,
|
session_id(),
|
||||||
entitled_key_array_[i].content_key_id_length,
|
content_key_id + entitled_key_array_[i].content_key_id.offset,
|
||||||
|
entitled_key_array_[i].content_key_id.length,
|
||||||
reinterpret_cast<uint8_t*>(&block), &size);
|
reinterpret_cast<uint8_t*>(&block), &size);
|
||||||
if (sts != OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
if (sts != OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||||
@@ -482,15 +526,12 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
|
|||||||
sizeof(license_.keys[i].key_iv)));
|
sizeof(license_.keys[i].key_iv)));
|
||||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
|
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
|
||||||
sizeof(license_.keys[i].control_iv)));
|
sizeof(license_.keys[i].control_iv)));
|
||||||
if (global_features.api_version == 14) {
|
if (global_features.api_version >= 12) {
|
||||||
// For version 14, we require OEMCrypto to handle kc14 for all licenses.
|
// For version 12 and above, we require OEMCrypto to handle kcNN for all
|
||||||
memcpy(license_.keys[i].control.verification, "kc14", 4);
|
// licenses.
|
||||||
} else if (global_features.api_version == 13) {
|
std::stringstream stream;
|
||||||
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
|
stream << "kc" << global_features.api_version;
|
||||||
memcpy(license_.keys[i].control.verification, "kc13", 4);
|
memcpy(license_.keys[i].control.verification, stream.str().c_str(), 4);
|
||||||
} else if (global_features.api_version == 12) {
|
|
||||||
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
|
|
||||||
memcpy(license_.keys[i].control.verification, "kc12", 4);
|
|
||||||
} else if (control & wvoec::kControlSecurityPatchLevelMask) {
|
} else if (control & wvoec::kControlSecurityPatchLevelMask) {
|
||||||
// For versions before 12, we require the special key control block only
|
// For versions before 12, we require the special key control block only
|
||||||
// when there are newer features present.
|
// when there are newer features present.
|
||||||
@@ -529,15 +570,12 @@ void Session::FillSimpleEntitlementMessage(
|
|||||||
sizeof(license_.keys[i].key_iv)));
|
sizeof(license_.keys[i].key_iv)));
|
||||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
|
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
|
||||||
sizeof(license_.keys[i].control_iv)));
|
sizeof(license_.keys[i].control_iv)));
|
||||||
if (global_features.api_version == 14) {
|
if (global_features.api_version >= 12) {
|
||||||
// For version 13, we require OEMCrypto to handle kc14 for all licenses.
|
// For version 12 and above, we require OEMCrypto to handle kcNN for all
|
||||||
memcpy(license_.keys[i].control.verification, "kc14", 4);
|
// licenses.
|
||||||
} else if (global_features.api_version == 13) {
|
std::stringstream stream;
|
||||||
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
|
stream << "kc" << global_features.api_version;
|
||||||
memcpy(license_.keys[i].control.verification, "kc13", 4);
|
memcpy(license_.keys[i].control.verification, stream.str().c_str(), 4);
|
||||||
} else if (global_features.api_version == 12) {
|
|
||||||
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
|
|
||||||
memcpy(license_.keys[i].control.verification, "kc12", 4);
|
|
||||||
} else if (control & wvoec::kControlSecurityPatchLevelMask) {
|
} else if (control & wvoec::kControlSecurityPatchLevelMask) {
|
||||||
// For versions before 12, we require the special key control block only
|
// For versions before 12, we require the special key control block only
|
||||||
// when there are newer features present.
|
// when there are newer features present.
|
||||||
@@ -565,15 +603,13 @@ void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
|||||||
encrypted_license().keys[i].key_id_length = license_.keys[i].key_id_length;
|
encrypted_license().keys[i].key_id_length = license_.keys[i].key_id_length;
|
||||||
memcpy(encrypted_license().keys[i].key_id, license_.keys[i].key_id,
|
memcpy(encrypted_license().keys[i].key_id, license_.keys[i].key_id,
|
||||||
encrypted_license().keys[i].key_id_length);
|
encrypted_license().keys[i].key_id_length);
|
||||||
if (global_features.api_version == 14) {
|
if (global_features.api_version >= 12) {
|
||||||
// For version 14, we require OEMCrypto to handle kc14 for all licenses.
|
// For version 12 and above, we require OEMCrypto to handle kcNN for all
|
||||||
memcpy(encrypted_license().keys[i].control.verification, "kc14", 4);
|
// licenses.
|
||||||
} else if (global_features.api_version == 13) {
|
std::stringstream stream;
|
||||||
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
|
stream << "kc" << global_features.api_version;
|
||||||
memcpy(encrypted_license().keys[i].control.verification, "kc13", 4);
|
memcpy(encrypted_license().keys[i].control.verification,
|
||||||
} else if (global_features.api_version == 12) {
|
stream.str().c_str(), 4);
|
||||||
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
|
|
||||||
memcpy(encrypted_license().keys[i].control.verification, "kc12", 4);
|
|
||||||
} else {
|
} else {
|
||||||
// For versions before 12, we require the special key control block only
|
// For versions before 12, we require the special key control block only
|
||||||
// when there are newer features present.
|
// when there are newer features present.
|
||||||
@@ -585,6 +621,27 @@ void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::SetLoadKeysSubstringParams() {
|
||||||
|
load_keys_params_.resize(4);
|
||||||
|
std::string message =
|
||||||
|
wvcdm::BytesToString(message_ptr(), sizeof(MessageData));
|
||||||
|
OEMCrypto_Substring* enc_mac_keys_iv = &load_keys_params_[0];
|
||||||
|
*enc_mac_keys_iv = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(encrypted_license().mac_key_iv,
|
||||||
|
sizeof(encrypted_license().mac_key_iv)));
|
||||||
|
OEMCrypto_Substring* enc_mac_keys = &load_keys_params_[1];
|
||||||
|
*enc_mac_keys = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(encrypted_license().mac_keys,
|
||||||
|
sizeof(encrypted_license().mac_keys)));
|
||||||
|
OEMCrypto_Substring* pst = &load_keys_params_[2];
|
||||||
|
size_t pst_length =
|
||||||
|
strlen(reinterpret_cast<const char*>(encrypted_license().pst));
|
||||||
|
*pst = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(encrypted_license().pst, pst_length));
|
||||||
|
OEMCrypto_Substring* srm_req = &load_keys_params_[3];
|
||||||
|
*srm_req = GetSubstring();
|
||||||
|
}
|
||||||
|
|
||||||
void Session::EncryptAndSign() {
|
void Session::EncryptAndSign() {
|
||||||
encrypted_license() = license_;
|
encrypted_license() = license_;
|
||||||
|
|
||||||
@@ -613,6 +670,7 @@ void Session::EncryptAndSign() {
|
|||||||
ServerSignBuffer(reinterpret_cast<const uint8_t*>(&padded_message_),
|
ServerSignBuffer(reinterpret_cast<const uint8_t*>(&padded_message_),
|
||||||
message_size_, &signature_);
|
message_size_, &signature_);
|
||||||
FillKeyArray(encrypted_license(), key_array_);
|
FillKeyArray(encrypted_license(), key_array_);
|
||||||
|
SetLoadKeysSubstringParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::EncryptProvisioningMessage(
|
void Session::EncryptProvisioningMessage(
|
||||||
@@ -671,31 +729,45 @@ void Session::VerifyClientSignature(size_t data_length) {
|
|||||||
|
|
||||||
void Session::FillKeyArray(const MessageData& data,
|
void Session::FillKeyArray(const MessageData& data,
|
||||||
OEMCrypto_KeyObject* key_array) {
|
OEMCrypto_KeyObject* key_array) {
|
||||||
|
const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&data);
|
||||||
|
std::string message = wvcdm::BytesToString(data_ptr, sizeof(MessageData));
|
||||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||||
key_array[i].key_id = data.keys[i].key_id;
|
key_array[i].key_id = GetSubstring(
|
||||||
key_array[i].key_id_length = data.keys[i].key_id_length;
|
message,
|
||||||
key_array[i].key_data_iv = data.keys[i].key_iv;
|
wvcdm::BytesToString(data.keys[i].key_id, data.keys[i].key_id_length));
|
||||||
key_array[i].key_data = data.keys[i].key_data;
|
key_array[i].key_data_iv = GetSubstring(
|
||||||
key_array[i].key_data_length = data.keys[i].key_data_length;
|
message,
|
||||||
key_array[i].key_control_iv = data.keys[i].control_iv;
|
wvcdm::BytesToString(data.keys[i].key_iv, sizeof(data.keys[i].key_iv)));
|
||||||
key_array[i].key_control =
|
key_array[i].key_data = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(data.keys[i].key_data,
|
||||||
|
data.keys[i].key_data_length));
|
||||||
|
key_array[i].key_control_iv = GetSubstring(
|
||||||
|
message, wvcdm::BytesToString(data.keys[i].control_iv,
|
||||||
|
sizeof(data.keys[i].control_iv)));
|
||||||
|
const uint8_t* key_control_ptr =
|
||||||
reinterpret_cast<const uint8_t*>(&data.keys[i].control);
|
reinterpret_cast<const uint8_t*>(&data.keys[i].control);
|
||||||
|
key_array[i].key_control = GetSubstring(
|
||||||
|
message,
|
||||||
|
wvcdm::BytesToString(key_control_ptr, sizeof(data.keys[i].control)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
|
void Session::FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
|
||||||
size_t key_count) {
|
size_t key_count) {
|
||||||
|
std::string message =
|
||||||
|
wvcdm::BytesToString(message_ptr(), sizeof(MessageData));
|
||||||
for (size_t i = 0; i < key_count; i++) {
|
for (size_t i = 0; i < key_count; i++) {
|
||||||
if (key_count > 1) {
|
key_array[i].key_id = GetSubstring(
|
||||||
key_array[i].key_id = encrypted_license().keys[i].key_id;
|
message,
|
||||||
key_array[i].key_id_length = encrypted_license().keys[i].key_id_length;
|
wvcdm::BytesToString(encrypted_license().keys[i].key_id,
|
||||||
} else {
|
sizeof(encrypted_license().keys[i].key_id)),
|
||||||
key_array[i].key_id = NULL;
|
key_count <= 1);
|
||||||
key_array[i].key_id_length = 0;
|
key_array[i].key_control_iv = GetSubstring();
|
||||||
}
|
key_array[i].key_control = GetSubstring(
|
||||||
key_array[i].key_control_iv = NULL;
|
message,
|
||||||
key_array[i].key_control =
|
wvcdm::BytesToString(reinterpret_cast<const uint8_t*>(
|
||||||
reinterpret_cast<const uint8_t*>(&encrypted_license().keys[i].control);
|
&encrypted_license().keys[i].control),
|
||||||
|
sizeof(encrypted_license().keys[i].control)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1297,4 +1369,8 @@ void Session::set_message_size(size_t size) {
|
|||||||
ASSERT_LE(message_size_, kMaxMessageSize);
|
ASSERT_LE(message_size_, kMaxMessageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t* Session::encrypted_entitled_message_ptr() {
|
||||||
|
return reinterpret_cast<const uint8_t*>(encrypted_entitled_message_.data());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvoec
|
} // namespace wvoec
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ void PrintTo(const vector<uint8_t>& value, ostream* os);
|
|||||||
|
|
||||||
namespace wvoec {
|
namespace wvoec {
|
||||||
|
|
||||||
|
// Make sure this is larger than kMaxKeysPerSession, in oemcrypto_test.cpp
|
||||||
const size_t kMaxNumKeys = 20;
|
const size_t kMaxNumKeys = 20;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -61,7 +62,6 @@ const int kDefaultKeyIdLength = 16;
|
|||||||
const size_t kMaxTestRSAKeyLength = 2000; // Rough estimate.
|
const size_t kMaxTestRSAKeyLength = 2000; // Rough estimate.
|
||||||
const size_t kMaxPSTLength = 255; // In specification.
|
const size_t kMaxPSTLength = 255; // In specification.
|
||||||
const size_t kMaxMessageSize = 8 * 1024; // In specification.
|
const size_t kMaxMessageSize = 8 * 1024; // In specification.
|
||||||
const size_t kMaxDecryptSize = 100 * 1024; // In specification.
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t key_id[kTestKeyIdMaxLength];
|
uint8_t key_id[kTestKeyIdMaxLength];
|
||||||
@@ -125,6 +125,13 @@ uint32_t htonl_fnc(uint32_t x);
|
|||||||
// Prints error string from BoringSSL
|
// Prints error string from BoringSSL
|
||||||
void dump_boringssl_error();
|
void dump_boringssl_error();
|
||||||
|
|
||||||
|
// Given a message and field, returns an OEMCrypto_Substring with the field's
|
||||||
|
// offset into the message and its length. If |set_zero| is true, both the
|
||||||
|
// offset and length will be zero.
|
||||||
|
OEMCrypto_Substring GetSubstring(const std::string& message = "",
|
||||||
|
const std::string& field = "",
|
||||||
|
bool set_zero = false);
|
||||||
|
|
||||||
class Session {
|
class Session {
|
||||||
public:
|
public:
|
||||||
Session();
|
Session();
|
||||||
@@ -165,12 +172,12 @@ class Session {
|
|||||||
// using OEMCrypto_LoadKeys. This message should have already been created
|
// using OEMCrypto_LoadKeys. This message should have already been created
|
||||||
// by FillSimpleEntitlementMessage, modified if needed, and then encrypted
|
// by FillSimpleEntitlementMessage, modified if needed, and then encrypted
|
||||||
// and signed by the server's mac key in EncryptAndSign.
|
// and signed by the server's mac key in EncryptAndSign.
|
||||||
void LoadEnitlementTestKeys(const std::string& pst = "",
|
void LoadEntitlementTestKeys(const std::string& pst = "",
|
||||||
bool new_mac_keys = true,
|
bool new_mac_keys = true,
|
||||||
OEMCryptoResult expected_sts = OEMCrypto_SUCCESS);
|
OEMCryptoResult expected_sts = OEMCrypto_SUCCESS);
|
||||||
// Fills an OEMCrypto_EntitledContentKeyObject using the information from
|
// Fills an OEMCrypto_EntitledContentKeyObject using the information from
|
||||||
// the license_ and randomly generated content keys. This method should be
|
// the license_ and randomly generated content keys. This method should be
|
||||||
// called after LoadEnitlementTestKeys.
|
// called after LoadEntitlementTestKeys.
|
||||||
void FillEntitledKeyArray();
|
void FillEntitledKeyArray();
|
||||||
// Encrypts and loads the entitled content keys via
|
// Encrypts and loads the entitled content keys via
|
||||||
// OEMCrypto_LoadEntitledContentKeys.
|
// OEMCrypto_LoadEntitledContentKeys.
|
||||||
@@ -196,7 +203,7 @@ class Session {
|
|||||||
const std::string& pst = "");
|
const std::string& pst = "");
|
||||||
// This fills the data structure license_ with entitlement key information.
|
// This fills the data structure license_ with entitlement key information.
|
||||||
// This data can be modified, and then should be encrypted and signed in
|
// This data can be modified, and then should be encrypted and signed in
|
||||||
// EncryptAndSign before being loaded in LoadEnitlementTestKeys.
|
// EncryptAndSign before being loaded in LoadEntitlementTestKeys.
|
||||||
void FillSimpleEntitlementMessage(
|
void FillSimpleEntitlementMessage(
|
||||||
uint32_t duration, uint32_t control,
|
uint32_t duration, uint32_t control,
|
||||||
uint32_t nonce, const std::string& pst = "");
|
uint32_t nonce, const std::string& pst = "");
|
||||||
@@ -205,6 +212,11 @@ class Session {
|
|||||||
// is just signed. The signature is computed in RefreshTestKeys, above.
|
// is just signed. The signature is computed in RefreshTestKeys, above.
|
||||||
void FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
void FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
||||||
uint32_t nonce);
|
uint32_t nonce);
|
||||||
|
// Sets the OEMCrypto_Substring parameters of the LoadKeys method.
|
||||||
|
// Specifically, it sets the |enc_mac_keys_iv|, |enc_mac_keys|, |pst|, and
|
||||||
|
// |srm_restriction_data| in that order. For testing purposes,
|
||||||
|
// |srm_restriction_data| will always be NULL.
|
||||||
|
void SetLoadKeysSubstringParams();
|
||||||
// This copies data from license_ to encrypted_license_, and then encrypts
|
// This copies data from license_ to encrypted_license_, and then encrypts
|
||||||
// each field in the key array appropriately. It then signes the buffer with
|
// each field in the key array appropriately. It then signes the buffer with
|
||||||
// the server mac keys. It then fills out the key_array_ so that pointers in
|
// the server mac keys. It then fills out the key_array_ so that pointers in
|
||||||
@@ -364,6 +376,12 @@ class Session {
|
|||||||
|
|
||||||
// An array of key objects for use in LoadKeys.
|
// An array of key objects for use in LoadKeys.
|
||||||
OEMCrypto_KeyObject* key_array() { return key_array_; }
|
OEMCrypto_KeyObject* key_array() { return key_array_; }
|
||||||
|
|
||||||
|
// An array of key objects for LoadEntitledContentKeys.
|
||||||
|
OEMCrypto_EntitledContentKeyObject* entitled_key_array() {
|
||||||
|
return entitled_key_array_;
|
||||||
|
}
|
||||||
|
|
||||||
// The last signature generated with the server's mac key.
|
// The last signature generated with the server's mac key.
|
||||||
std::vector<uint8_t>& signature() { return signature_; }
|
std::vector<uint8_t>& signature() { return signature_; }
|
||||||
|
|
||||||
@@ -380,6 +398,19 @@ class Session {
|
|||||||
// The size of the encrypted message.
|
// The size of the encrypted message.
|
||||||
size_t message_size() { return message_size_; }
|
size_t message_size() { return message_size_; }
|
||||||
|
|
||||||
|
// The OEMCrypto_Substrings associated with the encrypted license that are
|
||||||
|
// passed to LoadKeys.
|
||||||
|
vector<OEMCrypto_Substring> load_keys_params() { return load_keys_params_; }
|
||||||
|
OEMCrypto_Substring enc_mac_keys_iv_substr() { return load_keys_params_[0]; }
|
||||||
|
OEMCrypto_Substring enc_mac_keys_substr() { return load_keys_params_[1]; }
|
||||||
|
OEMCrypto_Substring pst_substr() { return load_keys_params_[2]; }
|
||||||
|
OEMCrypto_Substring srm_restriction_data_substr() {
|
||||||
|
return load_keys_params_[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointer to buffer holding |encrypted_entitled_message_|
|
||||||
|
const uint8_t* encrypted_entitled_message_ptr();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Generate mac and enc keys give the master key.
|
// Generate mac and enc keys give the master key.
|
||||||
void DeriveKeys(const uint8_t* master_key,
|
void DeriveKeys(const uint8_t* master_key,
|
||||||
@@ -404,6 +435,7 @@ class Session {
|
|||||||
} padded_message_;
|
} padded_message_;
|
||||||
size_t message_size_; // How much of the padded message to use.
|
size_t message_size_; // How much of the padded message to use.
|
||||||
OEMCrypto_KeyObject key_array_[kMaxNumKeys];
|
OEMCrypto_KeyObject key_array_[kMaxNumKeys];
|
||||||
|
vector<OEMCrypto_Substring> load_keys_params_;
|
||||||
std::vector<uint8_t> signature_;
|
std::vector<uint8_t> signature_;
|
||||||
unsigned int num_keys_;
|
unsigned int num_keys_;
|
||||||
vector<uint8_t> encrypted_usage_entry_;
|
vector<uint8_t> encrypted_usage_entry_;
|
||||||
@@ -413,8 +445,11 @@ class Session {
|
|||||||
// Clear Entitlement key data. This is the backing data for
|
// Clear Entitlement key data. This is the backing data for
|
||||||
// |entitled_key_array_|.
|
// |entitled_key_array_|.
|
||||||
EntitledContentKeyData entitled_key_data_[kMaxNumKeys];
|
EntitledContentKeyData entitled_key_data_[kMaxNumKeys];
|
||||||
|
// Message containing data from |key_array| and |entitled_key_data_|.
|
||||||
|
std::string entitled_message_;
|
||||||
// Entitled key object. Pointers are backed by |entitled_key_data_|.
|
// Entitled key object. Pointers are backed by |entitled_key_data_|.
|
||||||
OEMCrypto_EntitledContentKeyObject entitled_key_array_[kMaxNumKeys];
|
OEMCrypto_EntitledContentKeyObject entitled_key_array_[kMaxNumKeys];
|
||||||
|
std::string encrypted_entitled_message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wvoec
|
} // namespace wvoec
|
||||||
|
|||||||
@@ -15,48 +15,10 @@
|
|||||||
|
|
||||||
namespace wvoec {
|
namespace wvoec {
|
||||||
|
|
||||||
// These are test keyboxes. They will not be accepted by production systems.
|
// TODO(fredgc, b/119316243): REMOVE THIS KEYBOX!
|
||||||
// By using known keyboxes for these tests, the results for a given set of
|
// This test keybox is used for testing with OEMCrypto v13.
|
||||||
// inputs to a test are predictable and can be compared to the actual results.
|
// It should be removed before release!
|
||||||
// The first keybox, kTestKeybox, with deviceID "TestKey01" is used for most of
|
static const WidevineKeybox kTestKeyboxForV13 = {
|
||||||
// the tests. It should be loaded by OEMCrypto when OEMCrypto_LoadTestKeybox
|
|
||||||
// is called.
|
|
||||||
static const wvoec::WidevineKeybox kTestKeybox = {
|
|
||||||
// Sample keybox used for test vectors
|
|
||||||
{
|
|
||||||
// deviceID = WidevineTestOnlyKeybox000
|
|
||||||
0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65,
|
|
||||||
0x54, 0x65, 0x73, 0x74, 0x4f, 0x6e, 0x6c, 0x79,
|
|
||||||
0x4b, 0x65, 0x79, 0x62, 0x6f, 0x78, 0x30, 0x30,
|
|
||||||
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
}, {
|
|
||||||
// key
|
|
||||||
0xe4, 0xff, 0x57, 0x4c, 0x32, 0x2e, 0xf5, 0x34,
|
|
||||||
0x26, 0x21, 0x2c, 0xb3, 0xed, 0x37, 0xf3, 0x5e,
|
|
||||||
}, {
|
|
||||||
// data (system ID 7912).
|
|
||||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x1e, 0xe8,
|
|
||||||
0xca, 0x1e, 0x71, 0x7c, 0xfb, 0xe8, 0xa3, 0x94,
|
|
||||||
0x52, 0x0a, 0x6b, 0x71, 0x37, 0xd2, 0x69, 0xfa,
|
|
||||||
0x5a, 0xc6, 0xb5, 0x4c, 0x6b, 0x46, 0x63, 0x9b,
|
|
||||||
0xbe, 0x80, 0x3d, 0xbb, 0x4f, 0xf7, 0x4c, 0x5f,
|
|
||||||
0x6f, 0x55, 0x0e, 0x3d, 0x3d, 0x9a, 0xcf, 0x81,
|
|
||||||
0x12, 0x5d, 0x52, 0xe0, 0x47, 0x8c, 0xda, 0x0b,
|
|
||||||
0xf4, 0x31, 0x41, 0x13, 0xd0, 0xd5, 0x2d, 0xa0,
|
|
||||||
0x5b, 0x20, 0x9a, 0xed, 0x51, 0x5d, 0x13, 0xd6,
|
|
||||||
}, {
|
|
||||||
// magic
|
|
||||||
0x6b, 0x62, 0x6f, 0x78,
|
|
||||||
}, {
|
|
||||||
// Crc
|
|
||||||
0x39, 0xf2, 0x94, 0xa7,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// These are old test keyboxes. The first keybox can be used to update an
|
|
||||||
// older OEMCrypto because it is the same keybox that was previously used in
|
|
||||||
// unit tests.
|
|
||||||
static const wvoec::WidevineKeybox kValidKeybox01 = {
|
|
||||||
// Sample keybox used for test vectors
|
// Sample keybox used for test vectors
|
||||||
{
|
{
|
||||||
// deviceID
|
// deviceID
|
||||||
@@ -88,67 +50,38 @@ static const wvoec::WidevineKeybox kValidKeybox01 = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const wvoec::WidevineKeybox kValidKeybox02 = {
|
// This is a test keybox. They will not be accepted by production systems.
|
||||||
|
// By using known keyboxes for these tests, the results for a given set of
|
||||||
|
// inputs to a test are predictable and can be compared to the actual results.
|
||||||
|
static const WidevineKeybox kTestKeybox = {
|
||||||
// Sample keybox used for test vectors
|
// Sample keybox used for test vectors
|
||||||
{
|
{
|
||||||
// deviceID
|
// deviceID = WidevineTestOnlyKeybox000
|
||||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey02
|
0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65,
|
||||||
0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
0x54, 0x65, 0x73, 0x74, 0x4f, 0x6e, 0x6c, 0x79,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
0x4b, 0x65, 0x79, 0x62, 0x6f, 0x78, 0x30, 0x30,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
}, {
|
}, {
|
||||||
// key
|
// key
|
||||||
0x76, 0x5d, 0xce, 0x01, 0x04, 0x89, 0xb3, 0xd0,
|
0xe4, 0xff, 0x57, 0x4c, 0x32, 0x2e, 0xf5, 0x34,
|
||||||
0xdf, 0xce, 0x54, 0x8a, 0x49, 0xda, 0xdc, 0xb6,
|
0x26, 0x21, 0x2c, 0xb3, 0xed, 0x37, 0xf3, 0x5e,
|
||||||
}, {
|
}, {
|
||||||
// data
|
// data (system ID 7912 = 1EE8).
|
||||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x1e, 0xe8,
|
||||||
0x92, 0x27, 0x0b, 0x1f, 0x1a, 0xd5, 0xc6, 0x93,
|
0xca, 0x1e, 0x71, 0x7c, 0xfb, 0xe8, 0xa3, 0x94,
|
||||||
0x19, 0x3f, 0xaa, 0x74, 0x1f, 0xdd, 0x5f, 0xb4,
|
0x52, 0x0a, 0x6b, 0x71, 0x37, 0xd2, 0x69, 0xfa,
|
||||||
0xe9, 0x40, 0x2f, 0x34, 0xa4, 0x92, 0xf4, 0xae,
|
0x5a, 0xc6, 0xb5, 0x4c, 0x6b, 0x46, 0x63, 0x9b,
|
||||||
0x9a, 0x52, 0x39, 0xbc, 0xb7, 0x24, 0x38, 0x13,
|
0xbe, 0x80, 0x3d, 0xbb, 0x4f, 0xf7, 0x4c, 0x5f,
|
||||||
0xab, 0xf4, 0x92, 0x96, 0xc4, 0x81, 0x60, 0x33,
|
0x6f, 0x55, 0x0e, 0x3d, 0x3d, 0x9a, 0xcf, 0x81,
|
||||||
0xd8, 0xb8, 0x09, 0xc7, 0x55, 0x0e, 0x12, 0xfa,
|
0x12, 0x5d, 0x52, 0xe0, 0x47, 0x8c, 0xda, 0x0b,
|
||||||
0xa8, 0x98, 0x62, 0x8a, 0xec, 0xea, 0x74, 0x8a,
|
0xf4, 0x31, 0x41, 0x13, 0xd0, 0xd5, 0x2d, 0xa0,
|
||||||
0x4b, 0xfa, 0x5a, 0x9e, 0xb6, 0x49, 0x0d, 0x80,
|
0x5b, 0x20, 0x9a, 0xed, 0x51, 0x5d, 0x13, 0xd6,
|
||||||
}, {
|
}, {
|
||||||
// magic
|
// magic
|
||||||
0x6b, 0x62, 0x6f, 0x78,
|
0x6b, 0x62, 0x6f, 0x78,
|
||||||
}, {
|
}, {
|
||||||
// Crc
|
// Crc
|
||||||
0x2a, 0x3b, 0x3e, 0xe4,
|
0x39, 0xf2, 0x94, 0xa7,
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const wvoec::WidevineKeybox kValidKeybox03 = {
|
|
||||||
// Sample keybox used for test vectors
|
|
||||||
{
|
|
||||||
// deviceID
|
|
||||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey03
|
|
||||||
0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
|
||||||
}, {
|
|
||||||
// key
|
|
||||||
0x25, 0xe5, 0x2a, 0x02, 0x29, 0x68, 0x04, 0xa2,
|
|
||||||
0x92, 0xfd, 0x7c, 0x67, 0x0b, 0x67, 0x1f, 0x31,
|
|
||||||
}, {
|
|
||||||
// data
|
|
||||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
|
||||||
0xf4, 0x0a, 0x0e, 0xa2, 0x0a, 0x71, 0xd5, 0x92,
|
|
||||||
0xfa, 0xa3, 0x25, 0xc6, 0x4b, 0x76, 0xf1, 0x64,
|
|
||||||
0xf4, 0x60, 0xa0, 0x30, 0x72, 0x23, 0xbe, 0x03,
|
|
||||||
0xcd, 0xde, 0x7a, 0x06, 0xd4, 0x01, 0xeb, 0xdc,
|
|
||||||
0xe0, 0x50, 0xc0, 0x53, 0x0a, 0x50, 0xb0, 0x37,
|
|
||||||
0xe5, 0x05, 0x25, 0x0e, 0xa4, 0xc8, 0x5a, 0xff,
|
|
||||||
0x46, 0x6e, 0xa5, 0x31, 0xf3, 0xdd, 0x94, 0xb7,
|
|
||||||
0xe0, 0xd3, 0xf9, 0x04, 0xb2, 0x54, 0xb1, 0x64,
|
|
||||||
}, {
|
|
||||||
// magic
|
|
||||||
0x6b, 0x62, 0x6f, 0x78,
|
|
||||||
}, {
|
|
||||||
// Crc
|
|
||||||
0xa1, 0x99, 0x5f, 0x46,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -783,6 +716,8 @@ static const uint8_t kTestKeyRSAEuler_2048[] = {
|
|||||||
0x33, 0xe0, 0xdb, 0x03,
|
0x33, 0xe0, 0xdb, 0x03,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint8_t kTestSandbox[] = { 0x01, 0x02, 0x03 };
|
||||||
|
|
||||||
} // namespace wvoec
|
} // namespace wvoec
|
||||||
|
|
||||||
#endif // CDM_OEC_TEST_DATA_H_
|
#endif // CDM_OEC_TEST_DATA_H_
|
||||||
|
|||||||
@@ -103,11 +103,8 @@ void SessionUtil::EnsureTestKeys() {
|
|||||||
switch (global_features.derive_key_method) {
|
switch (global_features.derive_key_method) {
|
||||||
case DeviceFeatures::LOAD_TEST_KEYBOX:
|
case DeviceFeatures::LOAD_TEST_KEYBOX:
|
||||||
keybox_ = kTestKeybox;
|
keybox_ = kTestKeybox;
|
||||||
/* Note: If you are upgrading from an older version, it may be easier to
|
// TODO(fredgc, b/119316243): REMOVE FOLLOWING LINE:
|
||||||
* force the following condition. This uses the same test keybox as we
|
if (global_features.api_version < 14) keybox_ = kTestKeyboxForV13;
|
||||||
* used in older versions of this test.
|
|
||||||
*/
|
|
||||||
if (global_features.api_version < 14) keybox_ = kValidKeybox01;
|
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_LoadTestKeybox(
|
OEMCrypto_LoadTestKeybox(
|
||||||
reinterpret_cast<const uint8_t*>(&keybox_),
|
reinterpret_cast<const uint8_t*>(&keybox_),
|
||||||
@@ -116,10 +113,6 @@ void SessionUtil::EnsureTestKeys() {
|
|||||||
case DeviceFeatures::LOAD_TEST_RSA_KEY:
|
case DeviceFeatures::LOAD_TEST_RSA_KEY:
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
|
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
|
||||||
break;
|
break;
|
||||||
case DeviceFeatures::EXISTING_TEST_KEYBOX:
|
|
||||||
// already has old test keybox.
|
|
||||||
keybox_ = kValidKeybox01;
|
|
||||||
break;
|
|
||||||
case DeviceFeatures::FORCE_TEST_KEYBOX:
|
case DeviceFeatures::FORCE_TEST_KEYBOX:
|
||||||
keybox_ = kTestKeybox;
|
keybox_ = kTestKeybox;
|
||||||
InstallKeybox(keybox_, true);
|
InstallKeybox(keybox_, true);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,10 @@ namespace wvoec {
|
|||||||
// These tests are required for LollyPop Android devices.
|
// These tests are required for LollyPop Android devices.
|
||||||
class OEMCryptoAndroidLMPTest : public ::testing::Test {
|
class OEMCryptoAndroidLMPTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
virtual void SetUp() { ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize()); }
|
virtual void SetUp() {
|
||||||
|
OEMCrypto_SetSandbox(kTestSandbox, sizeof(kTestSandbox));
|
||||||
|
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize());
|
||||||
|
}
|
||||||
|
|
||||||
virtual void TearDown() { OEMCrypto_Terminate(); }
|
virtual void TearDown() { OEMCrypto_Terminate(); }
|
||||||
};
|
};
|
||||||
@@ -153,7 +156,7 @@ class OEMCryptoAndroidQTest : public OEMCryptoAndroidOCTest {};
|
|||||||
|
|
||||||
TEST_F(OEMCryptoAndroidQTest, MinVersionNumber14) {
|
TEST_F(OEMCryptoAndroidQTest, MinVersionNumber14) {
|
||||||
uint32_t version = OEMCrypto_APIVersion();
|
uint32_t version = OEMCrypto_APIVersion();
|
||||||
ASSERT_GE(version, 14u);
|
ASSERT_GE(version, 15u);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace wvoec
|
} // namespace wvoec
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# Override the variables below for the location of various gyp files.
|
# Override the variables below for the location of various gyp files.
|
||||||
# Alternatively, set the environment variable CDM_DIR to point to a recent
|
# Alternatively, set the environment variable CDM_DIR to point to a recent
|
||||||
# version of the source CDM.
|
# version of the source CDM.
|
||||||
'boringssl_dependency%': '<!(echo $CDM_DIR)/third_party/boringssl/boringssl.gyp:legacy_ssl',
|
'boringssl_dependency%': '<!(echo $CDM_DIR)/third_party/boringssl/boringssl.gyp:ssl',
|
||||||
'gtest_dependency%': '<!(echo $CDM_DIR)/third_party/gmock.gyp:gtest',
|
'gtest_dependency%': '<!(echo $CDM_DIR)/third_party/gmock.gyp:gtest',
|
||||||
'gmock_dependency%': '<!(echo $CDM_DIR)/third_party/gmock.gyp:gmock',
|
'gmock_dependency%': '<!(echo $CDM_DIR)/third_party/gmock.gyp:gmock',
|
||||||
'oemcrypto_dir%': '..',
|
'oemcrypto_dir%': '..',
|
||||||
|
|||||||
@@ -10,10 +10,12 @@
|
|||||||
'oec_session_util.cpp',
|
'oec_session_util.cpp',
|
||||||
'oemcrypto_session_tests_helper.cpp',
|
'oemcrypto_session_tests_helper.cpp',
|
||||||
'oemcrypto_test.cpp',
|
'oemcrypto_test.cpp',
|
||||||
|
'<(oemcrypto_dir)/ref/src/wvcrc.cpp',
|
||||||
],
|
],
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'<(util_dir)/include',
|
'<(util_dir)/include',
|
||||||
'<(oemcrypto_dir)/include',
|
'<(oemcrypto_dir)/include',
|
||||||
|
'<(oemcrypto_dir)/ref/src',
|
||||||
'<(oemcrypto_dir)/test',
|
'<(oemcrypto_dir)/test',
|
||||||
],
|
],
|
||||||
'defines': [
|
'defines': [
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ std::string HexEncode(const uint8_t* bytes, unsigned size);
|
|||||||
std::string IntToString(int value);
|
std::string IntToString(int value);
|
||||||
int64_t htonll64(int64_t x);
|
int64_t htonll64(int64_t x);
|
||||||
inline int64_t ntohll64(int64_t x) { return htonll64(x); }
|
inline int64_t ntohll64(int64_t x) { return htonll64(x); }
|
||||||
|
std::string BytesToString(const uint8_t* bytes, unsigned size);
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
|
|||||||
@@ -292,4 +292,10 @@ int64_t htonll64(int64_t x) { // Convert to big endian (network-byte-order)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string BytesToString(const uint8_t* bytes, unsigned size) {
|
||||||
|
if (!bytes || !size) return "";
|
||||||
|
const char* char_bytes = reinterpret_cast<const char*>(bytes);
|
||||||
|
return std::string(char_bytes, char_bytes + size);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
Reference in New Issue
Block a user