From ff7cc16e4a807e77d6dd16b63fa6c5e486e6fc5b Mon Sep 17 00:00:00 2001 From: Fred Gylys-Colwell Date: Fri, 13 Dec 2019 11:14:12 -0800 Subject: [PATCH] Provisioning Unit Tests --- oemcrypto/include/OEMCryptoCENC.h | 2 +- oemcrypto/ref/src/oemcrypto_ref.cpp | 36 +-- oemcrypto/test/oec_device_features.cpp | 59 ++++- oemcrypto/test/oec_device_features.h | 25 +- oemcrypto/test/oec_session_util.h | 1 + .../test/oemcrypto_session_tests_helper.cpp | 4 - oemcrypto/test/oemcrypto_test.cpp | 234 +++++++++--------- oemcrypto/test/oemcrypto_test_main.cpp | 10 +- 8 files changed, 219 insertions(+), 152 deletions(-) diff --git a/oemcrypto/include/OEMCryptoCENC.h b/oemcrypto/include/OEMCryptoCENC.h index 8d5f0cd..6af14b2 100644 --- a/oemcrypto/include/OEMCryptoCENC.h +++ b/oemcrypto/include/OEMCryptoCENC.h @@ -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 * diff --git a/oemcrypto/ref/src/oemcrypto_ref.cpp b/oemcrypto/ref/src/oemcrypto_ref.cpp index cd3a4da..13e3bda 100644 --- a/oemcrypto/ref/src/oemcrypto_ref.cpp +++ b/oemcrypto/ref/src/oemcrypto_ref.cpp @@ -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 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 diff --git a/oemcrypto/test/oec_device_features.cpp b/oemcrypto/test/oec_device_features.cpp index 76c3ef5..8430782 100644 --- a/oemcrypto/test/oec_device_features.cpp +++ b/oemcrypto/test/oec_device_features.cpp @@ -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& DeviceFeatures::GetOutputTypes() { + if (!initialized_) { + Initialize(); + } + return output_types_; +} + const char* ProvisioningMethodName(OEMCrypto_ProvisioningMethod method) { switch (method) { case OEMCrypto_ProvisioningError: diff --git a/oemcrypto/test/oec_device_features.h b/oemcrypto/test/oec_device_features.h index c0d94e0..2addb2a 100644 --- a/oemcrypto/test/oec_device_features.h +++ b/oemcrypto/test/oec_device_features.h @@ -2,12 +2,21 @@ #define CDM_OEC_DEVICE_FEATURES_H_ #include +#include #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& 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 output_types_; + bool initialized_ = false; }; // There is one global set of features for the version of OEMCrypto being diff --git a/oemcrypto/test/oec_session_util.h b/oemcrypto/test/oec_session_util.h index c1b6834..c74d079 100644 --- a/oemcrypto/test/oec_session_util.h +++ b/oemcrypto/test/oec_session_util.h @@ -222,6 +222,7 @@ class ProvisioningRoundTrip const std::vector& 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); diff --git a/oemcrypto/test/oemcrypto_session_tests_helper.cpp b/oemcrypto/test/oemcrypto_session_tests_helper.cpp index 3214269..51b717f 100644 --- a/oemcrypto/test/oemcrypto_session_tests_helper.cpp +++ b/oemcrypto/test/oemcrypto_session_tests_helper.cpp @@ -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; diff --git a/oemcrypto/test/oemcrypto_test.cpp b/oemcrypto/test/oemcrypto_test.cpp index b6032b6..fd639a0 100644 --- a/oemcrypto/test/oemcrypto_test.cpp +++ b/oemcrypto/test/oemcrypto_test.cpp @@ -52,14 +52,31 @@ using namespace std; namespace std { // GTest wants PrintTo to be in the std namespace. void PrintTo(const tuple& 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 = "; + 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 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 > { + public WithParamInterface > { 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 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 encrypted_buffer_; std::vector clear_buffer_; // OEMCrypto store clear output here. - void* secure_handle_; // OEMCrypto stores secure output here. std::vector 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 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. } diff --git a/oemcrypto/test/oemcrypto_test_main.cpp b/oemcrypto/test/oemcrypto_test_main.cpp index 0f40112..1cf4a59 100644 --- a/oemcrypto/test/oemcrypto_test_main.cpp +++ b/oemcrypto/test/oemcrypto_test_main.cpp @@ -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(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) {