Pick widevine oemcrypto-v18 change

No-Typo-Check: From a third party header file
Bug: 260918793
Test: unit tests
Test: atp v2/widevine-eng/drm_compliance
Change-Id: I36effd6a10a99bdb2399ab1f4a0fad026d607c70
This commit is contained in:
Kyle Zhang
2022-12-16 03:21:08 +00:00
parent 4586522c07
commit 11255b7426
105 changed files with 324641 additions and 299787 deletions

View File

@@ -16,10 +16,12 @@
#include "advance_iv_ctr.h"
#include "arraysize.h"
#include "cdm_random.h"
#include "content_key_session.h"
#include "crypto_key.h"
#include "entitlement_key_session.h"
#include "log.h"
#include "odk_structs.h"
#include "okp_fallback_policy.h"
#include "platform.h"
#include "privacy_crypto.h"
@@ -407,6 +409,8 @@ void CryptoSession::ReinitializeForTest() {
LOGE("OEMCrypto_Initialize failed: %d", status);
return;
}
OEMCrypto_SetMaxAPIVersion(ODK_MAJOR_VERSION);
OEMCrypto_EnterTestMode();
initialized_ = true;
// For integration and unit tests we will install a test keybox and do not
// need to do keybox provisioning.
@@ -926,13 +930,8 @@ CdmResponseType CryptoSession::Open(
open_ = true;
// Set up request ID
uint64_t request_id_base;
OEMCryptoResult random_sts;
WithOecReadLock("Open() calling OEMCrypto_GetRandom", [&] {
random_sts = OEMCrypto_GetRandom(
reinterpret_cast<uint8_t*>(&request_id_base), sizeof(request_id_base));
});
metrics_->oemcrypto_get_random_.Increment(random_sts);
uint64_t request_id_base =
wvutil::CdmRandom::RandomInRange(std::numeric_limits<uint64_t>::max());
uint64_t request_id_index =
request_id_index_source_.fetch_add(1, std::memory_order_relaxed);
request_id_ = wvutil::HexEncode(reinterpret_cast<uint8_t*>(&request_id_base),
@@ -942,7 +941,8 @@ CdmResponseType CryptoSession::Open(
// Initialize key session
WithOecSessionLock("Open() calling key_session_.reset()", [&] {
key_session_.reset(new ContentKeySession(oec_session_id_, metrics_));
key_session_.reset(new ContentKeySession(requested_security_level_,
oec_session_id_, metrics_));
});
if (!GetApiVersion(&api_version_)) {
@@ -987,13 +987,27 @@ void CryptoSession::Close() {
CdmResponseType CryptoSession::PrepareAndSignLicenseRequest(
const std::string& message, std::string* core_message,
std::string* signature) {
std::string* signature, bool& should_specify_algorithm,
OEMCrypto_SignatureHashAlgorithm& algorithm) {
LOGV("Preparing and signing license request: id = %u", oec_session_id_);
RETURN_IF_NULL(signature, PARAMETER_NULL);
RETURN_IF_NULL(core_message, PARAMETER_NULL);
RETURN_IF_NOT_OPEN(CRYPTO_SESSION_NOT_OPEN);
OEMCryptoResult sts;
WithOecSessionLock("GetSignatureHashAlgorithm", [&] {
sts = OEMCrypto_GetSignatureHashAlgorithm(oec_session_id_, &algorithm);
});
metrics_->oemcrypto_get_signature_hash_algorithm_.Increment(sts, algorithm);
if (sts == OEMCrypto_SUCCESS) {
should_specify_algorithm = true;
} else if (sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
should_specify_algorithm = false;
} else {
return MapOEMCryptoResult(sts, GET_SIGNATURE_HASH_ALGORITHM_ERROR_1,
"PrepareAndSignLicenseRequest");
}
size_t signature_length = 0;
size_t core_message_length = 0;
*core_message = "";
@@ -1081,7 +1095,8 @@ CdmResponseType CryptoSession::LoadLicense(const std::string& signed_message,
WithOecSessionLock("LoadLicense", [&] {
if (key_type == kLicenseKeyTypeEntitlement &&
key_session_->Type() != KeySession::kEntitlement) {
key_session_.reset(new EntitlementKeySession(oec_session_id_, metrics_));
key_session_.reset(new EntitlementKeySession(requested_security_level_,
oec_session_id_, metrics_));
}
M_TIME(sts = OEMCrypto_LoadLicense(
@@ -1110,7 +1125,8 @@ CdmResponseType CryptoSession::LoadLicense(const std::string& signed_message,
CdmResponseType CryptoSession::PrepareAndSignRenewalRequest(
const std::string& message, std::string* core_message,
std::string* signature) {
std::string* signature, bool& should_specify_algorithm,
OEMCrypto_SignatureHashAlgorithm& algorithm) {
LOGV("Preparing and signing renewal request: id = %u", oec_session_id_);
if (signature == nullptr) {
LOGE("Output parameter |signature| not provided");
@@ -1122,6 +1138,19 @@ CdmResponseType CryptoSession::PrepareAndSignRenewalRequest(
}
OEMCryptoResult sts;
WithOecSessionLock("GetSignatureHashAlgorithm", [&] {
sts = OEMCrypto_GetSignatureHashAlgorithm(oec_session_id_, &algorithm);
});
metrics_->oemcrypto_get_signature_hash_algorithm_.Increment(sts, algorithm);
if (sts == OEMCrypto_SUCCESS) {
should_specify_algorithm = true;
} else if (sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
should_specify_algorithm = false;
} else {
return MapOEMCryptoResult(sts, GET_SIGNATURE_HASH_ALGORITHM_ERROR_2,
"PrepareAndSignRenewalRequest");
}
size_t signature_length = 0;
size_t core_message_length = 0;
*core_message = "";
@@ -1197,7 +1226,8 @@ CdmResponseType CryptoSession::LoadRenewal(const std::string& signed_message,
CdmResponseType CryptoSession::PrepareAndSignProvisioningRequest(
const std::string& message, std::string* core_message,
std::string* signature) {
std::string* signature, bool& should_specify_algorithm,
OEMCrypto_SignatureHashAlgorithm& algorithm) {
LOGV("Preparing and signing provisioning request: id = %u", oec_session_id_);
if (signature == nullptr) {
LOGE("Output parameter |signature| not provided");
@@ -1208,21 +1238,42 @@ CdmResponseType CryptoSession::PrepareAndSignProvisioningRequest(
return CdmResponseType(PARAMETER_NULL);
}
OEMCryptoResult sts;
if (pre_provision_token_type_ == kClientTokenKeybox) {
should_specify_algorithm = false;
const CdmResponseType status = GenerateDerivedKeys(message);
if (status != NO_ERROR) return status;
} else if (pre_provision_token_type_ == kClientTokenOemCert) {
const OEMCryptoResult status = OEMCrypto_LoadOEMPrivateKey(oec_session_id_);
if (status != OEMCrypto_SUCCESS) {
return MapOEMCryptoResult(status, GET_TOKEN_FROM_OEM_CERT_ERROR,
should_specify_algorithm = true;
WithOecSessionLock("LoadOEMPrivateKey", [&] {
sts = OEMCrypto_LoadOEMPrivateKey(oec_session_id_);
});
if (sts != OEMCrypto_SUCCESS) {
return MapOEMCryptoResult(sts, GET_TOKEN_FROM_OEM_CERT_ERROR,
"PrepareAndSignProvisioningRequest");
}
} else if (pre_provision_token_type_ == kClientTokenBootCertChain) {
should_specify_algorithm = true;
// Do nothing here. The key to signing the provisioning 4.0 request for each
// stage has been loaded already when it was generated by OEMCrypto.
} else {
LOGE("Unknown method %d", pre_provision_token_type_);
return CdmResponseType(UNKNOWN_CLIENT_TOKEN_TYPE);
}
OEMCryptoResult sts;
if (should_specify_algorithm) {
WithOecSessionLock("GetSignatureHashAlgorithm", [&] {
sts = OEMCrypto_GetSignatureHashAlgorithm(oec_session_id_, &algorithm);
});
metrics_->oemcrypto_get_signature_hash_algorithm_.Increment(sts, algorithm);
if (sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
should_specify_algorithm = false;
} else if (sts != OEMCrypto_SUCCESS) {
return MapOEMCryptoResult(sts, GET_SIGNATURE_HASH_ALGORITHM_ERROR_3,
"PrepareAndSignProvisioningRequest");
}
}
size_t signature_length = 0;
size_t core_message_length = 0;
*core_message = "";
@@ -2091,18 +2142,6 @@ bool CryptoSession::GetSupportedCertificateTypes(
return true;
}
CdmResponseType CryptoSession::GetRandom(size_t data_length,
uint8_t* random_data) {
RETURN_IF_NULL(random_data, PARAMETER_NULL);
OEMCryptoResult sts;
WithOecReadLock("GetRandom",
[&] { sts = OEMCrypto_GetRandom(random_data, data_length); });
metrics_->oemcrypto_get_random_.Increment(sts);
return MapOEMCryptoResult(sts, RANDOM_GENERATION_ERROR, "GetRandom");
}
CdmResponseType CryptoSession::GetNumberOfOpenSessions(
RequestedSecurityLevel security_level, size_t* count) {
LOGV("Getting number of open sessions: id = %u, security_level = %s",
@@ -2435,14 +2474,8 @@ CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer,
OEMCryptoResult sts;
WithOecSessionLock("GenericEncrypt", [&] {
M_TIME(
sts = OEMCrypto_Generic_Encrypt(
oec_session_id_, reinterpret_cast<const uint8_t*>(in_buffer.data()),
in_buffer.size(), reinterpret_cast<const uint8_t*>(iv.data()),
oec_algorithm,
reinterpret_cast<uint8_t*>(const_cast<char*>(out_buffer->data()))),
metrics_, oemcrypto_generic_encrypt_, sts,
metrics::Pow2Bucket(in_buffer.size()));
sts =
key_session_->GenericEncrypt(in_buffer, iv, oec_algorithm, out_buffer);
});
if (OEMCrypto_SUCCESS != sts) {
@@ -2496,14 +2529,8 @@ CdmResponseType CryptoSession::GenericDecrypt(const std::string& in_buffer,
OEMCryptoResult sts;
WithOecSessionLock("GenericDecrypt", [&] {
M_TIME(
sts = OEMCrypto_Generic_Decrypt(
oec_session_id_, reinterpret_cast<const uint8_t*>(in_buffer.data()),
in_buffer.size(), reinterpret_cast<const uint8_t*>(iv.data()),
oec_algorithm,
reinterpret_cast<uint8_t*>(const_cast<char*>(out_buffer->data()))),
metrics_, oemcrypto_generic_decrypt_, sts,
metrics::Pow2Bucket(in_buffer.size()));
sts =
key_session_->GenericDecrypt(in_buffer, iv, oec_algorithm, out_buffer);
});
if (OEMCrypto_SUCCESS != sts) {
@@ -2542,45 +2569,20 @@ CdmResponseType CryptoSession::GenericSign(const std::string& message,
return CdmResponseType(INVALID_PARAMETERS_ENG_15);
}
OEMCryptoResult sts;
size_t length = signature->size();
// TODO(jfore): We need to select a key with a cipher mode and algorithm
// doesn't seem to fit. Is it ok to just use a default value here?
// Or do we need to pass it in?
CdmResponseType result = SelectKey(key_id, kCipherModeCbc);
if (result != NO_ERROR) return result;
// At most two attempts.
// The first attempt may fail due to buffer too short
for (int i = 0; i < 2; ++i) {
WithOecSessionLock("GenericSign", [&] {
M_TIME(
sts = OEMCrypto_Generic_Sign(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
message.size(), oec_algorithm,
reinterpret_cast<uint8_t*>(const_cast<char*>(signature->data())),
&length),
metrics_, oemcrypto_generic_sign_, sts,
metrics::Pow2Bucket(message.size()));
});
if (OEMCrypto_SUCCESS == sts) {
// Trim signature buffer and done
signature->resize(length);
return CdmResponseType(NO_ERROR);
}
if (OEMCrypto_ERROR_SHORT_BUFFER != sts) {
break;
}
// Retry with proper-sized return buffer
signature->resize(length);
}
LOGE("OEMCrypto_Generic_Sign failed: status = %d", static_cast<int>(sts));
OEMCryptoResult sts;
WithOecSessionLock("GenericSign", [&] {
sts = key_session_->GenericSign(message, oec_algorithm, signature);
});
switch (sts) {
case OEMCrypto_SUCCESS:
return CdmResponseType(NO_ERROR);
case OEMCrypto_ERROR_KEY_EXPIRED:
return CRYPTO_ERROR(NEED_KEY, sts);
case OEMCrypto_ERROR_NO_CONTENT_KEY:
@@ -2616,14 +2618,7 @@ CdmResponseType CryptoSession::GenericVerify(const std::string& message,
OEMCryptoResult sts;
WithOecSessionLock("GenericVerify", [&] {
M_TIME(
sts = OEMCrypto_Generic_Verify(
oec_session_id_, reinterpret_cast<const uint8_t*>(message.data()),
message.size(), oec_algorithm,
reinterpret_cast<const uint8_t*>(signature.data()),
signature.size()),
metrics_, oemcrypto_generic_verify_, sts,
metrics::Pow2Bucket(signature.size()));
sts = key_session_->GenericVerify(message, oec_algorithm, signature);
});
if (OEMCrypto_SUCCESS != sts) {
@@ -2921,12 +2916,6 @@ bool CryptoSession::GetAnalogOutputCapabilities(bool* can_support_output,
return true;
}
// OEMCryptoResult OEMCrypto_DecryptCENC(
// OEMCrypto_SESSION session,
// const OEMCrypto_SampleDescription* samples, // an array of samples.
// size_t samples_length, // the number of samples.
// const OEMCrypto_CENCEncryptPatternDesc* pattern);
OEMCryptoResult CryptoSession::DecryptMultipleSamples(
const std::vector<OEMCrypto_SampleDescription>& samples,
CdmCipherMode cipher_mode,