Merge changes Ic23e2e48,I5d25844b
* changes: Google-style override & virtual Remove Sub-Licenses and Sub-Sessions
This commit is contained in:
@@ -34,21 +34,21 @@ namespace wvcdm {
|
||||
class UsagePropertySet : public CdmClientPropertySet {
|
||||
public:
|
||||
UsagePropertySet() {}
|
||||
virtual ~UsagePropertySet() {}
|
||||
~UsagePropertySet() override {}
|
||||
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 void set_service_certificate(const std::string&) {}
|
||||
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 */) {}
|
||||
virtual const std::string& app_id() const { return app_id_; }
|
||||
const std::string& security_level() const override { return security_level_; }
|
||||
bool use_privacy_mode() const override { return false; }
|
||||
const std::string& service_certificate() const override { return empty_; }
|
||||
void set_service_certificate(const std::string&) override {}
|
||||
bool is_session_sharing_enabled() const override { return false; }
|
||||
uint32_t session_sharing_id() const override { return 0; }
|
||||
void set_session_sharing_id(uint32_t /* id */) override {}
|
||||
const std::string& app_id() const override { return app_id_; }
|
||||
void set_app_id(const std::string& appId) { app_id_ = appId; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -418,18 +418,6 @@ CdmResponseType CdmSession::GenerateKeyRequestInternal(
|
||||
return KEY_REQUEST_ERROR_1;
|
||||
}
|
||||
|
||||
std::vector<video_widevine::SubLicense> embedded_key_data =
|
||||
init_data.ExtractSublicenseKeys();
|
||||
for (size_t i = 0; i < embedded_key_data.size(); ++i) {
|
||||
CdmResponseType sts = crypto_session_->AddSubSession(
|
||||
embedded_key_data[i].sub_session_key_id(),
|
||||
embedded_key_data[i].group_id());
|
||||
if (NO_ERROR != sts) {
|
||||
LOGE("CdmSession::GenerateKeyRequest: Unable to generate sub session");
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
|
||||
app_parameters_ = app_parameters;
|
||||
CdmResponseType status = license_parser_->PrepareKeyRequest(
|
||||
init_data, license_type, app_parameters, &key_request->message,
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "properties.h"
|
||||
#include "pst_report.h"
|
||||
#include "string_conversions.h"
|
||||
#include "sublicense_key_session.h"
|
||||
#include "usage_table_header.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
@@ -772,7 +771,6 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
|
||||
metrics_->oemcrypto_usage_table_support_.SetError(result);
|
||||
}
|
||||
|
||||
// TODO(gmorgan, jfore): resolve handling of usage records in sublicenses
|
||||
key_session_.reset(new ContentKeySession(oec_session_id_, metrics_));
|
||||
|
||||
return NO_ERROR;
|
||||
@@ -944,7 +942,6 @@ bool CryptoSession::LoadCertificatePrivateKey(std::string& wrapped_key) {
|
||||
LOGE("LoadCertificatePrivateKey: OEMCrypto_LoadDeviceRSAKey error=%d", sts);
|
||||
return false;
|
||||
}
|
||||
wrapped_key_ = wrapped_key;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2316,73 +2313,6 @@ bool CryptoSession::GetAnalogOutputCapabilities(bool* can_support_output,
|
||||
return true;
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::AddSubSession(
|
||||
const std::string& sub_session_key_id,
|
||||
const std::string& group_master_key_id) {
|
||||
size_t exists = sub_license_oec_sessions_.count(sub_session_key_id);
|
||||
if (exists > 0) {
|
||||
// TODO(jfore): Should this be an error if the key exists? If so add a new
|
||||
// error. If not, perhaps this should just print info message.
|
||||
LOGE("AddSubSession: SubSession already exists for id: %s",
|
||||
sub_session_key_id.c_str());
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
CryptoSessionId sid;
|
||||
OEMCryptoResult sts = OEMCrypto_OpenSession(&sid, requested_security_level_);
|
||||
if (OEMCrypto_ERROR_TOO_MANY_SESSIONS == sts) {
|
||||
LOGE("OEMCrypto_Open failed: %d, open sessions: %ld, initialized: %d", sts,
|
||||
session_count_, (int)initialized_);
|
||||
return INSUFFICIENT_CRYPTO_RESOURCES;
|
||||
} else if (OEMCrypto_SUCCESS != sts) {
|
||||
LOGE("OEMCrypto_Open failed: %d, open sessions: %ld, initialized: %d", sts,
|
||||
session_count_, (int)initialized_);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
M_TIME(sts = OEMCrypto_LoadDeviceRSAKey(
|
||||
sid, reinterpret_cast<const uint8_t*>(wrapped_key_.data()),
|
||||
wrapped_key_.size()),
|
||||
metrics_, oemcrypto_load_device_rsa_key_, sts);
|
||||
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
LOGE("LoadDeviceRSAKey failed: %d", sts);
|
||||
return NEED_PROVISIONING;
|
||||
}
|
||||
|
||||
sub_license_oec_sessions_[sub_session_key_id] = sid;
|
||||
if (key_session_->Type() != KeySession::kSubLicense) {
|
||||
key_session_.reset(new SubLicenseKeySession(
|
||||
sub_license_oec_sessions_, metrics_, wrapped_key_,
|
||||
requested_security_level_, group_master_key_id));
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool CryptoSession::GenerateSubSessionNonce(
|
||||
const std::string& sub_session_key_id, bool* exists, uint32_t* nonce) {
|
||||
if (!exists || !nonce) {
|
||||
LOGE("input parameter is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGV("CryptoSession::GenerateSubSessionNonce: Lock");
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
|
||||
SubLicenseSessionMap::iterator it =
|
||||
sub_license_oec_sessions_.find(sub_session_key_id);
|
||||
if (it == sub_license_oec_sessions_.end()) {
|
||||
// A subsession does not exist. Indicate that and return success.
|
||||
*exists = false;
|
||||
return false;
|
||||
}
|
||||
*exists = true;
|
||||
|
||||
OEMCryptoResult result;
|
||||
result = OEMCrypto_GenerateNonce(it->second, nonce);
|
||||
return OEMCrypto_SUCCESS == result;
|
||||
}
|
||||
|
||||
OEMCrypto_Algorithm CryptoSession::GenericSigningAlgorithm(
|
||||
CdmSigningAlgorithm algorithm) {
|
||||
if (kSigningAlgorithmHmacSha256 == algorithm) {
|
||||
|
||||
@@ -85,15 +85,6 @@ InitializationData::InitializationData(const std::string& type,
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the pssh data and return the embedded key data if it exists.
|
||||
std::vector<video_widevine::SubLicense>
|
||||
InitializationData::ExtractSublicenseKeys() const {
|
||||
std::vector<video_widevine::SubLicense> keys;
|
||||
// TODO(jfore): The pssh has changed in ways that are not compatible with
|
||||
//sublicenses. Restructure or remove sublicense support including this method.
|
||||
return keys;
|
||||
}
|
||||
|
||||
std::vector<video_widevine::WidevinePsshData_EntitledKey>
|
||||
InitializationData::ExtractWrappedKeys() const {
|
||||
std::vector<video_widevine::WidevinePsshData_EntitledKey> keys;
|
||||
|
||||
@@ -53,7 +53,6 @@ using video_widevine::SignedMessage;
|
||||
static std::vector<CryptoKey> ExtractEntitlementKeys(const License& license) {
|
||||
std::vector<CryptoKey> key_array;
|
||||
|
||||
// Extract sub session key(s)
|
||||
for (int i = 0; i < license.key_size(); ++i) {
|
||||
CryptoKey key;
|
||||
size_t length = 0;
|
||||
@@ -326,29 +325,6 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
|
||||
license_request.set_key_control_nonce(nonce);
|
||||
LOGD("PrepareKeyRequest: nonce=%u", nonce);
|
||||
|
||||
// Prepare the request for any embedded keys that may exist in the
|
||||
// initialization data.
|
||||
std::vector<video_widevine::SubLicense> embedded_key_data =
|
||||
init_data.ExtractSublicenseKeys();
|
||||
for (size_t i = 0; i < embedded_key_data.size(); ++i) {
|
||||
bool exists = false;
|
||||
if (!crypto_session_->GenerateSubSessionNonce(
|
||||
embedded_key_data[i].sub_session_key_id(), &exists, &nonce)) {
|
||||
if (exists) {
|
||||
return LICENSE_REQUEST_NONCE_GENERATION_ERROR;
|
||||
}
|
||||
}
|
||||
SignedMessage signed_sub_license;
|
||||
License_KeyContainer keyc;
|
||||
|
||||
// Parse the sub license for this track to extract the label.
|
||||
if (!signed_sub_license.ParseFromString(embedded_key_data[i].key_msg()) ||
|
||||
!keyc.ParseFromString(signed_sub_license.msg()) ||
|
||||
keyc.track_label().empty()) {
|
||||
return LICENSE_REQUEST_INVALID_SUBLICENSE;
|
||||
}
|
||||
}
|
||||
|
||||
license_request.set_protocol_version(video_widevine::VERSION_2_1);
|
||||
|
||||
// License request is complete. Serialize it.
|
||||
@@ -626,7 +602,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
|
||||
CdmResponseType resp = NO_CONTENT_KEY;
|
||||
if (kLicenseKeyTypeEntitlement == key_type) {
|
||||
entitlement_key_array_ = key_array;
|
||||
resp = HandleEntitlementKeyResponse(signed_response.msg(),
|
||||
signed_response.signature(), mac_key_iv,
|
||||
mac_keys, key_array, license);
|
||||
@@ -722,9 +697,7 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
|
||||
CdmResponseType CdmLicense::HandleEmbeddedKeyData(
|
||||
const InitializationData& init_data) {
|
||||
return (license_key_type_ == kLicenseKeyTypeEntitlement
|
||||
? HandleNewEntitledKeys(init_data.ExtractWrappedKeys())
|
||||
: HandleSubLicense(init_data));
|
||||
return HandleNewEntitledKeys(init_data.ExtractWrappedKeys());
|
||||
}
|
||||
|
||||
bool CdmLicense::RestoreOfflineLicense(
|
||||
@@ -1127,57 +1100,6 @@ CdmResponseType CdmLicense::HandleNewEntitledKeys(
|
||||
return resp;
|
||||
}
|
||||
|
||||
CdmResponseType CdmLicense::HandleSubLicense(
|
||||
const InitializationData& init_data) {
|
||||
std::vector<video_widevine::SubLicense> subkeys =
|
||||
init_data.ExtractSublicenseKeys();
|
||||
std::set<KeyId> loaded_keys;
|
||||
// Build a license with the rotated keys.
|
||||
License license;
|
||||
for (size_t i = 0; i < subkeys.size(); ++i) {
|
||||
SignedMessage sm;
|
||||
if (!sm.ParseFromString(subkeys[i].key_msg())) {
|
||||
return LICENSE_REQUEST_INVALID_SUBLICENSE;
|
||||
}
|
||||
License_KeyContainer keyc;
|
||||
if (!keyc.ParseFromString(sm.msg())) {
|
||||
return LICENSE_REQUEST_INVALID_SUBLICENSE;
|
||||
}
|
||||
size_t length;
|
||||
std::vector<CryptoKey> keys;
|
||||
keys.resize(1);
|
||||
keys[0].set_key_id(keyc.id());
|
||||
|
||||
// Strip PKCS#5 padding from sublicense content keys.
|
||||
// TODO(jfore): Refactor this to use ExtractContentKeys.
|
||||
if (keyc.key().size() > CONTENT_KEY_SIZE) {
|
||||
length = keyc.key().size() - CONTENT_KEY_SIZE;
|
||||
} else {
|
||||
length = 0;
|
||||
}
|
||||
keys[0].set_key_data(keyc.key().substr(0, length));
|
||||
keys[0].set_key_data_iv(keyc.iv());
|
||||
keys[0].set_key_control(keyc.key_control().key_control_block());
|
||||
keys[0].set_key_control_iv(keyc.key_control().iv());
|
||||
keys[0].set_track_label(keyc.track_label());
|
||||
// TODO: passing empty cipher_mode and srm_req params - OK?
|
||||
CdmResponseType result = crypto_session_->LoadKeys(
|
||||
sm.msg(), sm.signature(), std::string(), std::string(), keys,
|
||||
std::string(), std::string(), kLicenseKeyTypeContent);
|
||||
if (result != KEY_ADDED) {
|
||||
LOGE("CdmLicense::HandleSubLicense: LoadKeys() call failed, result=%d",
|
||||
result);
|
||||
return result;
|
||||
}
|
||||
loaded_keys.insert(keyc.id());
|
||||
*license.add_key() = keyc;
|
||||
}
|
||||
loaded_keys_.swap(loaded_keys);
|
||||
policy_engine_->UpdateLicenseKeys(license);
|
||||
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool CdmLicense::SetTypeAndId(CdmLicenseType license_type,
|
||||
const std::string& request_id, T* content_id) {
|
||||
|
||||
@@ -170,14 +170,6 @@ void PolicyEngine::SetLicense(const License& license) {
|
||||
UpdateLicense(license);
|
||||
}
|
||||
|
||||
void PolicyEngine::UpdateLicenseKeys(const video_widevine::License& license) {
|
||||
// Use the current policy and set the new keys.
|
||||
video_widevine::License loadable = license;
|
||||
loadable.mutable_policy()->CopyFrom(policy_);
|
||||
license_keys_->SetFromLicense(loadable);
|
||||
NotifyKeysChange(kKeyStatusUsable);
|
||||
}
|
||||
|
||||
void PolicyEngine::SetEntitledLicenseKeys(
|
||||
const std::vector<WidevinePsshData_EntitledKey>& entitled_keys) {
|
||||
license_keys_->SetEntitledKeys(entitled_keys);
|
||||
|
||||
@@ -1,328 +0,0 @@
|
||||
#include "sublicense_key_session.h"
|
||||
|
||||
#include "crypto_session.h"
|
||||
#include "log.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
SubLicenseKeySession::SubLicenseKeySession(
|
||||
SubLicenseSessionMap& sub_license_oec_sessions,
|
||||
metrics::CryptoMetrics* metrics,
|
||||
const std::string& wrapped_private_device_key,
|
||||
SecurityLevel requested_security_level,
|
||||
const std::string& group_id)
|
||||
: KeySession(metrics),
|
||||
state_(kInitializing),
|
||||
wrapped_private_device_key_(wrapped_private_device_key),
|
||||
sub_license_oec_sessions_(sub_license_oec_sessions),
|
||||
requested_security_level_(requested_security_level),
|
||||
group_id_(group_id) {}
|
||||
|
||||
SubLicenseKeySession::~SubLicenseKeySession() {
|
||||
for (SubLicenseSessionMap::iterator oec_session =
|
||||
sub_license_oec_sessions_.begin();
|
||||
oec_session != sub_license_oec_sessions_.end(); oec_session++) {
|
||||
metrics_->oemcrypto_close_session_.Increment(
|
||||
OEMCrypto_CloseSession(oec_session->second));
|
||||
}
|
||||
sub_license_oec_sessions_.clear();
|
||||
}
|
||||
|
||||
// GenerateDerivedKeys is called for each open oemcrypto session and is only
|
||||
// called once.
|
||||
bool SubLicenseKeySession::GenerateDerivedKeys(const std::string& message,
|
||||
const std::string& session_key) {
|
||||
std::string mac_deriv_message;
|
||||
std::string enc_deriv_message;
|
||||
GenerateMacContext(message, &mac_deriv_message);
|
||||
GenerateEncryptContext(message, &enc_deriv_message);
|
||||
|
||||
for (SubLicenseSessionMap::iterator it = sub_license_oec_sessions_.begin();
|
||||
it != sub_license_oec_sessions_.end(); it++) {
|
||||
LOGV("GenerateDerivedKeys: id=%ld", (uint32_t)it->second);
|
||||
OEMCryptoResult sts;
|
||||
M_TIME(sts = OEMCrypto_DeriveKeysFromSessionKey(
|
||||
it->second, reinterpret_cast<const uint8_t*>(session_key.data()),
|
||||
session_key.size(),
|
||||
reinterpret_cast<const uint8_t*>(mac_deriv_message.data()),
|
||||
mac_deriv_message.size(),
|
||||
reinterpret_cast<const uint8_t*>(enc_deriv_message.data()),
|
||||
enc_deriv_message.size()),
|
||||
metrics_, oemcrypto_derive_keys_from_session_key_, sts);
|
||||
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
LOGE("GenerateDerivedKeys: OEMCrypto_DeriveKeysFromSessionKey err=%d",
|
||||
sts);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
OEMCryptoResult SubLicenseKeySession::LoadKeys(
|
||||
const std::string& message, const std::string& signature,
|
||||
const std::string& mac_key_iv, const std::string& mac_key,
|
||||
const std::vector<CryptoKey>& keys,
|
||||
const std::string& provider_session_token, CdmCipherMode* cipher_mode,
|
||||
const std::string& srm_requirement) {
|
||||
if (state_ == kInitializing) {
|
||||
state_ = kInitialLicenseLoaded;
|
||||
keys_ = keys;
|
||||
OEMCryptoResult sts =
|
||||
DoLoadKeys(message, signature, mac_key_iv, mac_key, keys,
|
||||
provider_session_token, cipher_mode, srm_requirement);
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
state_ = kInitialLicenseFailed;
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
return DoSubLicenseLoadKeys(message, signature, mac_key_iv, mac_key, keys[0],
|
||||
provider_session_token, cipher_mode,
|
||||
srm_requirement);
|
||||
}
|
||||
|
||||
OEMCryptoResult SubLicenseKeySession::SelectKey(const std::string& key_id,
|
||||
CdmCipherMode cipher_mode) {
|
||||
for (size_t i = 0; i < keys_.size(); ++i) {
|
||||
if (keys_[i].key_id() == key_id) {
|
||||
cached_sub_session_key_id_ = keys_[i].sub_session_key_id();
|
||||
if (keys_[i].cipher_mode() != cipher_mode) {
|
||||
SubLicenseSessionMap::iterator it =
|
||||
sub_license_oec_sessions_.find(cached_sub_session_key_id_);
|
||||
if (it == sub_license_oec_sessions_.end()) {
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
|
||||
OEMCryptoResult status = OEMCrypto_SUCCESS;
|
||||
M_TIME(status = OEMCrypto_SelectKey(
|
||||
it->second,
|
||||
reinterpret_cast<const uint8_t*>(keys_[i].key_id().data()),
|
||||
keys_[i].key_id().size(),
|
||||
ToOEMCryptoCipherMode(cipher_mode)),
|
||||
metrics_, oemcrypto_select_key_, status);
|
||||
if (OEMCrypto_SUCCESS != status) {
|
||||
return status;
|
||||
}
|
||||
keys_[i].set_cipher_mode(cipher_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult SubLicenseKeySession::Decrypt(
|
||||
const CdmDecryptionParameters& params,
|
||||
OEMCrypto_DestBufferDesc& buffer_descriptor,
|
||||
OEMCrypto_CENCEncryptPatternDesc& pattern_descriptor) {
|
||||
SubLicenseSessionMap::iterator it =
|
||||
sub_license_oec_sessions_.find(cached_sub_session_key_id_);
|
||||
if (it == sub_license_oec_sessions_.end()) {
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
OEMCryptoResult sts;
|
||||
M_TIME(sts = OEMCrypto_DecryptCENC(
|
||||
it->second, params.encrypt_buffer, params.encrypt_length,
|
||||
params.is_encrypted, &(*params.iv).front(), params.block_offset,
|
||||
&buffer_descriptor, &pattern_descriptor, params.subsample_flags),
|
||||
metrics_, oemcrypto_decrypt_cenc_, sts,
|
||||
metrics::Pow2Bucket(params.encrypt_length));
|
||||
return sts;
|
||||
}
|
||||
|
||||
OEMCryptoResult SubLicenseKeySession::ResetCryptoSessions() {
|
||||
for (SubLicenseSessionMap::iterator it = sub_license_oec_sessions_.begin();
|
||||
it != sub_license_oec_sessions_.end(); it++) {
|
||||
OEMCryptoResult sts = OEMCrypto_CloseSession(it->second);
|
||||
metrics_->oemcrypto_close_session_.Increment(sts);
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
return sts;
|
||||
}
|
||||
sts = OEMCrypto_OpenSession(&it->second, requested_security_level_);
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
return sts;
|
||||
}
|
||||
M_TIME(sts = OEMCrypto_LoadDeviceRSAKey(
|
||||
it->second,
|
||||
reinterpret_cast<const uint8_t*>(
|
||||
wrapped_private_device_key_.data()),
|
||||
wrapped_private_device_key_.size()),
|
||||
metrics_, oemcrypto_load_device_rsa_key_, sts);
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult SubLicenseKeySession::DoLoadKeys(
|
||||
const std::string& message, const std::string& signature,
|
||||
const std::string& mac_key_iv, const std::string& mac_key,
|
||||
const std::vector<CryptoKey>& keys,
|
||||
const std::string& provider_session_token, CdmCipherMode* cipher_mode,
|
||||
const std::string& srm_requirement) {
|
||||
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
|
||||
bool valid_mac_keys =
|
||||
mac_key.length() >= MAC_KEY_SIZE && mac_key_iv.length() >= KEY_IV_SIZE;
|
||||
OEMCrypto_Substring enc_mac_key =
|
||||
GetSubstring(message, mac_key, !valid_mac_keys);
|
||||
OEMCrypto_Substring enc_mac_key_iv =
|
||||
GetSubstring(message, mac_key_iv, !valid_mac_keys);
|
||||
if (!valid_mac_keys) LOGV("CryptoSession::LoadKeys: enc_mac_key not set");
|
||||
|
||||
OEMCrypto_Substring pst = GetSubstring(message, provider_session_token);
|
||||
OEMCrypto_Substring srm_req = GetSubstring(message, srm_requirement);
|
||||
|
||||
for (size_t i = 0; i < keys.size(); i++) {
|
||||
OEMCrypto_KeyObject key_object;
|
||||
const CryptoKey& key_data = keys[i];
|
||||
key_object.key_id = GetSubstring(message, key_data.key_id());
|
||||
key_object.key_data_iv = GetSubstring(message, key_data.key_data_iv());
|
||||
key_object.key_data = GetSubstring(message, key_data.key_data());
|
||||
bool has_key_control = key_data.HasKeyControl();
|
||||
key_object.key_control_iv =
|
||||
GetSubstring(message, key_data.key_control_iv(), !has_key_control);
|
||||
key_object.key_control =
|
||||
GetSubstring(message, key_data.key_control(), !has_key_control);
|
||||
if (!has_key_control) {
|
||||
LOGE("For key %s: XXX key has no control block. size=%d",
|
||||
key_data.key_id().c_str(), key_data.key_control().size());
|
||||
}
|
||||
OEMCryptoCipherMode oem_cipher_mode =
|
||||
ToOEMCryptoCipherMode(key_data.cipher_mode());
|
||||
|
||||
// TODO(jfore): Does returning the cipher mode serve any purpose?
|
||||
// If not drop.
|
||||
*cipher_mode = key_data.cipher_mode();
|
||||
|
||||
SubLicenseSessionMap::iterator oec_session_id =
|
||||
sub_license_oec_sessions_.find(key_data.sub_session_key_id());
|
||||
if (oec_session_id == sub_license_oec_sessions_.end()) {
|
||||
LOGE("CryptoSession::LoadKeys: Unrecognized sub session %s",
|
||||
key_data.sub_session_key_id().c_str());
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
|
||||
OEMCryptoResult sts;
|
||||
M_TIME(sts = OEMCrypto_LoadKeys_Back_Compat(
|
||||
oec_session_id->second, msg, message.size(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
signature.size(), enc_mac_key_iv, enc_mac_key, 1, &key_object,
|
||||
pst, srm_req, OEMCrypto_ContentLicense, &oem_cipher_mode),
|
||||
metrics_, oemcrypto_load_keys_, sts);
|
||||
|
||||
if (sts != OEMCrypto_SUCCESS) {
|
||||
return sts;
|
||||
}
|
||||
|
||||
M_TIME(sts = OEMCrypto_SelectKey(
|
||||
oec_session_id->second,
|
||||
reinterpret_cast<const uint8_t*>(key_data.key_id().data()),
|
||||
key_data.key_id().size(),
|
||||
ToOEMCryptoCipherMode(key_data.cipher_mode())),
|
||||
metrics_, oemcrypto_select_key_, sts);
|
||||
|
||||
if (sts != OEMCrypto_SUCCESS) {
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
keys_ = keys;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult SubLicenseKeySession::DoSubLicenseLoadKeys(
|
||||
const std::string& message, const std::string& signature,
|
||||
const std::string& mac_key_iv, const std::string& mac_key,
|
||||
const CryptoKey& key, const std::string& provider_session_token,
|
||||
CdmCipherMode*, const std::string& srm_requirement) {
|
||||
SubLicenseSessionMap::iterator it = sub_license_oec_sessions_.end();
|
||||
size_t key_index = 0;
|
||||
for (; key_index < keys_.size(); key_index++) {
|
||||
if (keys_[key_index].track_label() == key.track_label()) {
|
||||
it =
|
||||
sub_license_oec_sessions_.find(keys_[key_index].sub_session_key_id());
|
||||
CryptoKey tmp = key;
|
||||
tmp.set_sub_session_key_id(keys_[key_index].sub_session_key_id());
|
||||
tmp.set_sub_session_key(keys_[key_index].sub_session_key());
|
||||
keys_[key_index] = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it == sub_license_oec_sessions_.end()) {
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
LOGV("GenerateDerivedKeys: id=%ld", (uint32_t)it->second);
|
||||
|
||||
std::string mac_deriv_message;
|
||||
std::string enc_deriv_message;
|
||||
GenerateMacContext(group_id_ + message.c_str(), &mac_deriv_message);
|
||||
GenerateEncryptContext(group_id_ + message.c_str(), &enc_deriv_message);
|
||||
|
||||
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
|
||||
bool valid_mac_keys =
|
||||
mac_key.length() >= MAC_KEY_SIZE && mac_key_iv.length() >= KEY_IV_SIZE;
|
||||
OEMCrypto_Substring enc_mac_key =
|
||||
GetSubstring(message, mac_key, !valid_mac_keys);
|
||||
OEMCrypto_Substring enc_mac_key_iv =
|
||||
GetSubstring(message, mac_key_iv, !valid_mac_keys);
|
||||
if (!valid_mac_keys) LOGV("CryptoSession::LoadKeys: enc_mac_key not set");
|
||||
|
||||
OEMCrypto_Substring pst = GetSubstring(message, provider_session_token);
|
||||
OEMCrypto_Substring srm_req = GetSubstring(message, srm_requirement);
|
||||
|
||||
OEMCryptoResult sts;
|
||||
const std::string& sub_session_key = keys_[key_index].sub_session_key();
|
||||
LOGV("ssksize = %d", sub_session_key.size());
|
||||
|
||||
M_TIME(
|
||||
sts = OEMCrypto_DeriveKeysFromSessionKey(
|
||||
it->second, reinterpret_cast<const uint8_t*>(sub_session_key.data()),
|
||||
sub_session_key.size(),
|
||||
reinterpret_cast<const uint8_t*>(mac_deriv_message.data()),
|
||||
mac_deriv_message.size(),
|
||||
reinterpret_cast<const uint8_t*>(enc_deriv_message.data()),
|
||||
enc_deriv_message.size()),
|
||||
metrics_, oemcrypto_derive_keys_from_session_key_, sts);
|
||||
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
LOGE("GenerateDerivedKeys: OEMCrypto_DeriveKeysFromSessionKey err=%d", sts);
|
||||
return sts;
|
||||
}
|
||||
|
||||
OEMCrypto_KeyObject key_object;
|
||||
key_object.key_id = GetSubstring(message, keys_[key_index].key_id());
|
||||
key_object.key_data_iv =
|
||||
GetSubstring(message, keys_[key_index].key_data_iv());
|
||||
key_object.key_data = GetSubstring(message, keys_[key_index].key_data());
|
||||
bool has_key_control = key.HasKeyControl();
|
||||
key_object.key_control_iv = GetSubstring(
|
||||
message, keys_[key_index].key_control_iv(), !has_key_control);
|
||||
key_object.key_control =
|
||||
GetSubstring(message, keys_[key_index].key_control(), !has_key_control);
|
||||
OEMCryptoCipherMode oem_cipher_mode =
|
||||
ToOEMCryptoCipherMode(keys_[key_index].cipher_mode());
|
||||
|
||||
M_TIME(sts = OEMCrypto_LoadKeys_Back_Compat(
|
||||
it->second, msg, message.size(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
signature.size(), enc_mac_key_iv, enc_mac_key, 1, &key_object, pst,
|
||||
srm_req, OEMCrypto_ContentLicense, &oem_cipher_mode),
|
||||
metrics_, oemcrypto_load_keys_, sts);
|
||||
|
||||
if (sts != OEMCrypto_SUCCESS) {
|
||||
return sts;
|
||||
}
|
||||
|
||||
M_TIME(sts = OEMCrypto_SelectKey(
|
||||
it->second,
|
||||
reinterpret_cast<const uint8_t*>(keys_[key_index].key_id().data()),
|
||||
keys_[key_index].key_id().size(),
|
||||
ToOEMCryptoCipherMode(keys_[key_index].cipher_mode())),
|
||||
metrics_, oemcrypto_select_key_, sts);
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
Reference in New Issue
Block a user