Provisioning Unit Tests

This commit is contained in:
Fred Gylys-Colwell
2019-12-13 11:14:12 -08:00
parent 5b9580a351
commit ff7cc16e4a
8 changed files with 219 additions and 152 deletions

View File

@@ -4902,7 +4902,7 @@ OEMCryptoResult OEMCrypto_AllocateSecureBuffer(
* [in] secure_fd: The integer returned by OEMCrypto_AllocateSecureBuffer * [in] secure_fd: The integer returned by OEMCrypto_AllocateSecureBuffer
* *
* Returns: * Returns:
* OEMCrypto_SUCCESS - if the buffer was created * OEMCrypto_SUCCESS - if the buffer was freed
* OEMCrypto_ERROR_NOT_IMPLEMENTED * OEMCrypto_ERROR_NOT_IMPLEMENTED
* OEMCrypto_ERROR_UNKNOWN_FAILURE * OEMCrypto_ERROR_UNKNOWN_FAILURE
* *

View File

@@ -216,7 +216,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignLicenseRequest(
} }
SessionContext* session_ctx = crypto_engine->FindSession(session); SessionContext* session_ctx = crypto_engine->FindSession(session);
if (session_ctx == nullptr || !session_ctx->isValid()) { if (session_ctx == nullptr || !session_ctx->isValid()) {
LOGE("ERROR_INVALID_SESSION"); LOGE("OEMCrypto_ERROR_INVALID_SESSION");
return OEMCrypto_ERROR_INVALID_SESSION; return OEMCrypto_ERROR_INVALID_SESSION;
} }
return session_ctx->PrepAndSignLicenseRequest(message, message_length, return session_ctx->PrepAndSignLicenseRequest(message, message_length,
@@ -233,7 +233,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest(
} }
SessionContext* session_ctx = crypto_engine->FindSession(session); SessionContext* session_ctx = crypto_engine->FindSession(session);
if (session_ctx == nullptr || !session_ctx->isValid()) { if (session_ctx == nullptr || !session_ctx->isValid()) {
LOGE("ERROR_INVALID_SESSION"); LOGE("OEMCrypto_ERROR_INVALID_SESSION");
return OEMCrypto_ERROR_INVALID_SESSION; return OEMCrypto_ERROR_INVALID_SESSION;
} }
return session_ctx->PrepAndSignRenewalRequest(message, message_length, return session_ctx->PrepAndSignRenewalRequest(message, message_length,
@@ -250,7 +250,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignProvisioningRequest(
} }
SessionContext* session_ctx = crypto_engine->FindSession(session); SessionContext* session_ctx = crypto_engine->FindSession(session);
if (session_ctx == nullptr || !session_ctx->isValid()) { if (session_ctx == nullptr || !session_ctx->isValid()) {
LOGE("ERROR_INVALID_SESSION"); LOGE("OEMCrypto_ERROR_INVALID_SESSION");
return OEMCrypto_ERROR_INVALID_SESSION; return OEMCrypto_ERROR_INVALID_SESSION;
} }
return session_ctx->PrepAndSignProvisioningRequest( return session_ctx->PrepAndSignProvisioningRequest(
@@ -698,7 +698,7 @@ OEMCrypto_LoadOEMPrivateKey(OEMCrypto_SESSION session) {
} }
SessionContext* session_ctx = crypto_engine->FindSession(session); SessionContext* session_ctx = crypto_engine->FindSession(session);
if (session_ctx == nullptr || !session_ctx->isValid()) { if (session_ctx == nullptr || !session_ctx->isValid()) {
LOGE("ERROR_INVALID_SESSION"); LOGE("OEMCrypto_ERROR_INVALID_SESSION");
return OEMCrypto_ERROR_INVALID_SESSION; return OEMCrypto_ERROR_INVALID_SESSION;
} }
return crypto_engine->load_oem_private_key(session_ctx); 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. // 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, OEMCrypto_SESSION session, const uint32_t* unaligned_nonce,
const uint8_t* encrypted_message_key, size_t encrypted_message_key_length, const uint8_t* encrypted_message_key, size_t encrypted_message_key_length,
const uint8_t* enc_rsa_key, size_t enc_rsa_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. // 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, OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
const uint8_t* signature, size_t signature_length, const uint8_t* signature, size_t signature_length,
const uint32_t* unaligned_nonce, const uint8_t* enc_rsa_key, const uint32_t* unaligned_nonce, const uint8_t* enc_rsa_key,
@@ -1023,22 +1023,18 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadProvisioning(
LOGE("OEMCrypto Not Initialized"); LOGE("OEMCrypto Not Initialized");
return OEMCrypto_ERROR_UNKNOWN_FAILURE; return OEMCrypto_ERROR_UNKNOWN_FAILURE;
} }
if (wrapped_private_key_length == nullptr) { if (wrapped_private_key_length == nullptr || message == nullptr ||
LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); message_length == 0 || signature == nullptr || signature_length == 0) {
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (message == nullptr || message_length == 0 || signature == nullptr ||
signature_length == 0) {
LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); LOGE("OEMCrypto_ERROR_INVALID_CONTEXT");
return OEMCrypto_ERROR_INVALID_CONTEXT; return OEMCrypto_ERROR_INVALID_CONTEXT;
} }
if (!crypto_engine->ValidRootOfTrust()) { if (!crypto_engine->ValidRootOfTrust()) {
LOGE("ERROR_KEYBOX_INVALID"); LOGE("OEMCrypto_ERROR_KEYBOX_INVALID");
return OEMCrypto_ERROR_KEYBOX_INVALID; return OEMCrypto_ERROR_KEYBOX_INVALID;
} }
SessionContext* session_ctx = crypto_engine->FindSession(session); SessionContext* session_ctx = crypto_engine->FindSession(session);
if (session_ctx == nullptr || !session_ctx->isValid()) { if (session_ctx == nullptr || !session_ctx->isValid()) {
LOGE("ERROR_INVALID_SESSION"); LOGE("OEMCrypto_ERROR_INVALID_SESSION");
return OEMCrypto_ERROR_INVALID_SESSION; return OEMCrypto_ERROR_INVALID_SESSION;
} }
std::vector<uint8_t> device_id = crypto_engine->DeviceRootId(); 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); 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 } // namespace wvoec_ref

View File

@@ -60,9 +60,8 @@ bool CanChangeTime() {
#endif #endif
} }
void DeviceFeatures::Initialize(bool is_cast_receiver, void DeviceFeatures::Initialize() {
bool force_load_test_keybox) { if (initialized_) return;
cast_receiver = is_cast_receiver;
uses_keybox = false; uses_keybox = false;
uses_certificate = false; uses_certificate = false;
loads_certificate = false; loads_certificate = false;
@@ -117,11 +116,7 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
// usage tables. // usage tables.
if (api_version > 12) usage_table = OEMCrypto_SupportsUsageTable(); if (api_version > 12) usage_table = OEMCrypto_SupportsUsageTable();
printf("usage_table = %s.\n", usage_table ? "true" : "false"); 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) { if (api_version >= 13) {
uint32_t supported_cert = OEMCrypto_SupportedCertificates(); uint32_t supported_cert = OEMCrypto_SupportedCertificates();
if (supported_cert & OEMCrypto_Supports_RSA_CAST) { if (supported_cert & OEMCrypto_Supports_RSA_CAST) {
@@ -161,9 +156,6 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
case LOAD_TEST_RSA_KEY: case LOAD_TEST_RSA_KEY:
printf("LOAD_TEST_RSA_KEY: Call LoadTestRSAKey before deriving keys.\n"); printf("LOAD_TEST_RSA_KEY: Call LoadTestRSAKey before deriving keys.\n");
break; break;
case FORCE_TEST_KEYBOX:
printf("FORCE_TEST_KEYBOX: User requested calling InstallKeybox.\n");
break;
case TEST_PROVISION_30: case TEST_PROVISION_30:
printf("TEST_PROVISION_30: Device provisioed with OEM Cert.\n"); printf("TEST_PROVISION_30: Device provisioed with OEM Cert.\n");
break; break;
@@ -173,15 +165,15 @@ void DeviceFeatures::Initialize(bool is_cast_receiver,
printf("SecurityLevel is %s (%s)\n", printf("SecurityLevel is %s (%s)\n",
supports_level_1 ? "Level 1" : "Not Level 1", supports_level_1 ? "Level 1" : "Not Level 1",
security_level.c_str()); security_level.c_str());
CheckSecureBuffers();
OEMCrypto_Terminate(); OEMCrypto_Terminate();
initialized_ = true;
} }
std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) { std::string DeviceFeatures::RestrictFilter(const std::string& initial_filter) {
std::string filter = initial_filter; std::string filter = initial_filter;
// clang-format off // clang-format off
if (!uses_keybox) FilterOut(&filter, "*KeyboxTest*"); if (!uses_keybox) FilterOut(&filter, "*KeyboxTest*");
if (derive_key_method
!= FORCE_TEST_KEYBOX) FilterOut(&filter, "*ForceKeybox*");
if (!uses_certificate) FilterOut(&filter, "OEMCrypto*Cert*"); if (!uses_certificate) FilterOut(&filter, "OEMCrypto*Cert*");
if (!loads_certificate) FilterOut(&filter, "OEMCryptoLoadsCert*"); if (!loads_certificate) FilterOut(&filter, "OEMCryptoLoadsCert*");
if (!generic_crypto) FilterOut(&filter, "*GenericCrypto*"); 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, void DeviceFeatures::FilterOut(std::string* current_filter,
const std::string& new_filter) { const std::string& new_filter) {
if (current_filter->find('-') == std::string::npos) { 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) { const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method) {
switch (method) { switch (method) {
case OEMCrypto_ProvisioningError: case OEMCrypto_ProvisioningError:

View File

@@ -2,12 +2,21 @@
#define CDM_OEC_DEVICE_FEATURES_H_ #define CDM_OEC_DEVICE_FEATURES_H_
#include <string> #include <string>
#include <vector>
#include "OEMCryptoCENC.h" #include "OEMCryptoCENC.h"
#include "oemcrypto_types.h" #include "oemcrypto_types.h"
namespace wvoec { 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 // Keeps track of which features are supported by the version of OEMCrypto being
// tested. See the integration guide for a list of optional features. // tested. See the integration guide for a list of optional features.
class DeviceFeatures { class DeviceFeatures {
@@ -19,7 +28,6 @@ class DeviceFeatures {
NO_METHOD, // Cannot derive known session keys. NO_METHOD, // Cannot derive known session keys.
LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys. LOAD_TEST_KEYBOX, // Call LoadTestKeybox before deriving keys.
LOAD_TEST_RSA_KEY, // Call LoadTestRSAKey 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. TEST_PROVISION_30, // Device has OEM Certificate installed.
}; };
@@ -34,23 +42,36 @@ class DeviceFeatures {
bool supports_level_1; // Device supports Level 1 security. bool supports_level_1; // Device supports Level 1 security.
uint32_t resource_rating; // Device's resource rating tier. uint32_t resource_rating; // Device's resource rating tier.
bool supports_crc; // Supported decrypt hash type CRC. 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; uint32_t api_version;
OEMCrypto_ProvisioningMethod provisioning_method; OEMCrypto_ProvisioningMethod provisioning_method;
// This should be called from the test program's main procedure. // 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 // 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 // called after Initialize. Tests are filtered out based on which features
// are not supported. For example, a device that uses Provisioning 3.0 will // are not supported. For example, a device that uses Provisioning 3.0 will
// have all keybox tests filtered out. // have all keybox tests filtered out.
std::string RestrictFilter(const std::string& initial_filter); std::string RestrictFilter(const std::string& initial_filter);
// Get a list of output types that should be tested.
const std::vector<OutputType>& GetOutputTypes();
private: private:
// Decide which method should be used to derive session keys, based on // Decide which method should be used to derive session keys, based on
// supported featuers. // supported featuers.
void PickDerivedKey(); void PickDerivedKey();
// Decide if secure buffers can be created, and initialize output_types_.
void CheckSecureBuffers();
// Add a GTest filter restriction to the current filter. // Add a GTest filter restriction to the current filter.
void FilterOut(std::string* current_filter, const std::string& new_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 // There is one global set of features for the version of OEMCrypto being

View File

@@ -222,6 +222,7 @@ class ProvisioningRoundTrip
const std::vector<uint8_t>& encoded_rsa_key) const std::vector<uint8_t>& encoded_rsa_key)
: RoundTrip(session), : RoundTrip(session),
allowed_schemes_(kSign_RSASSA_PSS), allowed_schemes_(kSign_RSASSA_PSS),
encryptor_(),
encoded_rsa_key_(encoded_rsa_key) {} encoded_rsa_key_(encoded_rsa_key) {}
// Prepare the session for signing the request. // Prepare the session for signing the request.
virtual void PrepareSession(const wvoec::WidevineKeybox& keybox); virtual void PrepareSession(const wvoec::WidevineKeybox& keybox);

View File

@@ -60,10 +60,6 @@ void SessionUtil::EnsureTestKeys() {
case DeviceFeatures::LOAD_TEST_RSA_KEY: case DeviceFeatures::LOAD_TEST_RSA_KEY:
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey()); ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey());
break; break;
case DeviceFeatures::FORCE_TEST_KEYBOX:
keybox_ = kTestKeybox;
InstallKeybox(keybox_, true);
break;
case DeviceFeatures::TEST_PROVISION_30: case DeviceFeatures::TEST_PROVISION_30:
// Can use oem certificate to install test rsa key. // Can use oem certificate to install test rsa key.
break; break;

View File

@@ -52,14 +52,31 @@ using namespace std;
namespace std { // GTest wants PrintTo to be in the std namespace. namespace std { // GTest wants PrintTo to be in the std namespace.
void PrintTo(const tuple<OEMCrypto_CENCEncryptPatternDesc, OEMCryptoCipherMode, void PrintTo(const tuple<OEMCrypto_CENCEncryptPatternDesc, OEMCryptoCipherMode,
bool>& param, wvoec::OutputType>& param,
ostream* os) { ostream* os) {
OEMCrypto_CENCEncryptPatternDesc pattern = ::testing::get<0>(param); OEMCrypto_CENCEncryptPatternDesc pattern = ::testing::get<0>(param);
OEMCryptoCipherMode mode = ::testing::get<1>(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") *os << ((mode == OEMCrypto_CipherMode_CTR) ? "CTR mode" : "CBC mode")
<< ", encrypt=" << pattern.encrypt << ", skip=" << pattern.skip << ", pattern=(encrypt:" << pattern.encrypt << ", skip:" << pattern.skip
<< ", decrypt in place = " << (decrypt_inplace ? "true" : "false"); << ")";
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 } // 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_; vector<uint8_t> encrypted_usage_header_;
}; };
@@ -759,53 +769,6 @@ TEST_F(OEMCryptoSessionTestKeyboxTest, TestKeyboxIsValid) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid()); 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. // Verify that a license may be signed.
TEST_F(OEMCryptoSessionTests, SignLicenseRequest) { TEST_F(OEMCryptoSessionTests, SignLicenseRequest) {
Session s; Session s;
@@ -1894,14 +1857,15 @@ struct SampleInitData {
// buffers to be the same. // buffers to be the same.
class OEMCryptoSessionTestsDecryptTests class OEMCryptoSessionTestsDecryptTests
: public OEMCryptoSessionTests, : public OEMCryptoSessionTests,
public WithParamInterface< public WithParamInterface<tuple<OEMCrypto_CENCEncryptPatternDesc,
tuple<OEMCrypto_CENCEncryptPatternDesc, OEMCryptoCipherMode, bool> > { OEMCryptoCipherMode, OutputType> > {
protected: protected:
void SetUp() override { void SetUp() override {
OEMCryptoSessionTests::SetUp(); OEMCryptoSessionTests::SetUp();
pattern_ = ::testing::get<0>(GetParam()); pattern_ = ::testing::get<0>(GetParam());
cipher_mode_ = ::testing::get<1>(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; verify_crc_ = global_features.supports_crc;
// Pick a random key. // Pick a random key.
EXPECT_EQ(1, GetRandBytes(key_, AES_BLOCK_SIZE)); EXPECT_EQ(1, GetRandBytes(key_, AES_BLOCK_SIZE));
@@ -1912,6 +1876,7 @@ class OEMCryptoSessionTestsDecryptTests
} }
void TearDown() override { void TearDown() override {
FreeBuffers();
ASSERT_NO_FATAL_FAILURE(session_.close()); ASSERT_NO_FATAL_FAILURE(session_.close());
OEMCryptoSessionTests::TearDown(); OEMCryptoSessionTests::TearDown();
} }
@@ -1924,14 +1889,16 @@ 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(). // This should be called after FindTotalSize().
void MakeBuffers() { void MakeBuffers() {
ASSERT_GT(total_size_, 0u); ASSERT_GT(total_size_, 0u);
encrypted_buffer_.resize(total_size_); encrypted_buffer_.resize(total_size_);
truth_buffer_.resize(total_size_); truth_buffer_.resize(total_size_);
for (size_t i = 0; i < total_size_; i++) truth_buffer_[i] = i % 256; for (size_t i = 0; i < total_size_; i++) truth_buffer_[i] = i % 256;
output_descriptor_.type = OEMCrypto_BufferType_Clear; output_descriptor_.type = output_buffer_type_;
switch (output_descriptor_.type) {
case OEMCrypto_BufferType_Clear:
if (decrypt_inplace_) { if (decrypt_inplace_) {
output_descriptor_.buffer.clear.address = encrypted_buffer_.data(); output_descriptor_.buffer.clear.address = encrypted_buffer_.data();
} else { } else {
@@ -1940,16 +1907,58 @@ class OEMCryptoSessionTestsDecryptTests
output_descriptor_.buffer.clear.address = clear_buffer_.data(); output_descriptor_.buffer.clear.address = clear_buffer_.data();
} }
output_descriptor_.buffer.clear.address_length = total_size_; 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.";
}
} }
void UpdateOutputOffset(size_t offset) { void UpdateOutputOffset(size_t offset) {
switch (output_descriptor_.type) {
case OEMCrypto_BufferType_Clear:
if (decrypt_inplace_) { if (decrypt_inplace_) {
output_descriptor_.buffer.clear.address = output_descriptor_.buffer.clear.address =
encrypted_buffer_.data() + offset; encrypted_buffer_.data() + offset;
} else { } else {
output_descriptor_.buffer.clear.address = clear_buffer_.data() + offset; output_descriptor_.buffer.clear.address =
clear_buffer_.data() + offset;
} }
output_descriptor_.buffer.clear.address_length = total_size_ - 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_));
}
} }
void EncryptData() { void EncryptData() {
@@ -2035,6 +2044,8 @@ class OEMCryptoSessionTestsDecryptTests
ASSERT_NO_FATAL_FAILURE(InstallTestRSAKey(&session_)); ASSERT_NO_FATAL_FAILURE(InstallTestRSAKey(&session_));
uint32_t control = 0; uint32_t control = 0;
if (verify_crc_) control |= kControlAllowHashVerification; if (verify_crc_) control |= kControlAllowHashVerification;
if (output_buffer_type_ == OEMCrypto_BufferType_Secure)
control |= kControlObserveDataPath | kControlDataPathSecure;
ASSERT_NO_FATAL_FAILURE(session_.FillSimpleMessage(kDuration, control, 0)); ASSERT_NO_FATAL_FAILURE(session_.FillSimpleMessage(kDuration, control, 0));
memcpy(session_.license().keys[0].key_data, key_, sizeof(key_)); memcpy(session_.license().keys[0].key_data, key_, sizeof(key_));
session_.license().keys[0].cipher_mode = cipher_mode_; session_.license().keys[0].cipher_mode = cipher_mode_;
@@ -2130,6 +2141,7 @@ class OEMCryptoSessionTestsDecryptTests
OEMCrypto_CENCEncryptPatternDesc pattern_; OEMCrypto_CENCEncryptPatternDesc pattern_;
OEMCryptoCipherMode cipher_mode_; OEMCryptoCipherMode cipher_mode_;
bool decrypt_inplace_; // If true, input and output buffers are the same. bool decrypt_inplace_; // If true, input and output buffers are the same.
OEMCryptoBufferType output_buffer_type_;
vector<SampleSize> subsample_size_; vector<SampleSize> subsample_size_;
size_t total_size_; size_t total_size_;
bool verify_crc_; bool verify_crc_;
@@ -2137,9 +2149,9 @@ class OEMCryptoSessionTestsDecryptTests
// Encrypted data -- this is input to OEMCrypto, and output from EncryptData. // Encrypted data -- this is input to OEMCrypto, and output from EncryptData.
std::vector<uint8_t> encrypted_buffer_; std::vector<uint8_t> encrypted_buffer_;
std::vector<uint8_t> clear_buffer_; // OEMCrypto store clear output here. 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. std::vector<uint8_t> truth_buffer_; // Truth data for clear text.
OEMCrypto_DestBufferDesc output_descriptor_; OEMCrypto_DestBufferDesc output_descriptor_;
int secure_buffer_fid_;
uint8_t key_[AES_BLOCK_SIZE]; // Encryption Key. uint8_t key_[AES_BLOCK_SIZE]; // Encryption Key.
std::vector<uint8_t> starting_iv_; // Starting IV. std::vector<uint8_t> starting_iv_; // Starting IV.
Session session_; Session session_;
@@ -2156,8 +2168,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) {
// full patterns if we have more than 320 -- round up to 400. // full patterns if we have more than 320 -- round up to 400.
subsample_size_.push_back(SampleSize(0, 400)); subsample_size_.push_back(SampleSize(0, 400));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
} }
@@ -2169,8 +2181,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) {
TEST_P(OEMCryptoSessionTestsDecryptTests, PatternPlusOneBlock) { TEST_P(OEMCryptoSessionTestsDecryptTests, PatternPlusOneBlock) {
subsample_size_.push_back(SampleSize(0, 160 + 16)); subsample_size_.push_back(SampleSize(0, 160 + 16));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
} }
@@ -2179,8 +2191,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, PatternPlusOneBlock) {
TEST_P(OEMCryptoSessionTestsDecryptTests, OneBlock) { TEST_P(OEMCryptoSessionTestsDecryptTests, OneBlock) {
subsample_size_.push_back(SampleSize(0, 16)); subsample_size_.push_back(SampleSize(0, 16));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); 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(50, 256));
subsample_size_.push_back(SampleSize(25, 160)); subsample_size_.push_back(SampleSize(25, 160));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); 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, 32));
subsample_size_.push_back(SampleSize(25, 50)); subsample_size_.push_back(SampleSize(25, 50));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
// CTR Mode is self-inverse -- i.e. We can pick the encrypted data and // 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, // 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 // 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, 75));
subsample_size_.push_back(SampleSize(10, 25)); subsample_size_.push_back(SampleSize(10, 25));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
} }
@@ -2257,8 +2269,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptWithNearWrap) {
starting_iv_ = wvcdm::a2b_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"); starting_iv_ = wvcdm::a2b_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE");
subsample_size_.push_back(SampleSize(0, 256)); subsample_size_.push_back(SampleSize(0, 256));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); 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. // other tests, e.g. (7, 3). 3*16 < 50 and 7*16 > 50.
subsample_size_.push_back(SampleSize(0, 50)); subsample_size_.push_back(SampleSize(0, 50));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
} }
@@ -2292,8 +2304,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSample) {
subsample_size_.push_back(SampleSize(0, max_subsample_size)); subsample_size_.push_back(SampleSize(0, max_subsample_size));
} }
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); 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(max_subsample_size, 0));
subsample_size_.push_back(SampleSize(0, max_subsample_size)); subsample_size_.push_back(SampleSize(0, max_subsample_size));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
} }
@@ -2314,8 +2326,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptMaxSubsample) {
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptSmallBuffer) { TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptSmallBuffer) {
subsample_size_.push_back(SampleSize(5, 5)); subsample_size_.push_back(SampleSize(5, 5));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
} }
@@ -2325,8 +2337,8 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptSmallBuffer) {
TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptUnencrypted) { TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptUnencrypted) {
subsample_size_.push_back(SampleSize(256, 0)); subsample_size_.push_back(SampleSize(256, 0));
FindTotalSize(); FindTotalSize();
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(LoadLicense()); ASSERT_NO_FATAL_FAILURE(LoadLicense());
ASSERT_NO_FATAL_FAILURE(MakeBuffers());
ASSERT_NO_FATAL_FAILURE(EncryptData()); ASSERT_NO_FATAL_FAILURE(EncryptData());
ASSERT_NO_FATAL_FAILURE(TestDecryptCENC()); ASSERT_NO_FATAL_FAILURE(TestDecryptCENC());
} }
@@ -2354,47 +2366,41 @@ OEMCrypto_CENCEncryptPatternDesc MakePattern(size_t encrypt, size_t skip) {
return pattern; return pattern;
} }
INSTANTIATE_TEST_CASE_P(CTRTests, OEMCryptoSessionTestsPartialBlockTests, INSTANTIATE_TEST_CASE_P(
Combine(Values(MakePattern(0,0)), CTRTests, OEMCryptoSessionTestsPartialBlockTests,
Values(OEMCrypto_CipherMode_CTR), Combine(Values(MakePattern(0, 0)), Values(OEMCrypto_CipherMode_CTR),
Bool())); ::testing::ValuesIn(global_features.GetOutputTypes())));
// Decrypt in place for CBC tests was only required in v13. // Decrypt in place for CBC tests was only required in v13.
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
CBCTestsAPI14, OEMCryptoSessionTestsPartialBlockTests, CBCTestsAPI14, OEMCryptoSessionTestsPartialBlockTests,
Combine( Combine(
Values(MakePattern(0, 0), Values(MakePattern(0, 0), MakePattern(3, 7),
MakePattern(3, 7),
// HLS Edge case. We should follow the CENC spec, not HLS spec. // HLS Edge case. We should follow the CENC spec, not HLS spec.
MakePattern(9, 1), MakePattern(9, 1), MakePattern(1, 9), MakePattern(1, 3),
MakePattern(1, 9),
MakePattern(1, 3),
MakePattern(2, 1)), MakePattern(2, 1)),
Values(OEMCrypto_CipherMode_CBC), Bool())); Values(OEMCrypto_CipherMode_CBC),
::testing::ValuesIn(global_features.GetOutputTypes())));
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
CTRTestsAPI11, OEMCryptoSessionTestsDecryptTests, CTRTestsAPI11, OEMCryptoSessionTestsDecryptTests,
Combine( Combine(Values(MakePattern(0, 0), MakePattern(3, 7),
Values(MakePattern(0, 0),
MakePattern(3, 7),
// Pattern length should be 10, but that is not guaranteed. // Pattern length should be 10, but that is not guaranteed.
MakePattern(1, 3), MakePattern(1, 3), MakePattern(2, 1)),
MakePattern(2, 1)), Values(OEMCrypto_CipherMode_CTR),
Values(OEMCrypto_CipherMode_CTR), Bool())); ::testing::ValuesIn(global_features.GetOutputTypes())));
// Decrypt in place for CBC tests was only required in v13. // Decrypt in place for CBC tests was only required in v13.
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
CBCTestsAPI14, OEMCryptoSessionTestsDecryptTests, CBCTestsAPI14, OEMCryptoSessionTestsDecryptTests,
Combine( Combine(
Values(MakePattern(0, 0), Values(MakePattern(0, 0), MakePattern(3, 7),
MakePattern(3, 7),
// HLS Edge case. We should follow the CENC spec, not HLS spec. // HLS Edge case. We should follow the CENC spec, not HLS spec.
MakePattern(9, 1), MakePattern(9, 1), MakePattern(1, 9),
MakePattern(1, 9),
// Pattern length should be 10, but that is not guaranteed. // Pattern length should be 10, but that is not guaranteed.
MakePattern(1, 3), MakePattern(1, 3), MakePattern(2, 1)),
MakePattern(2, 1)), Values(OEMCrypto_CipherMode_CBC),
Values(OEMCrypto_CipherMode_CBC), Bool())); ::testing::ValuesIn(global_features.GetOutputTypes())));
// A request to decrypt data to a clear buffer when the key control block // A request to decrypt data to a clear buffer when the key control block
// requires a secure data path. // 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.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
s.GenerateVerifyReport(pst, kActive, s.GenerateVerifyReport(pst, kActive,
loaded, // license recieved. loaded, // license received.
loaded, // First decrypt when loaded, not refresh. loaded, // First decrypt when loaded, not refresh.
0)); // last decrypt now. 0)); // last decrypt now.
} }

View File

@@ -17,9 +17,7 @@ static void acknowledge_cast() {
// because we need to initialize the list of features supported by the device. // because we need to initialize the list of features supported by the device.
// Also, the test filter is updated based on the feature list. // Also, the test filter is updated based on the feature list.
int main(int argc, char** argv) { int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
bool is_cast_receiver = false; bool is_cast_receiver = false;
bool force_load_test_keybox = false;
bool filter_tests = true; bool filter_tests = true;
int verbosity = 0; int verbosity = 0;
// Skip the first element, which is the program name. // Skip the first element, which is the program name.
@@ -32,7 +30,8 @@ int main(int argc, char** argv) {
is_cast_receiver = true; is_cast_receiver = true;
} }
if (arg == "--force_load_test_keybox") { 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") { if (arg == "--no_filter") {
filter_tests = false; filter_tests = false;
@@ -42,7 +41,10 @@ int main(int argc, char** argv) {
} }
} }
wvcdm::g_cutoff = static_cast<wvcdm::LogPriority>(verbosity); 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 // If the user requests --no_filter, we don't change the filter, otherwise, we
// filter out features that are not supported. // filter out features that are not supported.
if (filter_tests) { if (filter_tests) {