From 20fc54e3847001e643783c38577d0f9dc71dceff Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Mon, 4 May 2015 11:39:57 -0700 Subject: [PATCH] Add client information to release and renewal messages [ Merge of go/wvgerrit/14240 ] Client information is reported in release and renewal messages based on flag in the license. License proto has been updated to match server updates. There are two caveats * Client IDs will be reported unencrypted when usage reports are requested. * Release requests that enable privacy mode (encrypted client IDs) but do not specify a service certificate are not supported. b/19247020 Change-Id: I95e709922122370f310936fbad3d312262128e49 --- libwvdrmengine/cdm/core/include/cdm_session.h | 1 + .../cdm/core/include/device_files.h | 7 +- libwvdrmengine/cdm/core/include/license.h | 16 +- .../cdm/core/include/wv_cdm_types.h | 8 + libwvdrmengine/cdm/core/src/cdm_session.cpp | 21 +- libwvdrmengine/cdm/core/src/device_files.cpp | 32 +- .../cdm/core/src/device_files.proto | 6 + libwvdrmengine/cdm/core/src/license.cpp | 427 ++++++++------ .../cdm/core/src/license_protocol.proto | 42 +- .../cdm/core/test/config_test_env.cpp | 3 +- .../cdm/core/test/device_files_unittest.cpp | 387 +++++++++++-- .../cdm/test/request_license_test.cpp | 519 ++++++++++++++---- libwvdrmengine/include/WVErrors.h | 291 +++++----- libwvdrmengine/include/mapErrors-inl.h | 16 + 14 files changed, 1252 insertions(+), 524 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index c4613de2..4a96a576 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -139,6 +139,7 @@ class CdmSession { bool is_release_; CdmSecurityLevel security_level_; SecurityLevel requested_security_level_; + CdmAppParameterMap app_parameters_; // decryption and usage flags bool is_initial_decryption_; diff --git a/libwvdrmengine/cdm/core/include/device_files.h b/libwvdrmengine/cdm/core/include/device_files.h index 009c20e6..e33ee8bd 100644 --- a/libwvdrmengine/cdm/core/include/device_files.h +++ b/libwvdrmengine/cdm/core/include/device_files.h @@ -51,13 +51,15 @@ class DeviceFiles { const CdmKeyResponse& key_renewal_response, const std::string& release_server_url, int64_t playback_start_time, - int64_t last_playback_time); + int64_t last_playback_time, + const CdmAppParameterMap& app_parameters); virtual bool RetrieveLicense( const std::string& key_set_id, LicenseState* state, CdmInitData* pssh_data, CdmKeyMessage* key_request, CdmKeyResponse* key_response, CdmKeyMessage* key_renewal_request, CdmKeyResponse* key_renewal_response, std::string* release_server_url, - int64_t* playback_start_time, int64_t* last_playback_time); + int64_t* playback_start_time, int64_t* last_playback_time, + CdmAppParameterMap* app_parameters); virtual bool DeleteLicense(const std::string& key_set_id); virtual bool DeleteAllFiles(); virtual bool DeleteAllLicenses(); @@ -122,6 +124,7 @@ class DeviceFiles { FRIEND_TEST(DeviceFilesTest, DeleteLicense); FRIEND_TEST(DeviceFilesTest, ReserveLicenseIds); FRIEND_TEST(DeviceFilesTest, RetrieveLicenses); + FRIEND_TEST(DeviceFilesTest, AppParametersBackwardCompatibility); FRIEND_TEST(DeviceFilesTest, SecurityLevelPathBackwardCompatibility); FRIEND_TEST(DeviceFilesTest, StoreLicenses); FRIEND_TEST(DeviceFilesTest, UpdateLicenseState); diff --git a/libwvdrmengine/cdm/core/include/license.h b/libwvdrmengine/cdm/core/include/license.h index b27415bf..981f72a0 100644 --- a/libwvdrmengine/cdm/core/include/license.h +++ b/libwvdrmengine/cdm/core/include/license.h @@ -12,6 +12,7 @@ namespace video_widevine_server { namespace sdk { class SignedMessage; +class LicenseRequest; } } // namespace video_widevine_server @@ -35,9 +36,10 @@ class CdmLicense { const CdmSessionId& session_id, CdmKeyMessage* signed_request, std::string* server_url); - virtual CdmResponseType PrepareKeyUpdateRequest(bool is_renewal, - CdmKeyMessage* signed_request, - std::string* server_url); + virtual CdmResponseType PrepareKeyUpdateRequest( + bool is_renewal, const CdmAppParameterMap& app_parameters, + const CdmSessionId& session_id, CdmKeyMessage* signed_request, + std::string* server_url); virtual CdmResponseType HandleKeyResponse( const CdmKeyResponse& license_response); virtual CdmResponseType HandleKeyUpdateResponse( @@ -66,10 +68,17 @@ class CdmLicense { CdmResponseType HandleKeyErrorResponse( const video_widevine_server::sdk::SignedMessage& signed_message); + CdmResponseType PrepareClientId( + bool encrypt, const std::string& certificate, + const CdmAppParameterMap& app_parameters, + video_widevine_server::sdk::LicenseRequest* license_request); template bool PrepareContentId(const CdmLicenseType license_type, const std::string& request_id, T* content_id); + bool GetServiceCertificate(const CdmSessionId& session_id, + std::string* service_certificate); + CryptoSession* session_; PolicyEngine* policy_engine_; std::string server_url_; @@ -79,6 +88,7 @@ class CdmLicense { bool initialized_; std::set loaded_keys_; std::string provider_session_token_; + bool renew_with_client_id_; // Used for certificate based licensing CdmKeyMessage key_request_; diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index 6211f47a..5abafb5d 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -177,6 +177,14 @@ enum CdmResponseType { UNPROVISION_ERROR_4, UNSUPPORTED_INIT_DATA, USAGE_INFO_NOT_FOUND, + SERVICE_CERTIFICATE_REQUEST_GENERATE_ERROR, + PARSE_SERVICE_CERTIFICATE_ERROR, + SERVICE_CERTIFICATE_TYPE_ERROR, + CLIENT_ID_GENERATE_RANDOM_ERROR, + CLIENT_ID_AES_INIT_ERROR, + CLIENT_ID_AES_ENCRYPT_ERROR, + CLIENT_ID_RSA_INIT_ERROR, + CLIENT_ID_RSA_ENCRYPT_ERROR, }; enum CdmKeyStatus { diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 9f21ded2..2c42b098 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -107,7 +107,7 @@ CdmResponseType CdmSession::RestoreOfflineSession( key_set_id, &license_state, &offline_init_data_, &key_request_, &key_response_, &offline_key_renewal_request_, &offline_key_renewal_response_, &offline_release_server_url_, - &playback_start_time, &last_playback_time)) { + &playback_start_time, &last_playback_time, &app_parameters_)) { LOGE("CdmSession::Init failed to retrieve license. key set id = %s", key_set_id.c_str()); return GET_LICENSE_ERROR; @@ -208,6 +208,7 @@ CdmResponseType CdmSession::GenerateKeyRequest( return KEY_REQUEST_ERROR_1; } + app_parameters_ = app_parameters; if (!license_parser_->PrepareKeyRequest(init_data, license_type, app_parameters, session_id_, key_request, server_url)) { @@ -361,8 +362,8 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) { // session keys. CdmResponseType CdmSession::GenerateRenewalRequest(CdmKeyMessage* key_request, std::string* server_url) { - CdmResponseType status = - license_parser_->PrepareKeyUpdateRequest(true, key_request, server_url); + CdmResponseType status = license_parser_->PrepareKeyUpdateRequest( + true, app_parameters_, session_id_, key_request, server_url); if (KEY_MESSAGE != status) return status; @@ -389,8 +390,8 @@ CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) { CdmResponseType CdmSession::GenerateReleaseRequest(CdmKeyMessage* key_request, std::string* server_url) { is_release_ = true; - CdmResponseType status = - license_parser_->PrepareKeyUpdateRequest(false, key_request, server_url); + CdmResponseType status = license_parser_->PrepareKeyUpdateRequest( + false, app_parameters_, session_id_, key_request, server_url); if (KEY_MESSAGE != status) return status; @@ -499,7 +500,7 @@ bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) { key_set_id_, state, offline_init_data_, key_request_, key_response_, offline_key_renewal_request_, offline_key_renewal_response_, offline_release_server_url_, policy_engine_->GetPlaybackStartTime(), - policy_engine_->GetLastPlaybackTime()); + policy_engine_->GetLastPlaybackTime(), app_parameters_); } bool CdmSession::DeleteLicense() { @@ -507,8 +508,8 @@ bool CdmSession::DeleteLicense() { return false; if (!license_parser_->provider_session_token().empty()) { - if(crypto_session_->DeleteUsageInformation( - license_parser_->provider_session_token()) != NO_ERROR) { + if (crypto_session_->DeleteUsageInformation( + license_parser_->provider_session_token()) != NO_ERROR) { LOGE("CdmSession::DeleteLicense: error deleting usage info"); } } @@ -555,8 +556,8 @@ void CdmSession::GetApplicationId(std::string* app_id) { CdmResponseType CdmSession::DeleteMultipleUsageInformation( const std::vector& provider_session_tokens) { - return crypto_session_ - ->DeleteMultipleUsageInformation(provider_session_tokens); + return crypto_session_->DeleteMultipleUsageInformation( + provider_session_tokens); } CdmResponseType CdmSession::UpdateUsageInformation() { diff --git a/libwvdrmengine/cdm/core/src/device_files.cpp b/libwvdrmengine/cdm/core/src/device_files.cpp index 90588d91..df0bbb9c 100644 --- a/libwvdrmengine/cdm/core/src/device_files.cpp +++ b/libwvdrmengine/cdm/core/src/device_files.cpp @@ -27,6 +27,7 @@ using video_widevine_client::sdk::HashedFile; using video_widevine_client::sdk::License; using video_widevine_client::sdk::License_LicenseState_ACTIVE; using video_widevine_client::sdk::License_LicenseState_RELEASING; +using video_widevine_client::sdk::NameValue; using video_widevine_client::sdk::UsageInfo; using video_widevine_client::sdk::UsageInfo_ProviderSession; @@ -176,16 +177,14 @@ bool DeviceFiles::RemoveCertificate(const std::string& origin) { return RemoveFile(GetCertificateFileName(origin)); } -bool DeviceFiles::StoreLicense(const std::string& key_set_id, - const LicenseState state, - const CdmInitData& pssh_data, - const CdmKeyMessage& license_request, - const CdmKeyResponse& license_message, - const CdmKeyMessage& license_renewal_request, - const CdmKeyResponse& license_renewal, - const std::string& release_server_url, - int64_t playback_start_time, - int64_t last_playback_time) { +bool DeviceFiles::StoreLicense( + const std::string& key_set_id, const LicenseState state, + const CdmInitData& pssh_data, const CdmKeyMessage& license_request, + const CdmKeyResponse& license_message, + const CdmKeyMessage& license_renewal_request, + const CdmKeyResponse& license_renewal, + const std::string& release_server_url, int64_t playback_start_time, + int64_t last_playback_time, const CdmAppParameterMap& app_parameters) { if (!initialized_) { LOGW("DeviceFiles::StoreLicense: not initialized"); return false; @@ -218,6 +217,13 @@ bool DeviceFiles::StoreLicense(const std::string& key_set_id, license->set_release_server_url(release_server_url); license->set_playback_start_time(playback_start_time); license->set_last_playback_time(last_playback_time); + NameValue* app_params; + for (CdmAppParameterMap::const_iterator iter = app_parameters.begin(); + iter != app_parameters.end(); ++iter) { + app_params = license->add_app_parameters(); + app_params->set_name(iter->first); + app_params->set_value(iter->second); + } std::string serialized_file; file.SerializeToString(&serialized_file); @@ -230,7 +236,7 @@ bool DeviceFiles::RetrieveLicense( CdmKeyMessage* license_request, CdmKeyResponse* license_message, CdmKeyMessage* license_renewal_request, CdmKeyResponse* license_renewal, std::string* release_server_url, int64_t* playback_start_time, - int64_t* last_playback_time) { + int64_t* last_playback_time, CdmAppParameterMap* app_parameters) { if (!initialized_) { LOGW("DeviceFiles::RetrieveLicense: not initialized"); return false; @@ -285,6 +291,10 @@ bool DeviceFiles::RetrieveLicense( *release_server_url = license.release_server_url(); *playback_start_time = license.playback_start_time(); *last_playback_time = license.last_playback_time(); + for (int i = 0; i < license.app_parameters_size(); ++i) { + (*app_parameters)[license.app_parameters(i).name()] = + license.app_parameters(i).value(); + } return true; } diff --git a/libwvdrmengine/cdm/core/src/device_files.proto b/libwvdrmengine/cdm/core/src/device_files.proto index fe700bdd..468b4252 100644 --- a/libwvdrmengine/cdm/core/src/device_files.proto +++ b/libwvdrmengine/cdm/core/src/device_files.proto @@ -13,6 +13,11 @@ package video_widevine_client.sdk; // need this if we are using libprotobuf-cpp-2.3.0-lite option optimize_for = LITE_RUNTIME; +message NameValue { + optional string name = 1; + optional string value = 2; +} + message DeviceCertificate { optional bytes certificate = 1; optional bytes wrapped_private_key = 2; @@ -33,6 +38,7 @@ message License { optional bytes release_server_url = 7; optional int64 playback_start_time = 8 [default = 0]; optional int64 last_playback_time = 9 [default = 0]; + repeated NameValue app_parameters = 10; } message UsageInfo { diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index df1aa45a..b34326dc 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -129,7 +129,10 @@ static std::vector ExtractContentKeys(const License& license) { } CdmLicense::CdmLicense() - : session_(NULL), initialized_(false), clock_(new Clock()) {} + : session_(NULL), + initialized_(false), + renew_with_client_id_(false), + clock_(new Clock()) {} CdmLicense::CdmLicense(Clock* clock) : session_(NULL), initialized_(false) { if (NULL == clock) { @@ -194,184 +197,23 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data, return false; } + std::string service_certificate; bool privacy_mode_enabled = Properties::UsePrivacyMode(session_id); - std::string serialized_service_certificate; - if (!Properties::GetServiceCertificate(session_id, - &serialized_service_certificate) || - serialized_service_certificate.empty()) - serialized_service_certificate = service_certificate_; - - if (privacy_mode_enabled && serialized_service_certificate.empty()) { - stored_init_data_ = init_data.data(); - return PrepareServiceCertificateRequest(signed_request, server_url); + if (privacy_mode_enabled) { + if (!GetServiceCertificate(session_id, &service_certificate)) { + stored_init_data_ = init_data.data(); + return PrepareServiceCertificateRequest(signed_request, server_url); + } } std::string request_id; session_->GenerateRequestId(&request_id); LicenseRequest license_request; - ClientIdentification* client_id = license_request.mutable_client_id(); - - if (Properties::use_certificates_as_identification()) - client_id->set_type(ClientIdentification::DEVICE_CERTIFICATE); - else - client_id->set_type(ClientIdentification::KEYBOX); - client_id->set_token(token_); - - ClientIdentification_NameValue* client_info; - CdmAppParameterMap::const_iterator iter; - for (iter = app_parameters.begin(); iter != app_parameters.end(); iter++) { - client_info = client_id->add_client_info(); - client_info->set_name(iter->first); - client_info->set_value(iter->second); - } - std::string value; - if (Properties::GetCompanyName(&value)) { - client_info = client_id->add_client_info(); - client_info->set_name(kCompanyNameKey); - client_info->set_value(value); - } - if (Properties::GetModelName(&value)) { - client_info = client_id->add_client_info(); - client_info->set_name(kModelNameKey); - client_info->set_value(value); - } - if (Properties::GetArchitectureName(&value)) { - client_info = client_id->add_client_info(); - client_info->set_name(kArchitectureNameKey); - client_info->set_value(value); - } - if (Properties::GetDeviceName(&value)) { - client_info = client_id->add_client_info(); - client_info->set_name(kDeviceNameKey); - client_info->set_value(value); - } - if (Properties::GetProductName(&value)) { - client_info = client_id->add_client_info(); - client_info->set_name(kProductNameKey); - client_info->set_value(value); - } - if (Properties::GetBuildInfo(&value)) { - client_info = client_id->add_client_info(); - client_info->set_name(kBuildInfoKey); - client_info->set_value(value); - } - if (session_->GetDeviceUniqueId(&value)) { - client_info = client_id->add_client_info(); - client_info->set_name(kDeviceIdKey); - client_info->set_value(value); - } - if (Properties::GetWVCdmVersion(&value)) { - client_info = client_id->add_client_info(); - client_info->set_name(kWVCdmVersionKey); - client_info->set_value(value); - } - - ClientIdentification_ClientCapabilities* client_capabilities = - client_id->mutable_client_capabilities(); - bool supports_usage_information; - if (session_->UsageInformationSupport(&supports_usage_information)) { - client_capabilities->set_session_token(supports_usage_information); - } - - client_capabilities->set_anti_rollback_usage_table( - session_->IsAntiRollbackHwPresent()); - - uint32_t api_version = 0; - if (session_->GetApiVersion(&api_version)) { - client_capabilities->set_oem_crypto_api_version(api_version); - } - - CryptoSession::HdcpCapability current_version, max_version; - if (session_->GetHdcpCapabilities(¤t_version, &max_version)) { - switch (max_version) { - case HDCP_NONE: - client_capabilities->set_max_hdcp_version( - video_widevine_server::sdk:: - ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE); - break; - case HDCP_V1: - client_capabilities->set_max_hdcp_version( - video_widevine_server::sdk:: - ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1); - break; - case HDCP_V2: - client_capabilities->set_max_hdcp_version( - video_widevine_server::sdk:: - ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2); - break; - case HDCP_V2_1: - client_capabilities->set_max_hdcp_version( - video_widevine_server::sdk:: - ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1); - break; - case HDCP_V2_2: - client_capabilities->set_max_hdcp_version( - video_widevine_server::sdk:: - ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2); - break; - case HDCP_NO_DIGITAL_OUTPUT: - client_capabilities->set_max_hdcp_version( - video_widevine_server::sdk:: - ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NO_DIGITAL_OUTPUT); - break; - default: - LOGW( - "CdmLicense::PrepareKeyRequest: unexpected HDCP max capability " - "version %d", - max_version); - } - } - - if (privacy_mode_enabled) { - EncryptedClientIdentification* encrypted_client_id = - license_request.mutable_encrypted_client_id(); - DeviceCertificate service_certificate; - - if (!service_certificate.ParseFromString(serialized_service_certificate)) { - LOGE( - "CdmLicense::PrepareKeyRequest: unable to parse retrieved " - "service certificate"); - return false; - } - - if (service_certificate.type() != - video_widevine_server::sdk::DeviceCertificate_CertificateType_SERVICE) { - LOGE( - "CdmLicense::PrepareKeyRequest: retrieved certificate not of type" - " service, %d", - service_certificate.type()); - return false; - } - encrypted_client_id->set_service_id(service_certificate.service_id()); - encrypted_client_id->set_service_certificate_serial_number( - service_certificate.serial_number()); - - std::string iv(KEY_IV_SIZE, 0); - std::string key(KEY_SIZE, 0); - - if (!session_->GetRandom(key.size(), reinterpret_cast(&key[0]))) { - return false; - } - if (!session_->GetRandom(iv.size(), reinterpret_cast(&iv[0]))) { - return false; - } - std::string id, enc_id, enc_key; - client_id->SerializeToString(&id); - - AesCbcKey aes; - if (!aes.Init(key)) return false; - if (!aes.Encrypt(id, &enc_id, &iv)) return false; - - RsaPublicKey rsa; - if (!rsa.Init(service_certificate.public_key())) return false; - if (!rsa.Encrypt(key, &enc_key)) return false; - - encrypted_client_id->set_encrypted_client_id_iv(iv); - encrypted_client_id->set_encrypted_privacy_key(enc_key); - encrypted_client_id->set_encrypted_client_id(enc_id); - license_request.clear_client_id(); - } + CdmResponseType status = + PrepareClientId(privacy_mode_enabled, service_certificate, app_parameters, + &license_request); + if (NO_ERROR != status) return false; // Content Identification may be a cenc_id, a webm_id or a license_id LicenseRequest_ContentIdentification* content_id = @@ -463,7 +305,9 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data, } CdmResponseType CdmLicense::PrepareKeyUpdateRequest( - bool is_renewal, CdmKeyMessage* signed_request, std::string* server_url) { + bool is_renewal, const CdmAppParameterMap& app_parameters, + const CdmSessionId& session_id, CdmKeyMessage* signed_request, + std::string* server_url) { if (!initialized_) { LOGE("CdmLicense::PrepareKeyUpdateRequest: not initialized"); return LICENSE_PARSER_NOT_INITIALIZED_1; @@ -485,6 +329,22 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest( license_request.set_request_time(clock_->GetCurrentTime()); + if (renew_with_client_id_) { + std::string service_certificate; + bool privacy_mode_enabled = Properties::UsePrivacyMode(session_id); + if (privacy_mode_enabled) { + if (!GetServiceCertificate(session_id, &service_certificate)) { + return PrepareServiceCertificateRequest(signed_request, server_url) + ? KEY_MESSAGE + : SERVICE_CERTIFICATE_REQUEST_GENERATE_ERROR; + } + } + CdmResponseType status = + PrepareClientId(privacy_mode_enabled, service_certificate, + app_parameters, &license_request); + if (NO_ERROR != status) return status; + } + LicenseRequest_ContentIdentification_ExistingLicense* current_license = license_request.mutable_content_id()->mutable_license(); LicenseIdentification license_id = policy_engine_->license_id(); @@ -653,6 +513,10 @@ CdmResponseType CdmLicense::HandleKeyResponse( policy_engine_->SetLicense(license); + if (license.policy().has_renew_with_client_id()) { + renew_with_client_id_ = license.policy().renew_with_client_id(); + } + CdmResponseType resp = session_->LoadKeys( signed_response.msg(), signed_response.signature(), mac_key_iv, mac_key, key_array, provider_session_token_); @@ -684,8 +548,19 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse( return LICENSE_RESPONSE_PARSE_ERROR_2; } - if (signed_response.type() == SignedMessage::ERROR_RESPONSE) { - return HandleKeyErrorResponse(signed_response); + switch (signed_response.type()) { + case SignedMessage::LICENSE: + break; + case SignedMessage::SERVICE_CERTIFICATE: + return CdmLicense::HandleServiceCertificateResponse(signed_response); + case SignedMessage::ERROR_RESPONSE: + return HandleKeyErrorResponse(signed_response); + default: + LOGE( + "CdmLicense::HandleKeyUpdateResponse: unrecognized signed message " + "type: %d", + signed_response.type()); + return INVALID_LICENSE_TYPE; } if (!signed_response.has_signature()) { @@ -708,6 +583,10 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse( policy_engine_->UpdateLicense(license); + if (license.policy().has_renew_with_client_id()) { + renew_with_client_id_ = license.policy().renew_with_client_id(); + } + if (!is_renewal) { if (!license.id().has_provider_session_token()) return KEY_ADDED; @@ -842,27 +721,32 @@ bool CdmLicense::RestoreLicenseForRelease( SignedMessage signed_response; if (!signed_response.ParseFromString(license_response)) { - LOGE("CdmLicense::RestoreLicenseForRelease: unable to parse signed license" - " response"); + LOGE( + "CdmLicense::RestoreLicenseForRelease: unable to parse signed license" + " response"); return false; } if (SignedMessage::LICENSE != signed_response.type()) { - LOGE("CdmLicense::RestoreLicenseForRelease: unrecognized signed message " - "type: %d", signed_response.type()); + LOGE( + "CdmLicense::RestoreLicenseForRelease: unrecognized signed message " + "type: %d", + signed_response.type()); return false; } if (!signed_response.has_signature()) { - LOGE("CdmLicense::RestoreLicenseForRelease: license response is not" - " signed"); + LOGE( + "CdmLicense::RestoreLicenseForRelease: license response is not" + " signed"); return false; } License license; if (!license.ParseFromString(signed_response.msg())) { - LOGE("CdmLicense::RestoreLicenseForRelease: unable to parse license" - " response"); + LOGE( + "CdmLicense::RestoreLicenseForRelease: unable to parse license" + " response"); return false; } @@ -994,6 +878,183 @@ CdmResponseType CdmLicense::HandleKeyErrorResponse( } } +CdmResponseType CdmLicense::PrepareClientId( + bool encrypt, const std::string& certificate, + const CdmAppParameterMap& app_parameters, LicenseRequest* license_request) { + ClientIdentification* client_id = license_request->mutable_client_id(); + + if (Properties::use_certificates_as_identification()) + client_id->set_type(ClientIdentification::DEVICE_CERTIFICATE); + else + client_id->set_type(ClientIdentification::KEYBOX); + client_id->set_token(token_); + + ClientIdentification_NameValue* client_info; + CdmAppParameterMap::const_iterator iter; + for (iter = app_parameters.begin(); iter != app_parameters.end(); iter++) { + client_info = client_id->add_client_info(); + client_info->set_name(iter->first); + client_info->set_value(iter->second); + } + std::string value; + if (Properties::GetCompanyName(&value)) { + client_info = client_id->add_client_info(); + client_info->set_name(kCompanyNameKey); + client_info->set_value(value); + } + if (Properties::GetModelName(&value)) { + client_info = client_id->add_client_info(); + client_info->set_name(kModelNameKey); + client_info->set_value(value); + } + if (Properties::GetArchitectureName(&value)) { + client_info = client_id->add_client_info(); + client_info->set_name(kArchitectureNameKey); + client_info->set_value(value); + } + if (Properties::GetDeviceName(&value)) { + client_info = client_id->add_client_info(); + client_info->set_name(kDeviceNameKey); + client_info->set_value(value); + } + if (Properties::GetProductName(&value)) { + client_info = client_id->add_client_info(); + client_info->set_name(kProductNameKey); + client_info->set_value(value); + } + if (Properties::GetBuildInfo(&value)) { + client_info = client_id->add_client_info(); + client_info->set_name(kBuildInfoKey); + client_info->set_value(value); + } + if (session_->GetDeviceUniqueId(&value)) { + client_info = client_id->add_client_info(); + client_info->set_name(kDeviceIdKey); + client_info->set_value(value); + } + if (Properties::GetWVCdmVersion(&value)) { + client_info = client_id->add_client_info(); + client_info->set_name(kWVCdmVersionKey); + client_info->set_value(value); + } + + ClientIdentification_ClientCapabilities* client_capabilities = + client_id->mutable_client_capabilities(); + bool supports_usage_information; + if (session_->UsageInformationSupport(&supports_usage_information)) { + client_capabilities->set_session_token(supports_usage_information); + } + + client_capabilities->set_anti_rollback_usage_table( + session_->IsAntiRollbackHwPresent()); + + uint32_t api_version = 0; + if (session_->GetApiVersion(&api_version)) { + client_capabilities->set_oem_crypto_api_version(api_version); + } + + CryptoSession::HdcpCapability current_version, max_version; + if (session_->GetHdcpCapabilities(¤t_version, &max_version)) { + switch (max_version) { + case HDCP_NONE: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE); + break; + case HDCP_V1: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1); + break; + case HDCP_V2: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2); + break; + case HDCP_V2_1: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1); + break; + case HDCP_V2_2: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2); + break; + case HDCP_NO_DIGITAL_OUTPUT: + client_capabilities->set_max_hdcp_version( + video_widevine_server::sdk:: + ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NO_DIGITAL_OUTPUT); + break; + default: + LOGW( + "CdmLicense::PrepareClientId: unexpected HDCP max capability " + "version %d", + max_version); + } + } + + if (encrypt) { + EncryptedClientIdentification* encrypted_client_id = + license_request->mutable_encrypted_client_id(); + DeviceCertificate service_certificate; + + if (!service_certificate.ParseFromString(certificate)) { + LOGE( + "CdmLicense::PrepareClientId: unable to parse retrieved " + "service certificate"); + return PARSE_SERVICE_CERTIFICATE_ERROR; + } + + if (service_certificate.type() != + video_widevine_server::sdk::DeviceCertificate_CertificateType_SERVICE) { + LOGE( + "CdmLicense::PrepareClientId: retrieved certificate not of type" + " service, %d", + service_certificate.type()); + return SERVICE_CERTIFICATE_TYPE_ERROR; + } + encrypted_client_id->set_service_id(service_certificate.service_id()); + encrypted_client_id->set_service_certificate_serial_number( + service_certificate.serial_number()); + + std::string iv(KEY_IV_SIZE, 0); + std::string key(KEY_SIZE, 0); + + if (!session_->GetRandom(key.size(), reinterpret_cast(&key[0]))) + return CLIENT_ID_GENERATE_RANDOM_ERROR; + if (!session_->GetRandom(iv.size(), reinterpret_cast(&iv[0]))) + return CLIENT_ID_GENERATE_RANDOM_ERROR; + std::string id, enc_id, enc_key; + client_id->SerializeToString(&id); + + AesCbcKey aes; + if (!aes.Init(key)) return CLIENT_ID_AES_INIT_ERROR; + if (!aes.Encrypt(id, &enc_id, &iv)) return CLIENT_ID_AES_ENCRYPT_ERROR; + + RsaPublicKey rsa; + if (!rsa.Init(service_certificate.public_key())) + return CLIENT_ID_RSA_INIT_ERROR; + if (!rsa.Encrypt(key, &enc_key)) return CLIENT_ID_RSA_ENCRYPT_ERROR; + + encrypted_client_id->set_encrypted_client_id_iv(iv); + encrypted_client_id->set_encrypted_privacy_key(enc_key); + encrypted_client_id->set_encrypted_client_id(enc_id); + license_request->clear_client_id(); + } + return NO_ERROR; +} + +bool CdmLicense::GetServiceCertificate(const CdmSessionId& session_id, + std::string* service_certificate) { + if (!Properties::GetServiceCertificate(session_id, service_certificate) || + service_certificate->empty()) + *service_certificate = service_certificate_; + + if (service_certificate->size() > 0) return true; + return false; +} + template bool CdmLicense::PrepareContentId(const CdmLicenseType license_type, const std::string& request_id, diff --git a/libwvdrmengine/cdm/core/src/license_protocol.proto b/libwvdrmengine/cdm/core/src/license_protocol.proto index cc23e7cf..9079594e 100644 --- a/libwvdrmengine/cdm/core/src/license_protocol.proto +++ b/libwvdrmengine/cdm/core/src/license_protocol.proto @@ -78,6 +78,10 @@ message License { // Indicates that the license shall be sent for renewal when usage is // started. optional bool renew_with_usage = 11 [default = false]; + + // Indicates to client that license renewal and release requests ought to + // include ClientIdentification (client_id). + optional bool renew_with_client_id = 12 [default = false]; } message KeyContainer { @@ -167,6 +171,8 @@ message License { optional KeyType type = 4; optional SecurityLevel level = 5 [default = SW_SECURE_CRYPTO]; optional OutputProtection required_protection = 6; + // NOTE: Use of requested_protection is not recommended as it is only + // supported on a small number of platforms. optional OutputProtection requested_protection = 7; optional KeyControl key_control = 8; optional OperatorSessionKeyPermissions operator_session_key_permissions = 9; @@ -174,7 +180,13 @@ message License { // content being decrypted/decoded falls within one of the specified ranges, // the optional required_protections may be applied. Otherwise an error will // be reported. + // NOTE: Use of this feature is not recommended, as it is only supported on + // a small number of platforms. repeated VideoResolutionConstraint video_resolution_constraints = 10; + // Optional flag to indicate the key must only be used if the client + // supports anti rollback of the user table. Content provider can query the + // client capabilities to determine if the client support this feature. + optional bool anti_rollback_usage_table = 11 [default = false]; } optional LicenseIdentification id = 1; @@ -286,36 +298,6 @@ message SignedMessage { optional RemoteAttestation remote_attestation = 5; } -// This message is used to pass optional data on initial license issuance. -message SessionInit { - optional bytes session_id = 1; - optional bytes purchase_id = 2; - // master_signing_key should be 128 bits in length. - optional bytes master_signing_key = 3; - // signing_key should be 512 bits in length to be split into two - // (server || client) HMAC-SHA256 keys. - optional bytes signing_key = 4; - optional int64 license_start_time = 5; - // Client token for the session. This session is for use by the license - // provider, and is akin to a client cookie. It will be copied to - // License::provider_client_token, and sent back by the client in - // ClientIdentification::provider_client_token in all license requests - // thereafter. - optional bytes provider_client_token = 6; - // Session token for the session. This token is for use by the license - // provider, and is akin to a session cookie. It will be copied to - // LicenseIdentfication::provider_session_token, and sent back in all - // license renewal and release requests for the session thereafter. - optional bytes provider_session_token = 7; -} - -// This message is used by the server to preserve and restore session state. -message SessionState { - optional LicenseIdentification license_id = 1; - optional bytes signing_key = 2; - optional uint32 keybox_system_id = 3; -} - // ---------------------------------------------------------------------------- // certificate_provisioning.proto // ---------------------------------------------------------------------------- diff --git a/libwvdrmengine/cdm/core/test/config_test_env.cpp b/libwvdrmengine/cdm/core/test/config_test_env.cpp index 8e2baac2..d1bf72d6 100644 --- a/libwvdrmengine/cdm/core/test/config_test_env.cpp +++ b/libwvdrmengine/cdm/core/test/config_test_env.cpp @@ -5,7 +5,8 @@ namespace { const std::string kWidevineKeySystem = "com.widevine.alpha"; -// Content Protection license server data +// Content Protection license server (UAT) data +// For staging server replace url with http://wv-staging-proxy.appspot.com/proxy const std::string kCpLicenseServer = "http://widevine-proxy.appspot.com/proxy"; const std::string kCpClientAuth = ""; const std::string kCpKeyId = diff --git a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp index ac5e3648..e2647104 100644 --- a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp @@ -130,6 +130,7 @@ struct LicenseInfo { std::string key_release_url; int64_t playback_start_time; int64_t last_playback_time; + std::string app_parameters; std::string file_data; }; @@ -236,7 +237,7 @@ LicenseInfo license_test_data[] = { "0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF" "A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0" "BEA6CABACA1C2C"), - "https://test.google.com/license/GetCencLicense", 0x0, 0x0, + "https://test.google.com/license/GetCencLicense", 0x0, 0x0, "", wvcdm::a2bs_hex( "0AA8150802100122A1150801121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" @@ -417,8 +418,9 @@ LicenseInfo license_test_data[] = { "A68F051A20BDA6A56F7CBFD0942198F87C23A34AA5CBD64AFEB134277774" "CCF8E789D815DD"), "https://test.google.com/license/GetCencLicense", 0x12345678, 0x12348765, + "Name1 Value1", wvcdm::a2bs_hex( - "0AB0150802100122A9150802121408011210303132333435363738394142434445461" + "0AC1150802100122BA150802121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" @@ -497,8 +499,8 @@ LicenseInfo license_test_data[] = { "106B63746C00000000CA3A6A75000000002083E5A68F051A20BDA6A56F7CBFD094219" "8F87C23A34AA5CBD64AFEB134277774CCF8E789D815DD3A2E68747470733A2F2F7465" "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" - "36540F8ACD1910148E58ED291011220C47DDCB3FA0DF569B95DD9F46F83608632C93E" - "E0EA5C9360D7D537730D028EC6")}, + "36540F8ACD1910148E58ED29101520F0A054E616D6531120656616C7565311220BE69" + "AAB25B481BCAF57B741518D9F9DB8E3A7A6911D10C53D4F4649D78393C65")}, // license 2 {"ksidE8C37662C88DC673", DeviceFiles::kLicenseStateReleasing, @@ -597,9 +599,9 @@ LicenseInfo license_test_data[] = { "A68F051A2041EF0A9267D613D17AA90E1D1DA5BE091860E5E296D41D6D0F" "75E73660C279B3"), "https://test.google.com/license/GetCencLicense", 0x0123456789abcdef, - 0x123456789abfedc, + 0x123456789abfedc, "Name1 Value1 Name2 Param2", wvcdm::a2bs_hex( - "0AB8150802100122B1150802121408011210303132333435363738394142434445461" + "0AE7150802100122E0150802121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" @@ -678,8 +680,10 @@ LicenseInfo license_test_data[] = { "106B63746C000000001FF4944E000000002082E7A68F051A2041EF0A9267D613D17AA" "90E1D1DA5BE091860E5E296D41D6D0F75E73660C279B33A2E68747470733A2F2F7465" "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" - "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910112201486F63DAF90694D3C63C8" - "EA8D2B68A7592252154A193D4DF8CEA95635EA0543")}}; + "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910152150A054E616D6531120C5661" + "6C756531204E616D653252160A0C4E616D653220506172616D321206506172616D321" + "2203653BA57F16FE28D66D9F7A76128B7AD7F33680815FF70A3684617DE1FBB0F9" + "F")}}; // Sample license data and related data for storage and use for offline // playback. The license data and URLs in this test are not real. @@ -782,7 +786,7 @@ LicenseInfo license_update_test_data[] = { "B68F051A2000351030900858FCFD6977B67803ADFD1280AA661E6B0BD30B" "08B2C467355129"), "https://test.google.com/license/GetCencLicense", 0x0123456789abcdef, - 0x123456789abfedc, + 0x123456789abfedc, "Name1 Value1 Name2 Value2 Name3 Value3", wvcdm::a2bs_hex( "0AB8150802100122B1150801121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" @@ -867,7 +871,7 @@ LicenseInfo license_update_test_data[] = { "126C3222C2E584A50D08EFA75BC4FC091E7034E1DD")}, // license being released. all fields are identical except for license // state and hashed file data - {"", DeviceFiles::kLicenseStateReleasing, "", "", "", "", "", "", 0, 0, + {"", DeviceFiles::kLicenseStateReleasing, "", "", "", "", "", "", 0, 0, "", wvcdm::a2bs_hex( "0AB8150802100122B1150802121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" @@ -951,6 +955,190 @@ LicenseInfo license_update_test_data[] = { "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910112203D8933A735A22FE27AA956" "802B597529E8FFCB91A5F3CBBB3CE0C38E4AF3DC88")}}; +// Application parameters were added to the License message. This data +// is used to verify that a License saved without application parameters can +// be read out correctly by an updated version of the CDM. +LicenseInfo license_app_parameters_backwards_compatibility_test_data = { + + "ksid54C57C966E23CEF5", DeviceFiles::kLicenseStateActive, + wvcdm::a2bs_hex("0801121030313233343536373839414243444546"), + wvcdm::a2bs_hex( + "080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591B" + "C4D07A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD" + "55FB685FDB3025574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EF" + "FA0E5DFC3DE9A34BA5F08BE349553C319A9FB274905A8770ADC9CA4A2CBC" + "D8E556A1587FA18BFD4D286C644A6904F19EAAFBDFADD3B371B306D0B289" + "F459B491C814B5AD1F747610E990A60248A7DA5152F1CCFC047EF4230013" + "1F9C4758F4D9F30579393B860AAD9AD2EE43D721D6DB9F5800EF188386B9" + "4825AE05A883AC976D6970DF43EA6C83B86CE6D0F540207725B9890FCCEC" + "83A49027872DAFD2740B7748E9C3B1752D6F12859CED07E8882969B433EC" + "66F17FFC29AC6FDBEA79230B0FAED5D94CF6B829A420BBE3270323941776" + "EE60DD6BFD660BDDCA870203010001288001300112800250D1F8B1ECF849" + "B60FF93E37C4DEEF09E6FFB10BCFC996A4A24B7AA96928835ED5A72E1584" + "6D0A14015733239BD8B6E6D5E5D229B08394CE1E0692C159C44337CA7CAF" + "88476449B068D9D2FADED8EB1BC0F4B8F0FCAF293E8690E7403209534180" + "3408A0E8279E545945EE97838FDE7812F7171C3CC4F5ECF9418BBF1D336C" + "E58F4CBB1B44D4ADE6BF3364BAE7EC093281846E569E13E7719014030A60" + "59044FE7BBFF3E8F5723AEDD54DC6E0D041B309D7700B55575690E95CE60" + "85D0914F991C5F45E98CBB9C45BA33F47FD0862EBCC7EEBA8E60643C86E8" + "5476B18AEF8DE871571A75681A75F75028A5B58751C09A5296AAE99CEDCD" + "9785E9E2103240D40A1AB6050AB002080112102CE5CCF42200D6B5BCCF33" + "D7CC2D9C7018EAD1B88D05228E023082010A0282010100BE1B661EEC4700" + "DF4B0C83292D02AE029B8A224DD3048125049F74E30E1257FC2BE8D9CFAF" + "0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4396A805833730D" + "C6E534C62408B7C5076FC22568021C59ED34F98487196DA32078DAFCA37C" + "7CFB8E79612FA384963DF2167D5E87305D7BC92D621C10160672C27B9A69" + "1B1534F60D78C5893E40C5FF8A3F9DF8898612E9A5CCB56F4A0CC2A61A7A" + "EB04A9DCC015D9BC37DEF2AB9EAA9AAFD838869081D9249755F129BB0DBE" + "CA3B894975A65A36FD005CE77CD407E925D3172E33122A11D327968A08F8" + "E771FAEB2540EB52D17C4906405F47C31F60F0AF6C78AF53291B236E692B" + "506A2AF92AF43E3A81020301000128800130011280033A08A60418E5C81B" + "8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259834000FE35DCD8" + "14426F9C5D332418ED94C9C0C992217B1B6DC01C99085A3C3956C8267B87" + "73BABCF3F2C841C67D830F9DBC780DD68BF4E2FE424C6A54123BE4B2A1F7" + "E1F4DB58AB1164DAE9CF75C3392284A44B8CDB85D837E86C6B908243987E" + "552C8693878C9A1B7BEA3759783036F1595C406D6CBBA7F8642A9B3B244D" + "AA1F00531D0B908ADE4B533FD9FAFA21D0FB0C033D2AD5DDF24C60F4FAC3" + "0820758877F2E1A78EB44E9336DCFAFDF572BB22A84A5DEFDF2EB87B61DE" + "26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1C379C96961316B" + "5D2A66F38C222091AF74141B6CAF93507485A5D8F82808025451824F00C8" + "B6A0CD5803F6564584138C8B18BC679B442D837307B5CC90B1FD1FD32288" + "B4A5D18D2D80E5E6A7A9EFD255B8B363038BCC67AF534EAEE4A5903E304E" + "ED4990BB5BE735DB027A6DE35329D321EC051B956C55A5B11674017517FC" + "C3C7FF7397C13A7B7087A1F6AEC7F6761A130A0C636F6D70616E795F6E61" + "6D6512034C47451A150A0A6D6F64656C5F6E616D6512074E657875732034" + "1A200A116172636869746563747572655F6E616D65120B61726D65616269" + "2D7637611A130A0B6465766963655F6E616D6512046D616B6F1A150A0C70" + "726F647563745F6E616D6512056F6363616D1A440A0A6275696C645F696E" + "666F1236676F6F676C652F6F6363616D2F6D616B6F3A342E332F4A425F4D" + "52322F3731343239313A7573657264656275672F6465762D6B6579731A21" + "0A096465766963655F696412144C474D4332303132313030353030363339" + "32373812250A230A14080112103031323334353637383941424344454610" + "021A09393837363534333231180120002A0C333934303739343733370000" + "30151A8002734FBDED946EB74A1B61811C4C4A491214F6BEA125A80F0141" + "65B28AA97AD0AF60E4D129EB7F424AD659F24E5EED4B702BEE328E38B72C" + "A6F38CD0ECFD2E6D7B98147744C9B8A9610B3BDFE17675FF7D584C5BF680" + "64B0FE513FC322C9148795E4C2F2443C3024F5C1F29E6FEFB6D77005DAB2" + "2CD2B63131908DE4D88795BB931CEA38452CC568BE25032245E372F07A12" + "97F51748C7EA02F2C88360AFE7ABBC71DCDD5366126258E5AFA27C2A20B3" + "39FA1E7AE925B494B361F6F7116F20BE8EE6E446146027F4FD4300F4A0B0" + "A3361EE34925F338D0AACF20AE919B4BAE81C1D57A8D2B8FA38732A57697" + "C316C180717C182A971C94E4AC4C7DF8F161CB8CC1"), + wvcdm::a2bs_hex( + "080212CC020A190A0939383736353433323112084B9F26DAB8B06E112002" + "2800124108011801301E4239687474703A2F2F6B69723033666370673137" + "342E7769646576696E652E6E65742F7769646576696E652F6367692D6269" + "6E2F64726D2E6367691A6612102531DFD6CCEA511D00F8C0172F1189AA1A" + "5057FF9D9DBD5A205B1DEB075E4A90467C1E074CDE6071BFF831AD590BD5" + "D117614F33CE2C3CE1824FC0D54B36ECEAE58DF5C8F9347C2FEED17A3327" + "E8F52B8ECA6313A1FA6A042EB9525DD328113C05F920011A7E0A10303132" + "3334353637383941424344454612106D23622142B58F6D1EDD33AF3ECD2C" + "7E1A20884EE13BEA9DECDDBF68B532131C82B11CEC4D23C7FA9F3EF4C5EE" + "172E7C9736200242340A2050BFE71BB1BA683E35E0B49BB33048E5103FBB" + "B9C3E1CD6EBCDA7DD485DBAF431210D69D6F14C95CB6CFDB998E50D00F4D" + "A020DBDFA68F051A20AE5D6895E70F86F42F5FE3C58A505A865D05AB94B1" + "ABAA6CC59C3322F61C458D228002331F2BE95B5C796E0921CC27A7295501" + "DA10044E5CA36C0E2866FF068EA3515A6786BD5D60D74D80C6BA8BE6AAD0" + "85AF967909A143171E9CDDE36EA528402867CD04FB6F97A150CDE55F9B81" + "9F4104BEF48E4280D76645569E10AEF524D34D865B5B9E3EBC66C45EEBBE" + "16AB04493E7AEC4F99E7A99F3FC08FA431BECCC1978A079FA4801DB75E13" + "29A9921604E6F80CB148AA2DD5C8348057E9F4FC2AEA57EA4D215D0A8D48" + "6294860DFB4F4C42D57D9542B76179E179DD4AA23F9F7B2AE432B39E4CE8" + "F156E84877DDA781AAAAFC797FF75AFE2019ADC3A2E419BF0253C705BD47" + "97A96866AC4C059AD8F2E9C6B617C60C6ADCDB894C25F0C7D29252F52FD5"), + wvcdm::a2bs_hex( + "08011231121D1A1B0A190A0939383736353433323112084B9F26DAB8B06E" + "112002280018022A0C31353532333030360000000030151A20C30375683C" + "4D2033E05DCC95DDFB278CFB5125A021C3C043A16ACC933A768A27"), + wvcdm::a2bs_hex( + "0802123B0A190A0939383736353433323112084B9F26DAB8B06E11200228" + "0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF" + "A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0" + "BEA6CABACA1C2C"), + "https://test.google.com/license/GetCencLicense", 0x0, 0x0, "", + wvcdm::a2bs_hex( + "0AA8150802100122A1150801121408011210303132333435363738394142434445461" + "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" + "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" + "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" + "E349553C319A9FB274905A8770ADC9CA4A2CBCD8E556A1587FA18BFD4D286C644A690" + "4F19EAAFBDFADD3B371B306D0B289F459B491C814B5AD1F747610E990A60248A7DA51" + "52F1CCFC047EF42300131F9C4758F4D9F30579393B860AAD9AD2EE43D721D6DB9F580" + "0EF188386B94825AE05A883AC976D6970DF43EA6C83B86CE6D0F540207725B9890FCC" + "EC83A49027872DAFD2740B7748E9C3B1752D6F12859CED07E8882969B433EC66F17FF" + "C29AC6FDBEA79230B0FAED5D94CF6B829A420BBE3270323941776EE60DD6BFD660BDD" + "CA870203010001288001300112800250D1F8B1ECF849B60FF93E37C4DEEF09E6FFB10" + "BCFC996A4A24B7AA96928835ED5A72E15846D0A14015733239BD8B6E6D5E5D229B083" + "94CE1E0692C159C44337CA7CAF88476449B068D9D2FADED8EB1BC0F4B8F0FCAF293E8" + "690E74032095341803408A0E8279E545945EE97838FDE7812F7171C3CC4F5ECF9418B" + "BF1D336CE58F4CBB1B44D4ADE6BF3364BAE7EC093281846E569E13E7719014030A605" + "9044FE7BBFF3E8F5723AEDD54DC6E0D041B309D7700B55575690E95CE6085D0914F99" + "1C5F45E98CBB9C45BA33F47FD0862EBCC7EEBA8E60643C86E85476B18AEF8DE871571" + "A75681A75F75028A5B58751C09A5296AAE99CEDCD9785E9E2103240D40A1AB6050AB0" + "02080112102CE5CCF42200D6B5BCCF33D7CC2D9C7018EAD1B88D05228E023082010A0" + "282010100BE1B661EEC4700DF4B0C83292D02AE029B8A224DD3048125049F74E30E12" + "57FC2BE8D9CFAF0BFFCACAF7305351771C78FA451F13AF5EEBFB360941A4396A80583" + "3730DC6E534C62408B7C5076FC22568021C59ED34F98487196DA32078DAFCA37C7CFB" + "8E79612FA384963DF2167D5E87305D7BC92D621C10160672C27B9A691B1534F60D78C" + "5893E40C5FF8A3F9DF8898612E9A5CCB56F4A0CC2A61A7AEB04A9DCC015D9BC37DEF2" + "AB9EAA9AAFD838869081D9249755F129BB0DBECA3B894975A65A36FD005CE77CD407E" + "925D3172E33122A11D327968A08F8E771FAEB2540EB52D17C4906405F47C31F60F0AF" + "6C78AF53291B236E692B506A2AF92AF43E3A81020301000128800130011280033A08A" + "60418E5C81B8D71A5C0A28C26999FF4FA992E14107CA8A9E6A2B36259834000FE35DC" + "D814426F9C5D332418ED94C9C0C992217B1B6DC01C99085A3C3956C8267B8773BABCF" + "3F2C841C67D830F9DBC780DD68BF4E2FE424C6A54123BE4B2A1F7E1F4DB58AB1164DA" + "E9CF75C3392284A44B8CDB85D837E86C6B908243987E552C8693878C9A1B7BEA37597" + "83036F1595C406D6CBBA7F8642A9B3B244DAA1F00531D0B908ADE4B533FD9FAFA21D0" + "FB0C033D2AD5DDF24C60F4FAC30820758877F2E1A78EB44E9336DCFAFDF572BB22A84" + "A5DEFDF2EB87B61DE26EE9C4CEAA646A2AFDB2BB953845E6D7FE6F79A9501D1C379C9" + "6961316B5D2A66F38C222091AF74141B6CAF93507485A5D8F82808025451824F00C8B" + "6A0CD5803F6564584138C8B18BC679B442D837307B5CC90B1FD1FD32288B4A5D18D2D" + "80E5E6A7A9EFD255B8B363038BCC67AF534EAEE4A5903E304EED4990BB5BE735DB027" + "A6DE35329D321EC051B956C55A5B11674017517FCC3C7FF7397C13A7B7087A1F6AEC7" + "F6761A130A0C636F6D70616E795F6E616D6512034C47451A150A0A6D6F64656C5F6E6" + "16D6512074E6578757320341A200A116172636869746563747572655F6E616D65120B" + "61726D656162692D7637611A130A0B6465766963655F6E616D6512046D616B6F1A150" + "A0C70726F647563745F6E616D6512056F6363616D1A440A0A6275696C645F696E666F" + "1236676F6F676C652F6F6363616D2F6D616B6F3A342E332F4A425F4D52322F3731343" + "239313A7573657264656275672F6465762D6B6579731A210A096465766963655F6964" + "12144C474D433230313231303035303036333932373812250A230A140801121030313" + "23334353637383941424344454610021A09393837363534333231180120002A0C3339" + "3430373934373337000030151A8002734FBDED946EB74A1B61811C4C4A491214F6BEA" + "125A80F014165B28AA97AD0AF60E4D129EB7F424AD659F24E5EED4B702BEE328E38B7" + "2CA6F38CD0ECFD2E6D7B98147744C9B8A9610B3BDFE17675FF7D584C5BF68064B0FE5" + "13FC322C9148795E4C2F2443C3024F5C1F29E6FEFB6D77005DAB22CD2B63131908DE4" + "D88795BB931CEA38452CC568BE25032245E372F07A1297F51748C7EA02F2C88360AFE" + "7ABBC71DCDD5366126258E5AFA27C2A20B339FA1E7AE925B494B361F6F7116F20BE8E" + "E6E446146027F4FD4300F4A0B0A3361EE34925F338D0AACF20AE919B4BAE81C1D57A8" + "D2B8FA38732A57697C316C180717C182A971C94E4AC4C7DF8F161CB8CC122F6040802" + "12CC020A190A0939383736353433323112084B9F26DAB8B06E1120022800124108011" + "801301E4239687474703A2F2F6B69723033666370673137342E7769646576696E652E" + "6E65742F7769646576696E652F6367692D62696E2F64726D2E6367691A6612102531D" + "FD6CCEA511D00F8C0172F1189AA1A5057FF9D9DBD5A205B1DEB075E4A90467C1E074C" + "DE6071BFF831AD590BD5D117614F33CE2C3CE1824FC0D54B36ECEAE58DF5C8F9347C2" + "FEED17A3327E8F52B8ECA6313A1FA6A042EB9525DD328113C05F920011A7E0A103031" + "323334353637383941424344454612106D23622142B58F6D1EDD33AF3ECD2C7E1A208" + "84EE13BEA9DECDDBF68B532131C82B11CEC4D23C7FA9F3EF4C5EE172E7C9736200242" + "340A2050BFE71BB1BA683E35E0B49BB33048E5103FBBB9C3E1CD6EBCDA7DD485DBAF4" + "31210D69D6F14C95CB6CFDB998E50D00F4DA020DBDFA68F051A20AE5D6895E70F86F4" + "2F5FE3C58A505A865D05AB94B1ABAA6CC59C3322F61C458D228002331F2BE95B5C796" + "E0921CC27A7295501DA10044E5CA36C0E2866FF068EA3515A6786BD5D60D74D80C6BA" + "8BE6AAD085AF967909A143171E9CDDE36EA528402867CD04FB6F97A150CDE55F9B819" + "F4104BEF48E4280D76645569E10AEF524D34D865B5B9E3EBC66C45EEBBE16AB04493E" + "7AEC4F99E7A99F3FC08FA431BECCC1978A079FA4801DB75E1329A9921604E6F80CB14" + "8AA2DD5C8348057E9F4FC2AEA57EA4D215D0A8D486294860DFB4F4C42D57D9542B761" + "79E179DD4AA23F9F7B2AE432B39E4CE8F156E84877DDA781AAAAFC797FF75AFE2019A" + "DC3A2E419BF0253C705BD4797A96866AC4C059AD8F2E9C6B617C60C6ADCDB894C25F0" + "C7D29252F52FD52A5708011231121D1A1B0A190A0939383736353433323112084B9F2" + "6DAB8B06E112002280018022A0C31353532333030360000000030151A20C30375683C" + "4D2033E05DCC95DDFB278CFB5125A021C3C043A16ACC933A768A2732610802123B0A1" + "90A0939383736353433323112084B9F26DAB8B06E112002280112001A16200342120A" + "106B63746C0000000000ECDCBE0000000020DBDFA68F051A20182F029E35047A3841F" + "A176C74E5B387350E8D58DEA6878FF0BEA6CABACA1C2C3A2E68747470733A2F2F7465" + "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" + "365400048001220CD0599C2B85D9F2D573AC7893CE77CB5A10B326828BA8C89047505" + "A8C9B606AC")}; + struct UsageInfo { std::string provider_session_token; std::string license_request; @@ -1276,6 +1464,25 @@ class DeviceFilesTest : public ::testing::Test { data.key_release_url.size() + 2 * sizeof(int64_t); } + CdmAppParameterMap GetAppParameters(std::string str) { + CdmAppParameterMap app_parameters; + size_t start_pos = 0; + size_t len = str.length(); + bool more = true; + while (start_pos < len) { + size_t name_end_pos = str.find(' ', start_pos); + if (name_end_pos == std::string::npos) return app_parameters; + if (name_end_pos + 1 >= len) return app_parameters; + size_t value_end_pos = str.find(' ', name_end_pos + 1); + app_parameters[str.substr(start_pos, name_end_pos)] = + str.substr(name_end_pos + 1, value_end_pos); + if (value_end_pos == std::string::npos || value_end_pos + 1 >= len) + return app_parameters; + start_pos = value_end_pos + 1; + } + return app_parameters; + } + std::string device_base_path_; }; @@ -1284,8 +1491,7 @@ class DeviceFilesStoreTest : public DeviceFilesTest, struct CertStorageVariant { CertStorageVariant(bool dir_exists_value, const std::string& origin_value) - : dir_exists(dir_exists_value), - origin(origin_value) {} + : dir_exists(dir_exists_value), origin(origin_value) {} const bool dir_exists; const std::string origin; @@ -1344,6 +1550,32 @@ MATCHER_P6(Contains, str1, str2, str3, str4, str5, str6, "") { data.find(str6) != std::string::npos); } +MATCHER_P7(Contains, str1, str2, str3, str4, str5, str6, map7, "") { + // Estimating the length of data. We can have gmock provide length + // as well as pointer to data but that will introduce a dependency on tr1 + size_t map7_len = 0; + CdmAppParameterMap::const_iterator itr = map7.begin(); + for (itr = map7.begin(); itr != map7.end(); ++itr) { + map7_len += itr->first.length(); + map7_len += itr->second.length(); + } + std::string data(arg, str1.size() + str2.size() + str3.size() + str4.size() + + str5.size() + str6.size() + map7_len + + kProtobufEstimatedOverhead); + bool map7_entries_present = true; + for (itr = map7.begin(); itr != map7.end(); ++itr) { + map7_entries_present = map7_entries_present && + data.find(itr->first) != std::string::npos && + data.find(itr->second) != std::string::npos; + } + return (data.find(str1) != std::string::npos && + data.find(str2) != std::string::npos && + data.find(str3) != std::string::npos && + data.find(str4) != std::string::npos && + data.find(str5) != std::string::npos && + data.find(str6) != std::string::npos && map7_entries_present); +} + TEST_P(DeviceCertificateStoreTest, StoreCertificate) { MockFile file; CertStorageVariant params = GetParam(); @@ -1379,8 +1611,8 @@ TEST_P(DeviceCertificateStoreTest, StoreCertificate) { INSTANTIATE_TEST_CASE_P( StoreCertificate, DeviceCertificateStoreTest, - ::testing::Values(CertStorageVariant(true, EMPTY_ORIGIN), - CertStorageVariant(true, kTestOrigin), + ::testing::Values(CertStorageVariant(true, EMPTY_ORIGIN), + CertStorageVariant(true, kTestOrigin), CertStorageVariant(false, EMPTY_ORIGIN), CertStorageVariant(false, kTestOrigin))); @@ -1402,15 +1634,15 @@ TEST_P(DeviceCertificateTest, ReadCertificate) { Return(data.size()))); EXPECT_CALL(file, Close()).Times(1); EXPECT_CALL(file, Write(_, _)).Times(0); + EXPECT_CALL(file, List(_, NotNull())).WillOnce(Return(false)); DeviceFiles device_files; EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); device_files.SetTestFile(&file); std::string certificate, wrapped_private_key; - ASSERT_TRUE( - device_files.RetrieveCertificate(origin, &certificate, - &wrapped_private_key)); + ASSERT_TRUE(device_files.RetrieveCertificate(origin, &certificate, + &wrapped_private_key)); EXPECT_EQ(kTestCertificate, b2a_hex(certificate)); EXPECT_EQ(kTestWrappedPrivateKey, b2a_hex(wrapped_private_key)); } @@ -1492,6 +1724,9 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) { .WillOnce(Return(true)); } + CdmAppParameterMap app_parameters = + GetAppParameters(license_test_data[license_num].app_parameters); + EXPECT_CALL(file, Open(StrEq(license_path), AllOf(IsCreateFileFlagSet(), IsBinaryFileFlagSet()))) .WillOnce(Return(true)); @@ -1501,7 +1736,8 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) { license_test_data[license_num].key_response, license_test_data[license_num].key_renewal_request, license_test_data[license_num].key_renewal_response, - license_test_data[license_num].key_release_url), + license_test_data[license_num].key_release_url, + app_parameters), Gt(GetLicenseDataSize(license_test_data[license_num])))) .WillOnce(ReturnArg<1>()); EXPECT_CALL(file, Close()).Times(1); @@ -1520,7 +1756,7 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) { license_test_data[license_num].key_renewal_response, license_test_data[license_num].key_release_url, license_test_data[license_num].playback_start_time, - license_test_data[license_num].last_playback_time)); + license_test_data[license_num].last_playback_time, app_parameters)); } INSTANTIATE_TEST_CASE_P(StoreLicense, DeviceFilesStoreTest, ::testing::Bool()); @@ -1537,6 +1773,9 @@ TEST_F(DeviceFilesTest, StoreLicenses) { license_test_data[i].key_set_id + DeviceFiles::GetLicenseFileNameExtension(); + CdmAppParameterMap app_parameters = + GetAppParameters(license_test_data[i].app_parameters); + EXPECT_CALL(file, Open(StrEq(license_path), AllOf(IsCreateFileFlagSet(), IsBinaryFileFlagSet()))) .WillOnce(Return(true)); @@ -1546,7 +1785,8 @@ TEST_F(DeviceFilesTest, StoreLicenses) { license_test_data[i].key_response, license_test_data[i].key_renewal_request, license_test_data[i].key_renewal_response, - license_test_data[i].key_release_url), + license_test_data[i].key_release_url, + app_parameters), Gt(GetLicenseDataSize(license_test_data[i])))) .WillOnce(ReturnArg<1>()); } @@ -1557,6 +1797,9 @@ TEST_F(DeviceFilesTest, StoreLicenses) { EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); device_files.SetTestFile(&file); for (size_t i = 0; i < kNumberOfLicenses; i++) { + CdmAppParameterMap app_parameters = + GetAppParameters(license_test_data[i].app_parameters); + EXPECT_TRUE(device_files.StoreLicense( license_test_data[i].key_set_id, license_test_data[i].license_state, license_test_data[i].pssh_data, license_test_data[i].key_request, @@ -1565,7 +1808,7 @@ TEST_F(DeviceFilesTest, StoreLicenses) { license_test_data[i].key_renewal_response, license_test_data[i].key_release_url, license_test_data[i].playback_start_time, - license_test_data[i].last_playback_time)); + license_test_data[i].last_playback_time, app_parameters)); } } @@ -1603,6 +1846,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { CdmKeyResponse key_renewal_response; int64_t playback_start_time, last_playback_time; std::string release_server_url; + CdmAppParameterMap app_parameters; for (size_t i = 0; i < kNumberOfLicenses; i++) { DeviceFiles::LicenseState license_state; @@ -1610,7 +1854,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { license_test_data[i].key_set_id, &license_state, &pssh_data, &key_request, &key_response, &key_renewal_request, &key_renewal_response, &release_server_url, &playback_start_time, - &last_playback_time)); + &last_playback_time, &app_parameters)); EXPECT_EQ(license_test_data[i].license_state, license_state); EXPECT_EQ(license_test_data[i].pssh_data, pssh_data); EXPECT_EQ(license_test_data[i].key_request, key_request); @@ -1619,9 +1863,68 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { EXPECT_EQ(license_test_data[i].key_response, key_response); EXPECT_EQ(license_test_data[i].playback_start_time, playback_start_time); EXPECT_EQ(license_test_data[i].last_playback_time, last_playback_time); + + std::map::iterator itr; + for (itr = app_parameters.begin(); itr != app_parameters.end(); ++itr) { + EXPECT_NE(std::string::npos, + license_test_data[i].app_parameters.find(itr->first)); + EXPECT_NE(std::string::npos, + license_test_data[i].app_parameters.find(itr->second)); + } } } +TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) { + MockFile file; + LicenseInfo* test_data = + &license_app_parameters_backwards_compatibility_test_data; + + std::string license_path = device_base_path_ + test_data->key_set_id + + DeviceFiles::GetLicenseFileNameExtension(); + + size_t size = test_data->file_data.size(); + + EXPECT_CALL(file, Exists(StrEq(license_path))).WillOnce(Return(true)); + EXPECT_CALL(file, FileSize(StrEq(license_path))).WillOnce(Return(size)); + EXPECT_CALL(file, Open(StrEq(license_path), IsBinaryFileFlagSet())) + .WillOnce(Return(true)); + EXPECT_CALL(file, Read(NotNull(), Eq(size))) + .WillOnce(DoAll(SetArrayArgument<0>(test_data->file_data.begin(), + test_data->file_data.end()), + Return(size))); + + EXPECT_CALL(file, Close()).Times(1); + EXPECT_CALL(file, Write(_, _)).Times(0); + + DeviceFiles device_files; + EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); + device_files.SetTestFile(&file); + DeviceFiles::LicenseState license_state; + CdmInitData pssh_data; + CdmKeyMessage key_request; + CdmKeyResponse key_response; + CdmKeyMessage key_renewal_request; + CdmKeyResponse key_renewal_response; + int64_t playback_start_time, last_playback_time; + std::string release_server_url; + CdmAppParameterMap app_parameters; + + EXPECT_TRUE(device_files.RetrieveLicense( + test_data->key_set_id, &license_state, &pssh_data, &key_request, + &key_response, &key_renewal_request, &key_renewal_response, + &release_server_url, &playback_start_time, &last_playback_time, + &app_parameters)); + EXPECT_EQ(test_data->license_state, license_state); + EXPECT_EQ(test_data->pssh_data, pssh_data); + EXPECT_EQ(test_data->key_request, key_request); + EXPECT_EQ(test_data->key_response, key_response); + EXPECT_EQ(test_data->key_request, key_request); + EXPECT_EQ(test_data->key_response, key_response); + EXPECT_EQ(test_data->playback_start_time, playback_start_time); + EXPECT_EQ(test_data->last_playback_time, last_playback_time); + EXPECT_EQ(0u, app_parameters.size()); +} + TEST_F(DeviceFilesTest, SecurityLevelPathBackwardCompatibility) { MockFile file; std::vector security_dirs; @@ -1649,14 +1952,13 @@ TEST_F(DeviceFilesTest, SecurityLevelPathBackwardCompatibility) { } std::string old_path = - base_path + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN); + base_path + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN); old_files.push_back(DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN)); EXPECT_CALL(file, IsRegularFile(StrEq(old_path))).WillOnce(Return(true)); EXPECT_CALL(file, Remove(StrEq(old_path))).WillOnce(Return(true)); for (size_t i = 0; i < security_dirs.size(); ++i) { - new_path = - base_path + security_dirs[i] + - DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN); + new_path = base_path + security_dirs[i] + + DeviceFiles::GetCertificateFileName(EMPTY_ORIGIN); EXPECT_CALL(file, Copy(StrEq(old_path), StrEq(new_path))) .WillOnce(Return(true)); } @@ -1697,9 +1999,8 @@ TEST_F(DeviceFilesTest, SecurityLevelPathBackwardCompatibility) { Properties::Init(); std::string certificate, wrapped_private_key; - ASSERT_TRUE( - device_files.RetrieveCertificate(EMPTY_ORIGIN, &certificate, - &wrapped_private_key)); + ASSERT_TRUE(device_files.RetrieveCertificate(EMPTY_ORIGIN, &certificate, + &wrapped_private_key)); } TEST_F(DeviceFilesTest, UpdateLicenseState) { @@ -1738,7 +2039,8 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) { license_update_test_data[0].key_renewal_response, license_update_test_data[0].key_release_url, license_update_test_data[0].playback_start_time, - license_update_test_data[0].last_playback_time)); + license_update_test_data[0].last_playback_time, + GetAppParameters(license_test_data[0].app_parameters))); EXPECT_TRUE(device_files.StoreLicense( license_update_test_data[0].key_set_id, @@ -1750,7 +2052,8 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) { license_update_test_data[0].key_renewal_response, license_update_test_data[0].key_release_url, license_update_test_data[0].playback_start_time, - license_update_test_data[0].last_playback_time)); + license_update_test_data[0].last_playback_time, + GetAppParameters(license_test_data[0].app_parameters))); } TEST_F(DeviceFilesTest, DeleteLicense) { @@ -1788,11 +2091,13 @@ TEST_F(DeviceFilesTest, DeleteLicense) { CdmKeyResponse key_renewal_response; std::string release_server_url; int64_t playback_start_time, last_playback_time; + CdmAppParameterMap app_parameters; EXPECT_TRUE(device_files.RetrieveLicense( license_test_data[0].key_set_id, &license_state, &pssh_data, &key_request, &key_response, &key_renewal_request, &key_renewal_response, - &release_server_url, &playback_start_time, &last_playback_time)); + &release_server_url, &playback_start_time, &last_playback_time, + &app_parameters)); EXPECT_EQ(license_test_data[0].license_state, license_state); EXPECT_EQ(license_test_data[0].pssh_data, pssh_data); EXPECT_EQ(license_test_data[0].key_request, key_request); @@ -1801,6 +2106,13 @@ TEST_F(DeviceFilesTest, DeleteLicense) { EXPECT_EQ(license_test_data[0].key_response, key_response); EXPECT_EQ(license_test_data[0].playback_start_time, playback_start_time); EXPECT_EQ(license_test_data[0].last_playback_time, last_playback_time); + std::map::iterator itr; + for (itr = app_parameters.begin(); itr != app_parameters.end(); ++itr) { + EXPECT_NE(license_test_data[0].app_parameters.find(itr->first), + std::string::npos); + EXPECT_NE(license_test_data[0].app_parameters.find(itr->second), + std::string::npos); + } EXPECT_TRUE(device_files.DeleteLicense(license_test_data[0].key_set_id)); EXPECT_FALSE(device_files.LicenseExists(license_test_data[0].key_set_id)); @@ -1926,9 +2238,10 @@ TEST_P(DeviceFilesUsageInfoTest, Store) { EXPECT_CALL(file, Close()).Times(1); } - EXPECT_CALL(file, Write(Contains(pst, license_request, license, data.size()), - Gt(pst.size() + license_request.size() + - license.size()))).WillOnce(ReturnArg<1>()); + EXPECT_CALL(file, + Write(Contains(pst, license_request, license, data.size()), + Gt(pst.size() + license_request.size() + license.size()))) + .WillOnce(ReturnArg<1>()); DeviceFiles device_files; EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); @@ -2034,8 +2347,8 @@ TEST_P(DeviceFilesUsageInfoTest, DeleteAll) { // DeleteAllUsageInfoForApp returns a list of all psts that // should be deleted by oemcrypto. EXPECT_EQ(static_cast(index), psts.size()); - for(int i=0; i < index; i++) { - EXPECT_EQ(kUsageInfoTestData[i+1].provider_session_token, psts[i]); + for (int i = 0; i < index; i++) { + EXPECT_EQ(kUsageInfoTestData[i + 1].provider_session_token, psts[i]); } } } diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 2fb2207c..afbdb952 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -11,6 +11,7 @@ #include "config_test_env.h" #include "device_files.h" #include "file_store.h" +#include "license_protocol.pb.h" #include "license_request.h" #include "log.h" #include "oemcrypto_adapter.h" @@ -49,8 +50,7 @@ wvcdm::KeyId g_key_id; wvcdm::CdmKeySystem g_key_system; std::string g_license_server; wvcdm::KeyId g_wrong_key_id; -wvcdm::LicenseServerId g_license_server_id = - wvcdm::kContentProtectionServer; +wvcdm::LicenseServerId g_license_server_id = wvcdm::kContentProtectionServer; std::string kServiceCertificate = "0803121028703454C008F63618ADE7443DB6C4C8188BE7F99005228E023082010" @@ -399,9 +399,47 @@ UsageInfoSubSampleInfo usage_info_sub_sample_info[] = { {&usage_info_sub_samples_icp[0], 5, wvcdm::kLevel3, ""}, {&usage_info_sub_samples_icp[0], 3, wvcdm::kLevel3, "other app id"}}; +struct RenewWithClientIdTestConfiguration { + bool renew_with_client_id; + bool specify_app_parameters; + bool enable_privacy_mode; + bool specify_service_certificate; + std::string test_description; +}; + +RenewWithClientIdTestConfiguration + streaming_renew_client_id_test_configuration[] = { + {false, false, false, false, + "Test: Streaming renewal without client Id"}, + {true, false, false, false, "Test: Streaming renewal with client Id"}, + {true, true, false, false, + "Test: Streaming renewal with app parameters"}, + {true, false, true, false, + "Test: Streaming renewal fetch service cert"}, + {true, false, true, true, + "Test: Streaming renewal, service cert provided"}}; + +// Note: Offline renewal/release with encrypted client Ids and where a service +// certificate needs to be fetched is not supported. +RenewWithClientIdTestConfiguration + offline_release_client_id_test_configuration[] = { + {false, false, false, false, + "Test: Offline renewal/release without client Id"}, + {true, false, false, false, + "Test: Offline renewal/release with client Id"}, + {true, true, false, false, + "Test: Offline renewal/release with app parameters"}, + {true, false, true, true, + "Test: Offline renewal/release, service cert provided"}}; + } // namespace namespace wvcdm { +// Protobuf generated classes +using video_widevine_server::sdk::ClientIdentification; +using video_widevine_server::sdk::ClientIdentification_NameValue; +using video_widevine_server::sdk::SignedMessage; + class TestWvCdmClientPropertySet : public CdmClientPropertySet { public: TestWvCdmClientPropertySet() @@ -487,7 +525,14 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { void GenerateKeyRequest(const std::string& init_data, CdmLicenseType license_type, CdmClientPropertySet* property_set) { - wvcdm::CdmAppParameterMap app_parameters; + CdmAppParameterMap app_parameters; + GenerateKeyRequest(init_data, app_parameters, license_type, property_set); + } + + void GenerateKeyRequest(const std::string& init_data, + CdmAppParameterMap& app_parameters, + CdmLicenseType license_type, + CdmClientPropertySet* property_set) { std::string server_url; std::string key_set_id; EXPECT_EQ(wvcdm::KEY_MESSAGE, @@ -499,13 +544,13 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { } void GenerateRenewalRequest(CdmLicenseType license_type, - std::string* server_url) { - GenerateRenewalRequest(license_type, server_url, NULL); + CdmKeyMessage* key_msg, std::string* server_url) { + GenerateRenewalRequest(license_type, server_url); + *key_msg = key_msg_; } void GenerateRenewalRequest(CdmLicenseType license_type, - std::string* server_url, - CdmClientPropertySet* property_set) { + std::string* server_url) { // TODO application makes a license request, CDM will renew the license // when appropriate. std::string init_data; @@ -514,8 +559,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { EXPECT_EQ(wvcdm::KEY_MESSAGE, decryptor_.GenerateKeyRequest( session_id_, key_set_id_, "video/mp4", init_data, - license_type, app_parameters, property_set, EMPTY_ORIGIN, - &key_msg_, &key_request_type, server_url)); + license_type, app_parameters, NULL, EMPTY_ORIGIN, &key_msg_, + &key_request_type, server_url)); EXPECT_EQ(kKeyRequestTypeRenewal, key_request_type); // TODO(edwinwong, rfrias): Add tests cases for when license server url // is empty on renewal. Need appropriate key id at the server. @@ -523,11 +568,12 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { } void GenerateKeyRelease(CdmKeySetId key_set_id) { - GenerateKeyRelease(key_set_id, NULL); + GenerateKeyRelease(key_set_id, NULL, NULL); } void GenerateKeyRelease(CdmKeySetId key_set_id, - CdmClientPropertySet* property_set) { + CdmClientPropertySet* property_set, + CdmKeyMessage* key_msg) { CdmSessionId session_id; CdmInitData init_data; wvcdm::CdmAppParameterMap app_parameters; @@ -539,6 +585,7 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { kLicenseTypeRelease, app_parameters, property_set, EMPTY_ORIGIN, &key_msg_, &key_request_type, &server_url)); EXPECT_EQ(kKeyRequestTypeRelease, key_request_type); + if (key_msg) *key_msg = key_msg_; } void LogResponseError(const std::string& message, int http_status_code) { @@ -622,15 +669,22 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { void VerifyKeyRequestResponse(const std::string& server_url, const std::string& client_auth, bool is_renewal) { - std::string resp = GetKeyRequestResponse(server_url, client_auth); + std::string response; + VerifyKeyRequestResponse(server_url, client_auth, is_renewal, &response); + } + + void VerifyKeyRequestResponse(const std::string& server_url, + const std::string& client_auth, bool is_renewal, + std::string* response) { + *response = GetKeyRequestResponse(server_url, client_auth); if (is_renewal) { // TODO application makes a license request, CDM will renew the license // when appropriate - EXPECT_EQ(decryptor_.AddKey(session_id_, resp, &key_set_id_), + EXPECT_EQ(decryptor_.AddKey(session_id_, *response, &key_set_id_), wvcdm::KEY_ADDED); } else { - EXPECT_EQ(decryptor_.AddKey(session_id_, resp, &key_set_id_), + EXPECT_EQ(decryptor_.AddKey(session_id_, *response, &key_set_id_), wvcdm::KEY_ADDED); } } @@ -649,9 +703,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { property_set = &property_set_L3; } - CdmResponseType status = - decryptor_.OpenSession(g_key_system, property_set, EMPTY_ORIGIN, NULL, - &session_id_); + CdmResponseType status = decryptor_.OpenSession( + g_key_system, property_set, EMPTY_ORIGIN, NULL, &session_id_); switch (status) { case NO_ERROR: decryptor_.CloseSession(session_id_); @@ -667,9 +720,9 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; - status = decryptor_.GetProvisioningRequest( - cert_type, cert_authority, EMPTY_ORIGIN, &key_msg_, - &provisioning_server_url); + status = decryptor_.GetProvisioningRequest(cert_type, cert_authority, + EMPTY_ORIGIN, &key_msg_, + &provisioning_server_url); EXPECT_EQ(wvcdm::NO_ERROR, status); if (NO_ERROR != status) return; EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url()); @@ -678,8 +731,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); EXPECT_EQ(wvcdm::NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); + decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, + &cert, &wrapped_key)); EXPECT_EQ(0, static_cast(cert.size())); EXPECT_EQ(0, static_cast(wrapped_key.size())); decryptor_.CloseSession(session_id_); @@ -687,9 +740,9 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { } std::string GetSecurityLevel(TestWvCdmClientPropertySet* property_set) { - EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, property_set, - EMPTY_ORIGIN, NULL, - &session_id_)); + EXPECT_EQ(NO_ERROR, + decryptor_.OpenSession(g_key_system, property_set, EMPTY_ORIGIN, + NULL, &session_id_)); CdmQueryMap query_info; EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.QuerySessionStatus(session_id_, &query_info)); @@ -704,7 +757,6 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { } } - CdmSecurityLevel GetDefaultSecurityLevel() { std::string level = GetSecurityLevel(NULL).c_str(); CdmSecurityLevel security_level = kSecurityLevelUninitialized; @@ -738,9 +790,8 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) { std::string response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(wvcdm::NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); EXPECT_EQ(0, static_cast(cert.size())); EXPECT_EQ(0, static_cast(wrapped_key.size())); decryptor_.CloseSession(session_id_); @@ -781,18 +832,16 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningRetryTest) { std::string response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(wvcdm::NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); EXPECT_EQ(0, static_cast(cert.size())); EXPECT_EQ(0, static_cast(wrapped_key.size())); - response = - GetCertRequestResponse(g_config->provisioning_server_url()); + response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); EXPECT_EQ(wvcdm::EMPTY_PROVISIONING_CERTIFICATE, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); + decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, + &wrapped_key)); EXPECT_EQ(0, static_cast(cert.size())); EXPECT_EQ(0, static_cast(wrapped_key.size())); decryptor_.CloseSession(session_id_); @@ -814,9 +863,8 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_X509ProvisioningTest) { std::string response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(wvcdm::NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); EXPECT_NE(0, static_cast(cert.size())); EXPECT_NE(0, static_cast(wrapped_key.size())); decryptor_.CloseSession(session_id_); @@ -833,31 +881,29 @@ TEST_F(WvCdmRequestLicenseTest, PropertySetTest) { property_set_L1.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L1); property_set_L1.set_use_privacy_mode(true); decryptor_.OpenSession(g_key_system, &property_set_L1, EMPTY_ORIGIN, NULL, - &session_id_L1); + &session_id_L1); property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3); property_set_L3.set_use_privacy_mode(false); - CdmResponseType sts = decryptor_.OpenSession(g_key_system, &property_set_L3, - EMPTY_ORIGIN, NULL, - &session_id_L3); + CdmResponseType sts = decryptor_.OpenSession( + g_key_system, &property_set_L3, EMPTY_ORIGIN, NULL, &session_id_L3); if (NEED_PROVISIONING == sts) { std::string provisioning_server_url; CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest( - cert_type, cert_authority, EMPTY_ORIGIN, - &key_msg_, &provisioning_server_url)); + cert_type, cert_authority, EMPTY_ORIGIN, &key_msg_, + &provisioning_server_url)); EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url()); std::string response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); EXPECT_EQ(NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); - EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set_L3, - EMPTY_ORIGIN, NULL, - &session_id_L3)); + decryptor_.OpenSession(g_key_system, &property_set_L3, + EMPTY_ORIGIN, NULL, &session_id_L3)); } else { EXPECT_EQ(NO_ERROR, sts); } @@ -903,10 +949,9 @@ TEST_F(WvCdmRequestLicenseTest, ForceL3Test) { handle.SetTestFile(&file); EXPECT_TRUE(handle.DeleteAllFiles()); - EXPECT_EQ( - NEED_PROVISIONING, - decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, - &session_id_)); + EXPECT_EQ(NEED_PROVISIONING, + decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, + NULL, &session_id_)); std::string provisioning_server_url; CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; @@ -917,9 +962,8 @@ TEST_F(WvCdmRequestLicenseTest, ForceL3Test) { std::string response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); + EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, &session_id_)); @@ -1117,9 +1161,8 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) { std::string client_auth; GetOfflineConfiguration(&key_id, &client_auth); - CdmResponseType sts = - decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, - &session_id_); + CdmResponseType sts = decryptor_.OpenSession( + g_key_system, &property_set, EMPTY_ORIGIN, NULL, &session_id_); if (NEED_PROVISIONING == sts) { std::string provisioning_server_url; @@ -1132,12 +1175,11 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) { std::string response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); EXPECT_EQ(NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); - EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set, - EMPTY_ORIGIN, NULL, - &session_id_)); + decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, + NULL, &session_id_)); } else { EXPECT_EQ(NO_ERROR, sts); } @@ -1160,7 +1202,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) { session_id_.clear(); key_set_id_.clear(); - GenerateKeyRelease(key_set_id, &property_set); + GenerateKeyRelease(key_set_id, &property_set, NULL); session_id_.clear(); decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, @@ -1171,7 +1213,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) { session_id_.clear(); key_set_id_.clear(); - GenerateKeyRelease(key_set_id, &property_set); + GenerateKeyRelease(key_set_id, &property_set, NULL); key_set_id_ = key_set_id; VerifyKeyRequestResponse(g_license_server, client_auth, false); } @@ -1199,11 +1241,11 @@ TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) { decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, &listener, &session_id_); CdmSessionId restore_session_id = session_id_; - EXPECT_CALL(listener, - OnSessionKeysChange(restore_session_id, - AllOf(Each(Pair(_, kKeyStatusUsable)), - Not(IsEmpty())), - true)); + EXPECT_CALL( + listener, + OnSessionKeysChange( + restore_session_id, + AllOf(Each(Pair(_, kKeyStatusUsable)), Not(IsEmpty())), true)); EXPECT_CALL(listener, OnExpirationUpdate(restore_session_id, _)); EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(restore_session_id, key_set_id)); @@ -1213,11 +1255,11 @@ TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) { // Maybe called since VerifyKeyRequestResponse could take some time. EXPECT_CALL(listener, OnSessionRenewalNeeded(restore_session_id)) .Times(AtLeast(0)); - EXPECT_CALL(listener, - OnSessionKeysChange(restore_session_id, - AllOf(Each(Pair(_, kKeyStatusExpired)), - Not(IsEmpty())), - false)); + EXPECT_CALL( + listener, + OnSessionKeysChange( + restore_session_id, + AllOf(Each(Pair(_, kKeyStatusExpired)), Not(IsEmpty())), false)); GenerateKeyRelease(key_set_id); key_set_id_ = key_set_id; VerifyKeyRequestResponse(g_license_server, client_auth, false); @@ -1254,15 +1296,277 @@ TEST_F(WvCdmRequestLicenseTest, OfflineLicenseRenewal) { } TEST_F(WvCdmRequestLicenseTest, RemoveKeys) { - ASSERT_EQ(NO_ERROR, - decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, NULL, - &session_id_)); + ASSERT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, NULL, EMPTY_ORIGIN, + NULL, &session_id_)); GenerateKeyRequest(g_key_id, kLicenseTypeStreaming); VerifyKeyRequestResponse(g_license_server, g_client_auth, false); ASSERT_EQ(NO_ERROR, decryptor_.RemoveKeys(session_id_)); ASSERT_EQ(NO_ERROR, decryptor_.CloseSession(session_id_)); } +class WvCdmStreamingLicenseRenewalTest + : public WvCdmRequestLicenseTest, + public ::testing::WithParamInterface< + RenewWithClientIdTestConfiguration*> {}; + +TEST_P(WvCdmStreamingLicenseRenewalTest, DISABLED_WithClientId) { + RenewWithClientIdTestConfiguration* config = GetParam(); + std::string key_id; + if (config->renew_with_client_id) { + key_id = a2bs_hex( + "000000427073736800000000" // blob size and pssh + "EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id + "08011a0d7769646576696e655f74657374220f73" // pssh data + "747265616d696e675f636c697036"); + } else { + key_id = g_key_id; + } + + const uint32_t kNameValueParamSize = 2; + std::pair name_value_params[kNameValueParamSize] = { + {"Name1", "Value1"}, {"Name2", "Value2"}}; + wvcdm::CdmAppParameterMap app_parameters; + if (config->specify_app_parameters) { + for (uint32_t i = 0; i < kNameValueParamSize; ++i) { + app_parameters[name_value_params[i].first] = name_value_params[i].second; + } + } + + TestWvCdmClientPropertySet property_set; + if (config->enable_privacy_mode) { + property_set.set_use_privacy_mode(true); + if (config->specify_service_certificate) + property_set.set_service_certificate(a2bs_hex(kServiceCertificate)); + } + decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, + &session_id_); + GenerateKeyRequest(key_id, app_parameters, kLicenseTypeStreaming, + &property_set); + if (config->enable_privacy_mode && !config->specify_service_certificate) { + std::string resp = GetKeyRequestResponse(g_license_server, g_client_auth); + EXPECT_EQ(decryptor_.AddKey(session_id_, resp, &key_set_id_), + wvcdm::NEED_KEY); + GenerateKeyRequest(key_id, kLicenseTypeStreaming); + } + std::string key_response; + VerifyKeyRequestResponse(g_license_server, g_client_auth, false, + &key_response); + + // Validate signed license + SignedMessage signed_message; + EXPECT_TRUE(signed_message.ParseFromString(key_response)) + << config->test_description; + EXPECT_EQ(SignedMessage::LICENSE, signed_message.type()) + << config->test_description; + EXPECT_TRUE(signed_message.has_signature()) << config->test_description; + EXPECT_TRUE(!signed_message.msg().empty()) << config->test_description; + + // Verify license request + video_widevine_server::sdk::License license; + EXPECT_TRUE(license.ParseFromString(signed_message.msg())) + << config->test_description; + + // Verify renew_with_client_id + EXPECT_EQ(config->renew_with_client_id, + license.policy().has_renew_with_client_id()); + + std::string license_server; + CdmKeyMessage key_msg; + GenerateRenewalRequest(kLicenseTypeStreaming, &key_msg, &license_server); + if (license_server.empty()) license_server = g_license_server; + + // Validate signed renewal request + EXPECT_TRUE(signed_message.ParseFromString(key_msg)) + << config->test_description; + EXPECT_EQ(SignedMessage::LICENSE_REQUEST, signed_message.type()) + << config->test_description; + EXPECT_TRUE(signed_message.has_signature()) << config->test_description; + EXPECT_TRUE(!signed_message.msg().empty()) << config->test_description; + + // Verify license request + video_widevine_server::sdk::LicenseRequest license_renewal; + EXPECT_TRUE(license_renewal.ParseFromString(signed_message.msg())) + << config->test_description; + + // Verify ClientId + EXPECT_EQ(config->renew_with_client_id && !config->enable_privacy_mode, + license_renewal.has_client_id()) + << config->test_description; + + if (config->specify_app_parameters) { + for (uint32_t i = 0; i < kNameValueParamSize; ++i) { + bool found = false; + for (int j = 0; j < license_renewal.client_id().client_info_size(); ++j) { + ClientIdentification_NameValue client_info = + license_renewal.client_id().client_info(i); + if (name_value_params[i].first.compare(client_info.name()) == 0 && + name_value_params[i].second.compare(client_info.value()) == 0) { + found = true; + break; + } + } + EXPECT_TRUE(found) << config->test_description; + } + } + + if (config->enable_privacy_mode) { + EXPECT_EQ(config->renew_with_client_id, + license_renewal.has_encrypted_client_id()) + << config->test_description; + EXPECT_NE( + 0u, license_renewal.encrypted_client_id().encrypted_client_id().size()); + } + + VerifyKeyRequestResponse(license_server, g_client_auth, true); + decryptor_.CloseSession(session_id_); +} + +INSTANTIATE_TEST_CASE_P( + Cdm, WvCdmStreamingLicenseRenewalTest, + ::testing::Range(&streaming_renew_client_id_test_configuration[0], + &streaming_renew_client_id_test_configuration[5])); + +class WvCdmOfflineLicenseReleaseTest + : public WvCdmRequestLicenseTest, + public ::testing::WithParamInterface< + RenewWithClientIdTestConfiguration*> {}; + +TEST_P(WvCdmOfflineLicenseReleaseTest, DISABLED_WithClientId) { + Unprovision(); + Provision(kLevelDefault); + + RenewWithClientIdTestConfiguration* config = GetParam(); + std::string key_id; + std::string client_auth; + GetOfflineConfiguration(&key_id, &client_auth); + + if (config->renew_with_client_id) { + key_id = a2bs_hex( + "00000040" // blob size + "70737368" // "pssh" + "00000000" // flags + "edef8ba979d64acea3c827dcd51d21ed" // Widevine system id + "00000020" // pssh data size + // pssh data: + "08011a0d7769646576696e655f746573" + "74220d6f66666c696e655f636c697033"); + } + + const uint32_t kNameValueParamSize = 2; + std::pair name_value_params[kNameValueParamSize] = { + {"Name1", "Value1"}, {"Name2", "Value2"}}; + wvcdm::CdmAppParameterMap app_parameters; + if (config->specify_app_parameters) { + for (uint32_t i = 0; i < kNameValueParamSize; ++i) { + app_parameters[name_value_params[i].first] = name_value_params[i].second; + } + } + + TestWvCdmClientPropertySet property_set; + if (config->enable_privacy_mode) { + property_set.set_use_privacy_mode(true); + if (config->specify_service_certificate) + property_set.set_service_certificate(a2bs_hex(kServiceCertificate)); + } + decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, + &session_id_); + GenerateKeyRequest(key_id, app_parameters, kLicenseTypeOffline, NULL); + if (config->enable_privacy_mode && !config->specify_service_certificate) { + std::string resp = GetKeyRequestResponse(g_license_server, client_auth); + EXPECT_EQ(decryptor_.AddKey(session_id_, resp, &key_set_id_), + wvcdm::NEED_KEY); + GenerateKeyRequest(key_id, kLicenseTypeOffline); + } + std::string key_response; + VerifyKeyRequestResponse(g_license_server, client_auth, false, &key_response); + + // Validate signed license + SignedMessage signed_message; + EXPECT_TRUE(signed_message.ParseFromString(key_response)) + << config->test_description; + EXPECT_EQ(SignedMessage::LICENSE, signed_message.type()) + << config->test_description; + EXPECT_TRUE(signed_message.has_signature()) << config->test_description; + EXPECT_TRUE(!signed_message.msg().empty()) << config->test_description; + + // Verify license request + video_widevine_server::sdk::License license; + EXPECT_TRUE(license.ParseFromString(signed_message.msg())) + << config->test_description; + + // Verify renew_with_client_id + EXPECT_EQ(config->renew_with_client_id, + license.policy().has_renew_with_client_id()); + + CdmKeySetId key_set_id = key_set_id_; + EXPECT_TRUE(key_set_id_.size() > 0); + decryptor_.CloseSession(session_id_); + + session_id_.clear(); + key_set_id_.clear(); + + decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, + &session_id_); + EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id)); + decryptor_.CloseSession(session_id_); + + session_id_.clear(); + key_set_id_.clear(); + CdmKeyMessage key_msg; + GenerateKeyRelease(key_set_id, &property_set, &key_msg); + key_set_id_ = key_set_id; + + // Validate signed renewal request + EXPECT_TRUE(signed_message.ParseFromString(key_msg)) + << config->test_description; + EXPECT_EQ(SignedMessage::LICENSE_REQUEST, signed_message.type()) + << config->test_description; + EXPECT_TRUE(signed_message.has_signature()) << config->test_description; + EXPECT_TRUE(!signed_message.msg().empty()) << config->test_description; + + // Verify license request + video_widevine_server::sdk::LicenseRequest license_release; + EXPECT_TRUE(license_release.ParseFromString(signed_message.msg())) + << config->test_description; + + // Verify ClientId + EXPECT_EQ(config->renew_with_client_id && !config->enable_privacy_mode, + license_release.has_client_id()) + << config->test_description; + + if (config->specify_app_parameters) { + for (uint32_t i = 0; i < kNameValueParamSize; ++i) { + bool found = false; + for (int j = 0; j < license_release.client_id().client_info_size(); ++j) { + ClientIdentification_NameValue client_info = + license_release.client_id().client_info(i); + if (name_value_params[i].first.compare(client_info.name()) == 0 && + name_value_params[i].second.compare(client_info.value()) == 0) { + found = true; + break; + } + } + EXPECT_TRUE(found) << config->test_description; + } + } + + if (config->enable_privacy_mode) { + EXPECT_EQ(config->renew_with_client_id, + license_release.has_encrypted_client_id()) + << config->test_description; + EXPECT_NE( + 0u, license_release.encrypted_client_id().encrypted_client_id().size()); + } + + VerifyKeyRequestResponse(g_license_server, client_auth, false); + decryptor_.CloseSession(session_id_); +} + +INSTANTIATE_TEST_CASE_P( + Cdm, WvCdmOfflineLicenseReleaseTest, + ::testing::Range(&offline_release_client_id_test_configuration[0], + &offline_release_client_id_test_configuration[4])); + TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) { Unprovision(); Provision(kLevelDefault); @@ -1318,10 +1622,15 @@ TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) { } status = decryptor_.GetUsageInfo(app_id, &usage_info); switch (status) { - case KEY_MESSAGE: EXPECT_FALSE(usage_info.empty()); break; - case NO_ERROR: EXPECT_TRUE(usage_info.empty()); break; - default: FAIL() << "GetUsageInfo failed with error " - << static_cast(status) ; break; + case KEY_MESSAGE: + EXPECT_FALSE(usage_info.empty()); + break; + case NO_ERROR: + EXPECT_TRUE(usage_info.empty()); + break; + default: + FAIL() << "GetUsageInfo failed with error " << static_cast(status); + break; } } } @@ -1581,9 +1890,8 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) { std::string response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(wvcdm::NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); decryptor_.CloseSession(session_id_); std::vector files; @@ -1630,20 +1938,17 @@ TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) { TestWvCdmClientPropertySet property_set; property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3); - EXPECT_EQ( - wvcdm::NEED_PROVISIONING, - decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, - &session_id_)); + EXPECT_EQ(wvcdm::NEED_PROVISIONING, + decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, + NULL, &session_id_)); EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest( cert_type, cert_authority, EMPTY_ORIGIN, &key_msg_, &provisioning_server_url)); EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url()); - response = - GetCertRequestResponse(g_config->provisioning_server_url()); + response = GetCertRequestResponse(g_config->provisioning_server_url()); EXPECT_NE(0, static_cast(response.size())); - EXPECT_EQ(NO_ERROR, - decryptor_.HandleProvisioningResponse(EMPTY_ORIGIN, response, &cert, - &wrapped_key)); + EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse( + EMPTY_ORIGIN, response, &cert, &wrapped_key)); EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set, EMPTY_ORIGIN, NULL, &session_id_)); @@ -1948,16 +2253,17 @@ TEST(VersionNumberTest, VersionNumberChangeCanary) { char release_number[PROPERTY_VALUE_MAX]; ASSERT_GT(property_get("ro.build.version.release", release_number, "Unknown"), 0); - EXPECT_STREQ("MNC", release_number) << - "The Android version number has changed. You need to update this test " - "and also possibly update the Widevine version number in " - "properties_android.cpp."; + EXPECT_STREQ("MNC", release_number) + << "The Android version number has changed. You need to update this test " + "and also possibly update the Widevine version number in " + "properties_android.cpp."; std::string widevine_version; ASSERT_TRUE(Properties::GetWVCdmVersion(&widevine_version)); - EXPECT_EQ("v3.0.0-android", widevine_version) << - "The Widevine CDM version number has changed. Did you forget to update " - "this test after changing it?"; + EXPECT_EQ("v3.0.0-android", widevine_version) + << "The Widevine CDM version number has changed. Did you forget to " + "update " + "this test after changing it?"; } } // namespace wvcdm @@ -1981,8 +2287,8 @@ void show_menu(char* prog_name) { std::cout << std::setw(35) << std::left << " "; std::cout << "gp (case sensitive) for GooglePlay server" << std::endl; std::cout << std::setw(35) << std::left << " "; - std::cout << "cp (case sensitive) for Content Protection server" - << std::endl << std::endl; + std::cout << "cp (case sensitive) for Content Protection server" << std::endl + << std::endl; std::cout << std::setw(35) << std::left << " -k/--keyid="; std::cout << "configure the key id or pssh, in hex format" << std::endl @@ -1997,7 +2303,8 @@ void show_menu(char* prog_name) { std::cout << std::setw(35) << std::left << " -u/--server="; std::cout << "configure the license server url, please include http[s] in the url" - << std::endl << std::endl; + << std::endl + << std::endl; } int main(int argc, char** argv) { diff --git a/libwvdrmengine/include/WVErrors.h b/libwvdrmengine/include/WVErrors.h index 5f889f2b..9432e140 100644 --- a/libwvdrmengine/include/WVErrors.h +++ b/libwvdrmengine/include/WVErrors.h @@ -13,154 +13,163 @@ using android::ERROR_DRM_VENDOR_MIN; using android::ERROR_DRM_VENDOR_MAX; enum { - kErrorIncorrectBufferSize = ERROR_DRM_VENDOR_MIN, - kErrorCDMGeneric = ERROR_DRM_VENDOR_MIN + 1, - kErrorUnsupportedCrypto = ERROR_DRM_VENDOR_MIN + 2, - kErrorExpectedUnencrypted = ERROR_DRM_VENDOR_MIN + 3, - kErrorSessionIsOpen = ERROR_DRM_VENDOR_MIN + 4, - kErrorTooManySessions = ERROR_DRM_VENDOR_MIN + 5, - kErrorInvalidKey = ERROR_DRM_VENDOR_MIN + 6, - kErrorNoOriginSpecified = ERROR_DRM_VENDOR_MIN + 7, - kAddKeyError = ERROR_DRM_VENDOR_MIN + 8, + kErrorIncorrectBufferSize = ERROR_DRM_VENDOR_MIN, + kErrorCDMGeneric = ERROR_DRM_VENDOR_MIN + 1, + kErrorUnsupportedCrypto = ERROR_DRM_VENDOR_MIN + 2, + kErrorExpectedUnencrypted = ERROR_DRM_VENDOR_MIN + 3, + kErrorSessionIsOpen = ERROR_DRM_VENDOR_MIN + 4, + kErrorTooManySessions = ERROR_DRM_VENDOR_MIN + 5, + kErrorInvalidKey = ERROR_DRM_VENDOR_MIN + 6, + kErrorNoOriginSpecified = ERROR_DRM_VENDOR_MIN + 7, + kAddKeyError = ERROR_DRM_VENDOR_MIN + 8, kCertProvisioningGetKeyboxError1 = ERROR_DRM_VENDOR_MIN + 9, kCertProvisioningGetKeyboxError2 = ERROR_DRM_VENDOR_MIN + 10, kCertProvisioningInvalidCertType = ERROR_DRM_VENDOR_MIN + 11, - kCertProvisioningRequestError1 = ERROR_DRM_VENDOR_MIN + 12, - kCertProvisioningRequestError2 = ERROR_DRM_VENDOR_MIN + 13, - kCertProvisioningRequestError3 = ERROR_DRM_VENDOR_MIN + 14, - kCertProvisioningRequestError4 = ERROR_DRM_VENDOR_MIN + 15, - kCertProvisioningResponseError1 = ERROR_DRM_VENDOR_MIN + 16, - kCertProvisioningResponseError2 = ERROR_DRM_VENDOR_MIN + 17, - kCertProvisioningResponseError3 = ERROR_DRM_VENDOR_MIN + 18, - kCertProvisioningResponseError4 = ERROR_DRM_VENDOR_MIN + 19, - kCertProvisioningResponseError5 = ERROR_DRM_VENDOR_MIN + 20, - kCertProvisioningResponseError6 = ERROR_DRM_VENDOR_MIN + 21, - kCertProvisioningResponseError7 = ERROR_DRM_VENDOR_MIN + 22, - kCertProvisioningResponseError8 = ERROR_DRM_VENDOR_MIN + 23, - kCryptoSessionOpenError1 = ERROR_DRM_VENDOR_MIN + 24, - kCryptoSessionOpenError2 = ERROR_DRM_VENDOR_MIN + 25, - kCryptoSessionOpenError3 = ERROR_DRM_VENDOR_MIN + 26, - kCryptoSessionOpenError4 = ERROR_DRM_VENDOR_MIN + 27, - kCryptoSessionOpenError5 = ERROR_DRM_VENDOR_MIN + 28, - kDecyrptNotReady = ERROR_DRM_VENDOR_MIN + 29, - kDeviceCertificateError1 = ERROR_DRM_VENDOR_MIN + 30, - kDeviceCertificateError2 = ERROR_DRM_VENDOR_MIN + 31, - kDeviceCertificateError3 = ERROR_DRM_VENDOR_MIN + 32, - kDeviceCertificateError4 = ERROR_DRM_VENDOR_MIN + 33, - kEmptyKeyData1 = ERROR_DRM_VENDOR_MIN + 34, - kEmptyKeyData2 = ERROR_DRM_VENDOR_MIN + 35, - kEmptyKeySetId = ERROR_DRM_VENDOR_MIN + 36, - kEmptyKeySetIdEng1 = ERROR_DRM_VENDOR_MIN + 37, - kEmptyKeySetIdEng2 = ERROR_DRM_VENDOR_MIN + 38, - kEmptyKeySetIdEng3 = ERROR_DRM_VENDOR_MIN + 39, - kEmptyKeySetIdEng4 = ERROR_DRM_VENDOR_MIN + 40, - kEmptyLicenseRequest = ERROR_DRM_VENDOR_MIN + 41, - kEmptyLicenseResponse1 = ERROR_DRM_VENDOR_MIN + 42, - kEmptyLicenseResponse2 = ERROR_DRM_VENDOR_MIN + 43, - kEmptyProvisioningCertificate = ERROR_DRM_VENDOR_MIN + 44, - kEmptyProvisioningResponse = ERROR_DRM_VENDOR_MIN + 45, - kEmptySessionId = ERROR_DRM_VENDOR_MIN + 46, - kGenerateDerivedKeysError = ERROR_DRM_VENDOR_MIN + 47, - kGenerateNonceError = ERROR_DRM_VENDOR_MIN + 48, - kGenerateUsageReportError = ERROR_DRM_VENDOR_MIN + 49, - kGetLicenseError = ERROR_DRM_VENDOR_MIN + 50, - kGetReleasedLicenseError = ERROR_DRM_VENDOR_MIN + 51, - kGetUsageInfoError1 = ERROR_DRM_VENDOR_MIN + 52, - kGetUsageInfoError2 = ERROR_DRM_VENDOR_MIN + 53, - kGetUsageInfoError3 = ERROR_DRM_VENDOR_MIN + 54, - kGetUsageInfoError4 = ERROR_DRM_VENDOR_MIN + 55, - kInitDataNotFound = ERROR_DRM_VENDOR_MIN + 56, - kInvalidCryptoSession1 = ERROR_DRM_VENDOR_MIN + 57, - kInvalidCryptoSession2 = ERROR_DRM_VENDOR_MIN + 58, - kInvalidCryptoSession3 = ERROR_DRM_VENDOR_MIN + 59, - kInvalidCryptoSession4 = ERROR_DRM_VENDOR_MIN + 60, - kInvalidCryptoSession5 = ERROR_DRM_VENDOR_MIN + 61, - kInvalidDecryptParametersEng1 = ERROR_DRM_VENDOR_MIN + 62, - kInvalidDecryptParametersEng2 = ERROR_DRM_VENDOR_MIN + 63, - kInvalidDecryptParametersEng3 = ERROR_DRM_VENDOR_MIN + 64, - kInvalidDecryptParametersEng4 = ERROR_DRM_VENDOR_MIN + 65, - kInvalidDeviceCertificateType = ERROR_DRM_VENDOR_MIN + 66, - kInvalidKeySystem = ERROR_DRM_VENDOR_MIN + 67, - kInvalidLicenseResponse = ERROR_DRM_VENDOR_MIN + 68, - kInvalidLicenseType = ERROR_DRM_VENDOR_MIN + 69, - kInvalidParametersEng1 = ERROR_DRM_VENDOR_MIN + 70, - kInvalidParametersEng2 = ERROR_DRM_VENDOR_MIN + 71, - kInvalidParametersEng3 = ERROR_DRM_VENDOR_MIN + 72, - kInvalidParametersEng4 = ERROR_DRM_VENDOR_MIN + 73, - kInvalidParametersLic1 = ERROR_DRM_VENDOR_MIN + 74, - kInvalidParametersLic2 = ERROR_DRM_VENDOR_MIN + 75, - kInvalidProvisioningParam1 = ERROR_DRM_VENDOR_MIN + 76, - kInvalidProvisioningParam2 = ERROR_DRM_VENDOR_MIN + 77, - kInvalidProvisioningReqParam1 = ERROR_DRM_VENDOR_MIN + 78, - kInvalidProvisioningReqParam2 = ERROR_DRM_VENDOR_MIN + 79, - kInvalidQueryKey = ERROR_DRM_VENDOR_MIN + 80, - kInvalidSessionId = ERROR_DRM_VENDOR_MIN + 81, - kKeyRequestError1 = ERROR_DRM_VENDOR_MIN + 82, - kKeyRequestError2 = ERROR_DRM_VENDOR_MIN + 83, - kKeySizeError = ERROR_DRM_VENDOR_MIN + 84, - kKeySetIdNotFound1 = ERROR_DRM_VENDOR_MIN + 85, - kKeySetIdNotFound2 = ERROR_DRM_VENDOR_MIN + 86, - kKeySetIdNotFound3 = ERROR_DRM_VENDOR_MIN + 87, - kLicenseIdNotFound = ERROR_DRM_VENDOR_MIN + 88, - kLicenseParserInitError = ERROR_DRM_VENDOR_MIN + 89, - kLicenseParserNotInitialized1 = ERROR_DRM_VENDOR_MIN + 90, - kLicenseParserNotInitialized2 = ERROR_DRM_VENDOR_MIN + 91, - kLicenseParserNotInitialized3 = ERROR_DRM_VENDOR_MIN + 92, - kLicenseResponseNotSigned = ERROR_DRM_VENDOR_MIN + 93, - kLicenseResponseParseError1 = ERROR_DRM_VENDOR_MIN + 94, - kLicenseResponseParseError2 = ERROR_DRM_VENDOR_MIN + 95, - kLicenseResponseParseError3 = ERROR_DRM_VENDOR_MIN + 96, - kLoadKeyError = ERROR_DRM_VENDOR_MIN + 97, - kNoContentKey = ERROR_DRM_VENDOR_MIN + 98, - kProvisioningGetKeyboxError = ERROR_DRM_VENDOR_MIN + 99, - kRefreshKeysError = ERROR_DRM_VENDOR_MIN + 100, - kReleaseAllUsageInfoError1 = ERROR_DRM_VENDOR_MIN + 101, - kReleaseAllUsageInfoError2 = ERROR_DRM_VENDOR_MIN + 102, - kReleaseKeyError = ERROR_DRM_VENDOR_MIN + 103, - kReleaseKeyRequestError = ERROR_DRM_VENDOR_MIN + 104, - kReleaseLicenseError1 = ERROR_DRM_VENDOR_MIN + 105, - kReleaseLicenseError2 = ERROR_DRM_VENDOR_MIN + 106, - kReleaseUsageInfoError = ERROR_DRM_VENDOR_MIN + 107, - kRenewKeyError1 = ERROR_DRM_VENDOR_MIN + 108, - kRenewKeyError2 = ERROR_DRM_VENDOR_MIN + 109, - kRenewalRequestError = ERROR_DRM_VENDOR_MIN + 110, - kRestoreOfflineLicenseError1 = ERROR_DRM_VENDOR_MIN + 111, - kRestoreOfflineLicenseError2 = ERROR_DRM_VENDOR_MIN + 112, - kSessionInitError1 = ERROR_DRM_VENDOR_MIN + 113, - kSessionInitError2 = ERROR_DRM_VENDOR_MIN + 114, - kSessionInitGetKeyboxError = ERROR_DRM_VENDOR_MIN + 115, - kSessionNotFound1 = ERROR_DRM_VENDOR_MIN + 116, - kSessionNotFound2 = ERROR_DRM_VENDOR_MIN + 117, - kSessionNotFound3 = ERROR_DRM_VENDOR_MIN + 118, - kSessionNotFound4 = ERROR_DRM_VENDOR_MIN + 119, - kSessionNotFound5 = ERROR_DRM_VENDOR_MIN + 120, - kSessionNotFound6 = ERROR_DRM_VENDOR_MIN + 121, - kSessionNotFound7 = ERROR_DRM_VENDOR_MIN + 122, - kSessionNotFound8 = ERROR_DRM_VENDOR_MIN + 123, - kSessionNotFound9 = ERROR_DRM_VENDOR_MIN + 124, - kSessionNotFound10 = ERROR_DRM_VENDOR_MIN + 125, - kSessionKeysNotFound = ERROR_DRM_VENDOR_MIN + 126, - kSessionNotFoundForDecrypt = ERROR_DRM_VENDOR_MIN + 127, - kSignatureNotFound = ERROR_DRM_VENDOR_MIN + 128, - kStoreLicenseError1 = ERROR_DRM_VENDOR_MIN + 129, - kStoreLicenseError2 = ERROR_DRM_VENDOR_MIN + 130, - kStoreLicenseError3 = ERROR_DRM_VENDOR_MIN + 131, - kStoreUsageInfoError = ERROR_DRM_VENDOR_MIN + 132, - kUnprovisioningError1 = ERROR_DRM_VENDOR_MIN + 133, - kUnprovisioningError2 = ERROR_DRM_VENDOR_MIN + 134, - kUnprovisioningError3 = ERROR_DRM_VENDOR_MIN + 135, - kUnprovisioningError4 = ERROR_DRM_VENDOR_MIN + 136, - kUnsupportedInitData = ERROR_DRM_VENDOR_MIN + 137, - kUsageInfoNotFound = ERROR_DRM_VENDOR_MIN + 138, - kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 138, + kCertProvisioningRequestError1 = ERROR_DRM_VENDOR_MIN + 12, + kCertProvisioningRequestError2 = ERROR_DRM_VENDOR_MIN + 13, + kCertProvisioningRequestError3 = ERROR_DRM_VENDOR_MIN + 14, + kCertProvisioningRequestError4 = ERROR_DRM_VENDOR_MIN + 15, + kCertProvisioningResponseError1 = ERROR_DRM_VENDOR_MIN + 16, + kCertProvisioningResponseError2 = ERROR_DRM_VENDOR_MIN + 17, + kCertProvisioningResponseError3 = ERROR_DRM_VENDOR_MIN + 18, + kCertProvisioningResponseError4 = ERROR_DRM_VENDOR_MIN + 19, + kCertProvisioningResponseError5 = ERROR_DRM_VENDOR_MIN + 20, + kCertProvisioningResponseError6 = ERROR_DRM_VENDOR_MIN + 21, + kCertProvisioningResponseError7 = ERROR_DRM_VENDOR_MIN + 22, + kCertProvisioningResponseError8 = ERROR_DRM_VENDOR_MIN + 23, + kCryptoSessionOpenError1 = ERROR_DRM_VENDOR_MIN + 24, + kCryptoSessionOpenError2 = ERROR_DRM_VENDOR_MIN + 25, + kCryptoSessionOpenError3 = ERROR_DRM_VENDOR_MIN + 26, + kCryptoSessionOpenError4 = ERROR_DRM_VENDOR_MIN + 27, + kCryptoSessionOpenError5 = ERROR_DRM_VENDOR_MIN + 28, + kDecyrptNotReady = ERROR_DRM_VENDOR_MIN + 29, + kDeviceCertificateError1 = ERROR_DRM_VENDOR_MIN + 30, + kDeviceCertificateError2 = ERROR_DRM_VENDOR_MIN + 31, + kDeviceCertificateError3 = ERROR_DRM_VENDOR_MIN + 32, + kDeviceCertificateError4 = ERROR_DRM_VENDOR_MIN + 33, + kEmptyKeyData1 = ERROR_DRM_VENDOR_MIN + 34, + kEmptyKeyData2 = ERROR_DRM_VENDOR_MIN + 35, + kEmptyKeySetId = ERROR_DRM_VENDOR_MIN + 36, + kEmptyKeySetIdEng1 = ERROR_DRM_VENDOR_MIN + 37, + kEmptyKeySetIdEng2 = ERROR_DRM_VENDOR_MIN + 38, + kEmptyKeySetIdEng3 = ERROR_DRM_VENDOR_MIN + 39, + kEmptyKeySetIdEng4 = ERROR_DRM_VENDOR_MIN + 40, + kEmptyLicenseRequest = ERROR_DRM_VENDOR_MIN + 41, + kEmptyLicenseResponse1 = ERROR_DRM_VENDOR_MIN + 42, + kEmptyLicenseResponse2 = ERROR_DRM_VENDOR_MIN + 43, + kEmptyProvisioningCertificate = ERROR_DRM_VENDOR_MIN + 44, + kEmptyProvisioningResponse = ERROR_DRM_VENDOR_MIN + 45, + kEmptySessionId = ERROR_DRM_VENDOR_MIN + 46, + kGenerateDerivedKeysError = ERROR_DRM_VENDOR_MIN + 47, + kGenerateNonceError = ERROR_DRM_VENDOR_MIN + 48, + kGenerateUsageReportError = ERROR_DRM_VENDOR_MIN + 49, + kGetLicenseError = ERROR_DRM_VENDOR_MIN + 50, + kGetReleasedLicenseError = ERROR_DRM_VENDOR_MIN + 51, + kGetUsageInfoError1 = ERROR_DRM_VENDOR_MIN + 52, + kGetUsageInfoError2 = ERROR_DRM_VENDOR_MIN + 53, + kGetUsageInfoError3 = ERROR_DRM_VENDOR_MIN + 54, + kGetUsageInfoError4 = ERROR_DRM_VENDOR_MIN + 55, + kInitDataNotFound = ERROR_DRM_VENDOR_MIN + 56, + kInvalidCryptoSession1 = ERROR_DRM_VENDOR_MIN + 57, + kInvalidCryptoSession2 = ERROR_DRM_VENDOR_MIN + 58, + kInvalidCryptoSession3 = ERROR_DRM_VENDOR_MIN + 59, + kInvalidCryptoSession4 = ERROR_DRM_VENDOR_MIN + 60, + kInvalidCryptoSession5 = ERROR_DRM_VENDOR_MIN + 61, + kInvalidDecryptParametersEng1 = ERROR_DRM_VENDOR_MIN + 62, + kInvalidDecryptParametersEng2 = ERROR_DRM_VENDOR_MIN + 63, + kInvalidDecryptParametersEng3 = ERROR_DRM_VENDOR_MIN + 64, + kInvalidDecryptParametersEng4 = ERROR_DRM_VENDOR_MIN + 65, + kInvalidDeviceCertificateType = ERROR_DRM_VENDOR_MIN + 66, + kInvalidKeySystem = ERROR_DRM_VENDOR_MIN + 67, + kInvalidLicenseResponse = ERROR_DRM_VENDOR_MIN + 68, + kInvalidLicenseType = ERROR_DRM_VENDOR_MIN + 69, + kInvalidParametersEng1 = ERROR_DRM_VENDOR_MIN + 70, + kInvalidParametersEng2 = ERROR_DRM_VENDOR_MIN + 71, + kInvalidParametersEng3 = ERROR_DRM_VENDOR_MIN + 72, + kInvalidParametersEng4 = ERROR_DRM_VENDOR_MIN + 73, + kInvalidParametersLic1 = ERROR_DRM_VENDOR_MIN + 74, + kInvalidParametersLic2 = ERROR_DRM_VENDOR_MIN + 75, + kInvalidProvisioningParam1 = ERROR_DRM_VENDOR_MIN + 76, + kInvalidProvisioningParam2 = ERROR_DRM_VENDOR_MIN + 77, + kInvalidProvisioningReqParam1 = ERROR_DRM_VENDOR_MIN + 78, + kInvalidProvisioningReqParam2 = ERROR_DRM_VENDOR_MIN + 79, + kInvalidQueryKey = ERROR_DRM_VENDOR_MIN + 80, + kInvalidSessionId = ERROR_DRM_VENDOR_MIN + 81, + kKeyRequestError1 = ERROR_DRM_VENDOR_MIN + 82, + kKeyRequestError2 = ERROR_DRM_VENDOR_MIN + 83, + kKeySizeError = ERROR_DRM_VENDOR_MIN + 84, + kKeySetIdNotFound1 = ERROR_DRM_VENDOR_MIN + 85, + kKeySetIdNotFound2 = ERROR_DRM_VENDOR_MIN + 86, + kKeySetIdNotFound3 = ERROR_DRM_VENDOR_MIN + 87, + kLicenseIdNotFound = ERROR_DRM_VENDOR_MIN + 88, + kLicenseParserInitError = ERROR_DRM_VENDOR_MIN + 89, + kLicenseParserNotInitialized1 = ERROR_DRM_VENDOR_MIN + 90, + kLicenseParserNotInitialized2 = ERROR_DRM_VENDOR_MIN + 91, + kLicenseParserNotInitialized3 = ERROR_DRM_VENDOR_MIN + 92, + kLicenseResponseNotSigned = ERROR_DRM_VENDOR_MIN + 93, + kLicenseResponseParseError1 = ERROR_DRM_VENDOR_MIN + 94, + kLicenseResponseParseError2 = ERROR_DRM_VENDOR_MIN + 95, + kLicenseResponseParseError3 = ERROR_DRM_VENDOR_MIN + 96, + kLoadKeyError = ERROR_DRM_VENDOR_MIN + 97, + kNoContentKey = ERROR_DRM_VENDOR_MIN + 98, + kProvisioningGetKeyboxError = ERROR_DRM_VENDOR_MIN + 99, + kRefreshKeysError = ERROR_DRM_VENDOR_MIN + 100, + kReleaseAllUsageInfoError1 = ERROR_DRM_VENDOR_MIN + 101, + kReleaseAllUsageInfoError2 = ERROR_DRM_VENDOR_MIN + 102, + kReleaseKeyError = ERROR_DRM_VENDOR_MIN + 103, + kReleaseKeyRequestError = ERROR_DRM_VENDOR_MIN + 104, + kReleaseLicenseError1 = ERROR_DRM_VENDOR_MIN + 105, + kReleaseLicenseError2 = ERROR_DRM_VENDOR_MIN + 106, + kReleaseUsageInfoError = ERROR_DRM_VENDOR_MIN + 107, + kRenewKeyError1 = ERROR_DRM_VENDOR_MIN + 108, + kRenewKeyError2 = ERROR_DRM_VENDOR_MIN + 109, + kRenewalRequestError = ERROR_DRM_VENDOR_MIN + 110, + kRestoreOfflineLicenseError1 = ERROR_DRM_VENDOR_MIN + 111, + kRestoreOfflineLicenseError2 = ERROR_DRM_VENDOR_MIN + 112, + kSessionInitError1 = ERROR_DRM_VENDOR_MIN + 113, + kSessionInitError2 = ERROR_DRM_VENDOR_MIN + 114, + kSessionInitGetKeyboxError = ERROR_DRM_VENDOR_MIN + 115, + kSessionNotFound1 = ERROR_DRM_VENDOR_MIN + 116, + kSessionNotFound2 = ERROR_DRM_VENDOR_MIN + 117, + kSessionNotFound3 = ERROR_DRM_VENDOR_MIN + 118, + kSessionNotFound4 = ERROR_DRM_VENDOR_MIN + 119, + kSessionNotFound5 = ERROR_DRM_VENDOR_MIN + 120, + kSessionNotFound6 = ERROR_DRM_VENDOR_MIN + 121, + kSessionNotFound7 = ERROR_DRM_VENDOR_MIN + 122, + kSessionNotFound8 = ERROR_DRM_VENDOR_MIN + 123, + kSessionNotFound9 = ERROR_DRM_VENDOR_MIN + 124, + kSessionNotFound10 = ERROR_DRM_VENDOR_MIN + 125, + kSessionKeysNotFound = ERROR_DRM_VENDOR_MIN + 126, + kSessionNotFoundForDecrypt = ERROR_DRM_VENDOR_MIN + 127, + kSignatureNotFound = ERROR_DRM_VENDOR_MIN + 128, + kStoreLicenseError1 = ERROR_DRM_VENDOR_MIN + 129, + kStoreLicenseError2 = ERROR_DRM_VENDOR_MIN + 130, + kStoreLicenseError3 = ERROR_DRM_VENDOR_MIN + 131, + kStoreUsageInfoError = ERROR_DRM_VENDOR_MIN + 132, + kUnprovisioningError1 = ERROR_DRM_VENDOR_MIN + 133, + kUnprovisioningError2 = ERROR_DRM_VENDOR_MIN + 134, + kUnprovisioningError3 = ERROR_DRM_VENDOR_MIN + 135, + kUnprovisioningError4 = ERROR_DRM_VENDOR_MIN + 136, + kUnsupportedInitData = ERROR_DRM_VENDOR_MIN + 137, + kUsageInfoNotFound = ERROR_DRM_VENDOR_MIN + 138, + kServiceCertificateRequestGenerateError = ERROR_DRM_VENDOR_MIN + 139, + kParseServiceCertificateError = ERROR_DRM_VENDOR_MIN + 140, + kServiceCertificateTypeError = ERROR_DRM_VENDOR_MIN + 141, + kClientIdGenerateRandomError = ERROR_DRM_VENDOR_MIN + 142, + kClientIdAesInitError = ERROR_DRM_VENDOR_MIN + 143, + kClientIdAesEncryptError = ERROR_DRM_VENDOR_MIN + 144, + kClientIdRsaInitError = ERROR_DRM_VENDOR_MIN + 145, + kClientIdRsaEncryptError = ERROR_DRM_VENDOR_MIN + 146, + kErrorWVDrmMaxErrorUsed = ERROR_DRM_VENDOR_MIN + 146, // Used by crypto test mode - kErrorTestMode = ERROR_DRM_VENDOR_MAX, + kErrorTestMode = ERROR_DRM_VENDOR_MAX, }; static_assert(static_cast(kErrorWVDrmMaxErrorUsed) <= - static_cast(ERROR_DRM_VENDOR_MAX), ""); + static_cast(ERROR_DRM_VENDOR_MAX), + ""); -} // namespace wvdrm +} // namespace wvdrm -#endif // WV_ERRORS_H_ +#endif // WV_ERRORS_H_ diff --git a/libwvdrmengine/include/mapErrors-inl.h b/libwvdrmengine/include/mapErrors-inl.h index 491affb3..767c3ace 100644 --- a/libwvdrmengine/include/mapErrors-inl.h +++ b/libwvdrmengine/include/mapErrors-inl.h @@ -289,6 +289,22 @@ static android::status_t mapCdmResponseType(wvcdm::CdmResponseType res) { return kUnsupportedInitData; case wvcdm::USAGE_INFO_NOT_FOUND: return kUsageInfoNotFound; + case wvcdm::SERVICE_CERTIFICATE_REQUEST_GENERATE_ERROR: + return kServiceCertificateRequestGenerateError; + case wvcdm::PARSE_SERVICE_CERTIFICATE_ERROR: + return kParseServiceCertificateError; + case wvcdm::SERVICE_CERTIFICATE_TYPE_ERROR: + return kServiceCertificateTypeError; + case wvcdm::CLIENT_ID_GENERATE_RANDOM_ERROR: + return kClientIdGenerateRandomError; + case wvcdm::CLIENT_ID_AES_INIT_ERROR: + return kClientIdAesInitError; + case wvcdm::CLIENT_ID_AES_ENCRYPT_ERROR: + return kClientIdAesEncryptError; + case wvcdm::CLIENT_ID_RSA_INIT_ERROR: + return kClientIdRsaInitError; + case wvcdm::CLIENT_ID_RSA_ENCRYPT_ERROR: + return kClientIdRsaEncryptError; case wvcdm::KEY_ERROR: // KEY_ERROR is used by the CDM to mean just about any kind of error, not // just license errors, so it is mapped to the generic response.