Merge "Add recoverable errors"

This commit is contained in:
Rahul Frias
2019-01-31 15:26:38 +00:00
committed by Android (Google) Code Review
27 changed files with 977 additions and 648 deletions

View File

@@ -565,10 +565,12 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
query_token == QUERY_KEY_MAX_HDCP_LEVEL) {
CryptoSession::HdcpCapability current_hdcp;
CryptoSession::HdcpCapability max_hdcp;
if (!crypto_session->GetHdcpCapabilities(security_level, &current_hdcp,
&max_hdcp)) {
LOGW("CdmEngine::QueryStatus: GetHdcpCapabilities failed");
return UNKNOWN_ERROR;
status = crypto_session->GetHdcpCapabilities(security_level, &current_hdcp,
&max_hdcp);
if (status != NO_ERROR) {
LOGW("CdmEngine::QueryStatus: GetHdcpCapabilities failed: %d", status);
return status;
}
*query_response =
MapHdcpVersion(query_token == QUERY_KEY_CURRENT_HDCP_LEVEL ?
@@ -594,20 +596,26 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
return NO_ERROR;
} else if (query_token == QUERY_KEY_NUMBER_OF_OPEN_SESSIONS) {
size_t number_of_open_sessions;
if (!crypto_session->GetNumberOfOpenSessions(security_level,
&number_of_open_sessions)) {
LOGW("CdmEngine::QueryStatus: GetNumberOfOpenSessions failed");
return UNKNOWN_ERROR;
status = crypto_session->GetNumberOfOpenSessions(security_level,
&number_of_open_sessions);
if (status != NO_ERROR) {
LOGW("CdmEngine::QueryStatus: GetNumberOfOpenSessions failed: %d",
status);
return status;
}
*query_response = std::to_string(number_of_open_sessions);
return NO_ERROR;
} else if (query_token == QUERY_KEY_MAX_NUMBER_OF_SESSIONS) {
size_t maximum_number_of_sessions = 0;
if (!crypto_session->GetMaxNumberOfSessions(security_level,
&maximum_number_of_sessions)) {
LOGW("CdmEngine::QueryStatus: GetMaxNumberOfOpenSessions failed");
return UNKNOWN_ERROR;
status =
crypto_session->GetMaxNumberOfSessions(security_level,
&maximum_number_of_sessions);
if (status != NO_ERROR) {
LOGW("CdmEngine::QueryStatus: GetMaxNumberOfOpenSessions failed: %d",
status);
return status;
}
*query_response = std::to_string(maximum_number_of_sessions);
@@ -623,9 +631,10 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
return NO_ERROR;
} else if (query_token == QUERY_KEY_CURRENT_SRM_VERSION) {
uint16_t current_srm_version;
if (!crypto_session->GetSrmVersion(&current_srm_version)) {
LOGW("CdmEngine::QueryStatus: GetCurrentSRMVersion failed");
return UNKNOWN_ERROR;
status = crypto_session->GetSrmVersion(&current_srm_version);
if (status != NO_ERROR) {
LOGW("CdmEngine::QueryStatus: GetCurrentSRMVersion failed: %d", status);
return status;
}
*query_response = std::to_string(current_srm_version);
@@ -672,19 +681,16 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
crypto_session_open_,
status,
security_level);
if (status != NO_ERROR)
return status;
if (status != NO_ERROR) return status;
// Add queries here, that need an open session before they can be answered
if (query_token == QUERY_KEY_DEVICE_ID) {
std::string deviceId;
bool got_id = crypto_session->GetExternalDeviceUniqueId(&deviceId);
status = crypto_session->GetExternalDeviceUniqueId(&deviceId);
metrics_.GetCryptoMetrics()->crypto_session_get_device_unique_id_
.Increment(got_id);
if (!got_id) {
LOGW("CdmEngine::QueryStatus: QUERY_KEY_DEVICE_ID unknown failure");
return UNKNOWN_ERROR;
}
.Increment(status);
if (status != NO_ERROR) return status;
*query_response = deviceId;
} else if (query_token == QUERY_KEY_SYSTEM_ID) {
@@ -698,9 +704,10 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
*query_response = std::to_string(system_id);
} else if (query_token == QUERY_KEY_PROVISIONING_ID) {
std::string provisioning_id;
if (!crypto_session->GetProvisioningId(&provisioning_id)) {
LOGW("CdmEngine::QueryStatus: GetProvisioningId failed");
return UNKNOWN_ERROR;
status = crypto_session->GetProvisioningId(&provisioning_id);
if (status != NO_ERROR) {
LOGW("CdmEngine::QueryStatus: GetProvisioningId failed: %d", status);
return status;
}
*query_response = provisioning_id;

View File

@@ -138,14 +138,20 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set,
&serial_number, NULL)) {
return NEED_PROVISIONING;
}
bool load_cert_sts;
CdmResponseType load_cert_sts;
M_TIME(
load_cert_sts = crypto_session_->LoadCertificatePrivateKey(wrapped_key),
crypto_metrics_, crypto_session_load_certificate_private_key_,
load_cert_sts);
if (!load_cert_sts) {
return NEED_PROVISIONING;
switch (load_cert_sts) {
case NO_ERROR: break;
case SESSION_LOST_STATE_ERROR:
case SYSTEM_INVALIDATED_ERROR:
return load_cert_sts;
default:
return NEED_PROVISIONING;
}
client_token_type = kClientTokenDrmCert;
// Session is provisioned with certificate needed to construct
@@ -792,7 +798,8 @@ bool CdmSession::GenerateKeySetId(CdmKeySetId* key_set_id) {
(kKeySetIdLength - sizeof(KEY_SET_ID_PREFIX)) / 2, 0);
while (key_set_id->empty()) {
if (!crypto_session_->GetRandom(random_data.size(), &random_data[0])) {
if (crypto_session_->GetRandom(random_data.size(), &random_data[0])
!= NO_ERROR) {
return false;
}

View File

@@ -122,13 +122,13 @@ CdmResponseType CertificateProvisioning::Init(
* server for determining a unique per origin ID for the device.
* It is also valid (though deprecated) to leave the settings unset.
*/
bool CertificateProvisioning::SetSpoidParameter(
CdmResponseType CertificateProvisioning::SetSpoidParameter(
const std::string& origin, const std::string& spoid,
ProvisioningRequest* request) {
if (!request) {
LOGE("CertificateProvisioning::SetSpoidParameter: No request buffer "
"passed to method.");
return false;
return PARAMETER_NULL;
}
if (!spoid.empty()) {
// Use the SPOID that has been pre-provided
@@ -139,19 +139,22 @@ bool CertificateProvisioning::SetSpoidParameter(
} else {
LOGE("CertificateProvisioning::SetSpoidParameter: Failure getting "
"provider ID");
return false;
return SERVICE_CERTIFICATE_PROVIDER_ID_EMPTY;
}
} else if (origin != EMPTY_ORIGIN) {
// Legacy behavior - Concatenate Unique ID with Origin
std::string device_unique_id;
if (!crypto_session_->GetInternalDeviceUniqueId(&device_unique_id)) {
CdmResponseType status =
crypto_session_->GetInternalDeviceUniqueId(&device_unique_id);
if (status != NO_ERROR) {
LOGE("CertificateProvisioning::SetSpoidParameter: Failure getting "
"device unique ID");
return false;
return status;
}
request->set_stable_id(device_unique_id + origin);
} // No else clause, by design. It is valid to do nothing.
return true;
return NO_ERROR;
}
/*
@@ -219,9 +222,12 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
provisioning_request.clear_client_id();
uint32_t nonce;
if (!crypto_session_->GenerateNonce(&nonce)) {
LOGE("GetProvisioningRequest: fails to generate a nonce");
return CERT_PROVISIONING_NONCE_GENERATION_ERROR;
status = crypto_session_->GenerateNonce(&nonce);
if (status != NO_ERROR) {
LOGE("GetProvisioningRequest: fails to generate a nonce: %d", status);
return status == NONCE_GENERATION_ERROR ?
CERT_PROVISIONING_NONCE_GENERATION_ERROR : status;
}
// The provisioning server does not convert the nonce to uint32_t, it just
@@ -247,20 +253,22 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
cert_type_ = cert_type;
options->set_certificate_authority(cert_authority);
if (!SetSpoidParameter(origin, spoid, &provisioning_request)) {
return CERT_PROVISIONING_GET_KEYBOX_ERROR_2;
}
status = SetSpoidParameter(origin, spoid, &provisioning_request);
if (status != NO_ERROR) return status;
std::string serialized_message;
provisioning_request.SerializeToString(&serialized_message);
// Derives signing and encryption keys and constructs signature.
std::string request_signature;
if (!crypto_session_->PrepareRequest(serialized_message, true,
&request_signature)) {
status = crypto_session_->PrepareRequest(serialized_message, true,
&request_signature);
if (status != NO_ERROR) {
LOGE("GetProvisioningRequest: fails to prepare request");
return CERT_PROVISIONING_REQUEST_ERROR_3;
return status;
}
if (request_signature.empty()) {
LOGE("GetProvisioningRequest: request signature is empty");
return CERT_PROVISIONING_REQUEST_ERROR_4;
@@ -371,11 +379,14 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
std::string wrapped_private_key;
if (!crypto_session_->RewrapCertificate(signed_message, signature, nonce,
CdmResponseType status =
crypto_session_->RewrapCertificate(signed_message, signature, nonce,
new_private_key, iv, wrapping_key,
&wrapped_private_key)) {
&wrapped_private_key);
if (status != NO_ERROR) {
LOGE("HandleProvisioningResponse: RewrapCertificate fails");
return CERT_PROVISIONING_RESPONSE_ERROR_6;
return status;
}
CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();

View File

@@ -90,9 +90,11 @@ CdmResponseType ClientIdentification::Prepare(
client_id->set_type(token_type);
std::string token;
if (!crypto_session_->GetProvisioningToken(&token)) {
LOGE("ClientIdentification::Prepare: failure getting provisioning token");
return CLIENT_IDENTIFICATION_TOKEN_ERROR_2;
CdmResponseType status = crypto_session_->GetProvisioningToken(&token);
if (status != NO_ERROR) {
LOGE("ClientIdentification::Prepare: failure getting provisioning token: "
"%d", status);
return status;
}
client_id->set_token(token);
}
@@ -172,7 +174,8 @@ CdmResponseType ClientIdentification::Prepare(
if (is_license_request_) {
CryptoSession::HdcpCapability current_version, max_version;
if (crypto_session_->GetHdcpCapabilities(&current_version, &max_version)) {
if (crypto_session_->GetHdcpCapabilities(&current_version, &max_version) ==
NO_ERROR) {
switch (max_version) {
case HDCP_NONE:
client_capabilities->set_max_hdcp_version(
@@ -235,7 +238,7 @@ CdmResponseType ClientIdentification::Prepare(
client_capabilities->set_can_update_srm(
crypto_session_->IsSrmUpdateSupported());
uint16_t srm_version;
if (crypto_session_->GetSrmVersion(&srm_version))
if (crypto_session_->GetSrmVersion(&srm_version) == NO_ERROR)
client_capabilities->set_srm_version(srm_version);
}
bool can_support_output;

View File

@@ -11,7 +11,8 @@
namespace wvcdm {
// Generate Derived Keys for ContentKeySession
bool ContentKeySession::GenerateDerivedKeys(const std::string& message) {
OEMCryptoResult ContentKeySession::GenerateDerivedKeys(
const std::string& message) {
std::string mac_deriv_message;
std::string enc_deriv_message;
GenerateMacContext(message, &mac_deriv_message);
@@ -28,15 +29,15 @@ bool ContentKeySession::GenerateDerivedKeys(const std::string& message) {
metrics_, oemcrypto_generate_derived_keys_, sts);
if (OEMCrypto_SUCCESS != sts) {
LOGE("GenerateDerivedKeys: OEMCrypto_GenerateDerivedKeys error=%d", sts);
return false;
}
return true;
return sts;
}
// Generate Derived Keys (from session key) for ContentKeySession
bool ContentKeySession::GenerateDerivedKeys(const std::string& message,
const std::string& session_key) {
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);
@@ -56,10 +57,9 @@ bool ContentKeySession::GenerateDerivedKeys(const std::string& message,
if (OEMCrypto_SUCCESS != sts) {
LOGE("GenerateDerivedKeys: OEMCrypto_DeriveKeysFromSessionKey err=%d", sts);
return false;
}
return true;
return sts;
}
// Load Keys for ContentKeySession

File diff suppressed because it is too large Load Diff

View File

@@ -321,8 +321,16 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
// Get/set the nonce. This value will be reflected in the Key Control Block
// of the license response.
uint32_t nonce;
if (!crypto_session_->GenerateNonce(&nonce)) {
return LICENSE_REQUEST_NONCE_GENERATION_ERROR;
status = crypto_session_->GenerateNonce(&nonce);
switch (status) {
case NO_ERROR:
break;
case SESSION_LOST_STATE_ERROR:
case SYSTEM_INVALIDATED_ERROR:
return status;
default:
return LICENSE_REQUEST_NONCE_GENERATION_ERROR;
}
license_request.set_key_control_nonce(nonce);
LOGD("PrepareKeyRequest: nonce=%u", nonce);
@@ -337,10 +345,12 @@ CdmResponseType CdmLicense::PrepareKeyRequest(
// Derive signing and encryption keys and construct signature.
std::string license_request_signature;
if (!crypto_session_->PrepareRequest(serialized_license_req, false,
&license_request_signature)) {
status = crypto_session_->PrepareRequest(serialized_license_req, false,
&license_request_signature);
if (status != NO_ERROR) {
signed_request->clear();
return LICENSE_REQUEST_SIGNING_ERROR;
return status;
}
if (license_request_signature.empty()) {
@@ -455,8 +465,16 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
// Get/set the nonce. This value will be reflected in the Key Control Block
// of the license response.
uint32_t nonce;
if (!crypto_session_->GenerateNonce(&nonce)) {
return LICENSE_RENEWAL_NONCE_GENERATION_ERROR;
CdmResponseType status = crypto_session_->GenerateNonce(&nonce);
switch (status) {
case NO_ERROR:
break;
case SESSION_LOST_STATE_ERROR:
case SYSTEM_INVALIDATED_ERROR:
return status;
default:
return LICENSE_RENEWAL_NONCE_GENERATION_ERROR;
}
license_request.set_key_control_nonce(nonce);
LOGD("PrepareKeyUpdateRequest: nonce=%u", nonce);
@@ -468,9 +486,9 @@ CdmResponseType CdmLicense::PrepareKeyUpdateRequest(
// Construct signature.
std::string license_request_signature;
if (!crypto_session_->PrepareRenewalRequest(serialized_license_req,
&license_request_signature))
return LICENSE_RENEWAL_SIGNING_ERROR;
status = crypto_session_->PrepareRenewalRequest(serialized_license_req,
&license_request_signature);
if (status != NO_ERROR) return status;
if (license_request_signature.empty()) {
LOGE(
@@ -544,9 +562,11 @@ CdmResponseType CdmLicense::HandleKeyResponse(
LOGE("CdmLicense::HandleKeyResponse: no session keys present");
return SESSION_KEYS_NOT_FOUND;
}
if (!crypto_session_->GenerateDerivedKeys(key_request_,
signed_response.session_key()))
return GENERATE_DERIVED_KEYS_ERROR;
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;
@@ -584,7 +604,17 @@ CdmResponseType CdmLicense::HandleKeyResponse(
license_key_type_ = key_type;
provider_client_token_ = license.provider_client_token();
if (license.has_srm_update()) crypto_session_->LoadSrm(license.srm_update());
if (license.has_srm_update()) {
CdmResponseType status = crypto_session_->LoadSrm(license.srm_update());
switch (status) {
case NO_ERROR:
break;
case SYSTEM_INVALIDATED_ERROR:
return status;
default:
break; // Ignore
}
}
if (license.id().type() == video_widevine::OFFLINE &&
license.policy().can_persist())
@@ -689,15 +719,16 @@ CdmResponseType CdmLicense::HandleKeyUpdateResponse(
std::vector<CryptoKey> key_array = ExtractContentKeys(license);
if (crypto_session_->RefreshKeys(signed_response.msg(),
CdmResponseType status =
crypto_session_->RefreshKeys(signed_response.msg(),
signed_response.signature(),
key_array.size(), &key_array[0])) {
policy_engine_->UpdateLicense(license);
key_array.size(), &key_array[0]);
return KEY_ADDED;
} else {
return REFRESH_KEYS_ERROR;
if (status == KEY_ADDED) {
policy_engine_->UpdateLicense(license);
}
return status;
}
CdmResponseType CdmLicense::HandleEmbeddedKeyData(

View File

@@ -83,7 +83,9 @@ void PolicyEngine::CheckDeviceHdcpStatus() {
if (!license_keys_->Empty()) {
CryptoSession::HdcpCapability current_hdcp_level;
CryptoSession::HdcpCapability ignored;
if (!crypto_session_->GetHdcpCapabilities(&current_hdcp_level, &ignored)) {
CdmResponseType status =
crypto_session_->GetHdcpCapabilities(&current_hdcp_level, &ignored);
if (status != NO_ERROR) {
current_hdcp_level = HDCP_NONE;
}
license_keys_->ApplyConstraints(current_resolution_, current_hdcp_level);

View File

@@ -228,12 +228,24 @@ CdmResponseType ServiceCertificate::EncryptClientId(
std::string iv(KEY_IV_SIZE, 0);
std::string key(SERVICE_KEY_SIZE, 0);
if (!crypto_session->GetRandom(key.size(),
reinterpret_cast<uint8_t*>(&key[0])))
return CLIENT_ID_GENERATE_RANDOM_ERROR;
if (!crypto_session->GetRandom(iv.size(),
reinterpret_cast<uint8_t*>(&iv[0])))
return CLIENT_ID_GENERATE_RANDOM_ERROR;
CdmResponseType status =
crypto_session->GetRandom(key.size(),
reinterpret_cast<uint8_t*>(&key[0]));
if (status != NO_ERROR) {
LOGE("ServiceCertificate::EncryptClientId: GetRandom error: %d", status);
return status == RANDOM_GENERATION_ERROR ?
CLIENT_ID_GENERATE_RANDOM_ERROR : status;
}
status = crypto_session->GetRandom(iv.size(),
reinterpret_cast<uint8_t*>(&iv[0]));
if (status != NO_ERROR) {
LOGE("ServiceCertificate::EncryptClientId: GetRandom error: %d", status);
return status == RANDOM_GENERATION_ERROR ?
CLIENT_ID_GENERATE_RANDOM_ERROR : status;
}
std::string id, enc_id, enc_key;
clear_client_id->SerializeToString(&id);