From 579b9144b57061173b6b968d653c122f15bc6f35 Mon Sep 17 00:00:00 2001 From: Vicky Min Date: Tue, 8 Nov 2022 13:56:10 -0800 Subject: [PATCH] Add a DecryptCENC call after SelectKey for entitled sessions Merge from Widevine repo of http://go/wvgerrit/154874 We do not require an error to come from SelectKey immediately, it can come from a following call to DecryptCENC. This adds a function Session::TestDecryptCENC to be called instead of SelectKey for the tests that use entitled sessions. Bug: 232225906 Test: tested with http://go/ag/20420224 Change-Id: If5695a5034cce371b6eb6bcf1b6467d84456c21d --- .../oemcrypto/test/oec_session_util.cpp | 36 ++++++++ .../oemcrypto/test/oec_session_util.h | 6 ++ .../oemcrypto/test/oemcrypto_test.cpp | 90 +++++++++---------- 3 files changed, 82 insertions(+), 50 deletions(-) diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index efc1a57d..1b3d37b5 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -1588,6 +1588,42 @@ void Session::TestDecryptCTR(bool select_key_first, } } +void Session::TestDecryptEntitled(OEMCryptoResult expected_result, + OEMCrypto_SESSION session_id, + const uint8_t* content_key_id, + size_t content_key_id_length) { + OEMCryptoResult select_result = OEMCrypto_SUCCESS; + // Select the key (from FillSimpleMessage) + select_result = OEMCrypto_SelectKey( + session_id, reinterpret_cast(content_key_id), + content_key_id_length, OEMCrypto_CipherMode_CENC); + + vector unencrypted_data; + vector output_buffer; + vector encrypted_data(kTestSubsampleSectionSize); + + vector in_buffer(256); + vector out_buffer(in_buffer.size()); + OEMCrypto_SampleDescription sample_description; + OEMCrypto_SubSampleDescription subsample_description; + ASSERT_NO_FATAL_FAILURE(GenerateSimpleSampleDescription( + in_buffer, out_buffer, &sample_description, &subsample_description)); + OEMCrypto_CENCEncryptPatternDesc pattern = {0, 0}; + + EncryptCTR(unencrypted_data, content_key_id, &sample_description.iv[0], + &encrypted_data); + // Try to decrypt the data with oemcrypto session id. + const OEMCryptoResult decrypt_result = + OEMCrypto_DecryptCENC(session_id, &sample_description, 1, &pattern); + + // We only have a few errors that we test are reported. + ASSERT_NO_FATAL_FAILURE( + TestDecryptResult(expected_result, select_result, decrypt_result)) + << "Either SelectKey or DecryptCENC should return " << expected_result + << ", but they returned " << select_result << " and " << decrypt_result + << ", respectively."; +} + void Session::TestDecryptResult(OEMCryptoResult expected_result, OEMCryptoResult actual_select_result, OEMCryptoResult actual_decrypt_result) { diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index 741f96a8..09ab77c9 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -561,6 +561,12 @@ class Session { void TestDecryptCTR(bool select_key_first = true, OEMCryptoResult expected_result = OEMCrypto_SUCCESS, size_t key_index = 0); + // Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption + // for entitled sessions. + void TestDecryptEntitled(OEMCryptoResult expected_result = OEMCrypto_SUCCESS, + OEMCrypto_SESSION session = 0, + const uint8_t* content_key_id = nullptr, + size_t content_key_id_length = 0); // Verify that an attempt to select an expired key either succeeds, or gives // an actionable error code. void TestSelectExpired(size_t key_index); diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 8d65b146..34240fe5 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -3051,11 +3051,10 @@ TEST_P(OEMCryptoLicenseTest, SelectKeyEntitledKeyNotThereAPI17) { ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(OEMCrypto_SUCCESS)); const char* content_key_id = "no_key"; - ASSERT_EQ( - OEMCrypto_ERROR_NO_CONTENT_KEY, - OEMCrypto_SelectKey(key_session_id, - reinterpret_cast(content_key_id), - strlen(content_key_id), OEMCrypto_CipherMode_CENC)); + ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( + OEMCrypto_ERROR_INVALID_CONTEXT, key_session_id, + reinterpret_cast(content_key_id), + strlen(content_key_id))); } // Select key with entitlement license fails if the key id is entitilement key @@ -3075,11 +3074,10 @@ TEST_P(OEMCryptoLicenseTest, SelectKeyEntitlementKeyAPI17) { entitled_message_1.SetEntitledKeySession(key_session_id); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(OEMCrypto_SUCCESS)); - ASSERT_EQ(OEMCrypto_ERROR_INVALID_CONTEXT, - OEMCrypto_SelectKey(session_.session_id(), - session_.license().keys[0].key_id, - session_.license().keys[0].key_id_length, - OEMCrypto_CipherMode_CENC)); + 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 entitled key sessions can be created and removed. @@ -3127,11 +3125,10 @@ TEST_P(OEMCryptoLicenseTest, EntitledKeySessionMultipleKeySessionsAPI17) { entitled_message_1.SetContentKeyId(0, content_key_id_1); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(OEMCrypto_SUCCESS)); // We can select content key 1 in entitled key session 1. - ASSERT_EQ( - OEMCrypto_SUCCESS, - OEMCrypto_SelectKey(key_session_id_1, - reinterpret_cast(content_key_id_1), - strlen(content_key_id_1), OEMCrypto_CipherMode_CENC)); + 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; ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CreateEntitledKeySession( @@ -3146,23 +3143,20 @@ TEST_P(OEMCryptoLicenseTest, EntitledKeySessionMultipleKeySessionsAPI17) { entitled_message_2.SetContentKeyId(0, content_key_id_2); ASSERT_NO_FATAL_FAILURE(entitled_message_2.LoadKeys(OEMCrypto_SUCCESS)); // We can select content key 2 in entitled key session 2. - ASSERT_EQ( - OEMCrypto_SUCCESS, - OEMCrypto_SelectKey(key_session_id_2, - reinterpret_cast(content_key_id_2), - strlen(content_key_id_2), OEMCrypto_CipherMode_CENC)); + 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_EQ( - OEMCrypto_ERROR_NO_CONTENT_KEY, - OEMCrypto_SelectKey(key_session_id_2, - reinterpret_cast(content_key_id_1), - strlen(content_key_id_1), OEMCrypto_CipherMode_CENC)); + 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_EQ( - OEMCrypto_ERROR_NO_CONTENT_KEY, - OEMCrypto_SelectKey(key_session_id_1, - reinterpret_cast(content_key_id_2), - strlen(content_key_id_2), OEMCrypto_CipherMode_CENC)); + 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))); } // This verifies that within an entitled key session, each entitlement key can @@ -3186,28 +3180,25 @@ TEST_P(OEMCryptoLicenseTest, entitled_message_1.SetContentKeyId(0, content_key_id_1); ASSERT_NO_FATAL_FAILURE(entitled_message_1.LoadKeys(OEMCrypto_SUCCESS)); // We can select content key 1 in entitled key session. - ASSERT_EQ( - OEMCrypto_SUCCESS, - OEMCrypto_SelectKey(key_session_id, - reinterpret_cast(content_key_id_1), - strlen(content_key_id_1), OEMCrypto_CipherMode_CENC)); + 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(OEMCrypto_SUCCESS)); // We can select content key 2 in entitled key session. - ASSERT_EQ( - OEMCrypto_SUCCESS, - OEMCrypto_SelectKey(key_session_id, - reinterpret_cast(content_key_id_2), - strlen(content_key_id_2), OEMCrypto_CipherMode_CENC)); + 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_EQ( - OEMCrypto_ERROR_NO_CONTENT_KEY, - OEMCrypto_SelectKey(key_session_id, - reinterpret_cast(content_key_id_1), - strlen(content_key_id_1), OEMCrypto_CipherMode_CENC)); + 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 decrypt @@ -3231,11 +3222,10 @@ TEST_P(OEMCryptoLicenseTest, const char* content_key_id = "content_key_id"; entitled_message.SetContentKeyId(0, content_key_id); ASSERT_NO_FATAL_FAILURE(entitled_message.LoadKeys(OEMCrypto_SUCCESS)); - ASSERT_EQ( - OEMCrypto_SUCCESS, - OEMCrypto_SelectKey(key_session_id, - reinterpret_cast(content_key_id), - strlen(content_key_id), OEMCrypto_CipherMode_CENC)); + ASSERT_NO_FATAL_FAILURE(session_.TestDecryptEntitled( + OEMCrypto_SUCCESS, key_session_id, + reinterpret_cast(content_key_id), + strlen(content_key_id))); vector in_buffer(256); vector out_buffer(in_buffer.size());