diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 45b9eb2b..ac81ef36 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -59,7 +59,8 @@ class CryptoSession { const std::string& mac_key_iv, const std::string& mac_key, const std::vector& key_array, - const std::string& provider_session_token); + const std::string& provider_session_token, + const std::string& srm_requirement); virtual bool LoadCertificatePrivateKey(std::string& wrapped_key); virtual bool RefreshKeys(const std::string& message, const std::string& signature, int num_keys, @@ -107,6 +108,10 @@ class CryptoSession { virtual bool GetNumberOfOpenSessions(size_t* count); virtual bool GetMaxNumberOfSessions(size_t* max); + virtual bool GetSrmVersion(uint16_t* srm_version); + virtual bool IsSrmUpdateSupported(); + virtual bool LoadSrm(const std::string& srm); + virtual CdmResponseType GenericEncrypt(const std::string& in_buffer, const std::string& key_id, const std::string& iv, diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 5697f5a1..2185be1c 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -460,7 +460,8 @@ CdmResponseType CryptoSession::LoadKeys( const std::string& message, const std::string& signature, const std::string& mac_key_iv, const std::string& mac_key, const std::vector& keys, - const std::string& provider_session_token) { + const std::string& provider_session_token, + const std::string& srm_requirement) { LOGV("CryptoSession::LoadKeys: Lock"); AutoLock auto_lock(crypto_lock_); @@ -501,13 +502,15 @@ CdmResponseType CryptoSession::LoadKeys( pst = const_cast(msg) + GetOffset(message, provider_session_token); } + uint8_t* srm_req = NULL; + if (!srm_requirement.empty()) + srm_req = const_cast(msg) + GetOffset(message, srm_requirement); LOGV("LoadKeys: id=%ld", (uint32_t)oec_session_id_); OEMCryptoResult sts = OEMCrypto_LoadKeys( oec_session_id_, msg, message.size(), reinterpret_cast(signature.data()), signature.size(), enc_mac_key_iv, enc_mac_key, keys.size(), &load_keys[0], pst, - provider_session_token.length(), - NULL); // TODO(rfrias): http://b/28955520 + provider_session_token.length(), srm_req); if (OEMCrypto_SUCCESS == sts) { if (!provider_session_token.empty()) { @@ -1213,6 +1216,45 @@ bool CryptoSession::GetMaxNumberOfSessions(size_t* max) { return true; } +bool CryptoSession::GetSrmVersion(uint16_t* srm_version) { + LOGV("GetSrmVersion"); + if (!initialized_) return false; + if (srm_version == NULL) { + LOGE("CryptoSession::GetSrmVersion: |srm_version| cannot be NULL"); + return false; + } + + OEMCryptoResult status = OEMCrypto_GetCurrentSRMVersion(srm_version); + if (OEMCrypto_SUCCESS != status) { + LOGW("OEMCrypto_GetCurrentSRMVersion fails with %d", status); + return false; + } + return true; +} + +bool CryptoSession::IsSrmUpdateSupported() { + LOGV("IsSrmUpdateSupported"); + if (!initialized_) return false; + return OEMCrypto_IsSRMUpdateSupported(); +} + +bool CryptoSession::LoadSrm(const std::string& srm) { + LOGV("LoadSrm"); + if (!initialized_) return false; + if (srm.empty()) { + LOGE("CryptoSession::LoadSrm: |srm| cannot be empty"); + return false; + } + + OEMCryptoResult status = OEMCrypto_LoadSRM( + reinterpret_cast(srm.data()), srm.size()); + if (OEMCrypto_SUCCESS != status) { + LOGW("OEMCrypto_LoadSRM fails with %d", status); + return false; + } + return true; +} + CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer, const std::string& key_id, const std::string& iv, diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index 87e445dd..b95b86de 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -494,6 +494,8 @@ CdmResponseType CdmLicense::HandleKeyResponse( return NO_CONTENT_KEY; } + if (license.has_srm_update()) crypto_session_->LoadSrm(license.srm_update()); + if (license.id().type() == video_widevine::OFFLINE && license.policy().can_persist()) is_offline_ = true; @@ -511,7 +513,7 @@ CdmResponseType CdmLicense::HandleKeyResponse( CdmResponseType resp = crypto_session_->LoadKeys( signed_response.msg(), signed_response.signature(), mac_key_iv, mac_key, - key_array, provider_session_token_); + key_array, provider_session_token_, license.srm_requirement()); if (KEY_ADDED == resp) { loaded_keys_.clear(); @@ -949,11 +951,18 @@ CdmResponseType CdmLicense::PrepareClientId( } } + client_capabilities->set_can_update_srm( + crypto_session_->IsSrmUpdateSupported()); + uint16_t srm_version; + if (crypto_session_->GetSrmVersion(&srm_version)) + client_capabilities->set_srm_version(srm_version); + if (service_certificate_->IsRequired()) { if (!service_certificate_->IsAvailable()) { LOGE("CdmLicense::PrepareClientId: Service Certificate not staged"); return LICENSE_REQUEST_SERVICE_CERTIFICATE_GENERATION_ERROR; } + EncryptedClientIdentification* encrypted_client_id = license_request->mutable_encrypted_client_id(); CdmResponseType status; diff --git a/libwvdrmengine/cdm/core/src/license_protocol.proto b/libwvdrmengine/cdm/core/src/license_protocol.proto index bb76a90c..7525b1f7 100644 --- a/libwvdrmengine/cdm/core/src/license_protocol.proto +++ b/libwvdrmengine/cdm/core/src/license_protocol.proto @@ -214,9 +214,13 @@ message License { // 4cc code specifying the CENC protection scheme as defined in the CENC 3.0 // specification. Propagated from Widevine PSSH box. Optional. optional uint32 protection_scheme = 7; - // Minimum HDCP SRM version needed for using this key on content sent to - // HDCP enabled outputs. - optional uint32 min_hdcp_srm_version = 8; + // 8 byte verification field "HDCPDATA" followed by unsigned 32 bit minimum + // HDCP SRM version. Additional details can be found in + // Widevine Modular DRM Security Integration Guide for CENC. + optional bytes srm_requirement = 8; + // If present this contains a signed SRM file that should be installed + // on the client device. + optional bytes srm_update = 9; } enum ProtocolVersion { @@ -515,6 +519,11 @@ message ClientIdentification { // storing the generation number in secure memory. For Details, see: // Widevine Modular DRM Security Integration Guide for CENC optional bool anti_rollback_usage_table = 6 [default = false]; + // The client shall report |srm_version| if available. + optional uint32 srm_version = 7; + // A device may have SRM data, and report a version, but may not be capable + // of updating SRM data. + optional bool can_update_srm = 8 [default = false]; } // Type of factory-provisioned device root of trust. Optional.