Merges to android Pi release (part 3)
These are a set of CLs merged from the wv cdm repo to the android repo. * Add CDM status return for decrypt blocked by HDCP. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/28062 ] New status code is kKeyUsageBlockedByPolicy. It is returned by the decrypt() call instead of kDecryptError or kNoKey. Also shuffled the CDM status returns to define the EME-aligned codes first, and added comments to highlight the differences in handling. BUG: 37540672 * Change division and mod ops to relocatables Author: Srujan Gaddam <srujzs@google.com> [ Merge of http://go/wvgerrit/28600 ] This is similar to I2dad1028acf295288cd10817a2bcff2513c053c9. We should be using the relocatable functions instead of the native division and mod operations. * Cleanup Encrypted ClientID in provisioning request Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/28083 ] b/36897239 Staging server does not support it (or the client is not constructing it properly). Leave it disabled pending investigation. * Certificate Provisioning fixes. Author: Gene Morgan <gmorgan@google.com> [ Merge of http://go/wvgerrit/28066 ] Partial fix for BUG: 37482676 Partial fix for BUG: 37481392 Update service certificates, get rid of DEV/QA root certificate. Provisioning request and response are base64 (web-safe) encoded. Response is optionally JSON-wrapped. Change ConfigTestEnv; clearer comments and a closer match to reality. BUG: 71650075 Test: Not currently passing. Will be addressed in a subsequent commit in the chain. Change-Id: I79d3c4bf1124e5e0d3e4d40baead65a8266ea874
This commit is contained in:
@@ -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<std::string>* 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<std::string>* 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<std::pair<CdmKeyMessage, CdmKeyResponse> >* 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<std::string>* usage_file_names);
|
||||
virtual bool RetrieveUsageInfo(const std::string& usage_info_file_name,
|
||||
std::vector<CdmUsageData>* 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<CdmUsageData>& 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<UsageEntryInfo>& usage_entry_info);
|
||||
const std::vector<CdmUsageEntryInfo>& usage_entry_info);
|
||||
|
||||
virtual bool RetrieveUsageTableInfo(
|
||||
CdmUsageTableHeader* usage_table_header,
|
||||
std::vector<UsageEntryInfo>* usage_entry_info);
|
||||
std::vector<CdmUsageEntryInfo>* 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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_|.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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<uint8_t> 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<uint8_t> 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<std::pair<CdmKeyMessage, CdmKeyResponse> > 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<CdmSecurityLevel>(j))) {
|
||||
std::vector<std::string> 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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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<std::string>* 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<std::pair<CdmKeyMessage, CdmKeyResponse> >* 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<CdmUsageData>& 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<CdmUsageData>* 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<std::string>* usage_info_file_names) {
|
||||
if (!initialized_) {
|
||||
LOGW("DeviceFiles::ListUsageInfoFiles: not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get list of filenames
|
||||
std::vector<std::string> 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<uint8_t>& 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<DeviceFiles::UsageEntryInfo>& usage_entry_info) {
|
||||
const std::vector<CdmUsageEntryInfo>& 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<DeviceFiles::UsageEntryInfo>* usage_entry_info) {
|
||||
std::vector<CdmUsageEntryInfo>* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<const char*>(&kRootCertForDev[0]),
|
||||
sizeof(kRootCertForDev));
|
||||
#else
|
||||
std::string root_cert_str(reinterpret_cast<const char*>(&kRootCertForProd[0]),
|
||||
sizeof(kRootCertForProd));
|
||||
#endif // !defined(QA_TEST_SERVER);
|
||||
|
||||
// Load root cert public key. Don't bother verifying it.
|
||||
SignedDrmDeviceCertificate signed_root_cert;
|
||||
|
||||
@@ -229,7 +229,7 @@ std::vector<uint8_t> 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<uint8_t> Base64SafeDecode(const std::string& b64_input) {
|
||||
if (b64_input.empty()) {
|
||||
return std::vector<uint8_t>();
|
||||
|
||||
@@ -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<uint8_t>(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<uint8_t> 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<uint8_t>(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<uint8_t> 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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,30 +6,50 @@
|
||||
#include <string>
|
||||
#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);
|
||||
|
||||
@@ -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<std::string, std::string>::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<std::pair<CdmKeyMessage, CdmKeyResponse> > 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<size_t>(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<std::string> 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<std::string> entry_data;
|
||||
std::vector<DeviceFiles::UsageEntryInfo> usage_entry_info;
|
||||
std::vector<CdmUsageEntryInfo> 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<DeviceFiles::UsageEntryInfo> usage_entry_info;
|
||||
std::string usage_table_header;
|
||||
std::vector<CdmUsageEntryInfo> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<std::string> 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,
|
||||
|
||||
@@ -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<std::string> 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<std::string> 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<std::string> 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<std::string> 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;
|
||||
|
||||
Reference in New Issue
Block a user