Save and retrieve key information from licenses and usage records am: e538c96131
Original change: https://googleplex-android-review.googlesource.com/c/platform/vendor/widevine/+/13947818 Change-Id: I069e5654eba3be908815406d38e270f6188f86e5
This commit is contained in:
@@ -219,6 +219,19 @@ class CdmSession {
|
|||||||
private:
|
private:
|
||||||
friend class CdmSessionTest;
|
friend class CdmSessionTest;
|
||||||
|
|
||||||
|
// Both these methods will attempt to load wrapped key material and
|
||||||
|
// cache values in |drm_certificate_| and |wrapped_private_key_|
|
||||||
|
// if successful.
|
||||||
|
// This methods will load the key from persistent storage.
|
||||||
|
CdmResponseType LoadPrivateKey();
|
||||||
|
// This method will load the specified key if valid or otherwise load
|
||||||
|
// the information from the legacy certificate.
|
||||||
|
CdmResponseType LoadPrivateOrLegacyKey(
|
||||||
|
const std::string& certificate,
|
||||||
|
const CryptoWrappedKey& wrapped_private_key);
|
||||||
|
|
||||||
|
CdmResponseType LoadPrivateKey(const CryptoWrappedKey& wrapped_private_key);
|
||||||
|
|
||||||
bool GenerateKeySetId(bool atsc_mode_enabled, CdmKeySetId* key_set_id);
|
bool GenerateKeySetId(bool atsc_mode_enabled, CdmKeySetId* key_set_id);
|
||||||
|
|
||||||
CdmResponseType StoreLicense();
|
CdmResponseType StoreLicense();
|
||||||
@@ -273,6 +286,9 @@ class CdmSession {
|
|||||||
CdmSecurityLevel security_level_;
|
CdmSecurityLevel security_level_;
|
||||||
SecurityLevel requested_security_level_;
|
SecurityLevel requested_security_level_;
|
||||||
CdmAppParameterMap app_parameters_;
|
CdmAppParameterMap app_parameters_;
|
||||||
|
bool atsc_mode_enabled_ = false;
|
||||||
|
std::string drm_certificate_;
|
||||||
|
CryptoWrappedKey wrapped_private_key_;
|
||||||
|
|
||||||
// decryption flags
|
// decryption flags
|
||||||
bool is_initial_decryption_;
|
bool is_initial_decryption_;
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ class CdmLicense {
|
|||||||
CdmLicense(const CdmSessionId& session_id);
|
CdmLicense(const CdmSessionId& session_id);
|
||||||
virtual ~CdmLicense();
|
virtual ~CdmLicense();
|
||||||
|
|
||||||
virtual bool Init(const std::string& client_token,
|
virtual bool Init(bool use_privacy_mode,
|
||||||
CdmClientTokenType client_token_type, bool use_privacy_mode,
|
|
||||||
const std::string& signed_service_certificate,
|
const std::string& signed_service_certificate,
|
||||||
CryptoSession* session, PolicyEngine* policy_engine);
|
CryptoSession* session, PolicyEngine* policy_engine);
|
||||||
|
|
||||||
@@ -49,9 +48,9 @@ class CdmLicense {
|
|||||||
const std::string& signed_service_certificate);
|
const std::string& signed_service_certificate);
|
||||||
|
|
||||||
virtual CdmResponseType PrepareKeyRequest(
|
virtual CdmResponseType PrepareKeyRequest(
|
||||||
const InitializationData& init_data, CdmLicenseType license_type,
|
const InitializationData& init_data, const std::string& client_token,
|
||||||
const CdmAppParameterMap& app_parameters, CdmKeyMessage* signed_request,
|
CdmLicenseType license_type, const CdmAppParameterMap& app_parameters,
|
||||||
std::string* server_url);
|
CdmKeyMessage* signed_request, std::string* server_url);
|
||||||
virtual CdmResponseType PrepareKeyUpdateRequest(
|
virtual CdmResponseType PrepareKeyUpdateRequest(
|
||||||
bool is_renewal, const CdmAppParameterMap& app_parameters,
|
bool is_renewal, const CdmAppParameterMap& app_parameters,
|
||||||
CdmSession* cdm_session, CdmKeyMessage* signed_request,
|
CdmSession* cdm_session, CdmKeyMessage* signed_request,
|
||||||
@@ -64,13 +63,13 @@ class CdmLicense {
|
|||||||
const InitializationData& init_data);
|
const InitializationData& init_data);
|
||||||
|
|
||||||
virtual CdmResponseType RestoreOfflineLicense(
|
virtual CdmResponseType RestoreOfflineLicense(
|
||||||
const CdmKeyMessage& license_request,
|
const std::string& client_token, const CdmKeyMessage& license_request,
|
||||||
const CdmKeyResponse& license_response,
|
const CdmKeyResponse& license_response,
|
||||||
const CdmKeyResponse& license_renewal_response,
|
const CdmKeyResponse& license_renewal_response,
|
||||||
int64_t playback_start_time, int64_t last_playback_time,
|
int64_t playback_start_time, int64_t last_playback_time,
|
||||||
int64_t grace_period_end_time, CdmSession* cdm_session);
|
int64_t grace_period_end_time, CdmSession* cdm_session);
|
||||||
virtual CdmResponseType RestoreLicenseForRelease(
|
virtual CdmResponseType RestoreLicenseForRelease(
|
||||||
const CdmKeyMessage& license_request,
|
const std::string& client_token, const CdmKeyMessage& license_request,
|
||||||
const CdmKeyResponse& license_response);
|
const CdmKeyResponse& license_response);
|
||||||
virtual bool HasInitData() { return static_cast<bool>(stored_init_data_); }
|
virtual bool HasInitData() { return static_cast<bool>(stored_init_data_); }
|
||||||
virtual bool IsKeyLoaded(const KeyId& key_id);
|
virtual bool IsKeyLoaded(const KeyId& key_id);
|
||||||
@@ -138,7 +137,6 @@ class CdmLicense {
|
|||||||
PolicyEngine* policy_engine_;
|
PolicyEngine* policy_engine_;
|
||||||
std::string server_url_;
|
std::string server_url_;
|
||||||
std::string client_token_;
|
std::string client_token_;
|
||||||
CdmClientTokenType client_token_type_;
|
|
||||||
const CdmSessionId session_id_;
|
const CdmSessionId session_id_;
|
||||||
std::unique_ptr<InitializationData> stored_init_data_;
|
std::unique_ptr<InitializationData> stored_init_data_;
|
||||||
bool initialized_;
|
bool initialized_;
|
||||||
|
|||||||
@@ -977,7 +977,7 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
|
|||||||
const CdmProvisioningResponse& response,
|
const CdmProvisioningResponse& response,
|
||||||
SecurityLevel requested_security_level, std::string* cert,
|
SecurityLevel requested_security_level, std::string* cert,
|
||||||
std::string* wrapped_key) {
|
std::string* wrapped_key) {
|
||||||
LOGI("Handling provision request");
|
LOGI("Handling provision response");
|
||||||
if (response.empty()) {
|
if (response.empty()) {
|
||||||
LOGE("Empty provisioning response");
|
LOGE("Empty provisioning response");
|
||||||
cert_provisioning_.reset();
|
cert_provisioning_.reset();
|
||||||
|
|||||||
@@ -169,56 +169,16 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
|
|||||||
usage_support_type_ = kNonSecureUsageSupport;
|
usage_support_type_ = kNonSecureUsageSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Device Provisioning state is not yet known.
|
|
||||||
// If not using certificates, then Keybox is client token for license
|
|
||||||
// requests.
|
|
||||||
// Otherwise, try to fetch device certificate. If not successful and
|
|
||||||
// provisioning is supported, return NEED_PROVISIONING. Otherwise, return
|
|
||||||
// an error.
|
|
||||||
// client_token and client_token_type are determined here; they are needed
|
|
||||||
// to initialize the license parser.
|
|
||||||
std::string client_token;
|
|
||||||
std::string serial_number;
|
|
||||||
CdmClientTokenType client_token_type =
|
|
||||||
crypto_session_->GetPreProvisionTokenType();
|
|
||||||
|
|
||||||
// License server client ID token is a stored certificate. Stage it or
|
|
||||||
// indicate that provisioning is needed. Get token from stored certificate
|
|
||||||
CryptoWrappedKey private_key;
|
|
||||||
bool atsc_mode_enabled = false;
|
|
||||||
if (cdm_client_property_set != nullptr)
|
if (cdm_client_property_set != nullptr)
|
||||||
atsc_mode_enabled = cdm_client_property_set->use_atsc_mode();
|
atsc_mode_enabled_ = cdm_client_property_set->use_atsc_mode();
|
||||||
if (file_handle_->RetrieveCertificate(
|
|
||||||
atsc_mode_enabled, &client_token, &private_key, &serial_number,
|
if (!file_handle_->HasCertificate(atsc_mode_enabled_))
|
||||||
nullptr) != DeviceFiles::kCertificateValid) {
|
|
||||||
return NEED_PROVISIONING;
|
return NEED_PROVISIONING;
|
||||||
}
|
|
||||||
CdmResponseType load_cert_sts;
|
|
||||||
M_TIME(
|
|
||||||
load_cert_sts = crypto_session_->LoadCertificatePrivateKey(private_key),
|
|
||||||
crypto_metrics_, crypto_session_load_certificate_private_key_,
|
|
||||||
load_cert_sts);
|
|
||||||
switch (load_cert_sts) {
|
|
||||||
case NO_ERROR:
|
|
||||||
metrics_->drm_certificate_key_type_.Record(
|
|
||||||
DrmKeyTypeToMetricValue(private_key.type()));
|
|
||||||
break;
|
|
||||||
case SESSION_LOST_STATE_ERROR:
|
|
||||||
case SYSTEM_INVALIDATED_ERROR:
|
|
||||||
return load_cert_sts;
|
|
||||||
default:
|
|
||||||
return NEED_PROVISIONING;
|
|
||||||
}
|
|
||||||
|
|
||||||
client_token_type = kClientTokenDrmCert;
|
|
||||||
|
|
||||||
// Session is provisioned with certificate needed to construct
|
|
||||||
// license request (or with keybox).
|
|
||||||
|
|
||||||
if (forced_session_id) {
|
if (forced_session_id) {
|
||||||
key_set_id_ = *forced_session_id;
|
key_set_id_ = *forced_session_id;
|
||||||
} else {
|
} else {
|
||||||
const bool ok = GenerateKeySetId(atsc_mode_enabled, &key_set_id_);
|
const bool ok = GenerateKeySetId(atsc_mode_enabled_, &key_set_id_);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
// Assertions may be disabled
|
// Assertions may be disabled
|
||||||
@@ -247,8 +207,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
|
|||||||
if (!Properties::GetServiceCertificate(session_id_, &service_certificate))
|
if (!Properties::GetServiceCertificate(session_id_, &service_certificate))
|
||||||
service_certificate.clear();
|
service_certificate.clear();
|
||||||
|
|
||||||
if (!license_parser_->Init(client_token, client_token_type,
|
if (!license_parser_->Init(Properties::UsePrivacyMode(session_id_),
|
||||||
Properties::UsePrivacyMode(session_id_),
|
|
||||||
service_certificate, crypto_session_.get(),
|
service_certificate, crypto_session_.get(),
|
||||||
policy_engine_.get()))
|
policy_engine_.get()))
|
||||||
return LICENSE_PARSER_INIT_ERROR;
|
return LICENSE_PARSER_INIT_ERROR;
|
||||||
@@ -337,6 +296,10 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
|||||||
usage_entry_ = std::move(license_data.usage_entry);
|
usage_entry_ = std::move(license_data.usage_entry);
|
||||||
usage_entry_number_ = license_data.usage_entry_number;
|
usage_entry_number_ = license_data.usage_entry_number;
|
||||||
|
|
||||||
|
CdmResponseType status = LoadPrivateOrLegacyKey(
|
||||||
|
license_data.drm_certificate, license_data.wrapped_private_key);
|
||||||
|
if (status != NO_ERROR) return status;
|
||||||
|
|
||||||
// Attempts to restore a released offline license are treated as a release
|
// Attempts to restore a released offline license are treated as a release
|
||||||
// retry.
|
// retry.
|
||||||
if (Properties::allow_restore_of_offline_licenses_with_release()) {
|
if (Properties::allow_restore_of_offline_licenses_with_release()) {
|
||||||
@@ -396,8 +359,8 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
|||||||
|
|
||||||
CdmResponseType result;
|
CdmResponseType result;
|
||||||
if (license_type == kLicenseTypeRelease) {
|
if (license_type == kLicenseTypeRelease) {
|
||||||
result =
|
result = license_parser_->RestoreLicenseForRelease(
|
||||||
license_parser_->RestoreLicenseForRelease(key_request_, key_response_);
|
license_data.drm_certificate, key_request_, key_response_);
|
||||||
|
|
||||||
if (result != NO_ERROR) {
|
if (result != NO_ERROR) {
|
||||||
SetErrorDetail(error_detail, result);
|
SetErrorDetail(error_detail, result);
|
||||||
@@ -405,9 +368,10 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = license_parser_->RestoreOfflineLicense(
|
result = license_parser_->RestoreOfflineLicense(
|
||||||
key_request_, key_response_, offline_key_renewal_response_,
|
license_data.drm_certificate, key_request_, key_response_,
|
||||||
license_data.playback_start_time, license_data.last_playback_time,
|
offline_key_renewal_response_, license_data.playback_start_time,
|
||||||
license_data.grace_period_end_time, this);
|
license_data.last_playback_time, license_data.grace_period_end_time,
|
||||||
|
this);
|
||||||
if (result != NO_ERROR) {
|
if (result != NO_ERROR) {
|
||||||
SetErrorDetail(error_detail, result);
|
SetErrorDetail(error_detail, result);
|
||||||
return RESTORE_OFFLINE_LICENSE_ERROR_2;
|
return RESTORE_OFFLINE_LICENSE_ERROR_2;
|
||||||
@@ -449,6 +413,10 @@ CdmResponseType CdmSession::RestoreUsageSession(
|
|||||||
usage_entry_number_ = usage_data.usage_entry_number;
|
usage_entry_number_ = usage_data.usage_entry_number;
|
||||||
usage_provider_session_token_ = usage_data.provider_session_token;
|
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;
|
CdmResponseType sts = NO_ERROR;
|
||||||
if (usage_support_type_ == kUsageEntrySupport &&
|
if (usage_support_type_ == kUsageEntrySupport &&
|
||||||
usage_table_header_ != nullptr) {
|
usage_table_header_ != nullptr) {
|
||||||
@@ -461,7 +429,8 @@ CdmResponseType CdmSession::RestoreUsageSession(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sts = license_parser_->RestoreLicenseForRelease(key_request_, key_response_);
|
sts = license_parser_->RestoreLicenseForRelease(usage_data.drm_certificate,
|
||||||
|
key_request_, key_response_);
|
||||||
|
|
||||||
if (sts != NO_ERROR) {
|
if (sts != NO_ERROR) {
|
||||||
SetErrorDetail(error_detail, sts);
|
SetErrorDetail(error_detail, sts);
|
||||||
@@ -568,10 +537,13 @@ CdmResponseType CdmSession::GenerateKeyRequestInternal(
|
|||||||
return KEY_REQUEST_ERROR_1;
|
return KEY_REQUEST_ERROR_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CdmResponseType status = LoadPrivateKey();
|
||||||
|
if (status != NO_ERROR) return status;
|
||||||
|
|
||||||
app_parameters_ = app_parameters;
|
app_parameters_ = app_parameters;
|
||||||
CdmResponseType status = license_parser_->PrepareKeyRequest(
|
status = license_parser_->PrepareKeyRequest(
|
||||||
init_data, license_type, app_parameters, &key_request->message,
|
init_data, drm_certificate_, license_type, app_parameters,
|
||||||
&key_request->url);
|
&key_request->message, &key_request->url);
|
||||||
if (status != KEY_MESSAGE) return status;
|
if (status != KEY_MESSAGE) return status;
|
||||||
|
|
||||||
key_request_ = key_request->message;
|
key_request_ = key_request->message;
|
||||||
@@ -1018,12 +990,10 @@ CdmResponseType CdmSession::StoreLicense() {
|
|||||||
|
|
||||||
std::string app_id;
|
std::string app_id;
|
||||||
GetApplicationId(&app_id);
|
GetApplicationId(&app_id);
|
||||||
std::string drm_certificate;
|
|
||||||
CryptoWrappedKey wrapped_private_key;
|
|
||||||
if (!file_handle_->StoreUsageInfo(
|
if (!file_handle_->StoreUsageInfo(
|
||||||
provider_session_token, key_request_, key_response_,
|
provider_session_token, key_request_, key_response_,
|
||||||
DeviceFiles::GetUsageInfoFileName(app_id), key_set_id_, usage_entry_,
|
DeviceFiles::GetUsageInfoFileName(app_id), key_set_id_, usage_entry_,
|
||||||
usage_entry_number_, drm_certificate, wrapped_private_key)) {
|
usage_entry_number_, drm_certificate_, wrapped_private_key_)) {
|
||||||
LOGE("Unable to store usage info");
|
LOGE("Unable to store usage info");
|
||||||
// Usage info file is corrupt. Delete current usage entry and file.
|
// Usage info file is corrupt. Delete current usage entry and file.
|
||||||
if (usage_support_type_ == kUsageEntrySupport) {
|
if (usage_support_type_ == kUsageEntrySupport) {
|
||||||
@@ -1044,7 +1014,6 @@ CdmResponseType CdmSession::StoreLicense() {
|
|||||||
bool CdmSession::StoreLicense(DeviceFiles::LicenseState state,
|
bool CdmSession::StoreLicense(DeviceFiles::LicenseState state,
|
||||||
int* error_detail) {
|
int* error_detail) {
|
||||||
DeviceFiles::ResponseType error_detail_alt = DeviceFiles::kNoError;
|
DeviceFiles::ResponseType error_detail_alt = DeviceFiles::kNoError;
|
||||||
std::string drm_certificate;
|
|
||||||
DeviceFiles::CdmLicenseData license_data{
|
DeviceFiles::CdmLicenseData license_data{
|
||||||
key_set_id_,
|
key_set_id_,
|
||||||
state,
|
state,
|
||||||
@@ -1060,8 +1029,8 @@ bool CdmSession::StoreLicense(DeviceFiles::LicenseState state,
|
|||||||
app_parameters_,
|
app_parameters_,
|
||||||
usage_entry_,
|
usage_entry_,
|
||||||
usage_entry_number_,
|
usage_entry_number_,
|
||||||
drm_certificate,
|
drm_certificate_,
|
||||||
CryptoWrappedKey()};
|
wrapped_private_key_};
|
||||||
|
|
||||||
bool result = file_handle_->StoreLicense(license_data, &error_detail_alt);
|
bool result = file_handle_->StoreLicense(license_data, &error_detail_alt);
|
||||||
if (error_detail != nullptr) {
|
if (error_detail != nullptr) {
|
||||||
@@ -1271,6 +1240,83 @@ bool CdmSession::VerifyOfflineUsageEntry() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CdmResponseType CdmSession::LoadPrivateKey() {
|
||||||
|
std::string drm_certificate;
|
||||||
|
CryptoWrappedKey private_key;
|
||||||
|
uint32_t system_id;
|
||||||
|
|
||||||
|
if (file_handle_->RetrieveCertificate(atsc_mode_enabled_, &drm_certificate,
|
||||||
|
&private_key, nullptr, &system_id) !=
|
||||||
|
DeviceFiles::kCertificateValid) {
|
||||||
|
return NEED_PROVISIONING;
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmResponseType status = LoadPrivateKey(private_key);
|
||||||
|
|
||||||
|
if (status == NO_ERROR) {
|
||||||
|
drm_certificate_ = drm_certificate;
|
||||||
|
wrapped_private_key_.set_type(private_key.type());
|
||||||
|
wrapped_private_key_.set_key(private_key.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmResponseType CdmSession::LoadPrivateOrLegacyKey(
|
||||||
|
const std::string& certificate, const CryptoWrappedKey& private_key) {
|
||||||
|
// Use provided key if valid
|
||||||
|
if (!certificate.empty() && private_key.IsValid()) {
|
||||||
|
CdmResponseType status = LoadPrivateKey(private_key);
|
||||||
|
|
||||||
|
if (status == NO_ERROR) {
|
||||||
|
drm_certificate_ = certificate;
|
||||||
|
wrapped_private_key_.set_type(private_key.type());
|
||||||
|
wrapped_private_key_.set_key(private_key.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise use key from legacy certificate
|
||||||
|
std::string drm_certificate;
|
||||||
|
CryptoWrappedKey wrapped_private_key;
|
||||||
|
if (file_handle_->RetrieveLegacyCertificate(
|
||||||
|
&drm_certificate, &wrapped_private_key, nullptr, nullptr) !=
|
||||||
|
DeviceFiles::kCertificateValid)
|
||||||
|
return NEED_PROVISIONING;
|
||||||
|
|
||||||
|
CdmResponseType status = LoadPrivateKey(wrapped_private_key);
|
||||||
|
|
||||||
|
if (status == NO_ERROR) {
|
||||||
|
drm_certificate_ = drm_certificate;
|
||||||
|
wrapped_private_key_.set_type(wrapped_private_key.type());
|
||||||
|
wrapped_private_key_.set_key(wrapped_private_key.key());
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmResponseType CdmSession::LoadPrivateKey(
|
||||||
|
const CryptoWrappedKey& private_key) {
|
||||||
|
CdmResponseType load_cert_sts;
|
||||||
|
M_TIME(
|
||||||
|
load_cert_sts = crypto_session_->LoadCertificatePrivateKey(private_key),
|
||||||
|
crypto_metrics_, crypto_session_load_certificate_private_key_,
|
||||||
|
load_cert_sts);
|
||||||
|
|
||||||
|
switch (load_cert_sts) {
|
||||||
|
case NO_ERROR:
|
||||||
|
metrics_->drm_certificate_key_type_.Record(
|
||||||
|
DrmKeyTypeToMetricValue(private_key.type()));
|
||||||
|
return NO_ERROR;
|
||||||
|
case SESSION_LOST_STATE_ERROR:
|
||||||
|
case SYSTEM_INVALIDATED_ERROR:
|
||||||
|
return load_cert_sts;
|
||||||
|
default:
|
||||||
|
return NEED_PROVISIONING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For testing only - takes ownership of pointers
|
// For testing only - takes ownership of pointers
|
||||||
|
|
||||||
void CdmSession::set_license_parser(CdmLicense* license_parser) {
|
void CdmSession::set_license_parser(CdmLicense* license_parser) {
|
||||||
|
|||||||
@@ -200,9 +200,7 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id, Clock* clock)
|
|||||||
|
|
||||||
CdmLicense::~CdmLicense() {}
|
CdmLicense::~CdmLicense() {}
|
||||||
|
|
||||||
bool CdmLicense::Init(const std::string& client_token,
|
bool CdmLicense::Init(bool use_privacy_mode,
|
||||||
CdmClientTokenType client_token_type,
|
|
||||||
bool use_privacy_mode,
|
|
||||||
const std::string& signed_service_certificate,
|
const std::string& signed_service_certificate,
|
||||||
CryptoSession* session, PolicyEngine* policy_engine) {
|
CryptoSession* session, PolicyEngine* policy_engine) {
|
||||||
if (!clock_) {
|
if (!clock_) {
|
||||||
@@ -213,10 +211,6 @@ bool CdmLicense::Init(const std::string& client_token,
|
|||||||
LOGE("Session ID not provided");
|
LOGE("Session ID not provided");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (client_token.size() == 0) {
|
|
||||||
LOGE("Client token not provided");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (session == nullptr || !session->IsOpen()) {
|
if (session == nullptr || !session->IsOpen()) {
|
||||||
LOGE("Crypto session not provided or not open");
|
LOGE("Crypto session not provided or not open");
|
||||||
return false;
|
return false;
|
||||||
@@ -231,8 +225,6 @@ bool CdmLicense::Init(const std::string& client_token,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
client_token_ = client_token;
|
|
||||||
client_token_type_ = client_token_type;
|
|
||||||
crypto_session_ = session;
|
crypto_session_ = session;
|
||||||
policy_engine_ = policy_engine;
|
policy_engine_ = policy_engine;
|
||||||
use_privacy_mode_ = use_privacy_mode;
|
use_privacy_mode_ = use_privacy_mode;
|
||||||
@@ -247,18 +239,19 @@ CdmResponseType CdmLicense::SetServiceCertificate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmLicense::PrepareKeyRequest(
|
CdmResponseType CdmLicense::PrepareKeyRequest(
|
||||||
const InitializationData& init_data, CdmLicenseType license_type,
|
const InitializationData& init_data, const std::string& client_token,
|
||||||
const CdmAppParameterMap& app_parameters, CdmKeyMessage* signed_request,
|
CdmLicenseType license_type, const CdmAppParameterMap& app_parameters,
|
||||||
std::string* server_url) {
|
CdmKeyMessage* signed_request, std::string* server_url) {
|
||||||
if (!initialized_) {
|
if (!initialized_) {
|
||||||
LOGE("CdmLicense not initialized");
|
LOGE("CdmLicense not initialized");
|
||||||
return LICENSE_PARSER_NOT_INITIALIZED_4;
|
return LICENSE_PARSER_NOT_INITIALIZED_4;
|
||||||
}
|
}
|
||||||
|
client_token_ = client_token;
|
||||||
if (init_data.IsEmpty() && stored_init_data_) {
|
if (init_data.IsEmpty() && stored_init_data_) {
|
||||||
InitializationData restored_init_data = *stored_init_data_;
|
InitializationData restored_init_data = *stored_init_data_;
|
||||||
stored_init_data_.reset();
|
stored_init_data_.reset();
|
||||||
return PrepareKeyRequest(restored_init_data, license_type, app_parameters,
|
return PrepareKeyRequest(restored_init_data, client_token, license_type,
|
||||||
signed_request, server_url);
|
app_parameters, signed_request, server_url);
|
||||||
}
|
}
|
||||||
wrapped_keys_ = init_data.ExtractWrappedKeys();
|
wrapped_keys_ = init_data.ExtractWrappedKeys();
|
||||||
if (!init_data.is_supported()) {
|
if (!init_data.is_supported()) {
|
||||||
@@ -793,7 +786,7 @@ CdmResponseType CdmLicense::HandleEmbeddedKeyData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmLicense::RestoreOfflineLicense(
|
CdmResponseType CdmLicense::RestoreOfflineLicense(
|
||||||
const CdmKeyMessage& license_request,
|
const std::string& client_token, const CdmKeyMessage& license_request,
|
||||||
const CdmKeyResponse& license_response,
|
const CdmKeyResponse& license_response,
|
||||||
const CdmKeyResponse& license_renewal_response, int64_t playback_start_time,
|
const CdmKeyResponse& license_renewal_response, int64_t playback_start_time,
|
||||||
int64_t last_playback_time, int64_t grace_period_end_time,
|
int64_t last_playback_time, int64_t grace_period_end_time,
|
||||||
@@ -808,6 +801,8 @@ CdmResponseType CdmLicense::RestoreOfflineLicense(
|
|||||||
return EMPTY_LICENSE_RESPONSE_3;
|
return EMPTY_LICENSE_RESPONSE_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client_token_ = client_token;
|
||||||
|
|
||||||
SignedMessage signed_request;
|
SignedMessage signed_request;
|
||||||
if (!signed_request.ParseFromString(license_request)) {
|
if (!signed_request.ParseFromString(license_request)) {
|
||||||
LOGE("Failed to parse license request");
|
LOGE("Failed to parse license request");
|
||||||
@@ -889,7 +884,7 @@ CdmResponseType CdmLicense::RestoreOfflineLicense(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmLicense::RestoreLicenseForRelease(
|
CdmResponseType CdmLicense::RestoreLicenseForRelease(
|
||||||
const CdmKeyMessage& license_request,
|
const std::string& client_token, const CdmKeyMessage& license_request,
|
||||||
const CdmKeyResponse& license_response) {
|
const CdmKeyResponse& license_response) {
|
||||||
if (license_request.empty()) {
|
if (license_request.empty()) {
|
||||||
LOGE("License request is empty");
|
LOGE("License request is empty");
|
||||||
@@ -901,6 +896,8 @@ CdmResponseType CdmLicense::RestoreLicenseForRelease(
|
|||||||
return EMPTY_LICENSE_RESPONSE_4;
|
return EMPTY_LICENSE_RESPONSE_4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client_token_ = client_token;
|
||||||
|
|
||||||
SignedMessage signed_request;
|
SignedMessage signed_request;
|
||||||
if (!signed_request.ParseFromString(license_request)) {
|
if (!signed_request.ParseFromString(license_request)) {
|
||||||
LOGE("Failed to parse signed license request");
|
LOGE("Failed to parse signed license request");
|
||||||
@@ -1046,6 +1043,11 @@ CdmResponseType CdmLicense::PrepareClientId(
|
|||||||
const CdmAppParameterMap& app_parameters,
|
const CdmAppParameterMap& app_parameters,
|
||||||
const std::string& provider_client_token, LicenseRequest* license_request) {
|
const std::string& provider_client_token, LicenseRequest* license_request) {
|
||||||
wvcdm::ClientIdentification id;
|
wvcdm::ClientIdentification id;
|
||||||
|
if (client_token_.empty()) {
|
||||||
|
LOGE("Client token not set when preparing client ID");
|
||||||
|
return CLIENT_TOKEN_NOT_SET;
|
||||||
|
}
|
||||||
|
|
||||||
CdmResponseType status = id.Init(client_token_, crypto_session_);
|
CdmResponseType status = id.Init(client_token_, crypto_session_);
|
||||||
if (status != NO_ERROR) return status;
|
if (status != NO_ERROR) return status;
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ class MockDeviceFiles : public DeviceFiles {
|
|||||||
DeviceFiles::CertificateState(bool, std::string*,
|
DeviceFiles::CertificateState(bool, std::string*,
|
||||||
CryptoWrappedKey*, std::string*,
|
CryptoWrappedKey*, std::string*,
|
||||||
uint32_t*));
|
uint32_t*));
|
||||||
|
MOCK_METHOD1(HasCertificate, bool(bool));
|
||||||
};
|
};
|
||||||
|
|
||||||
class MockUsageTableHeader : public UsageTableHeader {
|
class MockUsageTableHeader : public UsageTableHeader {
|
||||||
@@ -169,8 +170,8 @@ class MockCdmLicense : public CdmLicense {
|
|||||||
public:
|
public:
|
||||||
MockCdmLicense(const CdmSessionId& session_id) : CdmLicense(session_id) {}
|
MockCdmLicense(const CdmSessionId& session_id) : CdmLicense(session_id) {}
|
||||||
|
|
||||||
MOCK_METHOD6(Init, bool(const std::string&, CdmClientTokenType, bool,
|
MOCK_METHOD4(Init,
|
||||||
const std::string&, CryptoSession*, PolicyEngine*));
|
bool(bool, const std::string&, CryptoSession*, PolicyEngine*));
|
||||||
MOCK_METHOD0(provider_session_token, std::string());
|
MOCK_METHOD0(provider_session_token, std::string());
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -218,19 +219,10 @@ TEST_F(CdmSessionTest, InitWithBuiltInCertificate) {
|
|||||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
||||||
.InSequence(crypto_session_seq)
|
.InSequence(crypto_session_seq)
|
||||||
.WillOnce(Return(level));
|
.WillOnce(Return(level));
|
||||||
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
|
|
||||||
.WillOnce(Return(kClientTokenDrmCert));
|
|
||||||
EXPECT_CALL(*file_handle_,
|
|
||||||
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
|
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
|
|
||||||
Return(DeviceFiles::kCertificateValid)));
|
|
||||||
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey))
|
|
||||||
.InSequence(crypto_session_seq)
|
|
||||||
.WillOnce(Return(NO_ERROR));
|
|
||||||
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||||
EXPECT_CALL(*license_parser_,
|
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
|
||||||
Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString),
|
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
|
||||||
Eq(crypto_session_), Eq(policy_engine_)))
|
Eq(crypto_session_), Eq(policy_engine_)))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
|
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
|
||||||
@@ -245,19 +237,10 @@ TEST_F(CdmSessionTest, InitWithCertificate) {
|
|||||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
||||||
.InSequence(crypto_session_seq)
|
.InSequence(crypto_session_seq)
|
||||||
.WillOnce(Return(level));
|
.WillOnce(Return(level));
|
||||||
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
|
|
||||||
.WillOnce(Return(kClientTokenKeybox));
|
|
||||||
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||||
EXPECT_CALL(*file_handle_,
|
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
|
||||||
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
|
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
|
Eq(crypto_session_), Eq(policy_engine_)))
|
||||||
Return(DeviceFiles::kCertificateValid)));
|
|
||||||
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey))
|
|
||||||
.InSequence(crypto_session_seq)
|
|
||||||
.WillOnce(Return(NO_ERROR));
|
|
||||||
EXPECT_CALL(*license_parser_,
|
|
||||||
Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString),
|
|
||||||
Eq(crypto_session_), Eq(policy_engine_)))
|
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
|
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
|
||||||
@@ -272,19 +255,10 @@ TEST_F(CdmSessionTest, ReInitFail) {
|
|||||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
||||||
.InSequence(crypto_session_seq)
|
.InSequence(crypto_session_seq)
|
||||||
.WillOnce(Return(level));
|
.WillOnce(Return(level));
|
||||||
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
|
|
||||||
.WillOnce(Return(kClientTokenKeybox));
|
|
||||||
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||||
EXPECT_CALL(*file_handle_,
|
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
|
||||||
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
|
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
|
Eq(crypto_session_), Eq(policy_engine_)))
|
||||||
Return(DeviceFiles::kCertificateValid)));
|
|
||||||
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey))
|
|
||||||
.InSequence(crypto_session_seq)
|
|
||||||
.WillOnce(Return(NO_ERROR));
|
|
||||||
EXPECT_CALL(*license_parser_,
|
|
||||||
Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString),
|
|
||||||
Eq(crypto_session_), Eq(policy_engine_)))
|
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
|
ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr));
|
||||||
@@ -298,25 +272,6 @@ TEST_F(CdmSessionTest, InitFailCryptoError) {
|
|||||||
ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init(nullptr));
|
ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CdmSessionTest, InitNeedsProvisioning) {
|
|
||||||
Sequence crypto_session_seq;
|
|
||||||
CdmSecurityLevel level = kSecurityLevelL1;
|
|
||||||
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
|
||||||
.InSequence(crypto_session_seq)
|
|
||||||
.WillOnce(Return(NO_ERROR));
|
|
||||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
|
||||||
.InSequence(crypto_session_seq)
|
|
||||||
.WillOnce(Return(level));
|
|
||||||
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
|
|
||||||
.WillOnce(Return(kClientTokenKeybox));
|
|
||||||
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
|
||||||
EXPECT_CALL(*file_handle_,
|
|
||||||
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
|
|
||||||
.WillOnce(Return(DeviceFiles::kCertificateInvalid));
|
|
||||||
|
|
||||||
ASSERT_EQ(NEED_PROVISIONING, cdm_session_->Init(nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CdmSessionTest, UpdateUsageEntry) {
|
TEST_F(CdmSessionTest, UpdateUsageEntry) {
|
||||||
// Setup common expectations for initializing the CdmSession object.
|
// Setup common expectations for initializing the CdmSession object.
|
||||||
Sequence crypto_session_seq;
|
Sequence crypto_session_seq;
|
||||||
@@ -327,21 +282,12 @@ TEST_F(CdmSessionTest, UpdateUsageEntry) {
|
|||||||
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel())
|
||||||
.InSequence(crypto_session_seq)
|
.InSequence(crypto_session_seq)
|
||||||
.WillOnce(Return(level));
|
.WillOnce(Return(level));
|
||||||
EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType())
|
|
||||||
.WillOnce(Return(kClientTokenKeybox));
|
|
||||||
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||||
EXPECT_CALL(*file_handle_,
|
EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true));
|
||||||
RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _))
|
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey),
|
|
||||||
Return(DeviceFiles::kCertificateValid)));
|
|
||||||
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey))
|
|
||||||
.InSequence(crypto_session_seq)
|
|
||||||
.WillOnce(Return(NO_ERROR));
|
|
||||||
EXPECT_CALL(*crypto_session_, GetUsageTableHeader())
|
EXPECT_CALL(*crypto_session_, GetUsageTableHeader())
|
||||||
.WillOnce(Return(&usage_table_header_));
|
.WillOnce(Return(&usage_table_header_));
|
||||||
EXPECT_CALL(*license_parser_,
|
EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString),
|
||||||
Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString),
|
Eq(crypto_session_), Eq(policy_engine_)))
|
||||||
Eq(crypto_session_), Eq(policy_engine_)))
|
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
// Set up mocks and expectations for the UpdateUsageEntryInformation call.
|
// Set up mocks and expectations for the UpdateUsageEntryInformation call.
|
||||||
|
|||||||
@@ -250,22 +250,13 @@ TEST_F(CdmLicenseTest, InitSuccess) {
|
|||||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||||
|
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, false,
|
EXPECT_TRUE(cdm_license_->Init(false, kEmptyServiceCertificate,
|
||||||
kEmptyServiceCertificate, crypto_session_,
|
crypto_session_, policy_engine_));
|
||||||
policy_engine_));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(CdmLicenseTest, InitFail_EmptyToken) {
|
|
||||||
CreateCdmLicense();
|
|
||||||
EXPECT_FALSE(cdm_license_->Init("", kClientTokenDrmCert, false,
|
|
||||||
kEmptyServiceCertificate, crypto_session_,
|
|
||||||
policy_engine_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CdmLicenseTest, InitFail_CryptoSessionNull) {
|
TEST_F(CdmLicenseTest, InitFail_CryptoSessionNull) {
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, false,
|
EXPECT_FALSE(cdm_license_->Init(false, kEmptyServiceCertificate, nullptr,
|
||||||
kEmptyServiceCertificate, nullptr,
|
|
||||||
policy_engine_));
|
policy_engine_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,36 +264,32 @@ TEST_F(CdmLicenseTest, InitFail_PolicyEngineNull) {
|
|||||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||||
|
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, false,
|
EXPECT_FALSE(cdm_license_->Init(false, kEmptyServiceCertificate,
|
||||||
kEmptyServiceCertificate, crypto_session_,
|
crypto_session_, nullptr));
|
||||||
nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CdmLicenseTest, InitWithEmptyServiceCert) {
|
TEST_F(CdmLicenseTest, InitWithEmptyServiceCert) {
|
||||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||||
|
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
|
EXPECT_TRUE(cdm_license_->Init(true, kEmptyServiceCertificate,
|
||||||
kEmptyServiceCertificate, crypto_session_,
|
crypto_session_, policy_engine_));
|
||||||
policy_engine_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CdmLicenseTest, InitWithInvalidServiceCert) {
|
TEST_F(CdmLicenseTest, InitWithInvalidServiceCert) {
|
||||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||||
|
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
|
EXPECT_FALSE(cdm_license_->Init(true, kInvalidServiceCertificate,
|
||||||
kInvalidServiceCertificate, crypto_session_,
|
crypto_session_, policy_engine_));
|
||||||
policy_engine_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CdmLicenseTest, InitWithServiceCert) {
|
TEST_F(CdmLicenseTest, InitWithServiceCert) {
|
||||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||||
|
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
|
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||||
kDefaultServiceCertificate, crypto_session_,
|
crypto_session_, policy_engine_));
|
||||||
policy_engine_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||||
@@ -335,16 +322,15 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
|||||||
Return(NO_ERROR)));
|
Return(NO_ERROR)));
|
||||||
|
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
|
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||||
kDefaultServiceCertificate, crypto_session_,
|
crypto_session_, policy_engine_));
|
||||||
policy_engine_));
|
|
||||||
|
|
||||||
CdmAppParameterMap app_parameters;
|
CdmAppParameterMap app_parameters;
|
||||||
CdmKeyMessage signed_request;
|
CdmKeyMessage signed_request;
|
||||||
std::string server_url;
|
std::string server_url;
|
||||||
EXPECT_EQ(cdm_license_->PrepareKeyRequest(*init_data_, kLicenseTypeStreaming,
|
EXPECT_EQ(cdm_license_->PrepareKeyRequest(
|
||||||
app_parameters, &signed_request,
|
*init_data_, kToken, kLicenseTypeStreaming, app_parameters,
|
||||||
&server_url),
|
&signed_request, &server_url),
|
||||||
KEY_MESSAGE);
|
KEY_MESSAGE);
|
||||||
|
|
||||||
EXPECT_TRUE(!signed_request.empty());
|
EXPECT_TRUE(!signed_request.empty());
|
||||||
@@ -460,16 +446,15 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
|||||||
Return(NO_ERROR)));
|
Return(NO_ERROR)));
|
||||||
|
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
|
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||||
kDefaultServiceCertificate, crypto_session_,
|
crypto_session_, policy_engine_));
|
||||||
policy_engine_));
|
|
||||||
|
|
||||||
CdmAppParameterMap app_parameters;
|
CdmAppParameterMap app_parameters;
|
||||||
CdmKeyMessage signed_request;
|
CdmKeyMessage signed_request;
|
||||||
std::string server_url;
|
std::string server_url;
|
||||||
EXPECT_EQ(cdm_license_->PrepareKeyRequest(*init_data_, kLicenseTypeStreaming,
|
EXPECT_EQ(cdm_license_->PrepareKeyRequest(
|
||||||
app_parameters, &signed_request,
|
*init_data_, kToken, kLicenseTypeStreaming, app_parameters,
|
||||||
&server_url),
|
&signed_request, &server_url),
|
||||||
KEY_MESSAGE);
|
KEY_MESSAGE);
|
||||||
|
|
||||||
EXPECT_TRUE(!signed_request.empty());
|
EXPECT_TRUE(!signed_request.empty());
|
||||||
@@ -601,9 +586,8 @@ TEST_P(CdmLicenseEntitledKeyTest, LoadsEntitledKeys) {
|
|||||||
|
|
||||||
// Set up the CdmLicense with the mocks and fake entitlement key
|
// Set up the CdmLicense with the mocks and fake entitlement key
|
||||||
CreateCdmLicense();
|
CreateCdmLicense();
|
||||||
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true,
|
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||||
kDefaultServiceCertificate, crypto_session_,
|
crypto_session_, policy_engine_));
|
||||||
policy_engine_));
|
|
||||||
cdm_license_->set_entitlement_keys(entitlement_license);
|
cdm_license_->set_entitlement_keys(entitlement_license);
|
||||||
|
|
||||||
// Call the function under test and check its return value
|
// Call the function under test and check its return value
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ namespace {
|
|||||||
|
|
||||||
// HTTP response codes.
|
// HTTP response codes.
|
||||||
const int kHttpOk = 200;
|
const int kHttpOk = 200;
|
||||||
|
const int kDrmCertificateExpiryPeriod = 150;
|
||||||
|
const std::string kCencMimeType = "video/mp4";
|
||||||
|
|
||||||
const wvcdm::CdmIdentifier kExampleIdentifier = {
|
const wvcdm::CdmIdentifier kExampleIdentifier = {
|
||||||
wvcdm::EMPTY_SPOID, "com.example", "com.example", 7, 9};
|
wvcdm::EMPTY_SPOID, "com.example", "com.example", 7, 9};
|
||||||
@@ -1747,6 +1749,13 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|||||||
client_auth->assign(config.client_auth());
|
client_auth->assign(config.client_auth());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CdmResponseType GenerateKeyRequest() {
|
||||||
|
CdmAppParameterMap app_parameters;
|
||||||
|
return GenerateKeyRequest(kCencMimeType, binary_key_id(), app_parameters,
|
||||||
|
kLicenseTypeStreaming, kDefaultCdmIdentifier,
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void GenerateKeyRequest(const std::string& init_data,
|
void GenerateKeyRequest(const std::string& init_data,
|
||||||
CdmLicenseType license_type) {
|
CdmLicenseType license_type) {
|
||||||
GenerateKeyRequest(init_data, license_type, nullptr);
|
GenerateKeyRequest(init_data, license_type, nullptr);
|
||||||
@@ -1794,6 +1803,24 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|||||||
CdmLicenseType license_type,
|
CdmLicenseType license_type,
|
||||||
const CdmIdentifier& cdm_identifier,
|
const CdmIdentifier& cdm_identifier,
|
||||||
CdmClientPropertySet* property_set) {
|
CdmClientPropertySet* property_set) {
|
||||||
|
CdmResponseType status =
|
||||||
|
GenerateKeyRequest(init_data_type, init_data, app_parameters,
|
||||||
|
license_type, cdm_identifier, property_set);
|
||||||
|
EXPECT_EQ(expected_response, status)
|
||||||
|
<< "session_id_ " << session_id_ << std::endl
|
||||||
|
<< "init_data (hex) " << wvcdm::b2a_hex(init_data) << std::endl
|
||||||
|
<< "cdm_identifier.origin " << cdm_identifier.origin << std::endl
|
||||||
|
<< "cdm_identifier.app_package_name " << cdm_identifier.app_package_name
|
||||||
|
<< std::endl
|
||||||
|
<< "cdm_identifier.unique_id " << cdm_identifier.unique_id << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmResponseType GenerateKeyRequest(const std::string& init_data_type,
|
||||||
|
const std::string& init_data,
|
||||||
|
CdmAppParameterMap& app_parameters,
|
||||||
|
CdmLicenseType license_type,
|
||||||
|
const CdmIdentifier& cdm_identifier,
|
||||||
|
CdmClientPropertySet* property_set) {
|
||||||
CdmKeyRequest key_request;
|
CdmKeyRequest key_request;
|
||||||
std::string key_set_id;
|
std::string key_set_id;
|
||||||
license_type_ = license_type;
|
license_type_ = license_type;
|
||||||
@@ -1801,20 +1828,13 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|||||||
InitializationData parsed_init_data(init_data_type, init_data);
|
InitializationData parsed_init_data(init_data_type, init_data);
|
||||||
parsed_init_data.DumpToLogs();
|
parsed_init_data.DumpToLogs();
|
||||||
}
|
}
|
||||||
EXPECT_EQ(
|
|
||||||
expected_response,
|
CdmResponseType status = decryptor_->GenerateKeyRequest(
|
||||||
decryptor_->GenerateKeyRequest(
|
session_id_, key_set_id, init_data_type, init_data, license_type,
|
||||||
session_id_, key_set_id, init_data_type, init_data, license_type,
|
app_parameters, property_set, cdm_identifier, &key_request);
|
||||||
app_parameters, property_set, cdm_identifier, &key_request))
|
|
||||||
<< "session_id_ " << session_id_ << std::endl
|
|
||||||
<< "init_data (hex) " << wvcdm::b2a_hex(init_data) << std::endl
|
|
||||||
<< "key_set_id " << key_set_id << std::endl
|
|
||||||
<< "cdm_identifier.origin " << cdm_identifier.origin << std::endl
|
|
||||||
<< "cdm_identifier.app_package_name " << cdm_identifier.app_package_name
|
|
||||||
<< std::endl
|
|
||||||
<< "cdm_identifier.unique_id " << cdm_identifier.unique_id << std::endl;
|
|
||||||
key_msg_ = key_request.message;
|
key_msg_ = key_request.message;
|
||||||
EXPECT_EQ(0u, key_request.url.size());
|
EXPECT_EQ(0u, key_request.url.size());
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateRenewalRequest(CdmLicenseType license_type,
|
void GenerateRenewalRequest(CdmLicenseType license_type,
|
||||||
@@ -2027,6 +2047,40 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|||||||
decryptor_->Unprovision(kSecurityLevelL3, kDefaultCdmIdentifier));
|
decryptor_->Unprovision(kSecurityLevelL3, kDefaultCdmIdentifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsProvisioned(const CdmIdentifier& identifier,
|
||||||
|
SecurityLevel requested_security_level) {
|
||||||
|
TestWvCdmClientPropertySet property_set_L3;
|
||||||
|
TestWvCdmClientPropertySet* property_set = nullptr;
|
||||||
|
|
||||||
|
if (kLevel3 == requested_security_level) {
|
||||||
|
property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
|
||||||
|
property_set = &property_set_L3;
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmResponseType status = decryptor_->OpenSession(
|
||||||
|
config_.key_system(), property_set, identifier, nullptr, &session_id_);
|
||||||
|
|
||||||
|
if (status == NO_ERROR) {
|
||||||
|
wvcdm::CdmAppParameterMap app_parameters;
|
||||||
|
status =
|
||||||
|
GenerateKeyRequest(kCencMimeType, binary_key_id(), app_parameters,
|
||||||
|
kLicenseTypeStreaming, identifier, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptor_->CloseSession(session_id_);
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case NO_ERROR:
|
||||||
|
case KEY_MESSAGE:
|
||||||
|
return true;
|
||||||
|
case NEED_PROVISIONING:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
EXPECT_EQ(NO_ERROR, status);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Provision() { Provision(kDefaultCdmIdentifier, kLevelDefault); }
|
void Provision() { Provision(kDefaultCdmIdentifier, kLevelDefault); }
|
||||||
|
|
||||||
void Provision(const CdmIdentifier& identifier,
|
void Provision(const CdmIdentifier& identifier,
|
||||||
@@ -2040,24 +2094,13 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|||||||
property_set = &property_set_L3;
|
property_set = &property_set_L3;
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType status = decryptor_->OpenSession(
|
if (IsProvisioned(identifier, requested_security_level)) return;
|
||||||
config_.key_system(), property_set, identifier, nullptr, &session_id_);
|
|
||||||
switch (status) {
|
|
||||||
case NO_ERROR:
|
|
||||||
decryptor_->CloseSession(session_id_);
|
|
||||||
return;
|
|
||||||
case NEED_PROVISIONING:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
EXPECT_EQ(NO_ERROR, status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string provisioning_server;
|
std::string provisioning_server;
|
||||||
CdmCertificateType cert_type = kCertificateWidevine;
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
std::string cert_authority, cert, wrapped_key;
|
std::string cert_authority, cert, wrapped_key;
|
||||||
|
|
||||||
status = decryptor_->GetProvisioningRequest(
|
CdmResponseType status = decryptor_->GetProvisioningRequest(
|
||||||
cert_type, cert_authority, identifier, kEmptyServiceCertificate,
|
cert_type, cert_authority, identifier, kEmptyServiceCertificate,
|
||||||
requested_security_level, &key_msg_, &provisioning_server);
|
requested_security_level, &key_msg_, &provisioning_server);
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR, status);
|
EXPECT_EQ(wvcdm::NO_ERROR, status);
|
||||||
@@ -2169,10 +2212,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
|
TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
|
||||||
Unprovision();
|
Unprovision();
|
||||||
EXPECT_EQ(
|
EXPECT_FALSE(IsProvisioned(kDefaultCdmIdentifier, kLevelDefault));
|
||||||
NEED_PROVISIONING,
|
|
||||||
decryptor_->OpenSession(config_.key_system(), nullptr,
|
|
||||||
kDefaultCdmIdentifier, nullptr, &session_id_));
|
|
||||||
std::string provisioning_server;
|
std::string provisioning_server;
|
||||||
CdmCertificateType cert_type = kCertificateWidevine;
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
std::string cert_authority, cert, wrapped_key;
|
std::string cert_authority, cert, wrapped_key;
|
||||||
@@ -2195,11 +2236,9 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningTestWithServiceCertificate) {
|
TEST_F(WvCdmRequestLicenseTest, ProvisioningTestWithServiceCertificate) {
|
||||||
CdmResponseType status =
|
Unprovision();
|
||||||
decryptor_->OpenSession(config_.key_system(), nullptr,
|
EXPECT_FALSE(IsProvisioned(kDefaultCdmIdentifier, kLevelDefault));
|
||||||
kDefaultCdmIdentifier, nullptr, &session_id_);
|
|
||||||
EXPECT_TRUE(status == NEED_PROVISIONING || status == NO_ERROR)
|
|
||||||
<< "Failure to open session. error: " << status;
|
|
||||||
std::string provisioning_server;
|
std::string provisioning_server;
|
||||||
CdmCertificateType cert_type = kCertificateWidevine;
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
std::string cert_authority, cert, wrapped_key;
|
std::string cert_authority, cert, wrapped_key;
|
||||||
@@ -2222,6 +2261,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningTestWithServiceCertificate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, L3ProvisioningTest) {
|
TEST_F(WvCdmRequestLicenseTest, L3ProvisioningTest) {
|
||||||
|
Unprovision();
|
||||||
TestWvCdmClientPropertySet property_set_L3;
|
TestWvCdmClientPropertySet property_set_L3;
|
||||||
property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
|
property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
|
||||||
std::string provisioning_server;
|
std::string provisioning_server;
|
||||||
@@ -2246,19 +2286,28 @@ TEST_F(WvCdmRequestLicenseTest, L3ProvisioningTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningTest) {
|
TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningTest) {
|
||||||
|
Unprovision();
|
||||||
EXPECT_EQ(NO_ERROR,
|
EXPECT_EQ(NO_ERROR,
|
||||||
decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier));
|
decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier));
|
||||||
|
Provision();
|
||||||
|
|
||||||
// Verify the global identifier is provisioned.
|
// Verify the global identifier is provisioned.
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->OpenSession(
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->OpenSession(
|
||||||
config_.key_system(), nullptr,
|
config_.key_system(), nullptr,
|
||||||
kDefaultCdmIdentifier, nullptr, &session_id_));
|
kDefaultCdmIdentifier, nullptr, &session_id_));
|
||||||
|
|
||||||
|
CdmAppParameterMap app_parameters;
|
||||||
|
EXPECT_EQ(KEY_MESSAGE,
|
||||||
|
GenerateKeyRequest(kCencMimeType, binary_key_id(), app_parameters,
|
||||||
|
kLicenseTypeStreaming, kDefaultCdmIdentifier,
|
||||||
|
nullptr));
|
||||||
decryptor_->CloseSession(session_id_);
|
decryptor_->CloseSession(session_id_);
|
||||||
|
|
||||||
// The other identifier should not be provisioned.
|
// The other identifier should not be provisioned.
|
||||||
EXPECT_EQ(wvcdm::NEED_PROVISIONING,
|
EXPECT_EQ(wvcdm::NEED_PROVISIONING,
|
||||||
decryptor_->OpenSession(config_.key_system(), nullptr,
|
decryptor_->OpenSession(config_.key_system(), nullptr,
|
||||||
kExampleIdentifier, nullptr, &session_id_));
|
kExampleIdentifier, nullptr, &session_id_));
|
||||||
|
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningSupportsOldPaths) {
|
TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningSupportsOldPaths) {
|
||||||
@@ -2588,6 +2637,42 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningRevocationTest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WvCdmRequestLicenseTest, ProvisioningWithExpiringCertTest) {
|
||||||
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
||||||
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier));
|
||||||
|
|
||||||
|
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
ConfigTestEnv config(kContentProtectionStagingServer, true);
|
||||||
|
|
||||||
|
// Provision
|
||||||
|
std::string provisioning_server;
|
||||||
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
|
std::string cert_authority, cert, wrapped_key;
|
||||||
|
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
|
||||||
|
cert_type, cert_authority, kExampleIdentifier,
|
||||||
|
kEmptyServiceCertificate, kLevelDefault,
|
||||||
|
&key_msg_, &provisioning_server));
|
||||||
|
|
||||||
|
std::string response = GetCertRequestResponse(config.provisioning_server());
|
||||||
|
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
||||||
|
kExampleIdentifier, response, kLevelDefault,
|
||||||
|
&cert, &wrapped_key));
|
||||||
|
EXPECT_EQ(0, static_cast<int>(cert.size()));
|
||||||
|
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
||||||
|
decryptor_->CloseSession(session_id_);
|
||||||
|
|
||||||
|
// Make sure it is provisioned, then wait for certificate expiry period
|
||||||
|
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
sleep(kDrmCertificateExpiryPeriod);
|
||||||
|
|
||||||
|
// Verify that it is no longer provisioned after the certificate expires
|
||||||
|
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, PropertySetTest) {
|
TEST_F(WvCdmRequestLicenseTest, PropertySetTest) {
|
||||||
TestWvCdmClientPropertySet property_set_L1;
|
TestWvCdmClientPropertySet property_set_L1;
|
||||||
TestWvCdmClientPropertySet property_set_L3;
|
TestWvCdmClientPropertySet property_set_L3;
|
||||||
@@ -2760,6 +2845,48 @@ TEST_F(WvCdmRequestLicenseTest, AddStreamingKeyTest) {
|
|||||||
decryptor_->CloseSession(session_id_);
|
decryptor_->CloseSession(session_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WvCdmRequestLicenseTest, StreamingWithExpiringCertTest) {
|
||||||
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
||||||
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier));
|
||||||
|
|
||||||
|
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
ConfigTestEnv config(kContentProtectionStagingServer, true);
|
||||||
|
|
||||||
|
// Provision
|
||||||
|
std::string provisioning_server;
|
||||||
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
|
std::string cert_authority, cert, wrapped_key;
|
||||||
|
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
|
||||||
|
cert_type, cert_authority, kExampleIdentifier,
|
||||||
|
kEmptyServiceCertificate, kLevelDefault,
|
||||||
|
&key_msg_, &provisioning_server));
|
||||||
|
|
||||||
|
std::string response = GetCertRequestResponse(config.provisioning_server());
|
||||||
|
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
||||||
|
kExampleIdentifier, response, kLevelDefault,
|
||||||
|
&cert, &wrapped_key));
|
||||||
|
EXPECT_EQ(0, static_cast<int>(cert.size()));
|
||||||
|
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
||||||
|
|
||||||
|
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
|
||||||
|
// Fetch a streaming license
|
||||||
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_->OpenSession(config_.key_system(), nullptr,
|
||||||
|
kExampleIdentifier, nullptr, &session_id_));
|
||||||
|
|
||||||
|
CdmAppParameterMap app_parameters;
|
||||||
|
GenerateKeyRequest(KEY_MESSAGE, kCencMimeType, binary_key_id(),
|
||||||
|
app_parameters, kLicenseTypeStreaming, kExampleIdentifier,
|
||||||
|
nullptr);
|
||||||
|
VerifyKeyRequestResponse(config_.license_server(), config_.client_auth());
|
||||||
|
decryptor_->CloseSession(session_id_);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
|
TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
|
||||||
Unprovision();
|
Unprovision();
|
||||||
Provision();
|
Provision();
|
||||||
@@ -2801,6 +2928,68 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
|
|||||||
decryptor_->CloseSession(session_id_);
|
decryptor_->CloseSession(session_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
|
||||||
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
||||||
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier));
|
||||||
|
|
||||||
|
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
ConfigTestEnv config(kContentProtectionStagingServer, true);
|
||||||
|
|
||||||
|
// Provision
|
||||||
|
std::string provisioning_server;
|
||||||
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
|
std::string cert_authority, cert, wrapped_key;
|
||||||
|
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
|
||||||
|
cert_type, cert_authority, kExampleIdentifier,
|
||||||
|
kEmptyServiceCertificate, kLevelDefault,
|
||||||
|
&key_msg_, &provisioning_server));
|
||||||
|
|
||||||
|
std::string response = GetCertRequestResponse(config.provisioning_server());
|
||||||
|
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
||||||
|
kExampleIdentifier, response, kLevelDefault,
|
||||||
|
&cert, &wrapped_key));
|
||||||
|
EXPECT_EQ(0, static_cast<int>(cert.size()));
|
||||||
|
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
||||||
|
|
||||||
|
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
|
||||||
|
std::string key_id;
|
||||||
|
std::string client_auth;
|
||||||
|
GetOfflineConfiguration(&key_id, &client_auth);
|
||||||
|
|
||||||
|
// Fetch offline license
|
||||||
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_->OpenSession(config_.key_system(), nullptr,
|
||||||
|
kExampleIdentifier, nullptr, &session_id_));
|
||||||
|
|
||||||
|
CdmAppParameterMap app_parameters;
|
||||||
|
GenerateKeyRequest(KEY_MESSAGE, kCencMimeType, key_id, app_parameters,
|
||||||
|
kLicenseTypeOffline, kExampleIdentifier, nullptr);
|
||||||
|
VerifyKeyRequestResponse(config_.license_server(), client_auth);
|
||||||
|
|
||||||
|
CdmKeySetId key_set_id = key_set_id_;
|
||||||
|
EXPECT_FALSE(key_set_id_.empty());
|
||||||
|
decryptor_->CloseSession(session_id_);
|
||||||
|
|
||||||
|
session_id_.clear();
|
||||||
|
|
||||||
|
// Wait till certificate expires
|
||||||
|
sleep(kDrmCertificateExpiryPeriod);
|
||||||
|
|
||||||
|
// Make sure the certificate has expired and the device is not provisioned
|
||||||
|
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
|
||||||
|
// Restore offline license
|
||||||
|
decryptor_->OpenSession(config_.key_system(), nullptr, kExampleIdentifier,
|
||||||
|
nullptr, &session_id_);
|
||||||
|
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_->RestoreKey(session_id_, key_set_id));
|
||||||
|
decryptor_->CloseSession(session_id_);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, DisallowMultipleRestoreOfflineKeyTest) {
|
TEST_F(WvCdmRequestLicenseTest, DisallowMultipleRestoreOfflineKeyTest) {
|
||||||
Unprovision();
|
Unprovision();
|
||||||
Provision();
|
Provision();
|
||||||
@@ -2987,11 +3176,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) {
|
|||||||
std::string client_auth;
|
std::string client_auth;
|
||||||
GetOfflineConfiguration(&key_id, &client_auth);
|
GetOfflineConfiguration(&key_id, &client_auth);
|
||||||
|
|
||||||
CdmResponseType sts =
|
if (!IsProvisioned(kDefaultCdmIdentifier, kLevel3)) {
|
||||||
decryptor_->OpenSession(config_.key_system(), &property_set,
|
|
||||||
kDefaultCdmIdentifier, nullptr, &session_id_);
|
|
||||||
|
|
||||||
if (NEED_PROVISIONING == sts) {
|
|
||||||
std::string provisioning_server;
|
std::string provisioning_server;
|
||||||
CdmCertificateType cert_type = kCertificateWidevine;
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
std::string cert_authority, cert, wrapped_key;
|
std::string cert_authority, cert, wrapped_key;
|
||||||
@@ -3009,8 +3194,6 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) {
|
|||||||
EXPECT_EQ(NO_ERROR, decryptor_->OpenSession(
|
EXPECT_EQ(NO_ERROR, decryptor_->OpenSession(
|
||||||
config_.key_system(), &property_set,
|
config_.key_system(), &property_set,
|
||||||
kDefaultCdmIdentifier, nullptr, &session_id_));
|
kDefaultCdmIdentifier, nullptr, &session_id_));
|
||||||
} else {
|
|
||||||
EXPECT_EQ(NO_ERROR, sts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptor_->OpenSession(config_.key_system(), &property_set,
|
decryptor_->OpenSession(config_.key_system(), &property_set,
|
||||||
@@ -3063,11 +3246,7 @@ TEST_F(WvCdmRequestLicenseTest,
|
|||||||
GetOfflineConfiguration(&key_id, &client_auth);
|
GetOfflineConfiguration(&key_id, &client_auth);
|
||||||
key_id[key_id.size() - 1] = '1';
|
key_id[key_id.size() - 1] = '1';
|
||||||
|
|
||||||
CdmResponseType sts =
|
if (!IsProvisioned(kDefaultCdmIdentifier, kLevel3)) {
|
||||||
decryptor_->OpenSession(config_.key_system(), &property_set,
|
|
||||||
kDefaultCdmIdentifier, nullptr, &session_id_);
|
|
||||||
|
|
||||||
if (NEED_PROVISIONING == sts) {
|
|
||||||
std::string provisioning_server_url;
|
std::string provisioning_server_url;
|
||||||
CdmCertificateType cert_type = kCertificateWidevine;
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
std::string cert_authority, cert, wrapped_key;
|
std::string cert_authority, cert, wrapped_key;
|
||||||
@@ -3085,8 +3264,6 @@ TEST_F(WvCdmRequestLicenseTest,
|
|||||||
EXPECT_EQ(NO_ERROR, decryptor_->OpenSession(
|
EXPECT_EQ(NO_ERROR, decryptor_->OpenSession(
|
||||||
config_.key_system(), &property_set,
|
config_.key_system(), &property_set,
|
||||||
kDefaultCdmIdentifier, nullptr, &session_id_));
|
kDefaultCdmIdentifier, nullptr, &session_id_));
|
||||||
} else {
|
|
||||||
EXPECT_EQ(NO_ERROR, sts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptor_->OpenSession(config_.key_system(), &property_set,
|
decryptor_->OpenSession(config_.key_system(), &property_set,
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineAndSessionMetrics) {
|
|||||||
wvcdm::CdmKeySystem key_system("com.widevine");
|
wvcdm::CdmKeySystem key_system("com.widevine");
|
||||||
Unprovision(kDefaultCdmIdentifier);
|
Unprovision(kDefaultCdmIdentifier);
|
||||||
|
|
||||||
// Openning the session will fail with NEEDS_PROVISIONING error. But it will
|
// Opening the session will fail with NEEDS_PROVISIONING error. But it will
|
||||||
// still create some session-level stats.
|
// still create some session-level stats.
|
||||||
EXPECT_EQ(CdmResponseType::NEED_PROVISIONING,
|
EXPECT_EQ(CdmResponseType::NEED_PROVISIONING,
|
||||||
decryptor_.OpenSession(key_system, nullptr, kDefaultCdmIdentifier,
|
decryptor_.OpenSession(key_system, nullptr, kDefaultCdmIdentifier,
|
||||||
@@ -133,11 +133,6 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineAndSessionMetrics) {
|
|||||||
|
|
||||||
// Validate a session-level metric.
|
// Validate a session-level metric.
|
||||||
ASSERT_THAT(metrics.session_metrics().size(), Eq(1));
|
ASSERT_THAT(metrics.session_metrics().size(), Eq(1));
|
||||||
EXPECT_THAT(
|
|
||||||
metrics.session_metrics(0).cdm_session_life_span_ms().double_value(),
|
|
||||||
Gt(0.0))
|
|
||||||
<< "Unexpected failure with session_metrics: "
|
|
||||||
<< wvcdm::b2a_hex(serialized_metrics);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvContentDecryptionModuleMetricsTest,
|
TEST_F(WvContentDecryptionModuleMetricsTest,
|
||||||
@@ -190,11 +185,6 @@ TEST_F(WvContentDecryptionModuleMetricsTest,
|
|||||||
ASSERT_THAT(metrics.session_metrics().size(), Eq(i + 1))
|
ASSERT_THAT(metrics.session_metrics().size(), Eq(i + 1))
|
||||||
<< "Unexpected failure with session_metrics: "
|
<< "Unexpected failure with session_metrics: "
|
||||||
<< wvcdm::b2a_hex(serialized_metrics);
|
<< wvcdm::b2a_hex(serialized_metrics);
|
||||||
EXPECT_THAT(
|
|
||||||
metrics.session_metrics(0).cdm_session_life_span_ms().double_value(),
|
|
||||||
Gt(0.0))
|
|
||||||
<< "Unexpected failure with session_metrics: "
|
|
||||||
<< wvcdm::b2a_hex(serialized_metrics);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user