Update OEMCrypto test comments and logs

Merge from Widevine repo of http://go/wvgerrit/121886

This CL merges some changes from branch rvc-dev to sc-dev
that prepared it for merge.

One change is that the unit tests now say they are part of
Android S instead of R.

Bug: 180546871
Change-Id: I2ebbd8f7b8586389ebb75f3743a2dc2ad8caa214
This commit is contained in:
Fred Gylys-Colwell
2021-04-10 11:11:31 -07:00
parent d265a5fe73
commit 6628c7f693
8 changed files with 427 additions and 60 deletions

View File

@@ -0,0 +1,125 @@
# OEMCrypto Unit Tests
## Basic Functionality Tests
Most unit tests in this category verify that the basic functionality of opening
sessions, initializing and terminating the system, and reporting status work
correctly.
## Decrypt Tests
The decrypt tests verify that encrypted data is correctly decrypted with the
desired key. These tests cover a large variety of patterns, sample sizes, and
subsample sizes.
## Secure Buffers
If OEMCrypto implements the function `OEMCrypto_AllocateSecureBuffer`, then all
of the decrypt tests will also run with the output buffer being a secure
buffer. If the function `OEMCrypto_SupportsDecryptHash` returns
`OEMCrypto_CRC_Clear_Buffer`, then the secure buffer decryption will be verified
with the CRC32 hash of the input data.
## Usage Table Tests
Usage table tests verify that the usage table is correctly procesed. The usage
table is used to control reloading keys for offline playback, and for reporting
secure stops for online playback.
## Duration Tests
Duration tests verify that license durations are enforced correctly. Most of
this functionality can be met by keeping an accurate system time, and calling
the ODK functions as described in the document "License Duration and Renewal".
## OEMCrypto Memory Unit Tests
### Objective
* Add OEMCrypto buffer overflow unit tests (indirect way of fuzzing) to verify
OEMCrypto API behavior when the parameters passed to the API are out of
range or not reasonable. The API can return an error code, but shouldn't
crash.
* A lot of OEMCrypto APIs take buffers and their length as inputs to the APIs
and we have added unit tests with buffers of varying lengths (small
to huge) to verify API behavior which is an indirect and simplest way of
fuzz testing to detect buffer overflows.
* Add the tests for OEMCrypto APIs with prefix `OEMCryptoMemory` in the
following format. Huge length is set at 100 MB as of now.
```cpp
for (size_t length=small_length; length<huge_length; length=length * 2) {
Create buffer of size length.
Call api expecting it not to crash or segfault.
}
```
* Add tests for OEMCrypto APIs with out of range values for length and offsets
of OEMCryptoSubstring struct. This length and offset fields are used to read
values from an input buffer in most of the APIs. This can cause buffer
overflows if the length and offset fields are not validated against the
input buffer.
### Background
* Security is the top priority for Widevine. We came up with a simple approach
to catch most common issues with widevine's implementations. A simplest
approach is to add OEMCrypto unit tests to verify OEMCrypto API behavior
when the parameters are out of range, meaning for an unreasonable length
which can cause buffer overflows. Most of the implementation either does not
validate input length parameters or copies data to secure buffers out of TA
space causing memory corruptions, buffer overflows. Partners who implement
OEMCrypto implementations will run OEMCrypto unit tests as part of the
process.
* We have added unit tests with parameters that can cause buffer overflows if
the parameters are not validated. This way partners can catch issues
earlier in the process when they run OEMCrypto unit tests. All the unit
tests with prefix `OEMCryptoMemory` are added to test the above scenario.
### What to expect from these tests
* `OEMCryptoMemory*` tests are designed to fail if API doesn't have enough
validations around input buffer lengths, parameters or OEMCryptoSubstring
struct. If the API doesn't have validations which might lead to a crash, the
test fails with a segfault or an appropriate crash message based on the API
implementation.
* Find out for what buffer length, the API is crashing and then debugging the
test against the OEMCrypto implementation should be able to provide
information about the error.
* Another way to debug would be to compile the tests with sanitizer flags,
which will be able to provide detailed information about the crash.
* Partners are expected to fix issues with the API so that the tests don't
fail.
* As these tests run for varying lengths from small to huge buffer lengths,
some of the tests might take longer to run(~3 minutes).
* `OEMCryptoMemoryInstallKeyboxForHugeKeyboxBuffer*` tests which tries to
call install keybox API with varying buffer lengths. This test by default
is not compiled as it overwrites the keybox on the device. Uncomment,
compile and run the tests only if you have ability to recover the keybox
on device where the test is ran.
## Filtering out tests
The source code will check for functionality of OEMCrypto and filter out tests
that are not required. For example, if a device uses a keybox, then Provisioning
3.0 tests are skipped, and vice versa.
If you wish to skip slow tests because you only want to verify basic
functionality, then you can set the environment variable `GTEST_FILTER`,
as documented
[here](https://github.com/google/googletest/blob/master/docs/advanced.md#running-a-subset-of-the-tests).
For example, to skip the duration tests, buffer overflow tests and long running
stress tests, you would set
```
GTEST_FILTER="*-*Duration*:*TimingTest*:*Memory*:*Huge*:*NonceFlood*:*ManyUsageEntries*:*Defrag*"
```

View File

@@ -7,6 +7,7 @@
#include "log.h"
#include "oemcrypto_fuzz_helper.h"
#include "oemcrypto_fuzz_structs.h"
#include "oemcrypto_overflow.h"
namespace wvoec {
const size_t MAX_FUZZ_SAMPLE_SIZE = 5 * MB;
@@ -137,13 +138,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// Copy sub sample data.
sample_descriptions[i].subsamples = &subsamples[input_subsample_index];
input_subsample_index += sample_descriptions[i].subsamples_length;
if (AddOverflowUX(input_subsample_index,
sample_descriptions[i].subsamples_length,
&input_subsample_index)) {
return 0;
}
if (input_subsample_index > subsamples.size()) return 0;
} // Sample loop.
// Allocate input/output buffers for each sample description.
vector<OEMCrypto_SharedMemory> input_buffer(total_input_data_length);
RAND_bytes(input_buffer.data(), total_input_data_length);
size_t input_buffer_index = 0;
for (size_t i = 0; i < samples_length; i++) {
sample_descriptions[i].buffers.input_data =

View File

@@ -36,9 +36,7 @@ class OEMCryptoLicenseAPIFuzz : public InitializeFuzz {
session_.GenerateNonce();
}
~OEMCryptoLicenseAPIFuzz() {
session_.close();
}
~OEMCryptoLicenseAPIFuzz() { session_.close(); }
LicenseRoundTrip& license_messages() { return license_messages_; }

View File

@@ -0,0 +1,77 @@
#include <stdio.h>
#include "dispatcher.h"
#include "marshaller_base.h"
#include "transport_interface.h"
namespace wvoec {
void InitializeODKMessage(ODK_Message* message, uint8_t* data, size_t size) {
ODK_Message_Impl* impl = (ODK_Message_Impl*)message;
impl->base = data;
impl->size = size;
impl->capacity = size;
impl->read_offset = 0;
impl->status = MESSAGE_STATUS_OK;
}
void OpenOEMCryptoTASession() {
ODK_Message request;
ODK_Message* response = NULL;
uint8_t response_buffer[0x1000];
uint8_t request_body[] = {
0x06, // TAG_UINT32
0x09, 0x00, 0x00, 0x00, // API value (0x09)
0x01, // TAG_BOOL
0x00, // value (false)
0x0a // TAG_EOM
};
InitializeODKMessage(&request, request_body, sizeof(request_body));
ODK_DispatchMessage(&request, &response);
if (response != NULL) ODK_Transport_DeallocateMessage(response);
}
void InitializeOEMCryptoTA() {
ODK_Message init_request;
ODK_Message* init_response = NULL;
uint8_t response_buffer[0x1000];
uint8_t init_request_body[] = {
0x06, // TAG_UINT32
0x01, 0x00, 0x00, 0x00, // API value(0x01)
0x0a // TAG_EOM
};
InitializeODKMessage(&init_request, init_request_body,
sizeof(init_request_body));
ODK_DispatchMessage(&init_request, &init_response);
if (init_response != NULL) ODK_Transport_DeallocateMessage(init_response);
}
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
ODK_InitializeDispatcher();
InitializeOEMCryptoTA();
OpenOEMCryptoTASession();
return 0;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
ODK_Message request;
ODK_Message* response = NULL;
unsigned char response_buffer[0x1000];
uint8_t* input = new uint8_t[size];
memcpy(input, data, size);
InitializeODKMessage(&request, input, size);
ODK_DispatchMessage(&request, &response);
if (response != NULL) ODK_Transport_DeallocateMessage(response);
delete[] input;
return 0;
}
} // namespace wvoec

View File

@@ -129,6 +129,7 @@ std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
if (!generic_crypto) FilterOut(&filter, "*GenericCrypto*");
if (!cast_receiver) FilterOut(&filter, "*CastReceiver*");
if (!usage_table) FilterOut(&filter, "*UsageTable*");
if (!usage_table) FilterOut(&filter, "*BadRange_pst*");
if (derive_key_method == NO_METHOD) FilterOut(&filter, "*SessionTest*");
if (provisioning_method
!= OEMCrypto_OEMCertificate) FilterOut(&filter, "*Prov30*");

View File

@@ -154,8 +154,7 @@ RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse, ResponseData>::
constexpr size_t small_size = 42; // arbitrary.
uint32_t session_id = session()->session_id();
GetDefaultRequestSignatureAndCoreMessageLengths<PrepAndSignRequest>(
session_id, required_message_size_, small_size, &gen_signature_length,
&core_message_length);
session_id, small_size, &gen_signature_length, &core_message_length);
// Used to test request APIs with varying lengths of core message.
core_message_length =
std::max(core_message_length, required_core_message_size_);
@@ -192,9 +191,8 @@ RoundTrip<CoreRequest, PrepAndSignRequest, CoreResponse, ResponseData>::
template <PrepAndSignRequest_t PrepAndSignRequest>
void GetDefaultRequestSignatureAndCoreMessageLengths(
uint32_t& session_id, size_t& required_message_size,
const size_t& small_size, size_t* gen_signature_length,
size_t* core_message_length) {
uint32_t& session_id, const size_t& small_size,
size_t* gen_signature_length, size_t* core_message_length) {
vector<uint8_t> data(small_size);
for (size_t i = 0; i < data.size(); i++) data[i] = i & 0xFF;
ASSERT_EQ(

View File

@@ -669,9 +669,8 @@ void WriteRequestApiCorpus(size_t signature_length, size_t core_message_length,
vector<uint8_t>& data);
template <PrepAndSignRequest_t PrepAndSignRequest>
void GetDefaultRequestSignatureAndCoreMessageLengths(
uint32_t& session_id, size_t& required_message_size,
const size_t& small_size, size_t* gen_signature_length,
size_t* core_message_length);
uint32_t& session_id, const size_t& small_size,
size_t* gen_signature_length, size_t* core_message_length);
} // namespace wvoec
#endif // CDM_OEC_SESSION_UTIL_H_

View File

@@ -137,6 +137,11 @@ void TestHugeLengthDoesNotCrashAPI(oemcrypto_function f,
!check_status);
buffer_length *= 2) {
sts = f(buffer_length);
if (check_status && sts != OEMCrypto_SUCCESS &&
sts != OEMCrypto_ERROR_SHORT_BUFFER) {
LOGI("Test exits huge buffer loop for length:%zu, status:%d",
buffer_length, sts);
}
}
}
@@ -170,6 +175,17 @@ const size_t kLargeMessageSize[] = { 8*KiB, 8*KiB, 16*KiB, 32*KiB};
// const size_t kAV1NumberSubsamples[] = { 72, 144, 288, 576};
// clang-format on
// Return a printable string from data. If all the characters are printable,
// then just use the string. Otherwise, convert to hex.
std::string MaybeHex(const uint8_t* data, size_t length) {
for (size_t i = 0; i < length; i++) {
if (!isprint(data[i])) return "0x" + wvcdm::HexEncode(data, length);
}
return std::string(reinterpret_cast<const char*>(data), length);
}
std::string MaybeHex(const std::vector<uint8_t>& data) {
return MaybeHex(data.data(), data.size());
}
} // namespace
class OEMCryptoClientTest : public ::testing::Test, public SessionUtil {
@@ -202,6 +218,17 @@ class OEMCryptoClientTest : public ::testing::Test, public SessionUtil {
}
};
TEST_F(OEMCryptoClientTest, FreeUnallocatedSecureBufferNoFailure) {
Session s;
s.open();
OEMCrypto_DestBufferDesc output_descriptor;
int secure_fd = kHugeRandomNumber;
ASSERT_NE(OEMCrypto_SUCCESS,
OEMCrypto_FreeSecureBuffer(s.session_id(), &output_descriptor,
secure_fd));
s.close();
}
/// @addtogroup basic
/// @{
@@ -212,15 +239,20 @@ class OEMCryptoClientTest : public ::testing::Test, public SessionUtil {
*/
TEST_F(OEMCryptoClientTest, VersionNumber) {
const std::string log_message =
"OEMCrypto unit tests for API 16.4. Tests last updated 2020-10-07";
"OEMCrypto unit tests for API 16.3 or 4. Tests last updated 2021-02-22";
cout << " " << log_message << "\n";
cout << " "
<< "These tests are part of Android S."
<< "\n";
LOGI("%s", log_message.c_str());
// If any of the following fail, then it is time to update the log message
// above.
EXPECT_EQ(ODK_MAJOR_VERSION, 16);
// Note on minor versions. Widevine requires version 16.3 or greater for CE
// CDM and Android devices. For CE CDM devices that do not support usage
// tables, we strongly recommend 16.4.
// tables, we strongly recommend 16.4. Note: This is the version of the ODK
// library built into the tests, which might be different from the version
// that is pre-compiled into liboemcrypto.so.
EXPECT_GE(ODK_MINOR_VERSION, 3);
EXPECT_LE(ODK_MINOR_VERSION, 4);
EXPECT_EQ(kCurrentAPI, 16u);
@@ -229,7 +261,9 @@ TEST_F(OEMCryptoClientTest, VersionNumber) {
ASSERT_EQ('L', level[0]);
cout << " OEMCrypto Security Level is " << level << endl;
uint32_t version = OEMCrypto_APIVersion();
cout << " OEMCrypto API version is " << version << endl;
uint32_t minor_version = OEMCrypto_MinorAPIVersion();
cout << " OEMCrypto API version is " << version << "."
<< minor_version << endl;
if (OEMCrypto_SupportsUsageTable()) {
cout << " OEMCrypto supports usage tables" << endl;
} else {
@@ -661,8 +695,8 @@ TEST_F(OEMCryptoClientTest, ClearCopyTestAPI10) {
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample));
dest_buffer_descriptor.buffer.clear.address = output_buffer.data();
dest_buffer_descriptor.buffer.clear.address_length = output_buffer.size() - 1;
ASSERT_EQ(
OEMCrypto_ERROR_SHORT_BUFFER,
ASSERT_NE(
OEMCrypto_SUCCESS,
OEMCrypto_CopyBuffer(s.session_id(), input_buffer.data(),
input_buffer.size(), &dest_buffer_descriptor,
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample));
@@ -896,8 +930,8 @@ TEST_F(OEMCryptoKeyboxTest, NormalGetDeviceId) {
uint8_t dev_id[128] = {0};
size_t dev_id_len = 128;
sts = OEMCrypto_GetDeviceID(dev_id, &dev_id_len);
cout << " NormalGetDeviceId: dev_id = " << dev_id
<< " len = " << dev_id_len << endl;
cout << " NormalGetDeviceId: dev_id = "
<< MaybeHex(dev_id, dev_id_len) << " len = " << dev_id_len << endl;
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
}
@@ -1039,7 +1073,7 @@ TEST_F(OEMCryptoProv30Test, GetDeviceId) {
}
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
dev_id.resize(dev_id_len);
cout << " NormalGetDeviceId: dev_id = " << dev_id.data()
cout << " NormalGetDeviceId: dev_id = " << MaybeHex(dev_id)
<< " len = " << dev_id_len << endl;
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
}
@@ -2355,6 +2389,39 @@ TEST_P(OEMCryptoLicenseTest,
!kCheckStatus);
}
TEST_P(OEMCryptoLicenseTest,
DecryptCENCForNumBytesClearPlusEncryptedOverflowsSize) {
LoadLicense();
OEMCrypto_SelectKey(session_.session_id(), session_.license().keys[0].key_id,
session_.license().keys[0].key_id_length,
OEMCrypto_CipherMode_CTR);
size_t input_buffer_size = 1;
vector<uint8_t> in_buffer(input_buffer_size);
vector<uint8_t> out_buffer(in_buffer.size());
OEMCrypto_SampleDescription sample_description;
OEMCrypto_SubSampleDescription subsample_description;
GenerateSimpleSampleDescription(in_buffer, out_buffer, &sample_description,
&subsample_description);
OEMCrypto_SubSampleDescription* sub_samples =
const_cast<OEMCrypto_SubSampleDescription*>(
sample_description.subsamples);
// If Decrypt cenc API does not check for overflow on clear + encrypted
// addition operation. This will result in 1 which will match with input data
// length, which causes validation to pass.
sub_samples[0].num_bytes_clear = 2;
sub_samples[0].num_bytes_encrypted = 0xFFFFFFFFFFFFFFFF;
// Create the pattern description (always 0,0 for CTR)
OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0};
// Try to decrypt the data
ASSERT_NE(OEMCrypto_SUCCESS,
OEMCrypto_DecryptCENC(session_.session_id(), &sample_description, 1,
&pattern));
}
TEST_P(OEMCryptoLicenseTest,
OEMCryptoMemoryDecryptCENCForHugeNumBytesEncryptedAndBuffers) {
TestDecryptCENCForHugeBufferLengths(
@@ -3850,50 +3917,17 @@ class OEMCryptoSessionTestsDecryptTests
OEMCrypto_SUCCESS);
}
void TestDecryptCENC() {
OEMCryptoResult sts;
void TestDecryptCENC() { ASSERT_EQ(DecryptCENC(), OEMCrypto_SUCCESS); }
// OEMCrypto only supports providing a decrypt hash for one sample.
if (samples_.size() > 1) verify_crc_ = false;
// If supported, check the decrypt hashes.
if (verify_crc_) {
const TestSample& sample = samples_[0];
uint32_t hash =
wvcrc32(sample.truth_buffer.data(), sample.truth_buffer.size());
ASSERT_EQ(OEMCrypto_SetDecryptHash(
session_.session_id(), 1,
reinterpret_cast<const uint8_t*>(&hash), sizeof(hash)),
OEMCrypto_SUCCESS);
}
// Build an array of just the sample descriptions.
std::vector<OEMCrypto_SampleDescription> sample_descriptions;
sample_descriptions.reserve(samples_.size());
for (TestSample& sample : samples_) {
// This must be deferred until this point in case the test modifies the
// buffer before testing decrypt.
sample.description.buffers.input_data = sample.encrypted_buffer.data();
// Append to the description array.
sample_descriptions.push_back(sample.description);
}
// Perform decryption using the test data that was previously set up.
sts = DecryptFallbackChain::Decrypt(
session_.session_id(), sample_descriptions.data(),
sample_descriptions.size(), cipher_mode_, &pattern_);
ASSERT_EQ(sts, OEMCrypto_SUCCESS);
// Validate the decrypted data.
void ValidateDecryptedData() {
for (TestSample& sample : samples_) {
if (sample.description.buffers.output_descriptor.type ==
OEMCrypto_BufferType_Clear) {
const size_t total_size = sample.description.buffers.input_data_length;
// To verify there is no buffer overrun after decrypting, look at the
// padded bytes just after the data buffer that was written. It should
// not have changed from the original 0xaa that we set in MakeBuffer
// function.
// padded bytes just after the data buffer that was written. It
// should not have changed from the original 0xaa that we set in
// MakeBuffer function.
if (decrypt_inplace_) {
EXPECT_EQ(std::count(sample.encrypted_buffer.begin() + total_size,
sample.encrypted_buffer.end(), 0xaa),
@@ -3919,6 +3953,41 @@ class OEMCryptoSessionTestsDecryptTests
}
}
OEMCryptoResult DecryptCENC() {
// OEMCrypto only supports providing a decrypt hash for one sample.
if (samples_.size() > 1) verify_crc_ = false;
// If supported, check the decrypt hashes.
if (verify_crc_) {
const TestSample& sample = samples_[0];
uint32_t hash =
wvcrc32(sample.truth_buffer.data(), sample.truth_buffer.size());
OEMCrypto_SetDecryptHash(session_.session_id(), 1,
reinterpret_cast<const uint8_t*>(&hash),
sizeof(hash));
}
// Build an array of just the sample descriptions.
std::vector<OEMCrypto_SampleDescription> sample_descriptions;
sample_descriptions.reserve(samples_.size());
for (TestSample& sample : samples_) {
// This must be deferred until this point in case the test modifies the
// buffer before testing decrypt.
sample.description.buffers.input_data = sample.encrypted_buffer.data();
// Append to the description array.
sample_descriptions.push_back(sample.description);
}
// Perform decryption using the test data that was previously set up.
OEMCryptoResult result = DecryptFallbackChain::Decrypt(
session_.session_id(), sample_descriptions.data(),
sample_descriptions.size(), cipher_mode_, &pattern_);
if (result != OEMCrypto_SUCCESS) return result;
ValidateDecryptedData();
return result;
}
// Parameters of test case
OEMCrypto_CENCEncryptPatternDesc pattern_;
OEMCryptoCipherMode cipher_mode_;
@@ -4094,7 +4163,6 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSampleAPI16) {
// max_sample_size.
const size_t subsample_size =
std::min(max_sample_size / max_num_subsamples + 1, max_subsample_size);
size_t bytes_remaining = max_sample_size;
std::vector<SubsampleSize> subsample_sizes;
while (bytes_remaining > 0 && subsample_sizes.size() < max_num_subsamples) {
@@ -4113,6 +4181,103 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSampleAPI16) {
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
}
TEST_P(OEMCryptoSessionTestsDecryptTests,
OEMCryptoMemoryDecryptCENCForHugeNumberOfSubSamples) {
auto oemcrypto_function = [&](size_t number_of_subsamples) {
std::vector<SubsampleSize> subsample_sizes;
while (number_of_subsamples-- > 0) {
subsample_sizes.push_back({1, 1});
}
SetSubsampleSizes(subsample_sizes);
LoadLicense();
MakeBuffers();
EncryptData();
OEMCryptoResult result = DecryptCENC();
// Closing the session and opening it for next iteration.
// If it is last iteration, session will be closed in teardown method of
// class.
session_.close();
session_.open();
InstallTestRSAKey(&session_);
return result;
};
TestHugeLengthDoesNotCrashAPI(oemcrypto_function, 1, 2 * MiB, kCheckStatus);
}
TEST_P(OEMCryptoSessionTestsDecryptTests,
OEMCryptoMemoryCheckDecryptCENCStatusForHugeNumberOfSubSamples) {
size_t number_of_subsamples = 10000;
std::vector<SubsampleSize> subsample_sizes;
while (number_of_subsamples-- > 0) {
subsample_sizes.push_back({100, 100});
}
SetSubsampleSizes(subsample_sizes);
LoadLicense();
MakeBuffers();
EncryptData();
// Build an array of just the sample descriptions.
std::vector<OEMCrypto_SampleDescription> sample_descriptions;
sample_descriptions.reserve(samples_.size());
for (TestSample& sample : samples_) {
// This must be deferred until this point in case the test modifies the
// buffer before testing decrypt.
sample.description.buffers.input_data = sample.encrypted_buffer.data();
// Append to the description array.
sample_descriptions.push_back(sample.description);
}
OEMCryptoResult result = OEMCrypto_DecryptCENC(
session_.session_id(), sample_descriptions.data(), 1, &pattern_);
LOGD("Large number of subsamples test has return code %d", result);
}
TEST_P(OEMCryptoSessionTestsDecryptTests,
OEMCryptoMemoryCheckDecryptCENCStatusForHugeSubSample) {
std::vector<SubsampleSize> subsample_sizes;
subsample_sizes.push_back({100000, 100000});
SetSubsampleSizes(subsample_sizes);
LoadLicense();
MakeBuffers();
EncryptData();
// Build an array of just the sample descriptions.
std::vector<OEMCrypto_SampleDescription> sample_descriptions;
sample_descriptions.reserve(samples_.size());
for (TestSample& sample : samples_) {
// This must be deferred until this point in case the test modifies the
// buffer before testing decrypt.
sample.description.buffers.input_data = sample.encrypted_buffer.data();
// Append to the description array.
sample_descriptions.push_back(sample.description);
}
OEMCryptoResult result = OEMCrypto_DecryptCENC(
session_.session_id(), sample_descriptions.data(), 1, &pattern_);
LOGD("Large subsample test has return code %d", result);
}
TEST_P(OEMCryptoSessionTestsDecryptTests,
OEMCryptoMemoryDecryptCENCForHugeNumberOfSamples) {
auto oemcrypto_function = [&](size_t number_of_samples) {
std::vector<std::vector<SubsampleSize>> samples;
std::vector<SubsampleSize> subsample_sizes;
subsample_sizes.push_back({1, 1});
while (number_of_samples-- > 0) {
samples.push_back(subsample_sizes);
}
SetSampleSizes(samples);
LoadLicense();
MakeBuffers();
EncryptData();
OEMCryptoResult result = DecryptCENC();
// Closing the session and opening it for next iteration.
// If it is last iteration, session will be closed in teardown method of
// class.
session_.close();
session_.open();
InstallTestRSAKey(&session_);
return result;
};
TestHugeLengthDoesNotCrashAPI(oemcrypto_function, 1, 2 * MiB, kCheckStatus);
}
// Based on the resource rating, OEMCrypto should be able to handle the maximum
// subsample size.
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSubsample) {