Source release v3.1.0
This commit is contained in:
144
oemcrypto/test/oec_device_features.cpp
Normal file
144
oemcrypto/test/oec_device_features.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "oec_device_features.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "oec_test_data.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
DeviceFeatures global_features;
|
||||
|
||||
void DeviceFeatures::Initialize(bool is_cast_receiver,
|
||||
bool force_load_test_keybox) {
|
||||
cast_receiver = is_cast_receiver;
|
||||
uses_keybox = false;
|
||||
uses_certificate = false;
|
||||
loads_certificate = false;
|
||||
generic_crypto = false;
|
||||
usage_table = false;
|
||||
api_version = 0;
|
||||
derive_key_method = NO_METHOD;
|
||||
if (OEMCrypto_SUCCESS != OEMCrypto_Initialize()) {
|
||||
printf("OEMCrypto_Initialze failed. All tests will fail.\n");
|
||||
return;
|
||||
}
|
||||
uint32_t nonce = 0;
|
||||
uint8_t buffer[1];
|
||||
size_t size = 0;
|
||||
uses_keybox =
|
||||
(OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_GetKeyData(buffer, &size));
|
||||
printf("uses_keybox = %s.\n", uses_keybox ? "true" : "false");
|
||||
loads_certificate = uses_keybox && (OEMCrypto_ERROR_NOT_IMPLEMENTED !=
|
||||
OEMCrypto_RewrapDeviceRSAKey(
|
||||
0, buffer, 0, buffer, 0, &nonce,
|
||||
buffer, 0, buffer, buffer, &size));
|
||||
printf("loads_certificate = %s.\n", loads_certificate ? "true" : "false");
|
||||
uses_certificate = (OEMCrypto_ERROR_NOT_IMPLEMENTED !=
|
||||
OEMCrypto_GenerateRSASignature(0, buffer, 0, buffer,
|
||||
&size, kSign_RSASSA_PSS));
|
||||
printf("uses_certificate = %s.\n", uses_certificate ? "true" : "false");
|
||||
generic_crypto =
|
||||
(OEMCrypto_ERROR_NOT_IMPLEMENTED !=
|
||||
OEMCrypto_Generic_Encrypt(0, buffer, 0, buffer,
|
||||
OEMCrypto_AES_CBC_128_NO_PADDING, buffer));
|
||||
printf("generic_crypto = %s.\n", generic_crypto ? "true" : "false");
|
||||
api_version = OEMCrypto_APIVersion();
|
||||
printf("api_version = %d.\n", api_version);
|
||||
usage_table = OEMCrypto_SupportsUsageTable();
|
||||
printf("usage_table = %s.\n", usage_table ? "true" : "false");
|
||||
if (force_load_test_keybox) {
|
||||
derive_key_method = FORCE_TEST_KEYBOX;
|
||||
} else {
|
||||
PickDerivedKey();
|
||||
}
|
||||
printf("cast_receiver = %s.\n", cast_receiver ? "true" : "false");
|
||||
switch (derive_key_method) {
|
||||
case NO_METHOD:
|
||||
printf("NO_METHOD: Cannot derive known session keys.\n");
|
||||
// Note: cast_receiver left unchanged because set by user on command line.
|
||||
uses_keybox = false;
|
||||
uses_certificate = false;
|
||||
loads_certificate = false;
|
||||
generic_crypto = false;
|
||||
usage_table = false;
|
||||
break;
|
||||
case LOAD_TEST_KEYBOX:
|
||||
printf("LOAD_TEST_KEYBOX: Call LoadTestKeybox before deriving keys.\n");
|
||||
break;
|
||||
case LOAD_TEST_RSA_KEY:
|
||||
printf("LOAD_TEST_RSA_KEY: Call LoadTestRSAKey before deriving keys.\n");
|
||||
break;
|
||||
case EXISTING_TEST_KEYBOX:
|
||||
printf("EXISTING_TEST_KEYBOX: Keybox is already the test keybox.\n");
|
||||
break;
|
||||
case FORCE_TEST_KEYBOX:
|
||||
printf("FORCE_TEST_KEYBOX: User requested calling InstallKeybox.\n");
|
||||
break;
|
||||
}
|
||||
OEMCrypto_Terminate();
|
||||
}
|
||||
|
||||
std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
|
||||
std::string filter = initial_filter;
|
||||
if (!uses_keybox) FilterOut(&filter, "*KeyboxTest*");
|
||||
if (derive_key_method
|
||||
!= FORCE_TEST_KEYBOX) FilterOut(&filter, "*ForceKeybox*");
|
||||
if (!uses_certificate) FilterOut(&filter, "OEMCrypto*Cert*");
|
||||
if (!loads_certificate) FilterOut(&filter, "OEMCryptoLoadsCert*");
|
||||
if (!generic_crypto) FilterOut(&filter, "*GenericCrypto*");
|
||||
if (!cast_receiver) FilterOut(&filter, "*CastReceiver*");
|
||||
if (!usage_table) FilterOut(&filter, "*UsageTable*");
|
||||
if (derive_key_method == NO_METHOD) FilterOut(&filter, "*SessionTest*");
|
||||
if (api_version < 10) FilterOut(&filter, "*API10*");
|
||||
if (api_version < 11) FilterOut(&filter, "*API11*");
|
||||
// Performance tests take a long time. Filter them out if they are not
|
||||
// specifically requested.
|
||||
if (filter.find("Performance") == std::string::npos) {
|
||||
FilterOut(&filter, "*Performance*");
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
void DeviceFeatures::PickDerivedKey() {
|
||||
if (uses_keybox) {
|
||||
// If device uses a keybox, try to load the test keybox.
|
||||
if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestKeybox()) {
|
||||
derive_key_method = LOAD_TEST_KEYBOX;
|
||||
} else if (IsTestKeyboxInstalled()) {
|
||||
derive_key_method = EXISTING_TEST_KEYBOX;
|
||||
}
|
||||
} else if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestRSAKey()) {
|
||||
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(kTestKeybox.data_)) return false;
|
||||
if (memcmp(key_data, kTestKeybox.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*>(kTestKeybox.device_id_),
|
||||
sizeof(kTestKeybox.device_id_));
|
||||
}
|
||||
|
||||
void DeviceFeatures::FilterOut(std::string* current_filter,
|
||||
const std::string& new_filter) {
|
||||
if (current_filter->find('-') == std::string::npos) {
|
||||
*current_filter += "-" + new_filter;
|
||||
} else {
|
||||
*current_filter += ":" + new_filter;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef CDM_OEMCRYPTO_TEST_H_
|
||||
#define CDM_OEMCRYPTO_TEST_H_
|
||||
#ifndef CDM_OEC_DEVICE_FEATURES_H_
|
||||
#define CDM_OEC_DEVICE_FEATURES_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "wv_keybox.h"
|
||||
@@ -38,4 +40,4 @@ extern DeviceFeatures global_features;
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEMCRYPTO_TEST_H_
|
||||
#endif // CDM_OEC_DEVICE_FEATURES_H_
|
||||
802
oemcrypto/test/oec_session_util.cpp
Normal file
802
oemcrypto/test/oec_session_util.cpp
Normal file
@@ -0,0 +1,802 @@
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// OEMCrypto unit tests
|
||||
//
|
||||
|
||||
#include "oec_session_util.h"
|
||||
|
||||
#include <arpa/inet.h> // needed for ntoh()
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "log.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "oec_test_data.h"
|
||||
#include "oemcrypto_key_mock.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "string_conversions.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_keybox.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// GTest requires PrintTo to be in the same namespace as the thing it prints,
|
||||
// which is std::vector in this case.
|
||||
namespace std {
|
||||
|
||||
void PrintTo(const vector<uint8_t>& value, ostream* os) {
|
||||
*os << wvcdm::b2a_hex(value);
|
||||
}
|
||||
|
||||
void PrintTo(const PatternTestVariant& param, ostream* os) {
|
||||
*os << ((param.mode == OEMCrypto_CipherMode_CTR) ? "CTR mode" : "CBC mode")
|
||||
<< ", encrypt=" << param.pattern.encrypt
|
||||
<< ", skip=" << param.pattern.skip;
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// Increment counter for AES-CTR. The CENC spec specifies we increment only
|
||||
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This
|
||||
// is different from the OpenSSL implementation, so we implement the CTR loop
|
||||
// ourselves.
|
||||
void ctr128_inc64(int64_t increaseBy, uint8_t* iv) {
|
||||
ASSERT_NE(static_cast<void*>(NULL), iv);
|
||||
uint64_t* counterBuffer = reinterpret_cast<uint64_t*>(&iv[8]);
|
||||
(*counterBuffer) =
|
||||
wvcdm::htonll64(wvcdm::ntohll64(*counterBuffer) + increaseBy);
|
||||
}
|
||||
|
||||
// Some compilers don't like the macro htonl within an ASSERT_EQ.
|
||||
uint32_t htonl_fnc(uint32_t x) { return htonl(x); }
|
||||
|
||||
void dump_openssl_error() {
|
||||
while (unsigned long err = ERR_get_error()) {
|
||||
char buffer[120];
|
||||
ERR_error_string_n(err, buffer, sizeof(buffer));
|
||||
cout << "openssl error -- " << buffer << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
Session::Session()
|
||||
: open_(false),
|
||||
forced_session_id_(false),
|
||||
session_id_(0),
|
||||
mac_key_server_(wvcdm::MAC_KEY_SIZE),
|
||||
mac_key_client_(wvcdm::MAC_KEY_SIZE),
|
||||
enc_key_(wvcdm::KEY_SIZE),
|
||||
public_rsa_(0) {}
|
||||
|
||||
Session::~Session() {
|
||||
if (!forced_session_id_ && open_) close();
|
||||
if (public_rsa_) RSA_free(public_rsa_);
|
||||
}
|
||||
|
||||
void Session::open() {
|
||||
EXPECT_FALSE(forced_session_id_);
|
||||
EXPECT_FALSE(open_);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session_id_));
|
||||
open_ = true;
|
||||
}
|
||||
|
||||
void Session::SetSessionId(uint32_t session_id) {
|
||||
EXPECT_FALSE(open_);
|
||||
session_id_ = session_id;
|
||||
forced_session_id_ = true;
|
||||
}
|
||||
|
||||
void Session::close() {
|
||||
EXPECT_TRUE(open_ || forced_session_id_);
|
||||
if (open_) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(session_id_));
|
||||
}
|
||||
forced_session_id_ = false;
|
||||
open_ = false;
|
||||
}
|
||||
|
||||
void Session::GenerateNonce(uint32_t* nonce, int* error_counter) {
|
||||
if (OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(session_id(), nonce)) {
|
||||
return;
|
||||
}
|
||||
if (error_counter) {
|
||||
(*error_counter)++;
|
||||
} else {
|
||||
sleep(1); // wait a second, then try again.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GenerateNonce(session_id(), nonce));
|
||||
}
|
||||
}
|
||||
|
||||
void Session::FillDefaultContext(vector<uint8_t>* mac_context,
|
||||
vector<uint8_t>* enc_context) {
|
||||
/* Context strings
|
||||
* These context strings are normally created by the CDM layer
|
||||
* from a license request message.
|
||||
* They are used to test MAC and ENC key generation.
|
||||
*/
|
||||
*mac_context = wvcdm::a2b_hex(
|
||||
"41555448454e5449434154494f4e000a4c08001248000000020000101907d9ff"
|
||||
"de13aa95c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e5873"
|
||||
"4930acebe899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a"
|
||||
"230a14080112100915007caa9b5931b76a3a85f046523e10011a093938373635"
|
||||
"34333231180120002a0c31383836373837343035000000000200");
|
||||
*enc_context = wvcdm::a2b_hex(
|
||||
"454e4352595054494f4e000a4c08001248000000020000101907d9ffde13aa95"
|
||||
"c122678053362136bdf8408f8276e4c2d87ec52b61aa1b9f646e58734930aceb"
|
||||
"e899b3e464189a14a87202fb02574e70640bd22ef44b2d7e3912250a230a1408"
|
||||
"0112100915007caa9b5931b76a3a85f046523e10011a09393837363534333231"
|
||||
"180120002a0c31383836373837343035000000000080");
|
||||
}
|
||||
|
||||
void Session::GenerateDerivedKeysFromKeybox() {
|
||||
GenerateNonce(&nonce_);
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
FillDefaultContext(&mac_context, &enc_context);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GenerateDerivedKeys(session_id(), &mac_context[0],
|
||||
mac_context.size(), &enc_context[0],
|
||||
enc_context.size()));
|
||||
|
||||
// Expected MAC and ENC keys generated from context strings
|
||||
// with test keybox "installed".
|
||||
mac_key_server_ = wvcdm::a2b_hex(
|
||||
"3CFD60254786AF350B353B4FBB700AB382558400356866BA16C256BCD8C502BF");
|
||||
mac_key_client_ = wvcdm::a2b_hex(
|
||||
"A9DE7B3E4E199ED8D1FBC29CD6B4C772CC4538C8B0D3E208B3E76F2EC0FD6F47");
|
||||
enc_key_ = wvcdm::a2b_hex("D0BFC35DA9E33436E81C4229E78CB9F4");
|
||||
}
|
||||
|
||||
void Session::GenerateDerivedKeysFromSessionKey() {
|
||||
// Uses test certificate.
|
||||
GenerateNonce(&nonce_);
|
||||
vector<uint8_t> enc_session_key;
|
||||
PreparePublicKey();
|
||||
ASSERT_TRUE(GenerateRSASessionKey(&enc_session_key));
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
FillDefaultContext(&mac_context, &enc_context);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_DeriveKeysFromSessionKey(
|
||||
session_id(), &enc_session_key[0], enc_session_key.size(),
|
||||
&mac_context[0], mac_context.size(), &enc_context[0],
|
||||
enc_context.size()));
|
||||
|
||||
// Expected MAC and ENC keys generated from context strings
|
||||
// with RSA certificate "installed".
|
||||
mac_key_server_ = wvcdm::a2b_hex(
|
||||
"1E451E59CB663DA1646194DD28880788ED8ED2EFF913CBD6A0D535D1D5A90381");
|
||||
mac_key_client_ = wvcdm::a2b_hex(
|
||||
"F9AAE74690909F2207B53B13307FCA096CA8C49CC6DFE3659873CB952889A74B");
|
||||
enc_key_ = wvcdm::a2b_hex("CB477D09014D72C9B8DCE76C33EA43B3");
|
||||
}
|
||||
|
||||
void Session::GenerateTestSessionKeys() {
|
||||
if (global_features.derive_key_method == DeviceFeatures::LOAD_TEST_RSA_KEY) {
|
||||
GenerateDerivedKeysFromSessionKey();
|
||||
} else {
|
||||
GenerateDerivedKeysFromKeybox();
|
||||
}
|
||||
}
|
||||
|
||||
void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
||||
uint8_t* pst_ptr = NULL;
|
||||
if (pst.length() > 0) {
|
||||
pst_ptr = encrypted_license_.pst;
|
||||
}
|
||||
if (new_mac_keys) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadKeys(
|
||||
session_id(), message_ptr(), sizeof(MessageData),
|
||||
&signature_[0], signature_.size(),
|
||||
encrypted_license_.mac_key_iv, encrypted_license_.mac_keys,
|
||||
kNumKeys, key_array_, pst_ptr, pst.length()));
|
||||
// Update new generated keys.
|
||||
memcpy(&mac_key_server_[0], license_.mac_keys, wvcdm::MAC_KEY_SIZE);
|
||||
memcpy(&mac_key_client_[0], license_.mac_keys + wvcdm::MAC_KEY_SIZE,
|
||||
wvcdm::MAC_KEY_SIZE);
|
||||
} else {
|
||||
ASSERT_EQ(
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), sizeof(MessageData),
|
||||
&signature_[0], signature_.size(), NULL, NULL,
|
||||
kNumKeys, key_array_, pst_ptr, pst.length()));
|
||||
}
|
||||
VerifyTestKeys();
|
||||
}
|
||||
|
||||
void Session::VerifyTestKeys() {
|
||||
for (unsigned int i = 0; i < kNumKeys; i++) {
|
||||
KeyControlBlock block;
|
||||
size_t size = sizeof(block);
|
||||
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
|
||||
session_id(), license_.keys[i].key_id, license_.keys[i].key_id_length,
|
||||
reinterpret_cast<uint8_t*>(&block), &size);
|
||||
if (sts != OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_EQ(sizeof(block), size);
|
||||
// control duration and bits stored in network byte order. For printing
|
||||
// we change to host byte order.
|
||||
ASSERT_EQ((htonl_fnc(license_.keys[i].control.duration)),
|
||||
(htonl_fnc(block.duration))) << "For key " << i;
|
||||
ASSERT_EQ(htonl_fnc(license_.keys[i].control.control_bits),
|
||||
htonl_fnc(block.control_bits)) << "For key " << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Session::RefreshTestKeys(const size_t key_count,
|
||||
uint32_t control_bits, uint32_t nonce,
|
||||
OEMCryptoResult expected_result) {
|
||||
// Note: we store the message in encrypted_license_, but the refresh key
|
||||
// message is not actually encrypted. It is, however, signed.
|
||||
FillRefreshMessage(key_count, control_bits, nonce);
|
||||
ServerSignMessage(encrypted_license_, &signature_);
|
||||
OEMCrypto_KeyRefreshObject key_array[key_count];
|
||||
FillRefreshArray(key_array, key_count);
|
||||
OEMCryptoResult sts = OEMCrypto_RefreshKeys(
|
||||
session_id(), message_ptr(), sizeof(MessageData), &signature_[0],
|
||||
signature_.size(), key_count, key_array);
|
||||
ASSERT_EQ(expected_result, sts);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCTR());
|
||||
sleep(kShortSleep); // Should still be valid key.
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCTR(false));
|
||||
sleep(kShortSleep + kLongSleep); // Should be after first expiration.
|
||||
if (expected_result == OEMCrypto_SUCCESS) {
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCTR(false, OEMCrypto_SUCCESS));
|
||||
} else {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE));
|
||||
}
|
||||
}
|
||||
|
||||
void Session::SetKeyId(int index, const string& key_id) {
|
||||
MessageKeyData& key = license_.keys[index];
|
||||
key.key_id_length = key_id.length();
|
||||
ASSERT_LE(key.key_id_length, kTestKeyIdMaxLength);
|
||||
memcpy(key.key_id, key_id.data(), key.key_id_length);
|
||||
}
|
||||
|
||||
void Session::FillSimpleMessage(
|
||||
uint32_t duration, uint32_t control, uint32_t nonce,
|
||||
const std::string& pst) {
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetRandom(license_.mac_key_iv,
|
||||
sizeof(license_.mac_key_iv)));
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetRandom(license_.mac_keys, sizeof(license_.mac_keys)));
|
||||
for (unsigned int i = 0; i < kNumKeys; i++) {
|
||||
memset(license_.keys[i].key_id, 0, kTestKeyIdMaxLength);
|
||||
license_.keys[i].key_id_length = kDefaultKeyIdLength;
|
||||
memset(license_.keys[i].key_id, i, license_.keys[i].key_id_length);
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetRandom(license_.keys[i].key_data,
|
||||
sizeof(license_.keys[i].key_data)));
|
||||
license_.keys[i].key_data_length = wvcdm::KEY_SIZE;
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetRandom(license_.keys[i].key_iv,
|
||||
sizeof(license_.keys[i].key_iv)));
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetRandom(license_.keys[i].control_iv,
|
||||
sizeof(license_.keys[i].control_iv)));
|
||||
if (control & wvoec_mock::kControlSecurityPatchLevelMask) {
|
||||
memcpy(license_.keys[i].control.verification, "kc11", 4);
|
||||
} else if (control & wvoec_mock::kControlRequireAntiRollbackHardware) {
|
||||
memcpy(license_.keys[i].control.verification, "kc10", 4);
|
||||
} else if (control & (wvoec_mock::kControlHDCPVersionMask |
|
||||
wvoec_mock::kControlReplayMask)) {
|
||||
memcpy(license_.keys[i].control.verification, "kc09", 4);
|
||||
} else {
|
||||
memcpy(license_.keys[i].control.verification, "kctl", 4);
|
||||
}
|
||||
license_.keys[i].control.duration = htonl(duration);
|
||||
license_.keys[i].control.nonce = htonl(nonce);
|
||||
license_.keys[i].control.control_bits = htonl(control);
|
||||
license_.keys[i].cipher_mode = OEMCrypto_CipherMode_CTR;
|
||||
}
|
||||
memcpy(license_.pst, pst.c_str(), min(sizeof(license_.pst), pst.length()));
|
||||
}
|
||||
|
||||
void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
||||
uint32_t nonce) {
|
||||
for (unsigned int i = 0; i < key_count; i++) {
|
||||
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,
|
||||
encrypted_license_.keys[i].key_id_length);
|
||||
memcpy(encrypted_license_.keys[i].control.verification, "kctl", 4);
|
||||
encrypted_license_.keys[i].control.duration = htonl(kLongDuration);
|
||||
encrypted_license_.keys[i].control.nonce = htonl(nonce);
|
||||
encrypted_license_.keys[i].control.control_bits = htonl(control_bits);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::EncryptAndSign() {
|
||||
encrypted_license_ = license_;
|
||||
|
||||
uint8_t iv_buffer[16];
|
||||
memcpy(iv_buffer, &license_.mac_key_iv[0], wvcdm::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(&license_.mac_keys[0], &encrypted_license_.mac_keys[0],
|
||||
2 * wvcdm::MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||
|
||||
for (unsigned int i = 0; i < kNumKeys; i++) {
|
||||
memcpy(iv_buffer, &license_.keys[i].control_iv[0], wvcdm::KEY_IV_SIZE);
|
||||
AES_set_encrypt_key(&license_.keys[i].key_data[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(
|
||||
reinterpret_cast<const uint8_t*>(&license_.keys[i].control),
|
||||
reinterpret_cast<uint8_t*>(&encrypted_license_.keys[i].control),
|
||||
wvcdm::KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||
|
||||
memcpy(iv_buffer, &license_.keys[i].key_iv[0], wvcdm::KEY_IV_SIZE);
|
||||
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(&license_.keys[i].key_data[0],
|
||||
&encrypted_license_.keys[i].key_data[0],
|
||||
license_.keys[i].key_data_length, &aes_key, iv_buffer,
|
||||
AES_ENCRYPT);
|
||||
}
|
||||
memcpy(encrypted_license_.pst, license_.pst, sizeof(license_.pst));
|
||||
ServerSignMessage(encrypted_license_, &signature_);
|
||||
FillKeyArray(encrypted_license_, key_array_);
|
||||
}
|
||||
|
||||
void Session::EncryptMessage(RSAPrivateKeyMessage* data,
|
||||
RSAPrivateKeyMessage* encrypted) {
|
||||
*encrypted = *data;
|
||||
size_t padding = wvcdm::KEY_SIZE - (data->rsa_key_length % wvcdm::KEY_SIZE);
|
||||
memset(data->rsa_key + data->rsa_key_length, static_cast<uint8_t>(padding),
|
||||
padding);
|
||||
encrypted->rsa_key_length = data->rsa_key_length + padding;
|
||||
uint8_t iv_buffer[16];
|
||||
memcpy(iv_buffer, &data->rsa_key_iv[0], wvcdm::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(&data->rsa_key[0], &encrypted->rsa_key[0],
|
||||
encrypted->rsa_key_length, &aes_key, iv_buffer,
|
||||
AES_ENCRYPT);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Session::ServerSignMessage(const T& data,
|
||||
std::vector<uint8_t>* signature) {
|
||||
signature->assign(SHA256_DIGEST_LENGTH, 0);
|
||||
unsigned int md_len = SHA256_DIGEST_LENGTH;
|
||||
HMAC(EVP_sha256(), &mac_key_server_[0], mac_key_server_.size(),
|
||||
reinterpret_cast<const uint8_t*>(&data), sizeof(data),
|
||||
&(signature->front()), &md_len);
|
||||
}
|
||||
|
||||
void Session::ClientSignMessage(const vector<uint8_t>& data,
|
||||
std::vector<uint8_t>* signature) {
|
||||
signature->assign(SHA256_DIGEST_LENGTH, 0);
|
||||
unsigned int md_len = SHA256_DIGEST_LENGTH;
|
||||
HMAC(EVP_sha256(), &mac_key_client_[0], mac_key_client_.size(),
|
||||
&(data.front()), data.size(), &(signature->front()), &md_len);
|
||||
}
|
||||
|
||||
void Session::FillKeyArray(const MessageData& data,
|
||||
OEMCrypto_KeyObject* key_array) {
|
||||
for (unsigned int i = 0; i < kNumKeys; i++) {
|
||||
key_array[i].key_id = data.keys[i].key_id;
|
||||
key_array[i].key_id_length = data.keys[i].key_id_length;
|
||||
key_array[i].key_data_iv = data.keys[i].key_iv;
|
||||
key_array[i].key_data = data.keys[i].key_data;
|
||||
key_array[i].key_data_length = data.keys[i].key_data_length;
|
||||
key_array[i].key_control_iv = data.keys[i].control_iv;
|
||||
key_array[i].key_control =
|
||||
reinterpret_cast<const uint8_t*>(&data.keys[i].control);
|
||||
key_array[i].cipher_mode = data.keys[i].cipher_mode;
|
||||
}
|
||||
}
|
||||
|
||||
void Session::FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
|
||||
size_t key_count) {
|
||||
for (size_t i = 0; i < key_count; i++) {
|
||||
if (key_count > 1) {
|
||||
key_array[i].key_id = encrypted_license_.keys[i].key_id;
|
||||
key_array[i].key_id_length = encrypted_license_.keys[i].key_id_length;
|
||||
} else {
|
||||
key_array[i].key_id = NULL;
|
||||
key_array[i].key_id_length = 0;
|
||||
}
|
||||
key_array[i].key_control_iv = NULL;
|
||||
key_array[i].key_control =
|
||||
reinterpret_cast<const uint8_t*>(&encrypted_license_.keys[i].control);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::EncryptCTR(
|
||||
const vector<uint8_t>& in_buffer, const uint8_t *key,
|
||||
const uint8_t* starting_iv, vector<uint8_t>* out_buffer) {
|
||||
ASSERT_NE(static_cast<void*>(NULL), key);
|
||||
ASSERT_NE(static_cast<void*>(NULL), starting_iv);
|
||||
ASSERT_NE(static_cast<void*>(NULL), out_buffer);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(key, AES_BLOCK_SIZE * 8, &aes_key);
|
||||
out_buffer->resize(in_buffer.size());
|
||||
|
||||
uint8_t iv[AES_BLOCK_SIZE]; // Current iv.
|
||||
|
||||
memcpy(iv, &starting_iv[0], AES_BLOCK_SIZE);
|
||||
size_t l = 0; // byte index into encrypted subsample.
|
||||
while (l < in_buffer.size()) {
|
||||
uint8_t aes_output[AES_BLOCK_SIZE];
|
||||
AES_encrypt(iv, aes_output, &aes_key);
|
||||
for (size_t n = 0; n < AES_BLOCK_SIZE && l < in_buffer.size(); n++, l++) {
|
||||
(*out_buffer)[l] = aes_output[n] ^ in_buffer[l];
|
||||
}
|
||||
ctr128_inc64(1, iv);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::TestDecryptCTR(bool select_key_first,
|
||||
OEMCryptoResult expected_result) {
|
||||
OEMCryptoResult sts;
|
||||
if (select_key_first) {
|
||||
// Select the key (from FillSimpleMessage)
|
||||
sts = OEMCrypto_SelectKey(session_id(), license_.keys[0].key_id,
|
||||
license_.keys[0].key_id_length);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
vector<uint8_t> unencryptedData(256);
|
||||
for(size_t i=0; i < unencryptedData.size(); i++) unencryptedData[i] = i % 256;
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetRandom(&unencryptedData[0], unencryptedData.size()));
|
||||
vector<uint8_t> encryptionIv(wvcdm::KEY_IV_SIZE);
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetRandom(&encryptionIv[0], wvcdm::KEY_IV_SIZE));
|
||||
vector<uint8_t> encryptedData(unencryptedData.size());
|
||||
EncryptCTR(unencryptedData, license_.keys[0].key_data, &encryptionIv[0],
|
||||
&encryptedData);
|
||||
|
||||
// Describe the output
|
||||
vector<uint8_t> outputBuffer(256);
|
||||
OEMCrypto_DestBufferDesc destBuffer;
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = outputBuffer.data();
|
||||
destBuffer.buffer.clear.max_length = outputBuffer.size();
|
||||
OEMCrypto_CENCEncryptPatternDesc pattern;
|
||||
pattern.encrypt = 0;
|
||||
pattern.skip = 0;
|
||||
pattern.offset = 0;
|
||||
// Decrypt the data
|
||||
sts = OEMCrypto_DecryptCENC(
|
||||
session_id(), &encryptedData[0], encryptedData.size(), true,
|
||||
&encryptionIv[0], 0, &destBuffer, &pattern,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
|
||||
// We only have a few errors that we test are reported.
|
||||
if (expected_result == OEMCrypto_SUCCESS) { // No error.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_EQ(unencryptedData, outputBuffer);
|
||||
} else if (expected_result == OEMCrypto_ERROR_KEY_EXPIRED) {
|
||||
// Report stale keys.
|
||||
ASSERT_EQ(OEMCrypto_ERROR_KEY_EXPIRED, sts);
|
||||
ASSERT_NE(unencryptedData, outputBuffer);
|
||||
} else if (expected_result == OEMCrypto_ERROR_INSUFFICIENT_HDCP) {
|
||||
// Report HDCP errors.
|
||||
ASSERT_EQ(OEMCrypto_ERROR_INSUFFICIENT_HDCP, sts);
|
||||
ASSERT_NE(unencryptedData, outputBuffer);
|
||||
} else {
|
||||
// OEM's can fine tune other error codes for debugging.
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_NE(unencryptedData, outputBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::MakeRSACertificate(
|
||||
struct RSAPrivateKeyMessage* encrypted, std::vector<uint8_t>* signature,
|
||||
uint32_t allowed_schemes, const vector<uint8_t>& rsa_key) {
|
||||
// Dummy context for testing signature generation.
|
||||
vector<uint8_t> context = wvcdm::a2b_hex(
|
||||
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
|
||||
"8f8276e4c2d87ec52b61aa1b9f646e58734930acebe899b3e464189a14a87202"
|
||||
"fb02574e70640bd22ef44b2d7e3912250a230a14080112100915007caa9b5931"
|
||||
"b76a3a85f046523e10011a09393837363534333231180120002a0c3138383637"
|
||||
"38373430350000");
|
||||
|
||||
OEMCryptoResult sts;
|
||||
|
||||
// Generate signature
|
||||
size_t gen_signature_length = 0;
|
||||
sts = OEMCrypto_GenerateSignature(session_id(), &context[0], context.size(),
|
||||
NULL, &gen_signature_length);
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
||||
ASSERT_EQ(static_cast<size_t>(32), gen_signature_length);
|
||||
vector<uint8_t> gen_signature(gen_signature_length);
|
||||
sts = OEMCrypto_GenerateSignature(session_id(), &context[0], context.size(),
|
||||
&gen_signature[0], &gen_signature_length);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
std::vector<uint8_t> expected_signature;
|
||||
ClientSignMessage(context, &expected_signature);
|
||||
ASSERT_EQ(expected_signature, gen_signature);
|
||||
|
||||
// Rewrap Canned Response
|
||||
|
||||
// In the real world, the signature above would just have been used to
|
||||
// contact the certificate provisioning server to get this response.
|
||||
|
||||
struct RSAPrivateKeyMessage message;
|
||||
if (allowed_schemes != kSign_RSASSA_PSS) {
|
||||
uint32_t algorithm_n = htonl(allowed_schemes);
|
||||
memcpy(message.rsa_key, "SIGN", 4);
|
||||
memcpy(message.rsa_key + 4, &algorithm_n, 4);
|
||||
memcpy(message.rsa_key + 8, rsa_key.data(), rsa_key.size());
|
||||
message.rsa_key_length = 8 + rsa_key.size();
|
||||
} else {
|
||||
memcpy(message.rsa_key, rsa_key.data(), rsa_key.size());
|
||||
message.rsa_key_length = rsa_key.size();
|
||||
}
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetRandom(message.rsa_key_iv, wvcdm::KEY_IV_SIZE));
|
||||
message.nonce = nonce_;
|
||||
|
||||
EncryptMessage(&message, encrypted);
|
||||
ServerSignMessage(*encrypted, signature);
|
||||
}
|
||||
|
||||
void Session::RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
|
||||
const std::vector<uint8_t>& signature,
|
||||
vector<uint8_t>* wrapped_key, bool force) {
|
||||
size_t wrapped_key_length = 0;
|
||||
const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(&encrypted);
|
||||
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
OEMCrypto_RewrapDeviceRSAKey(
|
||||
session_id(), message_ptr, sizeof(encrypted), &signature[0],
|
||||
signature.size(), &encrypted.nonce, encrypted.rsa_key,
|
||||
encrypted.rsa_key_length, encrypted.rsa_key_iv, NULL,
|
||||
&wrapped_key_length));
|
||||
wrapped_key->clear();
|
||||
wrapped_key->assign(wrapped_key_length, 0);
|
||||
OEMCryptoResult sts = OEMCrypto_RewrapDeviceRSAKey(
|
||||
session_id(), message_ptr, sizeof(encrypted), &signature[0],
|
||||
signature.size(), &encrypted.nonce, encrypted.rsa_key,
|
||||
encrypted.rsa_key_length, encrypted.rsa_key_iv, &(wrapped_key->front()),
|
||||
&wrapped_key_length);
|
||||
if (force) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
wrapped_key->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Session::PreparePublicKey(const uint8_t* rsa_key,
|
||||
size_t rsa_key_length) {
|
||||
if (rsa_key == NULL) {
|
||||
rsa_key = kTestRSAPKCS8PrivateKeyInfo2_2048;
|
||||
rsa_key_length = sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048);
|
||||
}
|
||||
uint8_t* p = const_cast<uint8_t*>(rsa_key);
|
||||
BIO* bio = BIO_new_mem_buf(p, rsa_key_length);
|
||||
ASSERT_TRUE(NULL != bio);
|
||||
PKCS8_PRIV_KEY_INFO* pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL);
|
||||
ASSERT_TRUE(NULL != pkcs8_pki);
|
||||
EVP_PKEY* evp = NULL;
|
||||
evp = EVP_PKCS82PKEY(pkcs8_pki);
|
||||
ASSERT_TRUE(NULL != evp);
|
||||
if (public_rsa_) RSA_free(public_rsa_);
|
||||
public_rsa_ = EVP_PKEY_get1_RSA(evp);
|
||||
EVP_PKEY_free(evp);
|
||||
PKCS8_PRIV_KEY_INFO_free(pkcs8_pki);
|
||||
BIO_free(bio);
|
||||
if (!public_rsa_) {
|
||||
cout << "d2i_RSAPrivateKey failed. ";
|
||||
dump_openssl_error();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
switch (RSA_check_key(public_rsa_)) {
|
||||
case 1: // valid.
|
||||
ASSERT_TRUE(true);
|
||||
return;
|
||||
case 0: // not valid.
|
||||
cout << "[rsa key not valid] ";
|
||||
dump_openssl_error();
|
||||
ASSERT_TRUE(false);
|
||||
default: // -1 == check failed.
|
||||
cout << "[error checking rsa key] ";
|
||||
dump_openssl_error();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool Session::VerifyPSSSignature(
|
||||
EVP_PKEY* pkey, const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length) {
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
EVP_PKEY_CTX* pctx = NULL;
|
||||
|
||||
if (EVP_DigestVerifyInit(&ctx, &pctx, EVP_sha1(), NULL /* no ENGINE */,
|
||||
pkey) != 1) {
|
||||
LOGE("EVP_DigestVerifyInit failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1()) != 1) {
|
||||
LOGE("EVP_PKEY_CTX_set_signature_md failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) != 1) {
|
||||
LOGE("EVP_PKEY_CTX_set_rsa_padding failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, SHA_DIGEST_LENGTH) != 1) {
|
||||
LOGE("EVP_PKEY_CTX_set_rsa_pss_saltlen failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyUpdate(&ctx, message, message_length) != 1) {
|
||||
LOGE("EVP_DigestVerifyUpdate failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyFinal(&ctx, const_cast<uint8_t*>(signature),
|
||||
signature_length) != 1) {
|
||||
LOGE(
|
||||
"EVP_DigestVerifyFinal failed in VerifyPSSSignature. (Probably a bad "
|
||||
"signature.)");
|
||||
goto err;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return true;
|
||||
|
||||
err:
|
||||
dump_openssl_error();
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
void Session::VerifyRSASignature(
|
||||
const vector<uint8_t>& message, const uint8_t* signature,
|
||||
size_t signature_length, RSA_Padding_Scheme padding_scheme) {
|
||||
EXPECT_TRUE(NULL != public_rsa_)
|
||||
<< "No public RSA key loaded in test code.\n";
|
||||
EXPECT_EQ(static_cast<size_t>(RSA_size(public_rsa_)), signature_length)
|
||||
<< "Signature size is wrong. " << signature_length << ", should be "
|
||||
<< RSA_size(public_rsa_) << "\n";
|
||||
|
||||
if (padding_scheme == kSign_RSASSA_PSS) {
|
||||
EVP_PKEY* pkey = EVP_PKEY_new();
|
||||
ASSERT_TRUE(EVP_PKEY_set1_RSA(pkey, public_rsa_) == 1);
|
||||
|
||||
const bool ok = VerifyPSSSignature(pkey, &message[0], message.size(),
|
||||
signature, signature_length);
|
||||
EVP_PKEY_free(pkey);
|
||||
EXPECT_TRUE(ok) << "PSS signature check failed.";
|
||||
} else if (padding_scheme == kSign_PKCS1_Block1) {
|
||||
vector<uint8_t> padded_digest(signature_length);
|
||||
int size;
|
||||
// RSA_public_decrypt decrypts the signature, and then verifies that
|
||||
// it was padded with RSA PKCS1 padding.
|
||||
size = RSA_public_decrypt(signature_length, signature, &padded_digest[0],
|
||||
public_rsa_, RSA_PKCS1_PADDING);
|
||||
EXPECT_GT(size, 0);
|
||||
padded_digest.resize(size);
|
||||
EXPECT_EQ(message, padded_digest);
|
||||
} else {
|
||||
EXPECT_TRUE(false) << "Padding scheme not supported.";
|
||||
}
|
||||
}
|
||||
|
||||
bool Session::GenerateRSASessionKey(vector<uint8_t>* enc_session_key) {
|
||||
if (!public_rsa_) {
|
||||
cout << "No public RSA key loaded in test code.\n";
|
||||
return false;
|
||||
}
|
||||
vector<uint8_t> session_key =
|
||||
wvcdm::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1");
|
||||
enc_session_key->assign(RSA_size(public_rsa_), 0);
|
||||
int status = RSA_public_encrypt(session_key.size(), &session_key[0],
|
||||
&(enc_session_key->front()), public_rsa_,
|
||||
RSA_PKCS1_OAEP_PADDING);
|
||||
int size = static_cast<int>(RSA_size(public_rsa_));
|
||||
if (status != size) {
|
||||
cout << "GenerateRSASessionKey error encrypting session key. ";
|
||||
dump_openssl_error();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Session::InstallRSASessionTestKey(
|
||||
const vector<uint8_t>& wrapped_rsa_key) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadDeviceRSAKey(session_id(), &wrapped_rsa_key[0],
|
||||
wrapped_rsa_key.size()));
|
||||
GenerateDerivedKeysFromSessionKey();
|
||||
}
|
||||
|
||||
void Session::DisallowDeriveKeys() {
|
||||
GenerateNonce(&nonce_);
|
||||
vector<uint8_t> enc_session_key;
|
||||
PreparePublicKey();
|
||||
ASSERT_TRUE(GenerateRSASessionKey(&enc_session_key));
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
FillDefaultContext(&mac_context, &enc_context);
|
||||
ASSERT_NE(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_DeriveKeysFromSessionKey(
|
||||
session_id(), &enc_session_key[0], enc_session_key.size(),
|
||||
&mac_context[0], mac_context.size(), &enc_context[0],
|
||||
enc_context.size()));
|
||||
}
|
||||
|
||||
void Session::GenerateReport(
|
||||
const std::string& pst, bool expect_success, Session* other) {
|
||||
if (other) { // If other is specified, copy mac keys.
|
||||
mac_key_server_ = other->mac_key_server_;
|
||||
mac_key_client_ = other->mac_key_client_;
|
||||
}
|
||||
size_t length = 0;
|
||||
OEMCryptoResult sts = OEMCrypto_ReportUsage(
|
||||
session_id(), reinterpret_cast<const uint8_t*>(pst.c_str()), pst.length(),
|
||||
pst_report(), &length);
|
||||
if (expect_success) {
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
|
||||
}
|
||||
if (sts == OEMCrypto_ERROR_SHORT_BUFFER) {
|
||||
ASSERT_LE(sizeof(OEMCrypto_PST_Report), length);
|
||||
pst_report_buffer_.resize(length);
|
||||
}
|
||||
sts = OEMCrypto_ReportUsage(session_id(),
|
||||
reinterpret_cast<const uint8_t*>(pst.c_str()),
|
||||
pst.length(), pst_report(), &length);
|
||||
if (!expect_success) {
|
||||
ASSERT_NE(OEMCrypto_SUCCESS, sts);
|
||||
return;
|
||||
}
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
vector<uint8_t> computed_signature(SHA_DIGEST_LENGTH);
|
||||
unsigned int sig_len = SHA_DIGEST_LENGTH;
|
||||
HMAC(EVP_sha1(), &mac_key_client_[0], mac_key_client_.size(),
|
||||
reinterpret_cast<uint8_t*>(pst_report()) + SHA_DIGEST_LENGTH,
|
||||
length - SHA_DIGEST_LENGTH, &computed_signature[0], &sig_len);
|
||||
EXPECT_EQ(0, memcmp(&computed_signature[0], pst_report()->signature,
|
||||
SHA_DIGEST_LENGTH));
|
||||
EXPECT_GE(kInactive, pst_report()->status);
|
||||
EXPECT_GE(kHardwareSecureClock, pst_report()->clock_security_level);
|
||||
EXPECT_EQ(pst.length(), pst_report()->pst_length);
|
||||
EXPECT_EQ(0, memcmp(pst.c_str(), pst_report()->pst, pst.length()));
|
||||
}
|
||||
|
||||
OEMCrypto_PST_Report* Session::pst_report() {
|
||||
return reinterpret_cast<OEMCrypto_PST_Report*>(&pst_report_buffer_[0]);
|
||||
}
|
||||
|
||||
void Session::DeleteEntry(const std::string& pst) {
|
||||
uint8_t* pst_ptr = encrypted_license_.pst;
|
||||
memcpy(pst_ptr, pst.c_str(), min(sizeof(license_.pst), pst.length()));
|
||||
ServerSignMessage(encrypted_license_, &signature_);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_DeleteUsageEntry(session_id(), pst_ptr, pst.length(),
|
||||
message_ptr(), sizeof(MessageData),
|
||||
&signature_[0], signature_.size()));
|
||||
}
|
||||
|
||||
void Session::ForceDeleteEntry(const std::string& pst) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_ForceDeleteUsageEntry(
|
||||
reinterpret_cast<const uint8_t*>(pst.c_str()), pst.length()));
|
||||
}
|
||||
|
||||
const uint8_t* Session::message_ptr() {
|
||||
return reinterpret_cast<const uint8_t*>(&encrypted_license_);
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
207
oemcrypto/test/oec_session_util.h
Normal file
207
oemcrypto/test/oec_session_util.h
Normal file
@@ -0,0 +1,207 @@
|
||||
#ifndef CDM_OEC_SESSION_UTIL_H_
|
||||
#define CDM_OEC_SESSION_UTIL_H_
|
||||
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// OEMCrypto unit tests
|
||||
//
|
||||
#include <openssl/rsa.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "oec_device_features.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// GTest requires PrintTo to be in the same namespace as the thing it prints,
|
||||
// which is std::vector in this case.
|
||||
namespace std {
|
||||
|
||||
struct PatternTestVariant {
|
||||
PatternTestVariant(size_t encrypt, size_t skip, OEMCryptoCipherMode mode) {
|
||||
this->pattern.encrypt = encrypt;
|
||||
this->pattern.skip = skip;
|
||||
this->pattern.offset = 0;
|
||||
this->mode = mode;
|
||||
}
|
||||
OEMCrypto_CENCEncryptPatternDesc pattern;
|
||||
OEMCryptoCipherMode mode;
|
||||
};
|
||||
|
||||
void PrintTo(const vector<uint8_t>& value, ostream* os);
|
||||
void PrintTo(const PatternTestVariant& param, ostream* os);
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
const size_t kNumKeys = 4;
|
||||
|
||||
namespace {
|
||||
#if defined(TEST_SPEED_MULTIPLIER) // Can slow test time limits when
|
||||
// debugging is slowing everything.
|
||||
const int kSpeedMultiplier = TEST_SPEED_MULTIPLIER;
|
||||
#else
|
||||
const int kSpeedMultiplier = 1;
|
||||
#endif
|
||||
const int kShortSleep = 1 * kSpeedMultiplier;
|
||||
const int kLongSleep = 2 * kSpeedMultiplier;
|
||||
const uint32_t kDuration = 2 * kSpeedMultiplier;
|
||||
const uint32_t kLongDuration = 5 * kSpeedMultiplier;
|
||||
const int32_t kTimeTolerance = 3 * kSpeedMultiplier;
|
||||
} // namespace
|
||||
|
||||
typedef struct {
|
||||
uint8_t verification[4];
|
||||
uint32_t duration;
|
||||
uint32_t nonce;
|
||||
uint32_t control_bits;
|
||||
} KeyControlBlock;
|
||||
|
||||
// Note: The API does not specify a maximum key id length. We specify a
|
||||
// maximum just for these tests, so that we have a fixed message size.
|
||||
const size_t kTestKeyIdMaxLength = 16;
|
||||
|
||||
// Most content will use a key id that is 16 bytes long.
|
||||
const int kDefaultKeyIdLength = 16;
|
||||
|
||||
const size_t kMaxTestRSAKeyLength = 2000; // Rough estimate.
|
||||
|
||||
typedef struct {
|
||||
uint8_t key_id[kTestKeyIdMaxLength];
|
||||
size_t key_id_length;
|
||||
uint8_t key_data[wvcdm::MAC_KEY_SIZE];
|
||||
size_t key_data_length;
|
||||
uint8_t key_iv[wvcdm::KEY_IV_SIZE];
|
||||
uint8_t control_iv[wvcdm::KEY_IV_SIZE];
|
||||
KeyControlBlock control;
|
||||
// Note: cipher_mode may not be part of a real signed message. For these
|
||||
// tests, it is convenient to keep it in this structure anyway.
|
||||
OEMCryptoCipherMode cipher_mode;
|
||||
} MessageKeyData;
|
||||
|
||||
// This structure will be signed to simulate a message from the server.
|
||||
struct MessageData {
|
||||
MessageKeyData keys[kNumKeys];
|
||||
uint8_t mac_key_iv[wvcdm::KEY_IV_SIZE];
|
||||
uint8_t mac_keys[2 * wvcdm::MAC_KEY_SIZE];
|
||||
uint8_t pst[kTestKeyIdMaxLength];
|
||||
};
|
||||
|
||||
struct RSAPrivateKeyMessage {
|
||||
uint8_t rsa_key[kMaxTestRSAKeyLength];
|
||||
uint8_t rsa_key_iv[wvcdm::KEY_IV_SIZE];
|
||||
size_t rsa_key_length;
|
||||
uint32_t nonce;
|
||||
};
|
||||
|
||||
// Increment counter for AES-CTR. The CENC spec specifies we increment only
|
||||
// the low 64 bits of the IV counter, and leave the high 64 bits alone. This
|
||||
// is different from the OpenSSL implementation, so we implement the CTR loop
|
||||
// ourselves.
|
||||
void ctr128_inc64(int64_t increaseBy, uint8_t* iv);
|
||||
|
||||
// Some compilers don't like the macro htonl within an ASSERT_EQ.
|
||||
uint32_t htonl_fnc(uint32_t x);
|
||||
|
||||
// Prints error string from openSSL
|
||||
void dump_openssl_error();
|
||||
|
||||
class Session {
|
||||
public:
|
||||
Session();
|
||||
~Session();
|
||||
|
||||
uint32_t get_nonce() { return nonce_; }
|
||||
|
||||
uint32_t session_id() { return (uint32_t)session_id_; }
|
||||
|
||||
void open();
|
||||
void close();
|
||||
void SetSessionId(uint32_t session_id);
|
||||
|
||||
uint32_t GetOecSessionId() { return session_id_; }
|
||||
void GenerateNonce(uint32_t* nonce, int* error_counter = NULL);
|
||||
void FillDefaultContext(vector<uint8_t>* mac_context,
|
||||
vector<uint8_t>* enc_context);
|
||||
void GenerateDerivedKeysFromKeybox();
|
||||
void GenerateDerivedKeysFromSessionKey();
|
||||
void GenerateTestSessionKeys();
|
||||
void LoadTestKeys(const std::string& pst = "", bool new_mac_keys = true);
|
||||
void VerifyTestKeys();
|
||||
void RefreshTestKeys(const size_t key_count, uint32_t control_bits,
|
||||
uint32_t nonce, OEMCryptoResult expected_result);
|
||||
void SetKeyId(int index, const string& key_id);
|
||||
void FillSimpleMessage(uint32_t duration, uint32_t control, uint32_t nonce,
|
||||
const std::string& pst = "");
|
||||
|
||||
void FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
||||
uint32_t nonce);
|
||||
void EncryptAndSign();
|
||||
void EncryptMessage(RSAPrivateKeyMessage* data,
|
||||
RSAPrivateKeyMessage* encrypted);
|
||||
|
||||
template <typename T>
|
||||
void ServerSignMessage(const T& data, std::vector<uint8_t>* signature);
|
||||
|
||||
void ClientSignMessage(const vector<uint8_t>& data,
|
||||
std::vector<uint8_t>* signature);
|
||||
void FillKeyArray(const MessageData& data, OEMCrypto_KeyObject* key_array);
|
||||
void FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
|
||||
size_t key_count);
|
||||
void EncryptCTR(
|
||||
const vector<uint8_t>& in_buffer, const uint8_t *key,
|
||||
const uint8_t* starting_iv, vector<uint8_t>* out_buffer);
|
||||
void TestDecryptCTR(bool select_key_first = true,
|
||||
OEMCryptoResult expected_result = OEMCrypto_SUCCESS);
|
||||
void MakeRSACertificate(
|
||||
struct RSAPrivateKeyMessage* encrypted, std::vector<uint8_t>* signature,
|
||||
uint32_t allowed_schemes, const vector<uint8_t>& rsa_key);
|
||||
void RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
|
||||
const std::vector<uint8_t>& signature,
|
||||
vector<uint8_t>* wrapped_key, bool force);
|
||||
void PreparePublicKey(const uint8_t* rsa_key = NULL,
|
||||
size_t rsa_key_length = 0);
|
||||
static bool VerifyPSSSignature(
|
||||
EVP_PKEY* pkey, const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length);
|
||||
void VerifyRSASignature(
|
||||
const vector<uint8_t>& message, const uint8_t* signature,
|
||||
size_t signature_length, RSA_Padding_Scheme padding_scheme);
|
||||
bool GenerateRSASessionKey(vector<uint8_t>* enc_session_key);
|
||||
void InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key);
|
||||
void DisallowDeriveKeys();
|
||||
void GenerateReport(const std::string& pst, bool expect_success = true,
|
||||
Session* other = 0);
|
||||
OEMCrypto_PST_Report* pst_report();
|
||||
void DeleteEntry(const std::string& pst);
|
||||
void ForceDeleteEntry(const std::string& pst);
|
||||
|
||||
MessageData& license() { return license_; }
|
||||
MessageData& encrypted_license() { return encrypted_license_; }
|
||||
|
||||
const uint8_t* message_ptr();
|
||||
|
||||
OEMCrypto_KeyObject* key_array() { return key_array_; }
|
||||
std::vector<uint8_t>& signature() { return signature_; }
|
||||
|
||||
private:
|
||||
bool open_;
|
||||
bool forced_session_id_;
|
||||
OEMCrypto_SESSION session_id_;
|
||||
vector<uint8_t> mac_key_server_;
|
||||
vector<uint8_t> mac_key_client_;
|
||||
vector<uint8_t> enc_key_;
|
||||
uint32_t nonce_;
|
||||
RSA* public_rsa_;
|
||||
vector<uint8_t> pst_report_buffer_;
|
||||
MessageData license_;
|
||||
MessageData encrypted_license_;
|
||||
OEMCrypto_KeyObject key_array_[kNumKeys];
|
||||
std::vector<uint8_t> signature_;
|
||||
};
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEC_SESSION_UTIL_H_
|
||||
273
oemcrypto/test/oec_test_data.h
Normal file
273
oemcrypto/test/oec_test_data.h
Normal file
@@ -0,0 +1,273 @@
|
||||
#ifndef CDM_OEC_TEST_DATA_H_
|
||||
#define CDM_OEC_TEST_DATA_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#if 0
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "wv_keybox.h"
|
||||
#endif
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// These are test keyboxes. 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.
|
||||
// The first keybox, kTestKeybox, with deviceID "TestKey01" is used for most of
|
||||
// the tests. It should be loaded by OEMCrypto when OEMCrypto_LoadTestKeybox
|
||||
// is called.
|
||||
const wvoec_mock::WidevineKeybox kTestKeybox = {
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID
|
||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey01
|
||||
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
}, {
|
||||
// key
|
||||
0xfb, 0xda, 0x04, 0x89, 0xa1, 0x58, 0x16, 0x0e,
|
||||
0xa4, 0x02, 0xe9, 0x29, 0xe3, 0xb6, 0x8f, 0x04,
|
||||
}, {
|
||||
// data
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
||||
0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1,
|
||||
0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd,
|
||||
0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2, 0xd8,
|
||||
0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64,
|
||||
0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8,
|
||||
0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14, 0xa8,
|
||||
0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64,
|
||||
0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// Crc
|
||||
0x0a, 0x7a, 0x2c, 0x35,
|
||||
}
|
||||
};
|
||||
|
||||
static wvoec_mock::WidevineKeybox kValidKeybox02 = {
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID
|
||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey02
|
||||
0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
}, {
|
||||
// key
|
||||
0x76, 0x5d, 0xce, 0x01, 0x04, 0x89, 0xb3, 0xd0,
|
||||
0xdf, 0xce, 0x54, 0x8a, 0x49, 0xda, 0xdc, 0xb6,
|
||||
}, {
|
||||
// data
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
||||
0x92, 0x27, 0x0b, 0x1f, 0x1a, 0xd5, 0xc6, 0x93,
|
||||
0x19, 0x3f, 0xaa, 0x74, 0x1f, 0xdd, 0x5f, 0xb4,
|
||||
0xe9, 0x40, 0x2f, 0x34, 0xa4, 0x92, 0xf4, 0xae,
|
||||
0x9a, 0x52, 0x39, 0xbc, 0xb7, 0x24, 0x38, 0x13,
|
||||
0xab, 0xf4, 0x92, 0x96, 0xc4, 0x81, 0x60, 0x33,
|
||||
0xd8, 0xb8, 0x09, 0xc7, 0x55, 0x0e, 0x12, 0xfa,
|
||||
0xa8, 0x98, 0x62, 0x8a, 0xec, 0xea, 0x74, 0x8a,
|
||||
0x4b, 0xfa, 0x5a, 0x9e, 0xb6, 0x49, 0x0d, 0x80,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// Crc
|
||||
0x2a, 0x3b, 0x3e, 0xe4,
|
||||
}
|
||||
};
|
||||
|
||||
static wvoec_mock::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,
|
||||
}
|
||||
};
|
||||
|
||||
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format
|
||||
// Used to verify the functions that manipulate RSA keys.
|
||||
static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
|
||||
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||
0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01,
|
||||
0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa7, 0x00,
|
||||
0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a,
|
||||
0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f,
|
||||
0x94, 0x58, 0xdd, 0xde, 0xa7, 0x1f, 0x3c, 0x2c,
|
||||
0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e,
|
||||
0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a,
|
||||
0x2a, 0xaa, 0x9d, 0xb4, 0x4e, 0xfa, 0xa7, 0x6a,
|
||||
0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3,
|
||||
0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f,
|
||||
0x28, 0xda, 0x3f, 0xce, 0x31, 0x7b, 0xfd, 0x06,
|
||||
0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb,
|
||||
0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3,
|
||||
0x29, 0xf2, 0x73, 0x9e, 0x39, 0xd8, 0xf6, 0x6f,
|
||||
0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4,
|
||||
0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04,
|
||||
0xcd, 0x9a, 0x13, 0x8b, 0x54, 0x73, 0x54, 0x25,
|
||||
0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda,
|
||||
0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67,
|
||||
0x98, 0x56, 0x57, 0x54, 0x71, 0xcd, 0x12, 0x7f,
|
||||
0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03,
|
||||
0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53,
|
||||
0xc9, 0x83, 0x06, 0x51, 0x5a, 0x88, 0x65, 0x13,
|
||||
0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b,
|
||||
0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e,
|
||||
0x2d, 0x5f, 0xf8, 0x12, 0x7f, 0xa2, 0xfc, 0xbb,
|
||||
0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01,
|
||||
0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87,
|
||||
0x82, 0x46, 0x0b, 0x3a, 0x77, 0x8f, 0xc0, 0x72,
|
||||
0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed,
|
||||
0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44,
|
||||
0xd3, 0x5b, 0x3d, 0xdb, 0x9c, 0x5e, 0x1b, 0x7b,
|
||||
0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb,
|
||||
0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03,
|
||||
0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x5e,
|
||||
0x79, 0x65, 0x49, 0xa5, 0x76, 0x79, 0xf9, 0x05,
|
||||
0x45, 0x0f, 0xf4, 0x03, 0xbd, 0xa4, 0x7d, 0x29,
|
||||
0xd5, 0xde, 0x33, 0x63, 0xd8, 0xb8, 0xac, 0x97,
|
||||
0xeb, 0x3f, 0x5e, 0x55, 0xe8, 0x7d, 0xf3, 0xe7,
|
||||
0x3b, 0x5c, 0x2d, 0x54, 0x67, 0x36, 0xd6, 0x1d,
|
||||
0x46, 0xf5, 0xca, 0x2d, 0x8b, 0x3a, 0x7e, 0xdc,
|
||||
0x45, 0x38, 0x79, 0x7e, 0x65, 0x71, 0x5f, 0x1c,
|
||||
0x5e, 0x79, 0xb1, 0x40, 0xcd, 0xfe, 0xc5, 0xe1,
|
||||
0xc1, 0x6b, 0x78, 0x04, 0x4e, 0x8e, 0x79, 0xf9,
|
||||
0x0a, 0xfc, 0x79, 0xb1, 0x5e, 0xb3, 0x60, 0xe3,
|
||||
0x68, 0x7b, 0xc6, 0xef, 0xcb, 0x71, 0x4c, 0xba,
|
||||
0xa7, 0x79, 0x5c, 0x7a, 0x81, 0xd1, 0x71, 0xe7,
|
||||
0x00, 0x21, 0x13, 0xe2, 0x55, 0x69, 0x0e, 0x75,
|
||||
0xbe, 0x09, 0xc3, 0x4f, 0xa9, 0xc9, 0x68, 0x22,
|
||||
0x0e, 0x97, 0x8d, 0x89, 0x6e, 0xf1, 0xe8, 0x88,
|
||||
0x7a, 0xd1, 0xd9, 0x09, 0x5d, 0xd3, 0x28, 0x78,
|
||||
0x25, 0x0b, 0x1c, 0x47, 0x73, 0x25, 0xcc, 0x21,
|
||||
0xb6, 0xda, 0xc6, 0x24, 0x5a, 0xd0, 0x37, 0x14,
|
||||
0x46, 0xc7, 0x94, 0x69, 0xe4, 0x43, 0x6f, 0x47,
|
||||
0xde, 0x00, 0x33, 0x4d, 0x8f, 0x95, 0x72, 0xfa,
|
||||
0x68, 0x71, 0x17, 0x66, 0x12, 0x1a, 0x87, 0x27,
|
||||
0xf7, 0xef, 0x7e, 0xe0, 0x35, 0x58, 0xf2, 0x4d,
|
||||
0x6f, 0x35, 0x01, 0xaa, 0x96, 0xe2, 0x3d, 0x51,
|
||||
0x13, 0x86, 0x9c, 0x79, 0xd0, 0xb7, 0xb6, 0x64,
|
||||
0xe8, 0x86, 0x65, 0x50, 0xbf, 0xcc, 0x27, 0x53,
|
||||
0x1f, 0x51, 0xd4, 0xca, 0xbe, 0xf5, 0xdd, 0x77,
|
||||
0x70, 0x98, 0x0f, 0xee, 0xa8, 0x96, 0x07, 0x5f,
|
||||
0x45, 0x6a, 0x7a, 0x0d, 0x03, 0x9c, 0x4f, 0x29,
|
||||
0xf6, 0x06, 0xf3, 0x5d, 0x58, 0x6c, 0x47, 0xd0,
|
||||
0x96, 0xa9, 0x03, 0x17, 0xbb, 0x4e, 0xc9, 0x21,
|
||||
0xe0, 0xac, 0xcd, 0x78, 0x78, 0xb2, 0xfe, 0x81,
|
||||
0xb2, 0x51, 0x53, 0xa6, 0x1f, 0x98, 0x45, 0x02,
|
||||
0x81, 0x81, 0x00, 0xcf, 0x73, 0x8c, 0xbe, 0x6d,
|
||||
0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75,
|
||||
0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9,
|
||||
0x64, 0x60, 0x8c, 0x43, 0xeb, 0x85, 0xab, 0x04,
|
||||
0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda,
|
||||
0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4,
|
||||
0xde, 0x51, 0x4b, 0xb6, 0x51, 0x86, 0x7b, 0xd0,
|
||||
0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f,
|
||||
0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13,
|
||||
0x93, 0xd7, 0x9c, 0x27, 0x80, 0xb7, 0x1e, 0x64,
|
||||
0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8,
|
||||
0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96,
|
||||
0x90, 0x8f, 0xa2, 0x16, 0x22, 0x6a, 0xcc, 0x48,
|
||||
0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44,
|
||||
0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27,
|
||||
0x33, 0x85, 0x26, 0x60, 0x48, 0x16, 0xcb, 0xef,
|
||||
0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce,
|
||||
0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87,
|
||||
0xc3, 0x41, 0x45, 0x97, 0xb1, 0x49, 0xc2, 0x19,
|
||||
0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28,
|
||||
0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb,
|
||||
0xbb, 0xdb, 0xfd, 0x11, 0x9d, 0x17, 0x68, 0x78,
|
||||
0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3,
|
||||
0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54,
|
||||
0x91, 0x99, 0xe5, 0x91, 0x32, 0x2d, 0xeb, 0x3f,
|
||||
0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41,
|
||||
0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42,
|
||||
0x58, 0xf4, 0xd0, 0xb2, 0x74, 0x1d, 0x8e, 0x87,
|
||||
0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd,
|
||||
0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53,
|
||||
0xda, 0xfb, 0xed, 0x83, 0x51, 0x67, 0xa9, 0x55,
|
||||
0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17,
|
||||
0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02,
|
||||
0x81, 0x80, 0x67, 0x9c, 0x32, 0x83, 0x39, 0x57,
|
||||
0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0,
|
||||
0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97,
|
||||
0xf3, 0x90, 0x9a, 0xab, 0x9b, 0x0b, 0x1b, 0x43,
|
||||
0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c,
|
||||
0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80,
|
||||
0xb8, 0xe1, 0xb3, 0xa1, 0x6c, 0x25, 0x92, 0xe4,
|
||||
0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f,
|
||||
0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81,
|
||||
0x20, 0x82, 0xa1, 0x48, 0x2c, 0x2d, 0x45, 0xdc,
|
||||
0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41,
|
||||
0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54,
|
||||
0xc8, 0x28, 0x10, 0x1e, 0x08, 0x71, 0x16, 0xd8,
|
||||
0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5,
|
||||
0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf,
|
||||
0x35, 0x95, 0x41, 0x29, 0x40, 0x19, 0x83, 0x35,
|
||||
0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b,
|
||||
0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae,
|
||||
0x50, 0x76, 0x63, 0x94, 0x49, 0x4c, 0xad, 0x10,
|
||||
0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8,
|
||||
0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b,
|
||||
0x8a, 0xa2, 0xb9, 0x8f, 0xce, 0xec, 0x5e, 0x61,
|
||||
0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a,
|
||||
0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69,
|
||||
0xe4, 0x8b, 0x01, 0x06, 0x59, 0x22, 0xfa, 0x34,
|
||||
0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a,
|
||||
0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26,
|
||||
0x6c, 0xfa, 0x2b, 0xd9, 0x83, 0x5a, 0x2d, 0x0c,
|
||||
0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a,
|
||||
0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3,
|
||||
0x66, 0xff, 0x1c, 0x1b, 0xc8, 0x96, 0x76, 0xe8,
|
||||
0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8,
|
||||
0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80,
|
||||
0x2c, 0x7c, 0xad, 0x1e, 0x75, 0xf6, 0x69, 0x1d,
|
||||
0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65,
|
||||
0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57,
|
||||
0xae, 0xb7, 0x65, 0x2c, 0x52, 0xf9, 0xe4, 0xc7,
|
||||
0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33,
|
||||
0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50,
|
||||
0x75, 0x61, 0x96, 0x86, 0x4b, 0xb6, 0x2b, 0xad,
|
||||
0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35,
|
||||
0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a,
|
||||
0xd3, 0x29, 0x23, 0x02, 0x60, 0xf7, 0xab, 0x30,
|
||||
0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4,
|
||||
0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18,
|
||||
0xf4, 0xd4, 0x52, 0x95, 0x00, 0xae, 0x84, 0x6b,
|
||||
0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde,
|
||||
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18,
|
||||
0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03 };
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
#endif // CDM_OEC_TEST_DATA_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -88,7 +88,7 @@ TEST_F(OEMCryptoAndroidLMPTest, Level1Required) {
|
||||
}
|
||||
|
||||
// These tests are required for M Android devices.
|
||||
class OEMCryptoAndroidMNCTest : public OEMCryptoAndroidLMPTest {};
|
||||
class OEMCryptoAndroidMNCTest : public OEMCryptoAndroidLMPTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidMNCTest, MinVersionNumber10) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
@@ -111,4 +111,12 @@ TEST_F(OEMCryptoAndroidMNCTest, QueryKeyControlImplemented) {
|
||||
OEMCrypto_QueryKeyControl(0, NULL, 0, NULL, NULL));
|
||||
}
|
||||
|
||||
// These tests are required for N Android devices.
|
||||
class OEMCryptoAndroidNYCTest : public OEMCryptoAndroidMNCTest {};
|
||||
|
||||
TEST_F(OEMCryptoAndroidNYCTest, MinVersionNumber11) {
|
||||
uint32_t version = OEMCrypto_APIVersion();
|
||||
ASSERT_GE(version, 11u);
|
||||
}
|
||||
|
||||
} // namespace wvoec
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "log.h"
|
||||
#include "oemcrypto_test.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "properties.h"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user