Source release 14.0.0
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <arpa/inet.h> // needed for ntoh()
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/pem.h>
|
||||
@@ -17,6 +19,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -43,29 +46,20 @@ void PrintTo(const vector<uint8_t>& value, ostream* os) {
|
||||
namespace {
|
||||
int GetRandBytes(unsigned char* buf, int num) {
|
||||
// returns 1 on success, -1 if not supported, or 0 if other failure.
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
return RAND_pseudo_bytes(buf, num);
|
||||
#else
|
||||
return RAND_bytes(buf, num);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
void DeleteX509Stack(STACK_OF(X509)* stack) {
|
||||
sk_X509_pop_free(stack, X509_free);
|
||||
}
|
||||
|
||||
typedef size_t X509Count;
|
||||
#else
|
||||
typedef int X509Count;
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
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
|
||||
// is different from the BoringSSL implementation, so we implement the CTR loop
|
||||
// ourselves.
|
||||
void ctr128_inc64(int64_t increaseBy, uint8_t* iv) {
|
||||
ASSERT_NE(static_cast<void*>(NULL), iv);
|
||||
@@ -77,19 +71,19 @@ 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) { return htonl(x); }
|
||||
|
||||
void dump_openssl_error() {
|
||||
void dump_boringssl_error() {
|
||||
while (unsigned long err = ERR_get_error()) {
|
||||
char buffer[120];
|
||||
ERR_error_string_n(err, buffer, sizeof(buffer));
|
||||
cout << "openssl error -- " << buffer << "\n";
|
||||
cout << "BoringSSL Error -- " << buffer << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, void (*func)(T*)>
|
||||
class openssl_ptr {
|
||||
class boringssl_ptr {
|
||||
public:
|
||||
explicit openssl_ptr(T* p = NULL) : ptr_(p) {}
|
||||
~openssl_ptr() {
|
||||
explicit boringssl_ptr(T* p = NULL) : ptr_(p) {}
|
||||
~boringssl_ptr() {
|
||||
if (ptr_) func(ptr_);
|
||||
}
|
||||
T& operator*() const { return *ptr_; }
|
||||
@@ -99,7 +93,7 @@ class openssl_ptr {
|
||||
|
||||
private:
|
||||
T* ptr_;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(openssl_ptr);
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
|
||||
};
|
||||
|
||||
Session::Session()
|
||||
@@ -111,8 +105,9 @@ Session::Session()
|
||||
enc_key_(wvcdm::KEY_SIZE),
|
||||
public_rsa_(0),
|
||||
message_size_(sizeof(MessageData)),
|
||||
num_keys_(4) { // Most tests only use 4 keys.
|
||||
// Other tests will explicitly call set_num_keys.
|
||||
num_keys_(4), // Most tests only use 4 keys.
|
||||
// Other tests will explicitly call set_num_keys.
|
||||
has_entitlement_license_(false) {
|
||||
// Stripe the padded message.
|
||||
for (size_t i = 0; i < sizeof(padded_message_.padding); i++) {
|
||||
padded_message_.padding[i] = i % 0x100;
|
||||
@@ -180,7 +175,53 @@ void Session::FillDefaultContext(vector<uint8_t>* mac_context,
|
||||
"180120002a0c31383836373837343035000000000080");
|
||||
}
|
||||
|
||||
void Session::GenerateDerivedKeysFromKeybox() {
|
||||
void Session::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
|
||||
int counter, vector<uint8_t>* out) {
|
||||
ASSERT_FALSE(context.empty());
|
||||
ASSERT_GE(4, counter);
|
||||
ASSERT_NE(static_cast<void*>(NULL), out);
|
||||
|
||||
const EVP_CIPHER* cipher = EVP_aes_128_cbc();
|
||||
CMAC_CTX* cmac_ctx = CMAC_CTX_new();
|
||||
ASSERT_NE(static_cast<void*>(NULL), cmac_ctx);
|
||||
|
||||
ASSERT_EQ(1, CMAC_Init(cmac_ctx, key, wvcdm::KEY_SIZE, cipher, 0));
|
||||
|
||||
std::vector<uint8_t> message;
|
||||
message.push_back(counter);
|
||||
message.insert(message.end(), context.begin(), context.end());
|
||||
|
||||
ASSERT_EQ(1, CMAC_Update(cmac_ctx, &message[0], message.size()));
|
||||
|
||||
size_t reslen;
|
||||
uint8_t res[128];
|
||||
ASSERT_EQ(1, CMAC_Final(cmac_ctx, res, &reslen));
|
||||
|
||||
out->assign(res, res + reslen);
|
||||
CMAC_CTX_free(cmac_ctx);
|
||||
}
|
||||
|
||||
void Session::DeriveKeys(const uint8_t* master_key,
|
||||
const vector<uint8_t>& mac_key_context,
|
||||
const vector<uint8_t>& enc_key_context) {
|
||||
// Generate derived key for mac key
|
||||
std::vector<uint8_t> mac_key_part2;
|
||||
DeriveKey(master_key, mac_key_context, 1, &mac_key_server_);
|
||||
DeriveKey(master_key, mac_key_context, 2, &mac_key_part2);
|
||||
mac_key_server_.insert(mac_key_server_.end(), mac_key_part2.begin(),
|
||||
mac_key_part2.end());
|
||||
|
||||
DeriveKey(master_key, mac_key_context, 3, &mac_key_client_);
|
||||
DeriveKey(master_key, mac_key_context, 4, &mac_key_part2);
|
||||
mac_key_client_.insert(mac_key_client_.end(), mac_key_part2.begin(),
|
||||
mac_key_part2.end());
|
||||
|
||||
// Generate derived key for encryption key
|
||||
DeriveKey(master_key, enc_key_context, 1, &enc_key_);
|
||||
}
|
||||
|
||||
void Session::GenerateDerivedKeysFromKeybox(
|
||||
const wvcdm_test_auth::WidevineKeybox& keybox) {
|
||||
GenerateNonce();
|
||||
vector<uint8_t> mac_context;
|
||||
vector<uint8_t> enc_context;
|
||||
@@ -190,15 +231,7 @@ void Session::GenerateDerivedKeysFromKeybox() {
|
||||
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");
|
||||
DeriveKeys(keybox.device_key_, mac_context, enc_context);
|
||||
}
|
||||
|
||||
void Session::GenerateDerivedKeysFromSessionKey() {
|
||||
@@ -217,13 +250,7 @@ void Session::GenerateDerivedKeysFromSessionKey() {
|
||||
&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");
|
||||
DeriveKeys(&session_key[0], mac_context, enc_context);
|
||||
}
|
||||
|
||||
void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
||||
@@ -237,7 +264,8 @@ void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
||||
&signature_[0], signature_.size(),
|
||||
encrypted_license().mac_key_iv,
|
||||
encrypted_license().mac_keys, num_keys_,
|
||||
key_array_, pst_ptr, pst.length(), NULL));
|
||||
key_array_, pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
// 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,
|
||||
@@ -247,11 +275,114 @@ void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||
&signature_[0], signature_.size(), NULL, NULL,
|
||||
num_keys_, key_array_, pst_ptr, pst.length(), NULL));
|
||||
num_keys_, key_array_, pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_ContentLicense));
|
||||
}
|
||||
VerifyTestKeys();
|
||||
}
|
||||
|
||||
void Session::LoadEnitlementTestKeys(const std::string& pst,
|
||||
bool new_mac_keys,
|
||||
OEMCryptoResult expected_sts) {
|
||||
uint8_t* pst_ptr = NULL;
|
||||
if (pst.length() > 0) {
|
||||
pst_ptr = encrypted_license().pst;
|
||||
}
|
||||
if (new_mac_keys) {
|
||||
ASSERT_EQ(expected_sts,
|
||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||
&signature_[0], signature_.size(),
|
||||
encrypted_license().mac_key_iv,
|
||||
encrypted_license().mac_keys, num_keys_,
|
||||
key_array_, pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_EntitlementLicense));
|
||||
// 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(
|
||||
expected_sts,
|
||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||
&signature_[0], signature_.size(), NULL, NULL,
|
||||
num_keys_, key_array_, pst_ptr, pst.length(), NULL,
|
||||
OEMCrypto_EntitlementLicense));
|
||||
}
|
||||
}
|
||||
|
||||
void Session::FillEntitledKeyArray() {
|
||||
has_entitlement_license_ = true;
|
||||
for (size_t i = 0; i < num_keys_; ++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_length =
|
||||
key_array_[i].key_id_length;
|
||||
|
||||
EXPECT_EQ(
|
||||
1, GetRandBytes(key_data->content_key_id,
|
||||
sizeof(key_data->content_key_id)));
|
||||
entitled_key_array_[i].content_key_id = key_data->content_key_id;
|
||||
entitled_key_array_[i].content_key_id_length =
|
||||
sizeof(key_data->content_key_id);
|
||||
|
||||
EXPECT_EQ(
|
||||
1, GetRandBytes(key_data->content_key_data,
|
||||
sizeof(key_data->content_key_data)));
|
||||
entitled_key_array_[i].content_key_data = key_data->content_key_data;
|
||||
entitled_key_array_[i].content_key_data_length =
|
||||
sizeof(key_data->content_key_data);
|
||||
|
||||
EXPECT_EQ(
|
||||
1, GetRandBytes(entitled_key_data_[i].content_key_data_iv,
|
||||
sizeof(entitled_key_data_[i].content_key_data_iv)));
|
||||
entitled_key_array_[i].content_key_data_iv = key_data->content_key_data_iv;
|
||||
}
|
||||
}
|
||||
|
||||
void Session::LoadEntitledContentKeys(OEMCryptoResult expected_sts) {
|
||||
// Create a copy of the stored |entitled_key_array_|.
|
||||
std::vector<OEMCrypto_EntitledContentKeyObject> encrypted_entitled_key_array;
|
||||
encrypted_entitled_key_array.resize(num_keys_);
|
||||
memcpy(&encrypted_entitled_key_array[0], &entitled_key_array_[0],
|
||||
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) {
|
||||
// Load the entitlement key from |key_array_|.
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&key_array_[i].key_data[0], 256, &aes_key);
|
||||
encrypted_content_keys[i].resize(
|
||||
encrypted_entitled_key_array[i].content_key_data_length);
|
||||
|
||||
// Encrypt the content key with the entitlement key.
|
||||
uint8_t iv[16];
|
||||
memcpy(&iv[0], &encrypted_entitled_key_array[i].content_key_data[0], 16);
|
||||
AES_cbc_encrypt(
|
||||
&entitled_key_array_[i].content_key_data[0],
|
||||
const_cast<uint8_t*>(
|
||||
&encrypted_entitled_key_array[i].content_key_data[0]),
|
||||
encrypted_entitled_key_array[i].content_key_data_length,
|
||||
&aes_key, iv, AES_ENCRYPT);
|
||||
|
||||
// Set the |encrypted_entitled_key_array| to point to the encrypted copy
|
||||
// of the content key.
|
||||
encrypted_entitled_key_array[i].content_key_data =
|
||||
encrypted_content_keys[i].data();
|
||||
}
|
||||
ASSERT_EQ(expected_sts,
|
||||
OEMCrypto_LoadEntitledContentKeys(
|
||||
session_id(), num_keys_, &encrypted_entitled_key_array[0]));
|
||||
if (expected_sts != OEMCrypto_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
VerifyEntitlementTestKeys();
|
||||
}
|
||||
|
||||
void Session::VerifyTestKeys() {
|
||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||
KeyControlBlock block;
|
||||
@@ -274,6 +405,29 @@ void Session::VerifyTestKeys() {
|
||||
}
|
||||
}
|
||||
|
||||
void Session::VerifyEntitlementTestKeys() {
|
||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||
KeyControlBlock block;
|
||||
size_t size = sizeof(block);
|
||||
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
|
||||
session_id(), entitled_key_array_[i].content_key_id,
|
||||
entitled_key_array_[i].content_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
|
||||
@@ -329,7 +483,57 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
|
||||
sizeof(license_.keys[i].key_iv)));
|
||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
|
||||
sizeof(license_.keys[i].control_iv)));
|
||||
if (global_features.api_version == 13) {
|
||||
if (global_features.api_version == 14) {
|
||||
// For version 14, we require OEMCrypto to handle kc14 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc14", 4);
|
||||
} else if (global_features.api_version == 13) {
|
||||
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc13", 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_mock::kControlSecurityPatchLevelMask) {
|
||||
// For versions before 12, we require the special key control block only
|
||||
// when there are newer features present.
|
||||
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()));
|
||||
pst_ = pst;
|
||||
}
|
||||
|
||||
void Session::FillSimpleEntitlementMessage(
|
||||
uint32_t duration, uint32_t control, uint32_t nonce,
|
||||
const std::string& pst) {
|
||||
EXPECT_EQ(
|
||||
1, GetRandBytes(license_.mac_key_iv, sizeof(license_.mac_key_iv)));
|
||||
EXPECT_EQ(1, GetRandBytes(license_.mac_keys, sizeof(license_.mac_keys)));
|
||||
for (unsigned int i = 0; i < num_keys_; 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(1, GetRandBytes(license_.keys[i].key_data,
|
||||
sizeof(license_.keys[i].key_data)));
|
||||
license_.keys[i].key_data_length = wvcdm::KEY_SIZE * 2; // AES-256 keys
|
||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].key_iv,
|
||||
sizeof(license_.keys[i].key_iv)));
|
||||
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
|
||||
sizeof(license_.keys[i].control_iv)));
|
||||
if (global_features.api_version == 14) {
|
||||
// For version 13, we require OEMCrypto to handle kc14 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc14", 4);
|
||||
} else if (global_features.api_version == 13) {
|
||||
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
|
||||
memcpy(license_.keys[i].control.verification, "kc13", 4);
|
||||
} else if (global_features.api_version == 12) {
|
||||
@@ -362,7 +566,10 @@ void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
||||
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);
|
||||
if (global_features.api_version == 13) {
|
||||
if (global_features.api_version == 14) {
|
||||
// For version 14, we require OEMCrypto to handle kc14 for all licenses.
|
||||
memcpy(encrypted_license().keys[i].control.verification, "kc14", 4);
|
||||
} else if (global_features.api_version == 13) {
|
||||
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
|
||||
memcpy(encrypted_license().keys[i].control.verification, "kc13", 4);
|
||||
} else if (global_features.api_version == 12) {
|
||||
@@ -389,9 +596,10 @@ void Session::EncryptAndSign() {
|
||||
AES_cbc_encrypt(&license_.mac_keys[0], &encrypted_license().mac_keys[0],
|
||||
2 * wvcdm::MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||
|
||||
int key_size = has_entitlement_license() ? 256 : 128;
|
||||
for (unsigned int i = 0; i < num_keys_; 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_set_encrypt_key(&license_.keys[i].key_data[0], key_size, &aes_key);
|
||||
AES_cbc_encrypt(
|
||||
reinterpret_cast<const uint8_t*>(&license_.keys[i].control),
|
||||
reinterpret_cast<uint8_t*>(&encrypted_license().keys[i].control),
|
||||
@@ -474,7 +682,6 @@ void Session::FillKeyArray(const MessageData& data,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,7 +731,8 @@ void Session::TestDecryptCTR(bool select_key_first,
|
||||
if (select_key_first) {
|
||||
// Select the key (from FillSimpleMessage)
|
||||
sts = OEMCrypto_SelectKey(session_id(), license_.keys[key_index].key_id,
|
||||
license_.keys[key_index].key_id_length);
|
||||
license_.keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
@@ -588,7 +796,8 @@ void Session::TestSelectExpired(unsigned int key_index) {
|
||||
if (global_features.api_version >= 13) {
|
||||
OEMCryptoResult status =
|
||||
OEMCrypto_SelectKey(session_id(), license().keys[key_index].key_id,
|
||||
license().keys[key_index].key_id_length);
|
||||
license().keys[key_index].key_id_length,
|
||||
OEMCrypto_CipherMode_CTR);
|
||||
// It is OK for SelectKey to succeed with an expired key, but if there is
|
||||
// an error, it must be OEMCrypto_ERROR_KEY_EXIRED.
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
@@ -610,43 +819,30 @@ void Session::LoadOEMCert(bool verify_cert) {
|
||||
OEMCrypto_GetOEMPublicCertificate(session_id(), &public_cert[0],
|
||||
&public_cert_length));
|
||||
|
||||
// Load the certificate chain into an OpenSSL X509 Stack
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
const openssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
||||
// Load the certificate chain into a BoringSSL X509 Stack
|
||||
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
||||
sk_X509_new_null());
|
||||
ASSERT_TRUE(x509_stack.NotNull()) << "Unable to allocate X509 stack.";
|
||||
|
||||
CBS pkcs7;
|
||||
CBS_init(&pkcs7, public_cert.data(), public_cert.size());
|
||||
if (!PKCS7_get_certificates(x509_stack.get(), &pkcs7)) {
|
||||
dump_openssl_error();
|
||||
dump_boringssl_error();
|
||||
FAIL() << "Unable to deserialize certificate chain.";
|
||||
}
|
||||
|
||||
STACK_OF(X509)* certs = x509_stack.get();
|
||||
#else
|
||||
// load the cert into rsa_key_.
|
||||
openssl_ptr<BIO, BIO_vfree> bio(
|
||||
BIO_new_mem_buf(&public_cert[0], public_cert_length));
|
||||
ASSERT_TRUE(bio.NotNull());
|
||||
openssl_ptr<PKCS7, PKCS7_free> cert(
|
||||
d2i_PKCS7_bio(bio.get(), NULL));
|
||||
ASSERT_TRUE(cert.NotNull());
|
||||
|
||||
EXPECT_EQ(OBJ_obj2nid(cert->type), NID_pkcs7_signed);
|
||||
STACK_OF(X509)* certs = cert->d.sign->cert;
|
||||
#endif
|
||||
|
||||
// Load the public cert's key into public_rsa_ and verify, if requested
|
||||
for (X509Count i = 0; certs && i < sk_X509_num(certs); i++) {
|
||||
for (size_t i = 0; certs && i < sk_X509_num(certs); i++) {
|
||||
X509* x509_cert = sk_X509_value(certs, i);
|
||||
openssl_ptr<EVP_PKEY, EVP_PKEY_free> pubkey(X509_get_pubkey(x509_cert));
|
||||
boringssl_ptr<EVP_PKEY, EVP_PKEY_free> pubkey(X509_get_pubkey(x509_cert));
|
||||
ASSERT_TRUE(pubkey.NotNull());
|
||||
if (i == 0) {
|
||||
public_rsa_ = EVP_PKEY_get1_RSA(pubkey.get());
|
||||
if (!public_rsa_) {
|
||||
cout << "d2i_RSAPrivateKey failed.\n";
|
||||
dump_openssl_error();
|
||||
dump_boringssl_error();
|
||||
ASSERT_TRUE(NULL != public_rsa_);
|
||||
}
|
||||
}
|
||||
@@ -656,9 +852,9 @@ void Session::LoadOEMCert(bool verify_cert) {
|
||||
X509_NAME* name = X509_get_subject_name(x509_cert);
|
||||
printf(" OEM Certificate Name: %s\n",
|
||||
X509_NAME_oneline(name, &buffer[0], buffer.size()));
|
||||
openssl_ptr<X509_STORE, X509_STORE_free> store(X509_STORE_new());
|
||||
boringssl_ptr<X509_STORE, X509_STORE_free> store(X509_STORE_new());
|
||||
ASSERT_TRUE(store.NotNull());
|
||||
openssl_ptr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
|
||||
boringssl_ptr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
|
||||
X509_STORE_CTX_new());
|
||||
ASSERT_TRUE(store_ctx.NotNull());
|
||||
|
||||
@@ -667,23 +863,13 @@ void Session::LoadOEMCert(bool verify_cert) {
|
||||
// TODO(fredgc): Verify cert is signed by Google.
|
||||
|
||||
int result = X509_verify_cert(store_ctx.get());
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
ASSERT_GE(0, result) << " OEM Cert not valid. " <<
|
||||
X509_verify_cert_error_string(store_ctx->error);
|
||||
#else
|
||||
ASSERT_GE(0, result) << " OEM Cert not valid. " <<
|
||||
X509_verify_cert_error_string(
|
||||
X509_STORE_CTX_get_error(store_ctx.get()));
|
||||
#endif
|
||||
if (result == 0) {
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
printf("Cert not verified: %s.\n",
|
||||
X509_verify_cert_error_string(store_ctx->error));
|
||||
#else
|
||||
printf("Cert not verified: %s.\n",
|
||||
X509_verify_cert_error_string(
|
||||
X509_STORE_CTX_get_error(store_ctx.get())));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -767,32 +953,32 @@ void Session::RewrapRSAKey30(const struct RSAPrivateKeyMessage& encrypted,
|
||||
|
||||
void Session::PreparePublicKey(const uint8_t* rsa_key, size_t rsa_key_length) {
|
||||
if (rsa_key == NULL) {
|
||||
rsa_key = wvcdm_test_auth::kRsaPrivateKey_2048;
|
||||
rsa_key_length = wvcdm_test_auth::kRsaPrivateKeySize_2048;
|
||||
rsa_key = wvcdm_test_auth::kTestRSAPKCS8PrivateKeyInfo2_2048;
|
||||
rsa_key_length = wvcdm_test_auth::kTestRSAPKCS8PrivateKeyInfo2_2048_Size;
|
||||
}
|
||||
uint8_t* p = const_cast<uint8_t*>(rsa_key);
|
||||
openssl_ptr<BIO, BIO_vfree> bio(BIO_new_mem_buf(p, rsa_key_length));
|
||||
boringssl_ptr<BIO, BIO_vfree> bio(BIO_new_mem_buf(p, rsa_key_length));
|
||||
ASSERT_TRUE(bio.NotNull());
|
||||
openssl_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8_pki(
|
||||
boringssl_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8_pki(
|
||||
d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL));
|
||||
ASSERT_TRUE(pkcs8_pki.NotNull());
|
||||
openssl_ptr<EVP_PKEY, EVP_PKEY_free> evp(EVP_PKCS82PKEY(pkcs8_pki.get()));
|
||||
boringssl_ptr<EVP_PKEY, EVP_PKEY_free> evp(EVP_PKCS82PKEY(pkcs8_pki.get()));
|
||||
ASSERT_TRUE(evp.NotNull());
|
||||
if (public_rsa_) RSA_free(public_rsa_);
|
||||
public_rsa_ = EVP_PKEY_get1_RSA(evp.get());
|
||||
if (!public_rsa_) {
|
||||
cout << "d2i_RSAPrivateKey failed. ";
|
||||
dump_openssl_error();
|
||||
dump_boringssl_error();
|
||||
FAIL() << "Could not parse public RSA key.";
|
||||
}
|
||||
switch (RSA_check_key(public_rsa_)) {
|
||||
case 1: // valid.
|
||||
return;
|
||||
case 0: // not valid.
|
||||
dump_openssl_error();
|
||||
dump_boringssl_error();
|
||||
FAIL() << "[rsa key not valid] ";
|
||||
default: // -1 == check failed.
|
||||
dump_openssl_error();
|
||||
dump_boringssl_error();
|
||||
FAIL() << "[error checking rsa key] ";
|
||||
}
|
||||
}
|
||||
@@ -801,13 +987,9 @@ bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
size_t signature_length) {
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
EVP_MD_CTX md_ctx_struct;
|
||||
EVP_MD_CTX* md_ctx = &md_ctx_struct;
|
||||
EVP_MD_CTX_init(md_ctx);
|
||||
#else
|
||||
EVP_MD_CTX* md_ctx = EVP_MD_CTX_new();
|
||||
#endif
|
||||
EVP_PKEY_CTX* pkey_ctx = NULL;
|
||||
|
||||
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, EVP_sha1(), NULL /* no ENGINE */,
|
||||
@@ -845,20 +1027,12 @@ bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
goto err;
|
||||
}
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
EVP_MD_CTX_cleanup(md_ctx);
|
||||
#else
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
#endif
|
||||
return true;
|
||||
|
||||
err:
|
||||
dump_openssl_error();
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
dump_boringssl_error();
|
||||
EVP_MD_CTX_cleanup(md_ctx);
|
||||
#else
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -874,7 +1048,7 @@ void Session::VerifyRSASignature(const vector<uint8_t>& message,
|
||||
<< RSA_size(public_rsa_) << "\n";
|
||||
|
||||
if (padding_scheme == kSign_RSASSA_PSS) {
|
||||
openssl_ptr<EVP_PKEY, EVP_PKEY_free> pkey(EVP_PKEY_new());
|
||||
boringssl_ptr<EVP_PKEY, EVP_PKEY_free> pkey(EVP_PKEY_new());
|
||||
ASSERT_EQ(1, EVP_PKEY_set1_RSA(pkey.get(), public_rsa_));
|
||||
|
||||
const bool ok = VerifyPSSSignature(pkey.get(), &message[0], message.size(),
|
||||
@@ -909,7 +1083,7 @@ bool Session::GenerateRSASessionKey(vector<uint8_t>* session_key,
|
||||
int size = static_cast<int>(RSA_size(public_rsa_));
|
||||
if (status != size) {
|
||||
cout << "GenerateRSASessionKey error encrypting session key.\n";
|
||||
dump_openssl_error();
|
||||
dump_boringssl_error();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -1022,15 +1196,17 @@ void Session::VerifyPST(const Test_PST_Report& expected) {
|
||||
char* pst_ptr = reinterpret_cast<char *>(computed.pst());
|
||||
std::string computed_pst(pst_ptr, pst_ptr + computed.pst_length());
|
||||
ASSERT_EQ(expected.pst, computed_pst);
|
||||
EXPECT_NEAR(expected.seconds_since_license_received,
|
||||
time_t now = time(NULL);
|
||||
int64_t age = now - expected.time_created; // How old is this report.
|
||||
EXPECT_NEAR(expected.seconds_since_license_received + age,
|
||||
computed.seconds_since_license_received(),
|
||||
kTimeTolerance);
|
||||
// Decrypt times only valid on licenses that have been active.
|
||||
if (expected.status == kActive || expected.status == kInactiveUsed) {
|
||||
EXPECT_NEAR(expected.seconds_since_first_decrypt,
|
||||
EXPECT_NEAR(expected.seconds_since_first_decrypt + age,
|
||||
computed.seconds_since_first_decrypt(),
|
||||
kUsageTableTimeTolerance);
|
||||
EXPECT_NEAR(expected.seconds_since_last_decrypt,
|
||||
EXPECT_NEAR(expected.seconds_since_last_decrypt + age,
|
||||
computed.seconds_since_last_decrypt(),
|
||||
kUsageTableTimeTolerance);
|
||||
}
|
||||
@@ -1041,7 +1217,7 @@ void Session::VerifyPST(const Test_PST_Report& expected) {
|
||||
pst_report_buffer_.size() - SHA_DIGEST_LENGTH,
|
||||
&signature[0], &md_len)) {
|
||||
cout << "Error computing HMAC.\n";
|
||||
dump_openssl_error();
|
||||
dump_boringssl_error();
|
||||
}
|
||||
EXPECT_EQ(0, memcmp(computed.signature(), &signature[0],
|
||||
SHA_DIGEST_LENGTH));
|
||||
|
||||
Reference in New Issue
Block a user