Source release 16.3.0

This commit is contained in:
John W. Bruce
2020-07-24 14:30:03 -07:00
parent b830b1d1fb
commit 160df9f57a
74 changed files with 4632 additions and 2561 deletions

View File

@@ -708,12 +708,10 @@ uint8_t CryptoSession::GetSecurityPatchLevel() {
}
CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
LOGD(
"Opening crypto session: requested_security_level: "
"requested_security_level = %s",
requested_security_level == kLevel3
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
LOGD("Opening crypto session: requested_security_level = %s",
requested_security_level == kLevel3
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
RETURN_IF_UNINITIALIZED(UNKNOWN_ERROR);
if (open_) return NO_ERROR;
@@ -750,12 +748,13 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
open_ = true;
// Get System ID and save it.
if (GetSystemIdInternal(&system_id_) == NO_ERROR) {
result = GetSystemIdInternal(&system_id_);
if (result == NO_ERROR) {
metrics_->crypto_session_system_id_.Record(system_id_);
} else {
LOGE("Failed to fetch system ID");
metrics_->crypto_session_system_id_.SetError(LOAD_SYSTEM_ID_ERROR);
return LOAD_SYSTEM_ID_ERROR;
metrics_->crypto_session_system_id_.SetError(result);
return result;
}
// Set up request ID
@@ -802,35 +801,33 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
CdmSecurityLevel security_level = GetSecurityLevel();
if (security_level == kSecurityLevelL1 ||
security_level == kSecurityLevelL3) {
{
// This block cannot use |WithStaticFieldWriteLock| because it needs
// to unlock the lock partway through.
LOGV("Static field write lock: Open() initializing usage table");
std::unique_lock<shared_mutex> auto_lock(static_field_mutex_);
// This block cannot use |WithStaticFieldWriteLock| because it needs
// to unlock the lock partway through.
LOGV("Static field write lock: Open() initializing usage table");
std::unique_lock<shared_mutex> auto_lock(static_field_mutex_);
UsageTableHeader** header = security_level == kSecurityLevelL1
? &usage_table_header_l1_
: &usage_table_header_l3_;
if (*header == nullptr) {
*header = new UsageTableHeader();
// Ignore errors since we do not know when a session is opened,
// if it is intended to be used for offline/usage session related
// or otherwise.
auto_lock.unlock();
bool is_usage_table_header_inited =
(*header)->Init(security_level, this);
auto_lock.lock();
if (!is_usage_table_header_inited) {
delete *header;
*header = nullptr;
usage_table_header_ = nullptr;
return NO_ERROR;
}
UsageTableHeader** header = security_level == kSecurityLevelL1
? &usage_table_header_l1_
: &usage_table_header_l3_;
if (*header == nullptr) {
*header = new UsageTableHeader();
// Ignore errors since we do not know when a session is opened,
// if it is intended to be used for offline/usage session related
// or otherwise.
auto_lock.unlock();
bool is_usage_table_header_inited =
(*header)->Init(security_level, this);
auto_lock.lock();
if (!is_usage_table_header_inited) {
delete *header;
*header = nullptr;
usage_table_header_ = nullptr;
return NO_ERROR;
}
usage_table_header_ = *header;
metrics_->usage_table_header_initial_size_.Record((*header)->size());
}
}
usage_table_header_ = *header;
metrics_->usage_table_header_initial_size_.Record((*header)->size());
} // End |static_field_mutex_| block.
}
} else {
metrics_->oemcrypto_usage_table_support_.SetError(result);
@@ -943,7 +940,7 @@ CdmResponseType CryptoSession::LoadKeys(
update_usage_table_after_close_session_ = true;
return KEY_ADDED;
case OEMCrypto_ERROR_TOO_MANY_KEYS:
return INSUFFICIENT_CRYPTO_RESOURCES_4;
return INSUFFICIENT_CRYPTO_RESOURCES;
case OEMCrypto_ERROR_USAGE_TABLE_UNRECOVERABLE:
// Handle vendor specific error
return NEED_PROVISIONING;
@@ -983,7 +980,7 @@ CdmResponseType CryptoSession::LoadLicense(const std::string& signed_message,
return LOAD_LICENSE_ERROR;
case OEMCrypto_ERROR_TOO_MANY_KEYS:
LOGE("Too many keys in license");
return INSUFFICIENT_CRYPTO_RESOURCES_4;
return INSUFFICIENT_CRYPTO_RESOURCES;
default:
break;
}
@@ -1185,16 +1182,15 @@ CdmResponseType CryptoSession::PrepareAndSignProvisioningRequest(
CdmResponseType CryptoSession::LoadEntitledContentKeys(
const std::vector<CryptoKey>& key_array) {
OEMCryptoResult sts;
WithOecSessionLock("LoadEntitledContentKeys", [&] {
sts = key_session_->LoadEntitledContentKeys(key_array);
});
const OEMCryptoResult sts = WithOecSessionLock(
"LoadEntitledContentKeys",
[&] { return key_session_->LoadEntitledContentKeys(key_array); });
switch (sts) {
case OEMCrypto_SUCCESS:
return KEY_ADDED;
case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES:
return INSUFFICIENT_CRYPTO_RESOURCES_6;
return INSUFFICIENT_CRYPTO_RESOURCES;
case OEMCrypto_ERROR_INVALID_CONTEXT:
return NOT_AN_ENTITLEMENT_SESSION;
case OEMCrypto_KEY_NOT_ENTITLED:
@@ -1243,39 +1239,46 @@ CdmResponseType CryptoSession::LoadCertificatePrivateKey(
// Private.
CdmResponseType CryptoSession::SelectKey(const std::string& key_id,
CdmCipherMode cipher_mode) {
OEMCryptoResult sts;
WithOecSessionLock(
"SelectKey", [&] { sts = key_session_->SelectKey(key_id, cipher_mode); });
const OEMCryptoResult sts = WithOecSessionLock("SelectKey", [&] {
return key_session_->SelectKey(key_id, cipher_mode);
});
switch (sts) {
// SelectKey errors.
case OEMCrypto_SUCCESS:
return NO_ERROR;
case OEMCrypto_ERROR_KEY_EXPIRED:
return NEED_KEY;
case OEMCrypto_ERROR_INSUFFICIENT_HDCP:
return INSUFFICIENT_OUTPUT_PROTECTION;
case OEMCrypto_ERROR_ANALOG_OUTPUT:
return ANALOG_OUTPUT_ERROR;
case OEMCrypto_ERROR_INVALID_SESSION:
return INVALID_SESSION_1;
case OEMCrypto_ERROR_NO_DEVICE_KEY:
return NO_DEVICE_KEY_1;
case OEMCrypto_ERROR_NO_CONTENT_KEY:
return NO_CONTENT_KEY_2;
case OEMCrypto_KEY_NOT_LOADED: // obsolete.
return NO_CONTENT_KEY_3;
case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES:
return INSUFFICIENT_CRYPTO_RESOURCES_2;
case OEMCrypto_ERROR_UNKNOWN_FAILURE:
return UNKNOWN_SELECT_KEY_ERROR_1;
case OEMCrypto_ERROR_SESSION_LOST_STATE:
return SESSION_LOST_STATE_ERROR;
case OEMCrypto_ERROR_SYSTEM_INVALIDATED:
return SYSTEM_INVALIDATED_ERROR;
case OEMCrypto_ERROR_CONTROL_INVALID:
case OEMCrypto_ERROR_KEYBOX_INVALID:
default:
return UNKNOWN_SELECT_KEY_ERROR_2;
case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES:
return INSUFFICIENT_CRYPTO_RESOURCES;
case OEMCrypto_ERROR_UNKNOWN_FAILURE:
return UNKNOWN_SELECT_KEY_ERROR_1;
case OEMCrypto_ERROR_ANALOG_OUTPUT:
return ANALOG_OUTPUT_ERROR;
case OEMCrypto_ERROR_INSUFFICIENT_HDCP:
return INSUFFICIENT_OUTPUT_PROTECTION;
// LoadEntitledContentKeys errors.
// |key_session_| may make calls to OEMCrypto_LoadEntitledContentKeys
// if the key selected has not yet been loaded.
case OEMCrypto_ERROR_INVALID_CONTEXT:
return NOT_AN_ENTITLEMENT_SESSION;
case OEMCrypto_KEY_NOT_ENTITLED:
return NO_MATCHING_ENTITLEMENT_KEY;
// Obsolete errors.
case OEMCrypto_KEY_NOT_LOADED:
return NO_CONTENT_KEY_3;
// Catch all else.
default:
return MapOEMCryptoResult(sts, UNKNOWN_SELECT_KEY_ERROR_2, "SelectKey");
}
}
@@ -1530,7 +1533,7 @@ CdmResponseType CryptoSession::Decrypt(
case OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION:
return NO_ERROR;
case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES:
return INSUFFICIENT_CRYPTO_RESOURCES_5;
return INSUFFICIENT_CRYPTO_RESOURCES;
case OEMCrypto_ERROR_KEY_EXPIRED:
return NEED_KEY;
case OEMCrypto_ERROR_INVALID_SESSION:
@@ -2005,6 +2008,11 @@ bool CryptoSession::GetMaximumUsageTableEntries(SecurityLevel security_level,
metrics_->oemcrypto_maximum_usage_table_header_size_.Record(
*number_of_entries);
if (*number_of_entries == 0) {
// Special value, indicating that the table size is not directly
// limited.
return true;
}
return *number_of_entries >= kMinimumUsageTableEntriesSupported;
}
@@ -2349,18 +2357,20 @@ CdmResponseType CryptoSession::GetUsageSupportType(
}
CdmResponseType CryptoSession::CreateUsageTableHeader(
SecurityLevel requested_security_level,
CdmUsageTableHeader* usage_table_header) {
LOGV("Creating usage table header: id = %u", oec_session_id_);
LOGV("Creating usage table header: requested_security_level = %s",
requested_security_level == kLevel3
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
RETURN_IF_NULL(usage_table_header, PARAMETER_NULL);
usage_table_header->resize(kEstimatedInitialUsageTableHeader);
size_t usage_table_header_size = usage_table_header->size();
OEMCryptoResult result;
WithOecWriteLock("CreateUsageTableHeader Attempt 1", [&] {
result = OEMCrypto_CreateUsageTableHeader(
requested_security_level_,
requested_security_level,
reinterpret_cast<uint8_t*>(
const_cast<char*>(usage_table_header->data())),
&usage_table_header_size);
@@ -2371,7 +2381,7 @@ CdmResponseType CryptoSession::CreateUsageTableHeader(
usage_table_header->resize(usage_table_header_size);
WithOecWriteLock("CreateUsageTableHeader Attempt 2", [&] {
result = OEMCrypto_CreateUsageTableHeader(
requested_security_level_,
requested_security_level,
reinterpret_cast<uint8_t*>(
const_cast<char*>(usage_table_header->data())),
&usage_table_header_size);
@@ -2379,22 +2389,28 @@ CdmResponseType CryptoSession::CreateUsageTableHeader(
});
}
if (result == OEMCrypto_SUCCESS) {
usage_table_header->resize(usage_table_header_size);
switch (result) {
case OEMCrypto_SUCCESS:
usage_table_header->resize(usage_table_header_size);
return NO_ERROR;
default:
return MapOEMCryptoResult(result, CREATE_USAGE_TABLE_ERROR,
"CreateUsageTableHeader");
}
return MapOEMCryptoResult(result, CREATE_USAGE_TABLE_ERROR,
"CreateUsageTableHeader");
}
CdmResponseType CryptoSession::LoadUsageTableHeader(
SecurityLevel requested_security_level,
const CdmUsageTableHeader& usage_table_header) {
LOGV("Loading usage table header: id = %u", oec_session_id_);
LOGV("Loading usage table header: requested_security_level = %s",
requested_security_level == kLevel3
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
OEMCryptoResult result;
WithOecWriteLock("LoadUsageTableHeader", [&] {
result = OEMCrypto_LoadUsageTableHeader(
requested_security_level_,
requested_security_level,
reinterpret_cast<const uint8_t*>(usage_table_header.data()),
usage_table_header.size());
metrics_->oemcrypto_load_usage_table_header_.Increment(result);
@@ -2427,6 +2443,48 @@ CdmResponseType CryptoSession::LoadUsageTableHeader(
}
}
CdmResponseType CryptoSession::ShrinkUsageTableHeader(
SecurityLevel requested_security_level, uint32_t new_entry_count,
CdmUsageTableHeader* usage_table_header) {
LOGV("Shrinking usage table header: requested_security_level = %s",
requested_security_level == kLevel3
? QUERY_VALUE_SECURITY_LEVEL_L3.c_str()
: QUERY_VALUE_SECURITY_LEVEL_DEFAULT.c_str());
RETURN_IF_NULL(usage_table_header, PARAMETER_NULL);
size_t usage_table_header_len = 0;
OEMCryptoResult result;
WithOecWriteLock("ShrinkUsageTableHeader Attempt 1", [&] {
result = OEMCrypto_ShrinkUsageTableHeader(requested_security_level,
new_entry_count, nullptr,
&usage_table_header_len);
metrics_->oemcrypto_shrink_usage_table_header_.Increment(result);
});
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
usage_table_header->resize(usage_table_header_len);
WithOecWriteLock("ShrinkUsageTableHeader Attempt 2", [&] {
result = OEMCrypto_ShrinkUsageTableHeader(
requested_security_level, new_entry_count,
reinterpret_cast<uint8_t*>(
const_cast<char*>(usage_table_header->data())),
&usage_table_header_len);
metrics_->oemcrypto_shrink_usage_table_header_.Increment(result);
});
}
switch (result) {
case OEMCrypto_SUCCESS:
usage_table_header->resize(usage_table_header_len);
return NO_ERROR;
case OEMCrypto_ERROR_ENTRY_IN_USE:
return SHRINK_USAGE_TABLE_HEADER_ENTRY_IN_USE;
default:
return MapOEMCryptoResult(result, SHRINK_USAGE_TABLE_HEADER_UNKNOWN_ERROR,
"ShrinkUsageTableHeader");
}
}
CdmResponseType CryptoSession::CreateUsageEntry(uint32_t* entry_number) {
LOGV("Creating usage entry: id = %u", oec_session_id_);
@@ -2447,7 +2505,7 @@ CdmResponseType CryptoSession::CreateUsageEntry(uint32_t* entry_number) {
case OEMCrypto_SUCCESS:
return NO_ERROR;
case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES:
return INSUFFICIENT_CRYPTO_RESOURCES_3;
return INSUFFICIENT_CRYPTO_RESOURCES;
case OEMCrypto_ERROR_SESSION_LOST_STATE:
return SESSION_LOST_STATE_ERROR;
case OEMCrypto_ERROR_SYSTEM_INVALIDATED:
@@ -2483,18 +2541,19 @@ CdmResponseType CryptoSession::LoadUsageEntry(
case OEMCrypto_SUCCESS:
case OEMCrypto_WARNING_GENERATION_SKEW:
return NO_ERROR;
case OEMCrypto_ERROR_INVALID_SESSION:
// This case is special, as it could imply that the provided
// session ID is invalid (CDM internal bug), or that the entry
// being loaded is already in use in a different session.
// It is up to the caller to handle this.
return LOAD_USAGE_ENTRY_INVALID_SESSION;
case OEMCrypto_ERROR_GENERATION_SKEW:
return LOAD_USAGE_ENTRY_GENERATION_SKEW;
case OEMCrypto_ERROR_SIGNATURE_FAILURE:
return LOAD_USAGE_ENTRY_SIGNATURE_FAILURE;
case OEMCrypto_ERROR_INSUFFICIENT_RESOURCES:
return INSUFFICIENT_CRYPTO_RESOURCES_3;
case OEMCrypto_ERROR_SESSION_LOST_STATE:
return SESSION_LOST_STATE_ERROR;
case OEMCrypto_ERROR_SYSTEM_INVALIDATED:
return SYSTEM_INVALIDATED_ERROR;
default:
return LOAD_USAGE_ENTRY_UNKNOWN_ERROR;
return MapOEMCryptoResult(result, LOAD_USAGE_ENTRY_UNKNOWN_ERROR,
"LoadUsageEntry");
}
}
@@ -2540,42 +2599,6 @@ CdmResponseType CryptoSession::UpdateUsageEntry(
"UpdateUsageEntry");
}
CdmResponseType CryptoSession::ShrinkUsageTableHeader(
uint32_t new_entry_count, CdmUsageTableHeader* usage_table_header) {
LOGV("Shrinking usage table header: id = %u", oec_session_id_);
RETURN_IF_NULL(usage_table_header, PARAMETER_NULL);
size_t usage_table_header_len = 0;
OEMCryptoResult result;
WithOecWriteLock("ShrinkUsageTableHeader Attempt 1", [&] {
result = OEMCrypto_ShrinkUsageTableHeader(requested_security_level_,
new_entry_count, nullptr,
&usage_table_header_len);
metrics_->oemcrypto_shrink_usage_table_header_.Increment(result);
});
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
usage_table_header->resize(usage_table_header_len);
WithOecWriteLock("ShrinkUsageTableHeader Attempt 2", [&] {
result = OEMCrypto_ShrinkUsageTableHeader(
requested_security_level_, new_entry_count,
reinterpret_cast<uint8_t*>(
const_cast<char*>(usage_table_header->data())),
&usage_table_header_len);
metrics_->oemcrypto_shrink_usage_table_header_.Increment(result);
});
}
if (result == OEMCrypto_SUCCESS) {
usage_table_header->resize(usage_table_header_len);
}
return MapOEMCryptoResult(result, SHRINK_USAGE_TABLER_HEADER_UNKNOWN_ERROR,
"ShrinkUsageTableHeader");
}
CdmResponseType CryptoSession::MoveUsageEntry(uint32_t new_entry_number) {
LOGV("Moving usage entry: id = %u", oec_session_id_);
@@ -2585,8 +2608,15 @@ CdmResponseType CryptoSession::MoveUsageEntry(uint32_t new_entry_number) {
metrics_->oemcrypto_move_entry_.Increment(result);
});
return MapOEMCryptoResult(result, MOVE_USAGE_ENTRY_UNKNOWN_ERROR,
"MoveUsageEntry");
switch (result) {
case OEMCrypto_ERROR_ENTRY_IN_USE:
LOGW("OEMCrypto_MoveEntry failed: Destination index in use: index = %u",
new_entry_number);
return MOVE_USAGE_ENTRY_DESTINATION_IN_USE;
default:
return MapOEMCryptoResult(result, MOVE_USAGE_ENTRY_UNKNOWN_ERROR,
"MoveUsageEntry");
}
}
bool CryptoSession::GetAnalogOutputCapabilities(bool* can_support_output,