Merge changes Ic23e2e48,I5d25844b

* changes:
  Google-style override & virtual
  Remove Sub-Licenses and Sub-Sessions
This commit is contained in:
John Bruce
2018-12-07 00:35:51 +00:00
committed by Android (Google) Code Review
40 changed files with 116 additions and 832 deletions

View File

@@ -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:

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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