am 4819a26b: Fixes for query information and usage reporting
* commit '4819a26bd4ff7d9736f13e1b69611139f4a5d183': Fixes for query information and usage reporting
This commit is contained in:
@@ -49,6 +49,7 @@ adb root && adb wait-for-device remount
|
|||||||
|
|
||||||
adb push $OUT/system/bin/oemcrypto_test /system/bin
|
adb push $OUT/system/bin/oemcrypto_test /system/bin
|
||||||
adb push $OUT/system/bin/request_license_test /system/bin
|
adb push $OUT/system/bin/request_license_test /system/bin
|
||||||
|
adb push $OUT/system/bin/cdm_extended_duration_test /system/bin
|
||||||
adb push $OUT/system/bin/policy_engine_unittest /system/bin
|
adb push $OUT/system/bin/policy_engine_unittest /system/bin
|
||||||
adb push $OUT/system/bin/libwvdrmmediacrypto_test /system/bin
|
adb push $OUT/system/bin/libwvdrmmediacrypto_test /system/bin
|
||||||
adb push $OUT/system/bin/libwvdrmdrmplugin_test /system/bin
|
adb push $OUT/system/bin/libwvdrmdrmplugin_test /system/bin
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace wvcdm {
|
|||||||
|
|
||||||
class CdmClientPropertySet;
|
class CdmClientPropertySet;
|
||||||
class CryptoEngine;
|
class CryptoEngine;
|
||||||
|
class UsagePropertySet;
|
||||||
class WvCdmEventListener;
|
class WvCdmEventListener;
|
||||||
|
|
||||||
typedef std::map<CdmSessionId, CdmSession*> CdmSessionMap;
|
typedef std::map<CdmSessionId, CdmSession*> CdmSessionMap;
|
||||||
@@ -117,6 +118,8 @@ class CdmEngine {
|
|||||||
private:
|
private:
|
||||||
// private methods
|
// private methods
|
||||||
bool ValidateKeySystem(const CdmKeySystem& key_system);
|
bool ValidateKeySystem(const CdmKeySystem& key_system);
|
||||||
|
CdmResponseType GetUsageInfo(SecurityLevel requested_security_level,
|
||||||
|
CdmUsageInfo* usage_info);
|
||||||
|
|
||||||
void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
|
void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
|
||||||
|
|
||||||
@@ -132,7 +135,8 @@ class CdmEngine {
|
|||||||
|
|
||||||
// usage related variables
|
// usage related variables
|
||||||
scoped_ptr<CdmSession> usage_session_;
|
scoped_ptr<CdmSession> usage_session_;
|
||||||
int64_t last_usage_information_update_time;
|
scoped_ptr<UsagePropertySet> usage_property_set_;
|
||||||
|
int64_t last_usage_information_update_time_;
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(CdmEngine);
|
CORE_DISALLOW_COPY_AND_ASSIGN(CdmEngine);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -88,8 +88,10 @@ class CdmSession {
|
|||||||
|
|
||||||
virtual CdmResponseType UpdateUsageInformation();
|
virtual CdmResponseType UpdateUsageInformation();
|
||||||
|
|
||||||
|
virtual bool is_initial_usage_update() { return is_initial_usage_update_; }
|
||||||
virtual bool is_usage_update_needed() { return is_usage_update_needed_; }
|
virtual bool is_usage_update_needed() { return is_usage_update_needed_; }
|
||||||
virtual void reset_is_usage_update_needed() {
|
virtual void reset_usage_flags() {
|
||||||
|
is_initial_usage_update_ = false;
|
||||||
is_usage_update_needed_ = false;
|
is_usage_update_needed_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,10 +119,13 @@ class CdmSession {
|
|||||||
bool license_received_;
|
bool license_received_;
|
||||||
bool is_offline_;
|
bool is_offline_;
|
||||||
bool is_release_;
|
bool is_release_;
|
||||||
bool is_usage_update_needed_;
|
CdmSecurityLevel security_level_;
|
||||||
|
|
||||||
|
// decryption and usage flags
|
||||||
bool is_initial_decryption_;
|
bool is_initial_decryption_;
|
||||||
bool has_decrypted_recently_;
|
bool has_decrypted_recently_;
|
||||||
CdmSecurityLevel security_level_;
|
bool is_initial_usage_update_;
|
||||||
|
bool is_usage_update_needed_;
|
||||||
|
|
||||||
// information useful for offline and usage scenarios
|
// information useful for offline and usage scenarios
|
||||||
CdmKeyMessage key_request_;
|
CdmKeyMessage key_request_;
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class CryptoSession {
|
|||||||
// Media data path
|
// Media data path
|
||||||
virtual CdmResponseType Decrypt(const CdmDecryptionParameters& parameters);
|
virtual CdmResponseType Decrypt(const CdmDecryptionParameters& parameters);
|
||||||
|
|
||||||
|
// Usage related methods
|
||||||
virtual bool UsageInformationSupport(bool* has_support);
|
virtual bool UsageInformationSupport(bool* has_support);
|
||||||
virtual CdmResponseType UpdateUsageInformation();
|
virtual CdmResponseType UpdateUsageInformation();
|
||||||
virtual CdmResponseType DeactivateUsageInformation(
|
virtual CdmResponseType DeactivateUsageInformation(
|
||||||
@@ -95,6 +96,7 @@ class CryptoSession {
|
|||||||
virtual CdmResponseType ReleaseUsageInformation(
|
virtual CdmResponseType ReleaseUsageInformation(
|
||||||
const std::string& message, const std::string& signature,
|
const std::string& message, const std::string& signature,
|
||||||
const std::string& provider_session_token);
|
const std::string& provider_session_token);
|
||||||
|
virtual CdmResponseType DeleteAllUsageReports();
|
||||||
|
|
||||||
virtual bool GetHdcpCapabilities(OemCryptoHdcpVersion* current,
|
virtual bool GetHdcpCapabilities(OemCryptoHdcpVersion* current,
|
||||||
OemCryptoHdcpVersion* max);
|
OemCryptoHdcpVersion* max);
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class DeviceFiles {
|
|||||||
FRIEND_TEST(DeviceFilesUsageInfoTest, Store);
|
FRIEND_TEST(DeviceFilesUsageInfoTest, Store);
|
||||||
FRIEND_TEST(WvCdmRequestLicenseTest, UnprovisionTest);
|
FRIEND_TEST(WvCdmRequestLicenseTest, UnprovisionTest);
|
||||||
FRIEND_TEST(WvCdmRequestLicenseTest, ForceL3Test);
|
FRIEND_TEST(WvCdmRequestLicenseTest, ForceL3Test);
|
||||||
FRIEND_TEST(WvCdmUsageInfoTest, DISABLED_UsageInfo);
|
FRIEND_TEST(WvCdmUsageInfoTest, UsageInfo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scoped_ptr<File> file_;
|
scoped_ptr<File> file_;
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ class CdmLicense {
|
|||||||
const CdmKeyResponse& license_renewal_response,
|
const CdmKeyResponse& license_renewal_response,
|
||||||
int64_t playback_start_time,
|
int64_t playback_start_time,
|
||||||
int64_t last_playback_time);
|
int64_t last_playback_time);
|
||||||
virtual bool RestoreUsageLicense(const CdmKeyMessage& license_request,
|
virtual bool RestoreLicenseForRelease(const CdmKeyMessage& license_request,
|
||||||
const CdmKeyResponse& license_response);
|
const CdmKeyResponse& license_response);
|
||||||
virtual bool HasInitData() { return !stored_init_data_.empty(); }
|
virtual bool HasInitData() { return !stored_init_data_.empty(); }
|
||||||
virtual bool IsKeyLoaded(const KeyId& key_id);
|
virtual bool IsKeyLoaded(const KeyId& key_id);
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ std::string HexEncode(const uint8_t* bytes, unsigned size);
|
|||||||
std::string IntToString(int value);
|
std::string IntToString(int value);
|
||||||
std::string UintToString(unsigned int value);
|
std::string UintToString(unsigned int value);
|
||||||
int64_t htonll64(int64_t x);
|
int64_t htonll64(int64_t x);
|
||||||
|
int64_t ntohll64(int64_t x);
|
||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
|
|||||||
@@ -25,13 +25,36 @@ namespace {
|
|||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
|
||||||
|
class UsagePropertySet : public CdmClientPropertySet {
|
||||||
|
public:
|
||||||
|
UsagePropertySet() {}
|
||||||
|
virtual ~UsagePropertySet() {}
|
||||||
|
void set_security_level(SecurityLevel security_level) {
|
||||||
|
if (kLevel3 == security_level)
|
||||||
|
security_level_ = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||||
|
else
|
||||||
|
security_level_.clear();
|
||||||
|
}
|
||||||
|
virtual const std::string& security_level() const { return security_level_; }
|
||||||
|
virtual bool use_privacy_mode() const { return false; }
|
||||||
|
virtual const std::string& service_certificate() const { return empty_; }
|
||||||
|
virtual bool is_session_sharing_enabled() const { return false; }
|
||||||
|
virtual uint32_t session_sharing_id() const { return 0; }
|
||||||
|
virtual void set_session_sharing_id(uint32_t id) {
|
||||||
|
id; // noop to suppress warning
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string security_level_;
|
||||||
|
const std::string empty_;
|
||||||
|
};
|
||||||
|
|
||||||
bool CdmEngine::seeded_ = false;
|
bool CdmEngine::seeded_ = false;
|
||||||
|
|
||||||
CdmEngine::CdmEngine()
|
CdmEngine::CdmEngine()
|
||||||
: cert_provisioning_(NULL),
|
: cert_provisioning_(NULL),
|
||||||
cert_provisioning_requested_security_level_(kLevelDefault),
|
cert_provisioning_requested_security_level_(kLevelDefault),
|
||||||
usage_session_(NULL),
|
usage_session_(NULL),
|
||||||
last_usage_information_update_time(0) {
|
last_usage_information_update_time_(0) {
|
||||||
Properties::Init();
|
Properties::Init();
|
||||||
if (!seeded_) {
|
if (!seeded_) {
|
||||||
Clock clock;
|
Clock clock;
|
||||||
@@ -269,7 +292,7 @@ CdmResponseType CdmEngine::RestoreKey(
|
|||||||
LOGI("CdmEngine::RestoreKey");
|
LOGI("CdmEngine::RestoreKey");
|
||||||
|
|
||||||
if (key_set_id.empty()) {
|
if (key_set_id.empty()) {
|
||||||
LOGI("CdmEngine::RestoreKey: invalid key set id");
|
LOGE("CdmEngine::RestoreKey: invalid key set id");
|
||||||
return KEY_ERROR;
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,6 +309,9 @@ CdmResponseType CdmEngine::RestoreKey(
|
|||||||
cert_provisioning_requested_security_level_ =
|
cert_provisioning_requested_security_level_ =
|
||||||
iter->second->GetRequestedSecurityLevel();
|
iter->second->GetRequestedSecurityLevel();
|
||||||
}
|
}
|
||||||
|
if (KEY_ADDED != sts) {
|
||||||
|
LOGE("CdmEngine::RestoreKey: restore offline session error = %d", sts);
|
||||||
|
}
|
||||||
return sts;
|
return sts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,11 +565,46 @@ CdmResponseType CdmEngine::Unprovision(CdmSecurityLevel security_level) {
|
|||||||
LOGE("CdmEngine::Unprovision: unable to delete files");
|
LOGE("CdmEngine::Unprovision: unable to delete files");
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
return NO_ERROR;
|
|
||||||
|
scoped_ptr<CryptoSession> crypto_session(new CryptoSession());
|
||||||
|
CdmResponseType status = crypto_session->Open(
|
||||||
|
security_level == kSecurityLevelL3 ? kLevel3 : kLevelDefault);
|
||||||
|
if (NO_ERROR != status) {
|
||||||
|
LOGE("CdmEngine::Unprovision: error opening crypto session: %d", status);
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
status = crypto_session->DeleteAllUsageReports();
|
||||||
|
if (status != NO_ERROR) {
|
||||||
|
LOGE("CdmEngine::Unprovision: error deleteing usage reports: %d", status);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
||||||
usage_session_.reset(new CdmSession(NULL));
|
// Return a random usage report from a random security level
|
||||||
|
SecurityLevel security_level = ((rand() % 2) == 0) ? kLevelDefault : kLevel3;
|
||||||
|
CdmResponseType status = GetUsageInfo(security_level, usage_info);
|
||||||
|
|
||||||
|
if (KEY_MESSAGE == status && !usage_info->empty())
|
||||||
|
return status;
|
||||||
|
|
||||||
|
security_level = (kLevel3 == security_level) ? kLevelDefault : kLevel3;
|
||||||
|
status = GetUsageInfo(security_level, usage_info);
|
||||||
|
if (NEED_PROVISIONING == status)
|
||||||
|
return NO_ERROR; // Valid scenario that one of the security
|
||||||
|
// levels has not been provisioned
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmResponseType CdmEngine::GetUsageInfo(
|
||||||
|
SecurityLevel requested_security_level,
|
||||||
|
CdmUsageInfo* usage_info) {
|
||||||
|
if (NULL == usage_property_set_.get()) {
|
||||||
|
usage_property_set_.reset(new UsagePropertySet());
|
||||||
|
}
|
||||||
|
usage_property_set_->set_security_level(requested_security_level);
|
||||||
|
|
||||||
|
usage_session_.reset(new CdmSession(usage_property_set_.get()));
|
||||||
|
|
||||||
CdmResponseType status = usage_session_->Init();
|
CdmResponseType status = usage_session_->Init();
|
||||||
if (NO_ERROR != status) {
|
if (NO_ERROR != status) {
|
||||||
@@ -573,7 +634,7 @@ CdmResponseType CdmEngine::GetUsageInfo(CdmUsageInfo* usage_info) {
|
|||||||
|
|
||||||
uint32_t index = rand() % license_info.size();
|
uint32_t index = rand() % license_info.size();
|
||||||
status = usage_session_->RestoreUsageSession(license_info[index].first,
|
status = usage_session_->RestoreUsageSession(license_info[index].first,
|
||||||
license_info[index].second);
|
license_info[index].second);
|
||||||
if (KEY_ADDED != status) {
|
if (KEY_ADDED != status) {
|
||||||
LOGE("CdmEngine::GetUsageInfo: restore usage session (%u) error %d",
|
LOGE("CdmEngine::GetUsageInfo: restore usage session (%u) error %d",
|
||||||
index, status);
|
index, status);
|
||||||
@@ -600,6 +661,7 @@ CdmResponseType CdmEngine::ReleaseUsageInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType status = usage_session_->ReleaseKey(message);
|
CdmResponseType status = usage_session_->ReleaseKey(message);
|
||||||
|
usage_session_.reset(NULL);
|
||||||
if (NO_ERROR != status) {
|
if (NO_ERROR != status) {
|
||||||
LOGE("CdmEngine::ReleaseUsageInfo: release key error: %d", status);
|
LOGE("CdmEngine::ReleaseUsageInfo: release key error: %d", status);
|
||||||
}
|
}
|
||||||
@@ -724,29 +786,44 @@ bool CdmEngine::ValidateKeySystem(const CdmKeySystem& key_system) {
|
|||||||
void CdmEngine::OnTimerEvent() {
|
void CdmEngine::OnTimerEvent() {
|
||||||
Clock clock;
|
Clock clock;
|
||||||
uint64_t current_time = clock.GetCurrentTime();
|
uint64_t current_time = clock.GetCurrentTime();
|
||||||
bool update_usage_information = false;
|
bool usage_update_period_expired = false;
|
||||||
|
|
||||||
if (current_time - last_usage_information_update_time >
|
if (current_time - last_usage_information_update_time_ >
|
||||||
kUpdateUsageInformationPeriod) {
|
kUpdateUsageInformationPeriod) {
|
||||||
update_usage_information = true;
|
usage_update_period_expired = true;
|
||||||
last_usage_information_update_time = current_time;
|
last_usage_information_update_time_ = current_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_initial_usage_update = false;
|
||||||
|
bool is_usage_update_needed = false;
|
||||||
|
|
||||||
for (CdmSessionMap::iterator iter = sessions_.begin();
|
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||||
iter != sessions_.end(); ++iter) {
|
iter != sessions_.end(); ++iter) {
|
||||||
iter->second->OnTimerEvent(update_usage_information);
|
is_initial_usage_update = is_initial_usage_update ||
|
||||||
|
iter->second->is_initial_usage_update();
|
||||||
|
is_usage_update_needed = is_usage_update_needed ||
|
||||||
|
iter->second->is_usage_update_needed();
|
||||||
|
|
||||||
if (update_usage_information && iter->second->is_usage_update_needed()) {
|
iter->second->OnTimerEvent(usage_update_period_expired);
|
||||||
// usage is updated for all sessions so this needs to be
|
}
|
||||||
// called only once per update usage information period
|
|
||||||
CdmResponseType status = iter->second->UpdateUsageInformation();
|
if (is_usage_update_needed &&
|
||||||
if (NO_ERROR != status) {
|
(usage_update_period_expired || is_initial_usage_update)) {
|
||||||
LOGW("Update usage information failed: %d", status);
|
bool has_usage_been_updated = false;
|
||||||
} else {
|
for (CdmSessionMap::iterator iter = sessions_.begin();
|
||||||
update_usage_information = false;
|
iter != sessions_.end(); ++iter) {
|
||||||
|
iter->second->reset_usage_flags();
|
||||||
|
if (!has_usage_been_updated) {
|
||||||
|
// usage is updated for all sessions so this needs to be
|
||||||
|
// called only once per update usage information period
|
||||||
|
CdmResponseType status = iter->second->UpdateUsageInformation();
|
||||||
|
if (NO_ERROR != status) {
|
||||||
|
LOGW("Update usage information failed: %d", status);
|
||||||
|
} else {
|
||||||
|
has_usage_been_updated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iter->second->reset_is_usage_update_needed();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ void CdmSession::Create(
|
|||||||
license_received_ = false;
|
license_received_ = false;
|
||||||
is_offline_ = false;
|
is_offline_ = false;
|
||||||
is_release_ = false;
|
is_release_ = false;
|
||||||
|
is_initial_usage_update_ = true;
|
||||||
is_usage_update_needed_ = false;
|
is_usage_update_needed_ = false;
|
||||||
is_initial_decryption_ = true;
|
is_initial_decryption_ = true;
|
||||||
has_decrypted_recently_ = false;
|
has_decrypted_recently_ = false;
|
||||||
@@ -152,11 +153,18 @@ CdmResponseType CdmSession::RestoreOfflineSession(
|
|||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!license_parser_->RestoreOfflineLicense(key_request_, key_response_,
|
if (license_type == kLicenseTypeRelease) {
|
||||||
offline_key_renewal_response_,
|
if (!license_parser_->RestoreLicenseForRelease(key_request_,
|
||||||
playback_start_time,
|
key_response_)) {
|
||||||
last_playback_time)) {
|
return UNKNOWN_ERROR;
|
||||||
return UNKNOWN_ERROR;
|
}
|
||||||
|
} else {
|
||||||
|
if (!license_parser_->RestoreOfflineLicense(key_request_, key_response_,
|
||||||
|
offline_key_renewal_response_,
|
||||||
|
playback_start_time,
|
||||||
|
last_playback_time)) {
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
license_received_ = true;
|
license_received_ = true;
|
||||||
@@ -172,7 +180,7 @@ CdmResponseType CdmSession::RestoreUsageSession(
|
|||||||
key_request_ = key_request;
|
key_request_ = key_request;
|
||||||
key_response_ = key_response;
|
key_response_ = key_response;
|
||||||
|
|
||||||
if (!license_parser_->RestoreUsageLicense(key_request_, key_response_)) {
|
if (!license_parser_->RestoreLicenseForRelease(key_request_, key_response_)) {
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -421,10 +421,19 @@ CdmResponseType CryptoSession::LoadKeys(
|
|||||||
provider_session_token.length());
|
provider_session_token.length());
|
||||||
|
|
||||||
if (OEMCrypto_SUCCESS == sts) {
|
if (OEMCrypto_SUCCESS == sts) {
|
||||||
|
if (!provider_session_token.empty()) {
|
||||||
|
sts = OEMCrypto_UpdateUsageTable();
|
||||||
|
if (sts != OEMCrypto_SUCCESS) {
|
||||||
|
LOGW("CryptoSession::LoadKeys: OEMCrypto_UpdateUsageTable error=%ld",
|
||||||
|
sts);
|
||||||
|
}
|
||||||
|
}
|
||||||
return KEY_ADDED;
|
return KEY_ADDED;
|
||||||
} else if (OEMCrypto_ERROR_TOO_MANY_KEYS == sts) {
|
} else if (OEMCrypto_ERROR_TOO_MANY_KEYS == sts) {
|
||||||
|
LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts);
|
||||||
return INSUFFICIENT_CRYPTO_RESOURCES;
|
return INSUFFICIENT_CRYPTO_RESOURCES;
|
||||||
} else {
|
} else {
|
||||||
|
LOGE("CryptoSession::LoadKeys: OEMCrypto_LoadKeys error=%d", sts);
|
||||||
return KEY_ERROR;
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,7 +448,7 @@ bool CryptoSession::LoadCertificatePrivateKey(std::string& wrapped_key) {
|
|||||||
wrapped_key.size());
|
wrapped_key.size());
|
||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
LOGD("LoadCertificatePrivateKey: OEMCrypto_LoadDeviceRSAKey error=%d", sts);
|
LOGE("LoadCertificatePrivateKey: OEMCrypto_LoadDeviceRSAKey error=%d", sts);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +518,7 @@ bool CryptoSession::GenerateDerivedKeys(const std::string& message) {
|
|||||||
enc_deriv_message.size());
|
enc_deriv_message.size());
|
||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
LOGD("GenerateDerivedKeys: OEMCrypto_GenerateDerivedKeys error=%d", sts);
|
LOGE("GenerateDerivedKeys: OEMCrypto_GenerateDerivedKeys error=%d", sts);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,7 +542,7 @@ bool CryptoSession::GenerateDerivedKeys(const std::string& message,
|
|||||||
enc_deriv_message.size());
|
enc_deriv_message.size());
|
||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
LOGD("GenerateDerivedKeys: OEMCrypto_DeriveKeysFromSessionKey err=%d", sts);
|
LOGE("GenerateDerivedKeys: OEMCrypto_DeriveKeysFromSessionKey err=%d", sts);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +563,7 @@ bool CryptoSession::GenerateSignature(const std::string& message,
|
|||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
|
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
|
||||||
LOGD("GenerateSignature: OEMCrypto_GenerateSignature err=%d", sts);
|
LOGE("GenerateSignature: OEMCrypto_GenerateSignature err=%d", sts);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,7 +576,7 @@ bool CryptoSession::GenerateSignature(const std::string& message,
|
|||||||
&length);
|
&length);
|
||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
LOGD("GenerateSignature: OEMCrypto_GenerateSignature err=%d", sts);
|
LOGE("GenerateSignature: OEMCrypto_GenerateSignature err=%d", sts);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -593,7 +602,7 @@ bool CryptoSession::GenerateRsaSignature(const std::string& message,
|
|||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
|
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
|
||||||
LOGD("GenerateRsaSignature: OEMCrypto_GenerateRSASignature err=%d", sts);
|
LOGE("GenerateRsaSignature: OEMCrypto_GenerateRSASignature err=%d", sts);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,7 +615,7 @@ bool CryptoSession::GenerateRsaSignature(const std::string& message,
|
|||||||
&length, kSign_RSASSA_PSS);
|
&length, kSign_RSASSA_PSS);
|
||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
LOGD("GenerateRsaSignature: OEMCrypto_GenerateRSASignature err=%d", sts);
|
LOGE("GenerateRsaSignature: OEMCrypto_GenerateRSASignature err=%d", sts);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -774,10 +783,32 @@ CdmResponseType CryptoSession::GenerateUsageReport(
|
|||||||
*usage_duration_status = kUsageDurationPlaybackNotBegun;
|
*usage_duration_status = kUsageDurationPlaybackNotBegun;
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
LOGV("OEMCrypto_PST_Report.status: %d\n", pst_report.status);
|
||||||
|
LOGV("OEMCrypto_PST_Report.clock_security_level: %d\n",
|
||||||
|
pst_report.clock_security_level);
|
||||||
|
LOGV("OEMCrypto_PST_Report.pst_length: %d\n", pst_report.pst_length);
|
||||||
|
LOGV("OEMCrypto_PST_Report.padding: %d\n", pst_report.padding);
|
||||||
|
LOGV("OEMCrypto_PST_Report.seconds_since_license_received: %lld\n",
|
||||||
|
ntohll64(pst_report.seconds_since_license_received));
|
||||||
|
LOGV("OEMCrypto_PST_Report.seconds_since_first_decrypt: %lld\n",
|
||||||
|
ntohll64(pst_report.seconds_since_first_decrypt));
|
||||||
|
LOGV("OEMCrypto_PST_Report.seconds_since_last_decrypt: %lld\n",
|
||||||
|
ntohll64(pst_report.seconds_since_last_decrypt));
|
||||||
|
LOGV("OEMCrypto_PST_Report: %s\n", b2a_hex(*usage_report).c_str());
|
||||||
|
|
||||||
|
// When usage report state is inactive, we have to deduce whether the
|
||||||
|
// license was ever used.
|
||||||
|
if (kInactive == pst_report.status &&
|
||||||
|
(0 > ntohll64(pst_report.seconds_since_first_decrypt) ||
|
||||||
|
ntohll64(pst_report.seconds_since_license_received) <
|
||||||
|
ntohll64(pst_report.seconds_since_first_decrypt))) {
|
||||||
|
*usage_duration_status = kUsageDurationPlaybackNotBegun;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
*usage_duration_status = kUsageDurationsValid;
|
*usage_duration_status = kUsageDurationsValid;
|
||||||
*seconds_since_started = pst_report.seconds_since_first_decrypt;
|
*seconds_since_started = ntohll64(pst_report.seconds_since_first_decrypt);
|
||||||
*seconds_since_last_played = pst_report.seconds_since_last_decrypt;
|
*seconds_since_last_played = ntohll64(pst_report.seconds_since_last_decrypt);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,6 +830,31 @@ CdmResponseType CryptoSession::ReleaseUsageInformation(
|
|||||||
status);
|
status);
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
status = OEMCrypto_UpdateUsageTable();
|
||||||
|
if (status != OEMCrypto_SUCCESS) {
|
||||||
|
LOGW("CryptoSession::ReleaseUsageInformation: OEMCrypto_UpdateUsageTable: "
|
||||||
|
"error=%ld",
|
||||||
|
status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmResponseType CryptoSession::DeleteAllUsageReports() {
|
||||||
|
LOGV("DeleteAllUsageReports");
|
||||||
|
OEMCryptoResult status = OEMCrypto_DeleteUsageTable();
|
||||||
|
|
||||||
|
if (OEMCrypto_SUCCESS != status) {
|
||||||
|
LOGE("CryptoSession::DeleteAllUsageReports: Delete Usage Table error =%ld",
|
||||||
|
status);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = OEMCrypto_UpdateUsageTable();
|
||||||
|
if (status != OEMCrypto_SUCCESS) {
|
||||||
|
LOGE("CryptoSession::ReleaseUsageInformation: OEMCrypto_UpdateUsageTable: "
|
||||||
|
"error=%ld",
|
||||||
|
status);
|
||||||
|
}
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -840,7 +896,7 @@ bool CryptoSession::RewrapDeviceRSAKey(const std::string& message,
|
|||||||
const std::string& enc_rsa_key,
|
const std::string& enc_rsa_key,
|
||||||
const std::string& rsa_key_iv,
|
const std::string& rsa_key_iv,
|
||||||
std::string* wrapped_rsa_key) {
|
std::string* wrapped_rsa_key) {
|
||||||
LOGD("CryptoSession::RewrapDeviceRSAKey, session id=%ld",
|
LOGV("CryptoSession::RewrapDeviceRSAKey, session id=%ld",
|
||||||
static_cast<uint32_t>(oec_session_id_));
|
static_cast<uint32_t>(oec_session_id_));
|
||||||
|
|
||||||
const uint8_t* signed_msg = reinterpret_cast<const uint8_t*>(message.data());
|
const uint8_t* signed_msg = reinterpret_cast<const uint8_t*>(message.data());
|
||||||
|
|||||||
@@ -755,7 +755,6 @@ bool CdmLicense::RestoreOfflineLicense(
|
|||||||
const CdmKeyResponse& license_renewal_response,
|
const CdmKeyResponse& license_renewal_response,
|
||||||
int64_t playback_start_time,
|
int64_t playback_start_time,
|
||||||
int64_t last_playback_time) {
|
int64_t last_playback_time) {
|
||||||
|
|
||||||
if (license_request.empty() || license_response.empty()) {
|
if (license_request.empty() || license_response.empty()) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"CdmLicense::RestoreOfflineLicense: key_request or response empty: "
|
"CdmLicense::RestoreOfflineLicense: key_request or response empty: "
|
||||||
@@ -827,26 +826,28 @@ bool CdmLicense::RestoreOfflineLicense(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CdmLicense::RestoreUsageLicense(const CdmKeyMessage& license_request,
|
bool CdmLicense::RestoreLicenseForRelease(
|
||||||
const CdmKeyResponse& license_response) {
|
const CdmKeyMessage& license_request,
|
||||||
|
const CdmKeyResponse& license_response) {
|
||||||
|
|
||||||
if (license_request.empty() || license_response.empty()) {
|
if (license_request.empty() || license_response.empty()) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"CdmLicense::RestoreUsageLicense: key_request or response empty: %u %u",
|
"CdmLicense::RestoreLicenseForRelease: key_request or response empty:"
|
||||||
|
" %u %u",
|
||||||
license_request.size(), license_response.size());
|
license_request.size(), license_response.size());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignedMessage signed_request;
|
SignedMessage signed_request;
|
||||||
if (!signed_request.ParseFromString(license_request)) {
|
if (!signed_request.ParseFromString(license_request)) {
|
||||||
LOGE("CdmLicense::RestoreUsageLicense: license_request parse failed");
|
LOGE("CdmLicense::RestoreLicenseForRelease: license_request parse failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signed_request.type() != SignedMessage::LICENSE_REQUEST) {
|
if (signed_request.type() != SignedMessage::LICENSE_REQUEST) {
|
||||||
LOGE(
|
LOGE(
|
||||||
"CdmLicense::RestoreUsageLicense: license request type: expected = %d,"
|
"CdmLicense::RestoreLicenseForRelease: license request type: expected "
|
||||||
" actual = %d",
|
"= %d, actual = %d",
|
||||||
SignedMessage::LICENSE_REQUEST, signed_request.type());
|
SignedMessage::LICENSE_REQUEST, signed_request.type());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -855,20 +856,21 @@ bool CdmLicense::RestoreUsageLicense(const CdmKeyMessage& license_request,
|
|||||||
|
|
||||||
SignedMessage signed_response;
|
SignedMessage signed_response;
|
||||||
if (!signed_response.ParseFromString(license_response)) {
|
if (!signed_response.ParseFromString(license_response)) {
|
||||||
LOGE("CdmLicense::RestoreUsageLicense: unable to parse signed license"
|
LOGE("CdmLicense::RestoreLicenseForRelease: unable to parse signed license"
|
||||||
" response");
|
" response");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SignedMessage::LICENSE != signed_response.type()) {
|
if (SignedMessage::LICENSE != signed_response.type()) {
|
||||||
LOGE("CdmLicense::RestoreUsageLicense: unrecognized signed message type: %d"
|
LOGE("CdmLicense::RestoreLicenseForRelease: unrecognized signed message "
|
||||||
|
"type: %d"
|
||||||
, signed_response.type());
|
, signed_response.type());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Properties::use_certificates_as_identification()) {
|
if (Properties::use_certificates_as_identification()) {
|
||||||
if (!signed_response.has_session_key()) {
|
if (!signed_response.has_session_key()) {
|
||||||
LOGE("CdmLicense::RestoreUsageLicense: no session keys present");
|
LOGE("CdmLicense::RestoreLicenseForRelease: no session keys present");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -880,16 +882,24 @@ bool CdmLicense::RestoreUsageLicense(const CdmKeyMessage& license_request,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!signed_response.has_signature()) {
|
if (!signed_response.has_signature()) {
|
||||||
LOGE("CdmLicense::RestoreUsageLicense: license response is not signed");
|
LOGE("CdmLicense::RestoreLicenseForRelease: license response is not"
|
||||||
|
" signed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
License license;
|
License license;
|
||||||
if (!license.ParseFromString(signed_response.msg())) {
|
if (!license.ParseFromString(signed_response.msg())) {
|
||||||
LOGE("CdmLicense::RestoreUsageLicense: unable to parse license response");
|
LOGE("CdmLicense::RestoreLicenseForRelease: unable to parse license"
|
||||||
|
" response");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (license.id().has_provider_session_token())
|
||||||
|
provider_session_token_ = license.id().provider_session_token();
|
||||||
|
|
||||||
|
if (license.policy().has_renewal_server_url())
|
||||||
|
server_url_ = license.policy().renewal_server_url();
|
||||||
|
|
||||||
policy_engine_->SetLicense(license);
|
policy_engine_->SetLicense(license);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,14 +174,31 @@ int64_t htonll64(int64_t x) { // Convert to big endian (network-byte-order)
|
|||||||
int64_t number;
|
int64_t number;
|
||||||
} mixed;
|
} mixed;
|
||||||
mixed.number = 1;
|
mixed.number = 1;
|
||||||
if (mixed.array[0] == 1) {
|
if (mixed.array[0] == 1) { // Little Endian.
|
||||||
mixed.number = x; // Little Endian.
|
mixed.number = x;
|
||||||
uint32_t temp = mixed.array[0];
|
uint32_t temp = mixed.array[0];
|
||||||
mixed.array[0] = htonl(mixed.array[1]);
|
mixed.array[0] = htonl(mixed.array[1]);
|
||||||
mixed.array[1] = htonl(temp);
|
mixed.array[1] = htonl(temp);
|
||||||
return mixed.number;
|
return mixed.number;
|
||||||
} else {
|
} else { // Big Endian.
|
||||||
return x; // Big Endian.
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t ntohll64(int64_t x) { // Convert from big endian (network-byte-order)
|
||||||
|
union {
|
||||||
|
uint32_t array[2];
|
||||||
|
int64_t number;
|
||||||
|
} mixed;
|
||||||
|
mixed.number = 1;
|
||||||
|
if (mixed.array[0] == 1) { // Little Endian.
|
||||||
|
mixed.number = x;
|
||||||
|
uint32_t temp = mixed.array[0];
|
||||||
|
mixed.array[0] = ntohl(mixed.array[1]);
|
||||||
|
mixed.array[1] = ntohl(temp);
|
||||||
|
return mixed.number;
|
||||||
|
} else { // Big Endian.
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
240
libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp
Normal file
240
libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "cdm_session.h"
|
||||||
|
#include "crypto_key.h"
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "properties.h"
|
||||||
|
#include "string_conversions.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const std::string kToken = wvcdm::a2bs_hex(
|
||||||
|
"0AAE02080212107E0A892DEEB021E7AF696B938BB1D5B1188B85AD9D05228E023082010A02"
|
||||||
|
"82010100DBEDF2BFB0EC98213766E65049B9AB176FA4B1FBFBB2A0C96C87D9F2B895E0ED77"
|
||||||
|
"93BDA057E6BC3E0CA2348BC6831E03609445CA4D418CB98EAC98FFC87AB2364CE76BA26BEE"
|
||||||
|
"CDB0C45BD2A6FE9FD38CC5A1C26303AEEB7E9C3CAFAB0D10E46C07E50BEDAB42BF21F40BD2"
|
||||||
|
"E055DB0B455191D6B4CEEB11B3F1AFA42B5C0CE4C96B75A5283C0E3AE049AA7CF86D1C4EF6"
|
||||||
|
"6A9088B53BCF320ABC9B98A22C219DC109014EFEA72DA5FF2ED5D655DE7AE06EAC6C6B4191"
|
||||||
|
"523B2CD2DC1EBFF5F08B11CFE056F2826C1323F12704EC7EBBC1AF935129E5543804492AF9"
|
||||||
|
"23B848F4AF47B4BFB131C39DDDC99DBAEEE0F30AD2ADBBC63E60793D0876E37391008BB4DB"
|
||||||
|
"F7020301000128DD22128002A9E571776EA9D22A1BD14248DA88E12FD859989F613360B8D2"
|
||||||
|
"DA40AF31CC071C7A138466F0EB745E3FD664C0E1A5E4F01098B8D56C34A0158DF9916D192F"
|
||||||
|
"841ADCA17FD630E1C0CBE652CAC6A52B6A1581BE4029CE6FAE0E04D2D2C7861187AF8299D8"
|
||||||
|
"3E008DB9A2789672CA1DED903773D7E82B234CE2C799EB73CF80600C08F17EEDDDF369D2B8"
|
||||||
|
"4A08292F22D1F18FE89521905E713BA674F2217881DBD7711B8C48D5FDCE6FAB51F935E293"
|
||||||
|
"CB29191AB012B115FD2F5F23164B063D0A929C3E254BF0F4FA60051EB6B3498ED99FF77C19"
|
||||||
|
"68E8CD83A35CEB054D05433FD0EA6AAE43C87DDA377591D1DCC1831EE130BFFF6D139A5ADA"
|
||||||
|
"738B0F257CCE2649E71AB4050AAE020801121017DCBC27D11341D497135442A188DAA6188F"
|
||||||
|
"89809105228E023082010A0282010100D21ADD7549D2748B3494526A9C3FB86C79376BBE8C"
|
||||||
|
"8856F601B8D10461F77ACC7331B10DEBF365120056CDB5662D25907B74F12382F0F4A0CA47"
|
||||||
|
"5EEA9562815C6228F6F698ADA27879D8890F2A2D96A746DDEF5316301C003519C2A2250354"
|
||||||
|
"674169FDDA41CE14D3C52BEA7A20384515012D5952B38AA19E15E8563CC7AAA81C2122880A"
|
||||||
|
"A370A64FEA23C53FB83AC3DB5753214730A349E07F64BF32BE7EAD30D02612AF110BB44FB0"
|
||||||
|
"8E1D308173B327EF64D40C41639542B2D1A73C98A6607EC6C683B513A58470514106EF87AE"
|
||||||
|
"1E7B9C695B93A104DF7437BFC4167789748A43ED208F2C1FA710793C688885EAE732A8BFDF"
|
||||||
|
"5B423B23D75B88FC0ADC8FBDB5020301000128DD2212800372D2FB88098BA3B85B6B4354E0"
|
||||||
|
"3767DBE2D7724663FB0A62ABF7704EA910E01F221349EE16D0152C769384050CE78520668C"
|
||||||
|
"06CCFD3D789AF3EB69FF163615CD609169FDBE2E15A029D34AD2605625BC81844C9D1E2CE0"
|
||||||
|
"519039F3799ADAEF86641E20B033DC16DF2E5B9A1A2A417B8BB3B7A4D9AD1A99367448587D"
|
||||||
|
"A13DDE05A3ED9D62FA42078973B4AA40263D7BFA23F1072E94CDF323FA45F78408823E55C4"
|
||||||
|
"F4C5C723819CF44CE6D98E50C04EC24D93B1AAB8877B9108B9CA391308E1A3645EBB0E7CAC"
|
||||||
|
"BB40B5451560ED799421873BFB5ABB917FA60DB9C77CB8606AF7E3142626F5EA40E5CB8AA0"
|
||||||
|
"89D8E7D6A9361935C426A4450EA8BC2E57290D3BF0A0962991D2A91B752FC80C3E7E4E5503"
|
||||||
|
"3D71C94B325307A68815F026448F56A2741CEBEFC18E8C142F5F62BFAA67A291517DDE982D"
|
||||||
|
"8CD5A9DF6E3D3A99B806F6D60991358C5BE77117D4F3168F3348E9A048539F892F4D783152"
|
||||||
|
"C7A8095224AA56B78C5CF7BD1AB1B179C0C0D11E3C3BAC84C141A00191321E3ACC17242E68"
|
||||||
|
"3C");
|
||||||
|
const std::string kWrappedKey = wvcdm::a2bs_hex(
|
||||||
|
"3B84252DD84F1A710365014A114507FFFA3DD404625D61D1EEC7C3A39D72CB8D9318ADE9DA"
|
||||||
|
"05D69F9776DAFDA49A97BC30E84CA275925DFD98CA04F7DB23465103A224852192DE232902"
|
||||||
|
"99FF82024F5CCA7716ACA9BE0B56348BA16B9E3136D73789C842CB2ECA4820DDAAF59CCB9B"
|
||||||
|
"FCF2B4B0E2E5199FDCEC8DEBFFE50BB03041D8E767EA3FE6834C2E79E261ABF17B68EA66E1"
|
||||||
|
"45AD0A6B056F39C06531A9038C996BADD524E57AE7D5339F13C574E7A398C03D65FD730BAC"
|
||||||
|
"36F25347350DD2AD69EFA4DC040DC2D9DD4F53A729839FA3496CF580F2CBD51C3522DD67BC"
|
||||||
|
"BA4A91E89E2BD70449F28E026638920A6DF7B9A0B2C977ACC65AE845E76EF81CADAA746DAF"
|
||||||
|
"51D4D6FCBC083BE50DA1874D6EB1A30579B23C30881D94A8E5181FE20BF8F8C5F2522B1E7D"
|
||||||
|
"092B1E20BDE5373F40286DE15267247F88C564BD4EBF4F69B889A03C9892584DC340D87EE1"
|
||||||
|
"DFF2942D1B7E7EBD846349575F2DE6FDEF71BB005CFBEA845D87937BEBCAFEAC785A092C0A"
|
||||||
|
"76CE7F7A4FE2F8E43045DED5202A2A55F547BA5DE67AF9E6B2B7DC89EFAD34AC0B40BF4B8F"
|
||||||
|
"F82F8706B9A88FB9C7A0972E4A4B6CA970BF4F086573D595E5DB8ED0FDA4F9446ACD4B119C"
|
||||||
|
"1E949C194B042A5CFFC13043FF79F049068A67CC1EB671A10EF7DA927753C4D149E9D0000D"
|
||||||
|
"4307008BA0AED576ACCADF0CE6758F683087F26C2E38297B8C7D78DC3F1E8F24D7B3A0BED9"
|
||||||
|
"C066F8348FD19CDB54A92C4E944EE11E11B3B44344E0DB0E1B4BD6CF9295AB66C05454776A"
|
||||||
|
"8FE33AF659F67718AB43ACB52E83F8C29129DCE9654E8F1EBF9DAB9E933955E24389A37DBE"
|
||||||
|
"17BA89AC8C750B025CB2F65D5C8BF32FED87EF368F15751AA2114159B6C9C6C814D0720DA4"
|
||||||
|
"6E885BBB764ADC250D05F70306C3190991C31439BF273A33B6D1773E4FD089F32E753FA3C7"
|
||||||
|
"7B5ED7DB28407D87396F1F8C83B58176EDFE1F923BDB7DA0ADE58CA2BCD6E76F9463BE7A5A"
|
||||||
|
"909BE2731241BF1436F3E6A639FC7C717445D89AA5812E4532405B0FB368FE736E22D10FFD"
|
||||||
|
"15FACCF69FAC468B5552C7887763B96578038CCF154F333E2095BBFF71D5C1235E032174FB"
|
||||||
|
"44EAB4A753E7A917666A400EBE4F3D2C90100155C27F4B30C8ACFEDA6EFC763EF3556874E5"
|
||||||
|
"8A5AB0AEBBF39990F79EF4D65EC4697D7BBEEF4F32AE8C4A8A94814A9BE532B5AC902BC0C5"
|
||||||
|
"FB0A3E661AFF5961B6E79C82CC32FA7B7B48297347503FD58B110B93208167CC1FB96AD822"
|
||||||
|
"42F60B9D2BF9CCEE8E778A3D3A3302303FB4E33F607D46AACE49D3546A993EDC6FBEE6E19D"
|
||||||
|
"36831D85877013C57FE335F38D5CD9C3E09C1CEE28BC92C53A364663A7C031DF43B89BAAB4"
|
||||||
|
"AA8176900FD483AD70E3844BD15EE4F01D8BE72186BBF9E019FCEE5961166696854D1A901F"
|
||||||
|
"9D71B69B05F75FF233DB3C37F18DCADA640F68C4386F2E528CD77B93521A4574EF399375CD"
|
||||||
|
"2BE7B9FDC0AE62249717B7E0022BF55C0D023669DD09355EAA90E9DF9BEA309DF7561423BF"
|
||||||
|
"1DAD177F07A442E1591553924C0F67C2E86774009825490322A6B74319B4C77AA6195CA393"
|
||||||
|
"03A311F762FB0FD445278D9ACF26A9049C5031BE91F2C4A6BE994CA5A3CEBC2ACCF93AB1EB"
|
||||||
|
"993A6AA6DEB152DE8C9BB0E6B37B478393B50D1AAE99C086A0ED6D93BA7DD2DEEAB58EE34B"
|
||||||
|
"C5EE06BE238E8DE6CB44211097C5C90D5C04857918856F86B7036986C20A43153892ED9093"
|
||||||
|
"33EF70621A98184DDAB5E14BC971CF98CF6C91A37FFA83B00AD3BCABBAAB2DEF1C52F43003"
|
||||||
|
"E74C92B44F9205D22262FB47948654229DE1920F8EDF96A19A88A1CA1552F8856FB4CBF83B"
|
||||||
|
"AA3348419159D207F65FCE9C1A500C6818");
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace wvcdm {
|
||||||
|
|
||||||
|
// gmock methods
|
||||||
|
using ::testing::_;
|
||||||
|
using ::testing::Eq;
|
||||||
|
using ::testing::NotNull;
|
||||||
|
using ::testing::Return;
|
||||||
|
using ::testing::SetArgPointee;
|
||||||
|
using ::testing::StrEq;
|
||||||
|
|
||||||
|
class MockDeviceFiles : public DeviceFiles {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD1(Init, bool(CdmSecurityLevel));
|
||||||
|
MOCK_METHOD2(RetrieveCertificate, bool(std::string*, std::string*));
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockCryptoSession : public CryptoSession {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD1(GetToken, bool(std::string*));
|
||||||
|
MOCK_METHOD0(GetSecurityLevel, CdmSecurityLevel());
|
||||||
|
MOCK_METHOD0(Open, CdmResponseType());
|
||||||
|
MOCK_METHOD1(Open, CdmResponseType(SecurityLevel));
|
||||||
|
MOCK_METHOD1(LoadCertificatePrivateKey, bool(std::string&));
|
||||||
|
MOCK_METHOD0(DeleteAllUsageReports, CdmResponseType());
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockPolicyEngine : public PolicyEngine {
|
||||||
|
public:
|
||||||
|
// Leaving a place holder for when PolicyEngine methods need to be mocked
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockCdmLicense : public CdmLicense {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD3(Init, bool(const std::string&, CryptoSession*, PolicyEngine*));
|
||||||
|
};
|
||||||
|
|
||||||
|
class CdmSessionTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
virtual void SetUp() {
|
||||||
|
license_parser_ = new MockCdmLicense();
|
||||||
|
crypto_session_ = new MockCryptoSession();
|
||||||
|
policy_engine_ = new MockPolicyEngine();
|
||||||
|
file_handle_ = new MockDeviceFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() {
|
||||||
|
if (cdm_session_) delete cdm_session_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateSession() {
|
||||||
|
cdm_session_ = new CdmSession(license_parser_, crypto_session_,
|
||||||
|
policy_engine_, file_handle_, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateSession(const CdmClientPropertySet* cdm_client_property_set) {
|
||||||
|
cdm_session_ =
|
||||||
|
new CdmSession(license_parser_, crypto_session_, policy_engine_,
|
||||||
|
file_handle_, cdm_client_property_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
CdmSession* cdm_session_;
|
||||||
|
MockCdmLicense* license_parser_;
|
||||||
|
MockCryptoSession* crypto_session_;
|
||||||
|
MockPolicyEngine* policy_engine_;
|
||||||
|
MockDeviceFiles* file_handle_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(CdmSessionTest, InitWithCertificate) {
|
||||||
|
CdmSecurityLevel level = kSecurityLevelL1;
|
||||||
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||||
|
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||||
|
.WillOnce(Return(NO_ERROR));
|
||||||
|
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<0>(kToken), SetArgPointee<1>(kWrappedKey),
|
||||||
|
Return(true)));
|
||||||
|
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(StrEq(kWrappedKey)))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(*license_parser_,
|
||||||
|
Init(Eq(kToken), Eq(crypto_session_), Eq(policy_engine_)))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
|
Properties::set_use_certificates_as_identification(true);
|
||||||
|
|
||||||
|
CreateSession();
|
||||||
|
ASSERT_EQ(NO_ERROR, cdm_session_->Init());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CdmSessionTest, InitWithKeybox) {
|
||||||
|
CdmSecurityLevel level = kSecurityLevelL1;
|
||||||
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||||
|
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||||
|
.WillOnce(Return(NO_ERROR));
|
||||||
|
EXPECT_CALL(*crypto_session_, GetToken(NotNull()))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<0>(kToken), Return(true)));
|
||||||
|
EXPECT_CALL(*license_parser_,
|
||||||
|
Init(Eq(kToken), Eq(crypto_session_), Eq(policy_engine_)))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
|
Properties::set_use_certificates_as_identification(false);
|
||||||
|
|
||||||
|
CreateSession();
|
||||||
|
ASSERT_EQ(NO_ERROR, cdm_session_->Init());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CdmSessionTest, ReInitFail) {
|
||||||
|
CdmSecurityLevel level = kSecurityLevelL1;
|
||||||
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||||
|
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||||
|
.WillOnce(Return(NO_ERROR));
|
||||||
|
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<0>(kToken), SetArgPointee<1>(kWrappedKey),
|
||||||
|
Return(true)));
|
||||||
|
EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(StrEq(kWrappedKey)))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(*license_parser_,
|
||||||
|
Init(Eq(kToken), Eq(crypto_session_), Eq(policy_engine_)))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
|
Properties::set_use_certificates_as_identification(true);
|
||||||
|
|
||||||
|
CreateSession();
|
||||||
|
ASSERT_EQ(NO_ERROR, cdm_session_->Init());
|
||||||
|
ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CdmSessionTest, InitFailCryptoError) {
|
||||||
|
CdmSecurityLevel level = kSecurityLevelL1;
|
||||||
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||||
|
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||||
|
.WillOnce(Return(UNKNOWN_ERROR));
|
||||||
|
|
||||||
|
Properties::set_use_certificates_as_identification(true);
|
||||||
|
|
||||||
|
CreateSession();
|
||||||
|
ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CdmSessionTest, InitNeedsProvisioning) {
|
||||||
|
CdmSecurityLevel level = kSecurityLevelL1;
|
||||||
|
EXPECT_CALL(*crypto_session_, GetSecurityLevel()).WillOnce(Return(level));
|
||||||
|
EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault)))
|
||||||
|
.WillOnce(Return(NO_ERROR));
|
||||||
|
EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true));
|
||||||
|
EXPECT_CALL(*file_handle_, RetrieveCertificate(NotNull(), NotNull()))
|
||||||
|
.WillOnce(Return(false));
|
||||||
|
|
||||||
|
Properties::set_use_certificates_as_identification(true);
|
||||||
|
|
||||||
|
CreateSession();
|
||||||
|
ASSERT_EQ(NEED_PROVISIONING, cdm_session_->Init());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // wvcdm
|
||||||
@@ -27,7 +27,7 @@ const std::string kCpOfflineKeyId =
|
|||||||
"00000020" // pssh data size
|
"00000020" // pssh data size
|
||||||
// pssh data:
|
// pssh data:
|
||||||
"08011a0d7769646576696e655f746573"
|
"08011a0d7769646576696e655f746573"
|
||||||
"74220d6f66666c696e655f636c697031";
|
"74220d6f66666c696e655f636c697032";
|
||||||
|
|
||||||
// Google Play license server data
|
// Google Play license server data
|
||||||
const std::string kGpLicenseServer =
|
const std::string kGpLicenseServer =
|
||||||
|
|||||||
@@ -106,7 +106,10 @@ CdmResponseType WvContentDecryptionModule::AddKey(
|
|||||||
CdmResponseType WvContentDecryptionModule::RestoreKey(
|
CdmResponseType WvContentDecryptionModule::RestoreKey(
|
||||||
const CdmSessionId& session_id,
|
const CdmSessionId& session_id,
|
||||||
const CdmKeySetId& key_set_id) {
|
const CdmKeySetId& key_set_id) {
|
||||||
return cdm_engine_->RestoreKey(session_id, key_set_id);
|
CdmResponseType sts = cdm_engine_->RestoreKey(session_id, key_set_id);
|
||||||
|
if (sts == KEY_ADDED)
|
||||||
|
EnablePolicyTimer();
|
||||||
|
return sts;
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType WvContentDecryptionModule::CancelKeyRequest(
|
CdmResponseType WvContentDecryptionModule::CancelKeyRequest(
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ test_name := cdm_engine_test
|
|||||||
test_src_dir := ../core/test
|
test_src_dir := ../core/test
|
||||||
include $(LOCAL_PATH)/unit-test.mk
|
include $(LOCAL_PATH)/unit-test.mk
|
||||||
|
|
||||||
|
test_name := cdm_extended_duration_test
|
||||||
|
test_src_dir := .
|
||||||
|
include $(LOCAL_PATH)/unit-test.mk
|
||||||
|
|
||||||
test_name := cdm_session_unittest
|
test_name := cdm_session_unittest
|
||||||
test_src_dir := ../core/test
|
test_src_dir := ../core/test
|
||||||
include $(LOCAL_PATH)/unit-test.mk
|
include $(LOCAL_PATH)/unit-test.mk
|
||||||
|
|||||||
1278
libwvdrmengine/cdm/test/cdm_extended_duration_test.cpp
Normal file
1278
libwvdrmengine/cdm/test/cdm_extended_duration_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -581,8 +581,49 @@ class WvCdmRequestLicenseTest : public testing::Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unprovision() {
|
||||||
|
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL1));
|
||||||
|
EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Provision() {
|
||||||
|
CdmResponseType status =
|
||||||
|
decryptor_.OpenSession(g_key_system, NULL, &session_id_);
|
||||||
|
switch (status) {
|
||||||
|
case NO_ERROR:
|
||||||
|
decryptor_.CloseSession(session_id_);
|
||||||
|
return;
|
||||||
|
case NEED_PROVISIONING:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
EXPECT_EQ(NO_ERROR, status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string provisioning_server_url;
|
||||||
|
CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
|
std::string cert_authority, cert, wrapped_key;
|
||||||
|
|
||||||
|
status = decryptor_.GetProvisioningRequest(
|
||||||
|
cert_type, cert_authority, &key_msg_, &provisioning_server_url);
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, status);
|
||||||
|
if (NO_ERROR != status) return;
|
||||||
|
EXPECT_EQ(provisioning_server_url, g_config->provisioning_server_url());
|
||||||
|
|
||||||
|
std::string response =
|
||||||
|
GetCertRequestResponse(g_config->provisioning_server_url());
|
||||||
|
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
|
||||||
|
response, &cert, &wrapped_key));
|
||||||
|
EXPECT_EQ(0, static_cast<int>(cert.size()));
|
||||||
|
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
||||||
|
decryptor_.CloseSession(session_id_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetSecurityLevel(TestWvCdmClientPropertySet* property_set) {
|
std::string GetSecurityLevel(TestWvCdmClientPropertySet* property_set) {
|
||||||
decryptor_.OpenSession(g_key_system, property_set, &session_id_);
|
EXPECT_EQ(NO_ERROR,
|
||||||
|
decryptor_.OpenSession(g_key_system, property_set, &session_id_));
|
||||||
CdmQueryMap query_info;
|
CdmQueryMap query_info;
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
decryptor_.QuerySessionStatus(session_id_, &query_info));
|
decryptor_.QuerySessionStatus(session_id_, &query_info));
|
||||||
@@ -864,6 +905,9 @@ TEST_F(WvCdmRequestLicenseTest, AddStreamingKeyTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
|
TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
|
||||||
|
Unprovision();
|
||||||
|
Provision();
|
||||||
|
|
||||||
// override default settings unless configured through the command line
|
// override default settings unless configured through the command line
|
||||||
std::string key_id;
|
std::string key_id;
|
||||||
std::string client_auth;
|
std::string client_auth;
|
||||||
@@ -876,6 +920,9 @@ TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
|
TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
|
||||||
|
Unprovision();
|
||||||
|
Provision();
|
||||||
|
|
||||||
// override default settings unless configured through the command line
|
// override default settings unless configured through the command line
|
||||||
std::string key_id;
|
std::string key_id;
|
||||||
std::string client_auth;
|
std::string client_auth;
|
||||||
@@ -896,6 +943,9 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeyTest) {
|
TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeyTest) {
|
||||||
|
Unprovision();
|
||||||
|
Provision();
|
||||||
|
|
||||||
// override default settings unless configured through the command line
|
// override default settings unless configured through the command line
|
||||||
std::string key_id;
|
std::string key_id;
|
||||||
std::string client_auth;
|
std::string client_auth;
|
||||||
@@ -923,6 +973,9 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseOfflineKeyTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, ReleaseRetryOfflineKeyTest) {
|
TEST_F(WvCdmRequestLicenseTest, ReleaseRetryOfflineKeyTest) {
|
||||||
|
Unprovision();
|
||||||
|
Provision();
|
||||||
|
|
||||||
// override default settings unless configured through the command line
|
// override default settings unless configured through the command line
|
||||||
std::string key_id;
|
std::string key_id;
|
||||||
std::string client_auth;
|
std::string client_auth;
|
||||||
@@ -959,6 +1012,9 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryOfflineKeyTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
|
TEST_F(WvCdmRequestLicenseTest, ExpiryOnReleaseOfflineKeyTest) {
|
||||||
|
Unprovision();
|
||||||
|
Provision();
|
||||||
|
|
||||||
// override default settings unless configured through the command line
|
// override default settings unless configured through the command line
|
||||||
std::string key_id;
|
std::string key_id;
|
||||||
std::string client_auth;
|
std::string client_auth;
|
||||||
@@ -1034,7 +1090,7 @@ class WvCdmUsageInfoTest
|
|||||||
: public WvCdmRequestLicenseTest,
|
: public WvCdmRequestLicenseTest,
|
||||||
public ::testing::WithParamInterface<UsageInfoSubSampleInfo*> {};
|
public ::testing::WithParamInterface<UsageInfoSubSampleInfo*> {};
|
||||||
|
|
||||||
TEST_P(WvCdmUsageInfoTest, DISABLED_UsageInfo) {
|
TEST_P(WvCdmUsageInfoTest, UsageInfo) {
|
||||||
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
|
||||||
DeviceFiles handle;
|
DeviceFiles handle;
|
||||||
EXPECT_TRUE(handle.Init(security_level));
|
EXPECT_TRUE(handle.Init(security_level));
|
||||||
|
|||||||
Reference in New Issue
Block a user