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/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/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/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 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/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."; 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: