Add License::Policy::play_start_grace_period_seconds
[ Merge of http://go/wvgerrit/22565 ] When using the grace period, the CDM will need to override the values given to use by the TEE (through OEMCrypto). Normally the first (and last) decrypt times are stored securely by the TEE. To avoid extra complexity in OEMCrypto, we will simply ignore the values given to us by the TEE when using this feature. However, the TEE will still enforce the (hard) license duration. So only the rental/playback durations will be affected by malicious editing of files. b/34211676 Test: Reran unittests including newly added tests. All tests other than some oemcrypto, request_license_test passed. Those tests failed with or without this CL. Change-Id: I6d7b5bfb669fd8603b474b68c2f7175b0c30901d
This commit is contained in:
@@ -53,6 +53,7 @@ class DeviceFiles {
|
||||
const std::string& release_server_url,
|
||||
int64_t playback_start_time,
|
||||
int64_t last_playback_time,
|
||||
int64_t grace_period_end_time,
|
||||
const CdmAppParameterMap& app_parameters);
|
||||
virtual bool RetrieveLicense(
|
||||
const std::string& key_set_id, LicenseState* state,
|
||||
@@ -60,7 +61,7 @@ class DeviceFiles {
|
||||
CdmKeyResponse* key_response, CdmKeyMessage* key_renewal_request,
|
||||
CdmKeyResponse* key_renewal_response, std::string* release_server_url,
|
||||
int64_t* playback_start_time, int64_t* last_playback_time,
|
||||
CdmAppParameterMap* app_parameters);
|
||||
int64_t* grace_period_end_time, CdmAppParameterMap* app_parameters);
|
||||
virtual bool DeleteLicense(const std::string& key_set_id);
|
||||
virtual bool DeleteAllFiles();
|
||||
virtual bool DeleteAllLicenses();
|
||||
|
||||
@@ -44,7 +44,8 @@ class CdmLicense {
|
||||
const CdmKeyMessage& license_request,
|
||||
const CdmKeyResponse& license_response,
|
||||
const CdmKeyResponse& license_renewal_response,
|
||||
int64_t playback_start_time, int64_t last_playback_time);
|
||||
int64_t playback_start_time, int64_t last_playback_time,
|
||||
int64_t grace_period_end_time);
|
||||
virtual bool RestoreLicenseForRelease(const CdmKeyMessage& license_request,
|
||||
const CdmKeyResponse& license_response);
|
||||
virtual bool HasInitData() { return stored_init_data_.get(); }
|
||||
|
||||
@@ -80,11 +80,19 @@ class PolicyEngine {
|
||||
// for offline save and restore
|
||||
int64_t GetPlaybackStartTime() { return playback_start_time_; }
|
||||
int64_t GetLastPlaybackTime() { return last_playback_time_; }
|
||||
int64_t GetGracePeriodEndTime() { return grace_period_end_time_; }
|
||||
void RestorePlaybackTimes(int64_t playback_start_time,
|
||||
int64_t last_playback_time);
|
||||
int64_t last_playback_time,
|
||||
int64_t grace_period_end_time);
|
||||
|
||||
bool IsLicenseForFuture() { return license_state_ == kLicenseStatePending; }
|
||||
bool HasPlaybackStarted() { return playback_start_time_ > 0; }
|
||||
bool HasPlaybackStarted(int64_t current_time) {
|
||||
if (playback_start_time_ == 0)
|
||||
return false;
|
||||
|
||||
const int64_t playback_time = current_time - playback_start_time_;
|
||||
return playback_time >= policy_.play_start_grace_period_seconds();
|
||||
}
|
||||
|
||||
bool HasLicenseOrPlaybackDurationExpired(int64_t current_time);
|
||||
int64_t GetLicenseOrPlaybackDurationRemaining();
|
||||
@@ -119,7 +127,8 @@ class PolicyEngine {
|
||||
int64_t GetRentalExpiryTime();
|
||||
// Gets the clock time that the license expires based on whether we have
|
||||
// started playing. This takes into account GetHardLicenseExpiryTime.
|
||||
int64_t GetExpiryTime(bool ignore_soft_enforce_playback_duration);
|
||||
int64_t GetExpiryTime(int64_t current_time,
|
||||
bool ignore_soft_enforce_playback_duration);
|
||||
|
||||
int64_t GetLicenseOrRentalDurationRemaining(int64_t current_time);
|
||||
int64_t GetPlaybackDurationRemaining(int64_t current_time);
|
||||
@@ -136,7 +145,7 @@ class PolicyEngine {
|
||||
|
||||
// Notifies updates in expiry time and fire OnExpirationUpdate event if
|
||||
// expiry time changes.
|
||||
void NotifyExpirationUpdate();
|
||||
void NotifyExpirationUpdate(int64_t current_time);
|
||||
|
||||
// set_clock() is for testing only. It alters ownership of the
|
||||
// passed-in pointer.
|
||||
@@ -160,6 +169,7 @@ class PolicyEngine {
|
||||
int64_t playback_start_time_;
|
||||
int64_t last_playback_time_;
|
||||
int64_t last_expiry_time_;
|
||||
int64_t grace_period_end_time_;
|
||||
bool last_expiry_time_set_;
|
||||
bool was_expired_on_load_;
|
||||
|
||||
|
||||
@@ -129,12 +129,14 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
DeviceFiles::LicenseState license_state;
|
||||
int64_t playback_start_time;
|
||||
int64_t last_playback_time;
|
||||
int64_t grace_period_end_time;
|
||||
|
||||
if (!file_handle_->RetrieveLicense(
|
||||
key_set_id, &license_state, &offline_init_data_, &key_request_,
|
||||
&key_response_, &offline_key_renewal_request_,
|
||||
&offline_key_renewal_response_, &offline_release_server_url_,
|
||||
&playback_start_time, &last_playback_time, &app_parameters_)) {
|
||||
&playback_start_time, &last_playback_time, &grace_period_end_time,
|
||||
&app_parameters_)) {
|
||||
LOGE("CdmSession::Init failed to retrieve license. key set id = %s",
|
||||
key_set_id.c_str());
|
||||
return GET_LICENSE_ERROR;
|
||||
@@ -156,7 +158,7 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
||||
} else {
|
||||
if (!license_parser_->RestoreOfflineLicense(
|
||||
key_request_, key_response_, offline_key_renewal_response_,
|
||||
playback_start_time, last_playback_time)) {
|
||||
playback_start_time, last_playback_time, grace_period_end_time)) {
|
||||
return RESTORE_OFFLINE_LICENSE_ERROR_2;
|
||||
}
|
||||
}
|
||||
@@ -568,7 +570,8 @@ bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) {
|
||||
key_set_id_, state, offline_init_data_, key_request_, key_response_,
|
||||
offline_key_renewal_request_, offline_key_renewal_response_,
|
||||
offline_release_server_url_, policy_engine_->GetPlaybackStartTime(),
|
||||
policy_engine_->GetLastPlaybackTime(), app_parameters_);
|
||||
policy_engine_->GetLastPlaybackTime(),
|
||||
policy_engine_->GetGracePeriodEndTime(), app_parameters_);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::ReleaseCrypto() {
|
||||
|
||||
@@ -168,7 +168,8 @@ bool DeviceFiles::StoreLicense(
|
||||
const CdmKeyMessage& license_renewal_request,
|
||||
const CdmKeyResponse& license_renewal,
|
||||
const std::string& release_server_url, int64_t playback_start_time,
|
||||
int64_t last_playback_time, const CdmAppParameterMap& app_parameters) {
|
||||
int64_t last_playback_time, int64_t grace_period_end_time,
|
||||
const CdmAppParameterMap& app_parameters) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::StoreLicense: not initialized");
|
||||
return false;
|
||||
@@ -201,6 +202,7 @@ bool DeviceFiles::StoreLicense(
|
||||
license->set_release_server_url(release_server_url);
|
||||
license->set_playback_start_time(playback_start_time);
|
||||
license->set_last_playback_time(last_playback_time);
|
||||
license->set_grace_period_end_time(grace_period_end_time);
|
||||
NameValue* app_params;
|
||||
for (CdmAppParameterMap::const_iterator iter = app_parameters.begin();
|
||||
iter != app_parameters.end(); ++iter) {
|
||||
@@ -221,7 +223,8 @@ bool DeviceFiles::RetrieveLicense(
|
||||
CdmKeyMessage* license_request, CdmKeyResponse* license_message,
|
||||
CdmKeyMessage* license_renewal_request, CdmKeyResponse* license_renewal,
|
||||
std::string* release_server_url, int64_t* playback_start_time,
|
||||
int64_t* last_playback_time, CdmAppParameterMap* app_parameters) {
|
||||
int64_t* last_playback_time, int64_t* grace_period_end_time,
|
||||
CdmAppParameterMap* app_parameters) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::RetrieveLicense: not initialized");
|
||||
return false;
|
||||
@@ -270,6 +273,7 @@ bool DeviceFiles::RetrieveLicense(
|
||||
*release_server_url = license.release_server_url();
|
||||
*playback_start_time = license.playback_start_time();
|
||||
*last_playback_time = license.last_playback_time();
|
||||
*grace_period_end_time = license.grace_period_end_time();
|
||||
for (int i = 0; i < license.app_parameters_size(); ++i) {
|
||||
(*app_parameters)[license.app_parameters(i).name()] =
|
||||
license.app_parameters(i).value();
|
||||
|
||||
@@ -39,6 +39,10 @@ message License {
|
||||
optional int64 playback_start_time = 8 [default = 0];
|
||||
optional int64 last_playback_time = 9 [default = 0];
|
||||
repeated NameValue app_parameters = 10;
|
||||
// This will be 0/missing if the grace period has not expired; otherwise it
|
||||
// contains the playback_start_time we should use as an override. This is
|
||||
// ignored if there is no grace period.
|
||||
optional int64 grace_period_end_time = 11 [default = 0];
|
||||
}
|
||||
|
||||
message UsageInfo {
|
||||
|
||||
@@ -674,7 +674,7 @@ bool CdmLicense::RestoreOfflineLicense(
|
||||
const CdmKeyMessage& license_request,
|
||||
const CdmKeyResponse& license_response,
|
||||
const CdmKeyResponse& license_renewal_response, int64_t playback_start_time,
|
||||
int64_t last_playback_time) {
|
||||
int64_t last_playback_time, int64_t grace_period_end_time) {
|
||||
if (license_request.empty() || license_response.empty()) {
|
||||
LOGE(
|
||||
"CdmLicense::RestoreOfflineLicense: key_request or response empty: "
|
||||
@@ -742,7 +742,8 @@ bool CdmLicense::RestoreOfflineLicense(
|
||||
}
|
||||
}
|
||||
|
||||
policy_engine_->RestorePlaybackTimes(playback_start_time, last_playback_time);
|
||||
policy_engine_->RestorePlaybackTimes(playback_start_time, last_playback_time,
|
||||
grace_period_end_time);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ PolicyEngine::PolicyEngine(CdmSessionId session_id,
|
||||
playback_start_time_(0),
|
||||
last_playback_time_(0),
|
||||
last_expiry_time_(0),
|
||||
grace_period_end_time_(0),
|
||||
last_expiry_time_set_(false),
|
||||
was_expired_on_load_(false),
|
||||
next_renewal_time_(0),
|
||||
@@ -78,6 +79,12 @@ void PolicyEngine::CheckDevice(int64_t current_time) {
|
||||
void PolicyEngine::OnTimerEvent() {
|
||||
int64_t current_time = clock_->GetCurrentTime();
|
||||
|
||||
// If we have passed the grace period, the expiration will update.
|
||||
if (grace_period_end_time_ == 0 && HasPlaybackStarted(current_time)) {
|
||||
grace_period_end_time_ = playback_start_time_;
|
||||
NotifyExpirationUpdate(current_time);
|
||||
}
|
||||
|
||||
// License expiration trumps all.
|
||||
if (HasLicenseOrPlaybackDurationExpired(current_time) &&
|
||||
license_state_ != kLicenseStateExpired) {
|
||||
@@ -195,7 +202,7 @@ void PolicyEngine::UpdateLicense(const License& license) {
|
||||
license_state_ = kLicenseStatePending;
|
||||
NotifyKeysChange(kKeyStatusPending);
|
||||
}
|
||||
NotifyExpirationUpdate();
|
||||
NotifyExpirationUpdate(current_time);
|
||||
}
|
||||
|
||||
void PolicyEngine::BeginDecryption() {
|
||||
@@ -206,11 +213,13 @@ void PolicyEngine::BeginDecryption() {
|
||||
case kLicenseStateWaitingLicenseUpdate:
|
||||
playback_start_time_ = clock_->GetCurrentTime();
|
||||
last_playback_time_ = playback_start_time_;
|
||||
if (policy_.play_start_grace_period_seconds() == 0)
|
||||
grace_period_end_time_ = playback_start_time_;
|
||||
|
||||
if (policy_.renew_with_usage()) {
|
||||
license_state_ = kLicenseStateNeedRenewal;
|
||||
}
|
||||
NotifyExpirationUpdate();
|
||||
NotifyExpirationUpdate(playback_start_time_);
|
||||
break;
|
||||
case kLicenseStateInitial:
|
||||
case kLicenseStatePending:
|
||||
@@ -290,26 +299,38 @@ bool PolicyEngine::GetSecondsSinceLastPlayed(
|
||||
}
|
||||
|
||||
int64_t PolicyEngine::GetLicenseOrPlaybackDurationRemaining() {
|
||||
int64_t current_time = clock_->GetCurrentTime();
|
||||
const int64_t current_time = clock_->GetCurrentTime();
|
||||
const int64_t expiry_time =
|
||||
GetExpiryTime(/* ignore_soft_enforce_playback_duration */ false);
|
||||
GetExpiryTime(current_time,
|
||||
/* ignore_soft_enforce_playback_duration */ false);
|
||||
if (expiry_time == NEVER_EXPIRES) return LLONG_MAX;
|
||||
if (expiry_time < current_time) return 0;
|
||||
return expiry_time - current_time;
|
||||
}
|
||||
|
||||
void PolicyEngine::RestorePlaybackTimes(int64_t playback_start_time,
|
||||
int64_t last_playback_time) {
|
||||
int64_t last_playback_time,
|
||||
int64_t grace_period_end_time) {
|
||||
playback_start_time_ = (playback_start_time > 0) ? playback_start_time : 0;
|
||||
last_playback_time_ = (last_playback_time > 0) ? last_playback_time : 0;
|
||||
grace_period_end_time_ = grace_period_end_time;
|
||||
|
||||
if (policy_.play_start_grace_period_seconds() != 0) {
|
||||
// If we are using grace period, we may need to override some of the values
|
||||
// given to us by OEMCrypto. |grace_period_end_time| will be 0 if the grace
|
||||
// period has not expired (effectively playback has not begun). Otherwise,
|
||||
// |grace_period_end_time| contains the playback start time we should use.
|
||||
playback_start_time_ = grace_period_end_time;
|
||||
}
|
||||
|
||||
const int64_t current_time = clock_->GetCurrentTime();
|
||||
const int64_t expiry_time =
|
||||
GetExpiryTime(/* ignore_soft_enforce_playback_duration */ true);
|
||||
GetExpiryTime(current_time,
|
||||
/* ignore_soft_enforce_playback_duration */ true);
|
||||
was_expired_on_load_ =
|
||||
expiry_time != NEVER_EXPIRES && expiry_time < current_time;
|
||||
|
||||
NotifyExpirationUpdate();
|
||||
NotifyExpirationUpdate(current_time);
|
||||
}
|
||||
|
||||
void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
|
||||
@@ -319,8 +340,9 @@ void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
|
||||
|
||||
bool PolicyEngine::HasLicenseOrPlaybackDurationExpired(int64_t current_time) {
|
||||
const int64_t expiry_time =
|
||||
GetExpiryTime(/* ignore_soft_enforce_playback_duration */ false);
|
||||
return (expiry_time != NEVER_EXPIRES) && expiry_time <= current_time;
|
||||
GetExpiryTime(current_time,
|
||||
/* ignore_soft_enforce_playback_duration */ false);
|
||||
return expiry_time != NEVER_EXPIRES && expiry_time <= current_time;
|
||||
}
|
||||
|
||||
// For the policy time fields checked in the following methods, a value of 0
|
||||
@@ -343,8 +365,9 @@ int64_t PolicyEngine::GetRentalExpiryTime() {
|
||||
}
|
||||
|
||||
int64_t PolicyEngine::GetExpiryTime(
|
||||
int64_t current_time,
|
||||
bool ignore_soft_enforce_playback_duration) {
|
||||
if (!HasPlaybackStarted())
|
||||
if (!HasPlaybackStarted(current_time))
|
||||
return GetRentalExpiryTime();
|
||||
|
||||
const int64_t hard_limit = GetHardLicenseExpiryTime();
|
||||
@@ -418,9 +441,10 @@ void PolicyEngine::NotifyKeysChange(CdmKeyStatus new_status) {
|
||||
}
|
||||
}
|
||||
|
||||
void PolicyEngine::NotifyExpirationUpdate() {
|
||||
void PolicyEngine::NotifyExpirationUpdate(int64_t current_time) {
|
||||
const int64_t expiry_time =
|
||||
GetExpiryTime(/* ignore_soft_enforce_playback_duration */ false);
|
||||
GetExpiryTime(current_time,
|
||||
/* ignore_soft_enforce_playback_duration */ false);
|
||||
if (!last_expiry_time_set_ || expiry_time != last_expiry_time_) {
|
||||
last_expiry_time_ = expiry_time;
|
||||
if (event_listener_)
|
||||
|
||||
@@ -118,6 +118,7 @@ struct LicenseInfo {
|
||||
std::string key_release_url;
|
||||
int64_t playback_start_time;
|
||||
int64_t last_playback_time;
|
||||
int64_t grace_period_end_time;
|
||||
std::string app_parameters;
|
||||
std::string file_data;
|
||||
};
|
||||
@@ -225,9 +226,9 @@ LicenseInfo license_test_data[] = {
|
||||
"0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF"
|
||||
"A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0"
|
||||
"BEA6CABACA1C2C"),
|
||||
"https://test.google.com/license/GetCencLicense", 0x0, 0x0, "",
|
||||
"https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "",
|
||||
a2bs_hex(
|
||||
"0AA8150802100122A1150801121408011210303132333435363738394142434445461"
|
||||
"0AAA150802100122A3150801121408011210303132333435363738394142434445461"
|
||||
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
|
||||
"7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302"
|
||||
"5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B"
|
||||
@@ -306,8 +307,8 @@ LicenseInfo license_test_data[] = {
|
||||
"106B63746C0000000000ECDCBE0000000020DBDFA68F051A20182F029E35047A3841F"
|
||||
"A176C74E5B387350E8D58DEA6878FF0BEA6CABACA1C2C3A2E68747470733A2F2F7465"
|
||||
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
|
||||
"365400048001220CD0599C2B85D9F2D573AC7893CE77CB5A10B326828BA8C89047505"
|
||||
"A8C9B606AC")},
|
||||
"365400048005800122066F4FFF1CB2C0F978149A9402F3E4FF8D49B19635E646A0678"
|
||||
"71AA08E7A8FDC3")},
|
||||
|
||||
// license 1
|
||||
{"ksidC8EAA2579A282EB0", DeviceFiles::kLicenseStateReleasing,
|
||||
@@ -406,9 +407,9 @@ LicenseInfo license_test_data[] = {
|
||||
"A68F051A20BDA6A56F7CBFD0942198F87C23A34AA5CBD64AFEB134277774"
|
||||
"CCF8E789D815DD"),
|
||||
"https://test.google.com/license/GetCencLicense", 0x12345678, 0x12348765,
|
||||
"Name1 Value1",
|
||||
0x0, "Name1 Value1",
|
||||
a2bs_hex(
|
||||
"0AC1150802100122BA150802121408011210303132333435363738394142434445461"
|
||||
"0AC3150802100122BC150802121408011210303132333435363738394142434445461"
|
||||
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
|
||||
"7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302"
|
||||
"5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B"
|
||||
@@ -487,8 +488,8 @@ LicenseInfo license_test_data[] = {
|
||||
"106B63746C00000000CA3A6A75000000002083E5A68F051A20BDA6A56F7CBFD094219"
|
||||
"8F87C23A34AA5CBD64AFEB134277774CCF8E789D815DD3A2E68747470733A2F2F7465"
|
||||
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
|
||||
"36540F8ACD1910148E58ED29101520F0A054E616D6531120656616C7565311220BE69"
|
||||
"AAB25B481BCAF57B741518D9F9DB8E3A7A6911D10C53D4F4649D78393C65")},
|
||||
"36540F8ACD1910148E58ED29101520F0A054E616D6531120656616C75653158001220"
|
||||
"9C0315FC1812C6A0E5936E36D04ECE2FA56AF4AB544ECDF3C9135D54B4A26167")},
|
||||
|
||||
// license 2
|
||||
{"ksidE8C37662C88DC673", DeviceFiles::kLicenseStateReleasing,
|
||||
@@ -587,9 +588,9 @@ LicenseInfo license_test_data[] = {
|
||||
"A68F051A2041EF0A9267D613D17AA90E1D1DA5BE091860E5E296D41D6D0F"
|
||||
"75E73660C279B3"),
|
||||
"https://test.google.com/license/GetCencLicense", 0x0123456789abcdef,
|
||||
0x123456789abfedc, "Name1 Value1 Name2 Param2",
|
||||
0x123456789abfedc, 0x0, "Name1 Value1 Name2 Param2",
|
||||
a2bs_hex(
|
||||
"0AE7150802100122E0150802121408011210303132333435363738394142434445461"
|
||||
"0AE9150802100122E2150802121408011210303132333435363738394142434445461"
|
||||
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
|
||||
"7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302"
|
||||
"5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B"
|
||||
@@ -669,9 +670,9 @@ LicenseInfo license_test_data[] = {
|
||||
"90E1D1DA5BE091860E5E296D41D6D0F75E73660C279B33A2E68747470733A2F2F7465"
|
||||
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
|
||||
"36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910152150A054E616D6531120C5661"
|
||||
"6C756531204E616D653252160A0C4E616D653220506172616D321206506172616D321"
|
||||
"2203653BA57F16FE28D66D9F7A76128B7AD7F33680815FF70A3684617DE1FBB0F9"
|
||||
"F")}};
|
||||
"6C756531204E616D653252160A0C4E616D653220506172616D321206506172616D325"
|
||||
"8001220616E6AC4AF6EB4F7147E98CF7302425E2390B293BBC01F9F8E89B49F653EA3"
|
||||
"45")}};
|
||||
|
||||
// Sample license data and related data for storage and use for offline
|
||||
// playback. The license data and URLs in this test are not real.
|
||||
@@ -774,9 +775,9 @@ LicenseInfo license_update_test_data[] = {
|
||||
"B68F051A2000351030900858FCFD6977B67803ADFD1280AA661E6B0BD30B"
|
||||
"08B2C467355129"),
|
||||
"https://test.google.com/license/GetCencLicense", 0x0123456789abcdef,
|
||||
0x123456789abfedc, "Name1 Value1 Name2 Value2 Name3 Value3",
|
||||
0x123456789abfedc, 0x0, "Name1 Value1 Name2 Value2 Name3 Value3",
|
||||
a2bs_hex(
|
||||
"0AB8150802100122B1150801121408011210303132333435363738394142434445461"
|
||||
"0ABA150802100122B3150801121408011210303132333435363738394142434445461"
|
||||
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
|
||||
"7A7D5076189EDFB68F05228E023082010A0282010100CC1715C81AD3F6F279C686F82"
|
||||
"6E6D7C8961EB13318367D06B4061BBC57E3C616A226A10F042CAD54D44C6484C725CD"
|
||||
@@ -855,13 +856,14 @@ LicenseInfo license_update_test_data[] = {
|
||||
"106B63746C0000000071FEF30B0000000020F4DFB68F051A2000351030900858FCFD6"
|
||||
"977B67803ADFD1280AA661E6B0BD30B08B2C4673551293A2E68747470733A2F2F7465"
|
||||
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
|
||||
"36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD191011220C7ACA00F6877DAAE2E8F50"
|
||||
"126C3222C2E584A50D08EFA75BC4FC091E7034E1DD")},
|
||||
"36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD191015800122051F15CDA5B9414919D"
|
||||
"B67769A781CC4F43138D314DAFFCBFBD620E53167E4AF2")},
|
||||
// license being released. all fields are identical except for license
|
||||
// state and hashed file data
|
||||
{"", DeviceFiles::kLicenseStateReleasing, "", "", "", "", "", "", 0, 0, "",
|
||||
{"", DeviceFiles::kLicenseStateReleasing, "", "", "", "", "", "", 0, 0, 0,
|
||||
"",
|
||||
a2bs_hex(
|
||||
"0AB8150802100122B1150802121408011210303132333435363738394142434445461"
|
||||
"0ABA150802100122B3150802121408011210303132333435363738394142434445461"
|
||||
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
|
||||
"7A7D5076189EDFB68F05228E023082010A0282010100CC1715C81AD3F6F279C686F82"
|
||||
"6E6D7C8961EB13318367D06B4061BBC57E3C616A226A10F042CAD54D44C6484C725CD"
|
||||
@@ -940,8 +942,8 @@ LicenseInfo license_update_test_data[] = {
|
||||
"106B63746C0000000071FEF30B0000000020F4DFB68F051A2000351030900858FCFD6"
|
||||
"977B67803ADFD1280AA661E6B0BD30B08B2C4673551293A2E68747470733A2F2F7465"
|
||||
"73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7"
|
||||
"36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910112203D8933A735A22FE27AA956"
|
||||
"802B597529E8FFCB91A5F3CBBB3CE0C38E4AF3DC88")}};
|
||||
"36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD191015800122093FDE0D42BC60D3932"
|
||||
"02E0D5A49775E08093BF01560EF72C298321E921716E24")}};
|
||||
|
||||
// Application parameters were added to the License message. This data
|
||||
// is used to verify that a License saved without application parameters can
|
||||
@@ -1043,7 +1045,7 @@ LicenseInfo license_app_parameters_backwards_compatibility_test_data = {
|
||||
"0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF"
|
||||
"A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0"
|
||||
"BEA6CABACA1C2C"),
|
||||
"https://test.google.com/license/GetCencLicense", 0x0, 0x0, "",
|
||||
"https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "",
|
||||
a2bs_hex(
|
||||
"0AA8150802100122A1150801121408011210303132333435363738394142434445461"
|
||||
"A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0"
|
||||
@@ -1489,7 +1491,7 @@ class DeviceFilesTest : public ::testing::Test {
|
||||
return sizeof(DeviceFiles::LicenseState) + data.pssh_data.size() +
|
||||
data.key_request.size() + data.key_response.size() +
|
||||
data.key_renewal_request.size() + data.key_renewal_response.size() +
|
||||
data.key_release_url.size() + 2 * sizeof(int64_t);
|
||||
data.key_release_url.size() + 3 * sizeof(int64_t);
|
||||
}
|
||||
|
||||
CdmAppParameterMap GetAppParameters(std::string str) {
|
||||
@@ -1747,7 +1749,8 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) {
|
||||
license_test_data[license_num].key_renewal_response,
|
||||
license_test_data[license_num].key_release_url,
|
||||
license_test_data[license_num].playback_start_time,
|
||||
license_test_data[license_num].last_playback_time, app_parameters));
|
||||
license_test_data[license_num].last_playback_time,
|
||||
license_test_data[license_num].grace_period_end_time, app_parameters));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(StoreLicense, DeviceFilesStoreTest, ::testing::Bool());
|
||||
@@ -1794,7 +1797,8 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
|
||||
license_test_data[i].key_renewal_response,
|
||||
license_test_data[i].key_release_url,
|
||||
license_test_data[i].playback_start_time,
|
||||
license_test_data[i].last_playback_time, app_parameters));
|
||||
license_test_data[i].last_playback_time,
|
||||
license_test_data[i].grace_period_end_time, app_parameters));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1832,6 +1836,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
|
||||
CdmKeyMessage key_renewal_request;
|
||||
CdmKeyResponse key_renewal_response;
|
||||
int64_t playback_start_time, last_playback_time;
|
||||
int64_t grace_period_end_time;
|
||||
std::string release_server_url;
|
||||
CdmAppParameterMap app_parameters;
|
||||
|
||||
@@ -1841,7 +1846,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
|
||||
license_test_data[i].key_set_id, &license_state, &pssh_data,
|
||||
&key_request, &key_response, &key_renewal_request,
|
||||
&key_renewal_response, &release_server_url, &playback_start_time,
|
||||
&last_playback_time, &app_parameters));
|
||||
&last_playback_time, &grace_period_end_time, &app_parameters));
|
||||
EXPECT_EQ(license_test_data[i].license_state, license_state);
|
||||
EXPECT_EQ(license_test_data[i].pssh_data, pssh_data);
|
||||
EXPECT_EQ(license_test_data[i].key_request, key_request);
|
||||
@@ -1850,6 +1855,8 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) {
|
||||
EXPECT_EQ(license_test_data[i].key_response, key_response);
|
||||
EXPECT_EQ(license_test_data[i].playback_start_time, playback_start_time);
|
||||
EXPECT_EQ(license_test_data[i].last_playback_time, last_playback_time);
|
||||
EXPECT_EQ(license_test_data[i].grace_period_end_time,
|
||||
grace_period_end_time);
|
||||
|
||||
std::map<std::string, std::string>::iterator itr;
|
||||
for (itr = app_parameters.begin(); itr != app_parameters.end(); ++itr) {
|
||||
@@ -1894,6 +1901,7 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
|
||||
CdmKeyMessage key_renewal_request;
|
||||
CdmKeyResponse key_renewal_response;
|
||||
int64_t playback_start_time, last_playback_time;
|
||||
int64_t grace_period_end_time;
|
||||
std::string release_server_url;
|
||||
CdmAppParameterMap app_parameters;
|
||||
|
||||
@@ -1901,7 +1909,7 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
|
||||
test_data->key_set_id, &license_state, &pssh_data, &key_request,
|
||||
&key_response, &key_renewal_request, &key_renewal_response,
|
||||
&release_server_url, &playback_start_time, &last_playback_time,
|
||||
&app_parameters));
|
||||
&grace_period_end_time, &app_parameters));
|
||||
EXPECT_EQ(test_data->license_state, license_state);
|
||||
EXPECT_EQ(test_data->pssh_data, pssh_data);
|
||||
EXPECT_EQ(test_data->key_request, key_request);
|
||||
@@ -1910,6 +1918,7 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) {
|
||||
EXPECT_EQ(test_data->key_response, key_response);
|
||||
EXPECT_EQ(test_data->playback_start_time, playback_start_time);
|
||||
EXPECT_EQ(test_data->last_playback_time, last_playback_time);
|
||||
EXPECT_EQ(test_data->grace_period_end_time, grace_period_end_time);
|
||||
EXPECT_EQ(0u, app_parameters.size());
|
||||
}
|
||||
|
||||
@@ -1945,6 +1954,7 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) {
|
||||
license_update_test_data[0].key_release_url,
|
||||
license_update_test_data[0].playback_start_time,
|
||||
license_update_test_data[0].last_playback_time,
|
||||
license_update_test_data[0].grace_period_end_time,
|
||||
GetAppParameters(license_test_data[0].app_parameters)));
|
||||
|
||||
EXPECT_TRUE(device_files.StoreLicense(
|
||||
@@ -1958,6 +1968,7 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) {
|
||||
license_update_test_data[0].key_release_url,
|
||||
license_update_test_data[0].playback_start_time,
|
||||
license_update_test_data[0].last_playback_time,
|
||||
license_update_test_data[0].grace_period_end_time,
|
||||
GetAppParameters(license_test_data[0].app_parameters)));
|
||||
}
|
||||
|
||||
@@ -1996,14 +2007,14 @@ TEST_F(DeviceFilesTest, DeleteLicense) {
|
||||
CdmKeyMessage key_renewal_request;
|
||||
CdmKeyResponse key_renewal_response;
|
||||
std::string release_server_url;
|
||||
int64_t playback_start_time, last_playback_time;
|
||||
int64_t playback_start_time, last_playback_time, grace_period_end_time;
|
||||
CdmAppParameterMap app_parameters;
|
||||
|
||||
EXPECT_TRUE(device_files.RetrieveLicense(
|
||||
license_test_data[0].key_set_id, &license_state, &pssh_data, &key_request,
|
||||
&key_response, &key_renewal_request, &key_renewal_response,
|
||||
&release_server_url, &playback_start_time, &last_playback_time,
|
||||
&app_parameters));
|
||||
&grace_period_end_time, &app_parameters));
|
||||
EXPECT_EQ(license_test_data[0].license_state, license_state);
|
||||
EXPECT_EQ(license_test_data[0].pssh_data, pssh_data);
|
||||
EXPECT_EQ(license_test_data[0].key_request, key_request);
|
||||
@@ -2012,6 +2023,7 @@ TEST_F(DeviceFilesTest, DeleteLicense) {
|
||||
EXPECT_EQ(license_test_data[0].key_response, key_response);
|
||||
EXPECT_EQ(license_test_data[0].playback_start_time, playback_start_time);
|
||||
EXPECT_EQ(license_test_data[0].last_playback_time, last_playback_time);
|
||||
EXPECT_EQ(license_test_data[0].grace_period_end_time, grace_period_end_time);
|
||||
std::map<std::string, std::string>::iterator itr;
|
||||
for (itr = app_parameters.begin(); itr != app_parameters.end(); ++itr) {
|
||||
EXPECT_NE(license_test_data[0].app_parameters.find(itr->first),
|
||||
|
||||
@@ -1093,7 +1093,8 @@ TEST_F(PolicyEngineTest, LicenseExpired_SoftEnforceLoadBeforeExpire) {
|
||||
OnExpirationUpdate(_, kLicenseStartTime + kLicenseDuration));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
policy_engine_->RestorePlaybackTimes(kPlaybackStartTime, kPlaybackStartTime);
|
||||
policy_engine_->RestorePlaybackTimes(kPlaybackStartTime, kPlaybackStartTime,
|
||||
kPlaybackStartTime);
|
||||
policy_engine_->OnTimerEvent();
|
||||
|
||||
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
@@ -1117,12 +1118,147 @@ TEST_F(PolicyEngineTest, LicenseExpired_SoftEnforceLoadAfterExpire) {
|
||||
ExpectSessionKeysChange(kKeyStatusExpired, false);
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
policy_engine_->RestorePlaybackTimes(kPlaybackStartTime, kPlaybackStartTime);
|
||||
policy_engine_->RestorePlaybackTimes(kPlaybackStartTime, kPlaybackStartTime,
|
||||
kPlaybackStartTime);
|
||||
policy_engine_->OnTimerEvent();
|
||||
|
||||
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, PlaybackOk_GracePeriod) {
|
||||
const int64_t kGracePeriod = 300; // 5 minutes
|
||||
License_Policy* policy = license_.mutable_policy();
|
||||
policy->set_play_start_grace_period_seconds(kGracePeriod);
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kPlaybackStartTime))
|
||||
.WillOnce(Return(kPlaybackStartTime + kGracePeriod - 5))
|
||||
.WillOnce(Return(kPlaybackStartTime + kGracePeriod + 5))
|
||||
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration - 5))
|
||||
.WillOnce(Return(kPlaybackStartTime + kPlaybackDuration + 5));
|
||||
|
||||
InSequence seq;
|
||||
ExpectSessionKeysChange(kKeyStatusUsable, true);
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
|
||||
EXPECT_CALL(check_, Call(1));
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnExpirationUpdate(_, kPlaybackStartTime + kPlaybackDuration));
|
||||
EXPECT_CALL(check_, Call(2));
|
||||
EXPECT_CALL(check_, Call(3));
|
||||
ExpectSessionKeysChange(kKeyStatusExpired, false);
|
||||
EXPECT_CALL(check_, Call(4));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
policy_engine_->BeginDecryption();
|
||||
|
||||
for (int i = 1; i <= 4; ++i) {
|
||||
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
policy_engine_->OnTimerEvent();
|
||||
check_.Call(i);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, PlaybackOk_GracePeriodWithLoad) {
|
||||
const int64_t kGracePeriod = 300; // 5 minutes
|
||||
const int64_t kNewPlaybackStartTime = kPlaybackStartTime + kPlaybackDuration;
|
||||
License_Policy* policy = license_.mutable_policy();
|
||||
policy->set_play_start_grace_period_seconds(kGracePeriod);
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kNewPlaybackStartTime))
|
||||
.WillOnce(Return(kNewPlaybackStartTime))
|
||||
.WillOnce(Return(kNewPlaybackStartTime + kGracePeriod - 5))
|
||||
.WillOnce(Return(kNewPlaybackStartTime + kGracePeriod + 5))
|
||||
.WillOnce(Return(kNewPlaybackStartTime + kPlaybackDuration - 5))
|
||||
.WillOnce(Return(kNewPlaybackStartTime + kPlaybackDuration + 5));
|
||||
|
||||
InSequence seq;
|
||||
ExpectSessionKeysChange(kKeyStatusUsable, true);
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
|
||||
EXPECT_CALL(check_, Call(1));
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnExpirationUpdate(_, kNewPlaybackStartTime + kPlaybackDuration));
|
||||
EXPECT_CALL(check_, Call(2));
|
||||
EXPECT_CALL(check_, Call(3));
|
||||
ExpectSessionKeysChange(kKeyStatusExpired, false);
|
||||
EXPECT_CALL(check_, Call(4));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
policy_engine_->RestorePlaybackTimes(kPlaybackStartTime, kPlaybackStartTime,
|
||||
0);
|
||||
policy_engine_->BeginDecryption();
|
||||
|
||||
for (int i = 1; i <= 4; ++i) {
|
||||
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
policy_engine_->OnTimerEvent();
|
||||
check_.Call(i);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, PlaybackOk_GracePeriodWithExpiredLoad) {
|
||||
const int64_t kGracePeriod = 300; // 5 minutes
|
||||
const int64_t kNewPlaybackStartTime =
|
||||
kPlaybackStartTime + kPlaybackDuration + 5;
|
||||
License_Policy* policy = license_.mutable_policy();
|
||||
policy->set_play_start_grace_period_seconds(kGracePeriod);
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kNewPlaybackStartTime))
|
||||
.WillOnce(Return(kNewPlaybackStartTime));
|
||||
|
||||
InSequence seq;
|
||||
ExpectSessionKeysChange(kKeyStatusUsable, true);
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnExpirationUpdate(_, kPlaybackStartTime + kPlaybackDuration));
|
||||
ExpectSessionKeysChange(kKeyStatusExpired, false);
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
policy_engine_->RestorePlaybackTimes(kPlaybackStartTime, kPlaybackStartTime,
|
||||
kPlaybackStartTime);
|
||||
|
||||
policy_engine_->OnTimerEvent();
|
||||
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTest, PlaybackOk_CanStoreGracePeriod) {
|
||||
const int64_t kGracePeriod = 300; // 5 minutes
|
||||
License_Policy* policy = license_.mutable_policy();
|
||||
policy->set_play_start_grace_period_seconds(kGracePeriod);
|
||||
|
||||
EXPECT_CALL(*mock_clock_, GetCurrentTime())
|
||||
.WillOnce(Return(kLicenseStartTime + 1))
|
||||
.WillOnce(Return(kPlaybackStartTime))
|
||||
.WillOnce(Return(kPlaybackStartTime + 50))
|
||||
.WillOnce(Return(kPlaybackStartTime + kGracePeriod + 2));
|
||||
|
||||
InSequence seq;
|
||||
ExpectSessionKeysChange(kKeyStatusUsable, true);
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnExpirationUpdate(_, kLicenseStartTime + kRentalDuration));
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnExpirationUpdate(_, kPlaybackStartTime + kPlaybackDuration));
|
||||
|
||||
policy_engine_->SetLicense(license_);
|
||||
policy_engine_->BeginDecryption();
|
||||
|
||||
policy_engine_->OnTimerEvent();
|
||||
EXPECT_EQ(0, policy_engine_->GetGracePeriodEndTime());
|
||||
|
||||
policy_engine_->OnTimerEvent();
|
||||
EXPECT_EQ(kPlaybackStartTime, policy_engine_->GetGracePeriodEndTime());
|
||||
}
|
||||
|
||||
class PolicyEngineKeyAllowedUsageTest : public PolicyEngineTest {
|
||||
protected:
|
||||
enum KeyFlag {
|
||||
|
||||
Reference in New Issue
Block a user