From db05f1e01cf7945518e8f331271e1e929ab7b459 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Mon, 12 Jun 2017 20:03:57 -0700 Subject: [PATCH] Usage license handling corrections [ Merge of http://go/wvgerrit/28460 ] Validate that offline licenses that do not contain a provider session token are not handled by the TEE. b/38490468 Test: WV Unit/integration tests, GtsMediaTestCases, WvCdmRequestLicenseTest.ReleaseRetryL3OfflineKeySessionUsageDisabledTest Change-Id: Idaf62f2a882ae933c1a3e108d791943034780a46 --- libwvdrmengine/cdm/core/src/cdm_session.cpp | 12 ++- .../cdm/test/request_license_test.cpp | 75 +++++++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index e8162bb3..ab14d371 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -635,7 +635,8 @@ CdmResponseType CdmSession::GenerateReleaseRequest( if (KEY_MESSAGE != status) return status; - if (usage_support_type_ == kUsageEntrySupport) { + if (has_provider_session_token() && + usage_support_type_ == kUsageEntrySupport) { status = usage_table_header_->UpdateEntry(crypto_session_.get(), &usage_entry_); if (status != NO_ERROR) { @@ -666,7 +667,8 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) { if (is_offline_ || has_provider_session_token()) { DeleteLicense(); - if (usage_support_type_ == kUsageEntrySupport) { + if (usage_support_type_ == kUsageEntrySupport && + has_provider_session_token()) { sts = DeleteUsageEntry(usage_entry_number_); if (NO_ERROR != sts) return sts; } @@ -675,7 +677,8 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) { } CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) { - if (usage_support_type_ != kUsageEntrySupport) { + if (usage_support_type_ != kUsageEntrySupport || + !has_provider_session_token()) { LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d", usage_support_type_); return INCORRECT_USAGE_SUPPORT_TYPE_1; @@ -876,7 +879,8 @@ CdmResponseType CdmSession::UpdateUsageTableInformation() { } CdmResponseType CdmSession::UpdateUsageEntryInformation() { - if (usage_support_type_ != kUsageEntrySupport) { + if (usage_support_type_ != kUsageEntrySupport || + !has_provider_session_token()) { LOGE("CdmSession::UpdateUsageEntryInformation: Unexpected usage type " "supported: %d", usage_support_type_); return INCORRECT_USAGE_SUPPORT_TYPE_2; diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 027ab298..08a34121 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -1944,6 +1944,81 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) { VerifyKeyRequestResponse(g_license_server, client_auth); } +TEST_F(WvCdmRequestLicenseTest, + ReleaseRetryL3OfflineKeySessionUsageDisabledTest) { + Unprovision(); + + TestWvCdmClientPropertySet property_set; + property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3); + + // The default offline asset "offline_clip2" has the session usage table + // entry enabled in the replay control portion of the key control block. + // To have it disabled we must use "offline_clip1", so replace the last + // char in init data with '1' + std::string key_id; + std::string client_auth; + GetOfflineConfiguration(&key_id, &client_auth); + key_id[key_id.size()-1] = '1'; + + CdmResponseType sts = decryptor_.OpenSession( + g_key_system, &property_set, kDefaultCdmIdentifier, NULL, &session_id_); + + if (NEED_PROVISIONING == sts) { + std::string provisioning_server_url; + CdmCertificateType cert_type = kCertificateWidevine; + std::string cert_authority, cert, wrapped_key; + EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest( + cert_type, cert_authority, kDefaultCdmIdentifier, + &key_msg_, &provisioning_server_url)); + EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url()); + std::string response = + GetCertRequestResponse(g_config->provisioning_server_url()); + EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse( + kDefaultCdmIdentifier, response, &cert, + &wrapped_key)); + EXPECT_EQ(NO_ERROR, + decryptor_.OpenSession(g_key_system, &property_set, + kDefaultCdmIdentifier, NULL, + &session_id_)); + } else { + EXPECT_EQ(NO_ERROR, sts); + } + + decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier, + NULL, &session_id_); + GenerateKeyRequest(key_id, kLicenseTypeOffline, &property_set); + VerifyKeyRequestResponse(g_license_server, client_auth); + + CdmKeySetId key_set_id = key_set_id_; + EXPECT_FALSE(key_set_id_.empty()); + decryptor_.CloseSession(session_id_); + + session_id_.clear(); + key_set_id_.clear(); + decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier, + NULL, &session_id_); + EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id)); + decryptor_.CloseSession(session_id_); + + session_id_.clear(); + key_set_id_.clear(); + GenerateKeyRelease(key_set_id, &property_set, NULL); + + session_id_.clear(); + decryptor_.OpenSession(g_key_system, &property_set, kDefaultCdmIdentifier, + NULL, &session_id_); + EXPECT_EQ(wvcdm::GET_RELEASED_LICENSE_ERROR, + decryptor_.RestoreKey(session_id_, key_set_id)); + decryptor_.CloseSession(session_id_); + + session_id_.clear(); + key_set_id_.clear(); + GenerateKeyRelease(key_set_id, &property_set, NULL); + key_set_id_ = key_set_id; + VerifyKeyRequestResponse(g_license_server, client_auth); +} + TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) { Unprovision(); Provision(kLevelDefault);