Finer-Grained OEMCrypto Locking

(This is a merge of http://go/wvgerrit/72867)

This patch replaces the previous static std::mutexes in CryptoSession
with shared_mutexes, allowing multiple readers to access the resources
they protect. For the shared fields, this means only Initialize(),
Terminate(), and the code that sets up the usage table headers needs
exclusive access. All other CryptoSession code is able to read these
fields in parallel.

For OEMCrypto, the static OEMCrypto lock is joined by a per-session
std::mutex, which are used in concert to enforce the OEMCrypto v15
threading guarantees.

On my machine this results in a noticeable increase in performance for
the parallel unit tests.

Bug: 70889998
Bug: 118584039
Test: CE CDM Unit Tests
Test: Android Unit Tests
Test: Jenkins Tests
Change-Id: Ie6332ae4926ed4f14af897685d37bfe63831b14f
This commit is contained in:
John W. Bruce
2019-02-19 13:58:07 -08:00
parent d925048c35
commit e10ac3b465
2 changed files with 181 additions and 118 deletions

View File

@@ -75,8 +75,8 @@ void DeleteX509Stack(STACK_OF(X509)* stack) {
} // namespace
namespace wvcdm {
std::mutex CryptoSession::static_field_lock_;
std::mutex CryptoSession::oem_crypto_lock_;
shared_mutex CryptoSession::static_field_mutex_;
shared_mutex CryptoSession::oem_crypto_mutex_;
bool CryptoSession::initialized_ = false;
int CryptoSession::session_count_ = 0;
UsageTableHeader* CryptoSession::usage_table_header_l1_ = NULL;
@@ -214,7 +214,7 @@ CdmResponseType CryptoSession::GetProvisioningMethod(
SecurityLevel requested_security_level,
CdmClientTokenType* token_type) {
OEMCrypto_ProvisioningMethod method;
WithOecLock("GetProvisioningMethod", [&] {
WithOecReadLock("GetProvisioningMethod", [&] {
method = OEMCrypto_GetProvisioningMethod(requested_security_level);
});
metrics_->oemcrypto_provisioning_method_.Record(method);
@@ -241,12 +241,12 @@ CdmResponseType CryptoSession::GetProvisioningMethod(
void CryptoSession::Init() {
LOGV("CryptoSession::Init");
WithStaticFieldLock("Init", [&] {
WithStaticFieldWriteLock("Init", [&] {
session_count_ += 1;
if (!initialized_) {
std::string sandbox_id;
OEMCryptoResult sts;
WithOecLock("Init", [&] {
WithOecWriteLock("Init", [&] {
if (Properties::GetSandboxId(&sandbox_id) && !sandbox_id.empty()) {
sts = OEMCrypto_SetSandbox(
reinterpret_cast<const uint8_t*>(sandbox_id.c_str()),
@@ -268,7 +268,7 @@ void CryptoSession::Init() {
void CryptoSession::Terminate() {
LOGV("CryptoSession::Terminate");
WithStaticFieldLock("Terminate", [&] {
WithStaticFieldWriteLock("Terminate", [&] {
LOGV("initialized_=%d, session_count_=%d", initialized_, session_count_);
if (session_count_ > 0) {
session_count_ -= 1;
@@ -277,7 +277,7 @@ void CryptoSession::Terminate() {
}
if (session_count_ > 0 || !initialized_) return;
OEMCryptoResult sts;
WithOecLock("Terminate", [&] {
WithOecWriteLock("Terminate", [&] {
sts = OEMCrypto_Terminate();
});
if (OEMCrypto_SUCCESS != sts) {
@@ -307,7 +307,7 @@ CdmResponseType CryptoSession::GetTokenFromKeybox(std::string* token) {
uint8_t* buf = reinterpret_cast<uint8_t*>(&temp_buffer[0]);
OEMCryptoResult status;
WithOecLock("GetTokenFromKeybox", [&] {
WithOecReadLock("GetTokenFromKeybox", [&] {
M_TIME(
status =
OEMCrypto_GetKeyData(buf, &buf_size, requested_security_level_),
@@ -338,7 +338,7 @@ CdmResponseType CryptoSession::GetTokenFromOemCert(std::string* token) {
while (true) {
size_t buf_size = temp_buffer.size();
uint8_t* buf = reinterpret_cast<uint8_t*>(&temp_buffer[0]);
WithOecLock("GetTokenFromOemCert", [&] {
WithOecSessionLock("GetTokenFromOemCert", [&] {
status = OEMCrypto_GetOEMPublicCertificate(oec_session_id_, buf,
&buf_size);
});
@@ -402,7 +402,7 @@ CdmSecurityLevel CryptoSession::GetSecurityLevel(
}
std::string security_level;
WithOecLock("GetSecurityLevel", [&] {
WithOecReadLock("GetSecurityLevel", [&] {
security_level = OEMCrypto_SecurityLevel(requested_level);
});
@@ -448,14 +448,14 @@ CdmResponseType CryptoSession::GetInternalDeviceUniqueId(
id.resize(id_length);
OEMCryptoResult sts;
WithOecLock("GetInternalDeviceUniqueId Attempt 1", [&] {
WithOecReadLock("GetInternalDeviceUniqueId Attempt 1", [&] {
sts = OEMCrypto_GetDeviceID(&id[0], &id_length, requested_security_level_);
});
// Increment the count of times this method was called.
metrics_->oemcrypto_get_device_id_.Increment(sts);
if (sts == OEMCrypto_ERROR_SHORT_BUFFER) {
id.resize(id_length);
WithOecLock("GetInternalDeviceUniqueId Attempt 2", [&] {
WithOecReadLock("GetInternalDeviceUniqueId Attempt 2", [&] {
sts = OEMCrypto_GetDeviceID(&id[0], &id_length,
requested_security_level_);
});
@@ -494,7 +494,7 @@ CdmResponseType CryptoSession::GetExternalDeviceUniqueId(
size_t id_length = 0;
OEMCryptoResult sts;
WithOecLock("GetExternalDeviceUniqueId", [&] {
WithOecReadLock("GetExternalDeviceUniqueId", [&] {
sts = OEMCrypto_GetDeviceID(NULL, &id_length, requested_security_level_);
});
metrics_->oemcrypto_get_device_id_.Increment(sts);
@@ -538,7 +538,7 @@ bool CryptoSession::GetApiVersion(SecurityLevel security_level,
return false;
}
WithOecLock("GetApiVersion", [&] {
WithOecReadLock("GetApiVersion", [&] {
*version = OEMCrypto_APIVersion(security_level);
});
// Record the version into the metrics.
@@ -758,7 +758,7 @@ CdmResponseType CryptoSession::GetProvisioningId(std::string* provisioning_id) {
uint8_t CryptoSession::GetSecurityPatchLevel() {
uint8_t patch;
WithOecLock("GetSecurityPatchLevel", [&] {
WithOecReadLock("GetSecurityPatchLevel", [&] {
patch = OEMCrypto_Security_Patch_Level(requested_security_level_);
});
metrics_->oemcrypto_security_patch_level_.Record(patch);
@@ -781,15 +781,17 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
OEMCrypto_SESSION sid;
requested_security_level_ = requested_security_level;
OEMCryptoResult sts;
WithOecLock("Open() calling OEMCrypto_OpenSession", [&] {
WithOecWriteLock("Open() calling OEMCrypto_OpenSession", [&] {
sts = OEMCrypto_OpenSession(&sid, requested_security_level);
});
if (sts != OEMCrypto_SUCCESS) {
WithStaticFieldLock("Open() reporting OEMCrypto_OpenSession Failure", [&] {
LOGE("OEMCrypto_Open failed: %d, open sessions: %ld, initialized: %d",
sts, session_count_, (int)initialized_);
});
WithStaticFieldReadLock(
"Open() reporting OEMCrypto_OpenSession Failure",
[&] {
LOGE("OEMCrypto_Open failed: %d, open sessions: %ld, initialized: %d",
sts, session_count_, (int)initialized_);
});
return MapOEMCryptoResult(sts, OPEN_CRYPTO_SESSION_ERROR, "Open");
}
@@ -808,7 +810,7 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
uint64_t request_id_base;
OEMCryptoResult random_sts;
WithOecLock("Open() calling OEMCrypto_GetRandom", [&] {
WithOecReadLock("Open() calling OEMCrypto_GetRandom", [&] {
random_sts = OEMCrypto_GetRandom(
reinterpret_cast<uint8_t*>(&request_id_base), sizeof(request_id_base));
});
@@ -834,10 +836,10 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
if (security_level == kSecurityLevelL1 ||
security_level == kSecurityLevelL3) {
{
// This block cannot use |WithStaticFieldLock| because it needs to
// unlock the lock partway through.
LOGV("Static Field Lock - Open() Initializing Usage Table");
std::unique_lock<std::mutex> auto_lock(static_field_lock_);
// 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_
@@ -866,7 +868,7 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
metrics_->oemcrypto_usage_table_support_.SetError(result);
}
WithOecLock("Open() calling key_session_.reset()", [&] {
WithOecSessionLock("Open() calling key_session_.reset()", [&] {
key_session_.reset(new ContentKeySession(oec_session_id_, metrics_));
});
@@ -880,7 +882,7 @@ void CryptoSession::Close() {
OEMCryptoResult close_sts;
bool update_usage_table = false;
WithOecLock("Close", [&] {
WithOecWriteLock("Close", [&] {
close_sts = OEMCrypto_CloseSession(oec_session_id_);
});
metrics_->oemcrypto_close_session_.Increment(close_sts);
@@ -932,7 +934,7 @@ CdmResponseType CryptoSession::LoadKeys(
CdmResponseType result = KEY_ADDED;
OEMCryptoResult sts;
WithOecLock("LoadKeys", [&] {
WithOecSessionLock("LoadKeys", [&] {
if (key_type == kLicenseKeyTypeEntitlement &&
key_session_->Type() != KeySession::kEntitlement) {
key_session_.reset(new EntitlementKeySession(oec_session_id_, metrics_));
@@ -979,7 +981,7 @@ CdmResponseType CryptoSession::LoadKeys(
CdmResponseType CryptoSession::LoadEntitledContentKeys(
const std::vector<CryptoKey>& key_array) {
OEMCryptoResult sts;
WithOecLock("LoadEntitledContentKeys", [&] {
WithOecSessionLock("LoadEntitledContentKeys", [&] {
sts = key_session_->LoadEntitledContentKeys(key_array);
});
@@ -1009,7 +1011,7 @@ CdmResponseType CryptoSession::LoadCertificatePrivateKey(
size_t buf_size = temp_buffer.size();
uint8_t* buf = reinterpret_cast<uint8_t*>(&temp_buffer[0]);
OEMCryptoResult sts;
WithOecLock(
WithOecSessionLock(
"LoadCertificatePrivateKey() calling OEMCrypto_GetOEMPublicCertificate",
[&] {
sts =
@@ -1018,7 +1020,7 @@ CdmResponseType CryptoSession::LoadCertificatePrivateKey(
metrics_->oemcrypto_get_oem_public_certificate_.Increment(sts);
LOGV("LoadDeviceRSAKey: id=%lu", oec_session_id_);
WithOecLock(
WithOecSessionLock(
"LoadCertificatePrivateKey() calling OEMCrypto_LoadDeviceRSAKey()",
[&] {
M_TIME(sts = OEMCrypto_LoadDeviceRSAKey(
@@ -1050,7 +1052,7 @@ CdmResponseType CryptoSession::RefreshKeys(const std::string& message,
}
LOGV("RefreshKeys: id=%lu", oec_session_id_);
OEMCryptoResult refresh_sts;
WithOecLock("RefreshKeys", [&] {
WithOecSessionLock("RefreshKeys", [&] {
M_TIME(refresh_sts = OEMCrypto_RefreshKeys(
oec_session_id_, msg, message.size(),
reinterpret_cast<const uint8_t*>(signature.data()),
@@ -1067,7 +1069,7 @@ CdmResponseType CryptoSession::RefreshKeys(const std::string& message,
CdmResponseType CryptoSession::SelectKey(const std::string& key_id,
CdmCipherMode cipher_mode) {
OEMCryptoResult sts;
WithOecLock("SelectKey", [&] {
WithOecSessionLock("SelectKey", [&] {
sts = key_session_->SelectKey(key_id, cipher_mode);
});
@@ -1105,7 +1107,7 @@ CdmResponseType CryptoSession::SelectKey(const std::string& key_id,
CdmResponseType CryptoSession::GenerateDerivedKeys(const std::string& message) {
OEMCryptoResult sts;
WithOecLock("GenerateDerivedKeys without session_key", [&] {
WithOecSessionLock("GenerateDerivedKeys without session_key", [&] {
sts = key_session_->GenerateDerivedKeys(message);
});
@@ -1116,7 +1118,7 @@ CdmResponseType CryptoSession::GenerateDerivedKeys(const std::string& message) {
CdmResponseType CryptoSession::GenerateDerivedKeys(
const std::string& message, const std::string& session_key) {
OEMCryptoResult sts;
WithOecLock("GenerateDerivedKeys with session_key", [&] {
WithOecSessionLock("GenerateDerivedKeys with session_key", [&] {
sts = key_session_->GenerateDerivedKeys(message, session_key);
});
@@ -1138,7 +1140,7 @@ CdmResponseType CryptoSession::GenerateSignature(const std::string& message,
// At most two attempts.
// The first attempt may fail due to buffer too short
for (int i = 0; i < 2; ++i) {
WithOecLock("GenerateSignature", [&] {
WithOecSessionLock("GenerateSignature", [&] {
M_TIME(sts = OEMCrypto_GenerateSignature(
oec_session_id_,
reinterpret_cast<const uint8_t*>(message.data()),
@@ -1181,7 +1183,7 @@ CdmResponseType CryptoSession::GenerateRsaSignature(const std::string& message,
// At most two attempts.
// The first attempt may fail due to buffer too short
for (int i = 0; i < 2; ++i) {
WithOecLock("GenerateRsaSignature", [&] {
WithOecSessionLock("GenerateRsaSignature", [&] {
M_TIME(sts = OEMCrypto_GenerateRSASignature(
oec_session_id_,
reinterpret_cast<const uint8_t*>(message.data()),
@@ -1247,7 +1249,7 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
if (!params.is_encrypted &&
params.subsample_flags ==
(OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample)) {
WithOecLock("Decrypt() calling CopyBuffer", [&] {
WithOecSessionLock("Decrypt() calling CopyBuffer", [&] {
M_TIME(sts = OEMCrypto_CopyBuffer(oec_session_id_, params.encrypt_buffer,
params.encrypt_length,
&buffer_descriptor,
@@ -1279,7 +1281,7 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
if (result != NO_ERROR) return result;
}
WithOecLock("Decrypt() calling key_session_->Decrypt()", [&] {
WithOecSessionLock("Decrypt() calling key_session_->Decrypt()", [&] {
sts = key_session_->Decrypt(params, buffer_descriptor,
pattern_descriptor);
});
@@ -1348,7 +1350,7 @@ bool CryptoSession::UsageInformationSupport(SecurityLevel security_level,
return false;
}
WithOecLock("UsageInformationSupport", [&] {
WithOecReadLock("UsageInformationSupport", [&] {
*has_support = OEMCrypto_SupportsUsageTable(security_level);
});
return true;
@@ -1365,7 +1367,7 @@ CdmResponseType CryptoSession::UpdateUsageInformation() {
}
OEMCryptoResult status;
WithOecLock("UpdateUsageInformation", [&] {
WithOecWriteLock("UpdateUsageInformation", [&] {
status = OEMCrypto_UpdateUsageTable();
});
metrics_->oemcrypto_update_usage_table_.Increment(status);
@@ -1385,7 +1387,7 @@ CdmResponseType CryptoSession::DeactivateUsageInformation(
// TODO(fredgc or rfrias): make sure oec_session_id_ is valid.
OEMCryptoResult status;
WithOecLock("DeactivateUsageInformation", [&] {
WithOecWriteLock("DeactivateUsageInformation", [&] {
status = OEMCrypto_DeactivateUsageEntry(
oec_session_id_, pst, provider_session_token.length());
});
@@ -1425,7 +1427,7 @@ CdmResponseType CryptoSession::GenerateUsageReport(
size_t usage_length = 0;
OEMCryptoResult status;
WithOecLock("GenerateUsageReport Attempt 1", [&] {
WithOecWriteLock("GenerateUsageReport Attempt 1", [&] {
status = OEMCrypto_ReportUsage(
oec_session_id_, pst, provider_session_token.length(), NULL,
&usage_length);
@@ -1439,7 +1441,7 @@ CdmResponseType CryptoSession::GenerateUsageReport(
std::vector<uint8_t> buffer(usage_length);
WithOecLock("GenerateUsageReport Attempt 2", [&] {
WithOecWriteLock("GenerateUsageReport Attempt 2", [&] {
status = OEMCrypto_ReportUsage(oec_session_id_, pst,
provider_session_token.length(), &buffer[0],
&usage_length);
@@ -1516,7 +1518,7 @@ CdmResponseType CryptoSession::ReleaseUsageInformation(
const uint8_t* pst = msg + GetOffset(message, provider_session_token);
OEMCryptoResult status;
WithOecLock("ReleaseUsageInformation", [&] {
WithOecWriteLock("ReleaseUsageInformation", [&] {
status = OEMCrypto_DeleteUsageEntry(
oec_session_id_, pst, provider_session_token.length(), msg,
message.length(), sig, signature.length());
@@ -1538,7 +1540,7 @@ CdmResponseType CryptoSession::DeleteUsageInformation(
CdmResponseType response = NO_ERROR;
LOGV("CryptoSession::DeleteUsageInformation");
OEMCryptoResult status;
WithOecLock("DeleteUsageInformation", [&] {
WithOecWriteLock("DeleteUsageInformation", [&] {
status = OEMCrypto_ForceDeleteUsageEntry(
reinterpret_cast<const uint8_t*>(provider_session_token.c_str()),
provider_session_token.length());
@@ -1559,7 +1561,7 @@ CdmResponseType CryptoSession::DeleteMultipleUsageInformation(
const std::vector<std::string>& provider_session_tokens) {
LOGV("CryptoSession::DeleteMultipleUsageInformation");
CdmResponseType response = NO_ERROR;
WithOecLock("DeleteMultipleUsageInformation", [&] {
WithOecWriteLock("DeleteMultipleUsageInformation", [&] {
for (size_t i = 0; i < provider_session_tokens.size(); ++i) {
OEMCryptoResult status = OEMCrypto_ForceDeleteUsageEntry(
reinterpret_cast<const uint8_t*>(provider_session_tokens[i].c_str()),
@@ -1581,7 +1583,7 @@ CdmResponseType CryptoSession::DeleteMultipleUsageInformation(
CdmResponseType CryptoSession::DeleteAllUsageReports() {
LOGV("DeleteAllUsageReports");
OEMCryptoResult status;
WithOecLock("DeleteAllUsageReports", [&] {
WithOecWriteLock("DeleteAllUsageReports", [&] {
status = OEMCrypto_DeleteOldUsageTable();
});
metrics_->oemcrypto_delete_usage_table_.Increment(status);
@@ -1598,7 +1600,7 @@ CdmResponseType CryptoSession::DeleteAllUsageReports() {
bool CryptoSession::IsAntiRollbackHwPresent() {
bool is_present;
WithOecLock("IsAntiRollbackHwPresent", [&] {
WithOecReadLock("IsAntiRollbackHwPresent", [&] {
is_present = OEMCrypto_IsAntiRollbackHwPresent(requested_security_level_);
});
metrics_->oemcrypto_is_anti_rollback_hw_present_.Record(is_present);
@@ -1612,7 +1614,7 @@ CdmResponseType CryptoSession::GenerateNonce(uint32_t* nonce) {
}
OEMCryptoResult result;
WithOecLock("GenerateNonce", [&] {
WithOecSessionLock("GenerateNonce", [&] {
result = OEMCrypto_GenerateNonce(oec_session_id_, nonce);
});
metrics_->oemcrypto_generate_nonce_.Increment(result);
@@ -1690,7 +1692,7 @@ CdmResponseType CryptoSession::RewrapDeviceRSAKey(
// and 0 as wrapped_rsa_key_length.
size_t wrapped_rsa_key_length = 0;
OEMCryptoResult status;
WithOecLock("RewrapDeviceRSAKey Attempt 1", [&] {
WithOecSessionLock("RewrapDeviceRSAKey Attempt 1", [&] {
M_TIME(status = OEMCrypto_RewrapDeviceRSAKey(
oec_session_id_, signed_msg, message.size(),
reinterpret_cast<const uint8_t*>(signature.data()),
@@ -1705,7 +1707,7 @@ CdmResponseType CryptoSession::RewrapDeviceRSAKey(
}
wrapped_rsa_key->resize(wrapped_rsa_key_length);
WithOecLock("RewrapDeviceRSAKey Attempt 2", [&] {
WithOecSessionLock("RewrapDeviceRSAKey Attempt 2", [&] {
M_TIME(status = OEMCrypto_RewrapDeviceRSAKey(
oec_session_id_, signed_msg, message.size(),
reinterpret_cast<const uint8_t*>(signature.data()),
@@ -1749,7 +1751,7 @@ CdmResponseType CryptoSession::RewrapDeviceRSAKey30(
// and 0 as wrapped_rsa_key_length.
size_t wrapped_private_key_length = 0;
OEMCryptoResult status;
WithOecLock("RewrapDeviceRSAKey30 Attempt 1", [&] {
WithOecSessionLock("RewrapDeviceRSAKey30 Attempt 1", [&] {
M_TIME(
status = OEMCrypto_RewrapDeviceRSAKey30(
oec_session_id_, msg_nonce, msg_wrapping_key, wrapping_key.size(),
@@ -1766,7 +1768,7 @@ CdmResponseType CryptoSession::RewrapDeviceRSAKey30(
}
wrapped_private_key->resize(wrapped_private_key_length);
WithOecLock("RewrapDeviceRSAKey30 Attempt 2", [&] {
WithOecSessionLock("RewrapDeviceRSAKey30 Attempt 2", [&] {
M_TIME(
status = OEMCrypto_RewrapDeviceRSAKey30(
oec_session_id_, msg_nonce, msg_wrapping_key, wrapping_key.size(),
@@ -1809,7 +1811,7 @@ CdmResponseType CryptoSession::GetHdcpCapabilities(SecurityLevel security_level,
return PARAMETER_NULL;
}
OEMCryptoResult status;
WithOecLock("GetHdcpCapabilities", [&] {
WithOecReadLock("GetHdcpCapabilities", [&] {
status = OEMCrypto_GetHDCPCapability(security_level, current, max);
});
@@ -1837,7 +1839,7 @@ bool CryptoSession::GetSupportedCertificateTypes(
}
uint32_t oec_support;
WithOecLock("GetSupportedCertificateTypes", [&] {
WithOecReadLock("GetSupportedCertificateTypes", [&] {
oec_support = OEMCrypto_SupportedCertificates(requested_security_level_);
});
support->rsa_2048_bit = oec_support & OEMCrypto_Supports_RSA_2048bit;
@@ -1853,7 +1855,7 @@ CdmResponseType CryptoSession::GetRandom(size_t data_length,
return PARAMETER_NULL;
}
OEMCryptoResult sts;
WithOecLock("GetRandom", [&] {
WithOecReadLock("GetRandom", [&] {
sts = OEMCrypto_GetRandom(random_data, data_length);
});
metrics_->oemcrypto_get_random_.Increment(sts);
@@ -1876,7 +1878,7 @@ CdmResponseType CryptoSession::GetNumberOfOpenSessions(
size_t sessions_count;
OEMCryptoResult status;
WithOecLock("GetNumberOfOpenSessions", [&] {
WithOecReadLock("GetNumberOfOpenSessions", [&] {
status = OEMCrypto_GetNumberOfOpenSessions(security_level, &sessions_count);
});
@@ -1907,7 +1909,7 @@ CdmResponseType CryptoSession::GetMaxNumberOfSessions(
size_t max_sessions = 0;
OEMCryptoResult status;
WithOecLock("GetMaxNumberOfSessions", [&] {
WithOecReadLock("GetMaxNumberOfSessions", [&] {
status = OEMCrypto_GetMaxNumberOfSessions(security_level, &max_sessions);
});
@@ -1931,7 +1933,7 @@ CdmResponseType CryptoSession::GetSrmVersion(uint16_t* srm_version) {
}
OEMCryptoResult status;
WithOecLock("GetSrmVersion", [&] {
WithOecReadLock("GetSrmVersion", [&] {
status = OEMCrypto_GetCurrentSRMVersion(srm_version);
});
@@ -1942,7 +1944,7 @@ CdmResponseType CryptoSession::GetSrmVersion(uint16_t* srm_version) {
bool CryptoSession::IsSrmUpdateSupported() {
LOGV("IsSrmUpdateSupported");
if (!IsInitialized()) return false;
return WithOecLock("IsSrmUpdateSupported", [&] {
return WithOecReadLock("IsSrmUpdateSupported", [&] {
return OEMCrypto_IsSRMUpdateSupported();
});
}
@@ -1956,7 +1958,7 @@ CdmResponseType CryptoSession::LoadSrm(const std::string& srm) {
}
OEMCryptoResult status;
WithOecLock("LoadSrm", [&] {
WithOecWriteLock("LoadSrm", [&] {
status = OEMCrypto_LoadSRM(
reinterpret_cast<const uint8_t*>(srm.data()), srm.size());
});
@@ -1984,7 +1986,7 @@ bool CryptoSession::GetResourceRatingTier(SecurityLevel security_level,
LOGE("tier destination not provided");
return false;
}
WithOecLock("GetResourceRatingTier", [&] {
WithOecReadLock("GetResourceRatingTier", [&] {
*tier = OEMCrypto_ResourceRatingTier(security_level);
});
if (*tier < RESOURCE_RATING_TIER_LOW || *tier > RESOURCE_RATING_TIER_HIGH) {
@@ -2010,7 +2012,7 @@ bool CryptoSession::GetBuildInformation(SecurityLevel security_level,
return false;
}
const char* build_information;
WithOecLock("GetBuildInformation", [&] {
WithOecReadLock("GetBuildInformation", [&] {
build_information = OEMCrypto_BuildInformation(security_level);
});
if (build_information == nullptr) {
@@ -2030,7 +2032,7 @@ uint32_t CryptoSession::IsDecryptHashSupported(SecurityLevel security_level) {
}
uint32_t secure_decrypt_support;
WithOecLock("IsDecryptHashSupported", [&] {
WithOecReadLock("IsDecryptHashSupported", [&] {
secure_decrypt_support = OEMCrypto_SupportsDecryptHash(security_level);
});
switch (secure_decrypt_support) {
@@ -2052,7 +2054,7 @@ CdmResponseType CryptoSession::SetDecryptHash(
const std::string& hash) {
LOGV("SetDecryptHash");
OEMCryptoResult sts;
WithOecLock("SetDecryptHash", [&] {
WithOecSessionLock("SetDecryptHash", [&] {
sts = OEMCrypto_SetDecryptHash(
oec_session_id_, frame_number,
reinterpret_cast<const uint8_t*>(hash.data()), hash.size());
@@ -2071,7 +2073,7 @@ CdmResponseType CryptoSession::GetDecryptHashError(std::string* error_string) {
uint32_t failed_frame_number;
OEMCryptoResult sts;
WithOecLock("GetDecryptHashError", [&] {
WithOecSessionLock("GetDecryptHashError", [&] {
sts = OEMCrypto_GetHashErrorCode(oec_session_id_, &failed_frame_number);
});
error_string->assign(std::to_string(sts));
@@ -2127,7 +2129,7 @@ CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer,
OEMCryptoResult sts;
WithOecLock("GenericEncrypt", [&] {
WithOecSessionLock("GenericEncrypt", [&] {
M_TIME(
sts = OEMCrypto_Generic_Encrypt(
oec_session_id_, reinterpret_cast<const uint8_t*>(in_buffer.data()),
@@ -2190,7 +2192,7 @@ CdmResponseType CryptoSession::GenericDecrypt(const std::string& in_buffer,
OEMCryptoResult sts;
WithOecLock("GenericDecrypt", [&] {
WithOecSessionLock("GenericDecrypt", [&] {
M_TIME(
sts = OEMCrypto_Generic_Decrypt(
oec_session_id_, reinterpret_cast<const uint8_t*>(in_buffer.data()),
@@ -2251,7 +2253,7 @@ CdmResponseType CryptoSession::GenericSign(const std::string& message,
// At most two attempts.
// The first attempt may fail due to buffer too short
for (int i = 0; i < 2; ++i) {
WithOecLock("GenericSign", [&] {
WithOecSessionLock("GenericSign", [&] {
M_TIME(
sts = OEMCrypto_Generic_Sign(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
@@ -2312,7 +2314,7 @@ CdmResponseType CryptoSession::GenericVerify(const std::string& message,
if (result != NO_ERROR) return result;
OEMCryptoResult sts;
WithOecLock("GenericVerify", [&] {
WithOecSessionLock("GenericVerify", [&] {
M_TIME(
sts = OEMCrypto_Generic_Verify(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
@@ -2391,7 +2393,7 @@ CdmResponseType CryptoSession::CreateUsageTableHeader(
size_t usage_table_header_size = usage_table_header->size();
OEMCryptoResult result;
WithOecLock("CreateUsageTableHeader Attempt 1", [&] {
WithOecWriteLock("CreateUsageTableHeader Attempt 1", [&] {
result = OEMCrypto_CreateUsageTableHeader(
requested_security_level_,
reinterpret_cast<uint8_t*>(
@@ -2401,7 +2403,7 @@ CdmResponseType CryptoSession::CreateUsageTableHeader(
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
usage_table_header->resize(usage_table_header_size);
WithOecLock("CreateUsageTableHeader Attempt 2", [&] {
WithOecWriteLock("CreateUsageTableHeader Attempt 2", [&] {
result = OEMCrypto_CreateUsageTableHeader(
requested_security_level_,
reinterpret_cast<uint8_t*>(
@@ -2423,7 +2425,7 @@ CdmResponseType CryptoSession::LoadUsageTableHeader(
LOGV("LoadUsageTableHeader: id=%lu", oec_session_id_);
OEMCryptoResult result;
WithOecLock("LoadUsageTableHeader", [&] {
WithOecWriteLock("LoadUsageTableHeader", [&] {
result = OEMCrypto_LoadUsageTableHeader(
requested_security_level_,
reinterpret_cast<const uint8_t*>(usage_table_header.data()),
@@ -2468,7 +2470,7 @@ CdmResponseType CryptoSession::CreateUsageEntry(uint32_t* entry_number) {
}
OEMCryptoResult result;
WithOecLock("CreateUsageEntry", [&] {
WithOecWriteLock("CreateUsageEntry", [&] {
result = OEMCrypto_CreateNewUsageEntry(oec_session_id_, entry_number);
});
@@ -2495,7 +2497,7 @@ CdmResponseType CryptoSession::LoadUsageEntry(
LOGV("LoadUsageEntry: id=%lu", oec_session_id_);
OEMCryptoResult result;
WithOecLock("LoadUsageEntry", [&] {
WithOecWriteLock("LoadUsageEntry", [&] {
result = OEMCrypto_LoadUsageEntry(
oec_session_id_, entry_number,
reinterpret_cast<const uint8_t*>(usage_entry.data()),
@@ -2546,7 +2548,7 @@ CdmResponseType CryptoSession::UpdateUsageEntry(
size_t usage_table_header_len = 0;
size_t usage_entry_len = 0;
OEMCryptoResult result;
WithOecLock("UpdateUsageEntry Attempt 1", [&] {
WithOecWriteLock("UpdateUsageEntry Attempt 1", [&] {
result = OEMCrypto_UpdateUsageEntry(
oec_session_id_, NULL, &usage_table_header_len, NULL, &usage_entry_len);
});
@@ -2556,7 +2558,7 @@ CdmResponseType CryptoSession::UpdateUsageEntry(
usage_table_header->resize(usage_table_header_len);
usage_entry->resize(usage_entry_len);
WithOecLock("UpdateUsageEntry Attempt 2", [&] {
WithOecWriteLock("UpdateUsageEntry Attempt 2", [&] {
result = OEMCrypto_UpdateUsageEntry(
oec_session_id_,
reinterpret_cast<uint8_t*>(
@@ -2588,7 +2590,7 @@ CdmResponseType CryptoSession::ShrinkUsageTableHeader(
size_t usage_table_header_len = 0;
OEMCryptoResult result;
WithOecLock("ShrinkUsageTableHeader Attempt 1", [&] {
WithOecWriteLock("ShrinkUsageTableHeader Attempt 1", [&] {
result = OEMCrypto_ShrinkUsageTableHeader(
requested_security_level_, new_entry_count, NULL,
&usage_table_header_len);
@@ -2597,7 +2599,7 @@ CdmResponseType CryptoSession::ShrinkUsageTableHeader(
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
usage_table_header->resize(usage_table_header_len);
WithOecLock("ShrinkUsageTableHeader Attempt 2", [&] {
WithOecWriteLock("ShrinkUsageTableHeader Attempt 2", [&] {
result = OEMCrypto_ShrinkUsageTableHeader(
requested_security_level_, new_entry_count,
reinterpret_cast<uint8_t*>(
@@ -2618,7 +2620,7 @@ CdmResponseType CryptoSession::MoveUsageEntry(uint32_t new_entry_number) {
LOGV("MoveUsageEntry: id=%lu", oec_session_id_);
OEMCryptoResult result;
WithOecLock("MoveUsageEntry", [&] {
WithOecWriteLock("MoveUsageEntry", [&] {
result = OEMCrypto_MoveEntry(oec_session_id_, new_entry_number);
});
@@ -2660,7 +2662,7 @@ bool CryptoSession::CreateOldUsageEntry(
}
OEMCryptoResult result;
WithOecLock("CreateOldUsageEntry", [&] {
WithOecWriteLock("CreateOldUsageEntry", [&] {
result = OEMCrypto_CreateOldUsageEntry(
requested_security_level_, time_since_license_received,
time_since_first_decrypt, time_since_last_decrypt, status,
@@ -2683,7 +2685,7 @@ CdmResponseType CryptoSession::CopyOldUsageEntry(
LOGV("CopyOldUsageEntry: id=%lu", oec_session_id_);
OEMCryptoResult result;
WithOecLock("CopyOldUsageEntry", [&] {
WithOecWriteLock("CopyOldUsageEntry", [&] {
result = OEMCrypto_CopyOldUsageEntry(
oec_session_id_,
reinterpret_cast<const uint8_t*>(provider_session_token.data()),
@@ -2699,7 +2701,7 @@ bool CryptoSession::GetAnalogOutputCapabilities(bool* can_support_output,
bool* can_support_cgms_a) {
LOGV("GetAnalogOutputCapabilities: id=%lu", oec_session_id_);
uint32_t flags;
WithOecLock("GetAnalogOutputCapabilities", [&] {
WithOecReadLock("GetAnalogOutputCapabilities", [&] {
flags = OEMCrypto_GetAnalogOutputFlags(requested_security_level_);
});
@@ -2779,7 +2781,7 @@ OEMCryptoResult CryptoSession::CopyBufferInChunks(
}
OEMCryptoResult sts;
WithOecLock("CopyBufferInChunks", [&] {
WithOecSessionLock("CopyBufferInChunks", [&] {
M_TIME(sts = OEMCrypto_CopyBuffer(
oec_session_id_, params.encrypt_buffer + additional_offset,
chunk_size, &buffer_descriptor, subsample_flags),
@@ -2853,7 +2855,7 @@ OEMCryptoResult CryptoSession::DecryptInChunks(
// pattern length long, which is also guaranteed to be an exact number
// of AES blocks long.
OEMCryptoResult sts;
WithOecLock("DecryptInChunks", [&] {
WithOecSessionLock("DecryptInChunks", [&] {
M_TIME(
sts = OEMCrypto_DecryptCENC(
oec_session_id_, params.encrypt_buffer + additional_offset,
@@ -2927,27 +2929,52 @@ void CryptoSession::IncrementIV(uint64_t increase_by,
}
template <class Func>
auto CryptoSession::WithStaticFieldLock(const char* tag, Func body)
auto CryptoSession::WithStaticFieldWriteLock(const char* tag, Func body)
-> decltype(body()) {
LOGV("Static Field Lock - %s", tag);
std::unique_lock<std::mutex> auto_lock(static_field_lock_);
LOGV("Static Field Write Lock - %s", tag);
std::unique_lock<shared_mutex> auto_lock(static_field_mutex_);
return body();
}
template <class Func>
auto CryptoSession::WithOecLock(const char* tag, Func body)
auto CryptoSession::WithStaticFieldReadLock(const char* tag, Func body)
-> decltype(body()) {
LOGV("OEMCrypto Lock - %s", tag);
std::unique_lock<std::mutex> auto_lock(oem_crypto_lock_);
LOGV("Static Field Read Lock - %s", tag);
shared_lock<shared_mutex> auto_lock(static_field_mutex_);
return body();
}
template <class Func>
auto CryptoSession::WithOecWriteLock(const char* tag, Func body)
-> decltype(body()) {
LOGV("OEMCrypto Write Lock - %s", tag);
std::unique_lock<shared_mutex> auto_lock(oem_crypto_mutex_);
return body();
}
template <class Func>
auto CryptoSession::WithOecReadLock(const char* tag, Func body)
-> decltype(body()) {
LOGV("OEMCrypto Read Lock - %s", tag);
shared_lock<shared_mutex> auto_lock(oem_crypto_mutex_);
return body();
}
template <class Func>
auto CryptoSession::WithOecSessionLock(const char* tag, Func body)
-> decltype(body()) {
LOGV("OEMCrypto Session Lock - %s", tag);
shared_lock<shared_mutex> oec_auto_lock(oem_crypto_mutex_);
std::unique_lock<std::mutex> session_auto_lock(oem_crypto_session_mutex_);
return body();
}
bool CryptoSession::IsInitialized() {
return WithStaticFieldLock("IsInitialized", [] { return initialized_; });
return WithStaticFieldReadLock("IsInitialized", [] { return initialized_; });
}
// CryptoSesssionFactory support
std::mutex CryptoSession::factory_lock_;
std::mutex CryptoSession::factory_mutex_;
// The factory will either be set by WvCdmTestBase, or a default factory is
// created on the first call to MakeCryptoSession.
std::unique_ptr<CryptoSessionFactory> CryptoSession::factory_ =
@@ -2955,7 +2982,7 @@ std::unique_ptr<CryptoSessionFactory> CryptoSession::factory_ =
CryptoSession* CryptoSession::MakeCryptoSession(
metrics::CryptoMetrics* crypto_metrics) {
std::unique_lock<std::mutex> auto_lock(factory_lock_);
std::unique_lock<std::mutex> auto_lock(factory_mutex_);
// If the factory_ has not been set, then use a default factory.
if (factory_.get() == NULL) factory_.reset(new CryptoSessionFactory());
return factory_->MakeCryptoSession(crypto_metrics);