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:
Fred Gylys-Colwell
2019-05-21 11:33:19 -07:00
parent 6004c2a945
commit 8223d0e8b7
2 changed files with 182 additions and 217 deletions

View File

@@ -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.