// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine // License Agreement. // /** * @mainpage OEMCrypto Unit Tests * * The OEMCrypto unit tests are designed to verify that an implementation of * OEMCrypto is correctly supporting the OEMCrypto API. * * @defgroup basic Basic Functionality Tests * Basic functionality tests. * * @defgroup provision Provisioning Tests * Test for provisioning and certificate key processing. These tests cover * Provsioning 2.0, 3.0 and 4.0. Tests for the wrong provisioning scheme should * be skipped. * * @defgroup license License Request Tests * Test for requesting and loading licenses. * * @defgroup renewal License Renewal Tests * Tests for renewing licenses. * * @defgroup decrypt Decrypt Tests * Tests for decrypting content. * * @defgroup usage_table Usage Table Tests * Tests that use the usage table. * * @defgroup entitle Entitlement License tests * Tests for entitlement licenses. * * @defgroup cas Conditional Access System Tests * Tests for OEMCrypto implementations that support MediaCAS. * * @defgroup cast Cast Test * Tests for OEMCrypto implementations that support being a Cast receiver. * * @defgroup generic Generic Crypto Tests * Tests for the Generic Crypto functionality. * * @defgroup security Security Tests * Buffer overflow tests, off-by-one tests, and other security tests. * * The way the huge buffer tests work is to create a large buffer and then call * the API. The test then loops and doubles the buffer until the API returns an * error. An error is considered a passing test. We expect OEMCrypto to fail * gracefully on a huge buffer rather than crashing. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "OEMCryptoCENC.h" #include "clock.h" #include "log.h" #include "oec_decrypt_fallback_chain.h" #include "oec_device_features.h" #include "oec_extra_test_keys.h" #include "oec_session_util.h" #include "oec_test_data.h" #include "oemcrypto_basic_test.h" #include "oemcrypto_corpus_generator_helper.h" #include "oemcrypto_fuzz_structs.h" #include "oemcrypto_license_test.h" #include "oemcrypto_provisioning_test.h" #include "oemcrypto_resource_test.h" #include "oemcrypto_session_tests_helper.h" #include "oemcrypto_types.h" #include "oemcrypto_usage_table_test.h" #include "platform.h" #include "string_conversions.h" #include "test_sleep.h" #include "wvcrc32.h" using ::testing::Range; using ::testing::tuple; using ::testing::WithParamInterface; using namespace std; namespace std { // GTest wants PrintTo to be in the std namespace. void PrintTo(const tuple& param, ostream* os) { OEMCrypto_CENCEncryptPatternDesc pattern = ::testing::get<0>(param); OEMCryptoCipherMode mode = ::testing::get<1>(param); wvoec::OutputType output = ::testing::get<2>(param); bool decrypt_inplace = output.decrypt_inplace; OEMCryptoBufferType type = output.type; *os << ((mode == OEMCrypto_CipherMode_CENC) ? "CENC mode" : "CBCS mode") << ", 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 namespace wvoec { /// @addtogroup security /// @{ class OEMCryptoLicenseOverflowTest : public OEMCryptoSessionTests, public WithParamInterface { public: OEMCryptoLicenseOverflowTest() : license_api_version_(kCurrentAPI) {} void SetUp() override { OEMCryptoSessionTests::SetUp(); license_api_version_ = GetParam(); } void TearDown() override { OEMCryptoSessionTests::TearDown(); } void TestLoadLicenseForHugeBufferLengths( const std::function f, bool check_status, bool update_core_message_substring_values) { auto oemcrypto_function = [&](size_t message_length) { Session s; LicenseRoundTrip license_messages(&s); license_messages.set_api_version(license_api_version_); s.open(); InstallTestDrmKey(&s); bool verify_keys_loaded = true; license_messages.SignAndVerifyRequest(); license_messages.CreateDefaultResponse(); if (update_core_message_substring_values) { // Make the license message big enough so that updated core message // substring offset and length values from tests are still able to read // data from license_message buffer rather than reading some garbage // data. license_messages.set_message_size( sizeof(license_messages.response_data()) + message_length); } f(message_length, &license_messages); if (update_core_message_substring_values) { // We will be updating offset for these tests, which will cause verify // keys to fail with an assertion. Hence skipping verification. verify_keys_loaded = false; } license_messages.EncryptAndSignResponse(); OEMCryptoResult result = license_messages.LoadResponse(&s, verify_keys_loaded); s.close(); return result; }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, check_status); } void TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( const std::function f) { Session s; LicenseRoundTrip license_messages(&s); license_messages.set_api_version(license_api_version_); s.open(); InstallTestDrmKey(&s); license_messages.SignAndVerifyRequest(); license_messages.CreateDefaultResponse(); size_t message_length = sizeof(license_messages.response_data()); f(message_length, &license_messages); license_messages.EncryptAndSignResponse(); OEMCryptoResult result = license_messages.LoadResponse(); s.close(); // Verifying error is not due to signature failure which can be caused due // to test code. ASSERT_NE(OEMCrypto_ERROR_SIGNATURE_FAILURE, result); ASSERT_NE(OEMCrypto_SUCCESS, result); } protected: uint32_t license_api_version_; }; // This class is for testing a single license with the default API version // of 16. Used for buffer overflow tests. class OEMCryptoMemoryLicenseTest : public OEMCryptoLicenseTestAPI16 { public: OEMCryptoMemoryLicenseTest() : entitled_message_(&license_messages_) {} void SetUp() override { OEMCryptoLicenseTestAPI16::SetUp(); SetUpEntitledMessage(); entitlement_response_length_ = entitled_message_.entitled_key_data_size(); } void LoadLicense() { ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); } void SetUpEntitledMessage() { license_messages_.set_license_type(OEMCrypto_EntitlementLicense); LoadLicense(); entitled_message_.FillKeyArray(); entitled_message_.EncryptContentKey(); uint32_t key_session_id = 0; OEMCryptoResult sts = OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id); if (sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) { return; } ASSERT_EQ(OEMCrypto_SUCCESS, sts); entitled_message_.SetEntitledKeySession(key_session_id); } void TearDown() override { OEMCryptoLicenseTestAPI16::TearDown(); } protected: EntitledMessage entitled_message_; size_t entitlement_response_length_; void TestLoadEntitledKeysForHugeBufferLengths( const std::function f, bool check_status) { size_t entitled_key_data_size = entitled_message_.entitled_key_data_size(); vector message(entitled_key_data_size); memcpy(message.data(), entitled_message_.entitled_key_data(), entitled_key_data_size); auto oemcrypto_function = [&](size_t length) { // Make entitled message big enough so that updated substring offset and // length fields by core message substring tests can still be able to read // valid data from entitled message buffer rather than some garbage data. message.resize(entitled_key_data_size + length); f(length, &entitled_message_); return entitled_message_.LoadKeys(message); }; TestHugeLengthDoesNotCrashAPI(oemcrypto_function, check_status); } }; /// @} /// @addtogroup entitle /// @{ class OEMCryptoEntitlementLicenseTest : public OEMCryptoLicenseTest { protected: void LoadEntitlementLicense() { license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); } }; /** This verifies that entitlement keys and entitled content keys can be loaded. */ TEST_P(OEMCryptoEntitlementLicenseTest, LoadEntitlementKeysAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(true)); EntitledMessage entitled_message_2(&license_messages_); entitled_message_2.FillKeyArray(); entitled_message_2.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_2.LoadKeys(true)); } /** * This verifies that entitled content keys cannot be loaded if we have not yet * loaded the entitlement keys. */ TEST_P(OEMCryptoEntitlementLicenseTest, LoadEntitlementKeysNoEntitlementKeysAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(false)); } /** * This verifies that entitled content keys cannot be loaded if we have loaded * the wrong entitlement keys. */ TEST_P(OEMCryptoEntitlementLicenseTest, LoadEntitlementKeysWrongEntitlementKeysAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); const std::string key_id = "no_key"; entitled_message_1.SetEntitlementKeyId(0, key_id); entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(false)); } /** * This verifies that entitled content keys cannot be loaded if we specify an * entitled key session that has not been created. */ TEST_P(OEMCryptoEntitlementLicenseTest, LoadEntitlementKeysWrongEntitledKeySessionAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); const uint32_t wrong_key_session_id = key_session_id == 0 ? 1 : 0; entitled_message_1.SetEntitledKeySession(wrong_key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(false)); } INSTANTIATE_TEST_SUITE_P(TestAll, OEMCryptoEntitlementLicenseTest, Range(kCoreMessagesAPI, kCurrentAPI + 1)); /// @} /// @addtogroup security /// @{ /** Test that LoadEntitledContentKeys fails gracefully on huge buffer. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeSubstringContentKeyIdLength) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t key_id_length, EntitledMessage* entitled_message) { entitled_message->entitled_key_array()[0].content_key_id.length = key_id_length; }, !kCheckStatus); } /** Test that LoadEntitledContentKeys fails gracefully on huge buffer. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeSubstringContentKeyIdOffset) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t key_id_offset, EntitledMessage* entitled_message) { entitled_message->entitled_key_array()[0].content_key_id.offset = key_id_offset; }, !kCheckStatus); } /** Test that LoadEntitledContentKeys fails gracefully on huge buffer. */ TEST_F( OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForOutOfRangeSubstringContentKeyIdLength) { auto& content_key_id = entitled_message_.entitled_key_array()[0].content_key_id; content_key_id.length = entitlement_response_length_ - content_key_id.offset + 1; ASSERT_NE(OEMCrypto_SUCCESS, entitled_message_.LoadKeys()); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F( OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForOutOfRangeSubstringContentKeyIdOffset) { auto& content_key_id = entitled_message_.entitled_key_array()[0].content_key_id; content_key_id.offset = entitlement_response_length_ - content_key_id.length + 1; ASSERT_NE(OEMCrypto_SUCCESS, entitled_message_.LoadKeys()); } /** Test that LoadEntitledContentKeys fails gracefully on huge substring. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeSubstringEntitlementKeyIdLength) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t key_id_length, EntitledMessage* entitled_message) { entitled_message->entitled_key_array()[0].entitlement_key_id.length = key_id_length; }, !kCheckStatus); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeSubstringEntitlementKeyIdOffset) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t key_id_offset, EntitledMessage* entitled_message) { entitled_message->entitled_key_array()[0].entitlement_key_id.offset = key_id_offset; }, !kCheckStatus); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F( OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForOutOfRangeSubstringEntitlementKeyIdLength) { auto& entitlement_key_id = entitled_message_.entitled_key_array()[0].entitlement_key_id; entitlement_key_id.length = entitlement_response_length_ - entitlement_key_id.offset + 1; ASSERT_NE(OEMCrypto_SUCCESS, entitled_message_.LoadKeys()); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F( OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForOutOfRangeSubstringEntitlementKeyIdOffset) { auto& entitlement_key_id = entitled_message_.entitled_key_array()[0].entitlement_key_id; entitlement_key_id.offset = entitlement_response_length_ - entitlement_key_id.length + 1; ASSERT_NE(OEMCrypto_SUCCESS, entitled_message_.LoadKeys()); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeSubstringContentKeyDataIvLength) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t content_key_data_iv_length, EntitledMessage* entitled_message) { entitled_message->entitled_key_array()[0].content_key_data_iv.length = content_key_data_iv_length; }, !kCheckStatus); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeSubstringContentKeyDataIvOffset) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t content_key_data_iv_offset, EntitledMessage* entitled_message) { entitled_message->entitled_key_array()[0].content_key_data_iv.offset = content_key_data_iv_offset; }, !kCheckStatus); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F( OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForOutOfRangeSubstringContentKeyDataIvLength) { auto& content_key_data_iv = entitled_message_.entitled_key_array()[0].content_key_data_iv; content_key_data_iv.length = entitlement_response_length_ - content_key_data_iv.offset + 1; ASSERT_NE(OEMCrypto_SUCCESS, entitled_message_.LoadKeys()); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F( OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForOutOfRangeSubstringContentKeyDataIvOffset) { auto& content_key_data_iv = entitled_message_.entitled_key_array()[0].content_key_data_iv; content_key_data_iv.offset = entitlement_response_length_ - content_key_data_iv.length + 1; ASSERT_NE(OEMCrypto_SUCCESS, entitled_message_.LoadKeys()); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeSubstringContentKeyDataLength) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t content_key_data_length, EntitledMessage* entitled_message) { entitled_message->entitled_key_array()[0].content_key_data.length = content_key_data_length; }, !kCheckStatus); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeSubstringContentKeyDataOffset) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t content_key_data_offset, EntitledMessage* entitled_message) { entitled_message->entitled_key_array()[0].content_key_data.offset = content_key_data_offset; }, !kCheckStatus); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F( OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForOutOfRangeSubstringContentKeyDataLength) { auto& content_key_data = entitled_message_.entitled_key_array()[0].content_key_data; content_key_data.length = entitlement_response_length_ - content_key_data.offset + 1; ASSERT_NE(OEMCrypto_SUCCESS, entitled_message_.LoadKeys()); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F( OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForOutOfRangeSubstringContentKeyDataOffset) { auto& content_key_data = entitled_message_.entitled_key_array()[0].content_key_data; content_key_data.offset = entitlement_response_length_ - content_key_data.length + 1; ASSERT_NE(OEMCrypto_SUCCESS, entitled_message_.LoadKeys()); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeEntitlementKeyIdLength) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t key_id_length, EntitledMessage* entitled_message) { entitled_message->entitled_key_data()->entitlement_key_id_length = key_id_length; }, !kCheckStatus); } /** Test LoadEntitledContentKeys rejects out of range substring. */ TEST_F(OEMCryptoMemoryLicenseTest, OEMCryptoMemoryLoadEntitledKeysForHugeContentKeyIdLength) { TestLoadEntitledKeysForHugeBufferLengths( [](size_t key_id_length, EntitledMessage* entitled_message) { entitled_message->entitled_key_data()->content_key_id_length = key_id_length; }, !kCheckStatus); } /// @} /// @addtogroup entitle /// @{ TEST_P(OEMCryptoLicenseTest, GetKeyHandleEntitledKeyAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); uint32_t key_session_id; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id); const char* content_key_id = "content_key_id"; entitled_message_1.SetContentKeyId(0, content_key_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(true)); vector key_handle; ASSERT_EQ( OEMCrypto_SUCCESS, GetKeyHandleIntoVector( key_session_id, reinterpret_cast(content_key_id), strlen(content_key_id), OEMCrypto_CipherMode_CENC, key_handle)); } // SelectEntitledKey should fail if we attempt to select a key that has not been // loaded. Also, the error should be NO_CONTENT_KEY. TEST_P(OEMCryptoLicenseTest, SelectKeyEntitledKeyNotThereAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); uint32_t key_session_id; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(true)); const char* content_key_id = "no_key"; ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_ERROR_INVALID_CONTEXT, key_session_id, reinterpret_cast(content_key_id), strlen(content_key_id))); } // This verifies that entitled key sessions can be created and removed. TEST_P(OEMCryptoLicenseTest, EntitledKeySessionsAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); uint32_t key_session_id_1; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id_1)); ASSERT_NE(key_session_id_1, 0u); // 0 is a reserved id number. uint32_t key_session_id_2; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id_2)); ASSERT_NE(key_session_id_2, 0u); // 0 is a reserved id number. // Entitled key sessions should have unique ids. ASSERT_NE(key_session_id_1, key_session_id_2); ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_RemoveEntitledKeySession(key_session_id_1)); ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_RemoveEntitledKeySession(key_session_id_2)); } TEST_P(OEMCryptoLicenseTest, EntitledKeySessionsCloseWithOEMCryptoSessionAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); uint32_t key_session_id_1; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id_1)); // Close the OEMCrypto session. session_.close(); // All entitled key sessions associated with the OEMCrypto session should // already be destroyed. ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_RemoveEntitledKeySession(key_session_id_1)); // Open a new session just for OEMCryptoLicenseTest TearDown. session_.open(); } // This verifies that within an entitled key session, each entitlement key can // corresponds to only one content key at most. TEST_P(OEMCryptoLicenseTest, EntitledKeySessionOneContentKeyPerEntitlementAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); uint32_t key_session_id; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); // Construct and load content keys to entitled key session. EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id); const char* content_key_id_1 = "content_key_id_1"; entitled_message_1.SetContentKeyId(0, content_key_id_1); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(true)); // We can select content key 1 in entitled key session. ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_SUCCESS, key_session_id, reinterpret_cast(content_key_id_1), strlen(content_key_id_1))); // Load content key with new content id. const char* content_key_id_2 = "content_key_id_2"; entitled_message_1.SetContentKeyId(0, content_key_id_2); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(true)); // We can select content key 2 in entitled key session. ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_SUCCESS, key_session_id, reinterpret_cast(content_key_id_2), strlen(content_key_id_2))); // Content key one is no longer in the entitled key session as they use the // same entitlement key. ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_ERROR_NO_CONTENT_KEY, key_session_id, reinterpret_cast(content_key_id_1), strlen(content_key_id_1))); } // Decrypt should fail if the license is entitlement license, and the key handle // is requested from the oemcrypto session (should use entitled key session id // instead). TEST_P(OEMCryptoLicenseTest, RejectOecSessionDecryptWithEntitlementLicenseAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); uint32_t key_session_id; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); // Skip the rest of this test on platforms that do not support separate // entitlement and entitled sessions. if (global_features.supports_cas || session_.session_id() != key_session_id) { // Construct and load content keys to entitled key session. EntitledMessage entitled_message(&license_messages_); entitled_message.FillKeyArray(); entitled_message.SetEntitledKeySession(key_session_id); constexpr char kContentKeyId[] = "content_key_id"; const size_t content_key_id_length = strlen(kContentKeyId); entitled_message.SetContentKeyId(0, kContentKeyId); ASSERT_NO_FATAL_FAILURE(entitled_message.LoadKeys(true)); ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_SUCCESS, key_session_id, reinterpret_cast(kContentKeyId), content_key_id_length)); // Try to get a key handle with the oemcrypto session id. vector key_handle; EXPECT_NE(GetKeyHandleIntoVector( session_.session_id(), reinterpret_cast(kContentKeyId), content_key_id_length, OEMCrypto_CipherMode_CENC, key_handle), OEMCrypto_SUCCESS); } } // This verifies that an entitled key session can be reassociated to an // OEMCrypto session. TEST_P(OEMCryptoEntitlementLicenseTest, ReassociateEntitledKeySessionAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); // Setup an entitled key session in the first OEMCrypto session. uint32_t key_session_id; OEMCryptoResult sts = OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id); ASSERT_EQ(OEMCrypto_SUCCESS, sts); EntitledMessage entitled_message(&license_messages_); entitled_message.FillKeyArray(); entitled_message.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message.LoadKeys(true)); // Setup another session. Session session2; ASSERT_NO_FATAL_FAILURE(session2.open()); ASSERT_NO_FATAL_FAILURE(InstallTestDrmKey(&session2)); // session2 does not have entitlement keys. Re-associating the entitled key // session to session2 should fail OEMCryptoResult status = OEMCrypto_ReassociateEntitledKeySession( key_session_id, session2.session_id()); if (status == OEMCrypto_ERROR_NOT_IMPLEMENTED && !global_features.supports_cas) { GTEST_SKIP() << "Skipping test because " "OEMCrypto_ReassociateEntitledKeySession not implemented."; } EXPECT_NE(OEMCrypto_SUCCESS, status); // session2 loads the correct entitlement keys. LicenseRoundTrip license_messages2(&session2); license_messages2.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages2.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages2.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages2.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages2.LoadResponse()); // Re-associating to session2 should succeed. ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_ReassociateEntitledKeySession( key_session_id, session2.session_id())); // Now reassociate the entitled key session back to the first OEMCrypto // session. ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_ReassociateEntitledKeySession( key_session_id, session_.session_id())); ASSERT_NO_FATAL_FAILURE(entitled_message.LoadKeys(true)); // session3 has unmatched key policies Session session3; ASSERT_NO_FATAL_FAILURE(session3.open()); ASSERT_NO_FATAL_FAILURE(InstallTestDrmKey(&session3)); LicenseRoundTrip license_messages3(&session3); license_messages3.set_license_type(OEMCrypto_EntitlementLicense); license_messages3.set_control(license_messages_.control() + 1); ASSERT_NO_FATAL_FAILURE(license_messages3.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages3.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages3.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages3.LoadResponse()); // Re-associating to session3 should fail. EXPECT_NE(OEMCrypto_SUCCESS, OEMCrypto_ReassociateEntitledKeySession( key_session_id, session3.session_id())); } /// @} /// @addtogroup security /// @{ /** Test that LoadLicense fails gracefully on huge buffer. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyIdLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_id.length = length; license_messages->response_data().keys[0].key_id_length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyIdOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_id.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyIdLength) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_id = license_messages->core_response().key_array[0].key_id; key_id.length = response_message_length - key_id.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyIdOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_id = license_messages->core_response().key_array[0].key_id; key_id.offset = response_message_length - key_id.length + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyDataIvLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_data_iv.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyDataIvOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_data_iv.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyDataIvLength) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_data_iv = license_messages->core_response().key_array[0].key_data_iv; key_data_iv.length = response_message_length - key_data_iv.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyDataIvOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_data_iv = license_messages->core_response().key_array[0].key_data_iv; key_data_iv.offset = response_message_length - key_data_iv.length + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyDataLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_data.length = length; license_messages->response_data().keys[0].key_data_length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyDataOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_data.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyDataLength) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_data = license_messages->core_response().key_array[0].key_data; key_data.length = response_message_length - key_data.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyDataOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_data = license_messages->core_response().key_array[0].key_data; key_data.offset = response_message_length - key_data.length + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyControlIvLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_control_iv.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyControlIvOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_control_iv.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyControlIvLengthAPI16) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_control_iv = license_messages->core_response().key_array[0].key_control_iv; key_control_iv.length = response_message_length - key_control_iv.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyControlIvOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_control_iv = license_messages->core_response().key_array[0].key_control_iv; key_control_iv.offset = response_message_length - key_control_iv.length + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyControlLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_control.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringKeyControlOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().key_array[0].key_control.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyControlLengthAPI16) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_control = license_messages->core_response().key_array[0].key_control; key_control.length = response_message_length - key_control.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringKeyControlOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& key_control = license_messages->core_response().key_array[0].key_control; key_control.offset = response_message_length - key_control.length + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringEncMacKeyIvLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().enc_mac_keys_iv.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringEncMacKeyIvOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().enc_mac_keys_iv.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringEncMacKeyIvLength) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& enc_mac_keys_iv = license_messages->core_response().enc_mac_keys_iv; enc_mac_keys_iv.length = response_message_length - enc_mac_keys_iv.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringEncMacKeyIvOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& enc_mac_keys_iv = license_messages->core_response().enc_mac_keys_iv; enc_mac_keys_iv.offset = response_message_length - enc_mac_keys_iv.length + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringEncMacKeyLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().enc_mac_keys.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringEncMacKeyOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().enc_mac_keys.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringEncMacKeyLength) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& enc_mac_keys = license_messages->core_response().enc_mac_keys; enc_mac_keys.length = response_message_length - enc_mac_keys.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringEncMacKeyOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& enc_mac_keys = license_messages->core_response().enc_mac_keys; enc_mac_keys.offset = response_message_length - enc_mac_keys.length + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringPstLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().pst.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringPstOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().pst.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringPstLength) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& pst = license_messages->core_response().pst; pst.length = response_message_length - pst.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringPstOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& pst = license_messages->core_response().pst; pst.offset = response_message_length; if (pst.length == 0) pst.length = 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringSrmRestrictionDataLength) { TestLoadLicenseForHugeBufferLengths( [](size_t length, LicenseRoundTrip* license_messages) { license_messages->core_response().srm_restriction_data.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageSubstringSrmRestrictionDataOffset) { TestLoadLicenseForHugeBufferLengths( [](size_t offset, LicenseRoundTrip* license_messages) { license_messages->core_response().srm_restriction_data.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringSrmRestrictionDataLength) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& srm_restriction_data = license_messages->core_response().srm_restriction_data; srm_restriction_data.length = response_message_length - srm_restriction_data.offset + 1; }); } /** Test that LoadLicense fails gracefully on out of range substring. */ TEST_P( OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForOutOfRangeCoreMessageSubstringSrmRestrictionDataOffset) { TestLoadLicenseForOutOfRangeSubStringOffSetAndLengths( [](size_t response_message_length, LicenseRoundTrip* license_messages) { auto& srm_restriction_data = license_messages->core_response().srm_restriction_data; srm_restriction_data.offset = response_message_length; if (srm_restriction_data.length == 0) srm_restriction_data.length = 1; }); } /** Test that LoadLicense fails gracefully on huge buffer. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeResponseLength) { TestLoadLicenseForHugeBufferLengths( [](size_t message_size, LicenseRoundTrip* license_messages) { license_messages->set_message_size(message_size); }, !kCheckStatus, !kUpdateCoreMessageSubstringValues); } /** Test that LoadLicense fails gracefully on huge buffer. */ TEST_P(OEMCryptoLicenseOverflowTest, OEMCryptoMemoryLoadLicenseForHugeCoreMessageLength) { TestLoadLicenseForHugeBufferLengths( [](size_t message_size, LicenseRoundTrip* license_messages) { license_messages->set_core_message_size(message_size); }, !kCheckStatus, !kUpdateCoreMessageSubstringValues); } INSTANTIATE_TEST_SUITE_P(TestAll, OEMCryptoLicenseOverflowTest, Range(kCurrentAPI - 1, kCurrentAPI + 1)); /// @} /// @addtogroup cas /// @{ TEST_P(OEMCryptoEntitlementLicenseTest, CasOnlyLoadCasKeysAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadCasKeys( /*load_even=*/true, /*load_odd=*/true, OEMCrypto_SUCCESS)); EntitledMessage entitled_message_2(&license_messages_); entitled_message_2.FillKeyArray(); entitled_message_2.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_2.LoadCasKeys( /*load_even=*/true, /*load_odd=*/false, OEMCrypto_SUCCESS)); EntitledMessage entitled_message_3(&license_messages_); entitled_message_3.FillKeyArray(); entitled_message_3.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_3.LoadCasKeys( /*load_even=*/false, /*load_odd=*/true, OEMCrypto_SUCCESS)); ASSERT_NO_FATAL_FAILURE(entitled_message_3.LoadCasKeys( /*load_even=*/false, /*load_odd=*/false, OEMCrypto_SUCCESS)); } /** * This verifies that entitled content keys cannot be loaded if we have loaded * the wrong entitlement keys. */ TEST_P(OEMCryptoEntitlementLicenseTest, CasOnlyLoadCasKeysNoEntitlementKeysAPI17) { if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadCasKeys( /*load_even=*/true, /*load_odd=*/true, OEMCrypto_ERROR_INVALID_CONTEXT)); } TEST_P(OEMCryptoEntitlementLicenseTest, CasOnlyLoadCasKeysWrongEntitlementKeysAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); const std::string key_id = "no_key"; entitled_message_1.SetEntitlementKeyId(0, key_id); entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadCasKeys( /*load_even=*/true, /*load_odd=*/true, OEMCrypto_KEY_NOT_ENTITLED)); } TEST_P(OEMCryptoEntitlementLicenseTest, CasOnlyLoadCasKeysWrongEntitledKeySessionAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); const uint32_t wrong_key_session_id = key_session_id == 0 ? 1 : 0; entitled_message_1.SetEntitledKeySession(wrong_key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadCasKeys( /*load_even=*/true, /*load_odd=*/true, OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION)); } /** * This verifies that entitled content keys cannot be loaded if we specify an * entitled key session that is actually an oemcrypto session. */ TEST_P(OEMCryptoEntitlementLicenseTest, LoadEntitlementKeysOemcryptoSessionAPI17) { if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); if (session_.session_id() == key_session_id) { GTEST_SKIP() << "Skipping test because entitled and entitlement sessions are both " << key_session_id << "."; } entitled_message_1.SetEntitledKeySession(session_.session_id()); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(false)); } TEST_P(OEMCryptoEntitlementLicenseTest, CasOnlyLoadCasKeysOemcryptoSessionAPI17) { if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(session_.session_id()); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadCasKeys( /*load_even=*/true, /*load_odd=*/true, OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION)); } /** * Select key with entitlement license fails if the key id is entitlement key * id. */ TEST_P(OEMCryptoLicenseTest, SelectKeyEntitlementKeyAPI17) { if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); uint32_t key_session_id; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(true)); if (session_.session_id() == key_session_id) { GTEST_SKIP() << "Skipping test because entitled and entitlement sessions are both " << key_session_id << "."; } ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_ERROR_INVALID_CONTEXT, session_.session_id(), session_.license().keys[0].key_id, session_.license().keys[0].key_id_length)); } // This verifies that multiple entitled key sessions can be created. They can // load and select keys independently. TEST_P(OEMCryptoLicenseTest, EntitledKeySessionMultipleKeySessionsAPI17) { if (!global_features.supports_cas) { GTEST_SKIP() << "OEMCrypto does not support CAS"; } if (wvoec::global_features.api_version < 17) { GTEST_SKIP() << "Test for versions 17 and up only."; } license_messages_.set_license_type(OEMCrypto_EntitlementLicense); ASSERT_NO_FATAL_FAILURE(license_messages_.SignAndVerifyRequest()); ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); ASSERT_NO_FATAL_FAILURE(license_messages_.EncryptAndSignResponse()); ASSERT_EQ(OEMCrypto_SUCCESS, license_messages_.LoadResponse()); uint32_t key_session_id_1; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id_1)); EntitledMessage entitled_message_1(&license_messages_); entitled_message_1.FillKeyArray(); entitled_message_1.SetEntitledKeySession(key_session_id_1); const char* content_key_id_1 = "content_key_id_1"; entitled_message_1.SetContentKeyId(0, content_key_id_1); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(true)); // We can select content key 1 in entitled key session 1. ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_SUCCESS, key_session_id_1, reinterpret_cast(content_key_id_1), strlen(content_key_id_1))); // Create another entitled key session. uint32_t key_session_id_2; OEMCryptoResult status = OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id_2); // For DRM, but not for CAS, we allow there to be only a single entitled // session. if (!global_features.supports_cas && (key_session_id_2 == key_session_id_1 || status == OEMCrypto_ERROR_TOO_MANY_SESSIONS)) { GTEST_SKIP() << "Skipping test because multiple entitled sessions not supported."; } ASSERT_EQ(OEMCrypto_SUCCESS, status); // Entitled key sessions should have unique ids. ASSERT_NE(key_session_id_1, key_session_id_2); EntitledMessage entitled_message_2(&license_messages_); entitled_message_2.FillKeyArray(); entitled_message_2.SetEntitledKeySession(key_session_id_2); const char* content_key_id_2 = "content_key_id_2"; entitled_message_2.SetContentKeyId(0, content_key_id_2); ASSERT_NO_FATAL_FAILURE(entitled_message_2.LoadKeys(true)); // We can select content key 2 in entitled key session 2. ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_SUCCESS, key_session_id_2, reinterpret_cast(content_key_id_2), strlen(content_key_id_2))); // Content key id 1 is not in entitled key session 2. ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_ERROR_NO_CONTENT_KEY, key_session_id_2, reinterpret_cast(content_key_id_1), strlen(content_key_id_1))); // Content key id 2 is not in entitled key session 1. ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( OEMCrypto_ERROR_NO_CONTENT_KEY, key_session_id_1, reinterpret_cast(content_key_id_2), strlen(content_key_id_2))); } /// @} /// @addtogroup security /// @{ /** Test that LoadProvisioning fails gracefully on huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeResponseLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForHugeBufferLengths( [](size_t message_size, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->set_message_size(message_size); }, !kCheckStatus, !kUpdateCoreMessageSubstringValues); } /** Test that LoadProvisioning fails gracefully on huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeCoreMessageLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForHugeBufferLengths( [](size_t message_size, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->set_core_message_size(message_size); }, !kCheckStatus, !kUpdateCoreMessageSubstringValues); } /** Test that LoadProvisioning fails gracefully on huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeCoreMessageEncPrivateKeyLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForHugeBufferLengths( [](size_t length, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->core_response().enc_private_key.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadProvisioning fails gracefully on huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeCoreMessageEncPrivateKeyOffset) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForHugeBufferLengths( [](size_t offset, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->core_response().enc_private_key.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F( OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForOutOfRangeCoreMessageEncPrivateKeyLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForOutOfRangeSubstringOffsetAndLengths( [](size_t response_message_length, ProvisioningRoundTrip* provisioning_messages) { auto& enc_private_key = provisioning_messages->core_response().enc_private_key; enc_private_key.length = response_message_length - enc_private_key.offset + 1; }); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F( OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForOutOfRangeCoreMessageEncPrivateKeyOffset) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForOutOfRangeSubstringOffsetAndLengths( [](size_t response_message_length, ProvisioningRoundTrip* provisioning_messages) { auto& enc_private_key = provisioning_messages->core_response().enc_private_key; enc_private_key.offset = response_message_length - enc_private_key.length + 1; }); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeCoreMessageEncPrivateKeyIvLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForHugeBufferLengths( [](size_t length, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->core_response().enc_private_key_iv.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeCoreMessageEncPrivateKeyIvOffset) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForHugeBufferLengths( [](size_t offset, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->core_response().enc_private_key_iv.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F( OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForOutOfRangeCoreMessageEncPrivateKeyIvLengthAPI16) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForOutOfRangeSubstringOffsetAndLengths( [](size_t response_message_length, ProvisioningRoundTrip* provisioning_messages) { auto& enc_private_key_iv = provisioning_messages->core_response().enc_private_key_iv; enc_private_key_iv.length = response_message_length - enc_private_key_iv.offset + 1; }); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F( OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForOutOfRangeCoreMessageEncPrivateKeyIvOffset) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForOutOfRangeSubstringOffsetAndLengths( [](size_t response_message_length, ProvisioningRoundTrip* provisioning_messages) { auto& enc_private_key_iv = provisioning_messages->core_response().enc_private_key_iv; enc_private_key_iv.offset = response_message_length - enc_private_key_iv.length + 1; }); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeCoreMessageEncMessageKeyLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForHugeBufferLengths( [](size_t length, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->core_response().encrypted_message_key.length = length; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForHugeCoreMessageEncMessageKeyOffset) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestLoadProvisioningForHugeBufferLengths( [](size_t offset, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->core_response().encrypted_message_key.offset = offset; }, !kCheckStatus, kUpdateCoreMessageSubstringValues); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F( OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForOutOfRangeCoreMessageEncMessageKeyLengthProv30) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } if (global_features.provisioning_method != OEMCrypto_OEMCertificate) { GTEST_SKIP() << "Test for Prov 3.0 devices only."; } TestLoadProvisioningForOutOfRangeSubstringOffsetAndLengths( [](size_t response_message_length, ProvisioningRoundTrip* provisioning_messages) { auto& encrypted_message_key = provisioning_messages->core_response().encrypted_message_key; encrypted_message_key.length = response_message_length - encrypted_message_key.offset + 1; }); } /** Test that LoadProvisioning fails gracefully on out of range substring. */ TEST_F( OEMCryptoLoadsCertificate, OEMCryptoMemoryLoadProvisioningForOutOfRangeCoreMessageEncMessageKeyOffsetProv30) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } if (global_features.provisioning_method != OEMCrypto_OEMCertificate) { GTEST_SKIP() << "Test for Prov 3.0 devices only."; } TestLoadProvisioningForOutOfRangeSubstringOffsetAndLengths( [](size_t response_message_length, ProvisioningRoundTrip* provisioning_messages) { auto& encrypted_message_key = provisioning_messages->core_response().encrypted_message_key; encrypted_message_key.offset = response_message_length - encrypted_message_key.length + 1; }); } /// @} /// @addtogroup security /// @{ /** Test that OEMCrypto_PrepAndSignProvisioningRequest fails gracefully on a * huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryPrepareProvisioningRequestForHugeRequestMessageLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestPrepareProvisioningRequestForHugeBufferLengths( [](size_t message_size, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->set_message_size(message_size); }, kCheckStatus); } /** Test that OEMCrypto_PrepAndSignProvisioningRequest fails gracefully on a * huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryPrepareProvisioningRequestForHugeSignatureLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestPrepareProvisioningRequestForHugeBufferLengths( [](size_t message_size, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->set_request_signature_size(message_size); }, !kCheckStatus); } /** Test that OEMCrypto_PrepAndSignProvisioningRequest fails gracefully on a * huge buffer. */ TEST_F(OEMCryptoLoadsCertificate, OEMCryptoMemoryPrepareProvisioningRequestForHugeCoreMessageLength) { // TODO(b/197141970): Need to revisit OEMCryptoLoadsCert* tests for // provisioning 4. Disabled here temporarily. if (!global_features.loads_certificate || global_features.provisioning_method == OEMCrypto_BootCertificateChain) { GTEST_SKIP() << "Test for non Prov 4.0 devices only."; } TestPrepareProvisioningRequestForHugeBufferLengths( [](size_t message_size, ProvisioningRoundTrip* provisioning_messages) { provisioning_messages->set_core_message_size(message_size); }, kCheckStatus); } /// @} /// @addtogroup cast /// @{ /// @} #ifdef CAS_TEST # include "tuner_hal.h" class OEMCryptoCasDemoTest : public OEMCryptoEntitlementLicenseTest {}; TEST_P(OEMCryptoCasDemoTest, BasicFlow) { // License contains entitlement keys, function reused from // OEMCryptoEntitlementLicenseTest LoadEntitlementLicense(); uint32_t key_session_id = 0; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( session_.session_id(), &key_session_id)); EntitledMessage entitled_message(&license_messages_); // Randomly generate entitled content keys entitled_message.FillKeyArray(); if (session_.session_id() == key_session_id) { GTEST_SKIP() << "Skipping test because entitled and entitlement sessions are both " << key_session_id << "."; } entitled_message.SetEntitledKeySession(key_session_id); // Encrypt and load 0th key (even key) into OEMCrypto ASSERT_NO_FATAL_FAILURE(entitled_message.LoadCasKeys( /*load_even=*/true, /*load_odd=*/false, OEMCrypto_SUCCESS)); // // Perform DecryptCTR() but for CAS // vector unencrypted_data(256, 0); vector encrypted_data(256, 0); vector output_buffer(256, 0); unencrypted_data.resize(encrypted_data.size()); output_buffer.resize(encrypted_data.size()); OEMCrypto_SampleDescription sample_description; OEMCrypto_SubSampleDescription subsample_description; GenerateSimpleSampleDescription(encrypted_data, output_buffer, &sample_description, &subsample_description); // Use 0th entitled content key and IV to encrypt test data EncryptCTR(unencrypted_data, entitled_message.entitled_key_data()->content_key_data, entitled_message.entitled_key_data()->content_iv, &encrypted_data); // Assume 0,0 pattern for CTR example OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0}; // Demo only -- copy IV into sample description so we can use // WTPI_DecryptSample() in the Tuner decrypt impl. A real implementation would // use the IV from the entitled content key, but the demo relies on the // existing decrypt which uses SampleDescription IV. memcpy(sample_description.iv, entitled_message.entitled_key_data()->content_iv, 16); // Get key token to send to Tuner for decrypt std::vector key_token; size_t key_token_length = key_token.size(); OEMCryptoResult res = OEMCrypto_GetOEMKeyToken( key_session_id, key_token.data(), &key_token_length); if (res == OEMCrypto_ERROR_SHORT_BUFFER) { key_token.resize(key_token_length); res = OEMCrypto_GetOEMKeyToken(key_session_id, key_token.data(), &key_token_length); } ASSERT_EQ(OEMCrypto_SUCCESS, res); // Decrypt the data ASSERT_EQ(TUNER_HAL_SUCCESS, TunerHal_Decrypt(key_token.data(), key_token_length, TunerHal_KeyParityType_EvenKey, &sample_description, // an array of samples. 1, // the number of samples. &pattern)); ASSERT_EQ(unencrypted_data, output_buffer); } INSTANTIATE_TEST_SUITE_P(TestAll, OEMCryptoCasDemoTest, Range(kCoreMessagesAPI, kCurrentAPI + 1)); #endif } // namespace wvoec