Add initial support for key rotation through ce cdm interface.

Merge from Widevine repo of http://go/wvgerrit/42941

Bug: 72168544
Test: tested as part of http://go/ag/4674759
Change-Id: I1a2d0f49371e5b3edf1d9dff85b85593f981d1f5
This commit is contained in:
Fred Gylys-Colwell
2018-07-01 17:56:23 -07:00
parent d17199fb83
commit fc4186e4fd
12 changed files with 480 additions and 332 deletions

View File

@@ -127,6 +127,20 @@ class LicenseKeysTest : public ::testing::Test {
key->set_id(key_id);
}
virtual void AddEntitlementKey(
const KeyId& key_id, bool set_level = false,
KeyContainer::SecurityLevel level = KeyContainer::SW_SECURE_CRYPTO,
bool set_hdcp = false,
KeyContainer::OutputProtection::HDCP hdcp_value =
KeyContainer::OutputProtection::HDCP_NONE,
bool set_constraints = false,
std::vector<VideoResolutionConstraint>* constraints = NULL) {
AddContentKey(key_id, set_level, level, set_hdcp, hdcp_value,
set_constraints, constraints);
license_.mutable_key(license_.key_size() - 1)
->set_type(KeyContainer::ENTITLEMENT);
}
virtual void AddOperatorSessionKey(
const KeyId& key_id, bool set_perms = false,
KeyFlag encrypt = kKeyFlagNull, KeyFlag decrypt = kKeyFlagNull,
@@ -375,6 +389,26 @@ TEST_F(LicenseKeysTest, ContentKey) {
EXPECT_TRUE(license_keys_.IsContentKey(c_key));
}
TEST_F(LicenseKeysTest, EntitlementKey) {
const KeyId e_key = "entitlement_key";
const KeyId c_key = "content_key";
AddEntitlementKey(e_key);
EXPECT_FALSE(license_keys_.IsContentKey(e_key));
license_keys_.SetFromLicense(license_);
// TODO(juce, rfrias): For simplicity entitlement keys are indicated as
// content keys. It doesn't break anything, but CanDecryptContent returns true
// for and entitlement key id.
EXPECT_TRUE(license_keys_.IsContentKey(e_key));
std::vector<WidevinePsshData_EntitledKey> entitled_keys(1);
entitled_keys[0].set_entitlement_key_id(e_key);
entitled_keys[0].set_key_id(c_key);
EXPECT_FALSE(license_keys_.IsContentKey(c_key));
license_keys_.SetEntitledKeys(entitled_keys);
EXPECT_TRUE(license_keys_.IsContentKey(c_key));
}
TEST_F(LicenseKeysTest, OperatorSessionKey) {
const KeyId os_key = "op_sess_key";
EXPECT_FALSE(license_keys_.IsContentKey(os_key));
@@ -387,13 +421,17 @@ TEST_F(LicenseKeysTest, OperatorSessionKey) {
TEST_F(LicenseKeysTest, CanDecrypt) {
const KeyId os_key = "op_sess_key";
const KeyId c_key = "content_key";
const KeyId e_key = "entitlement_key";
EXPECT_FALSE(license_keys_.CanDecryptContent(c_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(os_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(e_key));
AddOperatorSessionKey(os_key);
AddContentKey(c_key);
AddEntitlementKey(e_key);
license_keys_.SetFromLicense(license_);
EXPECT_FALSE(license_keys_.CanDecryptContent(c_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(os_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(e_key));
bool new_usable_keys = false;
bool any_change = false;
any_change = license_keys_.ApplyStatusChange(kKeyStatusUsable,
@@ -409,15 +447,18 @@ TEST_F(LicenseKeysTest, CanDecrypt) {
EXPECT_FALSE(new_usable_keys);
EXPECT_FALSE(license_keys_.CanDecryptContent(c_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(os_key));
EXPECT_FALSE(license_keys_.CanDecryptContent(e_key));
}
TEST_F(LicenseKeysTest, AllowedUsageNull) {
const KeyId os_key = "op_sess_key";
const KeyId c_key = "content_key";
const KeyId sign_key = "signing_key";
const KeyId e_key = "entitlement_key";
AddOperatorSessionKey(os_key);
AddContentKey(c_key);
AddSigningKey(sign_key);
AddEntitlementKey(e_key);
license_keys_.SetFromLicense(license_);
CdmKeyAllowedUsage usage_1;
EXPECT_FALSE(license_keys_.GetAllowedUsage(sign_key, &usage_1));
@@ -431,6 +472,11 @@ TEST_F(LicenseKeysTest, AllowedUsageNull) {
EXPECT_TRUE(license_keys_.GetAllowedUsage(os_key, &usage_3));
ExpectAllowedUsageContent(usage_3, kContentClearFalse, kContentSecureFalse,
kKeySecurityLevelUnset);
CdmKeyAllowedUsage usage_4;
EXPECT_TRUE(license_keys_.GetAllowedUsage(os_key, &usage_4));
ExpectAllowedUsageContent(usage_4, kContentClearFalse, kContentSecureFalse,
kKeySecurityLevelUnset);
}
TEST_F(LicenseKeysTest, AllowedUsageContent) {

View File

@@ -38,6 +38,7 @@ const int64_t kHighDuration =
const char* kRenewalServerUrl =
"https://test.google.com/license/GetCencLicense";
const KeyId kKeyId = "357adc89f1673433c36c621f1b5c41ee";
const KeyId kEntitlementKeyId = "entitlementkeyid";
const KeyId kAnotherKeyId = "another_key_id";
const KeyId kSomeRandomKeyId = "some_random_key_id";
const KeyId kUnknownKeyId = "some_random_unknown_key_id";
@@ -157,6 +158,16 @@ class PolicyEngineTest : public ::testing::Test {
expected_has_new_usable_key));
}
void ExpectSessionKeysChange(CdmKeyStatus expected_key_status,
bool expected_has_new_usable_key,
KeyId expected_keyid) {
EXPECT_CALL(mock_event_listener_,
OnSessionKeysChange(
kSessionId, UnorderedElementsAre(
Pair(expected_keyid, expected_key_status)),
expected_has_new_usable_key));
}
void ExpectSessionKeysChange(CdmKeyStatus expected_key1_status,
CdmKeyStatus expected_key2_status,
bool expected_has_new_usable_key) {
@@ -206,6 +217,73 @@ TEST_F(PolicyEngineTest, PlaybackSuccess_OfflineLicense) {
EXPECT_FALSE(policy_engine_->CanDecryptContent(kSomeRandomKeyId));
}
TEST_F(PolicyEngineTest, PlaybackSuccess_EntitlementLicense) {
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(kLicenseStartTime + 1))
.WillOnce(Return(kPlaybackStartTime))
.WillOnce(Return(kLicenseStartTime + 10));
ExpectSessionKeysChange(kKeyStatusUsable, true, kEntitlementKeyId);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kPlaybackStartTime + kPlaybackDuration));
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
.WillRepeatedly(
DoAll(SetArgPointee<0>(HDCP_NO_DIGITAL_OUTPUT),
Return(true)));
License::KeyContainer* key = license_.mutable_key(0);
key->set_type(License::KeyContainer::ENTITLEMENT);
key->set_id(kEntitlementKeyId);
policy_engine_->SetLicense(license_);
policy_engine_->BeginDecryption();
policy_engine_->OnTimerEvent();
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
std::vector<WidevinePsshData_EntitledKey> entitled_keys(1);
entitled_keys[0].set_entitlement_key_id(kEntitlementKeyId);
entitled_keys[0].set_key_id(kKeyId);
policy_engine_->SetEntitledLicenseKeys(entitled_keys);
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId));
EXPECT_FALSE(policy_engine_->CanDecryptContent(kSomeRandomKeyId));
}
TEST_F(PolicyEngineTest, PlaybackSuccess_EntitlementLicenseExpiration) {
EXPECT_CALL(*mock_clock_, GetCurrentTime())
.WillOnce(Return(kLicenseStartTime + 1))
.WillOnce(Return(kPlaybackStartTime))
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration + 10))
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration + 11));
ExpectSessionKeysChange(kKeyStatusUsable, true, kEntitlementKeyId);
ExpectSessionKeysChange(kKeyStatusExpired, false, kEntitlementKeyId);
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
EXPECT_CALL(mock_event_listener_,
OnExpirationUpdate(_, kPlaybackStartTime + kPlaybackDuration));
License::KeyContainer* key = license_.mutable_key(0);
key->set_type(License::KeyContainer::ENTITLEMENT);
key->set_id(kEntitlementKeyId);
policy_engine_->SetLicense(license_);
policy_engine_->BeginDecryption();
policy_engine_->OnTimerEvent();
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
std::vector<WidevinePsshData_EntitledKey> entitled_keys(1);
entitled_keys[0].set_entitlement_key_id(kEntitlementKeyId);
entitled_keys[0].set_key_id(kKeyId);
policy_engine_->SetEntitledLicenseKeys(entitled_keys);
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
policy_engine_->OnTimerEvent();
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
}
TEST_F(PolicyEngineTest, PlaybackSuccess_StreamingLicense) {
License_Policy* policy = license_.mutable_policy();
policy->set_license_duration_seconds(kLowDuration);