From a6aab24d914773525a3254e636b1946e399e037c Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Tue, 17 Apr 2018 18:27:54 -0700 Subject: [PATCH 1/3] Update OS Version in Version Canary (This is a merge of http://go/wvgerrit/47990) This is a test-only change. Bug: 78117686 Test: VersionNumberTest.* Change-Id: I4f53358fd6eacd498ddd1df7324084d0d4ae67fe --- libwvdrmengine/cdm/test/request_license_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index bf0031d7..20ad5cb8 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -4505,7 +4505,7 @@ TEST(VersionNumberTest, VersionNumberChangeCanary) { char release_number[PROPERTY_VALUE_MAX]; ASSERT_GT(property_get("ro.build.version.release", release_number, "Unknown"), 0); - EXPECT_STREQ("P", release_number) + EXPECT_STREQ("9", release_number) << "The Android version number has changed. You need to update this test " "and also possibly update the Widevine version number in " "properties_android.cpp."; From 07bb4de0427047076ba54ce2b2dd4eb32759e840 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Fri, 13 Apr 2018 01:12:16 -0700 Subject: [PATCH 2/3] Prevent race conditions between decrypt and close session [ Merge of http://go/wvgerrit/47520 ] Bug: 73781703 Test: WV unit/integration tests, GTS GtsMediaTestCases tests and AUPT tests. Change-Id: I618ed8ca38855aecdb31e829a7f4041cbd505a02 --- libwvdrmengine/cdm/core/include/cdm_session.h | 5 ++++- libwvdrmengine/cdm/core/include/wv_cdm_types.h | 1 + libwvdrmengine/cdm/core/src/cdm_session.cpp | 11 ++++++++++- libwvdrmengine/cdm/core/test/test_printers.cpp | 2 ++ libwvdrmengine/include/mapErrors-inl.h | 1 + libwvdrmengine/include_hidl/mapErrors-inl.h | 1 + 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index 113c9e96..854f459d 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -37,7 +37,7 @@ class CdmSession { CdmSession(FileSystem* file_system, metrics::SessionMetrics* metrics); virtual ~CdmSession(); - void Close() { closed_ = true; } + void Close(); bool IsClosed() { return closed_; } // Initializes this instance of CdmSession with the given property set. @@ -263,6 +263,9 @@ class CdmSession { bool mock_license_parser_in_use_; bool mock_policy_engine_in_use_; + // Lock to avoid race conditions between Close() and Decrypt() + Lock close_lock_; + CORE_DISALLOW_COPY_AND_ASSIGN(CdmSession); }; diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index bead3941..19fc6310 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -333,6 +333,7 @@ enum CdmResponseType { GET_PROVISIONING_METHOD_ERROR = 289, SESSION_NOT_FOUND_17 = 290, SESSION_NOT_FOUND_18 = 291, + SESSION_CLOSED_1 = 292, }; enum CdmKeyStatus { diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index f66ae08d..26267110 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -66,6 +66,11 @@ CdmSession::~CdmSession() { } } +void CdmSession::Close() { + AutoLock lock(close_lock_); + closed_ = true; +} + CdmResponseType CdmSession::Init( CdmClientPropertySet* cdm_client_property_set) { return Init(cdm_client_property_set, NULL, NULL); @@ -567,10 +572,14 @@ CdmResponseType CdmSession::QueryOemCryptoSessionId( // Decrypt() - Accept encrypted buffer and return decrypted data. CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) { if (!initialized_) { - LOGE("CdmSession::Decrypt: not initialized"); return NOT_INITIALIZED_ERROR; } + AutoLock lock(close_lock_); + if (IsClosed()) { + return SESSION_CLOSED_1; + } + // Playback may not begin until either the start time passes or the license // is updated, so we treat this Decrypt call as invalid. if (params.is_encrypted) { diff --git a/libwvdrmengine/cdm/core/test/test_printers.cpp b/libwvdrmengine/cdm/core/test/test_printers.cpp index 475c5f89..0dc40bf6 100644 --- a/libwvdrmengine/cdm/core/test/test_printers.cpp +++ b/libwvdrmengine/cdm/core/test/test_printers.cpp @@ -599,6 +599,8 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) { break; case SESSION_NOT_FOUND_18: *os << "SESSION_NOT_FOUND_18"; break; + case SESSION_CLOSED_1: *os << "SESSION_CLOSED_1"; + break; default: *os << "Unknown CdmResponseType"; break; diff --git a/libwvdrmengine/include/mapErrors-inl.h b/libwvdrmengine/include/mapErrors-inl.h index 029c11d9..8ebc454a 100644 --- a/libwvdrmengine/include/mapErrors-inl.h +++ b/libwvdrmengine/include/mapErrors-inl.h @@ -230,6 +230,7 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { case wvcdm::SESSION_NOT_FOUND_10: case wvcdm::SESSION_NOT_FOUND_17: case wvcdm::SESSION_NOT_FOUND_18: + case wvcdm::SESSION_CLOSED_1: return android::ERROR_DRM_SESSION_NOT_OPENED; case wvcdm::SESSION_KEYS_NOT_FOUND: return kSessionKeysNotFound; diff --git a/libwvdrmengine/include_hidl/mapErrors-inl.h b/libwvdrmengine/include_hidl/mapErrors-inl.h index 1637e626..18503efb 100644 --- a/libwvdrmengine/include_hidl/mapErrors-inl.h +++ b/libwvdrmengine/include_hidl/mapErrors-inl.h @@ -58,6 +58,7 @@ static Status mapCdmResponseType(wvcdm::CdmResponseType res) { case wvcdm::SESSION_NOT_FOUND_10: case wvcdm::SESSION_NOT_FOUND_17: case wvcdm::SESSION_NOT_FOUND_18: + case wvcdm::SESSION_CLOSED_1: return Status::ERROR_DRM_SESSION_NOT_OPENED; case wvcdm::DECRYPT_ERROR: From c171d024d950dbee30112f7424359a691fadafc6 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Wed, 4 Apr 2018 23:29:16 -0700 Subject: [PATCH 3/3] Enable encryption of client ID for provisioning [ Merge of http://go/wvgerrit/46760 ] This enables encryption of client ID for provisioning requests for devices with keyboxes as root of trust. Client ID will not be provided for those devices with OEM device certificates as root of trust. That will be addressed in b/78303730. Bug: 77607585 Test: WV unit/integration tests. Tests with L3 using OEM certs Change-Id: Id9bd697aa049bd5659ab80714e141dbc50408f6a --- .../core/include/certificate_provisioning.h | 3 + .../cdm/core/src/certificate_provisioning.cpp | 73 ++++++++++++++----- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/certificate_provisioning.h b/libwvdrmengine/cdm/core/include/certificate_provisioning.h index 4a825dc8..edf8a737 100644 --- a/libwvdrmengine/cdm/core/include/certificate_provisioning.h +++ b/libwvdrmengine/cdm/core/include/certificate_provisioning.h @@ -52,6 +52,9 @@ class CertificateProvisioning { video_widevine::SignedProvisioningMessage::ProtocolVersion GetProtocolVersion(); + bool GetProvisioningTokenType( + video_widevine::ClientIdentification::TokenType* token_type); + CryptoSession crypto_session_; CdmCertificateType cert_type_; scoped_ptr service_certificate_; diff --git a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp index 7b5387d8..cc9ac0d1 100644 --- a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp +++ b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp @@ -192,32 +192,51 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest( // Prepare device provisioning request. ProvisioningRequest provisioning_request; + video_widevine::ClientIdentification::TokenType token_type; + if (!GetProvisioningTokenType(&token_type)) { + LOGE("GetProvisioningRequest: failure getting provisioning token type"); + return CLIENT_IDENTIFICATION_TOKEN_ERROR_1; + } + wvcdm::ClientIdentification id; status = id.Init(&crypto_session_); if (status != NO_ERROR) return status; video_widevine::ClientIdentification* client_id = provisioning_request.mutable_client_id(); - CdmAppParameterMap app_parameter; - status = id.Prepare(app_parameter, client_id); - if (status != NO_ERROR) return status; - if (!service_certificate_->has_certificate()) { - LOGE("CertificateProvisioning::GetProvisioningRequest: Service Certificate " - "not staged"); - return CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE; + if (token_type == video_widevine::ClientIdentification::KEYBOX) { + CdmAppParameterMap app_parameter; + status = id.Prepare(app_parameter, client_id); + if (status != NO_ERROR) return status; + + if (!service_certificate_->has_certificate()) { + LOGE("CertificateProvisioning::GetProvisioningRequest: Service " + "Certificate not staged"); + return CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE; + } + + // Encrypt client identification + EncryptedClientIdentification* encrypted_client_id = + provisioning_request.mutable_encrypted_client_id(); + status = service_certificate_->EncryptClientId(&crypto_session_, client_id, + encrypted_client_id); + provisioning_request.clear_client_id(); + } else { + // TODO(rfrias,juce,b/78303730) provide encrypted client identification + // for devices whose root of trust is OEM_DEVICE_CERTIFICATES. + // Prerequisite is that apps need to transition to sending the + // provisioning request in the HTTP POST body. + client_id->set_type(token_type); + + std::string token; + if (!crypto_session_.GetProvisioningToken(&token)) { + LOGE("GetProvisioningRequest: failure getting provisioning token"); + return CLIENT_IDENTIFICATION_TOKEN_ERROR_2; + } + client_id->set_token(token); } - // TODO(rfrias): Uncomment when b/69427217 is addressed - /* - EncryptedClientIdentification* encrypted_client_id = - provisioning_request->mutable_encrypted_client_id(); - CdmResponseType status = - service_certificate_->EncryptClientId(&crypto_session_, client_id, - encrypted_client_id); - provisioning_request->clear_client_id(); - */ - uint32_t nonce; if (!crypto_session_.GenerateNonce(&nonce)) { LOGE("GetProvisioningRequest: fails to generate a nonce"); @@ -405,4 +424,24 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse( return NO_ERROR; } +bool CertificateProvisioning::GetProvisioningTokenType( + video_widevine::ClientIdentification::TokenType* token_type) { + CdmClientTokenType token = crypto_session_.GetPreProvisionTokenType(); + switch (token) { + case kClientTokenKeybox: + *token_type = video_widevine::ClientIdentification::KEYBOX; + return true; + case kClientTokenOemCert: + *token_type = + video_widevine::ClientIdentification::OEM_DEVICE_CERTIFICATE; + return true; + case kClientTokenDrmCert: + default: + // shouldn't happen + LOGE("CertificateProvisioning::GetProvisioningTokenType: unexpected " + "provisioning type: %d", token); + return false; + } +} + } // namespace wvcdm