Source release 18.1.0
This commit is contained in:
@@ -12,13 +12,15 @@
|
||||
#include <string>
|
||||
|
||||
#include "cdm_engine.h"
|
||||
#include "cdm_random.h"
|
||||
#include "cdm_usage_table.h"
|
||||
#include "clock.h"
|
||||
#include "crypto_wrapped_key.h"
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "usage_table_header.h"
|
||||
#include "system_id_extractor.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_event_listener.h"
|
||||
|
||||
@@ -29,7 +31,7 @@
|
||||
#define RETURN_STATUS_IF_NULL(PARAM) \
|
||||
if ((PARAM) == nullptr) { \
|
||||
LOGE("Output parameter |" STRINGIFY(PARAM) "| not provided"); \
|
||||
return PARAMETER_NULL; \
|
||||
return CdmResponseType(PARAMETER_NULL); \
|
||||
}
|
||||
|
||||
#define RETURN_FALSE_IF_NULL(PARAM) \
|
||||
@@ -46,7 +48,7 @@ const size_t kKeySetIdLength = 14;
|
||||
template <typename T>
|
||||
void SetErrorDetail(int* error_detail, T error_code) {
|
||||
if (error_detail != nullptr) {
|
||||
*error_detail = error_code;
|
||||
*error_detail = static_cast<int>(error_code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +82,6 @@ CdmSession::CdmSession(wvutil::FileSystem* file_system,
|
||||
requested_security_level_(kLevelDefault),
|
||||
is_initial_usage_update_(true),
|
||||
is_usage_update_needed_(false),
|
||||
usage_table_header_(nullptr),
|
||||
usage_entry_number_(0),
|
||||
mock_license_parser_in_use_(false),
|
||||
mock_policy_engine_in_use_(false) {
|
||||
assert(metrics_); // metrics_ must not be null.
|
||||
@@ -91,7 +91,7 @@ CdmSession::CdmSession(wvutil::FileSystem* file_system,
|
||||
}
|
||||
|
||||
CdmSession::~CdmSession() {
|
||||
if (has_provider_session_token() && supports_usage_info() && !is_release_) {
|
||||
if (has_provider_session_token() && SupportsUsageTable() && !is_release_) {
|
||||
UpdateUsageEntryInformation();
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
|
||||
bool forced_level3) {
|
||||
if (initialized_) {
|
||||
LOGE("Failed due to previous initialization");
|
||||
return REINIT_ERROR;
|
||||
return CdmResponseType(REINIT_ERROR);
|
||||
}
|
||||
|
||||
if ((cdm_client_property_set && cdm_client_property_set->security_level() ==
|
||||
@@ -144,12 +144,12 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
|
||||
|
||||
if (!file_handle_->Init(security_level_)) {
|
||||
LOGE("Unable to initialize file handle");
|
||||
return SESSION_FILE_HANDLE_INIT_ERROR;
|
||||
return CdmResponseType(SESSION_FILE_HANDLE_INIT_ERROR);
|
||||
}
|
||||
|
||||
bool has_support = false;
|
||||
if (crypto_session_->HasUsageInfoSupport(&has_support) && has_support) {
|
||||
usage_table_header_ = crypto_session_->GetUsageTableHeader();
|
||||
if (crypto_session_->HasUsageTableSupport(&has_support) && has_support) {
|
||||
usage_table_ = crypto_session_->GetUsageTable();
|
||||
}
|
||||
|
||||
if (cdm_client_property_set != nullptr)
|
||||
@@ -159,7 +159,10 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
|
||||
// The actual validation and loading of a certificate will happen when
|
||||
// a key request is generated or an offline license is loaded.
|
||||
if (!file_handle_->HasCertificate(atsc_mode_enabled_))
|
||||
return NEED_PROVISIONING;
|
||||
return CdmResponseType(NEED_PROVISIONING);
|
||||
|
||||
// Require reprovisioning if the root of trust has changed
|
||||
if (HasRootOfTrustBeenRenewed()) return CdmResponseType(NEED_PROVISIONING);
|
||||
|
||||
if (forced_session_id) {
|
||||
key_set_id_ = *forced_session_id;
|
||||
@@ -178,7 +181,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
|
||||
|
||||
if (session_id_.empty()) {
|
||||
LOGE("Empty session ID");
|
||||
return EMPTY_SESSION_ID;
|
||||
return CdmResponseType(EMPTY_SESSION_ID);
|
||||
}
|
||||
if (cdm_client_property_set)
|
||||
Properties::AddSessionPropertySet(session_id_, cdm_client_property_set);
|
||||
@@ -196,13 +199,13 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
|
||||
if (!license_parser_->Init(Properties::UsePrivacyMode(session_id_),
|
||||
service_certificate, crypto_session_.get(),
|
||||
policy_engine_.get()))
|
||||
return LICENSE_PARSER_INIT_ERROR;
|
||||
return CdmResponseType(LICENSE_PARSER_INIT_ERROR);
|
||||
|
||||
license_received_ = false;
|
||||
is_initial_decryption_ = true;
|
||||
initialized_ = true;
|
||||
closed_ = false;
|
||||
return NO_ERROR;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
@@ -210,7 +213,7 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
int* error_detail) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
if (!key_set_id_.empty()) {
|
||||
file_handle_->UnreserveLicenseId(key_set_id_);
|
||||
@@ -219,7 +222,7 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
LOGE(
|
||||
"Disallow multiple offline license restores or restoring a license if "
|
||||
"a license has already been loaded");
|
||||
return RESTORE_OFFLINE_LICENSE_ERROR_3;
|
||||
return CdmResponseType(RESTORE_OFFLINE_LICENSE_ERROR_3);
|
||||
}
|
||||
|
||||
key_set_id_ = key_set_id;
|
||||
@@ -233,8 +236,21 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
DeviceFiles::ResponseTypeToString(sub_error_code),
|
||||
IdToString(key_set_id));
|
||||
SetErrorDetail(error_detail, sub_error_code);
|
||||
return sub_error_code == DeviceFiles::kFileNotFound ? KEYSET_ID_NOT_FOUND_4
|
||||
: GET_LICENSE_ERROR;
|
||||
switch (sub_error_code) {
|
||||
case DeviceFiles::kFileNotFound:
|
||||
case DeviceFiles::kFileNotFoundEAcces:
|
||||
case DeviceFiles::kFileNotFoundEFault:
|
||||
case DeviceFiles::kFileNotFoundELoop:
|
||||
case DeviceFiles::kFileNotFoundENameTooLong:
|
||||
case DeviceFiles::kFileNotFoundENoEnt:
|
||||
case DeviceFiles::kFileNotFoundENoMem:
|
||||
case DeviceFiles::kFileNotFoundENotDir:
|
||||
case DeviceFiles::kFileNotFoundEOverflow:
|
||||
case DeviceFiles::kFileNotFoundOther:
|
||||
return (CdmResponseType(KEYSET_ID_NOT_FOUND_4));
|
||||
default:
|
||||
return (CdmResponseType(GET_LICENSE_ERROR));
|
||||
}
|
||||
}
|
||||
offline_init_data_ = std::move(license_data.pssh_data);
|
||||
key_request_ = std::move(license_data.license_request);
|
||||
@@ -245,7 +261,7 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
offline_release_server_url_ = std::move(license_data.release_server_url);
|
||||
app_parameters_ = std::move(license_data.app_parameters);
|
||||
usage_entry_ = std::move(license_data.usage_entry);
|
||||
usage_entry_number_ = license_data.usage_entry_number;
|
||||
usage_entry_index_ = license_data.usage_entry_index;
|
||||
|
||||
CdmResponseType result = LoadPrivateOrLegacyKey(
|
||||
license_data.drm_certificate, license_data.wrapped_private_key);
|
||||
@@ -266,27 +282,27 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
LOGE("Invalid offline license state: state = %s, license_type = %s",
|
||||
CdmOfflineLicenseStateToString(license_data.state),
|
||||
CdmLicenseTypeToString(license_type));
|
||||
return GET_RELEASED_LICENSE_ERROR;
|
||||
return CdmResponseType(GET_RELEASED_LICENSE_ERROR);
|
||||
}
|
||||
|
||||
std::string provider_session_token;
|
||||
bool sign_fake_request = false; // TODO(b/169483174): remove this variable.
|
||||
if (supports_usage_info()) {
|
||||
if (SupportsUsageTable()) {
|
||||
if (!license_parser_->ExtractProviderSessionToken(
|
||||
key_response_, &provider_session_token)) {
|
||||
provider_session_token.clear();
|
||||
sign_fake_request = true; // TODO(b/169483174): remove this line.
|
||||
} else if (!VerifyOfflineUsageEntry()) {
|
||||
LOGE("License usage entry is invalid, cannot restore");
|
||||
return LICENSE_USAGE_ENTRY_MISSING;
|
||||
return CdmResponseType(LICENSE_USAGE_ENTRY_MISSING);
|
||||
} else {
|
||||
CdmResponseType sts = usage_table_header_->LoadEntry(
|
||||
crypto_session_.get(), usage_entry_, usage_entry_number_);
|
||||
CdmResponseType sts = usage_table_->LoadEntry(
|
||||
crypto_session_.get(), usage_entry_, usage_entry_index_);
|
||||
crypto_metrics_->usage_table_header_load_entry_.Increment(sts);
|
||||
if (sts == LOAD_USAGE_ENTRY_INVALID_SESSION) {
|
||||
LOGE("License loaded in different session: key_set_id = %s",
|
||||
IdToString(key_set_id));
|
||||
return USAGE_ENTRY_ALREADY_LOADED;
|
||||
return CdmResponseType(USAGE_ENTRY_ALREADY_LOADED);
|
||||
}
|
||||
if (sts != NO_ERROR) {
|
||||
LOGE("Failed to load usage entry: status = %d", static_cast<int>(sts));
|
||||
@@ -305,13 +321,16 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
std::string fake_message("empty message");
|
||||
std::string core_message;
|
||||
std::string license_request_signature;
|
||||
bool should_specify_algorithm;
|
||||
OEMCrypto_SignatureHashAlgorithm algorithm = OEMCrypto_SHA1;
|
||||
uint32_t nonce;
|
||||
// Sign a fake message so that OEMCrypto will start the rental clock. The
|
||||
// signature and generated core message are ignored.
|
||||
result = crypto_session_->GenerateNonce(&nonce);
|
||||
if (result != NO_ERROR) return result;
|
||||
result = crypto_session_->PrepareAndSignLicenseRequest(
|
||||
fake_message, &core_message, &license_request_signature);
|
||||
fake_message, &core_message, &license_request_signature,
|
||||
should_specify_algorithm, algorithm);
|
||||
if (result != NO_ERROR) return result;
|
||||
}
|
||||
|
||||
@@ -320,8 +339,8 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
license_data.drm_certificate, key_request_, key_response_);
|
||||
|
||||
if (result != NO_ERROR) {
|
||||
SetErrorDetail(error_detail, result);
|
||||
return RELEASE_LICENSE_ERROR_1;
|
||||
SetErrorDetail(error_detail, result.code());
|
||||
return CdmResponseType(RELEASE_LICENSE_ERROR_1);
|
||||
}
|
||||
} else {
|
||||
result = license_parser_->RestoreOfflineLicense(
|
||||
@@ -330,14 +349,14 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
license_data.last_playback_time, license_data.grace_period_end_time,
|
||||
this);
|
||||
if (result != NO_ERROR) {
|
||||
SetErrorDetail(error_detail, result);
|
||||
return RESTORE_OFFLINE_LICENSE_ERROR_2;
|
||||
SetErrorDetail(error_detail, result.code());
|
||||
return CdmResponseType(RESTORE_OFFLINE_LICENSE_ERROR_2);
|
||||
}
|
||||
}
|
||||
|
||||
if (!provider_session_token.empty() && supports_usage_info()) {
|
||||
CdmResponseType sts = usage_table_header_->UpdateEntry(
|
||||
usage_entry_number_, crypto_session_.get(), &usage_entry_);
|
||||
if (!provider_session_token.empty() && SupportsUsageTable()) {
|
||||
CdmResponseType sts = usage_table_->UpdateEntry(
|
||||
usage_entry_index_, crypto_session_.get(), &usage_entry_);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGE("Failed to update usage entry: status = %d", static_cast<int>(sts));
|
||||
return sts;
|
||||
@@ -351,14 +370,14 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
||||
is_offline_ = true;
|
||||
is_release_ = license_type == kLicenseTypeRelease;
|
||||
has_license_been_restored_ = true;
|
||||
return KEY_ADDED;
|
||||
return CdmResponseType(KEY_ADDED);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::RestoreUsageSession(
|
||||
const DeviceFiles::CdmUsageData& usage_data, int* error_detail) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
if (!key_set_id_.empty()) {
|
||||
file_handle_->UnreserveLicenseId(key_set_id_);
|
||||
@@ -367,17 +386,17 @@ CdmResponseType CdmSession::RestoreUsageSession(
|
||||
key_request_ = usage_data.license_request;
|
||||
key_response_ = usage_data.license;
|
||||
usage_entry_ = usage_data.usage_entry;
|
||||
usage_entry_number_ = usage_data.usage_entry_number;
|
||||
usage_entry_index_ = usage_data.usage_entry_index;
|
||||
usage_provider_session_token_ = usage_data.provider_session_token;
|
||||
|
||||
CdmResponseType status = LoadPrivateOrLegacyKey(
|
||||
usage_data.drm_certificate, usage_data.wrapped_private_key);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
CdmResponseType sts = NO_ERROR;
|
||||
if (supports_usage_info()) {
|
||||
sts = usage_table_header_->LoadEntry(crypto_session_.get(), usage_entry_,
|
||||
usage_entry_number_);
|
||||
CdmResponseType sts(NO_ERROR);
|
||||
if (SupportsUsageTable()) {
|
||||
sts = usage_table_->LoadEntry(crypto_session_.get(), usage_entry_,
|
||||
usage_entry_index_);
|
||||
crypto_metrics_->usage_table_header_load_entry_.Increment(sts);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGE("Failed to load usage entry: status = %d", static_cast<int>(sts));
|
||||
@@ -390,12 +409,12 @@ CdmResponseType CdmSession::RestoreUsageSession(
|
||||
|
||||
if (sts != NO_ERROR) {
|
||||
SetErrorDetail(error_detail, sts);
|
||||
return RELEASE_LICENSE_ERROR_2;
|
||||
return CdmResponseType(RELEASE_LICENSE_ERROR_2);
|
||||
}
|
||||
|
||||
if (supports_usage_info()) {
|
||||
sts = usage_table_header_->UpdateEntry(
|
||||
usage_entry_number_, crypto_session_.get(), &usage_entry_);
|
||||
if (SupportsUsageTable()) {
|
||||
sts = usage_table_->UpdateEntry(usage_entry_index_, crypto_session_.get(),
|
||||
&usage_entry_);
|
||||
if (sts != NO_ERROR) {
|
||||
LOGE("Failed to update usage entry: status = %d", static_cast<int>(sts));
|
||||
return sts;
|
||||
@@ -408,7 +427,7 @@ CdmResponseType CdmSession::RestoreUsageSession(
|
||||
license_received_ = true;
|
||||
is_offline_ = false;
|
||||
is_release_ = true;
|
||||
return KEY_ADDED;
|
||||
return CdmResponseType(KEY_ADDED);
|
||||
}
|
||||
|
||||
// This is a thin wrapper that initiates the latency metric.
|
||||
@@ -432,7 +451,7 @@ CdmResponseType CdmSession::GenerateKeyRequestInternal(
|
||||
const CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
RETURN_STATUS_IF_NULL(key_request);
|
||||
|
||||
@@ -460,7 +479,7 @@ CdmResponseType CdmSession::GenerateKeyRequestInternal(
|
||||
return license_parser_->HandleEmbeddedKeyData(init_data);
|
||||
default:
|
||||
LOGE("Unrecognized license type: %d", static_cast<int>(license_type));
|
||||
return INVALID_LICENSE_TYPE;
|
||||
return CdmResponseType(INVALID_LICENSE_TYPE);
|
||||
}
|
||||
|
||||
if (is_release_) {
|
||||
@@ -482,15 +501,15 @@ CdmResponseType CdmSession::GenerateKeyRequestInternal(
|
||||
|
||||
if (!init_data.is_supported()) {
|
||||
LOGW("Unsupported init data type: %s", init_data.type().c_str());
|
||||
return UNSUPPORTED_INIT_DATA;
|
||||
return CdmResponseType(UNSUPPORTED_INIT_DATA);
|
||||
}
|
||||
if (init_data.IsEmpty() && !license_parser_->HasInitData()) {
|
||||
LOGW("Init data absent");
|
||||
return INIT_DATA_NOT_FOUND;
|
||||
return CdmResponseType(INIT_DATA_NOT_FOUND);
|
||||
}
|
||||
if (is_offline_ && key_set_id_.empty()) {
|
||||
LOGE("Key set ID not set");
|
||||
return KEY_REQUEST_ERROR_1;
|
||||
return CdmResponseType(KEY_REQUEST_ERROR_1);
|
||||
}
|
||||
// Attempt to load provisioned private key if available.
|
||||
CdmResponseType status = LoadPrivateKey();
|
||||
@@ -507,7 +526,7 @@ CdmResponseType CdmSession::GenerateKeyRequestInternal(
|
||||
offline_init_data_ = init_data.data();
|
||||
offline_release_server_url_ = key_request->url;
|
||||
}
|
||||
return KEY_MESSAGE;
|
||||
return CdmResponseType(KEY_MESSAGE);
|
||||
}
|
||||
|
||||
// This thin wrapper allows us to update metrics.
|
||||
@@ -521,12 +540,12 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
|
||||
if (!initialized_) {
|
||||
LOGE("Not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
|
||||
if (is_release_) {
|
||||
const CdmResponseType sts = ReleaseKey(key_response);
|
||||
return (sts == NO_ERROR) ? KEY_ADDED : sts;
|
||||
return (sts == NO_ERROR) ? CdmResponseType(KEY_ADDED) : sts;
|
||||
}
|
||||
if (license_received_) { // renewal
|
||||
return RenewKey(key_response);
|
||||
@@ -536,16 +555,16 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
|
||||
// to be created.
|
||||
CdmResponseType sts;
|
||||
std::string provider_session_token;
|
||||
if (supports_usage_info()) {
|
||||
if (SupportsUsageTable()) {
|
||||
if (license_parser_->ExtractProviderSessionToken(key_response,
|
||||
&provider_session_token) &&
|
||||
!provider_session_token.empty()) {
|
||||
std::string app_id;
|
||||
GetApplicationId(&app_id);
|
||||
sts = usage_table_header_->AddEntry(
|
||||
crypto_session_.get(), is_offline_, key_set_id_,
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), key_response,
|
||||
&usage_entry_number_);
|
||||
sts = usage_table_->AddEntry(crypto_session_.get(), is_offline_,
|
||||
key_set_id_,
|
||||
DeviceFiles::GetUsageInfoFileName(app_id),
|
||||
key_response, &usage_entry_index_);
|
||||
crypto_metrics_->usage_table_header_add_entry_.Increment(sts);
|
||||
if (sts != NO_ERROR) return sts;
|
||||
}
|
||||
@@ -560,11 +579,10 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
|
||||
version_info.license_service_version());
|
||||
|
||||
// Update or invalidate entry if usage table header+entries are supported
|
||||
if (!provider_session_token.empty() && supports_usage_info()) {
|
||||
if (!provider_session_token.empty() && SupportsUsageTable()) {
|
||||
if (sts != KEY_ADDED) {
|
||||
const CdmResponseType invalidate_sts =
|
||||
usage_table_header_->InvalidateEntry(
|
||||
usage_entry_number_, true, file_handle_.get(), crypto_metrics_);
|
||||
const CdmResponseType invalidate_sts = usage_table_->InvalidateEntry(
|
||||
usage_entry_index_, true, file_handle_.get(), crypto_metrics_);
|
||||
crypto_metrics_->usage_table_header_delete_entry_.Increment(
|
||||
invalidate_sts);
|
||||
if (invalidate_sts != NO_ERROR) {
|
||||
@@ -574,7 +592,8 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? ADD_KEY_ERROR : sts;
|
||||
if (sts != KEY_ADDED)
|
||||
return (sts == KEY_ERROR) ? CdmResponseType(ADD_KEY_ERROR) : sts;
|
||||
|
||||
license_received_ = true;
|
||||
key_response_ = key_response;
|
||||
@@ -584,9 +603,9 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
|
||||
license_parser_->provider_session_token().size());
|
||||
|
||||
if ((is_offline_ || has_provider_session_token()) && !is_temporary_) {
|
||||
if (has_provider_session_token() && supports_usage_info()) {
|
||||
usage_table_header_->UpdateEntry(usage_entry_number_,
|
||||
crypto_session_.get(), &usage_entry_);
|
||||
if (has_provider_session_token() && SupportsUsageTable()) {
|
||||
usage_table_->UpdateEntry(usage_entry_index_, crypto_session_.get(),
|
||||
&usage_entry_);
|
||||
}
|
||||
|
||||
if (!is_offline_)
|
||||
@@ -597,13 +616,13 @@ CdmResponseType CdmSession::AddKeyInternal(const CdmKeyResponse& key_response) {
|
||||
}
|
||||
|
||||
has_license_been_loaded_ = true;
|
||||
return KEY_ADDED;
|
||||
return CdmResponseType(KEY_ADDED);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::QueryStatus(CdmQueryMap* query_response) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
RETURN_STATUS_IF_NULL(query_response);
|
||||
|
||||
@@ -626,9 +645,9 @@ CdmResponseType CdmSession::QueryStatus(CdmQueryMap* query_response) {
|
||||
QUERY_VALUE_SECURITY_LEVEL_UNKNOWN;
|
||||
break;
|
||||
default:
|
||||
return INVALID_QUERY_KEY;
|
||||
return CdmResponseType(INVALID_QUERY_KEY);
|
||||
}
|
||||
return NO_ERROR;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::SetServiceCertificate(
|
||||
@@ -649,19 +668,19 @@ CdmResponseType CdmSession::QueryOemCryptoSessionId(
|
||||
CdmQueryMap* query_response) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
RETURN_STATUS_IF_NULL(query_response);
|
||||
|
||||
(*query_response)[QUERY_KEY_OEMCRYPTO_SESSION_ID] =
|
||||
std::to_string(crypto_session_->oec_session_id());
|
||||
return NO_ERROR;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
// Decrypt() - Accept encrypted buffer and return decrypted data.
|
||||
CdmResponseType CdmSession::Decrypt(const CdmDecryptionParametersV16& params) {
|
||||
if (!initialized_) {
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
|
||||
bool is_protected = std::any_of(
|
||||
@@ -680,18 +699,19 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParametersV16& params) {
|
||||
// the security level is not high enough yet.
|
||||
if (is_protected) {
|
||||
if (!policy_engine_->CanDecryptContent(params.key_id)) {
|
||||
if (policy_engine_->IsLicenseForFuture()) return DECRYPT_NOT_READY;
|
||||
if (policy_engine_->IsLicenseForFuture())
|
||||
return CdmResponseType(DECRYPT_NOT_READY);
|
||||
if (!policy_engine_->IsSufficientOutputProtection(params.key_id)) {
|
||||
LOGE("Key use prohibited as HDCP or resolution requirements not met");
|
||||
return INSUFFICIENT_OUTPUT_PROTECTION;
|
||||
return CdmResponseType(INSUFFICIENT_OUTPUT_PROTECTION);
|
||||
}
|
||||
return NEED_KEY;
|
||||
return CdmResponseType(NEED_KEY);
|
||||
}
|
||||
if (!policy_engine_->CanUseKeyForSecurityLevel(params.key_id)) {
|
||||
LOGE(
|
||||
"Key use prohibited as security level requirements in the policy"
|
||||
" not met");
|
||||
return KEY_PROHIBITED_FOR_SECURITY_LEVEL;
|
||||
return CdmResponseType(KEY_PROHIBITED_FOR_SECURITY_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -718,7 +738,7 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParametersV16& params) {
|
||||
const int64_t current_time = clock.GetCurrentTime();
|
||||
if (policy_engine_->HasLicenseOrRentalOrPlaybackDurationExpired(
|
||||
current_time)) {
|
||||
return NEED_KEY;
|
||||
return CdmResponseType(NEED_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,7 +751,7 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParametersV16& params) {
|
||||
CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyRequest* key_request) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
RETURN_STATUS_IF_NULL(key_request);
|
||||
|
||||
@@ -747,14 +767,14 @@ CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyRequest* key_request) {
|
||||
}
|
||||
key_request_type_ = key_request->type;
|
||||
license_request_latency_.Start(); // Start or restart timer.
|
||||
return KEY_MESSAGE;
|
||||
return CdmResponseType(KEY_MESSAGE);
|
||||
}
|
||||
|
||||
// RenewKey() - Accept renewal response and update key info.
|
||||
CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
CdmResponseType sts = license_parser_->HandleKeyUpdateResponse(
|
||||
/* is renewal */ true,
|
||||
@@ -763,35 +783,36 @@ CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
|
||||
// Record the timing on success.
|
||||
UpdateRequestLatencyTiming(sts);
|
||||
|
||||
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? RENEW_KEY_ERROR_1 : sts;
|
||||
if (sts != KEY_ADDED)
|
||||
return (sts == KEY_ERROR) ? CdmResponseType(RENEW_KEY_ERROR_1) : sts;
|
||||
|
||||
if (is_offline_) {
|
||||
offline_key_renewal_response_ = key_response;
|
||||
if (!StoreLicense(kLicenseStateActive, nullptr /* error_detail */))
|
||||
return RENEW_KEY_ERROR_2;
|
||||
return CdmResponseType(RENEW_KEY_ERROR_2);
|
||||
}
|
||||
return KEY_ADDED;
|
||||
return CdmResponseType(KEY_ADDED);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyRequest* key_request) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
RETURN_STATUS_IF_NULL(key_request);
|
||||
is_release_ = true;
|
||||
license_request_latency_.Clear();
|
||||
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
|
||||
false, app_parameters_, usage_table_header_ == nullptr ? nullptr : this,
|
||||
false, app_parameters_, usage_table_ == nullptr ? nullptr : this,
|
||||
&key_request->message, &key_request->url);
|
||||
|
||||
key_request->type = kKeyRequestTypeRelease;
|
||||
|
||||
if (KEY_MESSAGE != status) return status;
|
||||
|
||||
if (has_provider_session_token() && supports_usage_info()) {
|
||||
status = usage_table_header_->UpdateEntry(
|
||||
usage_entry_number_, crypto_session_.get(), &usage_entry_);
|
||||
if (has_provider_session_token() && SupportsUsageTable()) {
|
||||
status = usage_table_->UpdateEntry(usage_entry_index_,
|
||||
crypto_session_.get(), &usage_entry_);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("Update usage entry failed: status = %d", static_cast<int>(status));
|
||||
@@ -801,24 +822,24 @@ CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyRequest* key_request) {
|
||||
|
||||
if (is_offline_) { // Mark license as being released
|
||||
if (!StoreLicense(kLicenseStateReleasing, nullptr))
|
||||
return RELEASE_KEY_REQUEST_ERROR;
|
||||
return CdmResponseType(RELEASE_KEY_REQUEST_ERROR);
|
||||
} else if (!usage_provider_session_token_.empty()) {
|
||||
if (supports_usage_info()) {
|
||||
if (!UpdateUsageInfo()) return RELEASE_USAGE_INFO_FAILED;
|
||||
if (SupportsUsageTable()) {
|
||||
if (!UpdateUsageInfo()) return CdmResponseType(RELEASE_USAGE_INFO_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
key_request_type_ = key_request->type;
|
||||
license_request_latency_.Start(); // Start or restart timer.
|
||||
|
||||
return KEY_MESSAGE;
|
||||
return CdmResponseType(KEY_MESSAGE);
|
||||
}
|
||||
|
||||
// ReleaseKey() - Accept release response and release license.
|
||||
CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
CdmResponseType sts = license_parser_->HandleKeyUpdateResponse(
|
||||
/* is renewal */ false,
|
||||
@@ -826,19 +847,20 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
|
||||
// Record the timing on success.
|
||||
UpdateRequestLatencyTiming(sts);
|
||||
|
||||
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? RELEASE_KEY_ERROR : sts;
|
||||
if (sts != KEY_ADDED)
|
||||
return (sts == KEY_ERROR) ? CdmResponseType(RELEASE_KEY_ERROR) : sts;
|
||||
|
||||
return RemoveLicense();
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
|
||||
CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_index) {
|
||||
if (!initialized_) {
|
||||
LOGE("CDM session not initialized");
|
||||
return NOT_INITIALIZED_ERROR;
|
||||
return CdmResponseType(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
if (!supports_usage_info()) {
|
||||
if (!SupportsUsageTable()) {
|
||||
LOGE("Cannot delete entry, usage table not supported");
|
||||
return INCORRECT_USAGE_SUPPORT_TYPE_1;
|
||||
return CdmResponseType(INCORRECT_USAGE_SUPPORT_TYPE_1);
|
||||
}
|
||||
|
||||
// The usage entry cannot be deleted if it has a crypto session handling
|
||||
@@ -851,19 +873,19 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
|
||||
crypto_metrics_, crypto_session_open_, sts, requested_security_level_);
|
||||
if (sts != NO_ERROR) return sts;
|
||||
|
||||
usage_table_header_ = nullptr;
|
||||
usage_table_ = nullptr;
|
||||
bool has_support = false;
|
||||
if (crypto_session_->HasUsageInfoSupport(&has_support) && has_support) {
|
||||
usage_table_header_ = crypto_session_->GetUsageTableHeader();
|
||||
if (crypto_session_->HasUsageTableSupport(&has_support) && has_support) {
|
||||
usage_table_ = crypto_session_->GetUsageTable();
|
||||
}
|
||||
|
||||
if (usage_table_header_ == nullptr) {
|
||||
if (usage_table_ == nullptr) {
|
||||
LOGE("Usage table header unavailable");
|
||||
return INCORRECT_USAGE_SUPPORT_TYPE_1;
|
||||
return CdmResponseType(INCORRECT_USAGE_SUPPORT_TYPE_1);
|
||||
}
|
||||
|
||||
sts = usage_table_header_->InvalidateEntry(
|
||||
usage_entry_number, true, file_handle_.get(), crypto_metrics_);
|
||||
sts = usage_table_->InvalidateEntry(usage_entry_index, true,
|
||||
file_handle_.get(), crypto_metrics_);
|
||||
crypto_metrics_->usage_table_header_delete_entry_.Increment(sts);
|
||||
return sts;
|
||||
}
|
||||
@@ -886,15 +908,14 @@ bool CdmSession::GenerateKeySetId(bool atsc_mode_enabled,
|
||||
CdmKeySetId* key_set_id) {
|
||||
RETURN_FALSE_IF_NULL(key_set_id);
|
||||
|
||||
std::vector<uint8_t> random_data(
|
||||
(kKeySetIdLength - sizeof(KEY_SET_ID_PREFIX)) / 2, 0);
|
||||
|
||||
while (key_set_id->empty()) {
|
||||
if (crypto_session_->GetRandom(random_data.size(), &random_data[0]) !=
|
||||
NO_ERROR) {
|
||||
constexpr size_t random_size =
|
||||
(kKeySetIdLength - sizeof(KEY_SET_ID_PREFIX)) / 2;
|
||||
std::string random_data = wvutil::CdmRandom::RandomData(random_size);
|
||||
if (random_data.size() != random_size) {
|
||||
LOGE("Error generating random id.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (atsc_mode_enabled)
|
||||
*key_set_id = ATSC_KEY_SET_ID_PREFIX + wvutil::b2a_hex(random_data);
|
||||
else
|
||||
@@ -913,32 +934,32 @@ bool CdmSession::GenerateKeySetId(bool atsc_mode_enabled,
|
||||
CdmResponseType CdmSession::StoreLicense() {
|
||||
if (is_temporary_) {
|
||||
LOGE("Session type prohibits storage");
|
||||
return STORAGE_PROHIBITED;
|
||||
return CdmResponseType(STORAGE_PROHIBITED);
|
||||
}
|
||||
|
||||
if (is_offline_) {
|
||||
if (key_set_id_.empty()) {
|
||||
LOGE("No key set ID");
|
||||
return EMPTY_KEYSET_ID;
|
||||
return CdmResponseType(EMPTY_KEYSET_ID);
|
||||
}
|
||||
|
||||
if (!license_parser_->is_offline()) {
|
||||
LOGE("License policy prohibits storage");
|
||||
return OFFLINE_LICENSE_PROHIBITED;
|
||||
return CdmResponseType(OFFLINE_LICENSE_PROHIBITED);
|
||||
}
|
||||
|
||||
if (!StoreLicense(kLicenseStateActive, nullptr)) {
|
||||
LOGE("Unable to store license");
|
||||
return STORE_LICENSE_ERROR_1;
|
||||
return CdmResponseType(STORE_LICENSE_ERROR_1);
|
||||
}
|
||||
return NO_ERROR;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
} // if (is_offline_)
|
||||
|
||||
std::string provider_session_token =
|
||||
license_parser_->provider_session_token();
|
||||
if (provider_session_token.empty()) {
|
||||
LOGE("No provider session token and not offline");
|
||||
return STORE_LICENSE_ERROR_2;
|
||||
return CdmResponseType(STORE_LICENSE_ERROR_2);
|
||||
}
|
||||
|
||||
std::string app_id;
|
||||
@@ -946,11 +967,11 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
if (!file_handle_->StoreUsageInfo(
|
||||
provider_session_token, key_request_, key_response_,
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), key_set_id_, usage_entry_,
|
||||
usage_entry_number_, drm_certificate_, wrapped_private_key_)) {
|
||||
usage_entry_index_, drm_certificate_, wrapped_private_key_)) {
|
||||
LOGE("Unable to store usage info");
|
||||
// Usage info file is corrupt. Delete current usage entry and file.
|
||||
if (supports_usage_info()) {
|
||||
DeleteUsageEntry(usage_entry_number_);
|
||||
if (SupportsUsageTable()) {
|
||||
DeleteUsageEntry(usage_entry_index_);
|
||||
} else {
|
||||
LOGW("Cannot store, usage table not supported");
|
||||
}
|
||||
@@ -958,9 +979,9 @@ CdmResponseType CdmSession::StoreLicense() {
|
||||
file_handle_->DeleteAllUsageInfoForApp(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), &provider_session_tokens);
|
||||
|
||||
return STORE_USAGE_INFO_ERROR;
|
||||
return CdmResponseType(STORE_USAGE_INFO_ERROR);
|
||||
}
|
||||
return NO_ERROR;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
bool CdmSession::StoreLicense(CdmOfflineLicenseState state, int* error_detail) {
|
||||
@@ -979,7 +1000,7 @@ bool CdmSession::StoreLicense(CdmOfflineLicenseState state, int* error_detail) {
|
||||
policy_engine_->GetGracePeriodEndTime(),
|
||||
app_parameters_,
|
||||
usage_entry_,
|
||||
usage_entry_number_,
|
||||
usage_entry_index_,
|
||||
drm_certificate_,
|
||||
wrapped_private_key_};
|
||||
|
||||
@@ -998,17 +1019,17 @@ CdmResponseType CdmSession::RemoveKeys() {
|
||||
crypto_metrics_, crypto_session_open_, sts, requested_security_level_);
|
||||
policy_engine_.reset(
|
||||
new PolicyEngine(session_id_, nullptr, crypto_session_.get()));
|
||||
return NO_ERROR;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::RemoveLicense() {
|
||||
if (is_offline_ || has_provider_session_token()) {
|
||||
if (has_provider_session_token() && supports_usage_info()) {
|
||||
DeleteUsageEntry(usage_entry_number_);
|
||||
if (has_provider_session_token() && SupportsUsageTable()) {
|
||||
DeleteUsageEntry(usage_entry_index_);
|
||||
}
|
||||
DeleteLicenseFile();
|
||||
}
|
||||
return NO_ERROR;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
bool CdmSession::DeleteLicenseFile() {
|
||||
@@ -1052,19 +1073,19 @@ void CdmSession::GetApplicationId(std::string* app_id) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::UpdateUsageEntryInformation() {
|
||||
if (!has_provider_session_token() || !supports_usage_info()) {
|
||||
if (!has_provider_session_token() || !SupportsUsageTable()) {
|
||||
LOGE("Unexpected state: usage_support = %s, PST present = %s, ",
|
||||
supports_usage_info() ? "true" : "false",
|
||||
SupportsUsageTable() ? "true" : "false",
|
||||
has_provider_session_token() ? "yes" : "no");
|
||||
return INCORRECT_USAGE_SUPPORT_TYPE_2;
|
||||
return CdmResponseType(INCORRECT_USAGE_SUPPORT_TYPE_2);
|
||||
}
|
||||
|
||||
CdmResponseType sts = NO_ERROR;
|
||||
CdmResponseType sts(NO_ERROR);
|
||||
// TODO(blueeyes): Add measurements to all UpdateEntry calls in a way that
|
||||
// allos us to isolate this particular use case within
|
||||
// UpdateUsageEntryInformation.
|
||||
M_TIME(sts = usage_table_header_->UpdateEntry(
|
||||
usage_entry_number_, crypto_session_.get(), &usage_entry_),
|
||||
M_TIME(sts = usage_table_->UpdateEntry(usage_entry_index_,
|
||||
crypto_session_.get(), &usage_entry_),
|
||||
crypto_metrics_, usage_table_header_update_entry_, sts);
|
||||
|
||||
if (sts != NO_ERROR) return sts;
|
||||
@@ -1075,7 +1096,7 @@ CdmResponseType CdmSession::UpdateUsageEntryInformation() {
|
||||
else if (!usage_provider_session_token_.empty())
|
||||
UpdateUsageInfo();
|
||||
|
||||
return NO_ERROR;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer,
|
||||
@@ -1150,7 +1171,7 @@ bool CdmSession::UpdateUsageInfo() {
|
||||
usage_data.license = key_response_;
|
||||
usage_data.key_set_id = key_set_id_;
|
||||
usage_data.usage_entry = usage_entry_;
|
||||
usage_data.usage_entry_number = usage_entry_number_;
|
||||
usage_data.usage_entry_index = usage_entry_index_;
|
||||
|
||||
return file_handle_->UpdateUsageInfo(
|
||||
DeviceFiles::GetUsageInfoFileName(app_id), usage_data);
|
||||
@@ -1168,15 +1189,15 @@ bool CdmSession::VerifyOfflineUsageEntry() {
|
||||
// Check that the current license is the same as the expected
|
||||
// entry in the usage table. It is possible that the license has
|
||||
// been removed from the usage table but the license file remains.
|
||||
if (usage_entry_number_ >= usage_table_header_->size()) {
|
||||
LOGD("License usage entry does not exist: entry_number = %u, size = %zu",
|
||||
usage_entry_number_, usage_table_header_->size());
|
||||
if (usage_entry_index_ >= usage_table_->size()) {
|
||||
LOGD("License usage entry does not exist: entry_index = %u, size = %zu",
|
||||
usage_entry_index_, usage_table_->size());
|
||||
return false;
|
||||
}
|
||||
const CdmUsageEntryInfo& usage_entry_info =
|
||||
usage_table_header_->usage_entry_info().at(usage_entry_number_);
|
||||
if (usage_entry_info.storage_type != kStorageLicense ||
|
||||
usage_entry_info.key_set_id != key_set_id_) {
|
||||
const CdmUsageEntryInfo& entry_info =
|
||||
usage_table_->entry_info_list().at(usage_entry_index_);
|
||||
if (entry_info.storage_type != kStorageLicense ||
|
||||
entry_info.key_set_id != key_set_id_) {
|
||||
LOGD("License usage entry does not match");
|
||||
return false;
|
||||
}
|
||||
@@ -1191,7 +1212,7 @@ CdmResponseType CdmSession::LoadPrivateKey() {
|
||||
if (file_handle_->RetrieveCertificate(atsc_mode_enabled_, &drm_certificate,
|
||||
&private_key, nullptr, &system_id) !=
|
||||
DeviceFiles::kCertificateValid) {
|
||||
return NEED_PROVISIONING;
|
||||
return CdmResponseType(NEED_PROVISIONING);
|
||||
}
|
||||
|
||||
return LoadPrivateKey(drm_certificate, private_key);
|
||||
@@ -1209,7 +1230,7 @@ CdmResponseType CdmSession::LoadPrivateOrLegacyKey(
|
||||
if (file_handle_->RetrieveLegacyCertificate(
|
||||
&drm_certificate, &wrapped_private_key, nullptr, nullptr) !=
|
||||
DeviceFiles::kCertificateValid)
|
||||
return NEED_PROVISIONING;
|
||||
return CdmResponseType(NEED_PROVISIONING);
|
||||
|
||||
return LoadPrivateKey(drm_certificate, wrapped_private_key);
|
||||
}
|
||||
@@ -1222,22 +1243,65 @@ CdmResponseType CdmSession::LoadPrivateKey(
|
||||
crypto_metrics_, crypto_session_load_certificate_private_key_,
|
||||
load_cert_sts);
|
||||
|
||||
switch (load_cert_sts) {
|
||||
switch (load_cert_sts.code()) {
|
||||
case NO_ERROR:
|
||||
metrics_->drm_certificate_key_type_.Record(
|
||||
DrmKeyTypeToMetricValue(private_key.type()));
|
||||
|
||||
drm_certificate_ = drm_certificate;
|
||||
wrapped_private_key_ = std::move(private_key);
|
||||
return NO_ERROR;
|
||||
wrapped_private_key_ = private_key;
|
||||
return CdmResponseType(NO_ERROR);
|
||||
case SESSION_LOST_STATE_ERROR:
|
||||
case SYSTEM_INVALIDATED_ERROR:
|
||||
return load_cert_sts;
|
||||
default:
|
||||
return NEED_PROVISIONING;
|
||||
return CdmResponseType(NEED_PROVISIONING);
|
||||
}
|
||||
}
|
||||
|
||||
// Use a change in system ID as an indication that Root of Trust
|
||||
// has been renewed.
|
||||
bool CdmSession::HasRootOfTrustBeenRenewed() {
|
||||
if (atsc_mode_enabled_) return false;
|
||||
// Ignore System ID changes for L3 as the root of trust might not have
|
||||
// changed even if the system ID has
|
||||
if (crypto_session_->GetSecurityLevel() == kSecurityLevelL3) return false;
|
||||
|
||||
std::string drm_certificate;
|
||||
CryptoWrappedKey private_key;
|
||||
uint32_t drm_cert_system_id;
|
||||
if (file_handle_->RetrieveCertificate(
|
||||
atsc_mode_enabled_, &drm_certificate, &private_key, nullptr,
|
||||
&drm_cert_system_id) != DeviceFiles::kCertificateValid) {
|
||||
LOGE("Failed to retrieve DRM certificate");
|
||||
return true;
|
||||
}
|
||||
|
||||
wvutil::FileSystem global_file_system;
|
||||
SystemIdExtractor system_id_extractor(kLevelDefault, crypto_session_.get(),
|
||||
&global_file_system);
|
||||
|
||||
SystemIdExtractor* extractor = &system_id_extractor;
|
||||
if (mock_system_id_extractor_) {
|
||||
extractor = mock_system_id_extractor_.get();
|
||||
}
|
||||
|
||||
uint32_t system_id;
|
||||
if (!extractor->ExtractSystemId(&system_id)) {
|
||||
LOGW("ExtractSystemId failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (system_id == drm_cert_system_id) return false;
|
||||
|
||||
LOGI(
|
||||
"System Id changed from %d to %d. Removing certificates and "
|
||||
"reprovisioning",
|
||||
drm_cert_system_id, system_id);
|
||||
file_handle_->RemoveCertificate();
|
||||
return true;
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::LoadCastPrivateKey(
|
||||
const CryptoWrappedKey& private_key) {
|
||||
return crypto_session_->LoadCertificatePrivateKey(private_key);
|
||||
@@ -1269,4 +1333,8 @@ void CdmSession::set_policy_engine(PolicyEngine* policy_engine) {
|
||||
void CdmSession::set_file_handle(DeviceFiles* file_handle) {
|
||||
file_handle_.reset(file_handle);
|
||||
}
|
||||
|
||||
void CdmSession::set_system_id_extractor(SystemIdExtractor* extractor) {
|
||||
mock_system_id_extractor_.reset(extractor);
|
||||
}
|
||||
} // namespace wvcdm
|
||||
|
||||
Reference in New Issue
Block a user