OEMCrypto v16.1
Merge of http://go/wvgerrit/93404 This CL updates the Widevine CDM to support OEMCrypto v16.1 Test: Tested in 16.2 CL Bug: 141247171 Change-Id: I69bd993500f6fb63bf6010c8b0250dc7acc3d71b
This commit is contained in:
@@ -174,9 +174,9 @@ CdmResponseType CertificateProvisioning::SetSpoidParameter(
|
||||
SignedProvisioningMessage::ProtocolVersion
|
||||
CertificateProvisioning::GetProtocolVersion() {
|
||||
if (crypto_session_->GetPreProvisionTokenType() == kClientTokenOemCert)
|
||||
return SignedProvisioningMessage::VERSION_3;
|
||||
return SignedProvisioningMessage::PROVISIONING_30;
|
||||
else
|
||||
return SignedProvisioningMessage::VERSION_2;
|
||||
return SignedProvisioningMessage::PROVISIONING_20;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -191,8 +191,9 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
const std::string& cert_authority, const std::string& origin,
|
||||
const std::string& spoid, CdmProvisioningRequest* request,
|
||||
std::string* default_url) {
|
||||
if (!default_url) {
|
||||
LOGE("Output parameter |default_url| is not provided");
|
||||
if (!request || !default_url) {
|
||||
LOGE("Output parameter |%s| is not provided",
|
||||
request ? "default_url" : "request");
|
||||
return CERT_PROVISIONING_REQUEST_ERROR_1;
|
||||
}
|
||||
|
||||
@@ -212,11 +213,10 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
status = id.Init(crypto_session_.get());
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
video_widevine::ClientIdentification* client_id =
|
||||
provisioning_request.mutable_client_id();
|
||||
video_widevine::ClientIdentification client_id;
|
||||
|
||||
CdmAppParameterMap app_parameter;
|
||||
status = id.Prepare(app_parameter, kEmptyString, client_id);
|
||||
status = id.Prepare(app_parameter, kEmptyString, &client_id);
|
||||
if (status != NO_ERROR) return status;
|
||||
|
||||
if (!service_certificate_->has_certificate()) {
|
||||
@@ -228,8 +228,7 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
EncryptedClientIdentification* encrypted_client_id =
|
||||
provisioning_request.mutable_encrypted_client_id();
|
||||
status = service_certificate_->EncryptClientId(
|
||||
crypto_session_.get(), client_id, encrypted_client_id);
|
||||
provisioning_request.clear_client_id();
|
||||
crypto_session_.get(), &client_id, encrypted_client_id);
|
||||
|
||||
uint32_t nonce;
|
||||
status = crypto_session_->GenerateNonce(&nonce);
|
||||
@@ -271,9 +270,10 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
provisioning_request.SerializeToString(&serialized_message);
|
||||
|
||||
// Derives signing and encryption keys and constructs signature.
|
||||
std::string core_message;
|
||||
std::string request_signature;
|
||||
status = crypto_session_->PrepareRequest(serialized_message, true,
|
||||
&request_signature);
|
||||
status = crypto_session_->PrepareAndSignProvisioningRequest(
|
||||
serialized_message, &core_message, &request_signature);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("Failed to prepare provisioning request: status = %d",
|
||||
@@ -290,6 +290,12 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
signed_provisioning_msg.set_message(serialized_message);
|
||||
signed_provisioning_msg.set_signature(request_signature);
|
||||
signed_provisioning_msg.set_protocol_version(GetProtocolVersion());
|
||||
if (core_message.empty()) {
|
||||
// OEMCrypto does not support core messages.
|
||||
supports_core_messages_ = false;
|
||||
} else {
|
||||
signed_provisioning_msg.set_oemcrypto_core_message(core_message);
|
||||
}
|
||||
|
||||
std::string serialized_request;
|
||||
signed_provisioning_msg.SerializeToString(&serialized_request);
|
||||
@@ -298,9 +304,9 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||
// Return request as web-safe base64 string
|
||||
std::vector<uint8_t> request_vector(serialized_request.begin(),
|
||||
serialized_request.end());
|
||||
request->assign(Base64SafeEncodeNoPad(request_vector));
|
||||
*request = Base64SafeEncodeNoPad(request_vector);
|
||||
} else {
|
||||
request->swap(serialized_request);
|
||||
*request = std::move(serialized_request);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
@@ -353,66 +359,59 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (supports_core_messages() &&
|
||||
!signed_response.has_oemcrypto_core_message()) {
|
||||
LOGE("Signed response does not have core message");
|
||||
error = true;
|
||||
} else if (!supports_core_messages() &&
|
||||
signed_response.has_oemcrypto_core_message()) {
|
||||
const std::string& core_message = signed_response.oemcrypto_core_message();
|
||||
// This case should not occur. However, the CDM will let OEMCrypto
|
||||
// fail.
|
||||
LOGW(
|
||||
"Received unexpected core message in provisioning request: "
|
||||
"core_message_size = %zu",
|
||||
core_message.size());
|
||||
}
|
||||
|
||||
if (error) return CERT_PROVISIONING_RESPONSE_ERROR_3;
|
||||
|
||||
const std::string& signed_message = signed_response.message();
|
||||
const std::string& signature = signed_response.signature();
|
||||
ProvisioningResponse provisioning_response;
|
||||
const std::string core_message =
|
||||
supports_core_messages() ? signed_response.oemcrypto_core_message()
|
||||
: std::string();
|
||||
|
||||
ProvisioningResponse provisioning_response;
|
||||
if (!provisioning_response.ParseFromString(signed_message)) {
|
||||
LOGE("Failed to parse provisioning response");
|
||||
return CERT_PROVISIONING_RESPONSE_ERROR_4;
|
||||
}
|
||||
|
||||
if (!provisioning_response.has_device_rsa_key()) {
|
||||
LOGE("Provisioning response does not have RSA key");
|
||||
return CERT_PROVISIONING_RESPONSE_ERROR_5;
|
||||
}
|
||||
|
||||
// If Provisioning 3.0 (OEM Cert provisioned), verify that the
|
||||
// message is properly signed.
|
||||
if (crypto_session_->GetPreProvisionTokenType() == kClientTokenOemCert) {
|
||||
if (service_certificate_->VerifySignedMessage(signed_message, signature) !=
|
||||
NO_ERROR) {
|
||||
// TODO(b/69562876): if the cert is bad, request a new one.
|
||||
LOGE("Provisioning response message not properly signed");
|
||||
return CERT_PROVISIONING_RESPONSE_ERROR_6;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& new_private_key = provisioning_response.device_rsa_key();
|
||||
const std::string& nonce = provisioning_response.nonce();
|
||||
const std::string& iv = provisioning_response.device_rsa_key_iv();
|
||||
|
||||
const std::string& wrapping_key = (provisioning_response.has_wrapping_key())
|
||||
? provisioning_response.wrapping_key()
|
||||
: std::string();
|
||||
|
||||
std::string wrapped_private_key;
|
||||
|
||||
CdmResponseType status = crypto_session_->RewrapCertificate(
|
||||
signed_message, signature, nonce, new_private_key, iv, wrapping_key,
|
||||
&wrapped_private_key);
|
||||
const CdmResponseType status = crypto_session_->LoadProvisioning(
|
||||
signed_message, core_message, signature, &wrapped_private_key);
|
||||
|
||||
if (status != NO_ERROR) {
|
||||
LOGE("RewrapCertificate failed: status = %d", static_cast<int>(status));
|
||||
LOGE("LoadProvisioning failed: status = %d", static_cast<int>(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();
|
||||
const CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();
|
||||
crypto_session_->Close();
|
||||
|
||||
// This is the entire certificate (SignedDrmDeviceCertificate).
|
||||
const std::string& device_certificate =
|
||||
provisioning_response.device_certificate();
|
||||
|
||||
if (cert_type_ == kCertificateX509) {
|
||||
*cert = provisioning_response.device_certificate();
|
||||
*cert = device_certificate;
|
||||
*wrapped_key = wrapped_private_key;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// This is the entire certificate (SignedDrmDeviceCertificate).
|
||||
// This will be stored to the device as the final step in the device
|
||||
// provisioning process.
|
||||
const std::string& device_certificate =
|
||||
provisioning_response.device_certificate();
|
||||
// The certificate will be stored to the device as the final step in
|
||||
// the device provisioning process.
|
||||
|
||||
DeviceFiles handle(file_system);
|
||||
if (!handle.Init(security_level)) {
|
||||
|
||||
Reference in New Issue
Block a user