Merge "Key Status should reflect key container security level" into qt-dev
This commit is contained in:
@@ -635,8 +635,7 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
|
||||
return INSUFFICIENT_OUTPUT_PROTECTION;
|
||||
return NEED_KEY;
|
||||
}
|
||||
if (!policy_engine_->CanUseKeyForSecurityLevel(*params.key_id,
|
||||
security_level_)) {
|
||||
if (!policy_engine_->CanUseKeyForSecurityLevel(*params.key_id)) {
|
||||
return KEY_PROHIBITED_FOR_SECURITY_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +152,16 @@ bool LicenseKeys::MeetsConstraints(const KeyId& key_id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool LicenseKeys::MeetsSecurityLevelConstraints(const KeyId& key_id) {
|
||||
if (key_statuses_.count(key_id) > 0) {
|
||||
return key_statuses_[key_id]->MeetsSecurityLevelConstraints();
|
||||
} else {
|
||||
// If a Key ID is unknown to us, we don't know of any constraints for it,
|
||||
// so never block decryption.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void LicenseKeys::ApplyConstraints(
|
||||
uint32_t new_resolution, CryptoSession::HdcpCapability new_hdcp_level) {
|
||||
for (LicenseKeyStatusIterator i = key_statuses_.begin();
|
||||
@@ -168,7 +178,7 @@ void LicenseKeys::SetFromLicense(const video_widevine::License& license) {
|
||||
key.type() == KeyContainer::OPERATOR_SESSION ||
|
||||
key.type() == KeyContainer::ENTITLEMENT)) {
|
||||
const KeyId& key_id = key.id();
|
||||
key_statuses_[key_id] = new LicenseKeyStatus(key);
|
||||
key_statuses_[key_id] = new LicenseKeyStatus(key, security_level_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,23 +200,26 @@ void LicenseKeys::SetEntitledKeys(
|
||||
}
|
||||
}
|
||||
|
||||
LicenseKeyStatus::LicenseKeyStatus(const KeyContainer& key)
|
||||
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) {
|
||||
allowed_usage_.Clear();
|
||||
constraints_.Clear();
|
||||
|
||||
if (key.type() == KeyContainer::CONTENT ||
|
||||
key.type() == KeyContainer::ENTITLEMENT) {
|
||||
ParseContentKey(key);
|
||||
ParseContentKey(key, security_level);
|
||||
} else if (key.type() == KeyContainer::OPERATOR_SESSION) {
|
||||
ParseOperatorSessionKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
void LicenseKeyStatus::ParseContentKey(const KeyContainer& key) {
|
||||
void LicenseKeyStatus::ParseContentKey(const KeyContainer& key,
|
||||
CdmSecurityLevel security_level) {
|
||||
is_content_key_ = true;
|
||||
if (key.has_level() && ((key.level() == KeyContainer::HW_SECURE_DECODE) ||
|
||||
(key.level() == KeyContainer::HW_SECURE_ALL))) {
|
||||
@@ -238,8 +251,34 @@ void LicenseKeyStatus::ParseContentKey(const KeyContainer& key) {
|
||||
allowed_usage_.key_security_level_ = kKeySecurityLevelUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (security_level) {
|
||||
case kSecurityLevelL1:
|
||||
meets_security_level_constraints_ = true;
|
||||
break;
|
||||
case kSecurityLevelL2:
|
||||
case kSecurityLevelL3:
|
||||
switch (key.level()) {
|
||||
case KeyContainer::SW_SECURE_CRYPTO:
|
||||
case KeyContainer::SW_SECURE_DECODE:
|
||||
meets_security_level_constraints_ = true;
|
||||
break;
|
||||
case KeyContainer::HW_SECURE_CRYPTO:
|
||||
meets_security_level_constraints_ =
|
||||
security_level == kSecurityLevelL2;
|
||||
break;
|
||||
default:
|
||||
meets_security_level_constraints_ = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
meets_security_level_constraints_ = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
allowed_usage_.key_security_level_ = kKeySecurityLevelUnset;
|
||||
meets_security_level_constraints_ = true;
|
||||
}
|
||||
allowed_usage_.SetValid();
|
||||
|
||||
@@ -301,7 +340,7 @@ bool LicenseKeyStatus::ApplyStatusChange(CdmKeyStatus new_status,
|
||||
}
|
||||
CdmKeyStatus updated_status = new_status;
|
||||
if (updated_status == kKeyStatusUsable) {
|
||||
if (!MeetsConstraints()) {
|
||||
if (!MeetsConstraints() || !MeetsSecurityLevelConstraints()) {
|
||||
updated_status = kKeyStatusOutputNotAllowed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ PolicyEngine::PolicyEngine(CdmSessionId session_id,
|
||||
last_recorded_current_time_(0),
|
||||
session_id_(session_id),
|
||||
event_listener_(event_listener),
|
||||
license_keys_(new LicenseKeys),
|
||||
license_keys_(new LicenseKeys(crypto_session->GetSecurityLevel())),
|
||||
clock_(new Clock) {
|
||||
InitDevice(crypto_session);
|
||||
}
|
||||
@@ -311,30 +311,8 @@ CdmResponseType PolicyEngine::QueryKeyAllowedUsage(
|
||||
return KEY_NOT_FOUND_1;
|
||||
}
|
||||
|
||||
bool PolicyEngine::CanUseKeyForSecurityLevel(
|
||||
const KeyId& key_id,
|
||||
CdmSecurityLevel security_level) {
|
||||
|
||||
if (security_level == kSecurityLevelL1) return true;
|
||||
|
||||
CdmKeyAllowedUsage key_usage;
|
||||
CdmResponseType status = QueryKeyAllowedUsage(key_id, &key_usage);
|
||||
|
||||
if (status != NO_ERROR) return false;
|
||||
|
||||
// L1 has already been addressed so verify that L2/3 are allowed
|
||||
switch (key_usage.key_security_level_) {
|
||||
case kKeySecurityLevelUnset:
|
||||
return true;
|
||||
case kSoftwareSecureCrypto:
|
||||
case kSoftwareSecureDecode:
|
||||
return security_level == kSecurityLevelL2 ||
|
||||
security_level == kSecurityLevelL3;
|
||||
case kHardwareSecureCrypto:
|
||||
return security_level == kSecurityLevelL2;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
bool PolicyEngine::CanUseKeyForSecurityLevel(const KeyId& key_id) {
|
||||
return license_keys_->MeetsSecurityLevelConstraints(key_id);
|
||||
}
|
||||
|
||||
bool PolicyEngine::GetSecondsSinceStarted(int64_t* seconds_since_started) {
|
||||
@@ -525,4 +503,8 @@ int64_t PolicyEngine::GetCurrentTime() {
|
||||
|
||||
void PolicyEngine::set_clock(Clock* clock) { clock_.reset(clock); }
|
||||
|
||||
void PolicyEngine::SetSecurityLevelForTest(CdmSecurityLevel security_level) {
|
||||
license_keys_->SetSecurityLevelForTest(security_level);
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user