Buffer Size Unit Tests
Merge from widevine repo of http://go/wvgerrit/21260 This CL adds some oemcrypto unit tests for various buffer sizes, as described in b/28887904 and the OEMCrypto v12 specification. Encryption and Decryption buffers can be 100k large. License request and response messages can be 8k. A provider session token (pst) can be at most 255 bytes long. I also passed the code through clang-format. b/28887904 Change-Id: Ia3e317c0f6466e663461e66b610c9a98a90efb0a
This commit is contained in:
@@ -76,8 +76,14 @@ Session::Session()
|
|||||||
mac_key_client_(wvcdm::MAC_KEY_SIZE),
|
mac_key_client_(wvcdm::MAC_KEY_SIZE),
|
||||||
enc_key_(wvcdm::KEY_SIZE),
|
enc_key_(wvcdm::KEY_SIZE),
|
||||||
public_rsa_(0),
|
public_rsa_(0),
|
||||||
num_keys_(4) {} // Most tests only use 4 keys.
|
message_size_(sizeof(MessageData)),
|
||||||
// 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.
|
||||||
|
// Stripe the padded message.
|
||||||
|
for (int i = 0; i < sizeof(padded_message_.padding); i++) {
|
||||||
|
padded_message_.padding[i] = i % 0x100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Session::~Session() {
|
Session::~Session() {
|
||||||
if (!forced_session_id_ && open_) close();
|
if (!forced_session_id_ && open_) close();
|
||||||
@@ -194,25 +200,24 @@ void Session::GenerateTestSessionKeys() {
|
|||||||
void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
|
||||||
uint8_t* pst_ptr = NULL;
|
uint8_t* pst_ptr = NULL;
|
||||||
if (pst.length() > 0) {
|
if (pst.length() > 0) {
|
||||||
pst_ptr = encrypted_license_.pst;
|
pst_ptr = encrypted_license().pst;
|
||||||
}
|
}
|
||||||
if (new_mac_keys) {
|
if (new_mac_keys) {
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_LoadKeys(
|
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||||
session_id(), message_ptr(), sizeof(MessageData),
|
&signature_[0], signature_.size(),
|
||||||
&signature_[0], signature_.size(),
|
encrypted_license().mac_key_iv,
|
||||||
encrypted_license_.mac_key_iv, encrypted_license_.mac_keys,
|
encrypted_license().mac_keys, num_keys_,
|
||||||
num_keys_, key_array_, pst_ptr, pst.length()));
|
key_array_, pst_ptr, pst.length()));
|
||||||
// Update new generated keys.
|
// Update new generated keys.
|
||||||
memcpy(&mac_key_server_[0], license_.mac_keys, wvcdm::MAC_KEY_SIZE);
|
memcpy(&mac_key_server_[0], license_.mac_keys, wvcdm::MAC_KEY_SIZE);
|
||||||
memcpy(&mac_key_client_[0], license_.mac_keys + wvcdm::MAC_KEY_SIZE,
|
memcpy(&mac_key_client_[0], license_.mac_keys + wvcdm::MAC_KEY_SIZE,
|
||||||
wvcdm::MAC_KEY_SIZE);
|
wvcdm::MAC_KEY_SIZE);
|
||||||
} else {
|
} else {
|
||||||
ASSERT_EQ(
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_SUCCESS,
|
OEMCrypto_LoadKeys(session_id(), message_ptr(), message_size_,
|
||||||
OEMCrypto_LoadKeys(session_id(), message_ptr(), sizeof(MessageData),
|
&signature_[0], signature_.size(), NULL, NULL,
|
||||||
&signature_[0], signature_.size(), NULL, NULL,
|
num_keys_, key_array_, pst_ptr, pst.length()));
|
||||||
num_keys_, key_array_, pst_ptr, pst.length()));
|
|
||||||
}
|
}
|
||||||
VerifyTestKeys();
|
VerifyTestKeys();
|
||||||
}
|
}
|
||||||
@@ -222,8 +227,8 @@ void Session::VerifyTestKeys() {
|
|||||||
KeyControlBlock block;
|
KeyControlBlock block;
|
||||||
size_t size = sizeof(block);
|
size_t size = sizeof(block);
|
||||||
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
|
OEMCryptoResult sts = OEMCrypto_QueryKeyControl(
|
||||||
session_id(), license_.keys[i].key_id, license_.keys[i].key_id_length,
|
session_id(), license_.keys[i].key_id, license_.keys[i].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);
|
||||||
ASSERT_EQ(sizeof(block), size);
|
ASSERT_EQ(sizeof(block), size);
|
||||||
@@ -237,17 +242,17 @@ void Session::VerifyTestKeys() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::RefreshTestKeys(const size_t key_count,
|
void Session::RefreshTestKeys(const size_t key_count, uint32_t control_bits,
|
||||||
uint32_t control_bits, uint32_t nonce,
|
uint32_t nonce, OEMCryptoResult expected_result) {
|
||||||
OEMCryptoResult expected_result) {
|
|
||||||
// Note: we store the message in encrypted_license_, but the refresh key
|
// Note: we store the message in encrypted_license_, but the refresh key
|
||||||
// message is not actually encrypted. It is, however, signed.
|
// message is not actually encrypted. It is, however, signed.
|
||||||
FillRefreshMessage(key_count, control_bits, nonce);
|
FillRefreshMessage(key_count, control_bits, nonce);
|
||||||
ServerSignMessage(encrypted_license_, &signature_);
|
ServerSignBuffer(reinterpret_cast<const uint8_t*>(&padded_message_),
|
||||||
|
message_size_, &signature_);
|
||||||
OEMCrypto_KeyRefreshObject key_array[key_count];
|
OEMCrypto_KeyRefreshObject key_array[key_count];
|
||||||
FillRefreshArray(key_array, key_count);
|
FillRefreshArray(key_array, key_count);
|
||||||
OEMCryptoResult sts = OEMCrypto_RefreshKeys(
|
OEMCryptoResult sts = OEMCrypto_RefreshKeys(
|
||||||
session_id(), message_ptr(), sizeof(MessageData), &signature_[0],
|
session_id(), message_ptr(), message_size_, &signature_[0],
|
||||||
signature_.size(), key_count, key_array);
|
signature_.size(), key_count, key_array);
|
||||||
ASSERT_EQ(expected_result, sts);
|
ASSERT_EQ(expected_result, sts);
|
||||||
|
|
||||||
@@ -272,9 +277,9 @@ void Session::SetKeyId(int index, const string& key_id) {
|
|||||||
|
|
||||||
void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
|
void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
|
||||||
uint32_t nonce, const std::string& pst) {
|
uint32_t nonce, const std::string& pst) {
|
||||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
EXPECT_EQ(
|
||||||
OEMCrypto_GetRandom(license_.mac_key_iv,
|
OEMCrypto_SUCCESS,
|
||||||
sizeof(license_.mac_key_iv)));
|
OEMCrypto_GetRandom(license_.mac_key_iv, sizeof(license_.mac_key_iv)));
|
||||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_GetRandom(license_.mac_keys, sizeof(license_.mac_keys)));
|
OEMCrypto_GetRandom(license_.mac_keys, sizeof(license_.mac_keys)));
|
||||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||||
@@ -312,24 +317,24 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
|
|||||||
void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
|
||||||
uint32_t nonce) {
|
uint32_t nonce) {
|
||||||
for (unsigned int i = 0; i < key_count; i++) {
|
for (unsigned int i = 0; i < key_count; i++) {
|
||||||
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);
|
||||||
memcpy(encrypted_license_.keys[i].control.verification, "kctl", 4);
|
memcpy(encrypted_license().keys[i].control.verification, "kctl", 4);
|
||||||
encrypted_license_.keys[i].control.duration = htonl(kLongDuration);
|
encrypted_license().keys[i].control.duration = htonl(kLongDuration);
|
||||||
encrypted_license_.keys[i].control.nonce = htonl(nonce);
|
encrypted_license().keys[i].control.nonce = htonl(nonce);
|
||||||
encrypted_license_.keys[i].control.control_bits = htonl(control_bits);
|
encrypted_license().keys[i].control.control_bits = htonl(control_bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::EncryptAndSign() {
|
void Session::EncryptAndSign() {
|
||||||
encrypted_license_ = license_;
|
encrypted_license() = license_;
|
||||||
|
|
||||||
uint8_t iv_buffer[16];
|
uint8_t iv_buffer[16];
|
||||||
memcpy(iv_buffer, &license_.mac_key_iv[0], wvcdm::KEY_IV_SIZE);
|
memcpy(iv_buffer, &license_.mac_key_iv[0], wvcdm::KEY_IV_SIZE);
|
||||||
AES_KEY aes_key;
|
AES_KEY aes_key;
|
||||||
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
||||||
AES_cbc_encrypt(&license_.mac_keys[0], &encrypted_license_.mac_keys[0],
|
AES_cbc_encrypt(&license_.mac_keys[0], &encrypted_license().mac_keys[0],
|
||||||
2 * wvcdm::MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
2 * wvcdm::MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < num_keys_; i++) {
|
for (unsigned int i = 0; i < num_keys_; i++) {
|
||||||
@@ -337,19 +342,19 @@ void Session::EncryptAndSign() {
|
|||||||
AES_set_encrypt_key(&license_.keys[i].key_data[0], 128, &aes_key);
|
AES_set_encrypt_key(&license_.keys[i].key_data[0], 128, &aes_key);
|
||||||
AES_cbc_encrypt(
|
AES_cbc_encrypt(
|
||||||
reinterpret_cast<const uint8_t*>(&license_.keys[i].control),
|
reinterpret_cast<const uint8_t*>(&license_.keys[i].control),
|
||||||
reinterpret_cast<uint8_t*>(&encrypted_license_.keys[i].control),
|
reinterpret_cast<uint8_t*>(&encrypted_license().keys[i].control),
|
||||||
wvcdm::KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
wvcdm::KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||||
|
|
||||||
memcpy(iv_buffer, &license_.keys[i].key_iv[0], wvcdm::KEY_IV_SIZE);
|
memcpy(iv_buffer, &license_.keys[i].key_iv[0], wvcdm::KEY_IV_SIZE);
|
||||||
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
||||||
AES_cbc_encrypt(&license_.keys[i].key_data[0],
|
AES_cbc_encrypt(
|
||||||
&encrypted_license_.keys[i].key_data[0],
|
&license_.keys[i].key_data[0], &encrypted_license().keys[i].key_data[0],
|
||||||
license_.keys[i].key_data_length, &aes_key, iv_buffer,
|
license_.keys[i].key_data_length, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||||
AES_ENCRYPT);
|
|
||||||
}
|
}
|
||||||
memcpy(encrypted_license_.pst, license_.pst, sizeof(license_.pst));
|
memcpy(encrypted_license().pst, license_.pst, sizeof(license_.pst));
|
||||||
ServerSignMessage(encrypted_license_, &signature_);
|
ServerSignBuffer(reinterpret_cast<const uint8_t*>(&padded_message_),
|
||||||
FillKeyArray(encrypted_license_, key_array_);
|
message_size_, &signature_);
|
||||||
|
FillKeyArray(encrypted_license(), key_array_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::EncryptMessage(RSAPrivateKeyMessage* data,
|
void Session::EncryptMessage(RSAPrivateKeyMessage* data,
|
||||||
@@ -364,30 +369,18 @@ void Session::EncryptMessage(RSAPrivateKeyMessage* data,
|
|||||||
AES_KEY aes_key;
|
AES_KEY aes_key;
|
||||||
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
|
||||||
AES_cbc_encrypt(&data->rsa_key[0], &encrypted->rsa_key[0],
|
AES_cbc_encrypt(&data->rsa_key[0], &encrypted->rsa_key[0],
|
||||||
encrypted->rsa_key_length, &aes_key, iv_buffer,
|
encrypted->rsa_key_length, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||||
AES_ENCRYPT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
void Session::ServerSignBuffer(const uint8_t* data, size_t data_length,
|
||||||
void Session::ServerSignMessage(const T& data,
|
std::vector<uint8_t>* signature) {
|
||||||
std::vector<uint8_t>* signature) {
|
ASSERT_LE(data_length, kMaxMessageSize);
|
||||||
signature->assign(SHA256_DIGEST_LENGTH, 0);
|
signature->assign(SHA256_DIGEST_LENGTH, 0);
|
||||||
unsigned int md_len = SHA256_DIGEST_LENGTH;
|
unsigned int md_len = SHA256_DIGEST_LENGTH;
|
||||||
HMAC(EVP_sha256(), &mac_key_server_[0], mac_key_server_.size(),
|
HMAC(EVP_sha256(), &mac_key_server_[0], mac_key_server_.size(), data,
|
||||||
reinterpret_cast<const uint8_t*>(&data), sizeof(data),
|
data_length, &(signature->front()), &md_len);
|
||||||
&(signature->front()), &md_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template
|
|
||||||
void Session::ServerSignMessage<MessageData>(
|
|
||||||
const MessageData& data,
|
|
||||||
std::vector<uint8_t>* signature);
|
|
||||||
|
|
||||||
template
|
|
||||||
void Session::ServerSignMessage<RSAPrivateKeyMessage>(
|
|
||||||
const RSAPrivateKeyMessage& data,
|
|
||||||
std::vector<uint8_t>* signature);
|
|
||||||
|
|
||||||
void Session::ClientSignMessage(const vector<uint8_t>& data,
|
void Session::ClientSignMessage(const vector<uint8_t>& data,
|
||||||
std::vector<uint8_t>* signature) {
|
std::vector<uint8_t>* signature) {
|
||||||
signature->assign(SHA256_DIGEST_LENGTH, 0);
|
signature->assign(SHA256_DIGEST_LENGTH, 0);
|
||||||
@@ -415,21 +408,21 @@ void Session::FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
|
|||||||
size_t key_count) {
|
size_t key_count) {
|
||||||
for (size_t i = 0; i < key_count; i++) {
|
for (size_t i = 0; i < key_count; i++) {
|
||||||
if (key_count > 1) {
|
if (key_count > 1) {
|
||||||
key_array[i].key_id = encrypted_license_.keys[i].key_id;
|
key_array[i].key_id = encrypted_license().keys[i].key_id;
|
||||||
key_array[i].key_id_length = encrypted_license_.keys[i].key_id_length;
|
key_array[i].key_id_length = encrypted_license().keys[i].key_id_length;
|
||||||
} else {
|
} else {
|
||||||
key_array[i].key_id = NULL;
|
key_array[i].key_id = NULL;
|
||||||
key_array[i].key_id_length = 0;
|
key_array[i].key_id_length = 0;
|
||||||
}
|
}
|
||||||
key_array[i].key_control_iv = NULL;
|
key_array[i].key_control_iv = NULL;
|
||||||
key_array[i].key_control =
|
key_array[i].key_control =
|
||||||
reinterpret_cast<const uint8_t*>(&encrypted_license_.keys[i].control);
|
reinterpret_cast<const uint8_t*>(&encrypted_license().keys[i].control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::EncryptCTR(
|
void Session::EncryptCTR(const vector<uint8_t>& in_buffer, const uint8_t* key,
|
||||||
const vector<uint8_t>& in_buffer, const uint8_t *key,
|
const uint8_t* starting_iv,
|
||||||
const uint8_t* starting_iv, vector<uint8_t>* out_buffer) {
|
vector<uint8_t>* out_buffer) {
|
||||||
ASSERT_NE(static_cast<void*>(NULL), key);
|
ASSERT_NE(static_cast<void*>(NULL), key);
|
||||||
ASSERT_NE(static_cast<void*>(NULL), starting_iv);
|
ASSERT_NE(static_cast<void*>(NULL), starting_iv);
|
||||||
ASSERT_NE(static_cast<void*>(NULL), out_buffer);
|
ASSERT_NE(static_cast<void*>(NULL), out_buffer);
|
||||||
@@ -452,8 +445,7 @@ void Session::EncryptCTR(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Session::TestDecryptCTR(bool select_key_first,
|
void Session::TestDecryptCTR(bool select_key_first,
|
||||||
OEMCryptoResult expected_result,
|
OEMCryptoResult expected_result, int key_index) {
|
||||||
int key_index) {
|
|
||||||
OEMCryptoResult sts;
|
OEMCryptoResult sts;
|
||||||
if (select_key_first) {
|
if (select_key_first) {
|
||||||
// Select the key (from FillSimpleMessage)
|
// Select the key (from FillSimpleMessage)
|
||||||
@@ -463,15 +455,16 @@ void Session::TestDecryptCTR(bool select_key_first,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector<uint8_t> unencryptedData(256);
|
vector<uint8_t> unencryptedData(256);
|
||||||
for(size_t i=0; i < unencryptedData.size(); i++) unencryptedData[i] = i % 256;
|
for (size_t i = 0; i < unencryptedData.size(); i++)
|
||||||
|
unencryptedData[i] = i % 256;
|
||||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_GetRandom(&unencryptedData[0], unencryptedData.size()));
|
OEMCrypto_GetRandom(&unencryptedData[0], unencryptedData.size()));
|
||||||
vector<uint8_t> encryptionIv(wvcdm::KEY_IV_SIZE);
|
vector<uint8_t> encryptionIv(wvcdm::KEY_IV_SIZE);
|
||||||
EXPECT_EQ(OEMCrypto_SUCCESS,
|
EXPECT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_GetRandom(&encryptionIv[0], wvcdm::KEY_IV_SIZE));
|
OEMCrypto_GetRandom(&encryptionIv[0], wvcdm::KEY_IV_SIZE));
|
||||||
vector<uint8_t> encryptedData(unencryptedData.size());
|
vector<uint8_t> encryptedData(unencryptedData.size());
|
||||||
EncryptCTR(unencryptedData, license_.keys[key_index].key_data, &encryptionIv[0],
|
EncryptCTR(unencryptedData, license_.keys[key_index].key_data,
|
||||||
&encryptedData);
|
&encryptionIv[0], &encryptedData);
|
||||||
|
|
||||||
// Describe the output
|
// Describe the output
|
||||||
vector<uint8_t> outputBuffer(256);
|
vector<uint8_t> outputBuffer(256);
|
||||||
@@ -507,9 +500,11 @@ void Session::TestDecryptCTR(bool select_key_first,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::MakeRSACertificate(
|
void Session::MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted,
|
||||||
struct RSAPrivateKeyMessage* encrypted, std::vector<uint8_t>* signature,
|
size_t message_size,
|
||||||
uint32_t allowed_schemes, const vector<uint8_t>& rsa_key) {
|
std::vector<uint8_t>* signature,
|
||||||
|
uint32_t allowed_schemes,
|
||||||
|
const vector<uint8_t>& rsa_key) {
|
||||||
// Dummy context for testing signature generation.
|
// Dummy context for testing signature generation.
|
||||||
vector<uint8_t> context = wvcdm::a2b_hex(
|
vector<uint8_t> context = wvcdm::a2b_hex(
|
||||||
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
|
"0a4c08001248000000020000101907d9ffde13aa95c122678053362136bdf840"
|
||||||
@@ -555,28 +550,28 @@ void Session::MakeRSACertificate(
|
|||||||
message.nonce = nonce_;
|
message.nonce = nonce_;
|
||||||
|
|
||||||
EncryptMessage(&message, encrypted);
|
EncryptMessage(&message, encrypted);
|
||||||
ServerSignMessage(*encrypted, signature);
|
ServerSignBuffer(reinterpret_cast<const uint8_t*>(encrypted), message_size,
|
||||||
|
signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
|
void Session::RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
|
||||||
|
size_t message_size,
|
||||||
const std::vector<uint8_t>& signature,
|
const std::vector<uint8_t>& signature,
|
||||||
vector<uint8_t>* wrapped_key, bool force) {
|
vector<uint8_t>* wrapped_key, bool force) {
|
||||||
size_t wrapped_key_length = 0;
|
size_t wrapped_key_length = 0;
|
||||||
const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(&encrypted);
|
const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(&encrypted);
|
||||||
|
|
||||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||||
OEMCrypto_RewrapDeviceRSAKey(
|
OEMCrypto_RewrapDeviceRSAKey(
|
||||||
session_id(), message_ptr, sizeof(encrypted), &signature[0],
|
session_id(), message_ptr, message_size, &signature[0],
|
||||||
signature.size(), &encrypted.nonce, encrypted.rsa_key,
|
signature.size(), &encrypted.nonce, encrypted.rsa_key,
|
||||||
encrypted.rsa_key_length, encrypted.rsa_key_iv, NULL,
|
encrypted.rsa_key_length, encrypted.rsa_key_iv, NULL,
|
||||||
&wrapped_key_length));
|
&wrapped_key_length));
|
||||||
wrapped_key->clear();
|
wrapped_key->clear();
|
||||||
wrapped_key->assign(wrapped_key_length, 0);
|
wrapped_key->assign(wrapped_key_length, 0);
|
||||||
OEMCryptoResult sts = OEMCrypto_RewrapDeviceRSAKey(
|
OEMCryptoResult sts = OEMCrypto_RewrapDeviceRSAKey(
|
||||||
session_id(), message_ptr, sizeof(encrypted), &signature[0],
|
session_id(), message_ptr, message_size, &signature[0], signature.size(),
|
||||||
signature.size(), &encrypted.nonce, encrypted.rsa_key,
|
&encrypted.nonce, encrypted.rsa_key, encrypted.rsa_key_length,
|
||||||
encrypted.rsa_key_length, encrypted.rsa_key_iv, &(wrapped_key->front()),
|
encrypted.rsa_key_iv, &(wrapped_key->front()), &wrapped_key_length);
|
||||||
&wrapped_key_length);
|
|
||||||
if (force) {
|
if (force) {
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||||
}
|
}
|
||||||
@@ -585,8 +580,7 @@ void Session::RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::PreparePublicKey(const uint8_t* rsa_key,
|
void Session::PreparePublicKey(const uint8_t* rsa_key, size_t rsa_key_length) {
|
||||||
size_t rsa_key_length) {
|
|
||||||
if (rsa_key == NULL) {
|
if (rsa_key == NULL) {
|
||||||
rsa_key = kTestRSAPKCS8PrivateKeyInfo2_2048;
|
rsa_key = kTestRSAPKCS8PrivateKeyInfo2_2048;
|
||||||
rsa_key_length = sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048);
|
rsa_key_length = sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048);
|
||||||
@@ -610,23 +604,24 @@ void Session::PreparePublicKey(const uint8_t* rsa_key,
|
|||||||
ASSERT_TRUE(false);
|
ASSERT_TRUE(false);
|
||||||
}
|
}
|
||||||
switch (RSA_check_key(public_rsa_)) {
|
switch (RSA_check_key(public_rsa_)) {
|
||||||
case 1: // valid.
|
case 1: // valid.
|
||||||
ASSERT_TRUE(true);
|
ASSERT_TRUE(true);
|
||||||
return;
|
return;
|
||||||
case 0: // not valid.
|
case 0: // not valid.
|
||||||
cout << "[rsa key not valid] ";
|
cout << "[rsa key not valid] ";
|
||||||
dump_openssl_error();
|
dump_openssl_error();
|
||||||
ASSERT_TRUE(false);
|
ASSERT_TRUE(false);
|
||||||
default: // -1 == check failed.
|
default: // -1 == check failed.
|
||||||
cout << "[error checking rsa key] ";
|
cout << "[error checking rsa key] ";
|
||||||
dump_openssl_error();
|
dump_openssl_error();
|
||||||
ASSERT_TRUE(false);
|
ASSERT_TRUE(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Session::VerifyPSSSignature(
|
bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||||
EVP_PKEY* pkey, const uint8_t* message, size_t message_length,
|
size_t message_length,
|
||||||
const uint8_t* signature, size_t signature_length) {
|
const uint8_t* signature,
|
||||||
|
size_t signature_length) {
|
||||||
EVP_MD_CTX ctx;
|
EVP_MD_CTX ctx;
|
||||||
EVP_MD_CTX_init(&ctx);
|
EVP_MD_CTX_init(&ctx);
|
||||||
EVP_PKEY_CTX* pctx = NULL;
|
EVP_PKEY_CTX* pctx = NULL;
|
||||||
@@ -668,15 +663,16 @@ bool Session::VerifyPSSSignature(
|
|||||||
EVP_MD_CTX_cleanup(&ctx);
|
EVP_MD_CTX_cleanup(&ctx);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
dump_openssl_error();
|
dump_openssl_error();
|
||||||
EVP_MD_CTX_cleanup(&ctx);
|
EVP_MD_CTX_cleanup(&ctx);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::VerifyRSASignature(
|
void Session::VerifyRSASignature(const vector<uint8_t>& message,
|
||||||
const vector<uint8_t>& message, const uint8_t* signature,
|
const uint8_t* signature,
|
||||||
size_t signature_length, RSA_Padding_Scheme padding_scheme) {
|
size_t signature_length,
|
||||||
|
RSA_Padding_Scheme padding_scheme) {
|
||||||
EXPECT_TRUE(NULL != public_rsa_)
|
EXPECT_TRUE(NULL != public_rsa_)
|
||||||
<< "No public RSA key loaded in test code.\n";
|
<< "No public RSA key loaded in test code.\n";
|
||||||
EXPECT_EQ(static_cast<size_t>(RSA_size(public_rsa_)), signature_length)
|
EXPECT_EQ(static_cast<size_t>(RSA_size(public_rsa_)), signature_length)
|
||||||
@@ -726,8 +722,7 @@ bool Session::GenerateRSASessionKey(vector<uint8_t>* enc_session_key) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::InstallRSASessionTestKey(
|
void Session::InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key) {
|
||||||
const vector<uint8_t>& wrapped_rsa_key) {
|
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_LoadDeviceRSAKey(session_id(), &wrapped_rsa_key[0],
|
OEMCrypto_LoadDeviceRSAKey(session_id(), &wrapped_rsa_key[0],
|
||||||
wrapped_rsa_key.size()));
|
wrapped_rsa_key.size()));
|
||||||
@@ -749,8 +744,8 @@ void Session::DisallowDeriveKeys() {
|
|||||||
enc_context.size()));
|
enc_context.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::GenerateReport(
|
void Session::GenerateReport(const std::string& pst, bool expect_success,
|
||||||
const std::string& pst, bool expect_success, Session* other) {
|
Session* other) {
|
||||||
if (other) { // If other is specified, copy mac keys.
|
if (other) { // If other is specified, copy mac keys.
|
||||||
mac_key_server_ = other->mac_key_server_;
|
mac_key_server_ = other->mac_key_server_;
|
||||||
mac_key_client_ = other->mac_key_client_;
|
mac_key_client_ = other->mac_key_client_;
|
||||||
@@ -792,12 +787,13 @@ OEMCrypto_PST_Report* Session::pst_report() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Session::DeleteEntry(const std::string& pst) {
|
void Session::DeleteEntry(const std::string& pst) {
|
||||||
uint8_t* pst_ptr = encrypted_license_.pst;
|
uint8_t* pst_ptr = encrypted_license().pst;
|
||||||
memcpy(pst_ptr, pst.c_str(), min(sizeof(license_.pst), pst.length()));
|
memcpy(pst_ptr, pst.c_str(), min(sizeof(license_.pst), pst.length()));
|
||||||
ServerSignMessage(encrypted_license_, &signature_);
|
ServerSignBuffer(reinterpret_cast<const uint8_t*>(&padded_message_),
|
||||||
|
message_size_, &signature_);
|
||||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||||
OEMCrypto_DeleteUsageEntry(session_id(), pst_ptr, pst.length(),
|
OEMCrypto_DeleteUsageEntry(session_id(), pst_ptr, pst.length(),
|
||||||
message_ptr(), sizeof(MessageData),
|
message_ptr(), message_size_,
|
||||||
&signature_[0], signature_.size()));
|
&signature_[0], signature_.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,7 +804,13 @@ void Session::ForceDeleteEntry(const std::string& pst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* Session::message_ptr() {
|
const uint8_t* Session::message_ptr() {
|
||||||
return reinterpret_cast<const uint8_t*>(&encrypted_license_);
|
return reinterpret_cast<const uint8_t*>(&encrypted_license());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::set_message_size(size_t size) {
|
||||||
|
message_size_ = size;
|
||||||
|
ASSERT_GE(message_size_, sizeof(MessageData));
|
||||||
|
ASSERT_LE(message_size_, kMaxMessageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace wvoec
|
} // namespace wvoec
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ const size_t kTestKeyIdMaxLength = 16;
|
|||||||
const int kDefaultKeyIdLength = 16;
|
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 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];
|
||||||
@@ -86,7 +89,7 @@ struct MessageData {
|
|||||||
MessageKeyData keys[kMaxNumKeys];
|
MessageKeyData keys[kMaxNumKeys];
|
||||||
uint8_t mac_key_iv[wvcdm::KEY_IV_SIZE];
|
uint8_t mac_key_iv[wvcdm::KEY_IV_SIZE];
|
||||||
uint8_t mac_keys[2 * wvcdm::MAC_KEY_SIZE];
|
uint8_t mac_keys[2 * wvcdm::MAC_KEY_SIZE];
|
||||||
uint8_t pst[kTestKeyIdMaxLength];
|
uint8_t pst[kMaxPSTLength];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RSAPrivateKeyMessage {
|
struct RSAPrivateKeyMessage {
|
||||||
@@ -141,35 +144,34 @@ class Session {
|
|||||||
void EncryptAndSign();
|
void EncryptAndSign();
|
||||||
void EncryptMessage(RSAPrivateKeyMessage* data,
|
void EncryptMessage(RSAPrivateKeyMessage* data,
|
||||||
RSAPrivateKeyMessage* encrypted);
|
RSAPrivateKeyMessage* encrypted);
|
||||||
|
void ServerSignBuffer(const uint8_t* data, size_t data_length,
|
||||||
template <typename T>
|
std::vector<uint8_t>* signature);
|
||||||
void ServerSignMessage(const T& data, std::vector<uint8_t>* signature);
|
|
||||||
|
|
||||||
void ClientSignMessage(const vector<uint8_t>& data,
|
void ClientSignMessage(const vector<uint8_t>& data,
|
||||||
std::vector<uint8_t>* signature);
|
std::vector<uint8_t>* signature);
|
||||||
void FillKeyArray(const MessageData& data, OEMCrypto_KeyObject* key_array);
|
void FillKeyArray(const MessageData& data, OEMCrypto_KeyObject* key_array);
|
||||||
void FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
|
void FillRefreshArray(OEMCrypto_KeyRefreshObject* key_array,
|
||||||
size_t key_count);
|
size_t key_count);
|
||||||
void EncryptCTR(
|
void EncryptCTR(const vector<uint8_t>& in_buffer, const uint8_t* key,
|
||||||
const vector<uint8_t>& in_buffer, const uint8_t *key,
|
const uint8_t* starting_iv, vector<uint8_t>* out_buffer);
|
||||||
const uint8_t* starting_iv, vector<uint8_t>* out_buffer);
|
|
||||||
void TestDecryptCTR(bool select_key_first = true,
|
void TestDecryptCTR(bool select_key_first = true,
|
||||||
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
OEMCryptoResult expected_result = OEMCrypto_SUCCESS,
|
||||||
int key_index = 0);
|
int key_index = 0);
|
||||||
void MakeRSACertificate(
|
void MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted,
|
||||||
struct RSAPrivateKeyMessage* encrypted, std::vector<uint8_t>* signature,
|
size_t message_size, std::vector<uint8_t>* signature,
|
||||||
uint32_t allowed_schemes, const vector<uint8_t>& rsa_key);
|
uint32_t allowed_schemes,
|
||||||
|
const vector<uint8_t>& rsa_key);
|
||||||
void RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
|
void RewrapRSAKey(const struct RSAPrivateKeyMessage& encrypted,
|
||||||
const std::vector<uint8_t>& signature,
|
size_t message_size, const std::vector<uint8_t>& signature,
|
||||||
vector<uint8_t>* wrapped_key, bool force);
|
vector<uint8_t>* wrapped_key, bool force);
|
||||||
void PreparePublicKey(const uint8_t* rsa_key = NULL,
|
void PreparePublicKey(const uint8_t* rsa_key = NULL,
|
||||||
size_t rsa_key_length = 0);
|
size_t rsa_key_length = 0);
|
||||||
static bool VerifyPSSSignature(
|
static bool VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||||
EVP_PKEY* pkey, const uint8_t* message, size_t message_length,
|
size_t message_length,
|
||||||
const uint8_t* signature, size_t signature_length);
|
const uint8_t* signature,
|
||||||
void VerifyRSASignature(
|
size_t signature_length);
|
||||||
const vector<uint8_t>& message, const uint8_t* signature,
|
void VerifyRSASignature(const vector<uint8_t>& message,
|
||||||
size_t signature_length, RSA_Padding_Scheme padding_scheme);
|
const uint8_t* signature, size_t signature_length,
|
||||||
|
RSA_Padding_Scheme padding_scheme);
|
||||||
bool GenerateRSASessionKey(vector<uint8_t>* enc_session_key);
|
bool GenerateRSASessionKey(vector<uint8_t>* enc_session_key);
|
||||||
void InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key);
|
void InstallRSASessionTestKey(const vector<uint8_t>& wrapped_rsa_key);
|
||||||
void DisallowDeriveKeys();
|
void DisallowDeriveKeys();
|
||||||
@@ -180,7 +182,7 @@ class Session {
|
|||||||
void ForceDeleteEntry(const std::string& pst);
|
void ForceDeleteEntry(const std::string& pst);
|
||||||
|
|
||||||
MessageData& license() { return license_; }
|
MessageData& license() { return license_; }
|
||||||
MessageData& encrypted_license() { return encrypted_license_; }
|
MessageData& encrypted_license() { return padded_message_; }
|
||||||
|
|
||||||
const uint8_t* message_ptr();
|
const uint8_t* message_ptr();
|
||||||
|
|
||||||
@@ -190,6 +192,9 @@ class Session {
|
|||||||
void set_num_keys(int num_keys) { num_keys_ = num_keys; }
|
void set_num_keys(int num_keys) { num_keys_ = num_keys; }
|
||||||
int num_keys() const { return num_keys_; }
|
int num_keys() const { return num_keys_; }
|
||||||
|
|
||||||
|
void set_message_size(size_t size);
|
||||||
|
size_t message_size() { return message_size_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool open_;
|
bool open_;
|
||||||
bool forced_session_id_;
|
bool forced_session_id_;
|
||||||
@@ -201,7 +206,10 @@ class Session {
|
|||||||
RSA* public_rsa_;
|
RSA* public_rsa_;
|
||||||
vector<uint8_t> pst_report_buffer_;
|
vector<uint8_t> pst_report_buffer_;
|
||||||
MessageData license_;
|
MessageData license_;
|
||||||
MessageData encrypted_license_;
|
struct PaddedMessageData : public MessageData {
|
||||||
|
uint8_t padding[kMaxMessageSize - sizeof(MessageData)];
|
||||||
|
} padded_message_;
|
||||||
|
size_t message_size_; // How much of the padded message to use.
|
||||||
OEMCrypto_KeyObject key_array_[kMaxNumKeys];
|
OEMCrypto_KeyObject key_array_[kMaxNumKeys];
|
||||||
std::vector<uint8_t> signature_;
|
std::vector<uint8_t> signature_;
|
||||||
int num_keys_;
|
int num_keys_;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user