diff --git a/libwvdrmengine/cdm/core/include/cdm_engine.h b/libwvdrmengine/cdm/core/include/cdm_engine.h index 154d2dd8..50ad2246 100644 --- a/libwvdrmengine/cdm/core/include/cdm_engine.h +++ b/libwvdrmengine/cdm/core/include/cdm_engine.h @@ -415,8 +415,6 @@ class CdmEngine { void OnKeyReleaseEvent(const CdmKeySetId& key_set_id); - std::string MapHdcpVersion(CryptoSession::HdcpCapability version); - void CloseExpiredReleaseSessions(); // Returns "true" if |okp_provisioner_| should be checked. diff --git a/libwvdrmengine/cdm/core/include/license_key_status.h b/libwvdrmengine/cdm/core/include/license_key_status.h index db7b9525..d07cbffc 100644 --- a/libwvdrmengine/cdm/core/include/license_key_status.h +++ b/libwvdrmengine/cdm/core/include/license_key_status.h @@ -155,12 +155,12 @@ class LicenseKeyStatus { void SetConstraints(const ConstraintList& constraints); - bool is_content_key_; - CdmKeyStatus key_status_; - bool meets_constraints_; - bool meets_security_level_constraints_; + bool is_content_key_ = false; + CdmKeyStatus key_status_ = kKeyStatusInternalError; + bool meets_constraints_ = true; + bool meets_security_level_constraints_ = true; CdmKeyAllowedUsage allowed_usage_; - CryptoSession::HdcpCapability default_hdcp_level_; + CryptoSession::HdcpCapability default_hdcp_level_ = HDCP_NONE; ConstraintList constraints_; CORE_DISALLOW_COPY_AND_ASSIGN(LicenseKeyStatus); diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h index 1e40068a..800c55b1 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h @@ -142,6 +142,11 @@ static const std::string QUERY_VALUE_HDCP_V2_0 = "HDCP-2.0"; static const std::string QUERY_VALUE_HDCP_V2_1 = "HDCP-2.1"; static const std::string QUERY_VALUE_HDCP_V2_2 = "HDCP-2.2"; static const std::string QUERY_VALUE_HDCP_V2_3 = "HDCP-2.3"; +static const std::string QUERY_VALUE_HDCP_V1_0 = "HDCP-1.0"; +static const std::string QUERY_VALUE_HDCP_V1_1 = "HDCP-1.1"; +static const std::string QUERY_VALUE_HDCP_V1_2 = "HDCP-1.2"; +static const std::string QUERY_VALUE_HDCP_V1_3 = "HDCP-1.3"; +static const std::string QUERY_VALUE_HDCP_V1_4 = "HDCP-1.4"; static const std::string QUERY_VALUE_HDCP_LEVEL_UNKNOWN = "HDCP-LevelUnknown"; static const std::string QUERY_VALUE_DRM_CERTIFICATE = "DrmCertificate"; static const std::string QUERY_VALUE_KEYBOX = "Keybox"; diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 069a7842..1b554180 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -33,6 +33,37 @@ namespace wvcdm { namespace { const uint64_t kReleaseSessionTimeToLive = 60; // seconds const uint32_t kUpdateUsageInformationPeriod = 60; // seconds + +std::string MapHdcpVersion(CryptoSession::HdcpCapability version) { + switch (version) { + case HDCP_NONE: + return QUERY_VALUE_HDCP_NONE; + case HDCP_V1: + return QUERY_VALUE_HDCP_V1; + case HDCP_V2: + return QUERY_VALUE_HDCP_V2_0; + case HDCP_V2_1: + return QUERY_VALUE_HDCP_V2_1; + case HDCP_V2_2: + return QUERY_VALUE_HDCP_V2_2; + case HDCP_V2_3: + return QUERY_VALUE_HDCP_V2_3; + // V17 and forward. + case HDCP_V1_0: + return QUERY_VALUE_HDCP_V1_0; + case HDCP_V1_1: + return QUERY_VALUE_HDCP_V1_1; + case HDCP_V1_2: + return QUERY_VALUE_HDCP_V1_2; + case HDCP_V1_3: + return QUERY_VALUE_HDCP_V1_3; + case HDCP_V1_4: + return QUERY_VALUE_HDCP_V1_4; + case HDCP_NO_DIGITAL_OUTPUT: + return QUERY_VALUE_HDCP_NO_DIGITAL_OUTPUT; + } + return QUERY_VALUE_HDCP_LEVEL_UNKNOWN; +} } // namespace class UsagePropertySet : public CdmClientPropertySet { @@ -2190,27 +2221,6 @@ CdmResponseType CdmEngine::SetPlaybackId(const CdmSessionId& session_id, return CdmResponseType(NO_ERROR); } -std::string CdmEngine::MapHdcpVersion(CryptoSession::HdcpCapability version) { - switch (version) { - case HDCP_NONE: - return QUERY_VALUE_HDCP_NONE; - case HDCP_V1: - return QUERY_VALUE_HDCP_V1; - case HDCP_V2: - return QUERY_VALUE_HDCP_V2_0; - case HDCP_V2_1: - return QUERY_VALUE_HDCP_V2_1; - case HDCP_V2_2: - return QUERY_VALUE_HDCP_V2_2; - case HDCP_V2_3: - return QUERY_VALUE_HDCP_V2_3; - case HDCP_NO_DIGITAL_OUTPUT: - return QUERY_VALUE_HDCP_NO_DIGITAL_OUTPUT; - default: - return QUERY_VALUE_HDCP_LEVEL_UNKNOWN; - } -} - void CdmEngine::CloseExpiredReleaseSessions() { const int64_t current_time = clock_.GetCurrentTime(); std::set close_session_set; diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 7cb8e5dd..70775e88 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -2103,9 +2103,8 @@ CdmResponseType CryptoSession::GetHdcpCapabilities( RETURN_IF_NULL(current, PARAMETER_NULL); RETURN_IF_NULL(max, PARAMETER_NULL); - OEMCryptoResult status; - WithOecReadLock("GetHdcpCapabilities", [&] { - status = OEMCrypto_GetHDCPCapability(security_level, current, max); + const OEMCryptoResult status = WithOecReadLock("GetHdcpCapabilities", [&] { + return OEMCrypto_GetHDCPCapability(security_level, current, max); }); if (OEMCrypto_SUCCESS == status) { diff --git a/libwvdrmengine/cdm/core/src/license_key_status.cpp b/libwvdrmengine/cdm/core/src/license_key_status.cpp index a4fc365b..4e3bff28 100644 --- a/libwvdrmengine/cdm/core/src/license_key_status.cpp +++ b/libwvdrmengine/cdm/core/src/license_key_status.cpp @@ -9,6 +9,7 @@ #include "log.h" #include "wv_cdm_constants.h" +namespace wvcdm { namespace { // License protocol aliases using KeyContainer = ::video_widevine::License::KeyContainer; @@ -19,7 +20,7 @@ using ConstraintList = // Map the HDCP protection associated with a key in the license to // an equivalent OEMCrypto HDCP protection level -wvcdm::CryptoSession::HdcpCapability ProtobufHdcpToOemCryptoHdcp( +CryptoSession::HdcpCapability ProtobufHdcpToOemCryptoHdcp( const OutputProtection::HDCP& input) { switch (input) { case OutputProtection::HDCP_NONE: @@ -36,11 +37,46 @@ wvcdm::CryptoSession::HdcpCapability ProtobufHdcpToOemCryptoHdcp( return HDCP_V2_3; case OutputProtection::HDCP_NO_DIGITAL_OUTPUT: return HDCP_NO_DIGITAL_OUTPUT; - default: - LOGE("Unknown HDCP Level, returning HDCP_NO_DIGITAL_OUTPUT: input = %d", - static_cast(input)); - return HDCP_NO_DIGITAL_OUTPUT; } + LOGW("Unknown HDCP Level, returning HDCP_NO_DIGITAL_OUTPUT: input = %d", + static_cast(input)); + return HDCP_NO_DIGITAL_OUTPUT; +} + +bool MeetsHdcpRequirements(const CryptoSession::HdcpCapability& required, + const CryptoSession::HdcpCapability& provided) { + if (provided == HDCP_NO_DIGITAL_OUTPUT) return true; // Always met. + switch (required) { + case HDCP_NONE: + return true; // Always met. + case HDCP_V1: // Means v1.x + // Can be any HDCP level other than NONE. + return provided != HDCP_NONE; + case HDCP_V2: // Means v2.0 + case HDCP_V2_1: + case HDCP_V2_2: + case HDCP_V2_3: + // Must be equal to or higher than the required v2.x version. + return provided >= required && provided <= HDCP_V2_3; + case HDCP_V1_0: + case HDCP_V1_1: + case HDCP_V1_2: + case HDCP_V1_3: + case HDCP_V1_4: + // Must be equal to or higher than the required v1.x version, + // be exactly v1.x, or within the 2.x range. OEMCrypto may + // behave differently. + return (provided == HDCP_V1) || + (provided >= required && provided <= HDCP_V1_4) || + (provided >= HDCP_V2 && provided <= HDCP_V2_3); + case HDCP_NO_DIGITAL_OUTPUT: + // If |provided| was HDCP_NO_DIGITAL_OUTPUT, it would have been caught + // at the top of this function. + return false; + } + LOGE("Unknown required HDCP level: required = %d, provided = %d", + static_cast(required), static_cast(provided)); + return false; } // Returns the constraint from a set of constraints that matches the @@ -63,8 +99,6 @@ VideoResolutionConstraint* GetConstraintForRes( } // namespace -namespace wvcdm { - bool LicenseKeys::IsContentKey(const std::string& key_id) { if (key_statuses_.count(key_id) > 0) { return key_statuses_[key_id]->IsContentKey(); @@ -199,12 +233,7 @@ void LicenseKeys::SetEntitledKeys( } LicenseKeyStatus::LicenseKeyStatus(const KeyContainer& key, - const CdmSecurityLevel security_level) - : is_content_key_(false), - key_status_(kKeyStatusInternalError), - meets_constraints_(true), - meets_security_level_constraints_(true), - default_hdcp_level_(HDCP_NONE) { + const CdmSecurityLevel security_level) { allowed_usage_.Clear(); constraints_.Clear(); @@ -370,15 +399,14 @@ void LicenseKeyStatus::ApplyConstraints( } } - CryptoSession::HdcpCapability desired_hdcp_level; + CryptoSession::HdcpCapability desired_hdcp_level = default_hdcp_level_; if (current_constraint && current_constraint->has_required_protection()) { desired_hdcp_level = ProtobufHdcpToOemCryptoHdcp( current_constraint->required_protection().hdcp()); - } else { - desired_hdcp_level = default_hdcp_level_; } - meets_constraints_ = (new_hdcp_level >= desired_hdcp_level); + meets_constraints_ = + MeetsHdcpRequirements(desired_hdcp_level, new_hdcp_level); } void LicenseKeyStatus::SetConstraints(const ConstraintList& constraints) { diff --git a/libwvdrmengine/cdm/core/src/policy_engine.cpp b/libwvdrmengine/cdm/core/src/policy_engine.cpp index 6306dbfc..bfde62a8 100644 --- a/libwvdrmengine/cdm/core/src/policy_engine.cpp +++ b/libwvdrmengine/cdm/core/src/policy_engine.cpp @@ -72,9 +72,9 @@ void PolicyEngine::CheckDeviceHdcpStatusOnTimer(int64_t current_time) { void PolicyEngine::CheckDeviceHdcpStatus() { if (!license_keys_->Empty()) { - CryptoSession::HdcpCapability current_hdcp_level; - CryptoSession::HdcpCapability ignored; - CdmResponseType status = + CryptoSession::HdcpCapability current_hdcp_level = HDCP_NONE; + CryptoSession::HdcpCapability ignored = HDCP_NONE; + const CdmResponseType status = crypto_session_->GetHdcpCapabilities(¤t_hdcp_level, &ignored); if (status != NO_ERROR) { current_hdcp_level = HDCP_NONE;