Source release 19.1.0
This commit is contained in:
@@ -95,7 +95,9 @@ class UsagePropertySet : public CdmClientPropertySet {
|
||||
|
||||
CdmEngine::CdmEngine(wvutil::FileSystem* file_system,
|
||||
std::shared_ptr<metrics::EngineMetrics> metrics)
|
||||
: metrics_(metrics), file_system_(file_system), spoid_(EMPTY_SPOID) {
|
||||
: metrics_(std::move(metrics)),
|
||||
file_system_(file_system),
|
||||
spoid_(EMPTY_SPOID) {
|
||||
assert(file_system);
|
||||
Properties::Init();
|
||||
}
|
||||
@@ -712,7 +714,7 @@ CdmResponseType CdmEngine::QueryStatus(RequestedSecurityLevel security_level,
|
||||
LOGW("GetWVCdmVersion failed");
|
||||
return CdmResponseType(UNKNOWN_ERROR);
|
||||
}
|
||||
*query_response = cdm_version;
|
||||
*query_response = std::move(cdm_version);
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
if (query_token == QUERY_KEY_RESOURCE_RATING_TIER) {
|
||||
@@ -934,7 +936,7 @@ CdmResponseType CdmEngine::QueryStatus(RequestedSecurityLevel security_level,
|
||||
metrics_->GetCryptoMetrics()
|
||||
->crypto_session_get_device_unique_id_.Increment(status);
|
||||
if (status != NO_ERROR) return status;
|
||||
*query_response = device_id;
|
||||
*query_response = std::move(device_id);
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
if (query_token == QUERY_KEY_PROVISIONING_ID) {
|
||||
@@ -944,7 +946,7 @@ CdmResponseType CdmEngine::QueryStatus(RequestedSecurityLevel security_level,
|
||||
LOGW("GetProvisioningId failed: status = %d", static_cast<int>(status));
|
||||
return status;
|
||||
}
|
||||
*query_response = provisioning_id;
|
||||
*query_response = std::move(provisioning_id);
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
LOGW("Unknown status requested: query_token = %s", IdToString(query_token));
|
||||
@@ -1255,11 +1257,24 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||
|
||||
const CdmResponseType ret = cert_provisioning_->HandleProvisioningResponse(
|
||||
file_system_, response, cert, wrapped_key);
|
||||
// Release resources only on success. It is possible that a provisioning
|
||||
// attempt was made after this one was requested but before the response was
|
||||
// received, which will cause this attempt to fail. Not releasing will
|
||||
// allow for the possibility that the later attempt succeeds.
|
||||
if (NO_ERROR == ret) cert_provisioning_.reset();
|
||||
if (NO_ERROR == ret) {
|
||||
// Release resources on success.
|
||||
cert_provisioning_.reset();
|
||||
} else if (DEVICE_REVOKED == ret) {
|
||||
// If a device is revoked, future attempts will likely fail.
|
||||
// Caller may attempt changing security level to recover.
|
||||
LOGE("Device has been revoked, cannot provision: status = %s",
|
||||
ret.ToString().c_str());
|
||||
cert_provisioning_.reset();
|
||||
} else {
|
||||
// It is possible that a provisioning attempt was made after this one was
|
||||
// requested but before the response was received, which will cause this
|
||||
// attempt to fail. Not releasing will allow for the possibility that the
|
||||
// later attempt succeeds.
|
||||
LOGW("Provisioning failed, app may try again: status = %s",
|
||||
ret.ToString().c_str());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ int DrmKeyTypeToMetricValue(CryptoWrappedKey::Type type) {
|
||||
|
||||
CdmSession::CdmSession(wvutil::FileSystem* file_system,
|
||||
std::shared_ptr<metrics::SessionMetrics> metrics)
|
||||
: metrics_(metrics),
|
||||
: metrics_(std::move(metrics)),
|
||||
initialized_(false),
|
||||
closed_(true),
|
||||
file_handle_(new DeviceFiles(file_system)),
|
||||
@@ -81,7 +81,9 @@ CdmSession::CdmSession(wvutil::FileSystem* file_system,
|
||||
security_level_(kSecurityLevelUninitialized),
|
||||
requested_security_level_(kLevelDefault),
|
||||
is_initial_usage_update_(true),
|
||||
is_usage_update_needed_(false) {
|
||||
is_usage_update_needed_(false),
|
||||
mock_license_parser_in_use_(false),
|
||||
mock_policy_engine_in_use_(false) {
|
||||
assert(metrics_); // metrics_ must not be null.
|
||||
crypto_metrics_ = metrics_->GetCryptoMetrics();
|
||||
crypto_session_.reset(CryptoSession::MakeCryptoSession(crypto_metrics_));
|
||||
@@ -864,11 +866,19 @@ CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_index) {
|
||||
// The usage entry cannot be deleted if it has a crypto session handling
|
||||
// it, so close and reopen session.
|
||||
UpdateUsageEntryInformation();
|
||||
|
||||
CdmResponseType sts;
|
||||
crypto_session_->Close();
|
||||
CdmResponseType sts = ResetCryptoSession();
|
||||
crypto_session_.reset(CryptoSession::MakeCryptoSession(crypto_metrics_));
|
||||
M_TIME(sts = crypto_session_->Open(requested_security_level_),
|
||||
crypto_metrics_, crypto_session_open_, sts, requested_security_level_);
|
||||
if (sts != NO_ERROR) return sts;
|
||||
|
||||
usage_table_ = nullptr;
|
||||
bool has_support = false;
|
||||
if (crypto_session_->HasUsageTableSupport(&has_support) && has_support) {
|
||||
usage_table_ = crypto_session_->GetUsageTable();
|
||||
}
|
||||
|
||||
if (usage_table_ == nullptr) {
|
||||
LOGE("Usage table header unavailable");
|
||||
return CdmResponseType(INCORRECT_USAGE_SUPPORT_TYPE_1);
|
||||
@@ -1002,8 +1012,14 @@ bool CdmSession::StoreLicense(CdmOfflineLicenseState state, int* error_detail) {
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::RemoveKeys() {
|
||||
crypto_session_->Close();
|
||||
return ResetCryptoSession();
|
||||
CdmResponseType sts;
|
||||
crypto_session_.reset(CryptoSession::MakeCryptoSession(crypto_metrics_));
|
||||
// Ignore errors
|
||||
M_TIME(sts = crypto_session_->Open(requested_security_level_),
|
||||
crypto_metrics_, crypto_session_open_, sts, requested_security_level_);
|
||||
policy_engine_.reset(
|
||||
new PolicyEngine(session_id_, nullptr, crypto_session_.get()));
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::RemoveLicense() {
|
||||
@@ -1297,77 +1313,6 @@ CdmResponseType CdmSession::GenerateRsaSignature(const std::string& message,
|
||||
return crypto_session_->GenerateRsaSignature(message, signature, scheme);
|
||||
}
|
||||
|
||||
CdmResponseType CdmSession::ResetCryptoSession() {
|
||||
LOGD("Resetting crypto session: session_id = %s, ksid = %s",
|
||||
IdToString(session_id_), IdToString(key_set_id_));
|
||||
if (mock_crypto_session_in_use_) {
|
||||
// If the crypto session is not reset, then there is nothing to do.
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
CdmResponseType sts;
|
||||
crypto_session_.reset(CryptoSession::MakeCryptoSession(crypto_metrics_));
|
||||
usage_table_ = nullptr;
|
||||
M_TIME(sts = crypto_session_->Open(requested_security_level_),
|
||||
crypto_metrics_, crypto_session_open_, sts, requested_security_level_);
|
||||
|
||||
CdmResponseType final_sts(NO_ERROR);
|
||||
if (sts != NO_ERROR) {
|
||||
// Challenging case, still need to reset other components.
|
||||
LOGE("Failed to open crypto session: sts = %s", sts.ToString().c_str());
|
||||
final_sts = sts;
|
||||
} else {
|
||||
// Reset all component dependent on the crypto session.
|
||||
security_level_ = crypto_session_->GetSecurityLevel();
|
||||
crypto_metrics_->crypto_session_security_level_.Record(security_level_);
|
||||
|
||||
if (!file_handle_->Init(security_level_)) {
|
||||
LOGE("Unable to initialize file handle");
|
||||
final_sts = CdmResponseType(SESSION_FILE_HANDLE_INIT_ERROR);
|
||||
}
|
||||
|
||||
if (!file_handle_->HasCertificate(atsc_mode_enabled_)) {
|
||||
LOGE("Missing certificate: atsc_mode_enabled = %s",
|
||||
BoolToString(atsc_mode_enabled_));
|
||||
final_sts = CdmResponseType(NEED_PROVISIONING);
|
||||
}
|
||||
|
||||
bool has_support = false;
|
||||
if (crypto_session_->HasUsageTableSupport(&has_support) && has_support) {
|
||||
usage_table_ = crypto_session_->GetUsageTable();
|
||||
}
|
||||
}
|
||||
|
||||
// Even if the session is not open, other members need new session pointer.
|
||||
if (mock_policy_engine_in_use_) {
|
||||
// Simply pass the new pointer.
|
||||
policy_engine_->set_crypto_session(crypto_session_.get());
|
||||
} else {
|
||||
// Attempt to maintain event listener.
|
||||
WvCdmEventListener* event_listener =
|
||||
policy_engine_ ? policy_engine_->event_listener() : nullptr;
|
||||
policy_engine_.reset(
|
||||
new PolicyEngine(session_id_, event_listener, crypto_session_.get()));
|
||||
}
|
||||
|
||||
if (mock_license_parser_in_use_) {
|
||||
license_parser_->set_crypto_session(crypto_session_.get());
|
||||
license_parser_->set_policy_engine(policy_engine_.get());
|
||||
} else {
|
||||
license_parser_.reset(new CdmLicense(session_id_));
|
||||
std::string service_certificate;
|
||||
if (!Properties::GetServiceCertificate(session_id_, &service_certificate))
|
||||
service_certificate.clear();
|
||||
if (!license_parser_->Init(Properties::UsePrivacyMode(session_id_),
|
||||
service_certificate, crypto_session_.get(),
|
||||
policy_engine_.get())) {
|
||||
LOGE("Failed to initialize license parser");
|
||||
final_sts = CdmResponseType(LICENSE_PARSER_INIT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return final_sts;
|
||||
}
|
||||
|
||||
// For testing only - takes ownership of pointers
|
||||
|
||||
void CdmSession::set_license_parser(CdmLicense* license_parser) {
|
||||
@@ -1377,7 +1322,6 @@ void CdmSession::set_license_parser(CdmLicense* license_parser) {
|
||||
|
||||
void CdmSession::set_crypto_session(CryptoSession* crypto_session) {
|
||||
crypto_session_.reset(crypto_session);
|
||||
mock_crypto_session_in_use_ = true;
|
||||
}
|
||||
|
||||
void CdmSession::set_policy_engine(PolicyEngine* policy_engine) {
|
||||
|
||||
@@ -261,6 +261,7 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal(
|
||||
status = crypto_session_->PrepareAndSignProvisioningRequest(
|
||||
serialized_message, &core_message, &request_signature,
|
||||
should_specify_algorithm, oec_algorithm);
|
||||
request_ = serialized_message;
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("Failed to prepare provisioning request: status = %d",
|
||||
@@ -488,6 +489,7 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
|
||||
} else {
|
||||
*request = std::move(serialized_request);
|
||||
}
|
||||
request_ = std::move(serialized_message);
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
@@ -574,20 +576,14 @@ CdmResponseType CertificateProvisioning::HandleProvisioning40Response(
|
||||
return status;
|
||||
}
|
||||
|
||||
status = crypto_session_->GenerateDerivedKeys(
|
||||
provisioning_request_message_, signed_response.session_key());
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("Failed to generate derived keys.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Get wrapped private key for cast cert
|
||||
CryptoWrappedKey cast_cert_private_key;
|
||||
const std::string& signature = signed_response.signature();
|
||||
const std::string& core_message = signed_response.oemcrypto_core_message();
|
||||
status = crypto_session_->LoadProvisioning(response_message, core_message,
|
||||
signature,
|
||||
&cast_cert_private_key.key());
|
||||
status = crypto_session_->LoadProvisioningCast(
|
||||
signed_response.session_key(), provisioning_request_message_,
|
||||
response_message, core_message, signature,
|
||||
&cast_cert_private_key.key());
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("Failed to generate wrapped key for cast cert.");
|
||||
return status;
|
||||
@@ -727,14 +723,26 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
||||
}
|
||||
|
||||
CryptoWrappedKey private_key;
|
||||
const CdmResponseType status = crypto_session_->LoadProvisioning(
|
||||
signed_message, core_message, signature, &private_key.key());
|
||||
// TODO(b/316053127): clean this up a bit.
|
||||
if (cert_type_ == kCertificateX509) {
|
||||
const std::string dummy_key;
|
||||
const CdmResponseType status = crypto_session_->LoadProvisioningCast(
|
||||
dummy_key, request_, signed_message, core_message, signature,
|
||||
&private_key.key());
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("LoadProvisioning failed: status = %d", static_cast<int>(status));
|
||||
return status;
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("LoadProvisioning failed: status = %d", static_cast<int>(status));
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
const CdmResponseType status = crypto_session_->LoadProvisioning(
|
||||
request_, signed_message, core_message, signature, &private_key.key());
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("LoadProvisioning failed: status = %d", static_cast<int>(status));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
const CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();
|
||||
CloseSession();
|
||||
|
||||
|
||||
@@ -380,10 +380,30 @@ bool ClientIdentification::GetProvisioningTokenType(
|
||||
*token_type =
|
||||
video_widevine::ClientIdentification::OEM_DEVICE_CERTIFICATE;
|
||||
return true;
|
||||
case kClientTokenBootCertChain:
|
||||
*token_type =
|
||||
video_widevine::ClientIdentification::BOOT_CERTIFICATE_CHAIN;
|
||||
case kClientTokenBootCertChain: {
|
||||
OEMCrypto_BCCType bcc_type;
|
||||
const CdmResponseType result =
|
||||
crypto_session_->GetProvisioning40TokenType(&bcc_type);
|
||||
if (result == NOT_IMPLEMENTED_ERROR) {
|
||||
// Default to CBOR BCC for OEMCrypto that doesn't support GetBCCType().
|
||||
*token_type =
|
||||
video_widevine::ClientIdentification::BOOT_CERTIFICATE_CHAIN;
|
||||
return true;
|
||||
}
|
||||
if (result != NO_ERROR) return false;
|
||||
if (bcc_type == OEMCrypto_CBOR) {
|
||||
*token_type =
|
||||
video_widevine::ClientIdentification::BOOT_CERTIFICATE_CHAIN;
|
||||
} else if (bcc_type == OEMCrypto_X509) {
|
||||
*token_type =
|
||||
video_widevine::ClientIdentification::BOOT_CERTIFICATE_CHAIN_X509;
|
||||
} else {
|
||||
// shouldn't happen
|
||||
LOGE("Unexpected BCC type: %d", static_cast<int>(bcc_type));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case kClientTokenDrmCertificateReprovisioning:
|
||||
*token_type =
|
||||
video_widevine::ClientIdentification::DRM_DEVICE_CERTIFICATE;
|
||||
|
||||
@@ -11,59 +11,6 @@
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
// Generate Derived Keys for ContentKeySession
|
||||
OEMCryptoResult ContentKeySession::GenerateDerivedKeys(
|
||||
const std::string& message) {
|
||||
std::string mac_deriv_message;
|
||||
std::string enc_deriv_message;
|
||||
GenerateMacContext(message, &mac_deriv_message);
|
||||
GenerateEncryptContext(message, &enc_deriv_message);
|
||||
|
||||
LOGV("Generating derived keys: id = %u", oec_session_id_);
|
||||
OEMCryptoResult sts;
|
||||
M_TIME(sts = OEMCrypto_GenerateDerivedKeys(
|
||||
oec_session_id_,
|
||||
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_generate_derived_keys_, sts);
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
LOGE("OEMCrypto_GenerateDerivedKeys failed: status = %d",
|
||||
static_cast<int>(sts));
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
// Generate Derived Keys (from session key) for ContentKeySession
|
||||
OEMCryptoResult ContentKeySession::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);
|
||||
|
||||
LOGV("Generating derived keys from session key: id = %u", oec_session_id_);
|
||||
OEMCryptoResult sts;
|
||||
M_TIME(
|
||||
sts = OEMCrypto_DeriveKeysFromSessionKey(
|
||||
oec_session_id_, 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("OEMCrypto_DeriveKeysFromSessionKey failed: status = %d",
|
||||
static_cast<int>(sts));
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
// Load Keys for ContentKeySession
|
||||
OEMCryptoResult ContentKeySession::LoadKeys(
|
||||
const std::string& message, const std::string& signature,
|
||||
|
||||
@@ -248,38 +248,6 @@ OEMCrypto_Substring GetSubstring(const std::string& message,
|
||||
return substring;
|
||||
}
|
||||
|
||||
void GenerateMacContext(const std::string& input_context,
|
||||
std::string* deriv_context) {
|
||||
if (!deriv_context) {
|
||||
LOGE("Output parameter |deriv_context| not provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string kSigningKeyLabel = "AUTHENTICATION";
|
||||
const size_t kSigningKeySizeBits = wvcdm::MAC_KEY_SIZE * 8;
|
||||
|
||||
deriv_context->assign(kSigningKeyLabel);
|
||||
deriv_context->append(1, '\0');
|
||||
deriv_context->append(input_context);
|
||||
deriv_context->append(wvutil::EncodeUint32(kSigningKeySizeBits * 2));
|
||||
}
|
||||
|
||||
void GenerateEncryptContext(const std::string& input_context,
|
||||
std::string* deriv_context) {
|
||||
if (!deriv_context) {
|
||||
LOGE("Output parameter |deriv_context| not provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string kEncryptionKeyLabel = "ENCRYPTION";
|
||||
const size_t kEncryptionKeySizeBits = wvcdm::CONTENT_KEY_SIZE * 8;
|
||||
|
||||
deriv_context->assign(kEncryptionKeyLabel);
|
||||
deriv_context->append(1, '\0');
|
||||
deriv_context->append(input_context);
|
||||
deriv_context->append(wvutil::EncodeUint32(kEncryptionKeySizeBits));
|
||||
}
|
||||
|
||||
OEMCryptoCipherMode ToOEMCryptoCipherMode(CdmCipherMode cipher_mode) {
|
||||
return cipher_mode == kCipherModeCtr ? OEMCrypto_CipherMode_CENC
|
||||
: OEMCrypto_CipherMode_CBCS;
|
||||
@@ -696,6 +664,24 @@ CdmResponseType CryptoSession::GetProvisioningToken(
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::GetProvisioning40TokenType(
|
||||
OEMCrypto_BCCType* bcc_type) {
|
||||
RETURN_IF_NOT_OPEN(CRYPTO_SESSION_NOT_OPEN);
|
||||
return GetProvisioning40TokenType(requested_security_level_, bcc_type);
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::GetProvisioning40TokenType(
|
||||
RequestedSecurityLevel requested_security_level,
|
||||
OEMCrypto_BCCType* bcc_type) {
|
||||
RETURN_IF_NULL(bcc_type, PARAMETER_NULL);
|
||||
RETURN_IF_UNINITIALIZED(CRYPTO_SESSION_NOT_INITIALIZED);
|
||||
OEMCryptoResult sts = WithOecReadLock("GetBCCType", [&] {
|
||||
return OEMCrypto_GetBCCType(requested_security_level, bcc_type);
|
||||
});
|
||||
return MapOEMCryptoResult(sts, UNKNOWN_CLIENT_TOKEN_TYPE,
|
||||
"GetProvisioning40TokenType");
|
||||
}
|
||||
|
||||
CdmSecurityLevel CryptoSession::GetSecurityLevel() {
|
||||
LOGV("Getting security level");
|
||||
RETURN_IF_NOT_OPEN(kSecurityLevelUninitialized);
|
||||
@@ -1104,7 +1090,6 @@ CdmResponseType CryptoSession::PrepareAndSignLicenseRequest(
|
||||
"PrepareAndSignLicenseRequest");
|
||||
}
|
||||
|
||||
#ifdef HAS_DUAL_KEY
|
||||
CdmResponseType CryptoSession::UseSecondaryKey(bool dual_key) {
|
||||
OEMCryptoResult sts;
|
||||
WithOecSessionLock("UseSecondaryKey", [&] {
|
||||
@@ -1113,13 +1098,10 @@ CdmResponseType CryptoSession::UseSecondaryKey(bool dual_key) {
|
||||
|
||||
return MapOEMCryptoResult(sts, LOAD_KEY_ERROR, "UseSecondaryKey");
|
||||
}
|
||||
#else
|
||||
CdmResponseType CryptoSession::UseSecondaryKey(bool /* dual_key */) {
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
#endif
|
||||
|
||||
CdmResponseType CryptoSession::LoadLicense(const std::string& signed_message,
|
||||
CdmResponseType CryptoSession::LoadLicense(const std::string& context,
|
||||
const std::string& session_key,
|
||||
const std::string& signed_message,
|
||||
const std::string& core_message,
|
||||
const std::string& signature,
|
||||
CdmLicenseKeyType key_type) {
|
||||
@@ -1135,6 +1117,9 @@ CdmResponseType CryptoSession::LoadLicense(const std::string& signed_message,
|
||||
|
||||
M_TIME(sts = OEMCrypto_LoadLicense(
|
||||
oec_session_id_,
|
||||
reinterpret_cast<const uint8_t*>(context.data()), context.size(),
|
||||
reinterpret_cast<const uint8_t*>(session_key.data()),
|
||||
session_key.size(),
|
||||
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||
combined_message.size(), core_message.size(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
@@ -1262,8 +1247,6 @@ CdmResponseType CryptoSession::PrepareAndSignProvisioningRequest(
|
||||
// TODO: b/305093063 - Refactor to a switch statement to improve readability
|
||||
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) {
|
||||
should_specify_algorithm = true;
|
||||
WithOecSessionLock("LoadOEMPrivateKey", [&] {
|
||||
@@ -1764,26 +1747,6 @@ CdmResponseType CryptoSession::SelectKey(const std::string& key_id,
|
||||
}
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::GenerateDerivedKeys(const std::string& message) {
|
||||
OEMCryptoResult sts;
|
||||
WithOecSessionLock("GenerateDerivedKeys without session_key",
|
||||
[&] { sts = key_session_->GenerateDerivedKeys(message); });
|
||||
|
||||
return MapOEMCryptoResult(sts, GENERATE_DERIVED_KEYS_ERROR_2,
|
||||
"GenerateDerivedKeys");
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::GenerateDerivedKeys(
|
||||
const std::string& message, const std::string& session_key) {
|
||||
OEMCryptoResult sts;
|
||||
WithOecSessionLock("GenerateDerivedKeys with session_key", [&] {
|
||||
sts = key_session_->GenerateDerivedKeys(message, session_key);
|
||||
});
|
||||
|
||||
return MapOEMCryptoResult(sts, GENERATE_DERIVED_KEYS_ERROR,
|
||||
"GenerateDerivedKeys");
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::GenerateRsaSignature(const std::string& message,
|
||||
std::string* signature,
|
||||
RSA_Padding_Scheme scheme) {
|
||||
@@ -2265,8 +2228,9 @@ bool CryptoSession::SetDestinationBufferType() {
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::LoadProvisioning(
|
||||
const std::string& signed_message, const std::string& core_message,
|
||||
const std::string& signature, std::string* wrapped_private_key) {
|
||||
const std::string& request, const std::string& signed_message,
|
||||
const std::string& core_message, const std::string& signature,
|
||||
std::string* wrapped_private_key) {
|
||||
LOGV("Loading provisioning certificate: id = %u", oec_session_id_);
|
||||
if (wrapped_private_key == nullptr) {
|
||||
LOGE("Missing wrapped |wrapped_private_key|");
|
||||
@@ -2280,6 +2244,7 @@ CdmResponseType CryptoSession::LoadProvisioning(
|
||||
WithOecSessionLock("LoadProvisioning Attempt 1", [&] {
|
||||
M_TIME(status = OEMCrypto_LoadProvisioning(
|
||||
oec_session_id_,
|
||||
reinterpret_cast<const uint8_t*>(request.data()), request.size(),
|
||||
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||
combined_message.size(), core_message.size(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
@@ -2297,6 +2262,7 @@ CdmResponseType CryptoSession::LoadProvisioning(
|
||||
WithOecSessionLock("LoadProvisioning Attempt 2", [&] {
|
||||
M_TIME(status = OEMCrypto_LoadProvisioning(
|
||||
oec_session_id_,
|
||||
reinterpret_cast<const uint8_t*>(request.data()), request.size(),
|
||||
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||
combined_message.size(), core_message.size(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
@@ -2315,6 +2281,64 @@ CdmResponseType CryptoSession::LoadProvisioning(
|
||||
"LoadProvisioning");
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::LoadProvisioningCast(
|
||||
const std::string& derivation_key, const std::string& request,
|
||||
const std::string& signed_message, const std::string& core_message,
|
||||
const std::string& signature, std::string* wrapped_private_key) {
|
||||
LOGV("Loading provisioning certificate: id = %u", oec_session_id_);
|
||||
if (wrapped_private_key == nullptr) {
|
||||
LOGE("Missing wrapped |wrapped_private_key|");
|
||||
return CdmResponseType(PARAMETER_NULL);
|
||||
}
|
||||
|
||||
const std::string combined_message = core_message + signed_message;
|
||||
// Round 1, get the size of the wrapped private key buffer.
|
||||
size_t wrapped_private_key_length = 0;
|
||||
OEMCryptoResult status;
|
||||
WithOecSessionLock("LoadProvisioningCast Attempt 1", [&] {
|
||||
M_TIME(status = OEMCrypto_LoadProvisioningCast(
|
||||
oec_session_id_,
|
||||
reinterpret_cast<const uint8_t*>(derivation_key.data()),
|
||||
derivation_key.size(),
|
||||
reinterpret_cast<const uint8_t*>(request.data()), request.size(),
|
||||
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||
combined_message.size(), core_message.size(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
signature.size(), nullptr, &wrapped_private_key_length),
|
||||
metrics_, oemcrypto_load_provisioning_, status);
|
||||
});
|
||||
|
||||
if (status != OEMCrypto_ERROR_SHORT_BUFFER) {
|
||||
return MapOEMCryptoResult(status, LOAD_PROVISIONING_ERROR,
|
||||
"LoadProvisioningCast");
|
||||
}
|
||||
|
||||
wrapped_private_key->resize(wrapped_private_key_length);
|
||||
|
||||
WithOecSessionLock("LoadProvisioningCast Attempt 2", [&] {
|
||||
M_TIME(status = OEMCrypto_LoadProvisioningCast(
|
||||
oec_session_id_,
|
||||
reinterpret_cast<const uint8_t*>(derivation_key.data()),
|
||||
derivation_key.size(),
|
||||
reinterpret_cast<const uint8_t*>(request.data()), request.size(),
|
||||
reinterpret_cast<const uint8_t*>(combined_message.data()),
|
||||
combined_message.size(), core_message.size(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
signature.size(),
|
||||
reinterpret_cast<uint8_t*>(&wrapped_private_key->front()),
|
||||
&wrapped_private_key_length),
|
||||
metrics_, oemcrypto_load_provisioning_, status);
|
||||
});
|
||||
|
||||
if (status == OEMCrypto_SUCCESS) {
|
||||
wrapped_private_key->resize(wrapped_private_key_length);
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
wrapped_private_key->clear();
|
||||
return MapOEMCryptoResult(status, LOAD_PROVISIONING_ERROR,
|
||||
"LoadProvisioningCast");
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::GetHdcpCapabilities(HdcpCapability* current,
|
||||
HdcpCapability* max) {
|
||||
LOGV("Getting HDCP capabilities: id = %u", oec_session_id_);
|
||||
@@ -2625,10 +2649,15 @@ CdmResponseType CryptoSession::SetDecryptHash(uint32_t frame_number,
|
||||
const std::string& hash) {
|
||||
LOGV("Setting decrypt hash");
|
||||
OEMCryptoResult sts;
|
||||
RETURN_IF_NOT_OPEN(CRYPTO_SESSION_NOT_OPEN);
|
||||
if (hash.size() != sizeof(uint32_t)) {
|
||||
LOGE("Unsupported hash size: hash_size = %zu, expected = %zu", hash.size(),
|
||||
sizeof(uint32_t));
|
||||
return CdmResponseType(UNKNOWN_ERROR);
|
||||
}
|
||||
WithOecSessionLock("SetDecryptHash", [&] {
|
||||
sts = OEMCrypto_SetDecryptHash(
|
||||
oec_session_id_, frame_number,
|
||||
reinterpret_cast<const uint8_t*>(hash.data()), hash.size());
|
||||
const uint32_t crc32 = *reinterpret_cast<const uint32_t*>(hash.data());
|
||||
sts = OEMCrypto_SetDecryptHash(oec_session_id_, frame_number, crc32);
|
||||
metrics_->oemcrypto_set_decrypt_hash_.Increment(sts);
|
||||
});
|
||||
|
||||
@@ -3442,11 +3471,6 @@ CdmResponseType CryptoSession::SetDebugIgnoreKeyboxCount(uint32_t count) {
|
||||
return MapOEMCryptoResult(status, UNKNOWN_ERROR, "SetDebugIgnoreKeyboxCount");
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::SetAllowTestKeybox(bool allow) {
|
||||
OEMCryptoResult status = OEMCrypto_SetAllowTestKeybox(allow);
|
||||
return MapOEMCryptoResult(status, UNKNOWN_ERROR, "SetAllowTestKeybox");
|
||||
}
|
||||
|
||||
okp::SystemFallbackPolicy* CryptoSession::GetOkpFallbackPolicy() {
|
||||
const auto getter = [&]() -> okp::SystemFallbackPolicy* {
|
||||
// If not set, then OTA keybox provisioning is not supported or
|
||||
@@ -3505,40 +3529,40 @@ CdmResponseType CryptoSession::LoadOtaProvisioning(
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
auto CryptoSession::WithStaticFieldWriteLock(const char* tag, Func body)
|
||||
-> decltype(body()) {
|
||||
auto CryptoSession::WithStaticFieldWriteLock(const char* tag,
|
||||
Func body) -> decltype(body()) {
|
||||
LOGV("Static field write lock: %s", tag);
|
||||
std::unique_lock<wvutil::shared_mutex> auto_lock(static_field_mutex_);
|
||||
return body();
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
auto CryptoSession::WithStaticFieldReadLock(const char* tag, Func body)
|
||||
-> decltype(body()) {
|
||||
auto CryptoSession::WithStaticFieldReadLock(const char* tag,
|
||||
Func body) -> decltype(body()) {
|
||||
LOGV("Static field read lock: %s", tag);
|
||||
wvutil::shared_lock<wvutil::shared_mutex> auto_lock(static_field_mutex_);
|
||||
return body();
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
auto CryptoSession::WithOecWriteLock(const char* tag, Func body)
|
||||
-> decltype(body()) {
|
||||
auto CryptoSession::WithOecWriteLock(const char* tag,
|
||||
Func body) -> decltype(body()) {
|
||||
LOGV("OEMCrypto write lock: %s", tag);
|
||||
std::unique_lock<wvutil::shared_mutex> auto_lock(oem_crypto_mutex_);
|
||||
return body();
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
auto CryptoSession::WithOecReadLock(const char* tag, Func body)
|
||||
-> decltype(body()) {
|
||||
auto CryptoSession::WithOecReadLock(const char* tag,
|
||||
Func body) -> decltype(body()) {
|
||||
LOGV("OEMCrypto read lock: %s", tag);
|
||||
wvutil::shared_lock<wvutil::shared_mutex> auto_lock(oem_crypto_mutex_);
|
||||
return body();
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
auto CryptoSession::WithOecSessionLock(const char* tag, Func body)
|
||||
-> decltype(body()) {
|
||||
auto CryptoSession::WithOecSessionLock(const char* tag,
|
||||
Func body) -> decltype(body()) {
|
||||
LOGV("OEMCrypto session lock: %s", tag);
|
||||
wvutil::shared_lock<wvutil::shared_mutex> oec_auto_lock(oem_crypto_mutex_);
|
||||
std::unique_lock<std::mutex> session_auto_lock(oem_crypto_session_mutex_);
|
||||
|
||||
@@ -115,7 +115,7 @@ OEMCryptoResult EntitlementKeySession::SelectKey(const std::string& key_id,
|
||||
|
||||
OEMCrypto_EntitledContentKeyObject EntitlementKeySession::MakeOecEntitledKey(
|
||||
const CryptoKey& input_key, std::string& message) {
|
||||
OEMCrypto_EntitledContentKeyObject output_key;
|
||||
OEMCrypto_EntitledContentKeyObject output_key = {};
|
||||
message.clear();
|
||||
|
||||
const std::string& entitlement_key_id = input_key.entitlement_key_id();
|
||||
|
||||
@@ -113,7 +113,8 @@ std::vector<CryptoKey> ExtractEntitlementKeys(const License& license) {
|
||||
return key_array;
|
||||
}
|
||||
|
||||
std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
||||
std::vector<CryptoKey> ExtractContentKeys(
|
||||
const License& license, video_widevine::ProtocolVersion version) {
|
||||
std::vector<CryptoKey> key_array;
|
||||
|
||||
// Extract content key(s)
|
||||
@@ -130,21 +131,20 @@ std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
||||
// TODO(b/232464183): When we switch to License Protocol 2.2, there will
|
||||
// no longer be padding on these keys, so this
|
||||
// removal code must be removed at the same time.
|
||||
if (license.key(i).key().size() !=
|
||||
CONTENT_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING &&
|
||||
license.key(i).key().size() !=
|
||||
MAC_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING) {
|
||||
const auto padding = version <= video_widevine::VERSION_2_1
|
||||
? LICENSE_PROTOCOL_2_1_PADDING
|
||||
: 0;
|
||||
if (license.key(i).key().size() != CONTENT_KEY_SIZE + padding &&
|
||||
license.key(i).key().size() != MAC_KEY_SIZE + padding) {
|
||||
LOGE(
|
||||
"Skipping key %s because it is an unexpected size. Expected: %zu "
|
||||
"or %zu, Actual: %zu",
|
||||
license.key(i).id().c_str(),
|
||||
CONTENT_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING,
|
||||
MAC_KEY_SIZE + LICENSE_PROTOCOL_2_1_PADDING,
|
||||
license.key(i).key().size());
|
||||
license.key(i).id().c_str(), CONTENT_KEY_SIZE + padding,
|
||||
MAC_KEY_SIZE + padding, license.key(i).key().size());
|
||||
continue;
|
||||
}
|
||||
const size_t length =
|
||||
license.key(i).key().size() - LICENSE_PROTOCOL_2_1_PADDING;
|
||||
license.key(i).key().size() - padding;
|
||||
key.set_key_data(license.key(i).key().substr(0, length));
|
||||
key.set_key_data_iv(license.key(i).iv());
|
||||
if (license.key(i).has_key_control()) {
|
||||
@@ -195,8 +195,11 @@ std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
||||
} // namespace
|
||||
|
||||
CdmLicense::CdmLicense(const CdmSessionId& session_id)
|
||||
: session_id_(session_id),
|
||||
: crypto_session_(nullptr),
|
||||
policy_engine_(nullptr),
|
||||
session_id_(session_id),
|
||||
initialized_(false),
|
||||
protocol_version_(video_widevine::VERSION_2_2),
|
||||
renew_with_client_id_(false),
|
||||
is_offline_(false),
|
||||
use_privacy_mode_(false),
|
||||
@@ -204,17 +207,16 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id)
|
||||
license_key_type_(kLicenseKeyTypeContent) {}
|
||||
|
||||
CdmLicense::CdmLicense(const CdmSessionId& session_id, wvutil::Clock* clock)
|
||||
: session_id_(session_id),
|
||||
: crypto_session_(nullptr),
|
||||
policy_engine_(nullptr),
|
||||
session_id_(session_id),
|
||||
initialized_(false),
|
||||
protocol_version_(video_widevine::VERSION_2_2),
|
||||
renew_with_client_id_(false),
|
||||
is_offline_(false),
|
||||
use_privacy_mode_(false),
|
||||
clock_(clock),
|
||||
license_key_type_(kLicenseKeyTypeContent) {
|
||||
if (!clock_) {
|
||||
LOGW("Input |clock| is null, using default");
|
||||
clock_.reset(new wvutil::Clock());
|
||||
}
|
||||
clock_.reset(clock);
|
||||
}
|
||||
|
||||
CdmLicense::~CdmLicense() {}
|
||||
@@ -244,6 +246,13 @@ bool CdmLicense::Init(bool use_privacy_mode,
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t api_version;
|
||||
if (!session->GetApiVersion(&api_version)) {
|
||||
api_version = 16;
|
||||
}
|
||||
protocol_version_ = api_version >= 19 ? video_widevine::VERSION_2_2
|
||||
: video_widevine::VERSION_2_1;
|
||||
|
||||
crypto_session_ = session;
|
||||
policy_engine_ = policy_engine;
|
||||
use_privacy_mode_ = use_privacy_mode;
|
||||
@@ -338,7 +347,7 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
|
||||
return CdmResponseType(LICENSE_REQUEST_NONCE_GENERATION_ERROR);
|
||||
}
|
||||
license_request.set_key_control_nonce(license_nonce_);
|
||||
license_request.set_protocol_version(video_widevine::VERSION_2_1);
|
||||
license_request.set_protocol_version(protocol_version_);
|
||||
|
||||
// License request is complete. Serialize it.
|
||||
std::string serialized_license_req;
|
||||
@@ -494,7 +503,7 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
|
||||
current_license->set_seconds_since_last_played(seconds_since_last_played);
|
||||
}
|
||||
|
||||
license_request.set_protocol_version(video_widevine::VERSION_2_1);
|
||||
license_request.set_protocol_version(protocol_version_);
|
||||
|
||||
// License request is complete. Serialize it.
|
||||
std::string serialized_license_req;
|
||||
@@ -585,10 +594,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
LOGE("Signed response has no session keys present");
|
||||
return CdmResponseType(SESSION_KEYS_NOT_FOUND);
|
||||
}
|
||||
CdmResponseType status = crypto_session_->GenerateDerivedKeys(
|
||||
key_request_, signed_response.session_key());
|
||||
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
// Extract mac key
|
||||
std::string mac_key_iv;
|
||||
@@ -623,7 +628,7 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
CdmLicenseKeyType key_type = kLicenseKeyTypeEntitlement;
|
||||
std::vector<CryptoKey> key_array = ExtractEntitlementKeys(license);
|
||||
if (key_array.empty()) {
|
||||
key_array = ExtractContentKeys(license);
|
||||
key_array = ExtractContentKeys(license, protocol_version_);
|
||||
key_type = kLicenseKeyTypeContent;
|
||||
}
|
||||
if (key_array.empty()) {
|
||||
@@ -655,18 +660,19 @@ CdmResponseType CdmLicense::HandleKeyResponse(
|
||||
}
|
||||
|
||||
// If the field is not set, it will default to false.
|
||||
status =
|
||||
CdmResponseType status =
|
||||
crypto_session_->UseSecondaryKey(signed_response.using_secondary_key());
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
CdmResponseType resp(NO_CONTENT_KEY);
|
||||
if (kLicenseKeyTypeEntitlement == key_type) {
|
||||
resp =
|
||||
HandleEntitlementKeyResponse(is_restore, signed_message, core_message,
|
||||
signature, key_array, license);
|
||||
resp = HandleEntitlementKeyResponse(
|
||||
is_restore, signed_response.session_key(), signed_message, core_message,
|
||||
signature, key_array, license);
|
||||
} else if (kLicenseKeyTypeContent == key_type) {
|
||||
resp = HandleContentKeyResponse(is_restore, signed_message, core_message,
|
||||
signature, key_array, license);
|
||||
resp = HandleContentKeyResponse(is_restore, signed_response.session_key(),
|
||||
signed_message, core_message, signature,
|
||||
key_array, license);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
@@ -797,6 +803,7 @@ CdmResponseType CdmLicense::RestoreOfflineLicense(
|
||||
LOGW("Could not parse original request.");
|
||||
} else {
|
||||
license_nonce_ = original_license_request.key_control_nonce();
|
||||
protocol_version_ = original_license_request.protocol_version();
|
||||
}
|
||||
|
||||
CdmResponseType sts = HandleKeyResponse(true, license_response);
|
||||
@@ -1026,13 +1033,20 @@ CdmResponseType CdmLicense::PrepareClientId(
|
||||
license_request->mutable_encrypted_client_id();
|
||||
status = service_certificate_.EncryptClientId(crypto_session_, client_id,
|
||||
encrypted_client_id);
|
||||
if (NO_ERROR == status) {
|
||||
license_request->clear_client_id();
|
||||
} else {
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("Failed to encrypt client ID: status = %s",
|
||||
status.ToString().c_str());
|
||||
license_request->clear_encrypted_client_id();
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
license_request->clear_client_id();
|
||||
}
|
||||
|
||||
std::string client_version;
|
||||
if (Properties::GetWVCdmVersion(&client_version)) {
|
||||
license_request->set_client_version(std::move(client_version));
|
||||
}
|
||||
|
||||
return CdmResponseType(NO_ERROR);
|
||||
}
|
||||
|
||||
@@ -1079,15 +1093,19 @@ CdmResponseType CdmLicense::PrepareContentId(
|
||||
}
|
||||
|
||||
CdmResponseType CdmLicense::HandleContentKeyResponse(
|
||||
bool is_restore, const std::string& msg, const std::string& core_message,
|
||||
const std::string& signature, const std::vector<CryptoKey>& key_array,
|
||||
bool is_restore, const std::string& session_key, const std::string& msg,
|
||||
const std::string& core_message, const std::string& signature,
|
||||
const std::vector<CryptoKey>& key_array,
|
||||
const video_widevine::License& license) {
|
||||
if (key_array.empty()) {
|
||||
LOGE("No content keys provided");
|
||||
return CdmResponseType(NO_CONTENT_KEY);
|
||||
}
|
||||
const CdmResponseType resp = crypto_session_->LoadLicense(
|
||||
msg, core_message, signature, kLicenseKeyTypeContent);
|
||||
protocol_version_ <= video_widevine::VERSION_2_1
|
||||
? key_request_
|
||||
: Sha512Hash(key_request_),
|
||||
session_key, msg, core_message, signature, kLicenseKeyTypeContent);
|
||||
if (KEY_ADDED == resp) {
|
||||
loaded_keys_.clear();
|
||||
for (const CryptoKey& key : key_array) {
|
||||
@@ -1099,15 +1117,19 @@ CdmResponseType CdmLicense::HandleContentKeyResponse(
|
||||
}
|
||||
|
||||
CdmResponseType CdmLicense::HandleEntitlementKeyResponse(
|
||||
bool is_restore, const std::string& msg, const std::string& core_message,
|
||||
const std::string& signature, const std::vector<CryptoKey>& key_array,
|
||||
bool is_restore, const std::string& session_key, const std::string& msg,
|
||||
const std::string& core_message, const std::string& signature,
|
||||
const std::vector<CryptoKey>& key_array,
|
||||
const video_widevine::License& license) {
|
||||
if (key_array.empty()) {
|
||||
LOGE("No entitlement keys provided");
|
||||
return CdmResponseType(NO_CONTENT_KEY);
|
||||
}
|
||||
const CdmResponseType resp = crypto_session_->LoadLicense(
|
||||
msg, core_message, signature, kLicenseKeyTypeEntitlement);
|
||||
protocol_version_ <= video_widevine::VERSION_2_1
|
||||
? key_request_
|
||||
: Sha512Hash(key_request_),
|
||||
session_key, msg, core_message, signature, kLicenseKeyTypeEntitlement);
|
||||
|
||||
if (KEY_ADDED != resp) {
|
||||
return resp;
|
||||
|
||||
@@ -1097,7 +1097,10 @@ message ClientIdentification {
|
||||
DRM_DEVICE_CERTIFICATE = 1;
|
||||
REMOTE_ATTESTATION_CERTIFICATE = 2;
|
||||
OEM_DEVICE_CERTIFICATE = 3;
|
||||
// Boot certificate chain in CBOR format.
|
||||
BOOT_CERTIFICATE_CHAIN = 4;
|
||||
// Boot certificate chain in X509 format.
|
||||
BOOT_CERTIFICATE_CHAIN_X509 = 5;
|
||||
}
|
||||
|
||||
message NameValue {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "log.h"
|
||||
#include "odk_structs.h"
|
||||
#include "oemcrypto_adapter.h"
|
||||
#include "wv_attributes.h"
|
||||
|
||||
namespace wvcdm {
|
||||
OEMCryptoResult OEMCrypto_InitializeAndCheckKeybox(
|
||||
@@ -45,11 +46,6 @@ OEMCryptoResult OEMCrypto_SetDebugIgnoreKeyboxCount(uint32_t count) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
OEMCryptoResult OEMCrypto_SetAllowTestKeybox(bool allow) {
|
||||
(void)allow;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session,
|
||||
RequestedSecurityLevel) {
|
||||
return ::OEMCrypto_OpenSession(session);
|
||||
@@ -223,4 +219,16 @@ OEMCryptoResult OEMCrypto_Generic_Verify(
|
||||
signature_length);
|
||||
}
|
||||
|
||||
OEMCryptoResult OEMCrypto_GetBCCType(RequestedSecurityLevel level,
|
||||
OEMCrypto_BCCType* bcc_type) {
|
||||
(void)level;
|
||||
return ::OEMCrypto_GetBCCType(bcc_type);
|
||||
}
|
||||
} // namespace wvcdm
|
||||
|
||||
// Provide default implementation of L3-only functions. WEAK allows them to be
|
||||
// replaced by the L3 if available.
|
||||
|
||||
WEAK OEMCryptoResult OEMCrypto_UseSecondaryKey(OEMCrypto_SESSION, bool) {
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace wvcdm {
|
||||
PolicyEngine::PolicyEngine(CdmSessionId session_id,
|
||||
WvCdmEventListener* event_listener,
|
||||
CryptoSession* crypto_session)
|
||||
: session_id_(session_id),
|
||||
: session_id_(std::move(session_id)),
|
||||
event_listener_(event_listener),
|
||||
license_keys_(new LicenseKeys(crypto_session->GetSecurityLevel())),
|
||||
clock_(new wvutil::Clock()) {
|
||||
@@ -39,12 +39,9 @@ PolicyEngine::PolicyEngine(CdmSessionId session_id,
|
||||
if (version >= kMinOemCryptoApiVersionSupportsRenewalDelayBase) {
|
||||
policy_timers_.reset(new PolicyTimersV18());
|
||||
}
|
||||
} else {
|
||||
LOGW("Failed to get API version: session_id = %s", IdToString(session_id));
|
||||
}
|
||||
|
||||
if (!policy_timers_) {
|
||||
// Use V16 policy timers if getting version failed.
|
||||
if (policy_timers_ == nullptr) {
|
||||
policy_timers_.reset(new PolicyTimersV16());
|
||||
}
|
||||
InitDevice(crypto_session);
|
||||
|
||||
@@ -391,4 +391,10 @@ std::string Sha256Hash(const std::string& data) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::string Sha512Hash(const std::string& data) {
|
||||
std::string hash(CC_SHA512_DIGEST_LENGTH, '\0');
|
||||
CC_SHA512(data.data(), data.size(), reinterpret_cast<uint8_t*>(&hash[0]));
|
||||
return hash;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -417,4 +417,11 @@ std::string Sha256Hash(const std::string& data) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::string Sha512Hash(const std::string& data) {
|
||||
std::string hash(SHA512_DIGEST_LENGTH, '\0');
|
||||
SHA512(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||
reinterpret_cast<uint8_t*>(&hash[0]));
|
||||
return hash;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
# include <CommonCrypto/CommonDigest.h>
|
||||
# define SHA256 CC_SHA256
|
||||
# define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
|
||||
# define SHA512 CC_SHA512
|
||||
# define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
|
||||
# define MD5 CC_MD5
|
||||
# define MD5_DIGEST_LENGTH CC_MD5_DIGEST_LENGTH
|
||||
#else
|
||||
@@ -69,4 +71,10 @@ std::string Sha256Hash(const std::string& data) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::string Sha512Hash(const std::string& data) {
|
||||
std::string hash(SHA512_DIGEST_LENGTH, '\0');
|
||||
SHA512(data.data(), data.size(), reinterpret_cast<uint8_t*>(&hash[0]));
|
||||
return hash;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -12,8 +12,6 @@ namespace wvcdm {
|
||||
namespace {
|
||||
const char kEmptyIdRep[] = "<empty>";
|
||||
const char kNullIdRep[] = "<null>";
|
||||
const char kFalseRep[] = "false";
|
||||
const char kTrueRep[] = "true";
|
||||
|
||||
// Thread local buffer used by UnknownEnumValueToString() to represent
|
||||
// unknown enum values.
|
||||
@@ -898,8 +896,6 @@ const char* IdPtrToString(const std::string* id) {
|
||||
return id->empty() ? kEmptyIdRep : id->c_str();
|
||||
}
|
||||
|
||||
const char* BoolToString(bool value) { return value ? kTrueRep : kFalseRep; }
|
||||
|
||||
const char* OemCryptoResultToString(OEMCryptoResult result) {
|
||||
switch (result) {
|
||||
/* OEMCrypto return values */
|
||||
|
||||
Reference in New Issue
Block a user