Source release v3.4.1
This commit is contained in:
@@ -48,17 +48,41 @@ using video_widevine::ClientIdentification_NameValue;
|
||||
using video_widevine::DrmDeviceCertificate;
|
||||
using video_widevine::EncryptedClientIdentification;
|
||||
using video_widevine::License;
|
||||
using video_widevine::License_KeyContainer;
|
||||
using video_widevine::LicenseError;
|
||||
using video_widevine::LicenseIdentification;
|
||||
using video_widevine::LicenseRequest;
|
||||
using video_widevine::LicenseRequest_ContentIdentification;
|
||||
using video_widevine::LicenseRequest_ContentIdentification_CencDeprecated;
|
||||
using video_widevine::LicenseRequest_ContentIdentification_WebmDeprecated;
|
||||
using video_widevine::LicenseRequest_ContentIdentification_ExistingLicense;
|
||||
using video_widevine::LicenseRequest_ContentIdentification_WebmDeprecated;
|
||||
using video_widevine::License_KeyContainer;
|
||||
using video_widevine::SignedDrmDeviceCertificate;
|
||||
using video_widevine::SignedMessage;
|
||||
|
||||
static std::vector<CryptoKey> ExtractSubSessionKeys(const License& license) {
|
||||
std::vector<CryptoKey> key_array;
|
||||
|
||||
// Extract sub session key(s)
|
||||
for (int i = 0; i < license.key_size(); ++i) {
|
||||
CryptoKey key;
|
||||
switch (license.key(i).type()) {
|
||||
case License_KeyContainer::SUB_SESSION:
|
||||
key.set_key_data(license.key(i).key());
|
||||
key.set_key_data_iv(license.key(i).iv());
|
||||
key.set_key_id(license.key(i).id());
|
||||
key.set_track_label(license.key(i).track_label());
|
||||
key_array.push_back(key);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Ignore all but SUB_SESSION key types.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key_array;
|
||||
}
|
||||
|
||||
static std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
||||
std::vector<CryptoKey> key_array;
|
||||
|
||||
@@ -87,6 +111,7 @@ static std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
||||
if (license.has_protection_scheme()) {
|
||||
four_cc = license.protection_scheme();
|
||||
}
|
||||
key.set_track_label(license.key(i).track_label());
|
||||
switch (four_cc) {
|
||||
// b/30713238: Android N assumed that the "protection scheme" Four
|
||||
// CC code, after being extracted from the protobuf, was host byte
|
||||
@@ -115,11 +140,28 @@ static std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Ignore SIGNING key types as they are not content related
|
||||
// Ignore SIGNING and SUB_SESSION key types as they are not content
|
||||
// related.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CryptoKey> sub_session_keys = ExtractSubSessionKeys(license);
|
||||
// Match the track label from the key arrays and add sub_license_key_id to
|
||||
// the content key array.
|
||||
LOGI("Received %d subsession keys", sub_session_keys.size());
|
||||
if (!sub_session_keys.empty()) {
|
||||
for (int i = 0; i < key_array.size(); ++i) {
|
||||
if (key_array[i].track_label().empty()) continue;
|
||||
for (int x = 0; x < sub_session_keys.size(); ++x) {
|
||||
if (sub_session_keys[x].track_label() == key_array[i].track_label()) {
|
||||
key_array[i].set_sub_session_key_id(sub_session_keys[x].key_id());
|
||||
key_array[i].set_sub_session_key(sub_session_keys[x].key_data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return key_array;
|
||||
}
|
||||
|
||||
@@ -221,8 +263,8 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
|
||||
status = PrepareClientId(app_parameters, &license_request);
|
||||
if (NO_ERROR != status) return status;
|
||||
|
||||
status = PrepareContentId(init_data, license_type, request_id,
|
||||
&license_request);
|
||||
status =
|
||||
PrepareContentId(init_data, license_type, request_id, &license_request);
|
||||
if (NO_ERROR != status) return status;
|
||||
|
||||
license_request.set_type(LicenseRequest::NEW);
|
||||
@@ -237,6 +279,37 @@ 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.ExtractEmbeddedKeys();
|
||||
for (int 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)) {
|
||||
return LICENSE_REQUEST_NONCE_GENERATION_ERROR;
|
||||
}
|
||||
if (exists) {
|
||||
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;
|
||||
}
|
||||
|
||||
LicenseRequest::SubSessionData* sub_session_data =
|
||||
license_request.add_sub_session_data();
|
||||
sub_session_data->set_sub_session_key_id(
|
||||
embedded_key_data[i].sub_session_key_id());
|
||||
sub_session_data->set_nonce(nonce);
|
||||
sub_session_data->set_track_label(keyc.track_label());
|
||||
}
|
||||
}
|
||||
|
||||
license_request.set_protocol_version(video_widevine::VERSION_2_1);
|
||||
|
||||
// License request is complete. Serialize it.
|
||||
@@ -438,7 +511,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
LOGE("CdmLicense::HandleKeyResponse: no session keys present");
|
||||
return SESSION_KEYS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!crypto_session_->GenerateDerivedKeys(key_request_,
|
||||
signed_response.session_key()))
|
||||
return GENERATE_DERIVED_KEYS_ERROR;
|
||||
@@ -492,7 +564,8 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
renew_with_client_id_ = license.policy().always_include_client_id();
|
||||
}
|
||||
|
||||
CdmResponseType resp = crypto_session_->LoadKeys(
|
||||
CdmResponseType resp = NO_ERROR;
|
||||
resp = crypto_session_->LoadKeys(
|
||||
signed_response.msg(), signed_response.signature(), mac_key_iv, mac_key,
|
||||
key_array, provider_session_token_);
|
||||
|
||||
@@ -587,6 +660,45 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
|
||||
}
|
||||
}
|
||||
|
||||
CdmResponseType CdmLicense::HandleSubLicense(
|
||||
const InitializationData& init_data) {
|
||||
std::vector<video_widevine::SubLicense> subkeys =
|
||||
init_data.ExtractEmbeddedKeys();
|
||||
std::set<KeyId> loaded_keys;
|
||||
// Build a license with the rotated keys.
|
||||
License license;
|
||||
for (int 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;
|
||||
}
|
||||
std::vector<CryptoKey> keys;
|
||||
keys.resize(1);
|
||||
keys[0].set_key_id(keyc.id());
|
||||
keys[0].set_key_data(keyc.key());
|
||||
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());
|
||||
CdmResponseType result = crypto_session_->LoadKeys(
|
||||
sm.msg(), sm.signature(), std::string(), std::string(), keys,
|
||||
std::string());
|
||||
if (result != KEY_ADDED) {
|
||||
return result;
|
||||
}
|
||||
loaded_keys.insert(keyc.id());
|
||||
*license.add_key() = keyc;
|
||||
}
|
||||
loaded_keys_.swap(loaded_keys);
|
||||
policy_engine_->UpdateLicenseKeys(license);
|
||||
|
||||
return KEY_MESSAGE;
|
||||
}
|
||||
|
||||
bool CdmLicense::RestoreOfflineLicense(
|
||||
const CdmKeyMessage& license_request,
|
||||
const CdmKeyResponse& license_response,
|
||||
@@ -994,8 +1106,7 @@ CdmResponseType CdmLicense::PrepareContentId(
|
||||
|
||||
template <typename T>
|
||||
bool CdmLicense::SetTypeAndId(CdmLicenseType license_type,
|
||||
const std::string& request_id,
|
||||
T* content_id) {
|
||||
const std::string& request_id, T* content_id) {
|
||||
switch (license_type) {
|
||||
case kLicenseTypeOffline:
|
||||
content_id->set_license_type(video_widevine::OFFLINE);
|
||||
|
||||
Reference in New Issue
Block a user