Provisioning Unit Tests
This commit is contained in:
@@ -4902,7 +4902,7 @@ OEMCryptoResult OEMCrypto_AllocateSecureBuffer(
|
||||
* [in] secure_fd: The integer returned by OEMCrypto_AllocateSecureBuffer
|
||||
*
|
||||
* Returns:
|
||||
* OEMCrypto_SUCCESS - if the buffer was created
|
||||
* OEMCrypto_SUCCESS - if the buffer was freed
|
||||
* OEMCrypto_ERROR_NOT_IMPLEMENTED
|
||||
* OEMCrypto_ERROR_UNKNOWN_FAILURE
|
||||
*
|
||||
|
||||
@@ -216,7 +216,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignLicenseRequest(
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (session_ctx == nullptr || !session_ctx->isValid()) {
|
||||
LOGE("ERROR_INVALID_SESSION");
|
||||
LOGE("OEMCrypto_ERROR_INVALID_SESSION");
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
return session_ctx->PrepAndSignLicenseRequest(message, message_length,
|
||||
@@ -233,7 +233,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (session_ctx == nullptr || !session_ctx->isValid()) {
|
||||
LOGE("ERROR_INVALID_SESSION");
|
||||
LOGE("OEMCrypto_ERROR_INVALID_SESSION");
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
return session_ctx->PrepAndSignRenewalRequest(message, message_length,
|
||||
@@ -250,7 +250,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignProvisioningRequest(
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (session_ctx == nullptr || !session_ctx->isValid()) {
|
||||
LOGE("ERROR_INVALID_SESSION");
|
||||
LOGE("OEMCrypto_ERROR_INVALID_SESSION");
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
return session_ctx->PrepAndSignProvisioningRequest(
|
||||
@@ -698,7 +698,7 @@ OEMCrypto_LoadOEMPrivateKey(OEMCrypto_SESSION session) {
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (session_ctx == nullptr || !session_ctx->isValid()) {
|
||||
LOGE("ERROR_INVALID_SESSION");
|
||||
LOGE("OEMCrypto_ERROR_INVALID_SESSION");
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
return crypto_engine->load_oem_private_key(session_ctx);
|
||||
@@ -787,7 +787,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData,
|
||||
}
|
||||
|
||||
// This function is no longer exported -- it is only used by LoadProvisioning.
|
||||
OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
|
||||
static OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
|
||||
OEMCrypto_SESSION session, const uint32_t* unaligned_nonce,
|
||||
const uint8_t* encrypted_message_key, size_t encrypted_message_key_length,
|
||||
const uint8_t* enc_rsa_key, size_t enc_rsa_key_length,
|
||||
@@ -901,7 +901,7 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
|
||||
}
|
||||
|
||||
// This function is no longer exported -- it is only used by LoadProvisioning.
|
||||
OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
|
||||
static OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
|
||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length,
|
||||
const uint32_t* unaligned_nonce, const uint8_t* enc_rsa_key,
|
||||
@@ -1023,22 +1023,18 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadProvisioning(
|
||||
LOGE("OEMCrypto Not Initialized");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (wrapped_private_key_length == nullptr) {
|
||||
LOGE("OEMCrypto_ERROR_INVALID_CONTEXT");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (message == nullptr || message_length == 0 || signature == nullptr ||
|
||||
signature_length == 0) {
|
||||
if (wrapped_private_key_length == nullptr || message == nullptr ||
|
||||
message_length == 0 || signature == nullptr || signature_length == 0) {
|
||||
LOGE("OEMCrypto_ERROR_INVALID_CONTEXT");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (!crypto_engine->ValidRootOfTrust()) {
|
||||
LOGE("ERROR_KEYBOX_INVALID");
|
||||
LOGE("OEMCrypto_ERROR_KEYBOX_INVALID");
|
||||
return OEMCrypto_ERROR_KEYBOX_INVALID;
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (session_ctx == nullptr || !session_ctx->isValid()) {
|
||||
LOGE("ERROR_INVALID_SESSION");
|
||||
LOGE("OEMCrypto_ERROR_INVALID_SESSION");
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
std::vector<uint8_t> device_id = crypto_engine->DeviceRootId();
|
||||
@@ -1705,4 +1701,16 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetHashErrorCode(
|
||||
return session_ctx->GetHashErrorCode(failed_frame_number);
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_AllocateSecureBuffer(
|
||||
OEMCrypto_SESSION session, size_t buffer_size,
|
||||
OEMCrypto_DestBufferDesc* output_descriptor, int* secure_fd) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
OEMCRYPTO_API OEMCryptoResult OEMCrypto_FreeSecureBuffer(
|
||||
OEMCrypto_SESSION session, OEMCrypto_DestBufferDesc* output_descriptor,
|
||||
int secure_fd) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
@@ -60,9 +60,8 @@ bool CanChangeTime() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void DeviceFeatures::Initialize(bool is_cast_receiver,
|
||||
bool force_load_test_keybox) {
|
||||
cast_receiver = is_cast_receiver;
|
||||
void DeviceFeatures::Initialize() {
|
||||
if (initialized_) return;
|
||||
uses_keybox = false;
|
||||
uses_certificate = false;
|
||||
loads_certificate = false;
|
||||
@@ -117,11 +116,7 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
|
||||
// usage tables.
|
||||
if (api_version > 12) usage_table = OEMCrypto_SupportsUsageTable();
|
||||
printf("usage_table = %s.\n", usage_table ? "true" : "false");
|
||||
if (force_load_test_keybox) {
|
||||
derive_key_method = FORCE_TEST_KEYBOX;
|
||||
} else {
|
||||
PickDerivedKey();
|
||||
}
|
||||
PickDerivedKey();
|
||||
if (api_version >= 13) {
|
||||
uint32_t supported_cert = OEMCrypto_SupportedCertificates();
|
||||
if (supported_cert & OEMCrypto_Supports_RSA_CAST) {
|
||||
@@ -161,9 +156,6 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
|
||||
case LOAD_TEST_RSA_KEY:
|
||||
printf("LOAD_TEST_RSA_KEY: Call LoadTestRSAKey before deriving keys.\n");
|
||||
break;
|
||||
case FORCE_TEST_KEYBOX:
|
||||
printf("FORCE_TEST_KEYBOX: User requested calling InstallKeybox.\n");
|
||||
break;
|
||||
case TEST_PROVISION_30:
|
||||
printf("TEST_PROVISION_30: Device provisioed with OEM Cert.\n");
|
||||
break;
|
||||
@@ -173,15 +165,15 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
|
||||
printf("SecurityLevel is %s (%s)\n",
|
||||
supports_level_1 ? "Level 1" : "Not Level 1",
|
||||
security_level.c_str());
|
||||
CheckSecureBuffers();
|
||||
OEMCrypto_Terminate();
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
|
||||
std::string filter = initial_filter;
|
||||
// clang-format off
|
||||
if (!uses_keybox) FilterOut(&filter, "*KeyboxTest*");
|
||||
if (derive_key_method
|
||||
!= FORCE_TEST_KEYBOX) FilterOut(&filter, "*ForceKeybox*");
|
||||
if (!uses_certificate) FilterOut(&filter, "OEMCrypto*Cert*");
|
||||
if (!loads_certificate) FilterOut(&filter, "OEMCryptoLoadsCert*");
|
||||
if (!generic_crypto) FilterOut(&filter, "*GenericCrypto*");
|
||||
@@ -246,6 +238,39 @@ void DeviceFeatures::PickDerivedKey() {
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceFeatures::CheckSecureBuffers() {
|
||||
output_types_.push_back({false, OEMCrypto_BufferType_Clear});
|
||||
output_types_.push_back({true, OEMCrypto_BufferType_Clear});
|
||||
test_secure_buffers = false;
|
||||
OEMCrypto_SESSION session;
|
||||
OEMCryptoResult result = OEMCrypto_OpenSession(&session);
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
printf("--- ERROR: Could not open session: %d ----\n", result);
|
||||
return;
|
||||
}
|
||||
OEMCrypto_DestBufferDesc output_descriptor;
|
||||
output_descriptor.type = OEMCrypto_BufferType_Secure;
|
||||
int secure_fd;
|
||||
result = OEMCrypto_AllocateSecureBuffer(session, 42, &output_descriptor,
|
||||
&secure_fd);
|
||||
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
||||
printf("Secure buffers will not be tested\n");
|
||||
return;
|
||||
}
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
printf("--- ERROR: Could not create secure buffer: %d ----\n", result);
|
||||
return;
|
||||
}
|
||||
result = OEMCrypto_FreeSecureBuffer(session, &output_descriptor, secure_fd);
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
printf("--- ERROR: Could not free secure buffer: %d ----\n", result);
|
||||
return;
|
||||
}
|
||||
printf("Secure buffers will be tested\n");
|
||||
output_types_.push_back({false, OEMCrypto_BufferType_Secure});
|
||||
test_secure_buffers = true;
|
||||
}
|
||||
|
||||
void DeviceFeatures::FilterOut(std::string* current_filter,
|
||||
const std::string& new_filter) {
|
||||
if (current_filter->find('-') == std::string::npos) {
|
||||
@@ -255,6 +280,14 @@ void DeviceFeatures::FilterOut(std::string* current_filter,
|
||||
}
|
||||
}
|
||||
|
||||
// Return the list of output types for the decrypt tests.
|
||||
const std::vector<OutputType>& DeviceFeatures::GetOutputTypes() {
|
||||
if (!initialized_) {
|
||||
Initialize();
|
||||
}
|
||||
return output_types_;
|
||||
}
|
||||
|
||||
const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method) {
|
||||
switch (method) {
|
||||
case OEMCrypto_ProvisioningError:
|
||||
|
||||
@@ -2,12 +2,21 @@
|
||||
#define CDM_OEC_DEVICE_FEATURES_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec {
|
||||
|
||||
// An output type for testing. The type field is secure, clear, or direct. If
|
||||
// the type is clear, then decrypt_inplace could be true. Otherwise,
|
||||
// decrypt_inplace is false.
|
||||
struct OutputType {
|
||||
bool decrypt_inplace;
|
||||
OEMCryptoBufferType type;
|
||||
};
|
||||
|
||||
// Keeps track of which features are supported by the version of OEMCrypto being
|
||||
// tested. See the integration guide for a list of optional features.
|
||||
class DeviceFeatures {
|
||||
@@ -19,7 +28,6 @@ class DeviceFeatures {
|
||||
NO_METHOD, // Cannot derive known session keys.
|
||||
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
|
||||
LOAD_TEST_RSA_KEY, // Call LoadTestRSAKey before deriving keys.
|
||||
FORCE_TEST_KEYBOX, // User requested calling InstallKeybox.
|
||||
TEST_PROVISION_30, // Device has OEM Certificate installed.
|
||||
};
|
||||
|
||||
@@ -34,23 +42,36 @@ class DeviceFeatures {
|
||||
bool supports_level_1; // Device supports Level 1 security.
|
||||
uint32_t resource_rating; // Device's resource rating tier.
|
||||
bool supports_crc; // Supported decrypt hash type CRC.
|
||||
bool test_secure_buffers; // If we can create a secure buffer for testing.
|
||||
uint32_t api_version;
|
||||
OEMCrypto_ProvisioningMethod provisioning_method;
|
||||
|
||||
// This should be called from the test program's main procedure.
|
||||
void Initialize(bool is_cast_receiver, bool force_load_test_keybox);
|
||||
void Initialize();
|
||||
void set_cast_receiver(bool is_cast_receiver) {
|
||||
cast_receiver = is_cast_receiver;
|
||||
}
|
||||
// Generate a GTest filter of tests that should not be run. This should be
|
||||
// called after Initialize. Tests are filtered out based on which features
|
||||
// are not supported. For example, a device that uses Provisioning 3.0 will
|
||||
// have all keybox tests filtered out.
|
||||
std::string RestrictFilter(const std::string& initial_filter);
|
||||
|
||||
// Get a list of output types that should be tested.
|
||||
const std::vector<OutputType>& GetOutputTypes();
|
||||
|
||||
private:
|
||||
// Decide which method should be used to derive session keys, based on
|
||||
// supported featuers.
|
||||
void PickDerivedKey();
|
||||
// Decide if secure buffers can be created, and initialize output_types_.
|
||||
void CheckSecureBuffers();
|
||||
// Add a GTest filter restriction to the current filter.
|
||||
void FilterOut(std::string* current_filter, const std::string& new_filter);
|
||||
|
||||
// A list of possible output types.
|
||||
std::vector<OutputType> output_types_;
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
||||
// There is one global set of features for the version of OEMCrypto being
|
||||
|
||||
@@ -222,6 +222,7 @@ class ProvisioningRoundTrip
|
||||
const std::vector<uint8_t>& encoded_rsa_key)
|
||||
: RoundTrip(session),
|
||||
allowed_schemes_(kSign_RSASSA_PSS),
|
||||
encryptor_(),
|
||||
encoded_rsa_key_(encoded_rsa_key) {}
|
||||
// Prepare the session for signing the request.
|
||||
virtual void PrepareSession(const wvoec::WidevineKeybox& keybox);
|
||||
|
||||
@@ -60,10 +60,6 @@ void SessionUtil::EnsureTestKeys() {
|
||||
case DeviceFeatures::LOAD_TEST_RSA_KEY:
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
|
||||
break;
|
||||
case DeviceFeatures::FORCE_TEST_KEYBOX:
|
||||
keybox_ = kTestKeybox;
|
||||
InstallKeybox(keybox_, true);
|
||||
break;
|
||||
case DeviceFeatures::TEST_PROVISION_30:
|
||||
// Can use oem certificate to install test rsa key.
|
||||
break;
|
||||
|
||||
@@ -52,14 +52,31 @@ using namespace std;
|
||||
|
||||
namespace std { // GTest wants PrintTo to be in the std namespace.
|
||||
void PrintTo(const tuple<OEMCrypto_CENCEncryptPatternDesc, OEMCryptoCipherMode,
|
||||
bool>& param,
|
||||
wvoec::OutputType>& param,
|
||||
ostream* os) {
|
||||
OEMCrypto_CENCEncryptPatternDesc pattern = ::testing::get<0>(param);
|
||||
OEMCryptoCipherMode mode = ::testing::get<1>(param);
|
||||
bool decrypt_inplace = ::testing::get<2>(param);
|
||||
wvoec::OutputType output = ::testing::get<2>(param);
|
||||
bool decrypt_inplace = output.decrypt_inplace;
|
||||
OEMCryptoBufferType type = output.type;
|
||||
*os << ((mode == OEMCrypto_CipherMode_CTR) ? "CTR mode" : "CBC mode")
|
||||
<< ", encrypt=" << pattern.encrypt << ", skip=" << pattern.skip
|
||||
<< ", decrypt in place = " << (decrypt_inplace ? "true" : "false");
|
||||
<< ", pattern=(encrypt:" << pattern.encrypt << ", skip:" << pattern.skip
|
||||
<< ")";
|
||||
switch (type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
*os << ", BufferType = Clear";
|
||||
break;
|
||||
case OEMCrypto_BufferType_Secure:
|
||||
*os << ", BufferType = Secure";
|
||||
break;
|
||||
case OEMCrypto_BufferType_Direct:
|
||||
*os << ", BufferType = Direct";
|
||||
break;
|
||||
default:
|
||||
*os << ", type = <bad type " << type << ">";
|
||||
break;
|
||||
}
|
||||
if (decrypt_inplace) *os << " (in place)";
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
@@ -743,13 +760,6 @@ class OEMCryptoSessionTests : public OEMCryptoClientTest {
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// If we installed a bad keybox, end with a good one installed.
|
||||
if (global_features.derive_key_method == DeviceFeatures::FORCE_TEST_KEYBOX)
|
||||
InstallKeybox(kTestKeybox, true);
|
||||
OEMCryptoClientTest::TearDown();
|
||||
}
|
||||
|
||||
vector<uint8_t> encrypted_usage_header_;
|
||||
};
|
||||
|
||||
@@ -759,53 +769,6 @@ TEST_F(OEMCryptoSessionTestKeyboxTest, TestKeyboxIsValid) {
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTestKeyboxTest, GoodForceKeybox) {
|
||||
ASSERT_EQ(DeviceFeatures::FORCE_TEST_KEYBOX,
|
||||
global_features.derive_key_method)
|
||||
<< "ForceKeybox tests will modify the installed keybox.";
|
||||
wvoec::WidevineKeybox keybox = kTestKeybox;
|
||||
OEMCryptoResult sts;
|
||||
InstallKeybox(keybox, true);
|
||||
sts = OEMCrypto_IsKeyboxValid();
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTestKeyboxTest, BadCRCForceKeybox) {
|
||||
ASSERT_EQ(DeviceFeatures::FORCE_TEST_KEYBOX,
|
||||
global_features.derive_key_method)
|
||||
<< "ForceKeybox tests will modify the installed keybox.";
|
||||
wvoec::WidevineKeybox keybox = kTestKeybox;
|
||||
keybox.crc_[1] ^= 42;
|
||||
OEMCryptoResult sts;
|
||||
InstallKeybox(keybox, false);
|
||||
sts = OEMCrypto_IsKeyboxValid();
|
||||
ASSERT_EQ(OEMCrypto_ERROR_BAD_CRC, sts);
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTestKeyboxTest, BadMagicForceKeybox) {
|
||||
ASSERT_EQ(DeviceFeatures::FORCE_TEST_KEYBOX,
|
||||
global_features.derive_key_method)
|
||||
<< "ForceKeybox tests will modify the installed keybox.";
|
||||
wvoec::WidevineKeybox keybox = kTestKeybox;
|
||||
keybox.magic_[1] ^= 42;
|
||||
OEMCryptoResult sts;
|
||||
InstallKeybox(keybox, false);
|
||||
sts = OEMCrypto_IsKeyboxValid();
|
||||
ASSERT_EQ(OEMCrypto_ERROR_BAD_MAGIC, sts);
|
||||
}
|
||||
|
||||
TEST_F(OEMCryptoSessionTestKeyboxTest, BadDataForceKeybox) {
|
||||
ASSERT_EQ(DeviceFeatures::FORCE_TEST_KEYBOX,
|
||||
global_features.derive_key_method)
|
||||
<< "ForceKeybox tests will modify the installed keybox.";
|
||||
wvoec::WidevineKeybox keybox = kTestKeybox;
|
||||
keybox.data_[1] ^= 42;
|
||||
OEMCryptoResult sts;
|
||||
InstallKeybox(keybox, false);
|
||||
sts = OEMCrypto_IsKeyboxValid();
|
||||
ASSERT_EQ(OEMCrypto_ERROR_BAD_CRC, sts);
|
||||
}
|
||||
|
||||
// Verify that a license may be signed.
|
||||
TEST_F(OEMCryptoSessionTests, SignLicenseRequest) {
|
||||
Session s;
|
||||
@@ -1894,14 +1857,15 @@ struct SampleInitData {
|
||||
// buffers to be the same.
|
||||
class OEMCryptoSessionTestsDecryptTests
|
||||
: public OEMCryptoSessionTests,
|
||||
public WithParamInterface<
|
||||
tuple<OEMCrypto_CENCEncryptPatternDesc, OEMCryptoCipherMode, bool> > {
|
||||
public WithParamInterface<tuple<OEMCrypto_CENCEncryptPatternDesc,
|
||||
OEMCryptoCipherMode, OutputType> > {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
OEMCryptoSessionTests::SetUp();
|
||||
pattern_ = ::testing::get<0>(GetParam());
|
||||
cipher_mode_ = ::testing::get<1>(GetParam());
|
||||
decrypt_inplace_ = ::testing::get<2>(GetParam());
|
||||
decrypt_inplace_ = ::testing::get<2>(GetParam()).decrypt_inplace;
|
||||
output_buffer_type_ = ::testing::get<2>(GetParam()).type;
|
||||
verify_crc_ = global_features.supports_crc;
|
||||
// Pick a random key.
|
||||
EXPECT_EQ(1, GetRandBytes(key_, AES_BLOCK_SIZE));
|
||||
@@ -1912,6 +1876,7 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
FreeBuffers();
|
||||
ASSERT_NO_FATAL_FAILURE(session_.close());
|
||||
OEMCryptoSessionTests::TearDown();
|
||||
}
|
||||
@@ -1924,32 +1889,76 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the input buffer and output buffer.
|
||||
// Set up the input buffer and either a clear or secure 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_.type = output_buffer_type_;
|
||||
switch (output_descriptor_.type) {
|
||||
case 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.address_length = total_size_;
|
||||
break;
|
||||
case OEMCrypto_BufferType_Secure:
|
||||
output_descriptor_.buffer.secure.handle_length = total_size_;
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_AllocateSecureBuffer(
|
||||
session_.session_id(), total_size_, &output_descriptor_,
|
||||
&secure_buffer_fid_));
|
||||
ASSERT_NE(nullptr, output_descriptor_.buffer.secure.handle);
|
||||
// It is OK if OEMCrypto changes the maximum size, but there must still
|
||||
// be enough room for our data.
|
||||
ASSERT_GE(output_descriptor_.buffer.secure.handle_length, total_size_);
|
||||
output_descriptor_.buffer.secure.offset = 0;
|
||||
break;
|
||||
case OEMCrypto_BufferType_Direct:
|
||||
output_descriptor_.buffer.direct.is_video = false;
|
||||
break;
|
||||
default:
|
||||
ASSERT_TRUE(false) << "Invalid buffer type.";
|
||||
}
|
||||
output_descriptor_.buffer.clear.address_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;
|
||||
switch (output_descriptor_.type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
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.address_length = total_size_ - offset;
|
||||
break;
|
||||
case OEMCrypto_BufferType_Secure:
|
||||
ASSERT_NE(nullptr, output_descriptor_.buffer.secure.handle);
|
||||
ASSERT_GE(output_descriptor_.buffer.secure.handle_length, total_size_);
|
||||
output_descriptor_.buffer.secure.offset = offset;
|
||||
break;
|
||||
case OEMCrypto_BufferType_Direct:
|
||||
break;
|
||||
default:
|
||||
ASSERT_TRUE(false) << "Invalid buffer type.";
|
||||
}
|
||||
}
|
||||
|
||||
void FreeBuffers() {
|
||||
if (output_descriptor_.type == OEMCrypto_BufferType_Secure) {
|
||||
ASSERT_EQ(
|
||||
OEMCrypto_SUCCESS,
|
||||
OEMCrypto_FreeSecureBuffer(session_.session_id(), &output_descriptor_,
|
||||
secure_buffer_fid_));
|
||||
}
|
||||
output_descriptor_.buffer.clear.address_length = total_size_ - offset;
|
||||
}
|
||||
|
||||
void EncryptData() {
|
||||
@@ -2035,6 +2044,8 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestRSAKey(&session_));
|
||||
uint32_t control = 0;
|
||||
if (verify_crc_) control |= kControlAllowHashVerification;
|
||||
if (output_buffer_type_ == OEMCrypto_BufferType_Secure)
|
||||
control |= kControlObserveDataPath | kControlDataPathSecure;
|
||||
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_;
|
||||
@@ -2130,6 +2141,7 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
OEMCrypto_CENCEncryptPatternDesc pattern_;
|
||||
OEMCryptoCipherMode cipher_mode_;
|
||||
bool decrypt_inplace_; // If true, input and output buffers are the same.
|
||||
OEMCryptoBufferType output_buffer_type_;
|
||||
vector<SampleSize> subsample_size_;
|
||||
size_t total_size_;
|
||||
bool verify_crc_;
|
||||
@@ -2137,9 +2149,9 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
// 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_;
|
||||
int secure_buffer_fid_;
|
||||
uint8_t key_[AES_BLOCK_SIZE]; // Encryption Key.
|
||||
std::vector<uint8_t> starting_iv_; // Starting IV.
|
||||
Session session_;
|
||||
@@ -2156,8 +2168,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) {
|
||||
// full patterns if we have more than 320 -- round up to 400.
|
||||
subsample_size_.push_back(SampleSize(0, 400));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2169,8 +2181,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) {
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, PatternPlusOneBlock) {
|
||||
subsample_size_.push_back(SampleSize(0, 160 + 16));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2179,8 +2191,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, PatternPlusOneBlock) {
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, OneBlock) {
|
||||
subsample_size_.push_back(SampleSize(0, 16));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2193,8 +2205,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, NoOffset) {
|
||||
subsample_size_.push_back(SampleSize(50, 256));
|
||||
subsample_size_.push_back(SampleSize(25, 160));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2209,8 +2221,8 @@ TEST_P(OEMCryptoSessionTestsPartialBlockTests, EvenOffset) {
|
||||
subsample_size_.push_back(SampleSize(25, 32));
|
||||
subsample_size_.push_back(SampleSize(25, 50));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
// 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
|
||||
@@ -2237,8 +2249,8 @@ TEST_P(OEMCryptoSessionTestsPartialBlockTests, OddOffset) {
|
||||
subsample_size_.push_back(SampleSize(10, 75));
|
||||
subsample_size_.push_back(SampleSize(10, 25));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2257,8 +2269,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptWithNearWrap) {
|
||||
starting_iv_ = wvcdm::a2b_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE");
|
||||
subsample_size_.push_back(SampleSize(0, 256));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2272,8 +2284,8 @@ 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();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2292,8 +2304,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSample) {
|
||||
subsample_size_.push_back(SampleSize(0, max_subsample_size));
|
||||
}
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2304,8 +2316,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSubsample) {
|
||||
subsample_size_.push_back(SampleSize(max_subsample_size, 0));
|
||||
subsample_size_.push_back(SampleSize(0, max_subsample_size));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2314,8 +2326,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSubsample) {
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptSmallBuffer) {
|
||||
subsample_size_.push_back(SampleSize(5, 5));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2325,8 +2337,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptSmallBuffer) {
|
||||
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptUnencrypted) {
|
||||
subsample_size_.push_back(SampleSize(256, 0));
|
||||
FindTotalSize();
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
|
||||
ASSERT_NO_FATAL_FAILURE(EncryptData());
|
||||
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
|
||||
}
|
||||
@@ -2354,47 +2366,41 @@ OEMCrypto_CENCEncryptPatternDesc MakePattern(size_t encrypt, size_t skip) {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CTRTests, OEMCryptoSessionTestsPartialBlockTests,
|
||||
Combine(Values(MakePattern(0,0)),
|
||||
Values(OEMCrypto_CipherMode_CTR),
|
||||
Bool()));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
CTRTests, OEMCryptoSessionTestsPartialBlockTests,
|
||||
Combine(Values(MakePattern(0, 0)), Values(OEMCrypto_CipherMode_CTR),
|
||||
::testing::ValuesIn(global_features.GetOutputTypes())));
|
||||
|
||||
// Decrypt in place for CBC tests was only required in v13.
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
CBCTestsAPI14, OEMCryptoSessionTestsPartialBlockTests,
|
||||
Combine(
|
||||
Values(MakePattern(0, 0),
|
||||
MakePattern(3, 7),
|
||||
Values(MakePattern(0, 0), MakePattern(3, 7),
|
||||
// HLS Edge case. We should follow the CENC spec, not HLS spec.
|
||||
MakePattern(9, 1),
|
||||
MakePattern(1, 9),
|
||||
MakePattern(1, 3),
|
||||
MakePattern(9, 1), MakePattern(1, 9), MakePattern(1, 3),
|
||||
MakePattern(2, 1)),
|
||||
Values(OEMCrypto_CipherMode_CBC), Bool()));
|
||||
Values(OEMCrypto_CipherMode_CBC),
|
||||
::testing::ValuesIn(global_features.GetOutputTypes())));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
CTRTestsAPI11, OEMCryptoSessionTestsDecryptTests,
|
||||
Combine(
|
||||
Values(MakePattern(0, 0),
|
||||
MakePattern(3, 7),
|
||||
// Pattern length should be 10, but that is not guaranteed.
|
||||
MakePattern(1, 3),
|
||||
MakePattern(2, 1)),
|
||||
Values(OEMCrypto_CipherMode_CTR), Bool()));
|
||||
Combine(Values(MakePattern(0, 0), MakePattern(3, 7),
|
||||
// Pattern length should be 10, but that is not guaranteed.
|
||||
MakePattern(1, 3), MakePattern(2, 1)),
|
||||
Values(OEMCrypto_CipherMode_CTR),
|
||||
::testing::ValuesIn(global_features.GetOutputTypes())));
|
||||
|
||||
// Decrypt in place for CBC tests was only required in v13.
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
CBCTestsAPI14, OEMCryptoSessionTestsDecryptTests,
|
||||
Combine(
|
||||
Values(MakePattern(0, 0),
|
||||
MakePattern(3, 7),
|
||||
Values(MakePattern(0, 0), MakePattern(3, 7),
|
||||
// HLS Edge case. We should follow the CENC spec, not HLS spec.
|
||||
MakePattern(9, 1),
|
||||
MakePattern(1, 9),
|
||||
MakePattern(9, 1), MakePattern(1, 9),
|
||||
// Pattern length should be 10, but that is not guaranteed.
|
||||
MakePattern(1, 3),
|
||||
MakePattern(2, 1)),
|
||||
Values(OEMCrypto_CipherMode_CBC), Bool()));
|
||||
MakePattern(1, 3), MakePattern(2, 1)),
|
||||
Values(OEMCrypto_CipherMode_CBC),
|
||||
::testing::ValuesIn(global_features.GetOutputTypes())));
|
||||
|
||||
// A request to decrypt data to a clear buffer when the key control block
|
||||
// requires a secure data path.
|
||||
@@ -5171,7 +5177,7 @@ TEST_P(OEMCryptoUsageTableTestWithMAC, OfflineLicenseRefresh) {
|
||||
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
s.GenerateVerifyReport(pst, kActive,
|
||||
loaded, // license recieved.
|
||||
loaded, // license received.
|
||||
loaded, // First decrypt when loaded, not refresh.
|
||||
0)); // last decrypt now.
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ static void acknowledge_cast() {
|
||||
// because we need to initialize the list of features supported by the device.
|
||||
// Also, the test filter is updated based on the feature list.
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
bool is_cast_receiver = false;
|
||||
bool force_load_test_keybox = false;
|
||||
bool filter_tests = true;
|
||||
int verbosity = 0;
|
||||
// Skip the first element, which is the program name.
|
||||
@@ -32,7 +30,8 @@ int main(int argc, char** argv) {
|
||||
is_cast_receiver = true;
|
||||
}
|
||||
if (arg == "--force_load_test_keybox") {
|
||||
force_load_test_keybox = true;
|
||||
std::cerr << "The argument --force_load_test_keybox is obsolete.\n";
|
||||
return 1;
|
||||
}
|
||||
if (arg == "--no_filter") {
|
||||
filter_tests = false;
|
||||
@@ -42,7 +41,10 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
wvcdm::g_cutoff = static_cast<wvcdm::LogPriority>(verbosity);
|
||||
wvoec::global_features.Initialize(is_cast_receiver, force_load_test_keybox);
|
||||
wvoec::global_features.Initialize();
|
||||
wvoec::global_features.set_cast_receiver(is_cast_receiver);
|
||||
// Init GTest after device properties has been initialized.
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
// If the user requests --no_filter, we don't change the filter, otherwise, we
|
||||
// filter out features that are not supported.
|
||||
if (filter_tests) {
|
||||
|
||||
Reference in New Issue
Block a user