diff --git a/libwvdrmengine/cdm/core/include/device_files.h b/libwvdrmengine/cdm/core/include/device_files.h index 81b5547c..53e31b92 100644 --- a/libwvdrmengine/cdm/core/include/device_files.h +++ b/libwvdrmengine/cdm/core/include/device_files.h @@ -29,17 +29,13 @@ class DeviceFiles { kLicenseStateUnknown, } LicenseState; - typedef enum { - kStorageLicense, // persistent license - kStorageUsageInfo, // secure stop - } UsageEntryStorage; - - struct UsageEntryInfo { - UsageEntryStorage storage_type; - std::string key_set_id; // used when storage_type is kStorageLicense - std::string - provider_session_token; // used when storage_type is kStorageUsageInfo - std::string app_id; // used when storage_type is kStorageUsageInfo + struct CdmUsageData { + std::string provider_session_token; + CdmKeyMessage license_request; + CdmKeyResponse license; + std::string key_set_id; + CdmUsageEntry usage_entry; + uint32_t usage_entry_number; }; DeviceFiles(FileSystem*); @@ -71,7 +67,8 @@ class DeviceFiles { int64_t last_playback_time, int64_t grace_period_end_time, const CdmAppParameterMap& app_parameters, - const CdmUsageEntry& usage_entry); + const CdmUsageEntry& usage_entry, + uint32_t usage_entry_number); virtual bool RetrieveLicense( const std::string& key_set_id, LicenseState* state, CdmInitData* pssh_data, CdmKeyMessage* key_request, @@ -79,7 +76,7 @@ class DeviceFiles { CdmKeyResponse* key_renewal_response, std::string* release_server_url, int64_t* playback_start_time, int64_t* last_playback_time, int64_t* grace_period_end_time, CdmAppParameterMap* app_parameters, - CdmUsageEntry* usage_entry); + CdmUsageEntry* usage_entry, uint32_t* usage_entry_number); virtual bool DeleteLicense(const std::string& key_set_id); virtual bool ListLicenses(std::vector* key_set_ids); virtual bool DeleteAllFiles(); @@ -88,13 +85,25 @@ class DeviceFiles { virtual bool ReserveLicenseId(const std::string& key_set_id); virtual bool UnreserveLicenseId(const std::string& key_set_id); - // Store a usage record to the set of usage information on the file system. + // Use this method to create a |usage_info_file_name| from an |app_id| + static std::string GetUsageInfoFileName(const std::string& app_id); + + // The UsageInfo methods have been revised to use |usage_info_file_name| + // rather than |app_id| as a parameter. Use the helper method above to + // translate. + // OEMCrypto API 13 introduced big usage tables which required + // migration from usage tables stored by the TEE to usage table + // header+usage entries stored in unsecured persistent storage. The upgrade + // required creation of reverse lookup tables (CdmUsageEntryInfo). + // |app_id| however was hashed and unextractable, and necessitated the + // switch to |usage_info_file_name| virtual bool StoreUsageInfo(const std::string& provider_session_token, const CdmKeyMessage& key_request, const CdmKeyResponse& key_response, - const std::string& app_id, + const std::string& usage_info_file_name, const std::string& key_set_id, - const CdmUsageEntry& usage_entry); + const CdmUsageEntry& usage_entry, + uint32_t usage_entry_number); // Extract KSIDs from usage information on the file system. virtual bool ListUsageRecords(const std::string& app_id, @@ -105,37 +114,49 @@ class DeviceFiles { const std::string& key_set_id, std::string* provider_session_token); - // Delete the usage record for the given PST. - virtual bool DeleteUsageInfo(const std::string& app_id, + virtual bool DeleteUsageInfo(const std::string& usage_info_file_name, const std::string& provider_session_token); // Delete usage information from the file system. Puts a list of all the // psts that were deleted from the file into |provider_session_tokens|. virtual bool DeleteAllUsageInfoForApp( - const std::string& app_id, + const std::string& usage_info_file_name, std::vector* provider_session_tokens); // Retrieve one usage info from the file. Subsequent calls will retrieve // subsequent entries in the table for this app_id. virtual bool RetrieveUsageInfo( - const std::string& app_id, + const std::string& usage_info_file_name, std::vector >* usage_info); // Retrieve the usage info entry specified by |provider_session_token|. // Returns false if the entry could not be found. - virtual bool RetrieveUsageInfo(const std::string& app_id, + virtual bool RetrieveUsageInfo(const std::string& usage_info_file_name, const std::string& provider_session_token, CdmKeyMessage* license_request, CdmKeyResponse* license_response, - CdmUsageEntry* usage_entry); - + CdmUsageEntry* usage_entry, + uint32_t* usage_entry_number); // Retrieve the usage info entry specified by |key_set_id|. // Returns false if the entry could not be found. - virtual bool RetrieveUsageInfoByKeySetId(const std::string& app_id, - const std::string& key_set_id, - CdmKeyMessage* license_request, - CdmKeyResponse* license_response, - CdmUsageEntry* usage_entry); + virtual bool RetrieveUsageInfoByKeySetId( + const std::string& usage_info_file_name, + const std::string& key_set_id, + std::string* provider_session_token, + CdmKeyMessage* license_request, + CdmKeyResponse* license_response, + CdmUsageEntry* usage_entry, + uint32_t* usage_entry_number); + + // These APIs support upgrading from usage tables to usage tabler header + + // entries introduced in OEMCrypto V13. + + virtual bool ListUsageInfoFiles(std::vector* usage_file_names); + virtual bool RetrieveUsageInfo(const std::string& usage_info_file_name, + std::vector* usage_data); + // This method overwrites rather than appends data to the usage file + virtual bool StoreUsageInfo(const std::string& usage_info_file_name, + const std::vector& usage_data); virtual bool StoreHlsAttributes(const std::string& key_set_id, const CdmHlsMethod method, @@ -147,11 +168,11 @@ class DeviceFiles { virtual bool StoreUsageTableInfo( const CdmUsageTableHeader& usage_table_header, - const std::vector& usage_entry_info); + const std::vector& usage_entry_info); virtual bool RetrieveUsageTableInfo( CdmUsageTableHeader* usage_table_header, - std::vector* usage_entry_info); + std::vector* usage_entry_info); private: // Extract serial number and system ID from DRM Device certificate @@ -175,7 +196,6 @@ class DeviceFiles { static std::string GetCertificateFileName(); static std::string GetHlsAttributesFileNameExtension(); static std::string GetLicenseFileNameExtension(); - static std::string GetUsageInfoFileName(const std::string& app_id); static std::string GetUsageTableFileName(); static std::string GetFileNameSafeHash(const std::string& input); diff --git a/libwvdrmengine/cdm/core/include/license_key_status.h b/libwvdrmengine/cdm/core/include/license_key_status.h index 59689472..e5628732 100644 --- a/libwvdrmengine/cdm/core/include/license_key_status.h +++ b/libwvdrmengine/cdm/core/include/license_key_status.h @@ -37,7 +37,11 @@ class LicenseKeys { virtual bool ApplyStatusChange(CdmKeyStatus new_status, bool* new_usable_keys); - // Populates the CdmKeyStatusMap with the current content keys. + // Returns current CdmKeyStatus for the given key. + // Returns kKeyStatusKeyUnknown if key_id not found. + virtual CdmKeyStatus GetKeyStatus(const KeyId& key_id); + + // Populates a CdmKeyStatusMap with the current content keys. virtual void ExtractKeyStatuses(CdmKeyStatusMap* content_keys); // Determines whether the specified key can be used under the current diff --git a/libwvdrmengine/cdm/core/include/policy_engine.h b/libwvdrmengine/cdm/core/include/policy_engine.h index b0c36cb4..37c1e1dc 100644 --- a/libwvdrmengine/cdm/core/include/policy_engine.h +++ b/libwvdrmengine/cdm/core/include/policy_engine.h @@ -34,6 +34,11 @@ class PolicyEngine { // status is not calculated to avoid overhead in the decryption path. virtual bool CanDecryptContent(const KeyId& key_id); + // Returns the current CdmKeyStatus for the given key, or + // kKeyStatusKeyUnknown if the key is not found. This is useful for finding + // out why a key is not usable. + virtual CdmKeyStatus GetKeyStatus(const KeyId& key_id); + // OnTimerEvent is called when a timer fires. It notifies the Policy Engine // that the timer has fired and dispatches the relevant events through // |event_listener_|. diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index 1cbefb88..533d77e6 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -317,6 +317,7 @@ enum CdmResponseType { }; enum CdmKeyStatus { + kKeyStatusKeyUnknown, kKeyStatusUsable, kKeyStatusExpired, kKeyStatusOutputNotAllowed, @@ -398,6 +399,18 @@ enum CdmUsageSupportType { kUnknownUsageSupport, }; +enum CdmUsageEntryStorageType { + kStorageLicense, + kStorageUsageInfo, + kStorageUnknown, +}; + +struct CdmUsageEntryInfo { + CdmUsageEntryStorageType storage_type; + CdmKeySetId key_set_id; + std::string usage_info_file_name; +}; + class CdmKeyAllowedUsage { public: CdmKeyAllowedUsage() { diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 062d61f4..36987479 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -99,11 +99,6 @@ bool CdmEngine::GetServiceCertificateRequest(CdmKeyMessage* request) { SignedMessage message; message.set_type(SignedMessage::SERVICE_CERTIFICATE_REQUEST); message.SerializeToString(request); - - // Convert to base64. - std::vector request_vector(request->begin(), request->end()); - std::string request_b64 = Base64SafeEncodeNoPad(request_vector); - request->swap(request_b64); return true; } @@ -118,16 +113,8 @@ CdmResponseType CdmEngine::ParseServiceCertificateResponse( return INVALID_PARAMETERS_ENG_24; } - // The response is base64 encoded - decode it before parsing the string. - std::string padded_response(response); - while (padded_response.size() % 4 != 0) { - padded_response = padded_response + "="; - } - std::vector raw_message = Base64SafeDecode(padded_response); - std::string raw_string(raw_message.begin(), raw_message.end()); - SignedMessage signed_response; - if (!signed_response.ParseFromString(raw_string)) { + if (!signed_response.ParseFromString(response)) { LOGE( "CdmEngine::ParseServiceCertificateResponse: cannot parse response"); return PARSE_RESPONSE_ERROR_1; @@ -157,7 +144,8 @@ CdmResponseType CdmEngine::ParseServiceCertificateResponse( return PARSE_RESPONSE_ERROR_3; } else { LOGE( - "CdmEngine::ParseServiceCertificateResponse: response is wrong type"); + "CdmEngine::ParseServiceCertificateResponse: response (%d) is " + "wrong type", signed_response.type()); return PARSE_RESPONSE_ERROR_4; } return NO_ERROR; @@ -1079,8 +1067,11 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, CdmKeyMessage license_request; CdmKeyResponse license_response; std::string usage_entry; - if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request, - &license_response, &usage_entry)) { + uint32_t usage_entry_number = 0; + if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), + ssid, &license_request, + &license_response, &usage_entry, + &usage_entry_number)) { usage_property_set_->set_security_level(kLevel3); usage_property_set_->set_app_id(app_id); usage_session_.reset(new CdmSession(file_system_)); @@ -1093,8 +1084,10 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, LOGE("CdmEngine::GetUsageInfo: device file init error"); return GET_USAGE_INFO_ERROR_2; } - if (!handle.RetrieveUsageInfo(app_id, ssid, &license_request, - &license_response, &usage_entry)) { + if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), + ssid, &license_request, + &license_response, &usage_entry, + &usage_entry_number)) { // No entry found for that ssid. return USAGE_INFO_NOT_FOUND; } @@ -1120,6 +1113,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, usage_info->clear(); return status; } + return KEY_MESSAGE; } @@ -1135,7 +1129,9 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, do { status = GetUsageInfo(app_id, security_level, usage_info); - if (KEY_MESSAGE == status && !usage_info->empty()) return status; + if (KEY_MESSAGE == status && !usage_info->empty()) { + return status; + } } while (KEY_CANCELED == status); security_level = (kLevel3 == security_level) ? kLevelDefault : kLevel3; @@ -1172,7 +1168,8 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id, } std::vector > license_info; - if (!handle.RetrieveUsageInfo(app_id, &license_info)) { + if (!handle.RetrieveUsageInfo(DeviceFiles::GetUsageInfoFileName(app_id), + &license_info)) { LOGE("CdmEngine::GetUsageInfo: unable to read usage information"); return GET_USAGE_INFO_ERROR_4; } @@ -1262,7 +1259,9 @@ CdmResponseType CdmEngine::ReleaseAllUsageInfo(const std::string& app_id) { DeviceFiles handle(file_system_); if (handle.Init(static_cast(j))) { std::vector provider_session_tokens; - if (!handle.DeleteAllUsageInfoForApp(app_id, &provider_session_tokens)) { + if (!handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(app_id), + &provider_session_tokens)) { LOGE("CdmEngine::ReleaseAllUsageInfo: failed to delete L%d secure" "stops", j); status = RELEASE_ALL_USAGE_INFO_ERROR_1; @@ -1338,11 +1337,15 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id, std::string app_id; session->GetApplicationId(&app_id); + std::string provider_session_token; CdmKeyMessage key_message; CdmKeyResponse key_response; std::string usage_entry; - if (!handle.RetrieveUsageInfoByKeySetId(app_id, key_set_id, &key_message, - &key_response, &usage_entry)) { + uint32_t usage_entry_number = 0; + if (!handle.RetrieveUsageInfoByKeySetId( + DeviceFiles::GetUsageInfoFileName(app_id), key_set_id, + &provider_session_token, &key_message, &key_response, + &usage_entry, &usage_entry_number)) { LOGE("CdmEngine::LoadUsageSession: unable to find usage information"); return LOAD_USAGE_INFO_MISSING; } diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index e2551c8a..611fb34f 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -189,13 +189,14 @@ CdmResponseType CdmSession::RestoreOfflineSession( int64_t last_playback_time; int64_t grace_period_end_time; std::string usage_entry; + uint32_t usage_entry_number = 0; if (!file_handle_->RetrieveLicense( 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, &grace_period_end_time, - &app_parameters_, &usage_entry)) { + &app_parameters_, &usage_entry, &usage_entry_number)) { LOGE("CdmSession::Init failed to retrieve license. key set id = %s", key_set_id.c_str()); return GET_LICENSE_ERROR; @@ -345,6 +346,10 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) { license_received_ = true; key_response_ = key_response; + LOGV("AddKey: provider_session_token (size=%d) =%s", + license_parser_->provider_session_token().size(), + license_parser_->provider_session_token().c_str()); + if (is_offline_ || !license_parser_->provider_session_token().empty()) { sts = StoreLicense(); if (sts != NO_ERROR) return sts; @@ -598,9 +603,12 @@ CdmResponseType CdmSession::StoreLicense() { std::string app_id; GetApplicationId(&app_id); std::string usage_entry; + uint32_t usage_entry_number = 0; if (!file_handle_->StoreUsageInfo(provider_session_token, key_request_, - key_response_, app_id, key_set_id_, - usage_entry)) { + key_response_, + DeviceFiles::GetUsageInfoFileName(app_id), + key_set_id_, usage_entry, + usage_entry_number)) { LOGE("CdmSession::StoreLicense: Unable to store usage info"); return STORE_USAGE_INFO_ERROR; } @@ -609,12 +617,14 @@ CdmResponseType CdmSession::StoreLicense() { bool CdmSession::StoreLicense(DeviceFiles::LicenseState state) { std::string usage_entry; + uint32_t usage_entry_number = 0; return file_handle_->StoreLicense( 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_->GetGracePeriodEndTime(), app_parameters_, usage_entry); + policy_engine_->GetGracePeriodEndTime(), app_parameters_, usage_entry, + usage_entry_number); } CdmResponseType CdmSession::ReleaseCrypto() { @@ -632,7 +642,8 @@ bool CdmSession::DeleteLicense() { std::string app_id; GetApplicationId(&app_id); return file_handle_->DeleteUsageInfo( - app_id, license_parser_->provider_session_token()); + DeviceFiles::GetUsageInfoFileName(app_id), + license_parser_->provider_session_token()); } } diff --git a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp index b50dbda5..f56f82c6 100644 --- a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp +++ b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp @@ -66,7 +66,7 @@ void ExtractAndDecodeSignedMessage(const std::string& provisioning_response, result->assign(decoded_message.begin(), decoded_message.end()); } -} +} // namespace namespace wvcdm { // Protobuf generated classes. @@ -190,7 +190,7 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest( client_id->set_type(token_type); #if 0 // TODO(gmorgan) Encrypt ClientIdentification. Pending Design. - if (service_certificate_->HasCertificate()) { + if (service_certificate_->has_certificate()) { EncryptedClientIdentification* encrypted_client_id = provisioning_request.mutable_encrypted_client_id(); CdmResponseType status; @@ -279,9 +279,9 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse( FileSystem* file_system, const CdmProvisioningResponse& response, std::string* cert, std::string* wrapped_key) { - std::string raw_string; // The response is base64 encoded in a JSON wrapper. // Extract it and decode it. If errors, return an empty string. + std::string raw_string; ExtractAndDecodeSignedMessage(response, &raw_string); if (raw_string.empty()) { diff --git a/libwvdrmengine/cdm/core/src/device_files.cpp b/libwvdrmengine/cdm/core/src/device_files.cpp index cd58e88b..64f1b5fe 100644 --- a/libwvdrmengine/cdm/core/src/device_files.cpp +++ b/libwvdrmengine/cdm/core/src/device_files.cpp @@ -41,6 +41,8 @@ using video_widevine_client::sdk:: UsageTableInfo_UsageEntryInfo_UsageEntryStorage_LICENSE; using video_widevine_client::sdk:: UsageTableInfo_UsageEntryInfo_UsageEntryStorage_USAGE_INFO; +using video_widevine_client::sdk:: + UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN; using video_widevine::SignedDrmDeviceCertificate; using video_widevine::DrmDeviceCertificate; @@ -218,7 +220,8 @@ bool DeviceFiles::StoreLicense( const std::string& release_server_url, int64_t playback_start_time, int64_t last_playback_time, int64_t grace_period_end_time, const CdmAppParameterMap& app_parameters, - const CdmUsageEntry& usage_entry) { + const CdmUsageEntry& usage_entry, + const uint32_t usage_entry_number) { if (!initialized_) { LOGW("DeviceFiles::StoreLicense: not initialized"); return false; @@ -260,6 +263,7 @@ bool DeviceFiles::StoreLicense( app_params->set_value(iter->second); } license->set_usage_entry(usage_entry); + license->set_usage_entry_number(usage_entry_number); std::string serialized_file; file.SerializeToString(&serialized_file); @@ -274,7 +278,8 @@ bool DeviceFiles::RetrieveLicense( CdmKeyMessage* license_renewal_request, CdmKeyResponse* license_renewal, std::string* release_server_url, int64_t* playback_start_time, int64_t* last_playback_time, int64_t* grace_period_end_time, - CdmAppParameterMap* app_parameters, CdmUsageEntry* usage_entry) { + CdmAppParameterMap* app_parameters, CdmUsageEntry* usage_entry, + uint32_t* usage_entry_number) { if (!initialized_) { LOGW("DeviceFiles::RetrieveLicense: not initialized"); return false; @@ -329,6 +334,7 @@ bool DeviceFiles::RetrieveLicense( license.app_parameters(i).value(); } *usage_entry = license.usage_entry(); + *usage_entry_number = license.usage_entry_number(); return true; } @@ -422,21 +428,21 @@ bool DeviceFiles::UnreserveLicenseId(const std::string& key_set_id) { bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token, const CdmKeyMessage& key_request, const CdmKeyResponse& key_response, - const std::string& app_id, + const std::string& usage_info_file_name, const std::string& key_set_id, - const CdmUsageEntry& usage_entry) { + const std::string& usage_entry, + uint32_t usage_entry_number) { if (!initialized_) { LOGW("DeviceFiles::StoreUsageInfo: not initialized"); return false; } video_widevine_client::sdk::File file; - std::string file_name = GetUsageInfoFileName(app_id); - if (!FileExists(file_name)) { + if (!FileExists(usage_info_file_name)) { file.set_type(video_widevine_client::sdk::File::USAGE_INFO); file.set_version(video_widevine_client::sdk::File::VERSION_1); } else { - if (!RetrieveHashedFile(file_name, &file)) { + if (!RetrieveHashedFile(usage_info_file_name, &file)) { LOGW("DeviceFiles::StoreUsageInfo: Unable to parse file"); return false; } @@ -451,10 +457,11 @@ bool DeviceFiles::StoreUsageInfo(const std::string& provider_session_token, provider_session->set_license(key_response.data(), key_response.size()); provider_session->set_key_set_id(key_set_id.data(), key_set_id.size()); provider_session->set_usage_entry(usage_entry); + provider_session->set_usage_entry_number(usage_entry_number); std::string serialized_file; file.SerializeToString(&serialized_file); - return StoreFileWithHash(file_name, serialized_file); + return StoreFileWithHash(usage_info_file_name, serialized_file); } bool DeviceFiles::ListUsageRecords(const std::string& app_id, @@ -528,15 +535,14 @@ bool DeviceFiles::GetProviderSessionToken(const std::string& app_id, return false; } -bool DeviceFiles::DeleteUsageInfo(const std::string& app_id, +bool DeviceFiles::DeleteUsageInfo(const std::string& usage_info_file_name, const std::string& provider_session_token) { if (!initialized_) { LOGW("DeviceFiles::DeleteUsageInfo: not initialized"); return false; } video_widevine_client::sdk::File file; - std::string file_name = GetUsageInfoFileName(app_id); - if (!RetrieveHashedFile(file_name, &file)) return false; + if (!RetrieveHashedFile(usage_info_file_name, &file)) return false; UsageInfo* usage_info = file.mutable_usage_info(); int index = 0; @@ -565,11 +571,11 @@ bool DeviceFiles::DeleteUsageInfo(const std::string& app_id, std::string serialized_file; file.SerializeToString(&serialized_file); - return StoreFileWithHash(file_name, serialized_file); + return StoreFileWithHash(usage_info_file_name, serialized_file); } bool DeviceFiles::DeleteAllUsageInfoForApp( - const std::string& app_id, + const std::string& usage_info_file_name, std::vector* provider_session_tokens) { if (!initialized_) { LOGW("DeviceFiles::DeleteAllUsageInfoForApp: not initialized"); @@ -581,22 +587,21 @@ bool DeviceFiles::DeleteAllUsageInfoForApp( } provider_session_tokens->clear(); - std::string file_name = GetUsageInfoFileName(app_id); - if (!FileExists(file_name)) return true; + if (!FileExists(usage_info_file_name)) return true; video_widevine_client::sdk::File file; - if (RetrieveHashedFile(file_name, &file)) { + if (RetrieveHashedFile(usage_info_file_name, &file)) { for (int i = 0; i < file.usage_info().sessions_size(); ++i) { provider_session_tokens->push_back(file.usage_info().sessions(i).token()); } } else { LOGW("DeviceFiles::DeleteAllUsageInfoForApp: Unable to retrieve file"); } - return RemoveFile(file_name); + return RemoveFile(usage_info_file_name); } bool DeviceFiles::RetrieveUsageInfo( - const std::string& app_id, + const std::string& usage_info_file_name, std::vector >* usage_info) { if (!initialized_) { LOGW("DeviceFiles::RetrieveUsageInfo: not initialized"); @@ -610,14 +615,14 @@ bool DeviceFiles::RetrieveUsageInfo( return false; } - std::string file_name = GetUsageInfoFileName(app_id); - if (!FileExists(file_name) || GetFileSize(file_name) == 0) { + if (!FileExists(usage_info_file_name) || + GetFileSize(usage_info_file_name) == 0) { usage_info->resize(0); return true; } video_widevine_client::sdk::File file; - if (!RetrieveHashedFile(file_name, &file)) { + if (!RetrieveHashedFile(usage_info_file_name, &file)) { LOGW("DeviceFiles::RetrieveUsageInfo: Unable to parse file"); return false; } @@ -632,19 +637,19 @@ bool DeviceFiles::RetrieveUsageInfo( return true; } -bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id, +bool DeviceFiles::RetrieveUsageInfo(const std::string& usage_info_file_name, const std::string& provider_session_token, CdmKeyMessage* license_request, CdmKeyResponse* license_response, - CdmUsageEntry* usage_entry) { + std::string* usage_entry, + uint32_t* usage_entry_number) { if (!initialized_) { LOGW("DeviceFiles::RetrieveUsageInfo: not initialized"); return false; } - std::string file_name = GetUsageInfoFileName(app_id); video_widevine_client::sdk::File file; - if (!RetrieveHashedFile(file_name, &file)) { + if (!RetrieveHashedFile(usage_info_file_name, &file)) { return false; } @@ -654,6 +659,8 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id, *license_request = file.usage_info().sessions(index).license_request(); *license_response = file.usage_info().sessions(index).license(); *usage_entry = file.usage_info().sessions(index).usage_entry(); + *usage_entry_number = + file.usage_info().sessions(index).usage_entry_number(); return true; } } @@ -662,28 +669,32 @@ bool DeviceFiles::RetrieveUsageInfo(const std::string& app_id, } bool DeviceFiles::RetrieveUsageInfoByKeySetId( - const std::string& app_id, + const std::string& usage_info_file_name, const std::string& key_set_id, + std::string* provider_session_token, CdmKeyMessage* license_request, CdmKeyResponse* license_response, - CdmUsageEntry* usage_entry) { + std::string* usage_entry, + uint32_t* usage_entry_number) { if (!initialized_) { LOGW("DeviceFiles::RetrieveUsageInfoByKeySetId: not initialized"); return false; } - std::string file_name = GetUsageInfoFileName(app_id); video_widevine_client::sdk::File file; - if (!RetrieveHashedFile(file_name, &file)) { + if (!RetrieveHashedFile(usage_info_file_name, &file)) { return false; } int index = 0; for (; index < file.usage_info().sessions_size(); ++index) { if (file.usage_info().sessions(index).key_set_id() == key_set_id) { + *provider_session_token = file.usage_info().sessions(index).token(); *license_request = file.usage_info().sessions(index).license_request(); *license_response = file.usage_info().sessions(index).license(); *usage_entry = file.usage_info().sessions(index).usage_entry(); + *usage_entry_number = + file.usage_info().sessions(index).usage_entry_number(); return true; } } @@ -691,6 +702,97 @@ bool DeviceFiles::RetrieveUsageInfoByKeySetId( return false; } +bool DeviceFiles::StoreUsageInfo(const std::string& usage_info_file_name, + const std::vector& usage_data) { + if (!initialized_) { + LOGW("DeviceFiles::StoreUsageInfo: not initialized"); + return false; + } + + video_widevine_client::sdk::File file; + file.set_type(video_widevine_client::sdk::File::USAGE_INFO); + file.set_version(video_widevine_client::sdk::File::VERSION_1); + + UsageInfo* usage_info = file.mutable_usage_info(); + for (size_t i = 0; i < usage_data.size(); ++i) { + UsageInfo_ProviderSession* provider_session = usage_info->add_sessions(); + + provider_session->set_token(usage_data[i].provider_session_token.data(), + usage_data[i].provider_session_token.size()); + provider_session->set_license_request(usage_data[i].license_request.data(), + usage_data[i].license_request.size()); + provider_session->set_license(usage_data[i].license.data(), + usage_data[i].license.size()); + provider_session->set_key_set_id(usage_data[i].key_set_id.data(), + usage_data[i].key_set_id.size()); + provider_session->set_usage_entry(usage_data[i].usage_entry); + provider_session->set_usage_entry_number(usage_data[i].usage_entry_number); + } + + std::string serialized_file; + file.SerializeToString(&serialized_file); + return StoreFileWithHash(usage_info_file_name, serialized_file); +} + +bool DeviceFiles::RetrieveUsageInfo(const std::string& usage_info_file_name, + std::vector* usage_data) { + + if (!initialized_) { + LOGW("DeviceFiles::RetrieveUsageInfo: not initialized"); + return false; + } + + video_widevine_client::sdk::File file; + if (!RetrieveHashedFile(usage_info_file_name, &file)) { + return false; + } + + usage_data->resize(file.usage_info().sessions_size()); + for (int i = 0; i < file.usage_info().sessions_size(); ++i) { + (*usage_data)[i].provider_session_token = + file.usage_info().sessions(i).token(); + (*usage_data)[i].license_request = + file.usage_info().sessions(i).license_request(); + (*usage_data)[i].license = file.usage_info().sessions(i).license(); + (*usage_data)[i].key_set_id = file.usage_info().sessions(i).key_set_id(); + (*usage_data)[i].usage_entry = file.usage_info().sessions(i).usage_entry(); + (*usage_data)[i].usage_entry_number = + file.usage_info().sessions(i).usage_entry_number(); + } + + return false; +} + +bool DeviceFiles::ListUsageInfoFiles( + std::vector* usage_info_file_names) { + if (!initialized_) { + LOGW("DeviceFiles::ListUsageInfoFiles: not initialized"); + return false; + } + + // Get list of filenames + std::vector filenames; + if (!ListFiles(&filenames)) { + return false; + } + + // Scan list of all filenames and return only usage info filenames + usage_info_file_names->clear(); + for (size_t i = 0; i < filenames.size(); i++) { + std::string* name = &filenames[i]; + std::size_t pos_prefix = name->find(kUsageInfoFileNamePrefix); + std::size_t pos_suffix = name->find(kUsageInfoFileNameExt); + if (pos_prefix == std::string::npos || + pos_suffix == std::string::npos) { + // Skip this file - extension does not match + continue; + } + + usage_info_file_names->push_back(*name); + } + return true; +} + bool DeviceFiles::StoreHlsAttributes( const std::string& key_set_id, const CdmHlsMethod method, const std::vector& media_segment_iv) { @@ -790,7 +892,7 @@ bool DeviceFiles::DeleteHlsAttributes(const std::string& key_set_id) { bool DeviceFiles::StoreUsageTableInfo( const CdmUsageTableHeader& usage_table_header, - const std::vector& usage_entry_info) { + const std::vector& usage_entry_info) { if (!initialized_) { LOGW("DeviceFiles::StoreUsageTableHeader: not initialized"); return false; @@ -807,23 +909,23 @@ bool DeviceFiles::StoreUsageTableInfo( for (size_t i = 0; i < usage_entry_info.size(); ++i) { UsageTableInfo_UsageEntryInfo* info = usage_table_info->add_usage_entry_info(); + info->set_key_set_id(usage_entry_info[i].key_set_id); switch (usage_entry_info[i].storage_type) { case kStorageLicense: info->set_storage( UsageTableInfo_UsageEntryInfo_UsageEntryStorage_LICENSE); - info->set_key_set_id(usage_entry_info[i].key_set_id); break; case kStorageUsageInfo: info->set_storage( UsageTableInfo_UsageEntryInfo_UsageEntryStorage_USAGE_INFO); - info->set_provider_session_token( - usage_entry_info[i].provider_session_token); - info->set_app_id(usage_entry_info[i].app_id); + info->set_usage_info_file_name( + usage_entry_info[i].usage_info_file_name); break; + case kStorageUnknown: default: - LOGW("DeviceFiles::StoreUsageTableHeader: unknown storage type: %d", - usage_entry_info[i].storage_type); - return false; + info->set_storage( + UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN); + break; } } @@ -835,7 +937,7 @@ bool DeviceFiles::StoreUsageTableInfo( bool DeviceFiles::RetrieveUsageTableInfo( CdmUsageTableHeader* usage_table_header, - std::vector* usage_entry_info) { + std::vector* usage_entry_info) { if (!initialized_) { LOGW("DeviceFiles::RetrieveUsageTableInfo: not initialized"); return false; @@ -879,21 +981,20 @@ bool DeviceFiles::RetrieveUsageTableInfo( for (int i = 0; i < usage_table_info.usage_entry_info_size(); ++i) { const UsageTableInfo_UsageEntryInfo& info = usage_table_info.usage_entry_info(i); + (*usage_entry_info)[i].key_set_id = info.key_set_id(); switch (info.storage()) { case UsageTableInfo_UsageEntryInfo_UsageEntryStorage_LICENSE: (*usage_entry_info)[i].storage_type = kStorageLicense; - (*usage_entry_info)[i].key_set_id = info.key_set_id(); break; case UsageTableInfo_UsageEntryInfo_UsageEntryStorage_USAGE_INFO: (*usage_entry_info)[i].storage_type = kStorageUsageInfo; - (*usage_entry_info)[i].provider_session_token = - info.provider_session_token(); - (*usage_entry_info)[i].app_id = info.app_id(); + (*usage_entry_info)[i].usage_info_file_name = + info.usage_info_file_name(); break; + case UsageTableInfo_UsageEntryInfo_UsageEntryStorage_UNKNOWN: default: - LOGW("DeviceFiles::RetrieveUsageTableInfo: Unknown storage type: %d", - info.storage()); - return false; + (*usage_entry_info)[i].storage_type = kStorageUnknown; + break; } } diff --git a/libwvdrmengine/cdm/core/src/device_files.proto b/libwvdrmengine/cdm/core/src/device_files.proto index 1bfb21ce..02b86bdf 100644 --- a/libwvdrmengine/cdm/core/src/device_files.proto +++ b/libwvdrmengine/cdm/core/src/device_files.proto @@ -44,6 +44,7 @@ message License { // ignored if there is no grace period. optional int64 grace_period_end_time = 11 [default = 0]; optional bytes usage_entry = 12; + optional int64 usage_entry_number = 13; } message UsageInfo { @@ -53,6 +54,7 @@ message UsageInfo { optional bytes license = 3; optional bytes key_set_id = 4; optional bytes usage_entry = 5; + optional int64 usage_entry_number = 6; } repeated ProviderSession sessions = 1; @@ -72,12 +74,12 @@ message UsageTableInfo { enum UsageEntryStorage { LICENSE = 1; USAGE_INFO = 2; + UNKNOWN = 3; } optional UsageEntryStorage storage = 1; - optional bytes key_set_id = 2; // used if storage is LICENSE - optional bytes provider_session_token = 3; // used if storage is USAGE_INFO - optional bytes app_id = 4; // used if storage is USAGE_INFO + optional bytes key_set_id = 2; + optional bytes usage_info_file_name = 3; // hash of the app_id } optional bytes usage_table_header = 1; diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index 8bef079c..a75bb675 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -205,8 +205,7 @@ CdmResponseType CdmLicense::PrepareKeyRequest( return INVALID_PARAMETERS_LIC_7; } - // If privacy mode and no service certificate, initiate a - // service certificate request. + // If privacy mode, must have service certificate if (Properties::UsePrivacyMode(session_id_) && !service_certificate_->has_certificate()) { LOGE("CdmLicense::PrepareKeyRequest: failure with privacy mode - " @@ -479,8 +478,13 @@ CdmResponseType CdmLicense::HandleKeyResponse( license.policy().can_persist()) is_offline_ = true; - if (license.id().has_provider_session_token()) + LOGV("Get Provider_session_token:"); + if (license.id().has_provider_session_token()) { provider_session_token_ = license.id().provider_session_token(); + LOGV("Provider_session_token=%s", provider_session_token_.c_str()); + } else { + LOGV("NO Provider_session_token"); + } if (license.policy().has_renewal_server_url()) { server_url_ = license.policy().renewal_server_url(); @@ -797,6 +801,7 @@ bool CdmLicense::GetClientTokenType( case kClientTokenOemCert: default: // shouldn't happen + LOGE("GetClientTokenType: BAD TOKEN TYPE"); return false; } } @@ -980,7 +985,7 @@ CdmResponseType CdmLicense::PrepareContentId( if (!init_data.IsEmpty()) { cenc_content_id->add_pssh(init_data.data()); } else { - LOGE("CdmLicense::PrepareKeyRequest: ISO-CENC init data not available"); + LOGE("CdmLicense::PrepareContentId: ISO-CENC init data not available"); return CENC_INIT_DATA_UNAVAILABLE; } @@ -994,7 +999,7 @@ CdmResponseType CdmLicense::PrepareContentId( if (!init_data.IsEmpty()) { webm_content_id->set_header(init_data.data()); } else { - LOGE("CdmLicense::PrepareKeyRequest: WebM init data not available"); + LOGE("CdmLicense::PrepareContentId: WebM init data not available"); return WEBM_INIT_DATA_UNAVAILABLE; } @@ -1002,7 +1007,7 @@ CdmResponseType CdmLicense::PrepareContentId( return PREPARE_WEBM_CONTENT_ID_FAILED; } } else { - LOGE("CdmLicense::PrepareKeyRequest: no support for init data type (%s)", + LOGE("CdmLicense::PrepareContentId: no support for init data type (%s)", init_data.type().c_str()); return UNSUPPORTED_INIT_DATA_FORMAT; } diff --git a/libwvdrmengine/cdm/core/src/license_key_status.cpp b/libwvdrmengine/cdm/core/src/license_key_status.cpp index 940fa0a8..29a847f1 100644 --- a/libwvdrmengine/cdm/core/src/license_key_status.cpp +++ b/libwvdrmengine/cdm/core/src/license_key_status.cpp @@ -103,7 +103,15 @@ bool LicenseKeys::ApplyStatusChange(CdmKeyStatus new_status, return keys_changed; } +CdmKeyStatus LicenseKeys::GetKeyStatus(const KeyId& key_id) { + if (keys_.count(key_id) == 0) { + return kKeyStatusKeyUnknown; + } + return keys_[key_id]->GetKeyStatus(); +} + void LicenseKeys::ExtractKeyStatuses(CdmKeyStatusMap* content_keys) { + content_keys->clear(); for (LicenseKeyStatusIterator it = keys_.begin(); it != keys_.end(); ++it) { if (it->second->IsContentKey()) { const KeyId key_id = it->first; diff --git a/libwvdrmengine/cdm/core/src/policy_engine.cpp b/libwvdrmengine/cdm/core/src/policy_engine.cpp index bbee4342..062b6619 100644 --- a/libwvdrmengine/cdm/core/src/policy_engine.cpp +++ b/libwvdrmengine/cdm/core/src/policy_engine.cpp @@ -47,6 +47,10 @@ bool PolicyEngine::CanDecryptContent(const KeyId& key_id) { } } +CdmKeyStatus PolicyEngine::GetKeyStatus(const KeyId& key_id) { + return license_keys_->GetKeyStatus(key_id); +} + void PolicyEngine::InitDevice(CryptoSession* crypto_session) { current_resolution_ = HDCP_UNSPECIFIED_VIDEO_RESOLUTION; next_device_check_ = 0; @@ -101,7 +105,9 @@ void PolicyEngine::OnTimerEvent() { // Test to determine if renewal should be attempted. switch (license_state_) { case kLicenseStateCanPlay: { - if (HasRenewalDelayExpired(current_time)) renewal_needed = true; + if (HasRenewalDelayExpired(current_time)) { + renewal_needed = true; + } // HDCP may change, so force a check. NotifyKeysChange(kKeyStatusUsable); break; @@ -113,7 +119,9 @@ void PolicyEngine::OnTimerEvent() { } case kLicenseStateWaitingLicenseUpdate: { - if (HasRenewalRetryIntervalExpired(current_time)) renewal_needed = true; + if (HasRenewalRetryIntervalExpired(current_time)) { + renewal_needed = true; + } break; } @@ -429,6 +437,10 @@ bool PolicyEngine::HasRenewalRetryIntervalExpired(int64_t current_time) { next_renewal_time_ <= current_time; } +// Apply a key status to the current keys. +// If this represents a new key status, perform a notification callback. +// NOTE: if the new status is kKeyStatusUsable, the HDCP check may result in an +// override to kKeyStatusOutputNotAllowed. void PolicyEngine::NotifyKeysChange(CdmKeyStatus new_status) { bool keys_changed; bool has_new_usable_key = false; diff --git a/libwvdrmengine/cdm/core/src/service_certificate.cpp b/libwvdrmengine/cdm/core/src/service_certificate.cpp index cf2b9815..3f331076 100644 --- a/libwvdrmengine/cdm/core/src/service_certificate.cpp +++ b/libwvdrmengine/cdm/core/src/service_certificate.cpp @@ -11,110 +11,6 @@ namespace { // Service certificate for Google/Widevine Provisioning and License servers. -static const unsigned char kRootCertForDev[] = { - 0x0a, 0x9c, 0x03, 0x08, 0x00, 0x12, 0x01, 0x00, - 0x18, 0xc3, 0x94, 0x88, 0x8b, 0x05, 0x22, 0x8e, - 0x03, 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, - 0x81, 0x00, 0xc0, 0x00, 0x36, 0x6f, 0x8e, 0xe9, - 0xcf, 0x86, 0xdb, 0xcd, 0xdd, 0x4e, 0xfd, 0xcd, - 0x45, 0xbf, 0x6d, 0x96, 0x05, 0x00, 0xb8, 0x72, - 0xff, 0x9c, 0xb4, 0x39, 0xa8, 0xd8, 0xc0, 0x09, - 0x73, 0xc0, 0x24, 0x6a, 0x39, 0x4d, 0x36, 0x3f, - 0x9a, 0xe4, 0xb8, 0x76, 0xdc, 0x34, 0xe3, 0xee, - 0x5f, 0xdd, 0x13, 0x20, 0x08, 0xdc, 0x4e, 0x6f, - 0x4e, 0x9f, 0xc0, 0x36, 0xf9, 0xce, 0xc6, 0xb7, - 0xdb, 0xe0, 0x51, 0x2d, 0x30, 0x0b, 0xae, 0x0a, - 0x20, 0xd2, 0x29, 0x3c, 0x2c, 0x1d, 0x87, 0x65, - 0xeb, 0x5f, 0x93, 0xd7, 0x3f, 0x12, 0x08, 0x50, - 0x0e, 0x55, 0xf3, 0xf1, 0x19, 0xee, 0x18, 0x21, - 0x6e, 0xea, 0xb6, 0x0a, 0x4a, 0x0b, 0x9c, 0x72, - 0x37, 0xeb, 0x0b, 0x68, 0xfc, 0x52, 0x46, 0x62, - 0xd0, 0xa2, 0x99, 0x66, 0xe2, 0x2b, 0x74, 0xdd, - 0x5c, 0xaf, 0x9a, 0x03, 0xc4, 0x5d, 0x93, 0xfb, - 0xcd, 0x45, 0x9a, 0xee, 0xfb, 0x7b, 0x18, 0x94, - 0xc1, 0x8c, 0x82, 0x34, 0x7f, 0x02, 0x12, 0x21, - 0xfc, 0x40, 0xc1, 0x50, 0xc9, 0xf4, 0x7c, 0xd5, - 0x96, 0xbe, 0x55, 0x7f, 0x3c, 0x1d, 0x70, 0x34, - 0xb4, 0xa2, 0x03, 0xc4, 0x3f, 0x89, 0x60, 0xe4, - 0x24, 0x09, 0x1a, 0x74, 0xc4, 0xb6, 0x39, 0xf0, - 0x34, 0x60, 0x8e, 0xa7, 0x5f, 0x02, 0x7f, 0xb9, - 0x2a, 0xc5, 0xaa, 0xb2, 0x4c, 0x34, 0xd3, 0x5a, - 0x5d, 0xfa, 0x07, 0xf2, 0xb9, 0xb3, 0xc1, 0xba, - 0xab, 0xbe, 0x89, 0x99, 0xe3, 0x6d, 0x9b, 0xa9, - 0xd3, 0xaf, 0x2a, 0x08, 0x76, 0xf3, 0x0e, 0xc9, - 0xe0, 0xb3, 0xbf, 0x51, 0x0c, 0xc5, 0xf4, 0xf3, - 0x15, 0x7b, 0x08, 0x11, 0x8f, 0x61, 0x1f, 0x61, - 0x64, 0xdb, 0x15, 0x84, 0x5b, 0x8a, 0xd1, 0x28, - 0x40, 0xde, 0xc5, 0x32, 0xb5, 0xad, 0xad, 0x65, - 0x4c, 0xf5, 0xf7, 0xd1, 0x90, 0x14, 0x5d, 0xc2, - 0x85, 0x98, 0xcc, 0xe9, 0xe6, 0x95, 0x42, 0xe1, - 0x3e, 0xfc, 0x7f, 0xc4, 0x49, 0xed, 0x9c, 0xe4, - 0x49, 0x3f, 0x03, 0x1b, 0x0d, 0xa0, 0xfb, 0xf5, - 0x38, 0x49, 0xd2, 0xdf, 0xa3, 0x88, 0xb2, 0x76, - 0x93, 0x08, 0x20, 0x18, 0xfe, 0xdc, 0x72, 0x6c, - 0x6e, 0xbf, 0x61, 0x37, 0x03, 0xdb, 0xe5, 0x72, - 0x68, 0xe0, 0x99, 0x2f, 0xb9, 0xe0, 0x2e, 0xbb, - 0x9f, 0x96, 0x36, 0x61, 0xaa, 0x2d, 0xa4, 0x93, - 0xe8, 0x50, 0x58, 0xe6, 0x61, 0xe1, 0x14, 0xcf, - 0xac, 0x86, 0x98, 0x7f, 0x3c, 0x67, 0x16, 0xce, - 0xb8, 0x70, 0x90, 0x3a, 0x5a, 0xd4, 0xe1, 0xe2, - 0x35, 0x98, 0xbf, 0x93, 0x41, 0x11, 0xb2, 0x44, - 0xb2, 0x64, 0xc2, 0xe7, 0x09, 0x45, 0xb7, 0x6f, - 0xb0, 0xbd, 0x6e, 0xe8, 0x67, 0xfa, 0x8d, 0xd4, - 0xfa, 0x4b, 0xef, 0xa8, 0x9d, 0x8a, 0x0a, 0xd9, - 0x14, 0x77, 0x09, 0x11, 0x9e, 0xc3, 0x50, 0x14, - 0x6c, 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, 0x12, - 0x80, 0x03, 0x17, 0x01, 0x60, 0x24, 0xe1, 0xfd, - 0x75, 0x60, 0x17, 0x5c, 0x5e, 0x6f, 0x9f, 0x7f, - 0xdf, 0xee, 0xf0, 0xf7, 0x7d, 0xb2, 0x50, 0x65, - 0x36, 0x26, 0x14, 0x19, 0x01, 0x5e, 0x98, 0x94, - 0x65, 0x97, 0x83, 0xaa, 0x4a, 0x2b, 0x98, 0x2e, - 0x02, 0xf3, 0xb2, 0xc9, 0xb2, 0xed, 0xd3, 0x1b, - 0x20, 0x27, 0x9e, 0xe1, 0x25, 0xc7, 0x86, 0xf0, - 0x66, 0x68, 0x5d, 0xd2, 0x3d, 0xa7, 0xbb, 0xbc, - 0x22, 0xfc, 0x29, 0xfa, 0x17, 0x16, 0xf4, 0xa2, - 0x00, 0x10, 0x87, 0xb4, 0x5d, 0x51, 0x45, 0x6b, - 0xc8, 0xf4, 0x6b, 0xcc, 0x92, 0x91, 0xe7, 0xa7, - 0x93, 0xbc, 0xc7, 0x2e, 0xdc, 0xac, 0x82, 0x2b, - 0x85, 0x56, 0x7b, 0xae, 0xf2, 0xd8, 0xda, 0xa6, - 0xd7, 0xfa, 0x6d, 0x70, 0x2a, 0x2e, 0xcf, 0x69, - 0xef, 0x57, 0x91, 0xa7, 0xaa, 0x40, 0x15, 0x4a, - 0x49, 0x1b, 0xbc, 0x36, 0xbb, 0x1c, 0x94, 0x33, - 0x36, 0x61, 0x22, 0x9d, 0x22, 0x66, 0xf0, 0x88, - 0x5e, 0x7c, 0x3c, 0xa5, 0xff, 0x81, 0xcf, 0x1a, - 0x44, 0xa1, 0x2b, 0xdf, 0xc9, 0x3d, 0xd5, 0xc7, - 0xc7, 0x3a, 0x75, 0xac, 0x29, 0xfa, 0xfd, 0x5b, - 0xda, 0xf5, 0x8f, 0xd9, 0xdf, 0x08, 0xa4, 0x8d, - 0x19, 0x4a, 0xa4, 0x79, 0x6e, 0x47, 0xf6, 0x07, - 0xe0, 0xbd, 0xbf, 0x30, 0x3a, 0xf9, 0xf5, 0xc0, - 0x90, 0x6d, 0x70, 0x27, 0x44, 0xa8, 0x5e, 0x70, - 0xcd, 0x43, 0x3e, 0xaf, 0xf0, 0xd7, 0x20, 0xd3, - 0x5e, 0x97, 0x2d, 0x32, 0x1a, 0x3d, 0x2d, 0x0f, - 0x0f, 0xcf, 0xac, 0x4e, 0x88, 0x75, 0x98, 0x6c, - 0xfa, 0xe8, 0x42, 0x58, 0x99, 0xaa, 0x45, 0x0c, - 0x41, 0x0c, 0x6e, 0x27, 0x58, 0x57, 0xd2, 0x5b, - 0x82, 0x3d, 0x75, 0x2f, 0x9e, 0xf3, 0xe4, 0x00, - 0xcf, 0x91, 0x48, 0x25, 0xca, 0x98, 0xf2, 0x91, - 0x6b, 0x41, 0xa5, 0xe8, 0xcd, 0x64, 0xa7, 0x2e, - 0x78, 0xc7, 0x76, 0x82, 0x3f, 0xf8, 0x57, 0x8a, - 0x9d, 0x78, 0x25, 0xad, 0xf3, 0x1a, 0x8b, 0xfc, - 0x83, 0x9a, 0x98, 0x87, 0xe4, 0x55, 0x3e, 0x1c, - 0xa7, 0x80, 0x8f, 0xd6, 0x76, 0xab, 0x03, 0xc7, - 0x05, 0x66, 0xc3, 0xa0, 0x4c, 0x33, 0x1f, 0x39, - 0x74, 0x1b, 0x2a, 0xbf, 0xe6, 0xb0, 0x9f, 0x6b, - 0xc1, 0xd6, 0xd3, 0xf4, 0x46, 0x9b, 0xf3, 0xab, - 0xca, 0x2e, 0x88, 0x3d, 0x84, 0x5f, 0xc9, 0x9b, - 0x47, 0xbb, 0x57, 0x64, 0x08, 0x0e, 0x18, 0x74, - 0x83, 0x44, 0xd4, 0xc3, 0x18, 0x97, 0xcf, 0x89, - 0x6a, 0x49, 0x51, 0xc6, 0xff, 0x8d, 0x39, 0xc5, - 0x23, 0xf9, 0xd5, 0x01, 0xd7, 0x2f, 0xa9, 0xa5, - 0x5d, 0xa9, 0xf3, 0xc9, 0xfd, 0xc4, 0x52, 0x19, - 0x7d, 0xf6, 0xa4, 0x2c, 0x0c, 0xa0, 0x07, 0xdf, - 0x7b, 0x44, 0xd7, 0xe5, 0xbf, 0x57, 0x87, 0xc9, - 0x8c, 0xfe, 0x30, 0xb2, 0x89, 0x5d, 0x00, 0x03, - 0x3b, 0xe5 -}; - static const unsigned char kRootCertForProd[] = { 0x0a, 0x9c, 0x03, 0x08, 0x00, 0x12, 0x01, 0x00, 0x18, 0xdd, 0x94, 0x88, 0x8b, 0x05, 0x22, 0x8e, @@ -231,14 +127,8 @@ using video_widevine::SignedDrmDeviceCertificate; using video_widevine::SignedMessage; CdmResponseType ServiceCertificate::Init(const std::string& certificate) { - // TODO(tinskip): Get rid of conditional compilation. -#if defined(QA_TEST_SERVER) - std::string root_cert_str(reinterpret_cast(&kRootCertForDev[0]), - sizeof(kRootCertForDev)); -#else std::string root_cert_str(reinterpret_cast(&kRootCertForProd[0]), sizeof(kRootCertForProd)); -#endif // !defined(QA_TEST_SERVER); // Load root cert public key. Don't bother verifying it. SignedDrmDeviceCertificate signed_root_cert; diff --git a/libwvdrmengine/cdm/core/src/string_conversions.cpp b/libwvdrmengine/cdm/core/src/string_conversions.cpp index 7d4368f0..7e7ecb76 100644 --- a/libwvdrmengine/cdm/core/src/string_conversions.cpp +++ b/libwvdrmengine/cdm/core/src/string_conversions.cpp @@ -229,7 +229,7 @@ std::vector Base64Decode(const std::string& b64_input) { } // Decode for Filename-friendly base64 encoding (RFC4648), commonly referred -// as Base64WebSafeDecode. +// as Base64WebSafeDecode. Add padding if needed. std::vector Base64SafeDecode(const std::string& b64_input) { if (b64_input.empty()) { return std::vector(); diff --git a/libwvdrmengine/cdm/core/test/cdm_engine_test.cpp b/libwvdrmengine/cdm/core/test/cdm_engine_test.cpp index 4a56a5a3..082ae972 100644 --- a/libwvdrmengine/cdm/core/test/cdm_engine_test.cpp +++ b/libwvdrmengine/cdm/core/test/cdm_engine_test.cpp @@ -38,24 +38,26 @@ KeyId g_key_id_unwrapped; CdmKeySystem g_key_system; std::string g_license_server; std::string g_provisioning_server; -std::string g_service_certificate; +std::string g_provisioning_service_certificate; +std::string g_license_service_certificate; KeyId g_wrong_key_id; const std::string kCencMimeType = "video/mp4"; const std::string kWebmMimeType = "video/webm"; -static void CommonSetup(bool use_qa) { +static void CommonSetup(ServerConfigurationId which) { - // NOTE: Select QA/Test server config vs. UAT server config - ConfigTestEnv config((use_qa) ? kContentProtectionTestQAServer : - kContentProtectionUatServer); + // NOTE: Select configuration + ConfigTestEnv config(which); g_client_auth.assign(config.client_auth()); g_key_system.assign(config.key_system()); g_wrong_key_id.assign(config.wrong_key_id()); g_license_server.assign(config.license_server()); g_key_id_pssh.assign(a2bs_hex(config.key_id())); - g_service_certificate.assign(config.service_certificate()); + g_provisioning_service_certificate.assign( + config.provisioning_service_certificate()); + g_license_service_certificate.assign(config.license_service_certificate()); g_provisioning_server.assign(config.provisioning_server()); // Extract the key ID from the PSSH box. @@ -63,6 +65,45 @@ static void CommonSetup(bool use_qa) { g_key_id_unwrapped = extractor.data(); } +/* + * Locate the portion of the server's response message that is between + * the strings jason_start_substr and json_end_substr. Returns the string + * through *result. If the start substring match fails, assume the entire + * string represents a serialized protobuf mesaage and return true with + * the entire string. If the end_substring match fails, return false with + * an empty *result. + */ +bool ExtractSignedMessage(const std::string& response, + const std::string& json_start_substr, + const std::string& json_end_substr, + std::string* result) { + std::string response_string; + size_t start = response.find(json_start_substr); + + if (start == response.npos) { + // Assume serialized protobuf message. + result->assign(response); + } else { + // Assume JSON-wrapped protobuf. + size_t end = response.find(json_end_substr, + start + json_start_substr.length()); + if (end == response.npos) { + LOGE("ExtractSignedMessage cannot locate end substring"); + result->clear(); + return false; + } + size_t result_string_size = end - start - json_start_substr.length(); + result->assign(response, start + json_start_substr.length(), + result_string_size); + } + + if (result->empty()) { + LOGE("ExtractSignedMessage: Response message is empty"); + return false; + } + return true; +} + } // namespace class WvCdmEnginePreProvTest : public testing::Test { @@ -72,15 +113,6 @@ class WvCdmEnginePreProvTest : public testing::Test { virtual ~WvCdmEnginePreProvTest() {} - static void SetUpTestCase() { - // NOTE: Select QA/Test server config vs. UAT server config -#if defined(QA_TEST_SERVER) - CommonSetup(true); -#else - CommonSetup(false); -#endif // !defined(QA_TEST_SERVER) - } - virtual void SetUp() { CdmResponseType status = cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_); @@ -97,24 +129,11 @@ class WvCdmEnginePreProvTest : public testing::Test { protected: - bool IsBase64Encoded(const std::string& message) { - for (size_t i = 0; i < message.size(); ++i) { - uint8_t ch = message[i]; - if (ch >= 'a' && ch <= 'z') continue; - if (ch >= 'A' && ch <= 'Z') continue; - if (ch >= '0' && ch <= '9') continue; - if (ch == '-' || ch == '_' || ch == '=' || ch == '.' || ch == '/') { - continue; - } - return false; - } - return true; - } - // Trade request for response via the license server. bool LicenseServerRequestResponse(const std::string& request, std::string* response) { - LOGV("server url: %s", g_license_server.c_str()); + LOGV("LicenseServerRequestResponse: server url: %s", + g_license_server.c_str()); UrlRequest url_request(g_license_server + g_client_auth); url_request.PostRequest(request); @@ -123,29 +142,67 @@ class WvCdmEnginePreProvTest : public testing::Test { return false; } - LOGV("http_resp:\n%s\n", http_response.c_str()); + LOGV("http_response:\n%s\n", http_response.c_str()); // Separate message from HTTP headers. LicenseRequest license_request; - std::string response_message; - license_request.GetDrmMessage(http_response, response_message); + license_request.GetDrmMessage(http_response, *response); - LOGV("resp: size=%u, string:\n%s\n", response_message.size(), - Base64SafeEncode( - std::vector(response_message.begin(), - response_message.end())).c_str()); - - // Response should be base64 encoded. If it is not, - // fix it now. - if (!IsBase64Encoded(response_message)) { - std::vector response_vector(response_message.begin(), - response_message.end()); - response_message = Base64SafeEncode(response_vector); - } - response->swap(response_message); + LOGV("response: size=%u, string:\n%s\n", response->size(), + Base64SafeEncode(std::vector(response->begin(), + response->end())).c_str()); return true; } + virtual void Provision() { + LOGV("WvCdmEnginePreProvTest::Provision: url=%s", + g_provisioning_server.c_str()); + CdmProvisioningRequest prov_request; + std::string provisioning_server_url; + CdmCertificateType cert_type = kCertificateWidevine; + std::string cert_authority; + std::string cert, wrapped_key; + ASSERT_EQ(NO_ERROR, cdm_engine_.SetServiceCertificate( + g_provisioning_service_certificate)); + ASSERT_EQ(NO_ERROR, cdm_engine_.GetProvisioningRequest( + cert_type, cert_authority, &prov_request, + &provisioning_server_url)); + + LOGV("WvCdmEnginePreProvTest::Provision: req=%s", prov_request.c_str()); + + // Ignore URL provided by CdmEngine. Use ours, as configured + // for test vs. production server. + provisioning_server_url.assign(g_provisioning_server); + UrlRequest url_request(provisioning_server_url); + EXPECT_TRUE(url_request.is_connected()); + url_request.PostCertRequestInQueryString(prov_request); + std::string http_message; + bool ok = url_request.GetResponse(&http_message); + EXPECT_TRUE(ok); + + LOGV("WvCdmEnginePreProvTest::Provision: http_message: \n%s\n", + http_message.c_str()); + + // extract provisioning response from received message + // Extracts signed response from JSON string, result is serialized protobuf. + const std::string kMessageStart = "\"signedResponse\": \""; + const std::string kMessageEnd = "\""; + std::string protobuf_response; + EXPECT_TRUE (ExtractSignedMessage(http_message, kMessageStart, kMessageEnd, + &protobuf_response)) << + "Failed to extract signed serialized response from JSON response"; + + LOGV("WvCdmEnginePreProvTest::Provision: extracted response " + "message: \n%s\n", protobuf_response.c_str()); + + ASSERT_EQ(NO_ERROR, + cdm_engine_.HandleProvisioningResponse(protobuf_response, + &cert, &wrapped_key)); + + ASSERT_EQ(NO_ERROR, + cdm_engine_.SetServiceCertificate(g_license_service_certificate)); + } + FileSystem file_system_; CdmEngine cdm_engine_; bool session_opened_; @@ -153,10 +210,75 @@ class WvCdmEnginePreProvTest : public testing::Test { std::string session_id_; }; +class WvCdmEnginePreProvTestStaging : public WvCdmEnginePreProvTest { + public: + WvCdmEnginePreProvTestStaging() {} + + virtual ~WvCdmEnginePreProvTestStaging() {} + + static void SetUpTestCase() { + // NOTE: Select server configuration + CommonSetup(kContentProtectionStagingLicense); + } +}; + +class WvCdmEnginePreProvTestProd : public WvCdmEnginePreProvTest { + public: + WvCdmEnginePreProvTestProd() {} + + virtual ~WvCdmEnginePreProvTestProd() {} + + static void SetUpTestCase() { + // NOTE: Select server configuration + CommonSetup(kContentProtectionProdLicense); + } +}; + +class WvCdmEnginePreProvTestUat : public WvCdmEnginePreProvTest { + public: + WvCdmEnginePreProvTestUat() {} + + virtual ~WvCdmEnginePreProvTestUat() {} + + static void SetUpTestCase() { + // NOTE: Select server configuration + CommonSetup(kContentProtectionUatLicense); + } +}; + +class WvCdmEnginePreProvTestStagingProv30 : public WvCdmEnginePreProvTest { + public: + WvCdmEnginePreProvTestStagingProv30() {} + + virtual ~WvCdmEnginePreProvTestStagingProv30() {} + + static void SetUpTestCase() { + // NOTE: Select server configuration + CommonSetup(kContentProtectionStagingPlusProv30); + } +}; + +class WvCdmEnginePreProvTestUatProv30 : public WvCdmEnginePreProvTest { + public: + WvCdmEnginePreProvTestUatProv30() {} + + virtual ~WvCdmEnginePreProvTestUatProv30() {} + + static void SetUpTestCase() { + // NOTE: Select server configuration + CommonSetup(kContentProtectionUatPlusProv30); + } +}; + class WvCdmEngineTest : public WvCdmEnginePreProvTest { public: WvCdmEngineTest() {} + static void SetUpTestCase() { + // NOTE: Select server configuration + CommonSetup(kContentProtectionStagingLicense); + } + virtual void SetUp() { CdmResponseType status = cdm_engine_.OpenSession(g_key_system, NULL, NULL, &session_id_); @@ -170,43 +292,6 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest { } protected: - void Provision() { - CdmProvisioningRequest prov_request; - std::string provisioning_server_url; - CdmCertificateType cert_type = kCertificateWidevine; - std::string cert_authority; - std::string cert, wrapped_key; - ASSERT_EQ(NO_ERROR, cdm_engine_.SetServiceCertificate( - g_service_certificate)); - CdmResponseType result = NO_ERROR; - for (int i = 0; i < 2; i++) { // Retry once if there is a nonce problem. - result = cdm_engine_.GetProvisioningRequest( - cert_type, cert_authority, &prov_request, &provisioning_server_url); - if (result == CERT_PROVISIONING_NONCE_GENERATION_ERROR) { - LOGW("Woops. Nonce problem. Try again?"); - sleep(1); - } else { - break; - } - } - ASSERT_EQ(NO_ERROR, result); - // Ignore URL provided by CdmEngine. Use ours, as configured - // for test vs. production server. - provisioning_server_url.assign(g_provisioning_server); - UrlRequest url_request(provisioning_server_url); - EXPECT_TRUE(url_request.is_connected()); - url_request.PostCertRequestInQueryString(prov_request); - std::string message; - bool ok = url_request.GetResponse(&message); - EXPECT_TRUE(ok); - // One of many reasons a device might fail to provision is that the server - // rejects its keybox. In that case, we usually see an error of - // CERT_PROVISIONING_RESPONSE_ERROR_1. The error response may help - // somebody look through the server logs for more clues. - ASSERT_EQ(NO_ERROR, cdm_engine_.HandleProvisioningResponse(message, &cert, - &wrapped_key)) - << "Error response: " << message; - } void GenerateKeyRequest(const std::string& key_id, const std::string& init_data_type_string) { @@ -269,6 +354,9 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest { const std::string& client_auth, bool expect_success) { // Use secure connection and chunk transfer coding. + + LOGV("GetKeyRequestResponse: server_url: %s", server_url.c_str()); + UrlRequest url_request(server_url + client_auth); if (!url_request.is_connected()) { return ""; @@ -315,19 +403,19 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest { }; // Test that service certificate is initially absent. -TEST_F(WvCdmEnginePreProvTest, ServiceCertificateInitialNoneTest) { +TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateInitialNoneTest) { ASSERT_FALSE(cdm_engine_.HasServiceCertificate()); }; // Test that service certificate can be properly installed. -TEST_F(WvCdmEnginePreProvTest, ServiceCertificateGoodTest) { - ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_service_certificate), +TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateGoodTest) { + ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_license_service_certificate), NO_ERROR); ASSERT_TRUE(cdm_engine_.HasServiceCertificate()); }; // Test that service certificate can be retrieved from the license server. -TEST_F(WvCdmEnginePreProvTest, ServiceCertificateRequestResponse) { +TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateRequestResponse) { CdmKeyMessage request; std::string certificate; @@ -335,65 +423,110 @@ TEST_F(WvCdmEnginePreProvTest, ServiceCertificateRequestResponse) { ASSERT_FALSE(cdm_engine_.HasServiceCertificate()); // Generate request. - // The request will be a base64 encode of a serialized protobuf message. + // The request will be a serialized protobuf message. ASSERT_TRUE(cdm_engine_.GetServiceCertificateRequest(&request)); - LOGV("ret'd request message:\"%s\"", request.c_str()); - std::string response; ASSERT_TRUE(LicenseServerRequestResponse(request, &response)); // Extract the service certificate - if (cdm_engine_.ParseServiceCertificateResponse(response, &certificate) == - NO_ERROR) { - ASSERT_TRUE(cdm_engine_.HasServiceCertificate()); - LOGV("ret'd cert:\"%s\"", b2a_hex(certificate).c_str()); - return; - } - - // Message did not parse. Possibly it is because of base64 encoding - // of the request. Try again with binary (base64 decoded) message. - - LOGE("Base64 encoded request failed - RETRY with binary request"); - - while (request.size() % 4 != 0) { - request = request + "="; // add padding if necessary - } - std::vector binary_vector = Base64SafeDecode(request); - std::string binary_request(binary_vector.begin(), binary_vector.end()); - LOGV("raw_string=%s", b2a_hex(binary_request).c_str()); - - ASSERT_TRUE(LicenseServerRequestResponse(binary_request, &response)); - ASSERT_EQ(cdm_engine_.ParseServiceCertificateResponse(response, &certificate), NO_ERROR); - LOGV("ret'd cert:\"%s\"", b2a_hex(certificate).c_str()); + ASSERT_TRUE(cdm_engine_.HasServiceCertificate()); + LOGV("ret'd service certificate:\n%s\n", b2a_hex(certificate).c_str()); +}; + +// Test that service certificate can be retrieved from the license server. +TEST_F(WvCdmEnginePreProvTestUat, ServiceCertificateRequestResponse) { + CdmKeyMessage request; + std::string certificate; + + // Initial condition - no service certificate. + ASSERT_FALSE(cdm_engine_.HasServiceCertificate()); + + // Generate request. + // The request will be a serialized protobuf message. + ASSERT_TRUE(cdm_engine_.GetServiceCertificateRequest(&request)); + + std::string response; + ASSERT_TRUE(LicenseServerRequestResponse(request, &response)); + + // Extract the service certificate + ASSERT_EQ(cdm_engine_.ParseServiceCertificateResponse(response, &certificate), + NO_ERROR); ASSERT_TRUE(cdm_engine_.HasServiceCertificate()); + LOGV("ret'd service certificate:\n%s\n", b2a_hex(certificate).c_str()); +}; + +// Test that service certificate can be retrieved from the license server. +TEST_F(WvCdmEnginePreProvTestProd, ServiceCertificateRequestResponse) { + CdmKeyMessage request; + std::string certificate; + + // Initial condition - no service certificate. + ASSERT_FALSE(cdm_engine_.HasServiceCertificate()); + + // Generate request. + // The request will be a serialized protobuf message. + ASSERT_TRUE(cdm_engine_.GetServiceCertificateRequest(&request)); + + std::string response; + ASSERT_TRUE(LicenseServerRequestResponse(request, &response)); + + // Extract the service certificate + ASSERT_EQ(cdm_engine_.ParseServiceCertificateResponse(response, &certificate), + NO_ERROR); + + ASSERT_TRUE(cdm_engine_.HasServiceCertificate()); + LOGV("ret'd service certificate:\n%s\n", b2a_hex(certificate).c_str()); }; // Test that empty service certificate fails. -TEST_F(WvCdmEnginePreProvTest, ServiceCertificateEmptyFailTest) { +TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateEmptyFailTest) { std::string empty_cert; - ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_service_certificate), + ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_license_service_certificate), NO_ERROR); ASSERT_TRUE(cdm_engine_.HasServiceCertificate()); }; // Test that provisioning works, even if device is already provisioned. -TEST_F(WvCdmEngineTest, DISABLED_Provisioning30Test) { +TEST_F(WvCdmEnginePreProvTestStaging, DISABLED_ProvisioningTest) { uint32_t nonce = 0; uint8_t buffer[1]; size_t size = 0; + int result = OEMCrypto_RewrapDeviceRSAKey( 0, buffer, 0, buffer, 0, &nonce, buffer, 0, buffer, buffer, &size); - if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) { + int result30 = OEMCrypto_RewrapDeviceRSAKey30( + 0, &nonce, buffer, 0, buffer, 0, buffer, buffer, &size); + int method = OEMCrypto_GetProvisioningMethod(kLevelDefault); + + if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED && + result30 == OEMCrypto_ERROR_NOT_IMPLEMENTED) { LOGW("WARNING: Skipping ProvisioningTest because the device does not " - "support provisioning. If you are using a baked-in certificate, this " - "is expected. Otherwise, something is wrong."); - return; + "support provisioning. If you are using a baked-in certificate, " + "this is expected. Otherwise, something is wrong."); + ASSERT_EQ(method, OEMCrypto_DrmCertificate); + } else { + if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) { + ASSERT_EQ(method, OEMCrypto_OEMCertificate); + } else { + ASSERT_EQ(method, OEMCrypto_Keybox); + } } + + Provision(); +} + +TEST_F(WvCdmEnginePreProvTestStagingProv30, ProvisioningTest) { + Provision(); +} + +// Test that provisioning works, even if device is already provisioned. +TEST_F(WvCdmEngineTest, DISABLED_ProvisioningTest) { + Provision(); } @@ -403,7 +536,7 @@ TEST_F(WvCdmEngineTest, BaseIsoBmffMessageTest) { } // TODO(juce): Set up with correct test data. -TEST_F(WvCdmEngineTest, BaseWebmMessageTest) { +TEST_F(WvCdmEngineTest, DISABLED_BaseWebmMessageTest) { GenerateKeyRequest(g_key_id_unwrapped, kWebmMimeType); GetKeyRequestResponse(g_license_server, g_client_auth); } @@ -423,7 +556,7 @@ TEST_F(WvCdmEngineTest, NormalDecryptionIsoBmff) { } // TODO(juce): Set up with correct test data. -TEST_F(WvCdmEngineTest, NormalDecryptionWebm) { +TEST_F(WvCdmEngineTest, DISABLED_NormalDecryptionWebm) { GenerateKeyRequest(g_key_id_unwrapped, kWebmMimeType); VerifyNewKeyResponse(g_license_server, g_client_auth); } diff --git a/libwvdrmengine/cdm/core/test/config_test_env.cpp b/libwvdrmengine/cdm/core/test/config_test_env.cpp index a73683e1..3675a7f6 100644 --- a/libwvdrmengine/cdm/core/test/config_test_env.cpp +++ b/libwvdrmengine/cdm/core/test/config_test_env.cpp @@ -3,6 +3,12 @@ #include "config_test_env.h" #include "string_conversions.h" +// Holds the data needed to talk to the various provisioning and +// license servers. +// +// Define a series of configurations, and specify the specific +// data items needed for that configuration. + namespace wvcdm { namespace { @@ -95,18 +101,14 @@ const std::string kUatServiceCertificate = "38540F8A0C227C0011E0F5B38E4E298ED2CB301EB4564965F55C5D79757A" "250A4EB9C84AB3E6539F6B6FDF56899EA29914"; -// QA/Test server (kContentProtectionTestQAServer) -// -const std::string kQALicenseServerUrl = - "https://widevine-proxy-qa.corp.google.com/proxy"; - -const std::string kQAProvisioningServerUrl = - "http://www-googleapis-test.sandbox.google.com/" - "certificateprovisioning/v1/devicecertificates/create"; +// Content Protection license server (Production) data +const std::string kCpProdLicenseServer = + "https://widevine-proxy.appspot.com/proxy"; // Content Protection license server (UAT) data const std::string kCpUatLicenseServer = - "http://widevine-proxy.appspot.com/proxy"; + "https://proxy.uat.widevine.com/proxy"; + const std::string kCpClientAuth = ""; const std::string kCpKeyId = "00000042" // blob size @@ -130,7 +132,7 @@ const std::string kCpOfflineKeyId = // Content Protection license server (staging) data const std::string kCpStagingLicenseServer = - "http://wv-staging-proxy.appspot.com/proxy"; + "https://proxy.staging.widevine.com/proxy"; // Google Play license server data const std::string kGpLicenseServer = @@ -181,28 +183,47 @@ const std::string kStagingProvisioningServerUrl = "certificateprovisioning/v1/devicecertificates/create" "?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE"; - const ConfigTestEnv::LicenseServerConfiguration license_servers[] = { - {kGooglePlayServer, kGpLicenseServer, kGpClientAuth, kGpKeyId, - kGpOfflineKeyId, "", kStagingProvisioningServerUrl}, - {kContentProtectionUatServer, kCpUatLicenseServer, kCpClientAuth, - kCpKeyId, kCpOfflineKeyId, kProdServiceCertificate, - kStagingProvisioningServerUrl}, - {kContentProtectionStagingServer, kCpStagingLicenseServer, - kCpClientAuth, kCpKeyId, kCpOfflineKeyId, kProdServiceCertificate, - kStagingProvisioningServerUrl}, + {kGooglePlayServer, kGpLicenseServer, "", kGpClientAuth, kGpKeyId, + kGpOfflineKeyId, kStagingProvisioningServerUrl, ""}, + + {kContentProtectionProdLicense, kCpProdLicenseServer, + kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId, + kProductionProvisioningServerUrl, kProdServiceCertificate}, + + {kContentProtectionUatLicense, kCpUatLicenseServer, + kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId, + kProductionProvisioningServerUrl, kProdServiceCertificate}, + + {kContentProtectionStagingLicense, kCpStagingLicenseServer, + kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId, + kStagingProvisioningServerUrl, kStagingServiceCertificate}, + + {kContentProtectionProdPlusProv30, kCpProdLicenseServer, + kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId, + kStagingProvisioningServerUrl, kStagingServiceCertificate}, + + {kContentProtectionUatPlusProv30, kCpUatLicenseServer, + kProdServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId, + kStagingProvisioningServerUrl, kStagingServiceCertificate}, + + {kContentProtectionStagingPlusProv30, kCpStagingLicenseServer, + kStagingServiceCertificate, kCpClientAuth, kCpKeyId, kCpOfflineKeyId, + kStagingProvisioningServerUrl, kStagingServiceCertificate}, }; } // namespace -ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id) { Init(server_id); } +ConfigTestEnv::ConfigTestEnv(ServerConfigurationId server_id) { + Init(server_id); +} -ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id, bool streaming) { +ConfigTestEnv::ConfigTestEnv(ServerConfigurationId server_id, bool streaming) { Init(server_id); if (!streaming) key_id_ = license_servers[server_id].offline_key_id; } -ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id, bool streaming, +ConfigTestEnv::ConfigTestEnv(ServerConfigurationId server_id, bool streaming, bool renew, bool release) { Init(server_id); if (!streaming) { @@ -220,13 +241,16 @@ ConfigTestEnv::ConfigTestEnv(LicenseServerId server_id, bool streaming, } } -void ConfigTestEnv::Init(LicenseServerId server_id) { +void ConfigTestEnv::Init(ServerConfigurationId server_id) { client_auth_ = license_servers[server_id].client_tag; key_id_ = license_servers[server_id].key_id; key_system_ = kWidevineKeySystem; - license_server_ = license_servers[server_id].url; - provisioning_server_ = license_servers[server_id].provisioning_server; - service_certificate_ = a2bs_hex(license_servers[server_id].service_certificate); + license_server_ = license_servers[server_id].license_server_url; + provisioning_server_ = license_servers[server_id].provisioning_server_url; + license_service_certificate_ = + a2bs_hex(license_servers[server_id].license_service_certificate); + provisioning_service_certificate_ = + a2bs_hex(license_servers[server_id].provisioning_service_certificate); wrong_key_id_ = kWrongKeyId; } diff --git a/libwvdrmengine/cdm/core/test/config_test_env.h b/libwvdrmengine/cdm/core/test/config_test_env.h index f7052eb4..1a3f26dc 100644 --- a/libwvdrmengine/cdm/core/test/config_test_env.h +++ b/libwvdrmengine/cdm/core/test/config_test_env.h @@ -6,30 +6,50 @@ #include #include "wv_cdm_types.h" +// Declare class ConfigTestEnv - holds the configuration settings needed +// to talk to the various provisioning and license servers. +// +// License Servers +// QA - early test server (corporate access only, not generally usable). +// UAT - test server with non-production data. +// Staging - test server with access to production data. +// Production - live, production server. +// Google Play - Allows testing on Google Play servers (very stale). +// +// Provisioning Servers +// UAT - early access provisioning server. +// Staging - early access to features. +// Production - live production server. + +// Useful configurations namespace wvcdm { typedef enum { - kGooglePlayServer, - kContentProtectionUatServer, - kContentProtectionStagingServer, - kContentProtectionTestQAServer, -} LicenseServerId; + kGooglePlayServer, // not tested recently + kContentProtectionProdLicense, + kContentProtectionUatLicense, + kContentProtectionStagingLicense, + kContentProtectionProdPlusProv30, + kContentProtectionUatPlusProv30, + kContentProtectionStagingPlusProv30, +} ServerConfigurationId; // Configures default test environment. class ConfigTestEnv { public: typedef struct { - LicenseServerId id; - std::string url; + ServerConfigurationId id; + std::string license_server_url; + std::string license_service_certificate; std::string client_tag; std::string key_id; std::string offline_key_id; - std::string service_certificate; - std::string provisioning_server; + std::string provisioning_server_url; + std::string provisioning_service_certificate; } LicenseServerConfiguration; - explicit ConfigTestEnv(LicenseServerId server_id); - ConfigTestEnv(LicenseServerId server_id, bool streaming); - ConfigTestEnv(LicenseServerId server_id, bool streaming, bool renew, + explicit ConfigTestEnv(ServerConfigurationId server_id); + ConfigTestEnv(ServerConfigurationId server_id, bool streaming); + ConfigTestEnv(ServerConfigurationId server_id, bool streaming, bool renew, bool release); ~ConfigTestEnv() {}; @@ -40,8 +60,11 @@ class ConfigTestEnv { const std::string& provisioning_server() const { return provisioning_server_; } - const std::string& service_certificate() const { - return service_certificate_; + const std::string& license_service_certificate() const { + return license_service_certificate_; + } + const std::string& provisioning_service_certificate() const { + return provisioning_service_certificate_; } const KeyId& wrong_key_id() const { return wrong_key_id_; } @@ -54,14 +77,15 @@ class ConfigTestEnv { } private: - void Init(LicenseServerId server_id); + void Init(ServerConfigurationId server_id); std::string client_auth_; KeyId key_id_; CdmKeySystem key_system_; std::string license_server_; std::string provisioning_server_; - std::string service_certificate_; + std::string license_service_certificate_; + std::string provisioning_service_certificate_; KeyId wrong_key_id_; CORE_DISALLOW_COPY_AND_ASSIGN(ConfigTestEnv); diff --git a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp index de9f2a69..438cbe58 100644 --- a/libwvdrmengine/cdm/core/test/device_files_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/device_files_unittest.cpp @@ -124,6 +124,7 @@ struct LicenseInfo { int64_t grace_period_end_time; std::string app_parameters; std::string usage_entry; + uint32_t usage_entry_number; std::string file_data; }; @@ -230,9 +231,9 @@ LicenseInfo license_test_data[] = { "0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF" "A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0" "BEA6CABACA1C2C"), - "https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "", "", + "https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "", "", 0, a2bs_hex( - "0AAC150802100122A5150801121408011210303132333435363738394142434445461" + "0AAE150802100122A7150801121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" @@ -311,8 +312,9 @@ LicenseInfo license_test_data[] = { "106B63746C0000000000ECDCBE0000000020DBDFA68F051A20182F029E35047A3841F" "A176C74E5B387350E8D58DEA6878FF0BEA6CABACA1C2C3A2E68747470733A2F2F7465" "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" - "3654000480058006200122039CB77169260F923E5D4BA5BBF6A7611117483253F2869" - "9DF3D9D14C3718E309")}, + "365400048005800620068001220785CE1756656A049E77F28C8449AB2DD115B6C43B2" + "FF232D23F98B72F1DCE96A" + )}, // license 1 {"ksidC8EAA2579A282EB0", DeviceFiles::kLicenseStateReleasing, @@ -415,8 +417,9 @@ LicenseInfo license_test_data[] = { a2bs_hex( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021" "22232425262728292a2b2c2d2e2f"), + 5, a2bs_hex( - "0AF5150802100122EE150802121408011210303132333435363738394142434445461" + "0AF7150802100122F0150802121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" @@ -497,8 +500,8 @@ LicenseInfo license_test_data[] = { "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" "36540F8ACD1910148E58ED29101520F0A054E616D6531120656616C75653158006230" "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212" - "2232425262728292A2B2C2D2E2F1220312487214ACA5A9AF5ED9D45F209DC77E03CA1" - "DBFFDF86C44A35A1351CE968B9")}, + "2232425262728292A2B2C2D2E2F6805122010DB816A045F2AA5865B17FE2F20DA2114" + "17B2F8B2D7511C9DE89A87CB5208AB")}, // license 2 {"ksidE8C37662C88DC673", DeviceFiles::kLicenseStateReleasing, @@ -601,8 +604,9 @@ LicenseInfo license_test_data[] = { a2bs_hex( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021" "22232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + 12, a2bs_hex( - "0AAB160802100122A4160802121408011210303132333435363738394142434445461" + "0AAD160802100122A6160802121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" "7A7D507618A5D3A68F05228E023082010A0282010100A947904B8DBD55FB685FDB302" "5574517CCCC74EE4FEAF6629D5179A52FF85CE7409528EFFA0E5DFC3DE9A34BA5F08B" @@ -684,8 +688,9 @@ LicenseInfo license_test_data[] = { "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910152150A054E616D6531120C5661" "6C756531204E616D653252160A0C4E616D653220506172616D321206506172616D325" "8006240000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E" - "1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F122" - "07CEAAE401B81E635808AC830A0F3F43308A38FAB16069E542F994B6EC1325280")}}; + "1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F680" + "C12206AA0237760D1F06E5CB78F5AFC3D124BBF7C26921CB3CC2EA44766801E25D34" + "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. @@ -792,8 +797,9 @@ LicenseInfo license_update_test_data[] = { a2bs_hex( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021" "22232425262728292a2b2c2d2e2f"), + 15, a2bs_hex( - "0AEC150802100122E5150801121408011210303132333435363738394142434445461" + "0AEE150802100122E7150801121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" "7A7D5076189EDFB68F05228E023082010A0282010100CC1715C81AD3F6F279C686F82" "6E6D7C8961EB13318367D06B4061BBC57E3C616A226A10F042CAD54D44C6484C725CD" @@ -874,14 +880,14 @@ LicenseInfo license_update_test_data[] = { "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910158006230000102030405060708" "090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2" - "B2C2D2E2F1220A33C179B7718632337DFDC32D3711FD543336EBE838979DFDEB3A168" - "BC9AFB27")}, + "B2C2D2E2F680F122009B8588A8E9926339289BA373DB8479A71F7AA1164083D90613F" + "766D60B07CBC")}, // license being released. all fields are identical except for license // state and hashed file data {"", DeviceFiles::kLicenseStateReleasing, "", "", "", "", "", "", 0, 0, 0, - "", "", + "", "", 15, a2bs_hex( - "0AEC150802100122E5150802121408011210303132333435363738394142434445461" + "0AEE150802100122E7150802121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" "7A7D5076189EDFB68F05228E023082010A0282010100CC1715C81AD3F6F279C686F82" "6E6D7C8961EB13318367D06B4061BBC57E3C616A226A10F042CAD54D44C6484C725CD" @@ -962,8 +968,8 @@ LicenseInfo license_update_test_data[] = { "73742E676F6F676C652E636F6D2F6C6963656E73652F47657443656E634C6963656E7" "36540EF9BAFCDF8ACD1910148DCFDAFCDF8ACD1910158006230000102030405060708" "090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2" - "B2C2D2E2F1220394BA01DFB519C1A7311115F8B2A0AC3141F981FFEA09FCD48A8EFA3" - "A045AAE6")}}; + "B2C2D2E2F680F12202F5B77A3168AC2A81832231A435D0587F6D1DF3B905A7058C5E8" + "565C81B96CA6")}}; // Application parameters were added to the License message. This data // is used to verify that a License saved without application parameters can @@ -1065,7 +1071,7 @@ LicenseInfo license_app_parameters_backwards_compatibility_test_data = { "0112001A16200342120A106B63746C0000000000ECDCBE0000000020DBDF" "A68F051A20182F029E35047A3841FA176C74E5B387350E8D58DEA6878FF0" "BEA6CABACA1C2C"), - "https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "", "", + "https://test.google.com/license/GetCencLicense", 0x0, 0x0, 0x0, "", "", 0, a2bs_hex( "0AA8150802100122A1150801121408011210303132333435363738394142434445461" "A9D0E080112950C0AD70B080112EF090AB002080212103E560EC5335E346F591BC4D0" @@ -1154,11 +1160,12 @@ struct UsageInfo { std::string license_request; std::string license; std::string usage_entry; + uint32_t usage_entry_number; std::string file_data; }; UsageInfo kUsageInfoTestData[] = { - {"", "", "", "", // 0 usage info records + {"", "", "", "", 0, // 0 usage info records a2bs_hex("0A06080210012A00122095053501C5FA405B7EF01DA94685C6B20CB36493" "A9CF1653B720E2BEA3B77929")}, {// 1 usage info record @@ -1196,6 +1203,7 @@ UsageInfo kUsageInfoTestData[] = { a2bs_hex( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021" "22232425262728292a2b2c2d2e2f"), + 6, a2bs_hex( "0AB307080210012AAC070AA9070A8001924B035FBDA56AE5EF0ED05A08DE7AECC8ABE" "1835E0C4A548F7803937F4C3B4520EB7F3334FFCDFA00DE56408F09D5019FCE87072D" @@ -1261,6 +1269,7 @@ UsageInfo kUsageInfoTestData[] = { a2bs_hex( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021" "22232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + 14, a2bs_hex( "0ADF0E080210012AD80E0AA9070A8001924B035FBDA56AE5EF0ED05A08DE7AECC8ABE" "1835E0C4A548F7803937F4C3B4520EB7F3334FFCDFA00DE56408F09D5019FCE87072D" @@ -1353,6 +1362,7 @@ UsageInfo kUsageInfoTestData[] = { a2bs_hex( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021" "22232425262728292a2b2c2d2e2f"), + 19, a2bs_hex( "0A8B16080210012A84160AA9070A8001924B035FBDA56AE5EF0ED05A08DE7AECC8ABE" "1835E0C4A548F7803937F4C3B4520EB7F3334FFCDFA00DE56408F09D5019FCE87072D" @@ -1465,88 +1475,82 @@ HlsAttributesInfo kHlsAttributesTestData[] = { // Usage Table and Entry Test Data // Note: Make sure the number of entries in kUsageEntriesTestData and // kUsageTableInfoTestData are equal. -DeviceFiles::UsageEntryInfo kUsageEntriesTestData[] = { +CdmUsageEntryInfo kUsageEntriesTestData[] = { // usage entry 0 { - DeviceFiles::kStorageLicense, "ksid0", "", "", + kStorageLicense, "ksid0", "", }, // usage entry 1 { - DeviceFiles::kStorageLicense, "ksid1", "", "", + kStorageLicense, "ksid1", "", }, // usage entry 2 { - DeviceFiles::kStorageUsageInfo, "", "provider_session_token_2", - "app_id_2", + kStorageUsageInfo, "", "app_id_2", }, // usage entry 3 { - DeviceFiles::kStorageUsageInfo, "", "provider_session_token_3", - "app_id_3", + kStorageUsageInfo, "", "app_id_3", }, // usage entry 4 { - DeviceFiles::kStorageLicense, "ksid4", "", "", + kStorageLicense, "ksid4", "", }, // usage entry 5 { - DeviceFiles::kStorageUsageInfo, "", "provider_session_token_5", - "app_id_5", + kStorageUsageInfo, "", "app_id_5", }, }; struct UsageTableTestInfo { - std::string usage_table_header; + CdmUsageTableHeader usage_table_header; std::string file_data; }; UsageTableTestInfo kUsageTableInfoTestData[] = { // usage table 0 + {a2bs_hex("5574517CCC"), a2bs_hex("0A18080510013A120A055574517CCC1209080112056B73696430122018268E3F" "384F28D04BEE00304089C000463C22E987532855390915FD02C36B5C")}, // usage table 1 {a2bs_hex("CA870203010001288001"), - a2bs_hex("0A28080510013A220A0ACA8702030100012880011209080112056B7369643012" - "09080112056B7369643112202D3638164ADC3B4276734A8EDE96C40BFE14DDB2" - "8013337A3A1A9DFC09F34923")}, + a2bs_hex("0A2C080510013A260A0ACA870203010001288001120B080112056B736964301A" + "00120B080112056B736964311A00122049A8F3481444A5B64B6C4F05FBCC2EF8" + "CB67444A08654763F2F5B80F658D7B38")}, // usage table 2 {a2bs_hex("7A7D507618A5D3A68F05228E023082010A028201"), - a2bs_hex("0A5A080510013A540A147A7D507618A5D3A68F05228E023082010A0282011209" - "080112056B736964301209080112056B73696431122608021A1870726F766964" - "65725F73657373696F6E5F746F6B656E5F3222086170705F69645F321220CB07" - "CA08A1E76C61A5F45067176B960A9DB40D169025AF245CF1AFC66C979F47")}, + a2bs_hex("0A46080510013A400A147A7D507618A5D3A68F05228E023082010A028201120B" + "080112056B736964301A00120B080112056B736964311A00120E080212001A08" + "6170705F69645F321220783E93A02223BDB94E743856C0F69C35B213ACCDDE91" + "93E48E9186AA83B80584")}, // usage table 3 {a2bs_hex("E83A4902772DAFD2740B7748E9C3B1752D6F12859CED07E82969B4EC"), - a2bs_hex("0A8B01080510013A84010A1CE83A4902772DAFD2740B7748E9C3B1752D6F1285" - "9CED07E82969B4EC1209080112056B736964301209080112056B736964311226" - "08021A1870726F76696465725F73657373696F6E5F746F6B656E5F3222086170" - "705F69645F32122608021A1870726F76696465725F73657373696F6E5F746F6B" - "656E5F3322086170705F69645F331220C4157F80E81C923A9F0885CE6B928D15" - "7E1648384C3E44F04A966815EB09B260")}, + a2bs_hex("0A5E080510013A580A1CE83A4902772DAFD2740B7748E9C3B1752D6F12859CED" + "07E82969B4EC120B080112056B736964301A00120B080112056B736964311A00" + "120E080212001A086170705F69645F32120E080212001A086170705F69645F33" + "122084E67F1338727291BC3D92E28442DC8B0F44CB5AF7B98A799313B7EB7F55" + "ED18")}, // usage table 4 {a2bs_hex("CA870203010001288001300112800250D1F8B1ECF849B60FF93E37C4DEEF" "52F1CCFC047EF42300131F9C4758F4"), - a2bs_hex("0AA701080510013AA0010A2DCA870203010001288001300112800250D1F8B1EC" - "F849B60FF93E37C4DEEF52F1CCFC047EF42300131F9C4758F41209080112056B" - "736964301209080112056B73696431122608021A1870726F76696465725F7365" - "7373696F6E5F746F6B656E5F3222086170705F69645F32122608021A1870726F" - "76696465725F73657373696F6E5F746F6B656E5F3322086170705F69645F3312" - "09080112056B7369643412203F75C53693E7A3DC9BA5BF3E23D7EFCF3C05687A" - "A6082E3AB78F563525981999")}, + a2bs_hex("0A7C080510013A760A2DCA870203010001288001300112800250D1F8B1ECF849" + "B60FF93E37C4DEEF52F1CCFC047EF42300131F9C4758F4120B080112056B7369" + "64301A00120B080112056B736964311A00120E080212001A086170705F69645F" + "32120E080212001A086170705F69645F33120B080112056B736964341A001220" + "1CDFCFED5E58A1DF77E1B335305424E1F0260340F9CC15985684C43A4207652" + "1")}, // usage table 5 {a2bs_hex("EC83A4902772DAFD2740B7748E9C3B1752D6F12859CED07E8882969B433E" "C29AC6FDBE79230B0FAED5D94CF6B829A420BBE3270323941776EE60DD6B"), - a2bs_hex("0ADE01080510013AD7010A3CEC83A4902772DAFD2740B7748E9C3B1752D6F128" + a2bs_hex("0A9C01080510013A95010A3CEC83A4902772DAFD2740B7748E9C3B1752D6F128" "59CED07E8882969B433EC29AC6FDBE79230B0FAED5D94CF6B829A420BBE32703" - "23941776EE60DD6B1209080112056B736964301209080112056B736964311226" - "08021A1870726F76696465725F73657373696F6E5F746F6B656E5F3222086170" - "705F69645F32122608021A1870726F76696465725F73657373696F6E5F746F6B" - "656E5F3322086170705F69645F331209080112056B73696434122608021A1870" - "726F76696465725F73657373696F6E5F746F6B656E5F3522086170705F69645F" - "3512203B35BD5C615BBA79008A7A1DA29AFA69F5CD529DFDE794A0544E423B72" - "1CB8E8")}, + "23941776EE60DD6B120B080112056B736964301A00120B080112056B73696431" + "1A00120E080212001A086170705F69645F32120E080212001A086170705F6964" + "5F33120B080112056B736964341A00120E080212001A086170705F69645F3512" + "20305C7A27A918268119E1996FC182C153DF805034A387F90C3585749E764731" + "32")}, }; class MockFile : public File { @@ -1889,7 +1893,8 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) { license_test_data[license_num].playback_start_time, license_test_data[license_num].last_playback_time, license_test_data[license_num].grace_period_end_time, app_parameters, - license_test_data[license_num].usage_entry)); + license_test_data[license_num].usage_entry, + license_test_data[license_num].usage_entry_number)); } INSTANTIATE_TEST_CASE_P(StoreLicense, DeviceFilesStoreTest, ::testing::Bool()); @@ -1939,7 +1944,8 @@ TEST_F(DeviceFilesTest, StoreLicenses) { license_test_data[i].playback_start_time, license_test_data[i].last_playback_time, license_test_data[i].grace_period_end_time, app_parameters, - license_test_data[i].usage_entry)); + license_test_data[i].usage_entry, + license_test_data[i].usage_entry_number)); } } @@ -1981,6 +1987,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { std::string release_server_url; CdmAppParameterMap app_parameters; std::string usage_entry; + uint32_t usage_entry_number; for (size_t i = 0; i < kNumberOfLicenses; i++) { DeviceFiles::LicenseState license_state; @@ -1989,7 +1996,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { &key_request, &key_response, &key_renewal_request, &key_renewal_response, &release_server_url, &playback_start_time, &last_playback_time, &grace_period_end_time, &app_parameters, - &usage_entry)); + &usage_entry, &usage_entry_number)); 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); @@ -2001,6 +2008,7 @@ TEST_F(DeviceFilesTest, RetrieveLicenses) { EXPECT_EQ(license_test_data[i].grace_period_end_time, grace_period_end_time); EXPECT_EQ(license_test_data[i].usage_entry, usage_entry); + EXPECT_EQ(license_test_data[i].usage_entry_number, usage_entry_number); std::map::iterator itr; for (itr = app_parameters.begin(); itr != app_parameters.end(); ++itr) { @@ -2049,12 +2057,14 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) { std::string release_server_url; CdmAppParameterMap app_parameters; std::string usage_entry; + uint32_t usage_entry_number; 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, - &grace_period_end_time, &app_parameters, &usage_entry)); + &grace_period_end_time, &app_parameters, &usage_entry, + &usage_entry_number)); EXPECT_EQ(test_data->license_state, license_state); EXPECT_EQ(test_data->pssh_data, pssh_data); EXPECT_EQ(test_data->key_request, key_request); @@ -2066,6 +2076,7 @@ TEST_F(DeviceFilesTest, AppParametersBackwardCompatibility) { EXPECT_EQ(test_data->grace_period_end_time, grace_period_end_time); EXPECT_EQ(0u, app_parameters.size()); EXPECT_EQ(test_data->usage_entry, usage_entry); + EXPECT_EQ(test_data->usage_entry_number, usage_entry_number); } TEST_F(DeviceFilesTest, UpdateLicenseState) { @@ -2102,7 +2113,8 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) { license_update_test_data[0].last_playback_time, license_update_test_data[0].grace_period_end_time, GetAppParameters(license_test_data[0].app_parameters), - license_update_test_data[0].usage_entry)); + license_update_test_data[0].usage_entry, + license_update_test_data[0].usage_entry_number)); EXPECT_TRUE(device_files.StoreLicense( license_update_test_data[0].key_set_id, @@ -2117,7 +2129,8 @@ TEST_F(DeviceFilesTest, UpdateLicenseState) { license_update_test_data[0].last_playback_time, license_update_test_data[0].grace_period_end_time, GetAppParameters(license_test_data[0].app_parameters), - license_update_test_data[0].usage_entry)); + license_update_test_data[0].usage_entry, + license_update_test_data[0].usage_entry_number)); } TEST_F(DeviceFilesTest, DeleteLicense) { @@ -2158,12 +2171,14 @@ TEST_F(DeviceFilesTest, DeleteLicense) { int64_t playback_start_time, last_playback_time, grace_period_end_time; CdmAppParameterMap app_parameters; std::string usage_entry; + uint32_t usage_entry_number; 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, - &grace_period_end_time, &app_parameters, &usage_entry)); + &grace_period_end_time, &app_parameters, &usage_entry, + &usage_entry_number)); 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); @@ -2181,6 +2196,7 @@ TEST_F(DeviceFilesTest, DeleteLicense) { std::string::npos); } EXPECT_EQ(license_test_data[0].usage_entry, usage_entry); + EXPECT_EQ(license_test_data[0].usage_entry_number, usage_entry_number); EXPECT_TRUE(device_files.DeleteLicense(license_test_data[0].key_set_id)); EXPECT_FALSE(device_files.LicenseExists(license_test_data[0].key_set_id)); @@ -2235,7 +2251,9 @@ TEST_P(DeviceFilesUsageInfoTest, Read) { EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); std::vector > license_info; - ASSERT_TRUE(device_files.RetrieveUsageInfo(app_id, &license_info)); + ASSERT_TRUE(device_files.RetrieveUsageInfo( + DeviceFiles::GetUsageInfoFileName(app_id), + &license_info)); if (index >= 0) { EXPECT_EQ(static_cast(index), license_info.size()); for (size_t i = 0; i < license_info.size(); ++i) { @@ -2263,6 +2281,7 @@ TEST_P(DeviceFilesUsageInfoTest, Store) { std::string license(GenerateRandomData(kLicenseLen)); std::string key_set_id(GenerateRandomData(kKeySetIdLen)); std::string usage_entry(GenerateRandomData(kUsageEntryLen)); + uint32_t usage_entry_number = 16; std::string path = device_base_path_ + DeviceFiles::GetUsageInfoFileName(app_id); @@ -2300,8 +2319,10 @@ TEST_P(DeviceFilesUsageInfoTest, Store) { DeviceFiles device_files(&file_system); EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); - ASSERT_TRUE(device_files.StoreUsageInfo(pst, license_request, license, app_id, - key_set_id, usage_entry)); + ASSERT_TRUE(device_files.StoreUsageInfo( + pst, license_request, license, + DeviceFiles::GetUsageInfoFileName(app_id), + key_set_id, usage_entry, usage_entry_number)); } TEST_P(DeviceFilesUsageInfoTest, Delete) { @@ -2349,9 +2370,13 @@ TEST_P(DeviceFilesUsageInfoTest, Delete) { EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); if (index >= 1) { - ASSERT_TRUE(device_files.DeleteUsageInfo(app_id, pst)); + ASSERT_TRUE(device_files.DeleteUsageInfo( + DeviceFiles::GetUsageInfoFileName(app_id), + pst)); } else { - ASSERT_FALSE(device_files.DeleteUsageInfo(app_id, pst)); + ASSERT_FALSE(device_files.DeleteUsageInfo( + DeviceFiles::GetUsageInfoFileName(app_id), + pst)); } } @@ -2385,7 +2410,9 @@ TEST_P(DeviceFilesUsageInfoTest, DeleteAll) { EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); std::vector psts; - ASSERT_TRUE(device_files.DeleteAllUsageInfoForApp(app_id, &psts)); + ASSERT_TRUE(device_files.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(app_id), + &psts)); if (index < 0) { EXPECT_EQ(0u, psts.size()); } else { @@ -2479,20 +2506,14 @@ TEST_P(DeviceFilesUsageTableTest, Store) { size_t entry_data_length = 0; std::vector entry_data; - std::vector usage_entry_info; + std::vector usage_entry_info; usage_entry_info.resize(index + 1); for (int i = 0; i <= index; ++i) { usage_entry_info[i] = kUsageEntriesTestData[i]; - if (kUsageEntriesTestData[i].storage_type == DeviceFiles::kStorageLicense) { - entry_data.push_back(kUsageEntriesTestData[i].key_set_id); - entry_data_length += kUsageEntriesTestData[i].key_set_id.size(); - } else { - entry_data.push_back(kUsageEntriesTestData[i].provider_session_token); - entry_data.push_back(kUsageEntriesTestData[i].app_id); - entry_data_length += - kUsageEntriesTestData[i].provider_session_token.size() + - kUsageEntriesTestData[i].app_id.size(); - } + entry_data.push_back(kUsageEntriesTestData[i].key_set_id); + entry_data.push_back(kUsageEntriesTestData[i].usage_info_file_name); + entry_data_length += kUsageEntriesTestData[i].key_set_id.size() + + kUsageEntriesTestData[i].usage_info_file_name.size(); } entry_data.push_back(kUsageTableInfoTestData[index].usage_table_header); entry_data_length += kUsageTableInfoTestData[index].usage_table_header.size(); @@ -2516,7 +2537,7 @@ TEST_P(DeviceFilesUsageTableTest, Store) { TEST_P(DeviceFilesUsageTableTest, Read) { MockFileSystem file_system; MockFile file; - int index = GetParam(); + size_t index = GetParam(); std::string path = device_base_path_ + DeviceFiles::GetUsageTableFileName(); @@ -2535,28 +2556,22 @@ TEST_P(DeviceFilesUsageTableTest, Read) { DeviceFiles device_files(&file_system); EXPECT_TRUE(device_files.Init(kSecurityLevelL1)); - std::vector usage_entry_info; - std::string usage_table_header; + std::vector usage_entry_info; + CdmUsageTableHeader usage_table_header; ASSERT_TRUE(device_files.RetrieveUsageTableInfo(&usage_table_header, &usage_entry_info)); EXPECT_EQ(kUsageTableInfoTestData[index].usage_table_header, usage_table_header); EXPECT_EQ(index + 1u, usage_entry_info.size()); - for (int i = 0; i <= index; ++i) { + for (size_t i = 0; i <= index; ++i) { EXPECT_EQ(kUsageEntriesTestData[i].storage_type, usage_entry_info[i].storage_type); - if (usage_entry_info[i].storage_type == DeviceFiles::kStorageLicense) { - EXPECT_EQ(kUsageEntriesTestData[i].key_set_id, - usage_entry_info[i].key_set_id); - EXPECT_EQ(kEmptyString, usage_entry_info[i].provider_session_token); - EXPECT_EQ(kEmptyString, usage_entry_info[i].app_id); - } else { - EXPECT_EQ(kEmptyString, usage_entry_info[i].key_set_id); - EXPECT_EQ(kUsageEntriesTestData[i].provider_session_token, - usage_entry_info[i].provider_session_token); - EXPECT_EQ(kUsageEntriesTestData[i].app_id, usage_entry_info[i].app_id); - } + EXPECT_EQ(kUsageEntriesTestData[i].key_set_id, + usage_entry_info[i].key_set_id); + EXPECT_EQ( + kUsageEntriesTestData[i].usage_info_file_name, + usage_entry_info[i].usage_info_file_name); } } diff --git a/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp b/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp index 29f68486..dad28238 100644 --- a/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/generic_crypto_unittest.cpp @@ -25,7 +25,50 @@ namespace { const std::string kKeySystem = "com.widevine.alpha"; std::string g_provisioning_server; -std::string g_service_certificate; +std::string g_license_service_certificate; +std::string g_provisioning_service_certificate; + +/* + * Locate the portion of the server's response message that is between + * the strings jason_start_substr and json_end_substr. Returns the string + * through *result. If the start substring match fails, assume the entire + * string represents a serialized protobuf mesaage and return true with + * the entire string. If the end_substring match fails, return false with + * an empty *result. + */ +bool ExtractSignedMessage(const std::string& response, + const std::string& json_start_substr, + const std::string& json_end_substr, + std::string* result) { + std::string b64_string; + size_t start = response.find(json_start_substr); + + if (start == response.npos) { + // Assume web safe protobuf + b64_string.assign(response); + } else { + // Assume JSON-wrapped protobuf + size_t end = response.find(json_end_substr, + start + json_start_substr.length()); + if (end == response.npos) { + LOGE("ExtractSignedMessage cannot locate end substring"); + result->clear(); + return false; + } + size_t b64_string_size = end - start - json_start_substr.length(); + b64_string.assign(response, start + json_start_substr.length(), + b64_string_size); + } + + if (b64_string.empty()) { + LOGE("Response message is empty"); + result->clear(); + return false; + } + + result->swap(b64_string); + return true; +} } // namespace @@ -38,13 +81,11 @@ class WvGenericOperationsTest : public testing::Test { virtual void SetUp() { ::testing::Test::SetUp(); -#if defined(QA_TEST_SERVER) - ConfigTestEnv config(kContentProtectionTestQAServer); -#else - ConfigTestEnv config(kContentProtectionUatServer); -#endif // !defined(QA_TEST_SERVER) + ConfigTestEnv config(kContentProtectionStagingPlusProv30); - g_service_certificate.assign(config.service_certificate()); + g_provisioning_service_certificate.assign( + config.provisioning_service_certificate()); + g_license_service_certificate.assign(config.license_service_certificate()); g_provisioning_server.assign(config.provisioning_server()); cdm_engine_ = NULL; @@ -52,15 +93,13 @@ class WvGenericOperationsTest : public testing::Test { // TODO(fredgc or gmorgan): This should be updated for provisioning 3.0 // Load test keybox. This keybox will be used by any CryptoSession // created by the CDM under test. -#if defined(PROVISIONING_30) - ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestRSAKey()); -#else ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadTestKeybox()); -#endif // !defined(PROVISIONING_30) // Perform CdmEngine setup cdm_engine_ = new CdmEngine(&file_system_); + Provision(); + CdmResponseType status = cdm_engine_->OpenSession(kKeySystem, NULL, NULL, &session_id_); if (status == NEED_PROVISIONING) { @@ -177,29 +216,55 @@ class WvGenericOperationsTest : public testing::Test { } protected: - void Provision() { + + virtual void Provision() { + LOGE("WvCdmEnginePreProvTest::Provision: url=%s", + g_provisioning_server.c_str()); CdmProvisioningRequest prov_request; std::string provisioning_server_url; CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority; std::string cert, wrapped_key; - cdm_engine_->SetServiceCertificate(g_service_certificate); - ASSERT_EQ(NO_ERROR, - cdm_engine_->GetProvisioningRequest( - cert_type, cert_authority, &prov_request, - &provisioning_server_url)); + ASSERT_EQ(NO_ERROR, cdm_engine_->SetServiceCertificate( + g_provisioning_service_certificate)); + ASSERT_EQ(NO_ERROR, cdm_engine_->GetProvisioningRequest( + cert_type, cert_authority, &prov_request, + &provisioning_server_url)); + + LOGV("WvCdmEnginePreProvTest::Provision: req=%s", prov_request.c_str()); + // Ignore URL provided by CdmEngine. Use ours, as configured // for test vs. production server. provisioning_server_url.assign(g_provisioning_server); UrlRequest url_request(provisioning_server_url); EXPECT_TRUE(url_request.is_connected()); url_request.PostCertRequestInQueryString(prov_request); - std::string message; - bool ok = url_request.GetResponse(&message); + std::string http_message; + bool ok = url_request.GetResponse(&http_message); EXPECT_TRUE(ok); + + LOGV("WvCdmEnginePreProvTest::Provision: http_message: \n%s\n", + http_message.c_str()); + + // extract provisioning response from received message + // Extracts signed response from JSON string, decodes base64 signed response + const std::string kMessageStart = "\"signedResponse\": \""; + const std::string kMessageEnd = "\""; + std::string base64_response; + EXPECT_TRUE (ExtractSignedMessage(http_message, kMessageStart, kMessageEnd, + &base64_response)) << + "Failed to extract signed serialized response from JSON response"; + + LOGV("WvCdmEnginePreProvTest::Provision: extracted response " + "message: \n%s\n", base64_response.c_str()); + ASSERT_EQ(NO_ERROR, - cdm_engine_->HandleProvisioningResponse(message, &cert, - &wrapped_key)); + cdm_engine_->HandleProvisioningResponse(base64_response, + &cert, &wrapped_key)); + + ASSERT_EQ(NO_ERROR, + cdm_engine_->SetServiceCertificate( + g_license_service_certificate)); } // This CryptoSession object handles Initialization and Termination diff --git a/libwvdrmengine/cdm/test/cdm_extended_duration_test.cpp b/libwvdrmengine/cdm/test/cdm_extended_duration_test.cpp index c4ec3177..1e25e915 100644 --- a/libwvdrmengine/cdm/test/cdm_extended_duration_test.cpp +++ b/libwvdrmengine/cdm/test/cdm_extended_duration_test.cpp @@ -47,7 +47,8 @@ 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::kContentProtectionUatServer; +wvcdm::ServerConfigurationId g_license_server_id = + wvcdm::kContentProtectionUatServer; // TODO(rfrias): refactor to print out the decryption test names struct SubSampleInfo { @@ -940,7 +941,9 @@ TEST_F(WvCdmExtendedDurationTest, UsageOverflowTest) { DeviceFiles handle(&file_system); EXPECT_TRUE(handle.Init(security_level)); std::vector provider_session_tokens; - EXPECT_TRUE(handle.DeleteAllUsageInfoForApp("", &provider_session_tokens)); + EXPECT_TRUE(handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(""), + &provider_session_tokens)); for (size_t i = 0; i < kMaxUsageTableSize + 100; ++i) { decryptor_.OpenSession(g_key_system, property_set, kDefaultCdmIdentifier, diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 6501f59c..a89d128b 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -66,7 +66,8 @@ 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::kContentProtectionUatServer; +wvcdm::ServerConfigurationId g_license_server_id = + wvcdm::kContentProtectionUatServer; std::string g_service_certificate; // TODO(rfrias): refactor to print out the decryption test names @@ -2378,7 +2379,9 @@ TEST_P(WvCdmUsageTest, WithClientId) { DeviceFiles handle(&file_system); EXPECT_TRUE(handle.Init(security_level)); std::vector psts; - EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(app_id, &psts)); + EXPECT_TRUE(handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(app_id), + &psts)); RenewWithClientIdTestConfiguration* config = GetParam(); std::string key_id; @@ -2496,7 +2499,9 @@ TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) { DeviceFiles handle(&file_system); EXPECT_TRUE(handle.Init(security_level)); std::vector psts; - EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(app_id, &psts)); + EXPECT_TRUE(handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(app_id), + &psts)); SubSampleInfo* data = &usage_info_sub_samples_icp[0]; decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL, @@ -2579,7 +2584,9 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) { DeviceFiles handle(&file_system); EXPECT_TRUE(handle.Init(security_level)); std::vector psts; - EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(usage_info_data->app_id, &psts)); + EXPECT_TRUE(handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(usage_info_data->app_id), + &psts)); for (size_t i = 0; i < usage_info_data->usage_info; ++i) { SubSampleInfo* data = usage_info_data->sub_sample + i; @@ -2653,7 +2660,8 @@ TEST_F(WvCdmRequestLicenseTest, UsageReleaseAllTest) { DeviceFiles handle(&file_system); EXPECT_TRUE(handle.Init(security_level)); std::vector psts; - EXPECT_TRUE(handle.DeleteAllUsageInfoForApp("", &psts)); + EXPECT_TRUE(handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(""), &psts)); for (size_t i = 0; i < N_ELEM(usage_info_sub_samples_icp); ++i) { SubSampleInfo* data = usage_info_sub_samples_icp + i; diff --git a/libwvdrmengine/mediacrypto/test/Android.mk b/libwvdrmengine/mediacrypto/test/Android.mk index 3c3ff291..caa0c61c 100644 --- a/libwvdrmengine/mediacrypto/test/Android.mk +++ b/libwvdrmengine/mediacrypto/test/Android.mk @@ -91,13 +91,13 @@ LOCAL_STATIC_LIBRARIES += libhidl_utils LOCAL_SHARED_LIBRARIES := \ android.hardware.drm@1.0 \ - android.hidl.base@1.0 \ android.hidl.memory@1.0 \ libbinder \ libcutils \ libdl \ libhidlbase \ libhidlmemory \ + libhidltransport \ liblog \ libprotobuf-cpp-lite \ libutils \ diff --git a/libwvdrmengine/mediadrm/test/Android.mk b/libwvdrmengine/mediadrm/test/Android.mk index 75cefba8..33a969f9 100644 --- a/libwvdrmengine/mediadrm/test/Android.mk +++ b/libwvdrmengine/mediadrm/test/Android.mk @@ -92,13 +92,13 @@ LOCAL_STATIC_LIBRARIES += libhidl_utils LOCAL_SHARED_LIBRARIES := \ android.hardware.drm@1.0 \ - android.hidl.base@1.0 \ android.hidl.memory@1.0 \ libbinder \ libcutils \ libdl \ libhidlbase \ libhidlmemory \ + libhidltransport \ liblog \ libprotobuf-cpp-lite \ libutils \ diff --git a/libwvdrmengine/oemcrypto/mock/src/oem_cert.cpp b/libwvdrmengine/oemcrypto/mock/src/oem_cert.cpp index ecd4584e..3df15d68 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oem_cert.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oem_cert.cpp @@ -377,390 +377,10 @@ extern const uint8_t kOEMPublicCert_Prod[] = { }; extern const size_t kOEMPublicCertSize_Prod = 2555; -extern const uint32_t kOEMSystemId_Dev = 2001093; +// Refer to the following in main modules. +// This level of indirection is present so new OEM Certificates can be +// added and then selected for use at compile time or run time. -extern const uint8_t kOEMPrivateKey_Dev[] = { - 0x30, 0x82, 0x06, 0xfd, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x06, 0xe7, 0x30, 0x82, 0x06, 0xe3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, - 0x81, 0x00, 0xda, 0x30, 0x9c, 0xd2, 0xd9, 0xdb, 0xb7, 0x25, 0x86, 0xdc, - 0x99, 0x87, 0x91, 0x40, 0xca, 0x02, 0x76, 0xc4, 0xc6, 0x00, 0xcb, 0x60, - 0x8c, 0xb2, 0x01, 0xde, 0x9d, 0x44, 0x4c, 0x72, 0x42, 0xc2, 0xf1, 0x96, - 0x13, 0xa2, 0x15, 0xb2, 0x9c, 0x09, 0x11, 0x73, 0x96, 0x4e, 0xd3, 0xda, - 0xb4, 0xaf, 0xd5, 0x69, 0x69, 0xd9, 0xbe, 0x19, 0x5e, 0x49, 0x21, 0x01, - 0xf7, 0x31, 0xdd, 0x14, 0xea, 0x41, 0x5e, 0x81, 0xc5, 0x76, 0xff, 0x50, - 0xba, 0xa7, 0x0b, 0x81, 0x22, 0xba, 0x2b, 0x58, 0x7b, 0x5d, 0xb3, 0xaf, - 0xd1, 0xb4, 0x66, 0x8e, 0x70, 0x55, 0xd8, 0x4d, 0x47, 0xb7, 0x00, 0x2c, - 0x52, 0x46, 0x33, 0xa1, 0x5f, 0xca, 0xd8, 0xb1, 0xc5, 0x04, 0x0e, 0xb7, - 0xd8, 0x0a, 0xca, 0x7c, 0x2a, 0x11, 0x3d, 0xec, 0x7f, 0x4c, 0xea, 0xaa, - 0x8e, 0x1d, 0xef, 0x9e, 0x2b, 0x9e, 0x79, 0x09, 0x7e, 0xf4, 0xd0, 0xa3, - 0x58, 0xb5, 0x4e, 0x1c, 0xfb, 0x07, 0x17, 0xc4, 0xef, 0x30, 0xa3, 0x91, - 0xb6, 0x5f, 0xf8, 0xdb, 0x05, 0x73, 0x85, 0x9b, 0xe1, 0x16, 0xf1, 0x8e, - 0xe4, 0x9f, 0xe7, 0x54, 0xcf, 0x52, 0x84, 0xe7, 0x71, 0xe7, 0x38, 0x67, - 0x8e, 0x96, 0x59, 0x9b, 0x97, 0xa2, 0xc0, 0x01, 0xd5, 0x41, 0x36, 0xfa, - 0xc1, 0x61, 0x96, 0x6c, 0x38, 0x7d, 0xdd, 0x1c, 0x24, 0x2e, 0x57, 0x67, - 0x7c, 0x70, 0xd1, 0x8a, 0x8a, 0xe2, 0x6f, 0x66, 0xd2, 0xaa, 0x3e, 0xfa, - 0x4c, 0x4a, 0x68, 0xba, 0x86, 0x6e, 0x33, 0xfe, 0x30, 0xd2, 0xf4, 0x96, - 0x58, 0xe2, 0x35, 0x94, 0x4f, 0x11, 0xc7, 0x0a, 0x21, 0xe5, 0xd4, 0x1a, - 0x3c, 0xfd, 0x82, 0xbb, 0x34, 0x21, 0xdb, 0x2f, 0xd8, 0xd1, 0xbe, 0x38, - 0xe8, 0x47, 0x45, 0x04, 0x27, 0xb0, 0x19, 0x65, 0x6f, 0x55, 0xcd, 0x56, - 0x3a, 0xcc, 0xc1, 0xaf, 0xce, 0x59, 0x2e, 0xe6, 0x89, 0x24, 0x48, 0x94, - 0xc8, 0x73, 0x45, 0xc8, 0xe5, 0x1d, 0xe1, 0xf8, 0x7d, 0x88, 0xe5, 0x07, - 0x42, 0xb2, 0x80, 0x17, 0xf6, 0x67, 0x2a, 0x33, 0xa0, 0xca, 0x81, 0x0e, - 0xc4, 0x99, 0x93, 0x02, 0x8c, 0x90, 0x1d, 0x46, 0xad, 0x61, 0xec, 0xca, - 0xdd, 0x8e, 0x8b, 0x9f, 0x32, 0xab, 0xbf, 0xfa, 0xa6, 0x28, 0xda, 0x63, - 0xa2, 0xf0, 0x20, 0x52, 0x26, 0x06, 0x05, 0x59, 0xe1, 0x4a, 0x8d, 0x5e, - 0x6a, 0x65, 0xd8, 0x8e, 0x6e, 0x49, 0xa4, 0xa8, 0xc0, 0xba, 0x7b, 0x21, - 0x31, 0x7a, 0xd1, 0xb5, 0x46, 0x9e, 0xa5, 0x45, 0xeb, 0xdf, 0x38, 0xc4, - 0x1e, 0x10, 0xc6, 0xb6, 0x83, 0x46, 0x96, 0x63, 0xe5, 0xef, 0x7c, 0xdb, - 0x65, 0x3e, 0xec, 0x42, 0x00, 0x71, 0x78, 0x83, 0xfc, 0x73, 0x4f, 0x4e, - 0xb9, 0x01, 0x80, 0xd4, 0x7d, 0xf2, 0x72, 0x8d, 0x41, 0x7b, 0xee, 0xb5, - 0xca, 0xf7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x80, 0x2b, - 0xeb, 0x6d, 0x25, 0xe4, 0x44, 0x9d, 0xf1, 0x27, 0xdc, 0x6f, 0xeb, 0x22, - 0x09, 0xf0, 0x9f, 0xde, 0x58, 0x6d, 0xa2, 0xeb, 0x4d, 0x5c, 0x04, 0xd8, - 0xeb, 0x7e, 0xac, 0xa8, 0xd6, 0xb7, 0x29, 0x96, 0x87, 0xa7, 0x1c, 0x11, - 0x52, 0x0a, 0xa6, 0xa8, 0xa4, 0xa3, 0xb4, 0xea, 0x60, 0x33, 0xce, 0xd1, - 0x1e, 0x8e, 0xf8, 0x0d, 0x93, 0xfd, 0xae, 0xaa, 0xbe, 0x42, 0x8b, 0xfe, - 0xfc, 0x9e, 0xca, 0xd9, 0xc3, 0x35, 0x84, 0x66, 0x90, 0x51, 0x82, 0x1e, - 0x86, 0xb7, 0xfe, 0xd1, 0x8a, 0xd6, 0x0a, 0x5e, 0x89, 0x1d, 0xa5, 0x3a, - 0x9f, 0xa1, 0x6d, 0x26, 0x45, 0x28, 0x12, 0x66, 0x2e, 0x85, 0xc1, 0x2b, - 0xd3, 0x67, 0xfc, 0xe4, 0xf1, 0xa3, 0xbe, 0xd5, 0x57, 0x9c, 0x5d, 0x4f, - 0xb4, 0xfe, 0xa2, 0xc9, 0xdc, 0x39, 0x23, 0xba, 0x78, 0xea, 0x72, 0x8c, - 0x31, 0x42, 0x86, 0x7b, 0xc6, 0xb5, 0x8f, 0x82, 0x0f, 0xdf, 0x63, 0x5f, - 0x7d, 0xe5, 0xe9, 0xdf, 0x96, 0xfc, 0xae, 0xc5, 0xbe, 0x26, 0xff, 0xda, - 0x8f, 0xfb, 0xe0, 0xed, 0x1c, 0x1b, 0x8b, 0x0a, 0xc4, 0xc0, 0xb0, 0x8f, - 0x58, 0x3b, 0x03, 0x59, 0x4d, 0x5d, 0x58, 0x35, 0xba, 0x62, 0xb1, 0x51, - 0x08, 0x48, 0xd5, 0xb1, 0xe0, 0xac, 0x94, 0x9c, 0x04, 0x8d, 0xb8, 0x9f, - 0x16, 0xd9, 0xa8, 0x3c, 0x41, 0xd5, 0xe6, 0x9e, 0x21, 0x6e, 0xa2, 0xc7, - 0xdb, 0x2a, 0xeb, 0x2d, 0x54, 0xbd, 0xa0, 0x16, 0x90, 0xa1, 0x73, 0x15, - 0xf1, 0x88, 0xb0, 0xa0, 0xa0, 0x5d, 0xf3, 0x1a, 0x7d, 0x60, 0x6c, 0x59, - 0xcd, 0x1a, 0xb6, 0x6a, 0x5b, 0xca, 0x4a, 0x86, 0x35, 0xc4, 0x9d, 0xfc, - 0x27, 0x38, 0x8c, 0x53, 0x69, 0x8e, 0xba, 0x4b, 0x1f, 0x4a, 0x31, 0x70, - 0x41, 0xc5, 0x7d, 0x35, 0xf0, 0xe6, 0xc8, 0x70, 0xc9, 0x83, 0x8e, 0x05, - 0xbe, 0x97, 0x82, 0xb2, 0x59, 0xfc, 0xb4, 0x63, 0x98, 0xa3, 0x3b, 0x17, - 0xdc, 0xe7, 0xa4, 0x30, 0xce, 0xd1, 0x76, 0xc7, 0x42, 0xce, 0x92, 0x1b, - 0xdd, 0xde, 0xa1, 0xdd, 0xeb, 0x88, 0xb4, 0xd0, 0x90, 0xb6, 0xe9, 0x91, - 0x3b, 0xb5, 0x2a, 0x8c, 0xad, 0x48, 0x15, 0xd3, 0x69, 0x46, 0xfe, 0x43, - 0x11, 0xd9, 0x5b, 0x56, 0x66, 0xb1, 0x5f, 0xf4, 0x0f, 0x68, 0xb5, 0x55, - 0x17, 0x5c, 0x41, 0xd7, 0xdc, 0x2d, 0xd2, 0x6a, 0x9c, 0xd8, 0xd0, 0x45, - 0xff, 0xc7, 0x30, 0x81, 0xc8, 0x57, 0xe6, 0x6e, 0x12, 0xd7, 0xa1, 0x6f, - 0x51, 0x9d, 0x0b, 0x7c, 0x00, 0xbd, 0xa7, 0xc5, 0x7e, 0x58, 0x9b, 0x6a, - 0xf3, 0xe6, 0x17, 0x43, 0x89, 0x04, 0xa0, 0xf5, 0x61, 0xa8, 0xf9, 0xff, - 0x5f, 0x9f, 0xa5, 0x4b, 0xa7, 0xdb, 0x60, 0xea, 0xb9, 0x80, 0x5d, 0x1c, - 0x58, 0x2a, 0x60, 0x96, 0x6a, 0xba, 0xc7, 0xf3, 0xfc, 0x13, 0x41, 0x02, - 0x81, 0xc1, 0x00, 0xf3, 0x45, 0x5f, 0x13, 0x38, 0xa4, 0x51, 0x17, 0x3a, - 0xf9, 0x4d, 0x9f, 0x71, 0x98, 0x26, 0x27, 0xfb, 0x81, 0xe6, 0x49, 0x88, - 0x8d, 0x2f, 0xc6, 0x13, 0x41, 0x08, 0xef, 0x8b, 0x7d, 0xec, 0x62, 0x73, - 0x02, 0x73, 0xa8, 0x98, 0x77, 0x4c, 0x46, 0x7c, 0x62, 0xec, 0x9e, 0xa7, - 0xab, 0x19, 0x21, 0x8c, 0x2f, 0xad, 0xb8, 0x17, 0x3b, 0x83, 0x9b, 0x32, - 0xb8, 0xf4, 0x49, 0x70, 0x47, 0x3c, 0x2a, 0xb0, 0x8f, 0xdc, 0x9a, 0xa4, - 0x3e, 0xef, 0x3e, 0xce, 0x43, 0x7e, 0x28, 0xdd, 0x9e, 0x46, 0xf0, 0x28, - 0x86, 0xbf, 0xdd, 0x2f, 0xf7, 0xc6, 0x1c, 0xa0, 0xec, 0x14, 0x54, 0x23, - 0xce, 0x32, 0xd5, 0xc5, 0x77, 0x7f, 0xf0, 0x8c, 0x8b, 0x39, 0x86, 0x9d, - 0x18, 0xb6, 0x2c, 0xc9, 0x65, 0x20, 0xcf, 0x58, 0xeb, 0xe7, 0x21, 0xc3, - 0x49, 0x7e, 0x1e, 0xa7, 0xe0, 0x8a, 0xe4, 0x1f, 0x77, 0x8c, 0x25, 0xfb, - 0x97, 0x05, 0x6b, 0x10, 0xa5, 0xff, 0x00, 0xb9, 0x5b, 0xf4, 0x6f, 0x06, - 0x50, 0xe7, 0xdf, 0xa2, 0x22, 0x71, 0x9f, 0x8c, 0x32, 0x04, 0x68, 0x5e, - 0x89, 0x04, 0x53, 0x99, 0x57, 0xf6, 0x70, 0x7a, 0x7f, 0x4d, 0xfe, 0xd0, - 0xf9, 0xc2, 0x52, 0xb3, 0x0e, 0x81, 0x95, 0xcb, 0xb6, 0x7d, 0x89, 0x46, - 0x04, 0x50, 0xce, 0xf1, 0x3e, 0xb8, 0x75, 0x57, 0xde, 0xa0, 0xf6, 0x5f, - 0xf1, 0x19, 0xeb, 0x02, 0x81, 0xc1, 0x00, 0xe5, 0x9b, 0x47, 0x51, 0xed, - 0x05, 0x0c, 0x94, 0xa4, 0x5b, 0xd0, 0x2d, 0x62, 0x2a, 0x02, 0x76, 0xc9, - 0x77, 0x32, 0x18, 0x8c, 0xc8, 0x85, 0x9a, 0x4e, 0x3b, 0x47, 0x4e, 0xb0, - 0x8f, 0x61, 0x03, 0xc1, 0xf5, 0xe3, 0x57, 0x12, 0xd6, 0xad, 0x42, 0xaf, - 0xe1, 0x37, 0xe2, 0x7a, 0xcf, 0xd7, 0x34, 0xbb, 0xb7, 0xa4, 0xfd, 0xd7, - 0x5a, 0x44, 0x09, 0xa1, 0xdf, 0x7b, 0x26, 0x74, 0xb7, 0x05, 0xf8, 0x46, - 0xd3, 0x33, 0x03, 0x09, 0xc4, 0xb7, 0x71, 0xba, 0x96, 0x55, 0x64, 0xa1, - 0x3f, 0x4f, 0xcb, 0x05, 0x97, 0x87, 0x8c, 0xeb, 0xd6, 0x66, 0x02, 0xe1, - 0x32, 0xed, 0x7b, 0xed, 0xad, 0xb7, 0x99, 0xba, 0x80, 0x36, 0x92, 0xcc, - 0xa9, 0x0a, 0x8a, 0x34, 0x8b, 0x9b, 0x34, 0x3b, 0x50, 0xf5, 0xd0, 0xeb, - 0x49, 0x96, 0xb0, 0xab, 0x10, 0x45, 0x53, 0xeb, 0x63, 0xc3, 0x51, 0x52, - 0xbf, 0xe9, 0xbd, 0x7a, 0x59, 0xe1, 0x3b, 0x62, 0xd7, 0x91, 0x47, 0x31, - 0x4c, 0x9c, 0x31, 0x42, 0x55, 0x88, 0x65, 0xcd, 0x3e, 0x72, 0xf0, 0x04, - 0xd0, 0x57, 0x13, 0x6f, 0x25, 0xde, 0x66, 0xa2, 0xe7, 0x4d, 0x1f, 0xd1, - 0xae, 0x19, 0x60, 0x68, 0xc3, 0xb4, 0xb4, 0x7b, 0xc5, 0x22, 0x8b, 0xf8, - 0x4e, 0xad, 0xc8, 0x8a, 0x40, 0xb8, 0xcc, 0x01, 0xe6, 0x0e, 0xe7, 0xbe, - 0x17, 0x65, 0x02, 0xb5, 0xa8, 0x24, 0x25, 0x02, 0x81, 0xc0, 0x3e, 0x4f, - 0x1c, 0x64, 0xfd, 0xf3, 0x08, 0x5a, 0x1c, 0xde, 0xd2, 0x04, 0xee, 0xc1, - 0x7b, 0xb4, 0x6d, 0xf4, 0xfd, 0x99, 0x04, 0x02, 0xb5, 0xa3, 0xd4, 0x36, - 0xaa, 0x25, 0x40, 0xe3, 0x45, 0xf2, 0x89, 0x66, 0xad, 0x5d, 0x17, 0x80, - 0x26, 0xe7, 0x3e, 0xe0, 0xcf, 0x9e, 0x6b, 0x6f, 0xa5, 0x86, 0x34, 0x33, - 0xda, 0x18, 0xf6, 0xca, 0x65, 0x91, 0x10, 0xd2, 0xd2, 0xaf, 0x24, 0xb4, - 0xfa, 0x32, 0x2c, 0xfb, 0x0c, 0x14, 0x07, 0xd1, 0x9e, 0xd1, 0xc5, 0x5f, - 0x00, 0x27, 0x53, 0x6c, 0x40, 0xdb, 0x2e, 0x66, 0x25, 0x2a, 0x70, 0x28, - 0xd4, 0x73, 0x6c, 0xbc, 0x4b, 0x10, 0xaa, 0x03, 0x1c, 0x7e, 0x28, 0x8f, - 0xcd, 0x13, 0x3d, 0xcc, 0x43, 0x35, 0xb9, 0x73, 0x24, 0xe6, 0x1f, 0xc7, - 0x69, 0x39, 0xf2, 0x9a, 0xa9, 0x9e, 0xba, 0x38, 0x4e, 0xb7, 0x67, 0x64, - 0x59, 0xee, 0xc8, 0x28, 0x84, 0x9b, 0x0d, 0xef, 0xc6, 0x91, 0x7f, 0xb8, - 0x24, 0xb2, 0x78, 0xc7, 0x96, 0xba, 0x01, 0x32, 0x23, 0xd1, 0xe1, 0xe3, - 0x54, 0x9a, 0xfa, 0xfb, 0xac, 0xa9, 0x56, 0xdd, 0x5d, 0x60, 0x54, 0x3c, - 0x75, 0x80, 0xa5, 0xbf, 0x89, 0xa8, 0xa4, 0xb9, 0xf4, 0x0d, 0xde, 0x92, - 0xee, 0x9a, 0x01, 0x8d, 0x82, 0x65, 0xf0, 0xab, 0x16, 0x4f, 0x8a, 0xf6, - 0xf7, 0xa4, 0x06, 0x97, 0x9d, 0x3e, 0xbd, 0xa0, 0x31, 0x75, 0x02, 0x81, - 0xc0, 0x1a, 0xe3, 0x9b, 0x6f, 0x99, 0xbd, 0x5c, 0xa2, 0xcf, 0xb8, 0xbc, - 0xe1, 0x83, 0xbc, 0x7d, 0xbb, 0x61, 0x8e, 0xa6, 0xfc, 0x3f, 0x08, 0x80, - 0xb4, 0xf8, 0x72, 0x72, 0xc0, 0x61, 0x66, 0xf9, 0x2a, 0x92, 0x7d, 0x74, - 0x59, 0x4f, 0x28, 0x7a, 0xf3, 0xf3, 0x5b, 0x01, 0xcb, 0x71, 0x2c, 0x83, - 0xfc, 0x75, 0xfb, 0x64, 0xc4, 0x21, 0x83, 0x3d, 0xb2, 0x8f, 0x15, 0x77, - 0xfb, 0xa1, 0xf1, 0x89, 0x2e, 0x71, 0x44, 0xec, 0x95, 0x6f, 0x80, 0x6d, - 0x27, 0x51, 0x7d, 0xa7, 0x94, 0x78, 0x59, 0xcc, 0xc3, 0x6e, 0xed, 0x36, - 0xff, 0xa6, 0xe2, 0xdd, 0xe1, 0x7a, 0x74, 0x17, 0x61, 0xcb, 0x0c, 0xec, - 0x12, 0x81, 0xc7, 0xe0, 0x1c, 0x43, 0x01, 0x8c, 0xed, 0x70, 0x87, 0xe4, - 0xee, 0x32, 0x00, 0x22, 0x39, 0x8c, 0x44, 0x7a, 0xf4, 0x47, 0xa4, 0x49, - 0x2a, 0x31, 0xc7, 0xe6, 0x28, 0xd0, 0xf3, 0x0e, 0xb1, 0x94, 0xf1, 0x8f, - 0xb1, 0xff, 0xba, 0x55, 0x16, 0x2c, 0x4c, 0xd7, 0x81, 0xe1, 0x4d, 0xd9, - 0x02, 0x6b, 0x0d, 0xe4, 0x31, 0xfd, 0xae, 0x54, 0x74, 0x3f, 0x31, 0x05, - 0x21, 0xa9, 0xf4, 0x42, 0x90, 0xf6, 0x62, 0x58, 0x30, 0x75, 0x34, 0x6e, - 0x26, 0x30, 0xd4, 0x7e, 0x5e, 0x3b, 0xff, 0x22, 0xd4, 0xf8, 0x73, 0xe9, - 0xf0, 0x62, 0x4c, 0x89, 0xf4, 0x53, 0xcb, 0xb3, 0x95, 0xa4, 0xa6, 0x83, - 0x4d, 0x02, 0x81, 0xc1, 0x00, 0xf0, 0x0f, 0xf2, 0x41, 0x51, 0x00, 0xb8, - 0x7d, 0x23, 0xfd, 0xeb, 0xb4, 0xe2, 0x18, 0x20, 0x09, 0x37, 0x77, 0x44, - 0xe3, 0x4b, 0x88, 0xac, 0xab, 0x39, 0x28, 0x9b, 0x50, 0x57, 0xc8, 0x16, - 0xf3, 0xeb, 0x5f, 0x7f, 0xc5, 0x3a, 0x53, 0x70, 0x11, 0x37, 0x6c, 0x50, - 0xc3, 0xc4, 0x13, 0x26, 0x56, 0x31, 0x63, 0x7b, 0x34, 0xd2, 0xde, 0x40, - 0x15, 0xaa, 0xf8, 0x27, 0x5b, 0x79, 0x5b, 0xeb, 0x2c, 0xb0, 0x6d, 0x50, - 0x84, 0x86, 0x75, 0xff, 0x4a, 0x8c, 0x19, 0xa4, 0x1a, 0x54, 0xca, 0x7c, - 0xc7, 0xe5, 0x86, 0xc0, 0xd7, 0xf7, 0xf8, 0xfb, 0x01, 0xf3, 0x30, 0x10, - 0xd6, 0x74, 0x24, 0x64, 0x9f, 0x95, 0x94, 0x25, 0xc9, 0x2c, 0x04, 0x19, - 0x84, 0xea, 0xcc, 0xe9, 0x3e, 0x10, 0x2f, 0xd9, 0x33, 0xf9, 0x4d, 0x08, - 0x55, 0x98, 0xe6, 0x39, 0xfe, 0x27, 0x11, 0x07, 0xb3, 0xb8, 0x66, 0x88, - 0x0a, 0xde, 0x1f, 0x2c, 0x90, 0xbf, 0xc8, 0x44, 0xac, 0xc4, 0xbe, 0x30, - 0x82, 0xa7, 0x5e, 0x11, 0xa0, 0xe7, 0xbd, 0x21, 0xa9, 0x18, 0xf4, 0xe1, - 0x9f, 0x4d, 0x9f, 0x43, 0xd5, 0x2b, 0xe5, 0xdd, 0x96, 0xa4, 0x5c, 0xdc, - 0x28, 0x9b, 0x9e, 0xd9, 0x0d, 0x04, 0xb6, 0x82, 0xe3, 0x75, 0xd1, 0xbb, - 0x4d, 0x2b, 0x49, 0x21, 0xb7, 0x8a, 0x7b, 0x47, 0x81, 0x57, 0x5a, 0x1e, - 0x09, 0xdc, 0xe8, 0xe5, 0x29 -}; -extern const size_t kOEMPrivateKeySize_Dev = 1793; - -extern const uint8_t kOEMPublicCert_Dev[] = { - 0x30, 0x82, 0x09, 0xff, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x07, 0x02, 0xa0, 0x82, 0x09, 0xf0, 0x30, 0x82, 0x09, 0xec, 0x02, - 0x01, 0x01, 0x31, 0x00, 0x30, 0x0f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x02, 0x04, 0x00, 0xa0, 0x82, 0x09, - 0xd0, 0x30, 0x82, 0x04, 0x20, 0x30, 0x82, 0x03, 0x08, 0xa0, 0x03, 0x02, - 0x01, 0x02, 0x02, 0x10, 0x72, 0xa8, 0x0e, 0x1d, 0x3e, 0x4c, 0xec, 0x0c, - 0x57, 0xd8, 0xae, 0xf1, 0xe9, 0x43, 0xda, 0x2b, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, - 0x81, 0x8e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, - 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x4b, - 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x57, - 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, 0x33, 0x30, 0x31, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x20, 0x4f, 0x45, 0x4d, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x3b, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x20, 0x69, 0x64, 0x3a, 0x20, 0x32, 0x30, 0x30, 0x31, 0x30, 0x39, 0x33, - 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x37, 0x31, 0x31, - 0x30, 0x38, 0x30, 0x36, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x33, 0x31, - 0x35, 0x31, 0x31, 0x30, 0x38, 0x30, 0x36, 0x5a, 0x30, 0x70, 0x31, 0x15, - 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x32, 0x30, 0x30, - 0x31, 0x30, 0x39, 0x33, 0x2d, 0x6c, 0x65, 0x61, 0x66, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, - 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, - 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, - 0x6e, 0x65, 0x30, 0x82, 0x01, 0xa2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x8f, 0x00, 0x30, 0x82, 0x01, 0x8a, 0x02, 0x82, 0x01, 0x81, 0x00, 0xda, - 0x30, 0x9c, 0xd2, 0xd9, 0xdb, 0xb7, 0x25, 0x86, 0xdc, 0x99, 0x87, 0x91, - 0x40, 0xca, 0x02, 0x76, 0xc4, 0xc6, 0x00, 0xcb, 0x60, 0x8c, 0xb2, 0x01, - 0xde, 0x9d, 0x44, 0x4c, 0x72, 0x42, 0xc2, 0xf1, 0x96, 0x13, 0xa2, 0x15, - 0xb2, 0x9c, 0x09, 0x11, 0x73, 0x96, 0x4e, 0xd3, 0xda, 0xb4, 0xaf, 0xd5, - 0x69, 0x69, 0xd9, 0xbe, 0x19, 0x5e, 0x49, 0x21, 0x01, 0xf7, 0x31, 0xdd, - 0x14, 0xea, 0x41, 0x5e, 0x81, 0xc5, 0x76, 0xff, 0x50, 0xba, 0xa7, 0x0b, - 0x81, 0x22, 0xba, 0x2b, 0x58, 0x7b, 0x5d, 0xb3, 0xaf, 0xd1, 0xb4, 0x66, - 0x8e, 0x70, 0x55, 0xd8, 0x4d, 0x47, 0xb7, 0x00, 0x2c, 0x52, 0x46, 0x33, - 0xa1, 0x5f, 0xca, 0xd8, 0xb1, 0xc5, 0x04, 0x0e, 0xb7, 0xd8, 0x0a, 0xca, - 0x7c, 0x2a, 0x11, 0x3d, 0xec, 0x7f, 0x4c, 0xea, 0xaa, 0x8e, 0x1d, 0xef, - 0x9e, 0x2b, 0x9e, 0x79, 0x09, 0x7e, 0xf4, 0xd0, 0xa3, 0x58, 0xb5, 0x4e, - 0x1c, 0xfb, 0x07, 0x17, 0xc4, 0xef, 0x30, 0xa3, 0x91, 0xb6, 0x5f, 0xf8, - 0xdb, 0x05, 0x73, 0x85, 0x9b, 0xe1, 0x16, 0xf1, 0x8e, 0xe4, 0x9f, 0xe7, - 0x54, 0xcf, 0x52, 0x84, 0xe7, 0x71, 0xe7, 0x38, 0x67, 0x8e, 0x96, 0x59, - 0x9b, 0x97, 0xa2, 0xc0, 0x01, 0xd5, 0x41, 0x36, 0xfa, 0xc1, 0x61, 0x96, - 0x6c, 0x38, 0x7d, 0xdd, 0x1c, 0x24, 0x2e, 0x57, 0x67, 0x7c, 0x70, 0xd1, - 0x8a, 0x8a, 0xe2, 0x6f, 0x66, 0xd2, 0xaa, 0x3e, 0xfa, 0x4c, 0x4a, 0x68, - 0xba, 0x86, 0x6e, 0x33, 0xfe, 0x30, 0xd2, 0xf4, 0x96, 0x58, 0xe2, 0x35, - 0x94, 0x4f, 0x11, 0xc7, 0x0a, 0x21, 0xe5, 0xd4, 0x1a, 0x3c, 0xfd, 0x82, - 0xbb, 0x34, 0x21, 0xdb, 0x2f, 0xd8, 0xd1, 0xbe, 0x38, 0xe8, 0x47, 0x45, - 0x04, 0x27, 0xb0, 0x19, 0x65, 0x6f, 0x55, 0xcd, 0x56, 0x3a, 0xcc, 0xc1, - 0xaf, 0xce, 0x59, 0x2e, 0xe6, 0x89, 0x24, 0x48, 0x94, 0xc8, 0x73, 0x45, - 0xc8, 0xe5, 0x1d, 0xe1, 0xf8, 0x7d, 0x88, 0xe5, 0x07, 0x42, 0xb2, 0x80, - 0x17, 0xf6, 0x67, 0x2a, 0x33, 0xa0, 0xca, 0x81, 0x0e, 0xc4, 0x99, 0x93, - 0x02, 0x8c, 0x90, 0x1d, 0x46, 0xad, 0x61, 0xec, 0xca, 0xdd, 0x8e, 0x8b, - 0x9f, 0x32, 0xab, 0xbf, 0xfa, 0xa6, 0x28, 0xda, 0x63, 0xa2, 0xf0, 0x20, - 0x52, 0x26, 0x06, 0x05, 0x59, 0xe1, 0x4a, 0x8d, 0x5e, 0x6a, 0x65, 0xd8, - 0x8e, 0x6e, 0x49, 0xa4, 0xa8, 0xc0, 0xba, 0x7b, 0x21, 0x31, 0x7a, 0xd1, - 0xb5, 0x46, 0x9e, 0xa5, 0x45, 0xeb, 0xdf, 0x38, 0xc4, 0x1e, 0x10, 0xc6, - 0xb6, 0x83, 0x46, 0x96, 0x63, 0xe5, 0xef, 0x7c, 0xdb, 0x65, 0x3e, 0xec, - 0x42, 0x00, 0x71, 0x78, 0x83, 0xfc, 0x73, 0x4f, 0x4e, 0xb9, 0x01, 0x80, - 0xd4, 0x7d, 0xf2, 0x72, 0x8d, 0x41, 0x7b, 0xee, 0xb5, 0xca, 0xf7, 0x02, - 0x03, 0x01, 0x00, 0x01, 0xa3, 0x17, 0x30, 0x15, 0x30, 0x13, 0x06, 0x0a, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x04, 0x01, 0x01, 0x04, 0x05, - 0x02, 0x03, 0x1e, 0x88, 0xc5, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, - 0x00, 0x17, 0x78, 0x3e, 0x21, 0x3a, 0x55, 0x67, 0xdc, 0xa6, 0x41, 0x46, - 0xcd, 0x41, 0x8f, 0x4d, 0x0c, 0x5f, 0xaa, 0x4c, 0x6d, 0xcc, 0xa1, 0xed, - 0x69, 0x9a, 0x59, 0xa0, 0xc1, 0x10, 0x9e, 0x96, 0x2b, 0x2f, 0x36, 0xfb, - 0x82, 0xc9, 0x5f, 0x71, 0x76, 0x00, 0x38, 0x8f, 0x32, 0xed, 0xec, 0x41, - 0x4a, 0x3b, 0x4e, 0x3b, 0x2f, 0xf9, 0x1e, 0x04, 0xdc, 0xc0, 0x14, 0x55, - 0xec, 0xdb, 0xba, 0x50, 0x6f, 0x0e, 0xc1, 0xec, 0xde, 0x5e, 0xf4, 0xa0, - 0x58, 0x9e, 0x41, 0x72, 0xbc, 0xb2, 0x1f, 0xb5, 0x7e, 0xc0, 0xa8, 0xb2, - 0xf4, 0xe5, 0xe6, 0x67, 0x99, 0x6b, 0x90, 0xbe, 0xd8, 0x14, 0x7a, 0x9a, - 0xbf, 0x7d, 0x3d, 0xdf, 0xfb, 0xb3, 0x88, 0x3e, 0x62, 0x1f, 0xef, 0xd0, - 0xc7, 0xb3, 0xfe, 0xde, 0x4e, 0x85, 0x15, 0xca, 0xaf, 0x39, 0xc8, 0x5c, - 0x47, 0x54, 0x48, 0x38, 0x97, 0x6c, 0x8c, 0x98, 0x55, 0x22, 0x43, 0x45, - 0xf9, 0xb5, 0x6c, 0x84, 0x32, 0xcb, 0x01, 0x1c, 0x3e, 0x94, 0xb1, 0x57, - 0x47, 0x8b, 0xcd, 0x26, 0x78, 0xa2, 0x5f, 0x88, 0x24, 0xb3, 0x2b, 0xb4, - 0x4d, 0x04, 0xb2, 0xbc, 0x84, 0x3e, 0x95, 0x41, 0xd7, 0x6a, 0x0d, 0x11, - 0x26, 0x96, 0x99, 0x14, 0xd8, 0x2c, 0x9a, 0xdb, 0x92, 0x95, 0xe5, 0x92, - 0x07, 0x55, 0xf6, 0x1b, 0x8c, 0x55, 0x87, 0x58, 0xe0, 0xd1, 0x39, 0xf3, - 0x91, 0x41, 0x32, 0x83, 0x0d, 0x06, 0x97, 0x28, 0x7d, 0x3b, 0x4d, 0x8d, - 0x26, 0xb4, 0x8c, 0x9b, 0x0a, 0xd2, 0x09, 0x8d, 0xd2, 0xa9, 0xbc, 0x54, - 0xad, 0xb4, 0x7a, 0x6c, 0xa4, 0xd4, 0x26, 0xea, 0xc7, 0xf1, 0x56, 0x9e, - 0xd6, 0xe0, 0xae, 0xc9, 0x40, 0x6f, 0x22, 0x23, 0x36, 0xaa, 0xb4, 0x01, - 0x65, 0xc6, 0x22, 0x65, 0x4e, 0x07, 0xf0, 0xd6, 0xe6, 0xb4, 0xa1, 0xb3, - 0xd6, 0x69, 0xeb, 0xd9, 0x26, 0x30, 0x82, 0x05, 0xa8, 0x30, 0x82, 0x03, - 0x90, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0xe5, 0xc7, 0xfc, - 0x08, 0x78, 0xc3, 0x6d, 0x1d, 0xec, 0xff, 0x0b, 0xe7, 0xb2, 0xca, 0xb1, - 0x89, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x0b, 0x05, 0x00, 0x30, 0x7d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, - 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, - 0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, - 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x77, 0x69, - 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, - 0x65, 0x6d, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x30, - 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x37, 0x30, 0x30, 0x35, - 0x37, 0x32, 0x34, 0x5a, 0x17, 0x0d, 0x32, 0x37, 0x30, 0x33, 0x31, 0x35, - 0x30, 0x30, 0x35, 0x37, 0x32, 0x34, 0x5a, 0x30, 0x81, 0x8e, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, - 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, - 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65, 0x76, - 0x69, 0x6e, 0x65, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x0c, 0x2a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x4f, 0x45, 0x4d, - 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x3b, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x69, 0x64, 0x3a, - 0x20, 0x32, 0x30, 0x30, 0x31, 0x30, 0x39, 0x33, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0x45, 0x13, 0xf2, 0xb2, 0xcb, 0x4b, - 0x0f, 0xb4, 0x44, 0x25, 0x9c, 0x8a, 0x68, 0x54, 0xd5, 0x45, 0x1e, 0x15, - 0x89, 0x5b, 0xb8, 0xce, 0xda, 0x5a, 0x42, 0xe6, 0x9a, 0x8c, 0xc1, 0xcb, - 0xe8, 0xc5, 0xf5, 0x8f, 0x49, 0x0e, 0x02, 0xef, 0x5e, 0x97, 0x1a, 0x91, - 0xa4, 0x94, 0xc3, 0x50, 0x13, 0xe5, 0x13, 0xb7, 0x7f, 0x26, 0x53, 0x19, - 0xb0, 0x37, 0xa5, 0xef, 0xe6, 0x2a, 0x39, 0xdc, 0x93, 0x37, 0xe2, 0x3d, - 0x7f, 0xcb, 0x4b, 0x93, 0xa2, 0xc3, 0x69, 0x78, 0xc9, 0x01, 0xfa, 0x68, - 0x3b, 0xe0, 0xe2, 0x22, 0x6c, 0xeb, 0xe4, 0x8a, 0xa8, 0x3e, 0xf5, 0x20, - 0x82, 0xa8, 0x62, 0x68, 0x59, 0x78, 0x24, 0xde, 0xef, 0x47, 0x43, 0xb1, - 0x6c, 0x38, 0x29, 0xd3, 0x69, 0x3f, 0xae, 0x35, 0x57, 0x75, 0x80, 0xc9, - 0x21, 0xe7, 0x01, 0xb9, 0x54, 0x8b, 0x6e, 0x4e, 0x2e, 0x5a, 0x5b, 0x77, - 0xa4, 0x22, 0xc2, 0x7b, 0x95, 0xb9, 0x39, 0x2c, 0xbd, 0xc2, 0x1e, 0x02, - 0xa6, 0xb2, 0xbc, 0x0f, 0x7a, 0xcb, 0xdc, 0xbc, 0xbc, 0x90, 0x66, 0xe3, - 0xca, 0x46, 0x53, 0x3e, 0x98, 0xff, 0x2e, 0x78, 0x9f, 0xd3, 0xa1, 0x12, - 0x93, 0x66, 0x7d, 0xcc, 0x94, 0x6b, 0xec, 0x19, 0x0e, 0x20, 0x45, 0x22, - 0x57, 0x6d, 0x9e, 0xd0, 0x89, 0xf2, 0xa9, 0x34, 0xdc, 0xab, 0xa5, 0x73, - 0x47, 0x38, 0xe3, 0x7f, 0x98, 0x3a, 0x61, 0xae, 0x6c, 0x4d, 0xf2, 0x31, - 0x90, 0xcb, 0x83, 0xc1, 0xee, 0xb4, 0xf2, 0x9a, 0x28, 0x5f, 0xbb, 0x7d, - 0x89, 0xdf, 0xa2, 0x31, 0xb6, 0x1d, 0x39, 0x2b, 0x70, 0xbf, 0x1e, 0xad, - 0xe1, 0x74, 0x94, 0x1d, 0xf8, 0xc5, 0x1a, 0x8d, 0x13, 0x45, 0xf0, 0x6a, - 0x80, 0x0c, 0x5d, 0xbb, 0x46, 0x8a, 0x43, 0xd0, 0xff, 0x21, 0x39, 0x57, - 0x53, 0x5b, 0x51, 0xf8, 0xa2, 0x8f, 0x7f, 0x27, 0xc7, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x82, 0x01, 0x0f, 0x30, 0x82, 0x01, 0x0b, 0x30, 0x12, - 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, - 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, - 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x1d, - 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe8, 0xe9, 0xac, - 0x16, 0x5c, 0x5e, 0xb2, 0xe8, 0xeb, 0xff, 0x57, 0x27, 0x20, 0x08, 0x72, - 0x63, 0x9b, 0xe5, 0xb5, 0x16, 0x30, 0x81, 0xb0, 0x06, 0x03, 0x55, 0x1d, - 0x23, 0x04, 0x81, 0xa8, 0x30, 0x81, 0xa5, 0x80, 0x14, 0x7e, 0x03, 0xe5, - 0x06, 0x62, 0x3b, 0x2c, 0x21, 0xa5, 0x52, 0xa1, 0xe8, 0xee, 0x2c, 0xd2, - 0x52, 0xe4, 0xf6, 0xbb, 0x6e, 0xa1, 0x81, 0x81, 0xa4, 0x7f, 0x30, 0x7d, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, - 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x11, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, - 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, - 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x19, 0x77, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x65, 0x6d, 0x2d, 0x72, 0x6f, 0x6f, - 0x74, 0x2d, 0x64, 0x65, 0x76, 0x82, 0x09, 0x00, 0x95, 0xd7, 0xb5, 0xfc, - 0xcf, 0x8e, 0xcb, 0x51, 0x30, 0x13, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, - 0x01, 0xd6, 0x79, 0x04, 0x01, 0x01, 0x04, 0x05, 0x02, 0x03, 0x1e, 0x88, - 0xc5, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x73, 0x48, 0x8c, - 0x6f, 0x11, 0xfe, 0x4b, 0x27, 0xca, 0xdd, 0x57, 0xfe, 0xcb, 0x27, 0xca, - 0xaf, 0x1c, 0x78, 0x4c, 0x95, 0x16, 0x2a, 0x11, 0x28, 0x9e, 0x2e, 0x93, - 0xa5, 0x1f, 0x3f, 0x80, 0x8d, 0x44, 0xc6, 0xaa, 0x12, 0x25, 0x6c, 0x6c, - 0xe3, 0xa7, 0x6d, 0xa3, 0xe1, 0xf5, 0x6a, 0x69, 0xb1, 0x18, 0x89, 0x0e, - 0x61, 0x4a, 0xa5, 0x5c, 0x0b, 0xf8, 0x7d, 0x2d, 0x8e, 0xbc, 0xf4, 0x2e, - 0x61, 0xa6, 0xf9, 0x32, 0xf8, 0x47, 0x8b, 0xf5, 0x3d, 0xd9, 0xb7, 0x3b, - 0x7d, 0xc6, 0xe5, 0x14, 0x8f, 0xeb, 0x72, 0x9e, 0x2b, 0xfc, 0x12, 0xef, - 0xa1, 0x26, 0xce, 0xad, 0xd5, 0x5c, 0x74, 0x50, 0x76, 0xf4, 0xd1, 0xac, - 0xdd, 0x09, 0x37, 0xde, 0xa8, 0xcd, 0x0b, 0x35, 0x89, 0x19, 0x66, 0xce, - 0x6b, 0x79, 0x1a, 0x86, 0x12, 0x7e, 0x60, 0xb4, 0x1c, 0x86, 0x34, 0x39, - 0xe5, 0x88, 0x55, 0x2b, 0x28, 0xd1, 0x7c, 0x11, 0x23, 0xa6, 0xef, 0x24, - 0xcb, 0x3b, 0xd2, 0x07, 0xe2, 0x54, 0x88, 0x41, 0xdc, 0x16, 0x16, 0x74, - 0x8a, 0x81, 0x2b, 0x53, 0x42, 0x17, 0xef, 0x87, 0xdd, 0x27, 0x8c, 0x23, - 0xcd, 0x2d, 0x2d, 0xde, 0x9c, 0x1a, 0x0e, 0xda, 0xd2, 0xbe, 0xb0, 0x8d, - 0x9d, 0x2b, 0x46, 0x54, 0x97, 0x8d, 0x24, 0x4f, 0x3e, 0x92, 0x25, 0xf6, - 0x04, 0xb7, 0x69, 0x5d, 0x1c, 0x80, 0x0e, 0x30, 0x9b, 0x37, 0xc6, 0xc1, - 0x6b, 0x1a, 0xda, 0xfe, 0x10, 0xcd, 0x0d, 0xa7, 0x56, 0xa0, 0x31, 0x97, - 0xe6, 0xa1, 0xb5, 0x6f, 0x40, 0x1a, 0xcc, 0x01, 0x52, 0xbc, 0x72, 0xfd, - 0x0a, 0x83, 0x8a, 0x2a, 0xea, 0xad, 0xc5, 0x1e, 0x12, 0x56, 0x23, 0x52, - 0xca, 0x35, 0xdb, 0xef, 0x45, 0x8c, 0x31, 0xa3, 0x1f, 0xe2, 0xb5, 0x9c, - 0xfe, 0xb8, 0x44, 0x3a, 0x09, 0xe1, 0x9e, 0x32, 0x2f, 0x7f, 0xac, 0x70, - 0x80, 0xc4, 0xa7, 0x29, 0x02, 0xad, 0xeb, 0xbd, 0x5d, 0x92, 0xbc, 0x85, - 0x6c, 0x10, 0x9b, 0x5f, 0x07, 0xfc, 0x94, 0x4d, 0xff, 0xa6, 0x37, 0x87, - 0x9e, 0x50, 0x33, 0x66, 0x29, 0xfd, 0x51, 0x62, 0x45, 0x5c, 0x45, 0x75, - 0xcd, 0xf1, 0x9b, 0x42, 0x0d, 0xa7, 0xe9, 0x91, 0xd6, 0x7c, 0x23, 0x5b, - 0xa1, 0xe8, 0x7b, 0xaf, 0xba, 0x75, 0x13, 0x24, 0x6e, 0x12, 0xf5, 0x44, - 0x29, 0x75, 0x22, 0xdc, 0xe5, 0xfa, 0xa6, 0x25, 0xa2, 0x76, 0x45, 0xf7, - 0xf9, 0x96, 0x73, 0x22, 0xd1, 0xf1, 0xe8, 0xd5, 0xa3, 0x46, 0x7f, 0x72, - 0x2c, 0x26, 0x61, 0x68, 0x89, 0xc9, 0x0a, 0xc5, 0x20, 0x78, 0x5b, 0xaa, - 0x59, 0x8d, 0x3e, 0x26, 0x75, 0x3b, 0x12, 0xba, 0xae, 0x5a, 0x42, 0x78, - 0x3f, 0xd7, 0xb2, 0x7f, 0x49, 0x68, 0xa3, 0xc8, 0xaa, 0xdb, 0xc4, 0x41, - 0x89, 0x9a, 0x12, 0xa4, 0x1c, 0x87, 0x25, 0x5c, 0x97, 0x33, 0x92, 0xd8, - 0x5f, 0x83, 0x2d, 0x47, 0x71, 0x86, 0x91, 0xbc, 0x36, 0x95, 0xb2, 0x72, - 0x4a, 0x9c, 0x67, 0xad, 0x76, 0x26, 0xda, 0x0b, 0x68, 0x49, 0x04, 0x29, - 0x0a, 0x4a, 0xa4, 0x9a, 0x8f, 0xd9, 0xfb, 0x39, 0xdc, 0x38, 0xa1, 0xf4, - 0x00, 0x6f, 0x6f, 0x9e, 0x99, 0x03, 0x7c, 0x8c, 0xc5, 0x3f, 0xfc, 0x63, - 0x9a, 0x4e, 0xd8, 0x21, 0x05, 0xd2, 0x2d, 0x9e, 0x07, 0xdf, 0xf6, 0x20, - 0xb8, 0xe7, 0xc2, 0x40, 0x49, 0x69, 0x76, 0xf9, 0xff, 0xeb, 0xb8, 0x27, - 0x94, 0x72, 0x37, 0x63, 0x8d, 0x3a, 0x2d, 0x4f, 0x57, 0x11, 0x5f, 0x3c, - 0x62, 0xa5, 0x39, 0x4d, 0x01, 0x3f, 0x58, 0xbf, 0x59, 0xb3, 0xd9, 0xa2, - 0xd7, 0x3a, 0xdd, 0x2a, 0x65, 0x97, 0x9b, 0xa7, 0x6d, 0xc0, 0x6b, 0x4a, - 0x46, 0xfe, 0x55, 0x46, 0x27, 0x75, 0x2c, 0x0a, 0x8b, 0xc4, 0xf9, 0x1e, - 0x20, 0x5a, 0xbf, 0xf7, 0x88, 0x31, 0x00 -}; -extern const size_t kOEMPublicCertSize_Dev = 2563; - -// Refer to the following in main modules -#if defined(DEV_OEM_CERTS) -const uint32_t kOEMSystemId = kOEMSystemId_Dev; - -const uint8_t* kOEMPrivateKey = kOEMPrivateKey_Dev; -const uint8_t* kOEMPublicCert = kOEMPublicCert_Dev; - -const size_t kOEMPrivateKeySize = kOEMPrivateKeySize_Dev; -const size_t kOEMPublicCertSize = kOEMPublicCertSize_Dev; -#else const uint32_t kOEMSystemId = kOEMSystemId_Prod; const uint8_t* kOEMPrivateKey = kOEMPrivateKey_Prod; @@ -768,7 +388,5 @@ const uint8_t* kOEMPublicCert = kOEMPublicCert_Prod; const size_t kOEMPrivateKeySize = kOEMPrivateKeySize_Prod; const size_t kOEMPublicCertSize = kOEMPublicCertSize_Prod; -#endif // !defined(DEV_OEM_CERTS) - } // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp index f3e9d336..30935af9 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp @@ -3,8 +3,6 @@ // Mock implementation of OEMCrypto APIs // -#if !defined(PROVISIONING_30) - #include "oemcrypto_engine_mock.h" namespace wvoec_mock { @@ -14,5 +12,3 @@ CryptoEngine* CryptoEngine::MakeCryptoEngine(wvcdm::FileSystem* file_system) { } } // namespace wvoec_mock - -#endif // !defined(PROVISIONING_30) diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp index 3ca5aba2..7bd541db 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp @@ -6,8 +6,6 @@ // level 2 device that does not have persistant storage or a keybox. // Note: this is for illustration only. Production devices are rarely level 2. -#if defined(PROVISIONING_30) - #include "oemcrypto_engine_mock.h" #include @@ -24,8 +22,23 @@ class Prov30CryptoEngine : public CryptoEngine { bool config_local_display_only() { return true; } - bool config_supports_usage_table() { return false; } + // Returns the max HDCP version supported. + OEMCrypto_HDCP_Capability config_maximum_hdcp_capability() { + return HDCP_NO_DIGITAL_OUTPUT; + } + // Returns true if the client supports persistent storage of + // offline usage table information. + bool config_supports_usage_table() { + return false; + } + + // Returns true if the client uses a keybox as the root of trust. + bool config_supports_keybox() { + return false; + } + + // This version uses an OEM Certificate. OEMCrypto_ProvisioningMethod config_provisioning_method() { return OEMCrypto_OEMCertificate; } @@ -66,5 +79,3 @@ CryptoEngine* CryptoEngine::MakeCryptoEngine(wvcdm::FileSystem* file_system) { } } // namespace wvoec_mock - -#endif // defined(PROVISIONING_30) diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_session.cpp index 705935aa..cb26be27 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_session.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_session.cpp @@ -192,9 +192,14 @@ bool SessionContext::GenerateSignature(const uint8_t* message, return false; } - if (mac_key_client_.empty() || - mac_key_client_.size() != wvcdm::MAC_KEY_SIZE) { - LOGE("[GenerateSignature(): No MAC Key]"); + const uint8_t *mac_key = NULL; + if (mac_key_client_.size() == wvcdm::MAC_KEY_SIZE) { + // If we have a mac key, use it. + mac_key = &mac_key_client_[0]; + } else if (usage_entry_status_ == kUsageEntryLoaded) { + // If not, but we have a usage entry, use its key. + mac_key = usage_entry_->mac_key_client(); + } else { return false; } @@ -204,7 +209,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message, } unsigned int md_len = *signature_length; - if (HMAC(EVP_sha256(), &mac_key_client_[0], mac_key_client_.size(), message, + if (HMAC(EVP_sha256(), mac_key, wvcdm::MAC_KEY_SIZE, message, message_length, signature, &md_len)) { *signature_length = md_len; return true; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.h index 0afc00c9..4ec70bec 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.h @@ -69,6 +69,8 @@ class UsageTableEntry { void set_index(int32_t index) { data_.index = index; } uint32_t index() { return data_.index; } static size_t SignedEntrySize(); + const uint8_t* mac_key_server() { return data_.mac_key_server; } + const uint8_t* mac_key_client() { return data_.mac_key_client; } private: UsageTable* usage_table_; // Owner of this object. diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index 41810900..c43bc68b 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -941,6 +941,9 @@ void Session::GenerateReport(const std::string& pst, EXPECT_GE(kHardwareSecureClock, pst_report().clock_security_level()); EXPECT_EQ(pst.length(), pst_report().pst_length()); EXPECT_EQ(0, memcmp(pst.c_str(), pst_report().pst(), pst.length())); + // Also, we the session to be able to sign the release message with the + // correct mac keys from the usage table entry. + ASSERT_NO_FATAL_FAILURE(VerifyClientSignature()); } void Session::VerifyPST(const Test_PST_Report& expected) { diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index 7895d4e3..2284cea8 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -295,7 +295,8 @@ class Session { wvcdm::Unpacked_PST_Report pst_report() { return wvcdm::Unpacked_PST_Report(&pst_report_buffer_[0]); } - // Verify the PST report. + // Verify the values in the PST report. The signature should have been + // verified in GenerateReport, above. void VerifyPST(const Test_PST_Report& report); // Generate and Verify the Usage Report. If any time is greater than 10 // minutes, it is assumed to be an absolute time, and time_since will be