Source release 14.1.0
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "cdm_engine.h"
|
||||
|
||||
@@ -28,6 +30,8 @@ const size_t kUsageReportsPerRequest = 1;
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
Lock shared_ptr_ref_count_lock_;
|
||||
|
||||
class UsagePropertySet : public CdmClientPropertySet {
|
||||
public:
|
||||
UsagePropertySet() {}
|
||||
@@ -70,7 +74,6 @@ CdmEngine::CdmEngine(FileSystem* file_system, const std::string& spoid)
|
||||
seeded_ = true;
|
||||
}
|
||||
|
||||
life_span_.Start();
|
||||
metrics_.cdm_engine_creation_time_millis_.Record(clock_.GetCurrentTime());
|
||||
|
||||
std::string cdm_version;
|
||||
@@ -82,18 +85,7 @@ CdmEngine::CdmEngine(FileSystem* file_system, const std::string& spoid)
|
||||
}
|
||||
}
|
||||
|
||||
CdmEngine::~CdmEngine() {
|
||||
M_RECORD(&metrics_, cdm_engine_life_span_, life_span_.AsMs());
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::SetProvisioningServiceCertificate(
|
||||
const std::string& certificate) {
|
||||
return provisioning_service_certificate_.Init(certificate);
|
||||
}
|
||||
|
||||
bool CdmEngine::HasProvisioningServiceCertificate() {
|
||||
return provisioning_service_certificate_.has_certificate();
|
||||
}
|
||||
CdmEngine::~CdmEngine() {}
|
||||
|
||||
CdmResponseType CdmEngine::OpenSession(
|
||||
const CdmKeySystem& key_system, CdmClientPropertySet* property_set,
|
||||
@@ -149,6 +141,7 @@ CdmResponseType CdmEngine::OpenSession(
|
||||
return sts;
|
||||
}
|
||||
CdmSessionId id = new_session->session_id();
|
||||
LOGI("CdmEngine::OpenSession: %s", id.c_str());
|
||||
|
||||
session_map_.Add(id, new_session.release());
|
||||
if (session_id) *session_id = id;
|
||||
@@ -412,11 +405,23 @@ CdmResponseType CdmEngine::RemoveKeys(const CdmSessionId& session_id) {
|
||||
return SESSION_NOT_FOUND_5;
|
||||
}
|
||||
|
||||
session->ReleaseCrypto();
|
||||
session->RemoveKeys();
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::RemoveLicense(const CdmSessionId& session_id) {
|
||||
LOGI("CdmEngine::RemoveLicense");
|
||||
|
||||
shared_ptr<CdmSession> session;
|
||||
if (!session_map_.FindSession(session_id, &session)) {
|
||||
LOGE("session_id not found = %s", session_id.c_str());
|
||||
return SESSION_NOT_FOUND_19;
|
||||
}
|
||||
|
||||
return session->RemoveLicense();
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::GenerateRenewalRequest(
|
||||
const CdmSessionId& session_id, CdmKeyRequest* key_request) {
|
||||
LOGI("CdmEngine::GenerateRenewalRequest");
|
||||
@@ -761,7 +766,9 @@ CdmResponseType CdmEngine::QueryOemCryptoSessionId(
|
||||
*/
|
||||
CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
CdmCertificateType cert_type, const std::string& cert_authority,
|
||||
CdmProvisioningRequest* request, std::string* default_url) {
|
||||
const std::string& service_certificate, CdmProvisioningRequest* request,
|
||||
std::string* default_url) {
|
||||
LOGI("CdmEngine::GetProvisioningRequest");
|
||||
if (!request) {
|
||||
LOGE("CdmEngine::GetProvisioningRequest: invalid output parameters");
|
||||
return INVALID_PROVISIONING_REQUEST_PARAM_1;
|
||||
@@ -776,8 +783,7 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
if (NULL == cert_provisioning_.get()) {
|
||||
cert_provisioning_.reset(
|
||||
new CertificateProvisioning(metrics_.GetCryptoMetrics()));
|
||||
CdmResponseType status = cert_provisioning_->Init(
|
||||
provisioning_service_certificate_.certificate());
|
||||
CdmResponseType status = cert_provisioning_->Init(service_certificate);
|
||||
if (status != NO_ERROR) return status;
|
||||
}
|
||||
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
|
||||
@@ -799,6 +805,7 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
||||
CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||
const CdmProvisioningResponse& response, std::string* cert,
|
||||
std::string* wrapped_key) {
|
||||
LOGI("CdmEngine::HandleProvisioningResponse");
|
||||
if (response.empty()) {
|
||||
LOGE("CdmEngine::HandleProvisioningResponse: Empty provisioning response.");
|
||||
cert_provisioning_.reset(NULL);
|
||||
@@ -873,6 +880,19 @@ bool CdmEngine::IsProvisioned(CdmSecurityLevel security_level) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
|
||||
// Devices with baked-in DRM certs cannot be reprovisioned and therefore must
|
||||
// not be unprovisioned.
|
||||
CryptoSession crypto_session(metrics_.GetCryptoMetrics());
|
||||
CdmClientTokenType token_type = kClientTokenUninitialized;
|
||||
CdmResponseType res = crypto_session.GetProvisioningMethod(
|
||||
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault,
|
||||
&token_type);
|
||||
if (res != NO_ERROR) {
|
||||
return res;
|
||||
} else if (token_type == kClientTokenDrmCert) {
|
||||
return DEVICE_CANNOT_REPROVISION;
|
||||
}
|
||||
|
||||
DeviceFiles handle(file_system_);
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("CdmEngine::Unprovision: unable to initialize device files");
|
||||
@@ -939,20 +959,22 @@ CdmResponseType CdmEngine::ListStoredLicenses(
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ListUsageRecords(const std::string& app_id,
|
||||
CdmSecurityLevel security_level,
|
||||
std::vector<std::string>* ksids) {
|
||||
CdmResponseType CdmEngine::ListUsageIds(
|
||||
const std::string& app_id,
|
||||
CdmSecurityLevel security_level,
|
||||
std::vector<std::string>* ksids,
|
||||
std::vector<std::string>* provider_session_tokens) {
|
||||
DeviceFiles handle(file_system_);
|
||||
if (!ksids) {
|
||||
LOGE("CdmEngine::ListUsageRecords: no response destination");
|
||||
if (!ksids && !provider_session_tokens) {
|
||||
LOGE("CdmEngine::ListUsageIds: no response destination");
|
||||
return INVALID_PARAMETERS_ENG_23;
|
||||
}
|
||||
if (!handle.Init(security_level)) {
|
||||
LOGE("CdmEngine::ListUsageRecords: unable to initialize device files");
|
||||
LOGE("CdmEngine::ListUsageIds: unable to initialize device files");
|
||||
return LIST_USAGE_ERROR_1;
|
||||
}
|
||||
if (!handle.ListUsageRecords(app_id, ksids)) {
|
||||
LOGE("CdmEngine::ListUsageRecords: ListUsageRecords call failed");
|
||||
if (!handle.ListUsageIds(app_id, ksids, provider_session_tokens)) {
|
||||
LOGE("CdmEngine::ListUsageIds: ListUsageIds call failed");
|
||||
return LIST_USAGE_ERROR_2;
|
||||
}
|
||||
return NO_ERROR;
|
||||
@@ -1153,8 +1175,8 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
|
||||
switch (status) {
|
||||
case KEY_MESSAGE:
|
||||
break;
|
||||
case KEY_CANCELED: // usage information not present in
|
||||
usage_session_->DeleteLicense(); // OEMCrypto, delete and try again
|
||||
case KEY_CANCELED: // usage information not present in
|
||||
usage_session_->DeleteLicenseFile(); // OEMCrypto, delete and try again
|
||||
usage_info->clear();
|
||||
break;
|
||||
default:
|
||||
@@ -1226,24 +1248,29 @@ CdmResponseType CdmEngine::RemoveAllUsageInfo(const std::string& app_id) {
|
||||
if (!handle.RetrieveUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
&usage_data)) {
|
||||
status = REMOVE_ALL_USAGE_INFO_ERROR_4;
|
||||
LOGW("CdmEngine::RemoveAllUsageInfo: failed to retrieve usage info");
|
||||
break;
|
||||
}
|
||||
|
||||
if (usage_data.empty()) break;
|
||||
|
||||
status = usage_session_->DeleteUsageEntry(
|
||||
CdmResponseType res = usage_session_->DeleteUsageEntry(
|
||||
usage_data[0].usage_entry_number);
|
||||
|
||||
if (status != NO_ERROR) break;
|
||||
if (res != NO_ERROR) {
|
||||
LOGW("CdmEngine::RemoveAllUsageInfo: failed to delete usage "
|
||||
"entry: error: %d", res);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!handle.DeleteUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
usage_data[0].provider_session_token)) {
|
||||
status = REMOVE_ALL_USAGE_INFO_ERROR_6;
|
||||
LOGW("CdmEngine::RemoveAllUsageInfo: failed to delete usage "
|
||||
"info");
|
||||
break;
|
||||
}
|
||||
} while (status == NO_ERROR && !usage_data.empty());
|
||||
} while (!usage_data.empty());
|
||||
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
if (!handle.DeleteAllUsageInfoForApp(
|
||||
@@ -1282,6 +1309,84 @@ CdmResponseType CdmEngine::RemoveAllUsageInfo(const std::string& app_id) {
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::RemoveUsageInfo(
|
||||
const std::string& app_id,
|
||||
const CdmSecureStopId& provider_session_token) {
|
||||
if (NULL == usage_property_set_.get()) {
|
||||
usage_property_set_.reset(new UsagePropertySet());
|
||||
}
|
||||
usage_property_set_->set_app_id(app_id);
|
||||
|
||||
CdmResponseType status = NO_ERROR;
|
||||
for (int j = kSecurityLevelL1; j < kSecurityLevelUnknown; ++j) {
|
||||
DeviceFiles handle(file_system_);
|
||||
if (handle.Init(static_cast<CdmSecurityLevel>(j))) {
|
||||
SecurityLevel security_level =
|
||||
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
|
||||
? kLevel3
|
||||
: kLevelDefault;
|
||||
usage_property_set_->set_security_level(security_level);
|
||||
usage_session_.reset(new CdmSession(file_system_, metrics_.AddSession()));
|
||||
usage_session_->Init(usage_property_set_.get());
|
||||
|
||||
std::vector<DeviceFiles::CdmUsageData> usage_data;
|
||||
CdmKeyMessage license_request;
|
||||
CdmKeyResponse license_response;
|
||||
CdmUsageEntry usage_entry;
|
||||
uint32_t usage_entry_number;
|
||||
|
||||
if (!handle.RetrieveUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), provider_session_token,
|
||||
&license_request, &license_response, &usage_entry,
|
||||
&usage_entry_number)) {
|
||||
// Try other security level
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (usage_session_->get_usage_support_type()) {
|
||||
case kUsageEntrySupport: {
|
||||
status = usage_session_->DeleteUsageEntry(usage_entry_number);
|
||||
|
||||
if (!handle.DeleteUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
provider_session_token)) {
|
||||
status = REMOVE_USAGE_INFO_ERROR_1;
|
||||
}
|
||||
usage_session_.reset(NULL);
|
||||
return status;
|
||||
}
|
||||
case kUsageTableSupport: {
|
||||
std::vector<std::string> provider_session_tokens;
|
||||
handle.DeleteUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
provider_session_token);
|
||||
scoped_ptr<CryptoSession> crypto_session(
|
||||
new CryptoSession(metrics_.GetCryptoMetrics()));
|
||||
status = crypto_session->Open(
|
||||
static_cast<CdmSecurityLevel>(j) == kSecurityLevelL3
|
||||
? kLevel3 : kLevelDefault);
|
||||
if (status == NO_ERROR) {
|
||||
crypto_session->UpdateUsageInformation();
|
||||
status =
|
||||
crypto_session->DeleteUsageInformation(provider_session_token);
|
||||
crypto_session->UpdateUsageInformation();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
default:
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
LOGE("CdmEngine::RemoveUsageInfo: failed to initialize L%d devicefiles",
|
||||
j);
|
||||
status = REMOVE_USAGE_INFO_ERROR_2;
|
||||
}
|
||||
}
|
||||
usage_session_.reset(NULL);
|
||||
return REMOVE_USAGE_INFO_ERROR_3;
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ReleaseUsageInfo(
|
||||
const CdmUsageInfoReleaseMessage& message) {
|
||||
if (NULL == usage_session_.get()) {
|
||||
@@ -1358,7 +1463,7 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
|
||||
break;
|
||||
case KEY_CANCELED:
|
||||
// usage information not present in OEMCrypto, delete and try again
|
||||
session->DeleteLicense();
|
||||
session->DeleteLicenseFile();
|
||||
break;
|
||||
default:
|
||||
LOGE("CdmEngine::LoadUsageSession: generate release request error: %d",
|
||||
@@ -1594,7 +1699,9 @@ void CdmEngine::OnTimerEvent() {
|
||||
(*iter)->reset_usage_flags();
|
||||
switch ((*iter)->get_usage_support_type()) {
|
||||
case kUsageEntrySupport:
|
||||
(*iter)->UpdateUsageEntryInformation();
|
||||
if ((*iter)->has_provider_session_token()) {
|
||||
(*iter)->UpdateUsageEntryInformation();
|
||||
}
|
||||
break;
|
||||
case kUsageTableSupport:
|
||||
if (!has_usage_been_updated) {
|
||||
@@ -1627,6 +1734,11 @@ void CdmEngine::OnKeyReleaseEvent(const CdmKeySetId& key_set_id) {
|
||||
}
|
||||
}
|
||||
|
||||
CdmResponseType CdmEngine::ValidateServiceCertificate(const std::string& cert) {
|
||||
ServiceCertificate certificate;
|
||||
return certificate.Init(cert);
|
||||
}
|
||||
|
||||
std::string CdmEngine::MapHdcpVersion(
|
||||
CryptoSession::HdcpCapability version) {
|
||||
switch (version) {
|
||||
|
||||
Reference in New Issue
Block a user