Source release v2.1.4-0-804 + third_party libs

Change-Id: I1db8582efba613fa8a2b91a9c2697c5dfb2a8abf
This commit is contained in:
Joey Parrish
2014-07-02 09:27:29 -07:00
parent 84acd5a15e
commit 334525c8a5
22 changed files with 1090 additions and 271 deletions

View File

@@ -2,6 +2,8 @@
#include "cdm_engine.h"
#include <stdlib.h>
#include <iostream>
#include <sstream>
@@ -18,22 +20,26 @@
namespace {
const uint32_t kUpdateUsageInformationPeriod = 60; // seconds
const size_t kMinNoncesPerSession = 4;
const size_t kUsageReportsPerRequest = 1;
} // unnamed namespace
namespace wvcdm {
bool CdmEngine::seeded_ = false;
CdmEngine::CdmEngine()
: cert_provisioning_requested_security_level_(kLevelDefault),
usage_session_(NULL),
last_usage_information_update_time(0) {
Properties::Init();
if (!seeded_) {
Clock clock;
srand(clock.GetCurrentTime());
seeded_ = true;
}
}
CdmEngine::~CdmEngine() {
if (NULL != usage_session_)
delete usage_session_;
CdmSessionMap::iterator i(sessions_.begin());
for (; i != sessions_.end(); ++i) {
delete i->second;
@@ -505,9 +511,7 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
}
CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
if (NULL == usage_session_) {
usage_session_ = new CdmSession(NULL);
}
usage_session_.reset(new CdmSession(NULL));
CdmResponseType status = usage_session_->Init();
if (NO_ERROR != status) {
@@ -533,35 +537,32 @@ CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
}
std::string server_url;
// rate limit secure stop messages based on minimum nonce
// table size per session
usage_info->resize(license_info.size() >= kMinNoncesPerSession - 1
? kMinNoncesPerSession - 1
: license_info.size());
for (size_t i = 0; i < usage_info->size(); ++i) {
status = usage_session_->RestoreUsageSession(license_info[i].first,
license_info[i].second);
if (KEY_ADDED != status) {
LOGE("CdmEngine::GetUsageInfo: restore usage session error: %ld",
status);
usage_info->clear();
return status;
}
status = usage_session_->GenerateReleaseRequest(&(*usage_info)[i],
&server_url);
if (KEY_MESSAGE != status) {
LOGE("CdmEngine::GetUsageInfo: generate release request error: %ld",
status);
usage_info->clear();
return status;
}
usage_info->resize(kUsageReportsPerRequest);
uint32_t index = rand() % license_info.size();
status = usage_session_->RestoreUsageSession(license_info[index].first,
license_info[index].second);
if (KEY_ADDED != status) {
LOGE("CdmEngine::GetUsageInfo: restore usage session (%d) error %ld",
index, status);
usage_info->clear();
return status;
}
status = usage_session_->GenerateReleaseRequest(&(*usage_info)[0], &server_url);
if (KEY_MESSAGE != status) {
LOGE("CdmEngine::GetUsageInfo: generate release request error: %ld",
status);
usage_info->clear();
return status;
}
return KEY_MESSAGE;
}
CdmResponseType CdmEngine::ReleaseUsageInfo(
const CdmUsageInfoReleaseMessage& message) {
if (NULL == usage_session_) {
if (NULL == usage_session_.get()) {
LOGE("CdmEngine::ReleaseUsageInfo: cdm session not initialized");
return UNKNOWN_ERROR;
}
@@ -569,9 +570,8 @@ CdmResponseType CdmEngine::ReleaseUsageInfo(
CdmResponseType status = usage_session_->ReleaseKey(message);
if (NO_ERROR != status) {
LOGE("CdmEngine::ReleaseUsageInfo: release key error: %ld", status);
return UNKNOWN_ERROR;
}
return NO_ERROR;
return status;
}
CdmResponseType CdmEngine::Decrypt(

View File

@@ -7,7 +7,6 @@
#include <stdlib.h>
#include "cdm_engine.h"
#include "clock.h"
#include "crypto_session.h"
#include "device_files.h"
#include "file_store.h"
@@ -25,16 +24,56 @@ namespace wvcdm {
typedef std::set<WvCdmEventListener*>::iterator CdmEventListenerIter;
CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set)
: session_id_(GenerateSessionId()),
crypto_session_(NULL),
license_received_(false),
reinitialize_session_(false),
is_offline_(false),
is_release_(false),
is_usage_update_needed_(false),
is_initial_decryption_(true),
is_certificate_loaded_(false) {
CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set) {
Create(new CdmLicense(), new CryptoSession(), new PolicyEngine(),
new DeviceFiles(), cdm_client_property_set);
}
CdmSession::CdmSession(
CdmLicense* license_parser,
CryptoSession* crypto_session,
PolicyEngine* policy_engine,
DeviceFiles* file_handle,
const CdmClientPropertySet* cdm_client_property_set) {
Create(license_parser, crypto_session, policy_engine, file_handle,
cdm_client_property_set);
}
void CdmSession::Create(
CdmLicense* license_parser,
CryptoSession* crypto_session,
PolicyEngine* policy_engine,
DeviceFiles* file_handle,
const CdmClientPropertySet* cdm_client_property_set) {
// Just return on failures. Failures will be signaled in Init.
if (NULL == license_parser) {
LOGE("CdmSession::Create: License parser not provided");
return;
}
if (NULL == crypto_session) {
LOGE("CdmSession::Create: Crypto session not provided");
return;
}
if (NULL == policy_engine) {
LOGE("CdmSession::Create: Policy engine not provided");
return;
}
if (NULL == file_handle) {
LOGE("CdmSession::Create: Device files not provided");
return;
}
initialized_ = false;
session_id_ = GenerateSessionId();
license_parser_.reset(license_parser);
crypto_session_.reset(crypto_session);
file_handle_.reset(file_handle);
policy_engine_.reset(policy_engine);
license_received_ = false;
is_offline_ = false;
is_release_ = false;
is_usage_update_needed_ = false;
is_initial_decryption_ = true;
security_level_ = crypto_session_.get()->GetSecurityLevel();
if (cdm_client_property_set) {
Properties::AddSessionPropertySet(session_id_, cdm_client_property_set);
}
@@ -43,29 +82,36 @@ CdmSession::CdmSession(const CdmClientPropertySet* cdm_client_property_set)
CdmSession::~CdmSession() { Properties::RemoveSessionPropertySet(session_id_); }
CdmResponseType CdmSession::Init() {
scoped_ptr<CryptoSession> session(new CryptoSession());
CdmResponseType sts = session->Open(GetRequestedSecurityLevel());
if (session_id_.empty()) {
LOGE("CdmSession::Init: Failed, session not properly constructed");
return UNKNOWN_ERROR;
}
if (initialized_) {
LOGE("CdmSession::Init: Failed due to previous initialization");
return UNKNOWN_ERROR;
}
CdmResponseType sts = crypto_session_->Open(GetRequestedSecurityLevel());
if (NO_ERROR != sts) return sts;
std::string token;
if (Properties::use_certificates_as_identification()) {
DeviceFiles handle;
if (!handle.Init(session.get()->GetSecurityLevel()) ||
!handle.RetrieveCertificate(&token, &wrapped_key_)) {
std::string wrapped_key;
if (!file_handle_->Init(security_level_) ||
!file_handle_->RetrieveCertificate(&token, &wrapped_key) ||
!crypto_session_->LoadCertificatePrivateKey(wrapped_key)) {
return NEED_PROVISIONING;
}
} else {
if (!session->GetToken(&token)) return UNKNOWN_ERROR;
if (!crypto_session_->GetToken(&token)) return UNKNOWN_ERROR;
}
if (!license_parser_.Init(token, session.get(), &policy_engine_))
if (!license_parser_->Init(token, crypto_session_.get(),
policy_engine_.get()))
return UNKNOWN_ERROR;
crypto_session_.reset(session.release());
license_received_ = false;
reinitialize_session_ = false;
is_initial_decryption_ = true;
initialized_ = true;
return NO_ERROR;
}
@@ -74,17 +120,17 @@ CdmResponseType CdmSession::RestoreOfflineSession(
key_set_id_ = key_set_id;
// Retrieve license information from persistent store
DeviceFiles handle;
if (!handle.Init(crypto_session_->GetSecurityLevel()))
if (!file_handle_->Reset(security_level_))
return UNKNOWN_ERROR;
DeviceFiles::LicenseState license_state;
if (!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_)) {
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_)) {
LOGE("CdmSession::Init failed to retrieve license. key set id = %s",
key_set_id.c_str());
return UNKNOWN_ERROR;
@@ -95,17 +141,8 @@ CdmResponseType CdmSession::RestoreOfflineSession(
return UNKNOWN_ERROR;
}
if (Properties::use_certificates_as_identification()) {
if (is_certificate_loaded_ ||
crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
is_certificate_loaded_ = true;
} else {
return NEED_PROVISIONING;
}
}
if (!license_parser_.RestoreOfflineLicense(key_request_, key_response_,
offline_key_renewal_response_)) {
if (!license_parser_->RestoreOfflineLicense(key_request_, key_response_,
offline_key_renewal_response_)) {
return UNKNOWN_ERROR;
}
@@ -121,16 +158,8 @@ CdmResponseType CdmSession::RestoreUsageSession(
key_request_ = key_request;
key_response_ = key_response;
if (Properties::use_certificates_as_identification()) {
if (is_certificate_loaded_ ||
crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
is_certificate_loaded_ = true;
} else {
return NEED_PROVISIONING;
}
}
if (!license_parser_.RestoreUsageLicense(key_request_, key_response_)) {
if (!license_parser_->RestoreUsageLicense(key_request_, key_response_)) {
return UNKNOWN_ERROR;
}
@@ -144,14 +173,6 @@ CdmResponseType CdmSession::GenerateKeyRequest(
const InitializationData& init_data, const CdmLicenseType license_type,
const CdmAppParameterMap& app_parameters, CdmKeyMessage* key_request,
std::string* server_url) {
if (reinitialize_session_) {
CdmResponseType sts = Init();
if (sts != NO_ERROR) {
LOGW("CdmSession::GenerateKeyRequest: Reinitialization failed");
return sts;
}
}
if (crypto_session_.get() == NULL) {
LOGW("CdmSession::GenerateKeyRequest: Invalid crypto session");
return UNKNOWN_ERROR;
@@ -182,24 +203,14 @@ CdmResponseType CdmSession::GenerateKeyRequest(
init_data.type().c_str());
return KEY_ERROR;
}
if (init_data.IsEmpty() && !license_parser_.HasInitData()) {
if (init_data.IsEmpty() && !license_parser_->HasInitData()) {
LOGW("CdmSession::GenerateKeyRequest: init data absent");
return KEY_ERROR;
}
if (Properties::use_certificates_as_identification()) {
if (is_certificate_loaded_ ||
crypto_session_->LoadCertificatePrivateKey(wrapped_key_)) {
is_certificate_loaded_ = true;
} else {
reinitialize_session_ = true;
return NEED_PROVISIONING;
}
}
if (!license_parser_.PrepareKeyRequest(init_data, license_type,
app_parameters, session_id_,
key_request, server_url)) {
if (!license_parser_->PrepareKeyRequest(init_data, license_type,
app_parameters, session_id_,
key_request, server_url)) {
return KEY_ERROR;
}
@@ -227,18 +238,19 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response,
}
if (is_release_) {
return ReleaseKey(key_response);
CdmResponseType sts = ReleaseKey(key_response);
return (NO_ERROR == sts) ? KEY_ADDED : sts;
} else if (license_received_) { // renewal
return RenewKey(key_response);
} else {
CdmResponseType sts = license_parser_.HandleKeyResponse(key_response);
CdmResponseType sts = license_parser_->HandleKeyResponse(key_response);
if (sts != KEY_ADDED) return sts;
license_received_ = true;
key_response_ = key_response;
if (is_offline_ || !license_parser_.provider_session_token().empty()) {
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
sts = StoreLicense();
if (sts != NO_ERROR) return sts;
}
@@ -281,7 +293,7 @@ CdmResponseType CdmSession::QueryStatus(CdmQueryMap* key_info) {
}
CdmResponseType CdmSession::QueryKeyStatus(CdmQueryMap* key_info) {
return policy_engine_.Query(key_info);
return policy_engine_->Query(key_info);
}
CdmResponseType CdmSession::QueryKeyControlInfo(CdmQueryMap* key_info) {
@@ -316,12 +328,12 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
if (NO_ERROR == status) {
if (is_initial_decryption_) {
policy_engine_.BeginDecryption();
policy_engine_->BeginDecryption();
is_initial_decryption_ = false;
}
if (!is_usage_update_needed_) {
is_usage_update_needed_ =
!license_parser_.provider_session_token().empty();
!license_parser_->provider_session_token().empty();
}
}
@@ -333,7 +345,8 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
// session keys.
CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyMessage* key_request,
std::string* server_url) {
if (!license_parser_.PrepareKeyUpdateRequest(true, key_request, server_url)) {
if (!license_parser_->PrepareKeyUpdateRequest(true, key_request,
server_url)) {
LOGE("CdmSession::GenerateRenewalRequest: ERROR on prepare");
return KEY_ERROR;
}
@@ -347,7 +360,7 @@ CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyMessage* key_request,
// RenewKey() - Accept renewal response and update key info.
CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
CdmResponseType sts =
license_parser_.HandleKeyUpdateResponse(true, key_response);
license_parser_->HandleKeyUpdateResponse(true, key_response);
if (sts != KEY_ADDED) return sts;
if (is_offline_) {
@@ -360,7 +373,7 @@ CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyMessage* key_request,
std::string* server_url) {
is_release_ = true;
if (!license_parser_.PrepareKeyUpdateRequest(false, key_request, server_url))
if (!license_parser_->PrepareKeyUpdateRequest(false, key_request, server_url))
return UNKNOWN_ERROR;
if (is_offline_) { // Mark license as being released
@@ -372,19 +385,19 @@ CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyMessage* key_request,
// ReleaseKey() - Accept release response and release license.
CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
CdmResponseType sts = license_parser_.HandleKeyUpdateResponse(false,
CdmResponseType sts = license_parser_->HandleKeyUpdateResponse(false,
key_response);
if (NO_ERROR != sts)
if (KEY_ADDED != sts)
return sts;
if (is_offline_ || !license_parser_.provider_session_token().empty()) {
if (is_offline_ || !license_parser_->provider_session_token().empty()) {
DeleteLicense();
}
return NO_ERROR;
}
bool CdmSession::IsKeyLoaded(const KeyId& key_id) {
return license_parser_.IsKeyLoaded(key_id);
return license_parser_->IsKeyLoaded(key_id);
}
CdmSessionId CdmSession::GenerateSessionId() {
@@ -401,8 +414,7 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) {
std::vector<uint8_t> random_data(
(kKeySetIdLength - sizeof(KEY_SET_ID_PREFIX)) / 2, 0);
DeviceFiles handle;
if (!handle.Init(crypto_session_->GetSecurityLevel()))
if (!file_handle_->Reset(security_level_))
return false;
while (key_set_id->empty()) {
@@ -412,7 +424,7 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) {
*key_set_id = KEY_SET_ID_PREFIX + b2a_hex(random_data);
// key set collision
if (handle.LicenseExists(*key_set_id)) {
if (file_handle_->LicenseExists(*key_set_id)) {
key_set_id->clear();
}
}
@@ -440,20 +452,20 @@ CdmResponseType CdmSession::StoreLicense() {
return NO_ERROR;
}
std::string provider_session_token = license_parser_.provider_session_token();
std::string provider_session_token =
license_parser_->provider_session_token();
if (provider_session_token.empty()) {
LOGE("CdmSession::StoreLicense: No provider session token and not offline");
return UNKNOWN_ERROR;
}
DeviceFiles handle;
if (!handle.Init(crypto_session_->GetSecurityLevel())) {
if (!file_handle_->Reset(security_level_)) {
LOGE("CdmSession::StoreLicense: Unable to initialize device files");
return UNKNOWN_ERROR;
}
if (!handle.StoreUsageInfo(provider_session_token, key_request_,
key_response_)) {
if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_,
key_response_)) {
LOGE("CdmSession::StoreLicense: Unable to store usage info");
return UNKNOWN_ERROR;
}
@@ -461,31 +473,29 @@ CdmResponseType CdmSession::StoreLicense() {
}
bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) {
DeviceFiles handle;
if (!handle.Init(crypto_session_->GetSecurityLevel()))
if (!file_handle_->Reset(security_level_))
return false;
return handle.StoreLicense(
return file_handle_->StoreLicense(
key_set_id_, state, offline_init_data_, key_request_,
key_response_, offline_key_renewal_request_,
offline_key_renewal_response_, offline_release_server_url_);
}
bool CdmSession::DeleteLicense() {
if (!is_offline_ && license_parser_.provider_session_token().empty())
if (!is_offline_ && license_parser_->provider_session_token().empty())
return false;
DeviceFiles handle;
if (!handle.Init(crypto_session_->GetSecurityLevel())) {
if (!file_handle_->Reset(security_level_)) {
LOGE("CdmSession::DeleteLicense: Unable to initialize device files");
return false;
}
if (is_offline_)
return handle.DeleteLicense(key_set_id_);
return file_handle_->DeleteLicense(key_set_id_);
else
return handle.DeleteUsageInfo(
license_parser_.provider_session_token());
return file_handle_->DeleteUsageInfo(
license_parser_->provider_session_token());
}
bool CdmSession::AttachEventListener(WvCdmEventListener* listener) {
@@ -501,7 +511,7 @@ void CdmSession::OnTimerEvent() {
bool event_occurred = false;
CdmEventType event;
policy_engine_.OnTimerEvent(&event_occurred, &event);
policy_engine_->OnTimerEvent(&event_occurred, &event);
if (event_occurred) {
for (CdmEventListenerIter iter = listeners_.begin();

View File

@@ -159,6 +159,25 @@ bool CryptoSession::GetDeviceUniqueId(std::string* device_id) {
return true;
}
bool CryptoSession::GetApiVersion(uint32_t* version) {
if (!version) {
LOGE("CryptoSession::GetApiVersion: No buffer passed to method.");
return false;
}
if (!initialized_) {
return false;
}
CdmSecurityLevel level = GetSecurityLevel();
SecurityLevel security_level = kLevelDefault;
if (kSecurityLevelL3 == level) security_level = kLevel3;
LOGV("CryptoSession::GetApiVersion: Lock");
AutoLock auto_lock(crypto_lock_);
*version = OEMCrypto_APIVersion(security_level);
return true;
}
bool CryptoSession::GetSystemId(uint32_t* system_id) {
if (!system_id) {
LOGE("CryptoSession::GetSystemId : No buffer passed to method.");

View File

@@ -55,8 +55,13 @@ bool Hash(const std::string& data, std::string* hash) {
namespace wvcdm {
DeviceFiles::DeviceFiles()
: file_(NULL), security_level_(kSecurityLevelUninitialized),
initialized_(false), test_file_(false) {
}
DeviceFiles::~DeviceFiles() {
if (!file_ && !test_file_) delete file_;
if (test_file_) file_.release();
}
bool DeviceFiles::Init(CdmSecurityLevel security_level) {
@@ -69,7 +74,7 @@ bool DeviceFiles::Init(CdmSecurityLevel security_level) {
LOGW("DeviceFiles::Init: Unsupported security level %d", security_level);
return false;
}
file_ = new File();
if (!test_file_) file_.reset(new File());
security_level_ = security_level;
initialized_ = true;
return true;
@@ -363,18 +368,13 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
return false;
}
UsageInfo* updated_info = file.mutable_usage_info();
UsageInfo info(*(const_cast<const UsageInfo*>(updated_info)));
updated_info->clear_sessions();
UsageInfo* usage_info = file.mutable_usage_info();
int index = 0;
bool found = false;
for (int i = 0; i < info.sessions_size(); ++i) {
if (info.sessions(i).token().compare(provider_session_token) == 0) {
for (; index < usage_info->sessions_size(); ++index) {
if (usage_info->sessions(index).token().compare(provider_session_token) == 0) {
found = true;
} else {
updated_info->add_sessions()->set_token(info.sessions(i).token());
updated_info->add_sessions()->set_license_request(
info.sessions(i).license_request());
updated_info->add_sessions()->set_license(info.sessions(i).license());
break;
}
}
@@ -384,6 +384,13 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& provider_session_token) {
return false;
}
google::protobuf::RepeatedPtrField<UsageInfo_ProviderSession>* sessions =
usage_info->mutable_sessions();
if (index < usage_info->sessions_size() - 1) {
sessions->SwapElements(index, usage_info->sessions_size() - 1);
}
sessions->RemoveLast();
file.SerializeToString(&serialized_file);
return StoreFile(kUsageInfoFileName, serialized_file);
}
@@ -452,7 +459,7 @@ bool DeviceFiles::RetrieveUsageInfo(std::vector<
bool DeviceFiles::StoreFile(const char* name,
const std::string& serialized_file) {
if (!file_) {
if (!file_.get()) {
LOGW("DeviceFiles::StoreFile: Invalid file handle");
return false;
}
@@ -512,7 +519,7 @@ bool DeviceFiles::StoreFile(const char* name,
}
bool DeviceFiles::RetrieveFile(const char* name, std::string* serialized_file) {
if (!file_) {
if (!file_.get()) {
LOGW("DeviceFiles::RetrieveFile: Invalid file handle");
return false;
}
@@ -661,8 +668,7 @@ std::string DeviceFiles::GetUsageInfoFileName() {
}
void DeviceFiles::SetTestFile(File* file) {
if (file_) delete file_;
file_ = file;
file_.reset(file);
test_file_ = true;
}

View File

@@ -4,6 +4,7 @@
#include <vector>
#include "clock.h"
#include "crypto_key.h"
#include "crypto_session.h"
#include "device_files.h"
@@ -22,6 +23,7 @@ std::string kDeviceNameKey = "device_name";
std::string kProductNameKey = "product_name";
std::string kBuildInfoKey = "build_info";
std::string kDeviceIdKey = "device_id";
std::string kOemCryptoApiVersion = "oemcrypto_api_version";
const unsigned char kServiceCertificateCAPublicKey[] = {
0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81,
0x00, 0xb4, 0xfe, 0x39, 0xc3, 0x65, 0x90, 0x03,
@@ -254,12 +256,17 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
client_info->set_name(kBuildInfoKey);
client_info->set_value(value);
}
if (session_->GetDeviceUniqueId(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kDeviceIdKey);
client_info->set_value(value);
}
uint32_t version = 0;
if (session_->GetApiVersion(&version)) {
client_info = client_id->add_client_info();
client_info->set_name(kOemCryptoApiVersion);
client_info->set_value(UintToString(version));
}
if (privacy_mode_enabled) {
EncryptedClientIdentification* encrypted_client_id =
@@ -353,12 +360,11 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
return false;
}
// The time field will be updated once the cdm wrapper
// has been updated to pass us in the time.
license_request.set_request_time(0);
license_request.set_type(LicenseRequest::NEW);
Clock clock;
license_request.set_request_time(clock.GetCurrentTime());
// Get/set the nonce. This value will be reflected in the Key Control Block
// of the license response.
uint32_t nonce;
@@ -424,6 +430,9 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
else
license_request.set_type(LicenseRequest::RELEASE);
Clock clock;
license_request.set_request_time(clock.GetCurrentTime());
LicenseRequest_ContentIdentification_ExistingLicense* current_license =
license_request.mutable_content_id()->mutable_license();
LicenseIdentification license_id = policy_engine_->license_id();
@@ -432,8 +441,9 @@ bool CdmLicense::PrepareKeyUpdateRequest(bool is_renewal,
if (!is_renewal) {
if (license_id.has_provider_session_token()) {
std::string usage_report;
if (!session_->GenerateUsageReport(license_id.provider_session_token(),
&usage_report)) {
if (NO_ERROR !=
session_->GenerateUsageReport(license_id.provider_session_token(),
&usage_report)) {
return false;
}
current_license->set_session_usage_table_entry(usage_report);
@@ -560,7 +570,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
return KEY_ERROR;
}
std::string provider_session_token;
if (license.id().has_provider_session_token())
provider_session_token_ = license.id().provider_session_token();
@@ -575,7 +584,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
mac_key_iv,
mac_key,
key_array,
provider_session_token);
provider_session_token_);
if (KEY_ADDED == resp) {
loaded_keys_.clear();
@@ -627,24 +636,23 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
return KEY_ERROR;
}
if (is_renewal) {
if (license.policy().has_renewal_server_url() &&
license.policy().renewal_server_url().size() > 0) {
server_url_ = license.policy().renewal_server_url();
}
}
else {
if (license.id().has_provider_session_token()) {
provider_session_token_ = license.id().provider_session_token();
session_->ReleaseUsageInformation(signed_response.msg(),
signed_response.signature(),
provider_session_token_);
}
}
policy_engine_->UpdateLicense(license);
if (!is_renewal) return KEY_ADDED;
if (!is_renewal) {
if (!license.id().has_provider_session_token()) return KEY_ADDED;
provider_session_token_ = license.id().provider_session_token();
CdmResponseType status =
session_->ReleaseUsageInformation(signed_response.msg(),
signed_response.signature(),
provider_session_token_);
return (NO_ERROR == status) ? KEY_ADDED : status;
}
if (license.policy().has_renewal_server_url() &&
license.policy().renewal_server_url().size() > 0) {
server_url_ = license.policy().renewal_server_url();
}
std::vector<CryptoKey> key_array = ExtractContentKeys(license);

View File

@@ -33,7 +33,6 @@ void PolicyEngine::Init(Clock* clock) {
license_state_ = kLicenseStateInitial;
can_decrypt_ = false;
license_start_time_ = 0;
license_received_time_ = 0;
playback_start_time_ = 0;
next_renewal_time_ = 0;
policy_max_duration_seconds_ = 0;
@@ -76,6 +75,14 @@ void PolicyEngine::OnTimerEvent(bool* event_occurred, CdmEventType* event) {
break;
}
case kLicenseStatePending: {
if (current_time >= license_start_time_) {
license_state_ = kLicenseStateCanPlay;
can_decrypt_ = true;
}
break;
}
case kLicenseStateInitial:
case kLicenseStateExpired: {
break;
@@ -115,13 +122,11 @@ void PolicyEngine::UpdateLicense(
policy_.MergeFrom(license.policy());
// some basic license validation
if (license_state_ == kLicenseStateInitial) {
// license start time needs to be present in the initial response
if (!license.has_license_start_time())
return;
}
else {
// if renewal, discard license if version has not been updated
// license start time needs to be specified in the initial response
if (!license.has_license_start_time()) return;
// if renewal, discard license if version has not been updated
if (license_state_ != kLicenseStateInitial) {
if (license.id().version() > license_id_.version())
license_id_.CopyFrom(license.id());
else
@@ -129,12 +134,8 @@ void PolicyEngine::UpdateLicense(
}
// Update time information
int64_t current_time = clock_->GetCurrentTime();
if (license.has_license_start_time())
license_start_time_ = license.license_start_time();
license_received_time_ = current_time;
next_renewal_time_ = current_time +
policy_.renewal_delay_seconds();
license_start_time_ = license.license_start_time();
next_renewal_time_ = license_start_time_ + policy_.renewal_delay_seconds();
// Calculate policy_max_duration_seconds_. policy_max_duration_seconds_
// will be set to the minimum of the following policies :
@@ -157,12 +158,18 @@ void PolicyEngine::UpdateLicense(
return;
}
int64_t current_time = clock_->GetCurrentTime();
if (IsLicenseDurationExpired(current_time)) return;
if (IsPlaybackDurationExpired(current_time)) return;
// Update state
license_state_ = kLicenseStateCanPlay;
can_decrypt_ = true;
if (current_time >= license_start_time_) {
license_state_ = kLicenseStateCanPlay;
can_decrypt_ = true;
} else {
license_state_ = kLicenseStatePending;
can_decrypt_ = false;
}
}
void PolicyEngine::BeginDecryption() {
@@ -178,6 +185,7 @@ void PolicyEngine::BeginDecryption() {
}
break;
case kLicenseStateInitial:
case kLicenseStatePending:
case kLicenseStateExpired:
default:
break;
@@ -221,7 +229,7 @@ void PolicyEngine::UpdateRenewalRequest(int64_t current_time) {
// will always return false if the value is 0.
bool PolicyEngine::IsLicenseDurationExpired(int64_t current_time) {
return policy_max_duration_seconds_ &&
license_received_time_ + policy_max_duration_seconds_ <=
license_start_time_ + policy_max_duration_seconds_ <=
current_time;
}
@@ -229,9 +237,12 @@ int64_t PolicyEngine::GetLicenseDurationRemaining(int64_t current_time) {
if (0 == policy_max_duration_seconds_) return LLONG_MAX;
int64_t remaining_time = policy_max_duration_seconds_
+ license_received_time_ - current_time;
+ license_start_time_ - current_time;
if (remaining_time < 0) remaining_time = 0;
if (remaining_time < 0)
remaining_time = 0;
else if (remaining_time > policy_max_duration_seconds_)
remaining_time = policy_max_duration_seconds_;
return remaining_time;
}
@@ -256,7 +267,7 @@ int64_t PolicyEngine::GetPlaybackDurationRemaining(int64_t current_time) {
bool PolicyEngine::IsRenewalDelayExpired(int64_t current_time) {
return policy_.can_renew() &&
(policy_.renewal_delay_seconds() > 0) &&
license_received_time_ + policy_.renewal_delay_seconds() <=
license_start_time_ + policy_.renewal_delay_seconds() <=
current_time;
}
@@ -264,7 +275,7 @@ bool PolicyEngine::IsRenewalRecoveryDurationExpired(
int64_t current_time) {
// NOTE: Renewal Recovery Duration is currently not used.
return (policy_.renewal_recovery_duration_seconds() > 0) &&
license_received_time_ + policy_.renewal_recovery_duration_seconds() <=
license_start_time_ + policy_.renewal_recovery_duration_seconds() <=
current_time;
}