File util, generic crypto, and key query
This CL merges several CLs from the widevine repo: http://go/wvgerrit/18012 Add support for querying allowed usage for key. http://go/wvgerrit/17971 Add per-origin storage. http://go/wvgerrit/18152 Add OEMCrypto's generic crypto operations to CDM. http://go/wvgerrit/17911 QueryKeyControlInfo => QueryOemCryptoSessionId Note: numbering in wv_cdm_types.h was added in this CL and will be back ported to wvgerrit in a future CL. Change-Id: Idb9e9a67e94f62f25dc16c5307f75a08b3430b64
This commit is contained in:
@@ -19,8 +19,7 @@ namespace wvcdm {
|
||||
|
||||
Lock WvContentDecryptionModule::session_sharing_id_generation_lock_;
|
||||
|
||||
WvContentDecryptionModule::WvContentDecryptionModule()
|
||||
: cdm_engine_(new CdmEngine()) {}
|
||||
WvContentDecryptionModule::WvContentDecryptionModule() {}
|
||||
|
||||
WvContentDecryptionModule::~WvContentDecryptionModule() {
|
||||
DisablePolicyTimer(true);
|
||||
@@ -52,19 +51,31 @@ CdmResponseType WvContentDecryptionModule::OpenSession(
|
||||
property_set->set_session_sharing_id(GenerateSessionSharingId());
|
||||
}
|
||||
|
||||
return cdm_engine_->OpenSession(key_system, property_set, origin,
|
||||
event_listener, session_id);
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(origin);
|
||||
CdmResponseType sts = cdm_engine->OpenSession(key_system, property_set,
|
||||
event_listener, session_id);
|
||||
if (sts == NO_ERROR) {
|
||||
cdm_by_session_id_[*session_id] = cdm_engine;
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::CloseSession(
|
||||
const CdmSessionId& session_id) {
|
||||
CdmResponseType sts = cdm_engine_->CloseSession(session_id);
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
// TODO(rfrias): Avoid reusing the error codes from CdmEngine.
|
||||
if (!cdm_engine) return SESSION_NOT_FOUND_1;
|
||||
CdmResponseType sts = cdm_engine->CloseSession(session_id);
|
||||
if (sts == NO_ERROR) {
|
||||
cdm_by_session_id_.erase(session_id);
|
||||
}
|
||||
DisablePolicyTimer(false);
|
||||
return sts;
|
||||
}
|
||||
|
||||
bool WvContentDecryptionModule::IsOpenSession(const CdmSessionId& session_id) {
|
||||
return cdm_engine_->IsOpenSession(session_id);
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
return cdm_engine && cdm_engine->IsOpenSession(session_id);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GenerateKeyRequest(
|
||||
@@ -73,21 +84,24 @@ CdmResponseType WvContentDecryptionModule::GenerateKeyRequest(
|
||||
const CdmLicenseType license_type, CdmAppParameterMap& app_parameters,
|
||||
CdmClientPropertySet* property_set, const std::string& origin,
|
||||
CdmKeyRequest* key_request) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(origin);
|
||||
CdmResponseType sts;
|
||||
if (license_type == kLicenseTypeRelease) {
|
||||
sts = cdm_engine_->OpenKeySetSession(key_set_id, property_set, origin,
|
||||
NULL);
|
||||
sts = cdm_engine->OpenKeySetSession(key_set_id, property_set, NULL);
|
||||
if (sts != NO_ERROR) return sts;
|
||||
cdm_by_session_id_[key_set_id] = cdm_engine;
|
||||
}
|
||||
InitializationData initialization_data(init_data_type, init_data);
|
||||
sts = cdm_engine_->GenerateKeyRequest(
|
||||
sts = cdm_engine->GenerateKeyRequest(
|
||||
session_id, key_set_id, initialization_data, license_type, app_parameters,
|
||||
key_request);
|
||||
|
||||
switch(license_type) {
|
||||
case kLicenseTypeRelease:
|
||||
if (sts != KEY_MESSAGE)
|
||||
cdm_engine_->CloseKeySetSession(key_set_id);
|
||||
if (sts != KEY_MESSAGE) {
|
||||
cdm_engine->CloseKeySetSession(key_set_id);
|
||||
cdm_by_session_id_.erase(key_set_id);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (sts == KEY_MESSAGE)
|
||||
@@ -101,16 +115,23 @@ CdmResponseType WvContentDecryptionModule::AddKey(
|
||||
const CdmSessionId& session_id,
|
||||
const CdmKeyResponse& key_data,
|
||||
CdmKeySetId* key_set_id) {
|
||||
CdmResponseType sts = cdm_engine_->AddKey(session_id, key_data, key_set_id);
|
||||
if (sts == KEY_ADDED && session_id.empty()) // license type release
|
||||
cdm_engine_->CloseKeySetSession(*key_set_id);
|
||||
CdmEngine* cdm_engine = session_id.empty() ? GetCdmForSessionId(*key_set_id)
|
||||
: GetCdmForSessionId(session_id);
|
||||
if (!cdm_engine) return SESSION_NOT_FOUND_3;
|
||||
CdmResponseType sts = cdm_engine->AddKey(session_id, key_data, key_set_id);
|
||||
if (sts == KEY_ADDED && session_id.empty()) { // license type release
|
||||
cdm_engine->CloseKeySetSession(*key_set_id);
|
||||
cdm_by_session_id_.erase(*key_set_id);
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::RestoreKey(
|
||||
const CdmSessionId& session_id,
|
||||
const CdmKeySetId& key_set_id) {
|
||||
CdmResponseType sts = cdm_engine_->RestoreKey(session_id, key_set_id);
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
if (!cdm_engine) return SESSION_NOT_FOUND_4;
|
||||
CdmResponseType sts = cdm_engine->RestoreKey(session_id, key_set_id);
|
||||
if (sts == KEY_ADDED)
|
||||
EnablePolicyTimer();
|
||||
return sts;
|
||||
@@ -118,29 +139,38 @@ CdmResponseType WvContentDecryptionModule::RestoreKey(
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::RemoveKeys(
|
||||
const CdmSessionId& session_id) {
|
||||
return cdm_engine_->RemoveKeys(session_id);
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
if (!cdm_engine) return SESSION_NOT_FOUND_5;
|
||||
return cdm_engine->RemoveKeys(session_id);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::QueryStatus(
|
||||
SecurityLevel security_level,
|
||||
const std::string& key,
|
||||
std::string* value) {
|
||||
return cdm_engine_->QueryStatus(security_level, key, value);
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(EMPTY_ORIGIN);
|
||||
return cdm_engine->QueryStatus(security_level, key, value);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::QuerySessionStatus(
|
||||
const CdmSessionId& session_id, CdmQueryMap* key_info) {
|
||||
return cdm_engine_->QuerySessionStatus(session_id, key_info);
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
if (!cdm_engine) return SESSION_NOT_FOUND_8;
|
||||
return cdm_engine->QuerySessionStatus(session_id, key_info);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::QueryKeyStatus(
|
||||
const CdmSessionId& session_id, CdmQueryMap* key_info) {
|
||||
return cdm_engine_->QueryKeyStatus(session_id, key_info);
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
if (!cdm_engine) return SESSION_NOT_FOUND_9;
|
||||
return cdm_engine->QueryKeyStatus(session_id, key_info);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::QueryKeyControlInfo(
|
||||
const CdmSessionId& session_id, CdmQueryMap* key_info) {
|
||||
return cdm_engine_->QueryKeyControlInfo(session_id, key_info);
|
||||
CdmResponseType WvContentDecryptionModule::QueryOemCryptoSessionId(
|
||||
const CdmSessionId& session_id, CdmQueryMap* response) {
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
if (!cdm_engine) return SESSION_NOT_FOUND_10;
|
||||
return cdm_engine->QueryOemCryptoSessionId(session_id, response);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetProvisioningRequest(
|
||||
@@ -149,8 +179,9 @@ CdmResponseType WvContentDecryptionModule::GetProvisioningRequest(
|
||||
const std::string& origin,
|
||||
CdmProvisioningRequest* request,
|
||||
std::string* default_url) {
|
||||
return cdm_engine_->GetProvisioningRequest(cert_type, cert_authority, origin,
|
||||
request, default_url);
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(origin);
|
||||
return cdm_engine->GetProvisioningRequest(cert_type, cert_authority, request,
|
||||
default_url);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse(
|
||||
@@ -158,59 +189,70 @@ CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse(
|
||||
CdmProvisioningResponse& response,
|
||||
std::string* cert,
|
||||
std::string* wrapped_key) {
|
||||
return cdm_engine_->HandleProvisioningResponse(origin, response, cert,
|
||||
wrapped_key);
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(origin);
|
||||
return cdm_engine->HandleProvisioningResponse(response, cert, wrapped_key);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::Unprovision(
|
||||
CdmSecurityLevel level,
|
||||
const std::string& origin) {
|
||||
return cdm_engine_->Unprovision(level, origin);
|
||||
CdmSecurityLevel level, const std::string& origin) {
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(origin);
|
||||
return cdm_engine->Unprovision(level);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetUsageInfo(
|
||||
const std::string& app_id, CdmUsageInfo* usage_info) {
|
||||
return cdm_engine_->GetUsageInfo(app_id, usage_info);
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(EMPTY_ORIGIN);
|
||||
return cdm_engine->GetUsageInfo(app_id, usage_info);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::GetUsageInfo(
|
||||
const std::string& app_id,
|
||||
const CdmSecureStopId& ssid,
|
||||
CdmUsageInfo* usage_info) {
|
||||
return cdm_engine_->GetUsageInfo(app_id, ssid, usage_info);
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(EMPTY_ORIGIN);
|
||||
return cdm_engine->GetUsageInfo(app_id, ssid, usage_info);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::ReleaseAllUsageInfo(
|
||||
const std::string& app_id) {
|
||||
return cdm_engine_->ReleaseAllUsageInfo(app_id);
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(EMPTY_ORIGIN);
|
||||
return cdm_engine->ReleaseAllUsageInfo(app_id);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message) {
|
||||
return cdm_engine_->ReleaseUsageInfo(message);
|
||||
CdmEngine* cdm_engine = EnsureCdmForOrigin(EMPTY_ORIGIN);
|
||||
return cdm_engine->ReleaseUsageInfo(message);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::Decrypt(
|
||||
const CdmSessionId& session_id,
|
||||
bool validate_key_id,
|
||||
const CdmDecryptionParameters& parameters) {
|
||||
// First find the CdmEngine that has the given session_id. If we are using
|
||||
// key sharing, the shared session will still be in the same CdmEngine.
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
if (!cdm_engine) return SESSION_NOT_FOUND_FOR_DECRYPT;
|
||||
|
||||
CdmSessionId local_session_id = session_id;
|
||||
if (validate_key_id &&
|
||||
Properties::GetSessionSharingId(session_id) != 0) {
|
||||
bool status = cdm_engine_->FindSessionForKey(*parameters.key_id,
|
||||
bool status = cdm_engine->FindSessionForKey(*parameters.key_id,
|
||||
&local_session_id);
|
||||
if (!status) {
|
||||
LOGE("WvContentDecryptionModule::Decrypt: unable to find session");
|
||||
return NEED_KEY;
|
||||
return SESSION_NOT_FOUND_FOR_DECRYPT;
|
||||
}
|
||||
}
|
||||
return cdm_engine_->Decrypt(local_session_id, parameters);
|
||||
return cdm_engine->Decrypt(local_session_id, parameters);
|
||||
}
|
||||
|
||||
void WvContentDecryptionModule::NotifyResolution(const CdmSessionId& session_id,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
cdm_engine_->NotifyResolution(session_id, width, height);
|
||||
CdmEngine* cdm_engine = GetCdmForSessionId(session_id);
|
||||
if (!cdm_engine) return;
|
||||
cdm_engine->NotifyResolution(session_id, width, height);
|
||||
}
|
||||
|
||||
bool WvContentDecryptionModule::IsValidServiceCertificate(
|
||||
@@ -218,6 +260,27 @@ bool WvContentDecryptionModule::IsValidServiceCertificate(
|
||||
return CdmLicense::VerifySignedServiceCertificate(certificate) == NO_ERROR;
|
||||
}
|
||||
|
||||
WvContentDecryptionModule::CdmInfo::CdmInfo()
|
||||
: cdm_engine(new CdmEngine(&file_system)) {}
|
||||
|
||||
CdmEngine* WvContentDecryptionModule::EnsureCdmForOrigin(
|
||||
const std::string& origin) {
|
||||
if (cdms_.find(origin) == cdms_.end()) {
|
||||
// Will create a new instance using the default constructor.
|
||||
cdms_[origin].file_system.SetOrigin(origin);
|
||||
}
|
||||
|
||||
return cdms_[origin].cdm_engine.get();
|
||||
}
|
||||
|
||||
CdmEngine* WvContentDecryptionModule::GetCdmForSessionId(
|
||||
const std::string& session_id) {
|
||||
// Use find to avoid creating empty entries when not found.
|
||||
auto it = cdm_by_session_id_.find(session_id);
|
||||
if (it == cdm_by_session_id_.end()) return NULL;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void WvContentDecryptionModule::EnablePolicyTimer() {
|
||||
AutoLock auto_lock(policy_timer_lock_);
|
||||
if (!policy_timer_.IsRunning())
|
||||
@@ -226,12 +289,25 @@ void WvContentDecryptionModule::EnablePolicyTimer() {
|
||||
|
||||
void WvContentDecryptionModule::DisablePolicyTimer(bool force) {
|
||||
AutoLock auto_lock(policy_timer_lock_);
|
||||
if ((cdm_engine_->SessionSize() == 0 || force) && policy_timer_.IsRunning())
|
||||
bool has_sessions = false;
|
||||
for (auto it = cdms_.begin(); it != cdms_.end();) {
|
||||
if (it->second.cdm_engine->SessionSize() != 0) {
|
||||
has_sessions = true;
|
||||
++it;
|
||||
} else {
|
||||
// The CDM is no longer used for this origin, delete it.
|
||||
it = cdms_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
if ((!has_sessions || force) && policy_timer_.IsRunning())
|
||||
policy_timer_.Stop();
|
||||
}
|
||||
|
||||
void WvContentDecryptionModule::OnTimerEvent() {
|
||||
cdm_engine_->OnTimerEvent();
|
||||
for (auto it = cdms_.begin(); it != cdms_.end(); ++it) {
|
||||
it->second.cdm_engine->OnTimerEvent();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t WvContentDecryptionModule::GenerateSessionSharingId() {
|
||||
|
||||
Reference in New Issue
Block a user