Clean OEMCrypto unit tests
Merge from Widevine repo of http://go/wvgerrit/79243 Modify failures for LoadKeyWithSuspiciousIV and SelectKeyNotThereAPI15 This turns on some unit tests that were disabled for Q release. Merge from Widevine repo of http://go/wvgerrit/77948 Mod Mock: Dump entitlement keys - this allows some logging when running in a test environment. Merge from Widevine repo of http://go/wvgerrit/75763 Refactor OEMCrypto Decrypt Tests This CL refactors the oemcyrpto decryption tests. A bunch of boiler plate code was moved to a common test setup. Also, buffer handling was streamlined so that it will be easier to use these test with secure output buffers. Bug: 131281966 Bug: 129432708 Test: unit tests Change-Id: Iebf62611a16e0a4def9c4daed1c6cdf12686ba74
This commit is contained in:
@@ -1252,10 +1252,7 @@ TEST_F(OEMCryptoSessionTests, LoadKeyWithBadRange7) {
|
||||
|
||||
// The IV should not be identical to the data right before the encrypted mac
|
||||
// keys.
|
||||
// This test is for OEMCrypto v15.2. It is being disabled on the Android branch
|
||||
// the 15.2 updates to 15.2 were not available in time for the Q release. SOC
|
||||
// vendors who are able to pass this tests, should.
|
||||
TEST_F(OEMCryptoSessionTests, DISABLED_LoadKeyWithSuspiciousIV) {
|
||||
TEST_F(OEMCryptoSessionTests, LoadKeyWithSuspiciousIV) {
|
||||
Session s;
|
||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
||||
@@ -1606,9 +1603,7 @@ TEST_F(OEMCryptoSessionTests, SelectKeyNotThereAPI15) {
|
||||
s.session_id(), in_buffer.data(), in_buffer.size(), is_encrypted,
|
||||
encryptionIv.data(), 0, &destBuffer, &pattern,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
|
||||
EXPECT_TRUE(
|
||||
(OEMCrypto_ERROR_NO_CONTENT_KEY == sts) // Preferred return code.
|
||||
|| (OEMCrypto_KEY_NOT_LOADED == sts)); // Obsolete return code.
|
||||
EXPECT_EQ(OEMCrypto_ERROR_NO_CONTENT_KEY, sts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2075,6 +2070,18 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
pattern_ = ::testing::get<0>(GetParam());
|
||||
cipher_mode_ = ::testing::get<1>(GetParam());
|
||||
decrypt_inplace_ = ::testing::get<2>(GetParam());
|
||||
verify_crc_ = global_features.supports_crc;
|
||||
// Pick a random key.
|
||||
EXPECT_EQ(1, GetRandBytes(key_, AES_BLOCK_SIZE));
|
||||
// Pick a random starting iv. Some tests override this before using it.
|
||||
starting_iv_.resize(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(starting_iv_.data(), starting_iv_.size()));
|
||||
total_size_ = -1;
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
ASSERT_NO_FATAL_FAILURE(session_.close());
|
||||
OEMCryptoSessionTests::TearDown();
|
||||
}
|
||||
|
||||
void FindTotalSize() {
|
||||
@@ -2085,24 +2092,47 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
}
|
||||
}
|
||||
|
||||
void EncryptData(const vector<uint8_t>& key,
|
||||
const vector<uint8_t>& starting_iv,
|
||||
const vector<uint8_t>& in_buffer,
|
||||
vector<uint8_t>* out_buffer) {
|
||||
// Set up the input buffer and output buffer.
|
||||
// This should be called after FindTotalSize().
|
||||
void MakeBuffers() {
|
||||
ASSERT_GT(total_size_, 0u);
|
||||
encrypted_buffer_.resize(total_size_);
|
||||
truth_buffer_.resize(total_size_);
|
||||
for (size_t i = 0; i < total_size_; i++) truth_buffer_[i] = i % 256;
|
||||
output_descriptor_.type = OEMCrypto_BufferType_Clear;
|
||||
if (decrypt_inplace_) {
|
||||
output_descriptor_.buffer.clear.address = encrypted_buffer_.data();
|
||||
} else {
|
||||
// Add some padding to verify there is no overrun.
|
||||
clear_buffer_.resize(total_size_ + 16, 0xaa);
|
||||
output_descriptor_.buffer.clear.address = clear_buffer_.data();
|
||||
}
|
||||
output_descriptor_.buffer.clear.max_length = total_size_;
|
||||
}
|
||||
|
||||
void UpdateOutputOffset(size_t offset) {
|
||||
if (decrypt_inplace_) {
|
||||
output_descriptor_.buffer.clear.address =
|
||||
encrypted_buffer_.data() + offset;
|
||||
} else {
|
||||
output_descriptor_.buffer.clear.address = clear_buffer_.data() + offset;
|
||||
}
|
||||
output_descriptor_.buffer.clear.max_length = total_size_ - offset;
|
||||
}
|
||||
|
||||
void EncryptData() {
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(key.data(), AES_BLOCK_SIZE * 8, &aes_key);
|
||||
out_buffer->resize(in_buffer.size());
|
||||
AES_set_encrypt_key(key_, AES_BLOCK_SIZE * 8, &aes_key);
|
||||
|
||||
uint8_t iv[AES_BLOCK_SIZE]; // Current iv.
|
||||
|
||||
memcpy(iv, starting_iv.data(), AES_BLOCK_SIZE);
|
||||
memcpy(iv, starting_iv_.data(), AES_BLOCK_SIZE);
|
||||
|
||||
size_t buffer_index = 0; // byte index into in and out.
|
||||
size_t block_offset = 0; // byte index into current block.
|
||||
for (size_t i = 0; i < subsample_size_.size(); i++) {
|
||||
// Copy clear content.
|
||||
if (subsample_size_[i].clear_size > 0) {
|
||||
memcpy(&(*out_buffer)[buffer_index], &in_buffer[buffer_index],
|
||||
memcpy(&encrypted_buffer_[buffer_index], &truth_buffer_[buffer_index],
|
||||
subsample_size_[i].clear_size);
|
||||
buffer_index += subsample_size_[i].clear_size;
|
||||
}
|
||||
@@ -2129,15 +2159,17 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
// can put whatever we want in the output buffer.
|
||||
if (skip_block || ((cipher_mode_ == OEMCrypto_CipherMode_CBC) &&
|
||||
(size < AES_BLOCK_SIZE))) {
|
||||
memcpy(&(*out_buffer)[buffer_index], &in_buffer[buffer_index], size);
|
||||
memcpy(&encrypted_buffer_[buffer_index], &truth_buffer_[buffer_index],
|
||||
size);
|
||||
block_offset = 0; // Next block should be complete.
|
||||
} else {
|
||||
if (cipher_mode_ == OEMCrypto_CipherMode_CTR) {
|
||||
uint8_t aes_output[AES_BLOCK_SIZE];
|
||||
AES_encrypt(iv, aes_output, &aes_key);
|
||||
for (size_t n = 0; n < size; n++) {
|
||||
(*out_buffer)[buffer_index + n] =
|
||||
aes_output[n + block_offset] ^ in_buffer[buffer_index + n];
|
||||
encrypted_buffer_[buffer_index + n] =
|
||||
aes_output[n + block_offset] ^
|
||||
truth_buffer_[buffer_index + n];
|
||||
}
|
||||
if (size + block_offset < AES_BLOCK_SIZE) {
|
||||
// Partial block. Don't increment iv. Compute next block offset.
|
||||
@@ -2152,10 +2184,10 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
} else {
|
||||
uint8_t aes_input[AES_BLOCK_SIZE];
|
||||
for (size_t n = 0; n < size; n++) {
|
||||
aes_input[n] = in_buffer[buffer_index + n] ^ iv[n];
|
||||
aes_input[n] = truth_buffer_[buffer_index + n] ^ iv[n];
|
||||
}
|
||||
AES_encrypt(aes_input, &(*out_buffer)[buffer_index], &aes_key);
|
||||
memcpy(iv, &(*out_buffer)[buffer_index], AES_BLOCK_SIZE);
|
||||
AES_encrypt(aes_input, &encrypted_buffer_[buffer_index], &aes_key);
|
||||
memcpy(iv, &encrypted_buffer_[buffer_index], AES_BLOCK_SIZE);
|
||||
// CBC mode should always start on block boundary.
|
||||
block_offset = 0;
|
||||
}
|
||||
@@ -2165,73 +2197,58 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
}
|
||||
}
|
||||
|
||||
void TestDecryptCENC(const vector<uint8_t>& key,
|
||||
const vector<uint8_t>& /* encryptionIv */,
|
||||
const vector<uint8_t>& encryptedData,
|
||||
const vector<uint8_t>& unencryptedData) {
|
||||
void LoadLicense() {
|
||||
// First we open a session and load a license.
|
||||
ASSERT_NO_FATAL_FAILURE(session_.open());
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&session_));
|
||||
uint32_t control = 0;
|
||||
if (verify_crc_) control |= kControlAllowHashVerification;
|
||||
ASSERT_NO_FATAL_FAILURE(session_.FillSimpleMessage(
|
||||
kDuration, control, 0));
|
||||
memcpy(session_.license().keys[0].key_data, key_, sizeof(key_));
|
||||
session_.license().keys[0].cipher_mode = cipher_mode_;
|
||||
ASSERT_NO_FATAL_FAILURE(session_.EncryptAndSign());
|
||||
ASSERT_NO_FATAL_FAILURE(session_.LoadTestKeys());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SelectKey(
|
||||
session_.session_id(), session_.license().keys[0].key_id,
|
||||
session_.license().keys[0].key_id_length, cipher_mode_));
|
||||
}
|
||||
|
||||
void TestDecryptCENC() {
|
||||
OEMCryptoResult sts;
|
||||
Session s;
|
||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
s.FillSimpleMessage(kDuration, kControlAllowHashVerification, 0));
|
||||
memcpy(s.license().keys[0].key_data, key.data(), key.size());
|
||||
s.license().keys[0].cipher_mode = cipher_mode_;
|
||||
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
|
||||
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys());
|
||||
if (global_features.supports_crc) {
|
||||
uint32_t hash =
|
||||
wvcrc32(unencryptedData.data(), unencryptedData.size());
|
||||
// If supported, initialize the decrypt hash.
|
||||
if (verify_crc_) {
|
||||
uint32_t hash = wvcrc32(truth_buffer_.data(), truth_buffer_.size());
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_SetDecryptHash(
|
||||
s.session_id(), 1, reinterpret_cast<const uint8_t*>(&hash),
|
||||
sizeof(hash)));
|
||||
}
|
||||
sts = OEMCrypto_SelectKey(s.session_id(), s.license().keys[0].key_id,
|
||||
s.license().keys[0].key_id_length,
|
||||
cipher_mode_);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
// We decrypt each subsample.
|
||||
vector<uint8_t> output_buffer(total_size_ + 16, 0xaa);
|
||||
const uint8_t *input_buffer = NULL;
|
||||
if (decrypt_inplace_) { // Use same buffer for input and output.
|
||||
// Copy the useful data from encryptedData to output_buffer, which
|
||||
// will be the same as input_buffer. Leave the 0xaa padding at the end.
|
||||
for(size_t i=0; i < total_size_; i++) output_buffer[i] = encryptedData[i];
|
||||
// Now let input_buffer point to the same data.
|
||||
input_buffer = output_buffer.data();
|
||||
} else {
|
||||
input_buffer = encryptedData.data();
|
||||
session_.session_id(), 1,
|
||||
reinterpret_cast<const uint8_t*>(&hash), sizeof(hash)));
|
||||
}
|
||||
size_t buffer_offset = 0;
|
||||
for (size_t i = 0; i < subsample_size_.size(); i++) {
|
||||
OEMCrypto_CENCEncryptPatternDesc pattern = pattern_;
|
||||
pattern.offset = 0; // Final CENC spec says pattern offset always 0.
|
||||
bool is_encrypted = false;
|
||||
OEMCrypto_DestBufferDesc destBuffer;
|
||||
size_t block_offset = 0;
|
||||
uint8_t subsample_flags = 0;
|
||||
if (subsample_size_[i].clear_size > 0) {
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = &output_buffer[buffer_offset];
|
||||
destBuffer.buffer.clear.max_length = total_size_ - buffer_offset;
|
||||
ASSERT_NO_FATAL_FAILURE(UpdateOutputOffset(buffer_offset));
|
||||
if (i == 0) subsample_flags |= OEMCrypto_FirstSubsample;
|
||||
if ((i == subsample_size_.size() - 1) &&
|
||||
(subsample_size_[i].encrypted_size == 0)) {
|
||||
subsample_flags |= OEMCrypto_LastSubsample;
|
||||
}
|
||||
sts =
|
||||
OEMCrypto_DecryptCENC(s.session_id(), input_buffer + buffer_offset,
|
||||
subsample_size_[i].clear_size, is_encrypted,
|
||||
sample_init_data_[i].iv, block_offset,
|
||||
&destBuffer, &pattern, subsample_flags);
|
||||
sts = OEMCrypto_DecryptCENC(
|
||||
session_.session_id(), &encrypted_buffer_[buffer_offset],
|
||||
subsample_size_[i].clear_size, is_encrypted,
|
||||
sample_init_data_[i].iv, block_offset, &output_descriptor_,
|
||||
&pattern, subsample_flags);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
buffer_offset += subsample_size_[i].clear_size;
|
||||
}
|
||||
if (subsample_size_[i].encrypted_size > 0) {
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = &output_buffer[buffer_offset];
|
||||
destBuffer.buffer.clear.max_length = total_size_ - buffer_offset;
|
||||
ASSERT_NO_FATAL_FAILURE(UpdateOutputOffset(buffer_offset));
|
||||
is_encrypted = true;
|
||||
block_offset = sample_init_data_[i].block_offset;
|
||||
subsample_flags = 0;
|
||||
@@ -2242,10 +2259,10 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
subsample_flags |= OEMCrypto_LastSubsample;
|
||||
}
|
||||
sts = OEMCrypto_DecryptCENC(
|
||||
s.session_id(), input_buffer + buffer_offset,
|
||||
session_.session_id(), &encrypted_buffer_[buffer_offset],
|
||||
subsample_size_[i].encrypted_size, is_encrypted,
|
||||
sample_init_data_[i].iv, block_offset, &destBuffer, &pattern,
|
||||
subsample_flags);
|
||||
sample_init_data_[i].iv, block_offset, &output_descriptor_,
|
||||
&pattern, subsample_flags);
|
||||
// CBC mode should not accept a block offset.
|
||||
if ((block_offset > 0) && (cipher_mode_ == OEMCrypto_CipherMode_CBC)) {
|
||||
ASSERT_EQ(OEMCrypto_ERROR_INVALID_CONTEXT, sts)
|
||||
@@ -2256,14 +2273,23 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
buffer_offset += subsample_size_[i].encrypted_size;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(0xaa, output_buffer[total_size_]) << "Buffer overrun.";
|
||||
output_buffer.resize(total_size_);
|
||||
EXPECT_EQ(unencryptedData, output_buffer);
|
||||
if (output_descriptor_.type == OEMCrypto_BufferType_Clear) {
|
||||
if (decrypt_inplace_) {
|
||||
// We expect encrypted buffer to have been changed by OEMCrypto.
|
||||
EXPECT_EQ(encrypted_buffer_, truth_buffer_);
|
||||
} else {
|
||||
// If we are not decrypting in place, then look at the one byte just
|
||||
// after the data that was written. It should not have changed from the
|
||||
// original 0xaa that we set in MakeBuffersession_.
|
||||
EXPECT_EQ(0xaa, clear_buffer_[total_size_]) << "Buffer overrun.";
|
||||
clear_buffer_.resize(total_size_); // Remove padding.
|
||||
EXPECT_EQ(clear_buffer_, truth_buffer_);
|
||||
}
|
||||
}
|
||||
if (global_features.supports_crc) {
|
||||
uint32_t frame;
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GetHashErrorCode(s.session_id(), &frame));
|
||||
|
||||
OEMCrypto_GetHashErrorCode(session_.session_id(), &frame));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2272,7 +2298,17 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
bool decrypt_inplace_; // If true, input and output buffers are the same.
|
||||
vector<SampleSize> subsample_size_;
|
||||
size_t total_size_;
|
||||
bool verify_crc_;
|
||||
vector<SampleInitData> sample_init_data_;
|
||||
// Encrypted data -- this is input to OEMCrypto, and output from EncryptData.
|
||||
std::vector<uint8_t> encrypted_buffer_;
|
||||
std::vector<uint8_t> clear_buffer_; // OEMCrypto store clear output here.
|
||||
void* secure_handle_; // OEMCrypto stores secure output here.
|
||||
std::vector<uint8_t> truth_buffer_; // Truth data for clear text.
|
||||
OEMCrypto_DestBufferDesc output_descriptor_;
|
||||
uint8_t key_[AES_BLOCK_SIZE]; // Encryption Key.
|
||||
std::vector<uint8_t> starting_iv_; // Starting IV.
|
||||
Session session_;
|
||||
};
|
||||
|
||||
// Tests that generate partial ending blocks. These tests should not be used
|
||||
@@ -2286,15 +2322,10 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) {
|
||||
// full patterns if we have more than 320 -- round up to 400.
|
||||
subsample_size_.push_back(SampleSize(0, 400));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// When the pattern length is 10 blocks, there is a discrepancy between the
|
||||
@@ -2304,30 +2335,20 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) {
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, PatternPlusOneBlock) {
|
||||
subsample_size_.push_back(SampleSize(0, 160 + 16));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// Test that a single block can be decrypted.
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, OneBlock) {
|
||||
subsample_size_.push_back(SampleSize(0, 16));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// This tests the ability to decrypt multiple subsamples with no offset.
|
||||
@@ -2338,41 +2359,36 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, NoOffset) {
|
||||
subsample_size_.push_back(SampleSize(50, 256));
|
||||
subsample_size_.push_back(SampleSize(25, 160));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// This tests an offset into the block for the second encrypted subsample.
|
||||
// This should only work for CTR mode, for CBC mode an error is expected in
|
||||
// the decrypt step.
|
||||
// If this test fails for CTR mode, then it is probably handleing the
|
||||
// If this test fails for CTR mode, then it is probably handling the
|
||||
// block_offset incorrectly.
|
||||
TEST_P(OEMCryptoSessionTestsPartialBlockTests, EvenOffset) {
|
||||
subsample_size_.push_back(SampleSize(25, 8));
|
||||
subsample_size_.push_back(SampleSize(25, 32));
|
||||
subsample_size_.push_back(SampleSize(25, 50));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
// CTR Mode is self-inverse -- i.e. We can pick the encrypted data and
|
||||
// compute the unencrypted data. By picking the encrypted data to be all 0,
|
||||
// it is easier to re-encrypt the data and debug problems. Similarly, we
|
||||
// pick an iv = 0.
|
||||
EncryptData(key, encryptionIv, encryptedData, &unencryptedData);
|
||||
// Run EncryptData again to correctly compute intermediate IV vectors.
|
||||
// For CBC mode, this also computes the real encrypted data.
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
starting_iv_.assign(AES_BLOCK_SIZE, 0);
|
||||
truth_buffer_.assign(total_size_, 0);
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
truth_buffer_ = encrypted_buffer_; // truth_buffer_ = encrypted zero buffer.
|
||||
// Run EncryptData to re-encrypt this buffer. For CTR mode, we should get
|
||||
// back to zeros.
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// If the EvenOffset test passes, but this one doesn't, then DecryptCTR might
|
||||
@@ -2387,15 +2403,10 @@ TEST_P(OEMCryptoSessionTestsPartialBlockTests, OddOffset) {
|
||||
subsample_size_.push_back(SampleSize(10, 75));
|
||||
subsample_size_.push_back(SampleSize(10, 25));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// This tests that the algorithm used to increment the counter for
|
||||
@@ -2409,17 +2420,13 @@ TEST_P(OEMCryptoSessionTestsPartialBlockTests, OddOffset) {
|
||||
// If you start with an IV of 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE, after you
|
||||
// increment twice, you should get 0xFFFFFFFFFFFFFFFF0000000000000000.
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptWithNearWrap) {
|
||||
starting_iv_ = wvcdm::a2b_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE");
|
||||
subsample_size_.push_back(SampleSize(0, 256));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
encryptionIv = wvcdm::a2b_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE");
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// This tests the case where an encrypted sample is not an even number of
|
||||
@@ -2431,15 +2438,10 @@ TEST_P(OEMCryptoSessionTestsPartialBlockTests, PartialBlock) {
|
||||
// other tests, e.g. (7, 3). 3*16 < 50 and 7*16 > 50.
|
||||
subsample_size_.push_back(SampleSize(0, 50));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// Based on the resource rating, oemcrypto should handle at least
|
||||
@@ -2456,15 +2458,10 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSample) {
|
||||
subsample_size_.push_back(SampleSize(0, max_subsample_size));
|
||||
}
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// This tests that we can decrypt the required maximum number of subsamples.
|
||||
@@ -2473,30 +2470,20 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSubsample) {
|
||||
subsample_size_.push_back(SampleSize(max_subsample_size, 0));
|
||||
subsample_size_.push_back(SampleSize(0, max_subsample_size));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// There are probably no frames this small, but we should handle them anyway.
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptSmallBuffer) {
|
||||
subsample_size_.push_back(SampleSize(5, 5));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// Test the case where there is only a clear subsample and no encrypted
|
||||
@@ -2504,47 +2491,25 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptSmallBuffer) {
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptUnencrypted) {
|
||||
subsample_size_.push_back(SampleSize(256, 0));
|
||||
FindTotalSize();
|
||||
vector<uint8_t> unencryptedData(total_size_);
|
||||
vector<uint8_t> encryptedData(total_size_);
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
vector<uint8_t> key(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
EXPECT_EQ(1, GetRandBytes(key.data(), AES_BLOCK_SIZE));
|
||||
for (size_t i = 0; i < total_size_; i++) unencryptedData[i] = i % 256;
|
||||
EncryptData(key, encryptionIv, unencryptedData, &encryptedData);
|
||||
TestDecryptCENC(key, encryptionIv, encryptedData, unencryptedData);
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTests, DecryptUnencryptedNoKey) {
|
||||
OEMCryptoResult sts;
|
||||
Session s;
|
||||
ASSERT_NO_FATAL_FAILURE(s.open());
|
||||
// Clear data should be copied even if there is no key selected.
|
||||
// Set up our expected input and output
|
||||
// This is dummy decrypted data.
|
||||
vector<uint8_t> in_buffer(256);
|
||||
for (size_t i = 0; i < in_buffer.size(); i++) in_buffer[i] = i % 256;
|
||||
vector<uint8_t> encryptionIv(AES_BLOCK_SIZE);
|
||||
EXPECT_EQ(1, GetRandBytes(encryptionIv.data(), AES_BLOCK_SIZE));
|
||||
// Describe the output
|
||||
vector<uint8_t> out_buffer(in_buffer.size());
|
||||
OEMCrypto_DestBufferDesc destBuffer;
|
||||
destBuffer.type = OEMCrypto_BufferType_Clear;
|
||||
destBuffer.buffer.clear.address = out_buffer.data();
|
||||
destBuffer.buffer.clear.max_length = out_buffer.size();
|
||||
OEMCrypto_CENCEncryptPatternDesc pattern;
|
||||
pattern.encrypt = 0;
|
||||
pattern.skip = 0;
|
||||
pattern.offset = 0;
|
||||
|
||||
// Decrypt the data
|
||||
sts =
|
||||
OEMCrypto_DecryptCENC(s.session_id(), in_buffer.data(), in_buffer.size(),
|
||||
false, encryptionIv.data(), 0, &destBuffer,
|
||||
&pattern,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
ASSERT_EQ(in_buffer, out_buffer);
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptUnencryptedNoKey) {
|
||||
ASSERT_NO_FATAL_FAILURE(session_.open());
|
||||
// Single clear subsample
|
||||
subsample_size_.push_back(SampleSize(400, 0));
|
||||
// Do not try to compute the CRC because we have not loaded a license.
|
||||
verify_crc_ = false;
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
// Clear data should be copied even if there is no key selected, and no
|
||||
// license loaded.
|
||||
// ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
|
||||
// Used to construct a specific pattern.
|
||||
|
||||
Reference in New Issue
Block a user