diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index b43bfc7b..43c43fb2 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -980,7 +980,7 @@ CdmResponseType CryptoSession::SelectKey(const std::string& key_id, return NO_DEVICE_KEY_1; case OEMCrypto_ERROR_NO_CONTENT_KEY: return NO_CONTENT_KEY_2; - case OEMCrypto_KEY_NOT_LOADED: + case OEMCrypto_KEY_NOT_LOADED: // obsolete. return NO_CONTENT_KEY_3; case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES: return INSUFFICIENT_CRYPTO_RESOURCES_2; @@ -1802,7 +1802,8 @@ CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer, LOGE("GenericEncrypt: OEMCrypto_Generic_Encrypt err=%d", sts); if (OEMCrypto_ERROR_KEY_EXPIRED == sts) { return NEED_KEY; - } else if (OEMCrypto_ERROR_NO_CONTENT_KEY == sts) { + } else if (OEMCrypto_ERROR_NO_CONTENT_KEY == sts + || OEMCrypto_KEY_NOT_LOADED == sts) { // obsolete in v15. return KEY_NOT_FOUND_3; } else { return UNKNOWN_ERROR; @@ -1854,7 +1855,8 @@ CdmResponseType CryptoSession::GenericDecrypt(const std::string& in_buffer, LOGE("GenericDecrypt: OEMCrypto_Generic_Decrypt err=%d", sts); if (OEMCrypto_ERROR_KEY_EXPIRED == sts) { return NEED_KEY; - } else if (OEMCrypto_ERROR_NO_CONTENT_KEY == sts) { + } else if (OEMCrypto_ERROR_NO_CONTENT_KEY == sts + || OEMCrypto_KEY_NOT_LOADED == sts) { // obsolete in v15. return KEY_NOT_FOUND_4; } else { return UNKNOWN_ERROR; @@ -1916,7 +1918,8 @@ CdmResponseType CryptoSession::GenericSign(const std::string& message, LOGE("GenericSign: OEMCrypto_Generic_Sign err=%d", sts); if (OEMCrypto_ERROR_KEY_EXPIRED == sts) { return NEED_KEY; - } else if (OEMCrypto_ERROR_NO_CONTENT_KEY == sts) { + } else if (OEMCrypto_ERROR_NO_CONTENT_KEY == sts + || OEMCrypto_KEY_NOT_LOADED == sts) { // obsolete in v15. return KEY_NOT_FOUND_5; } else { return UNKNOWN_ERROR; @@ -1954,7 +1957,8 @@ CdmResponseType CryptoSession::GenericVerify(const std::string& message, LOGE("GenericVerify: OEMCrypto_Generic_Verify err=%d", sts); if (OEMCrypto_ERROR_KEY_EXPIRED == sts) { return NEED_KEY; - } else if (OEMCrypto_ERROR_NO_CONTENT_KEY == sts) { + } else if (OEMCrypto_ERROR_NO_CONTENT_KEY == sts + || OEMCrypto_KEY_NOT_LOADED == sts) { // obsolete in v15. return KEY_NOT_FOUND_6; } else { return UNKNOWN_ERROR; diff --git a/libwvdrmengine/cdm/core/src/entitlement_key_session.cpp b/libwvdrmengine/cdm/core/src/entitlement_key_session.cpp index 06041886..52c1607b 100644 --- a/libwvdrmengine/cdm/core/src/entitlement_key_session.cpp +++ b/libwvdrmengine/cdm/core/src/entitlement_key_session.cpp @@ -49,7 +49,7 @@ OEMCryptoResult EntitlementKeySession::SelectKey(const std::string& key_id, // correct key every time SelectKey() is called. if (entitled_keys_.find(key_id) == entitled_keys_.end()) { LOGE("Unknown entitled key ID selected."); - return OEMCrypto_KEY_NOT_LOADED; + return OEMCrypto_ERROR_NO_CONTENT_KEY; } OEMCrypto_EntitledContentKeyObject entitled_key = diff --git a/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp b/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp index b04a9ea8..7fb44034 100644 --- a/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp @@ -120,7 +120,7 @@ TEST_F(WvGenericOperationsTest, GenericEncryptNoKey) { cdm_sts = cdm_engine_.GenericEncrypt( holder_.session_id(), in_buffer_, key_id, iv_, wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer); - EXPECT_EQ(NO_CONTENT_KEY_3, cdm_sts); + EXPECT_EQ(NO_CONTENT_KEY_2, cdm_sts); EXPECT_NE(encrypted, out_buffer); } @@ -163,7 +163,7 @@ TEST_F(WvGenericOperationsTest, GenericDecryptNoKey) { cdm_sts = cdm_engine_.GenericDecrypt( holder_.session_id(), in_buffer_, key_id, iv_, wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer); - EXPECT_EQ(NO_CONTENT_KEY_3, cdm_sts); + EXPECT_EQ(NO_CONTENT_KEY_2, cdm_sts); EXPECT_NE(decrypted, out_buffer); } diff --git a/libwvdrmengine/include_hidl/mapErrors-inl.h b/libwvdrmengine/include_hidl/mapErrors-inl.h index 7aa9f4c0..b1c6d815 100644 --- a/libwvdrmengine/include_hidl/mapErrors-inl.h +++ b/libwvdrmengine/include_hidl/mapErrors-inl.h @@ -30,6 +30,9 @@ static Status mapCdmResponseType(wvcdm::CdmResponseType res) { case wvcdm::KEY_NOT_FOUND_IN_SESSION: case wvcdm::NEED_KEY: case wvcdm::NO_MATCHING_ENTITLEMENT_KEY: + // TODO(http://b/119690361): there are several NO_CONTENT_* errors. + // that should probably all turn into NO_LICENSE. Here, and below, and + // everywhere. case wvcdm::NO_CONTENT_KEY_3: return Status::ERROR_DRM_NO_LICENSE; diff --git a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h index 6eee9120..50e688e4 100644 --- a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h +++ b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h @@ -81,7 +81,7 @@ typedef enum OEMCryptoResult { OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE = 48, OEMCrypto_ERROR_ENTRY_IN_USE = 49, OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE = 50, // Reserved. Do not use. - OEMCrypto_KEY_NOT_LOADED = 51, + OEMCrypto_KEY_NOT_LOADED = 51, // obsolete. use error 26. OEMCrypto_KEY_NOT_ENTITLED = 52, OEMCrypto_ERROR_BAD_HASH = 53, OEMCrypto_ERROR_OUTPUT_TOO_LARGE = 54, diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp index b6a4350e..eadc640b 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp @@ -809,7 +809,7 @@ OEMCryptoResult SessionContext::RefreshKey( if (NULL == content_key) { LOGE("Key ID not found."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; + return OEMCrypto_ERROR_NO_CONTENT_KEY; } if (key_control.empty()) { @@ -1156,7 +1156,7 @@ OEMCryptoResult SessionContext::SelectContentKey( Key* content_key = session_keys_->Find(key_id); if (NULL == content_key) { LOGE("No key matches key id"); - return OEMCrypto_KEY_NOT_LOADED; + return OEMCrypto_ERROR_NO_CONTENT_KEY; } content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR); current_content_key_ = content_key; diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index ae4b19ab..e1ff80d7 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -282,7 +282,7 @@ void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) { VerifyTestKeys(); } -void Session::LoadEnitlementTestKeys(const std::string& pst, +void Session::LoadEntitlementTestKeys(const std::string& pst, bool new_mac_keys, OEMCryptoResult expected_sts) { uint8_t* pst_ptr = NULL; @@ -347,7 +347,7 @@ void Session::LoadEntitledContentKeys(OEMCryptoResult expected_sts) { memcpy(&encrypted_entitled_key_array[0], &entitled_key_array_[0], sizeof(OEMCrypto_EntitledContentKeyObject) * num_keys_); - // Create a encrypted version of all of the content keys stored in + // Create an encrypted version of all of the content keys stored in // |entitled_key_array_|. std::vector > encrypted_content_keys; encrypted_content_keys.resize(num_keys_); diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index 05645cdd..9002d1bf 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -165,12 +165,12 @@ class Session { // using OEMCrypto_LoadKeys. This message should have already been created // by FillSimpleEntitlementMessage, modified if needed, and then encrypted // and signed by the server's mac key in EncryptAndSign. - void LoadEnitlementTestKeys(const std::string& pst = "", + void LoadEntitlementTestKeys(const std::string& pst = "", bool new_mac_keys = true, OEMCryptoResult expected_sts = OEMCrypto_SUCCESS); // Fills an OEMCrypto_EntitledContentKeyObject using the information from // the license_ and randomly generated content keys. This method should be - // called after LoadEnitlementTestKeys. + // called after LoadEntitlementTestKeys. void FillEntitledKeyArray(); // Encrypts and loads the entitled content keys via // OEMCrypto_LoadEntitledContentKeys. @@ -196,7 +196,7 @@ class Session { const std::string& pst = ""); // This fills the data structure license_ with entitlement key information. // This data can be modified, and then should be encrypted and signed in - // EncryptAndSign before being loaded in LoadEnitlementTestKeys. + // EncryptAndSign before being loaded in LoadEntitlementTestKeys. void FillSimpleEntitlementMessage( uint32_t duration, uint32_t control, uint32_t nonce, const std::string& pst = ""); @@ -364,6 +364,12 @@ class Session { // An array of key objects for use in LoadKeys. OEMCrypto_KeyObject* key_array() { return key_array_; } + + // An array of key objects for LoadEntitledContentKeys. + OEMCrypto_EntitledContentKeyObject* entitled_key_array() { + return entitled_key_array_; + } + // The last signature generated with the server's mac key. std::vector& signature() { return signature_; } diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index a66b62c4..befba38f 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -850,7 +850,7 @@ TEST_F(OEMCryptoSessionTests, LoadEntitlementKeysAPI14) { ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s)); ASSERT_NO_FATAL_FAILURE(s.FillSimpleEntitlementMessage(0, 0, 0)); ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); - ASSERT_NO_FATAL_FAILURE(s.LoadEnitlementTestKeys()); + ASSERT_NO_FATAL_FAILURE(s.LoadEntitlementTestKeys()); s.FillEntitledKeyArray(); ASSERT_NO_FATAL_FAILURE(s.LoadEntitledContentKeys()); s.FillEntitledKeyArray(); @@ -863,10 +863,26 @@ TEST_F(OEMCryptoSessionTests, LoadEntitlementKeysNoEntitlementKeysAPI14) { ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s)); ASSERT_NO_FATAL_FAILURE(s.FillSimpleEntitlementMessage(0, 0, 0)); ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); + // We do NOT call LoadEntitlementTestKeys. s.FillEntitledKeyArray(); s.LoadEntitledContentKeys(OEMCrypto_ERROR_INVALID_CONTEXT); } +TEST_F(OEMCryptoSessionTests, LoadEntitlementKeysWrongEntitlementKeysAPI14) { + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s)); + ASSERT_NO_FATAL_FAILURE(s.FillSimpleEntitlementMessage(0, 0, 0)); + ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); + ASSERT_NO_FATAL_FAILURE(s.LoadEntitlementTestKeys()); + s.FillEntitledKeyArray(); + const std::string key_id = "no_key"; + s.entitled_key_array()[0].entitlement_key_id = + reinterpret_cast(key_id.c_str()); + s.entitled_key_array()[0].entitlement_key_id_length = key_id.length(); + s.LoadEntitledContentKeys(OEMCrypto_KEY_NOT_ENTITLED); +} + // This tests GenerateSignature with an 8k licnese request. TEST_F(OEMCryptoSessionTests, ClientSignatureLargeBuffer) { Session s; @@ -1267,6 +1283,21 @@ TEST_F(OEMCryptoSessionTests, LoadKeyNoKeyWithNonce) { OEMCrypto_ContentLicense)); } +TEST_F(OEMCryptoSessionTests, SelectKeyNotThere) { + Session s; + ASSERT_NO_FATAL_FAILURE(s.open()); + ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s)); + ASSERT_NO_FATAL_FAILURE( + s.FillSimpleMessage(0, wvoec::kControlNonceEnabled, s.get_nonce())); + ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign()); + ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys()); + const char* key_id = "no_key"; + ASSERT_EQ(OEMCrypto_ERROR_NO_CONTENT_KEY, + OEMCrypto_SelectKey( + s.session_id(), reinterpret_cast(key_id), + strlen(key_id), OEMCrypto_CipherMode_CTR)); +} + TEST_F(OEMCryptoSessionTests, QueryKeyControl) { Session s; ASSERT_NO_FATAL_FAILURE(s.open()); @@ -1288,7 +1319,7 @@ TEST_F(OEMCryptoSessionTests, QueryKeyControl) { ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts); const char* key_id = "no_key"; size = sizeof(block); - ASSERT_NE(OEMCrypto_SUCCESS, + ASSERT_EQ(OEMCrypto_ERROR_NO_CONTENT_KEY, OEMCrypto_QueryKeyControl( s.session_id(), reinterpret_cast(key_id), strlen(key_id), reinterpret_cast(&block), &size));