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:
Fred Gylys-Colwell
2020-01-18 10:11:24 -08:00
parent 7e2619e379
commit 7665614b2e
132 changed files with 12331 additions and 9341 deletions

View File

@@ -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)) {