From 1857da2c8c6f59a12963684d7040c07f5b1002cf Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Wed, 7 Jun 2017 15:36:53 -0700 Subject: [PATCH] Correct offline license handling [ Merge of http://go/wvgerrit/28261 ] Licenses (offline, secure stops) that contain provider session tokens are handled securely using usage tables. A recent fix did not correctly handle offline licenses that do not contain a provider session token and are not handled by the TEE. b/62340248 Test: WV Unit/integration tests, GtsMediaTestCases Change-Id: Ia1331fea9deff44dd1d93219b37f5bea4b8ee168 --- .../cdm/core/include/wv_cdm_constants.h | 1 + libwvdrmengine/cdm/core/src/cdm_session.cpp | 16 +++++++++++++--- libwvdrmengine/cdm/core/src/crypto_session.cpp | 18 ++++++++++++------ .../core/test/usage_table_header_unittest.cpp | 2 -- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h index 25ce8d3a..8a29dacb 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h @@ -72,6 +72,7 @@ static const std::string QUERY_VALUE_SECURITY_LEVEL_L1 = "L1"; static const std::string QUERY_VALUE_SECURITY_LEVEL_L2 = "L2"; static const std::string QUERY_VALUE_SECURITY_LEVEL_L3 = "L3"; static const std::string QUERY_VALUE_SECURITY_LEVEL_UNKNOWN = "Unknown"; +static const std::string QUERY_VALUE_SECURITY_LEVEL_DEFAULT = "Default"; static const std::string QUERY_VALUE_DISCONNECTED = "Disconnected"; static const std::string QUERY_VALUE_UNPROTECTED = "Unprotected"; static const std::string QUERY_VALUE_HDCP_V1 = "HDCP-1.x"; diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 0731b465..e8162bb3 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -212,7 +212,14 @@ CdmResponseType CdmSession::RestoreOfflineSession( return GET_RELEASED_LICENSE_ERROR; } - if (usage_support_type_ == kUsageEntrySupport) { + std::string provider_session_token; + if (!license_parser_->ExtractProviderSessionToken( + key_response_, &provider_session_token)) { + provider_session_token.clear(); + } + + if (usage_support_type_ == kUsageEntrySupport && + provider_session_token.size() > 0) { CdmResponseType sts = usage_table_header_->LoadEntry(crypto_session_.get(), usage_entry_, usage_entry_number_); @@ -236,7 +243,8 @@ CdmResponseType CdmSession::RestoreOfflineSession( } } - if (usage_support_type_ == kUsageEntrySupport) { + if (usage_support_type_ == kUsageEntrySupport && + provider_session_token.size() > 0) { CdmResponseType sts = usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); if (sts != NO_ERROR) { @@ -459,8 +467,10 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) { key_response_ = key_response; if (is_offline_ || has_provider_session_token()) { - if (usage_support_type_ == kUsageEntrySupport) + if (has_provider_session_token() && + usage_support_type_ == kUsageEntrySupport) { usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); + } if (!is_offline_) usage_provider_session_token_ = diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 29b34dd3..426c3399 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -434,8 +434,10 @@ uint8_t CryptoSession::GetSecurityPatchLevel() { } CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) { - LOGV("CryptoSession::Open: Lock: requested_security_level: %d", - requested_security_level); + LOGD("CryptoSession::Open: Lock: requested_security_level: %s", + requested_security_level == kLevel3 + ? QUERY_VALUE_SECURITY_LEVEL_L3.c_str() + : QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str()); AutoLock auto_lock(crypto_lock_); if (!initialized_) return UNKNOWN_ERROR; if (open_) return NO_ERROR; @@ -1645,11 +1647,15 @@ bool CryptoSession::GetSrmVersion(uint16_t* srm_version) { } OEMCryptoResult status = OEMCrypto_GetCurrentSRMVersion(srm_version); - if (OEMCrypto_SUCCESS != status) { - LOGW("OEMCrypto_GetCurrentSRMVersion fails with %d", status); - return false; + switch (status) { + case OEMCrypto_SUCCESS: + return true; + case OEMCrypto_ERROR_NOT_IMPLEMENTED: + return false; + default: + LOGW("OEMCrypto_GetCurrentSRMVersion fails with %d", status); + return false; } - return true; } bool CryptoSession::IsSrmUpdateSupported() { diff --git a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp index 0c81b4cc..26bb500e 100644 --- a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp @@ -363,7 +363,6 @@ TEST_F(UsageTableHeaderTest, LoadEntry) { TEST_F(UsageTableHeaderTest, UpdateEntry_CryptoSessionError) { Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector); - uint32_t usage_entry_number; CdmUsageEntry usage_entry; EXPECT_CALL(*crypto_session_, UpdateUsageEntry(NotNull(), NotNull())) @@ -377,7 +376,6 @@ TEST_F(UsageTableHeaderTest, UpdateEntry_CryptoSessionError) { TEST_F(UsageTableHeaderTest, UpdateEntry) { Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector); - uint32_t usage_entry_number; CdmUsageEntry usage_entry; EXPECT_CALL(*crypto_session_, UpdateUsageEntry(NotNull(), NotNull()))