CDM core: Removed support for v15 provisioning responses.
[ Merge of http://go/wvgerrit/160277 ] OEMCrypto v15 did not require core messages during DRM certificate provisioning. The CDM's certificate provisioning flow was allowing for either case (with or without core messages) when provisioning. Now, devices can safely assume that all provsisioning responses will be v16 or newer; all requests/response must contain a core message. Bug: 252670759 Test: run_x86_64_tests and request_license_test Change-Id: I9f51e07caf642eaf646ef40bdd640b3ccfe2533c
This commit is contained in:
@@ -50,8 +50,6 @@ class CertificateProvisioning {
|
|||||||
wvutil::FileSystem* file_system, const CdmProvisioningResponse& response,
|
wvutil::FileSystem* file_system, const CdmProvisioningResponse& response,
|
||||||
std::string* cert, std::string* wrapped_key);
|
std::string* cert, std::string* wrapped_key);
|
||||||
|
|
||||||
bool supports_core_messages() const { return supports_core_messages_; }
|
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
|
|
||||||
// Extract serial number and system ID from a DRM Device certificate.
|
// Extract serial number and system ID from a DRM Device certificate.
|
||||||
@@ -123,13 +121,6 @@ class CertificateProvisioning {
|
|||||||
// Key type of the generated key pair in provisioning 4.
|
// Key type of the generated key pair in provisioning 4.
|
||||||
CryptoWrappedKey::Type provisioning_40_key_type_;
|
CryptoWrappedKey::Type provisioning_40_key_type_;
|
||||||
|
|
||||||
// Indicates whether OEMCrypto supports core messages, and whether the
|
|
||||||
// CDM should expect a core message in the response. This is primarily
|
|
||||||
// used to distinguish between v16+ OEMCrypto or an earlier version.
|
|
||||||
// Assume core messages are supported, and check if OEMCrypto populates
|
|
||||||
// the core message field when calling PrepAndSignProvisioningRequest().
|
|
||||||
bool supports_core_messages_ = true;
|
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(CertificateProvisioning);
|
CORE_DISALLOW_COPY_AND_ASSIGN(CertificateProvisioning);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -87,8 +87,6 @@ bool RetrieveOemCertificateAndLoadPrivateKey(CryptoSession& crypto_session,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
// Protobuf generated classes.
|
// Protobuf generated classes.
|
||||||
using video_widevine::ClientIdentification_ClientCapabilities;
|
|
||||||
using video_widevine::ClientIdentification_NameValue;
|
|
||||||
using video_widevine::DrmCertificate;
|
using video_widevine::DrmCertificate;
|
||||||
using video_widevine::EncryptedClientIdentification;
|
using video_widevine::EncryptedClientIdentification;
|
||||||
using video_widevine::ProvisioningOptions;
|
using video_widevine::ProvisioningOptions;
|
||||||
@@ -97,8 +95,6 @@ using video_widevine::ProvisioningResponse;
|
|||||||
using video_widevine::PublicKeyToCertify;
|
using video_widevine::PublicKeyToCertify;
|
||||||
using video_widevine::SignedDrmCertificate;
|
using video_widevine::SignedDrmCertificate;
|
||||||
using video_widevine::SignedProvisioningMessage;
|
using video_widevine::SignedProvisioningMessage;
|
||||||
using video_widevine::
|
|
||||||
SignedProvisioningMessage_ProvisioningProtocolVersion_VERSION_1_1;
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void CertificateProvisioning::GetProvisioningServerUrl(
|
void CertificateProvisioning::GetProvisioningServerUrl(
|
||||||
@@ -112,18 +108,16 @@ void CertificateProvisioning::GetProvisioningServerUrl(
|
|||||||
|
|
||||||
CdmResponseType CertificateProvisioning::Init(
|
CdmResponseType CertificateProvisioning::Init(
|
||||||
const std::string& service_certificate) {
|
const std::string& service_certificate) {
|
||||||
std::string certificate = service_certificate.empty()
|
const std::string certificate = service_certificate.empty()
|
||||||
? kCpProductionServiceCertificate
|
? kCpProductionServiceCertificate
|
||||||
: service_certificate;
|
: service_certificate;
|
||||||
return service_certificate_->Init(certificate);
|
return service_certificate_->Init(certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Fill in the appropriate SPOID (Stable Per-Origin IDentifier) option.
|
||||||
* Fill in the appropriate SPOID (Stable Per-Origin IDentifier) option.
|
// One of spoid, provider_id or stable_id will be passed to the provisioning
|
||||||
* One of spoid, provider_id or stable_id will be passed to the provisioning
|
// server for determining a unique per origin ID for the device.
|
||||||
* server for determining a unique per origin ID for the device.
|
// It is also valid (though deprecated) to leave the settings unset.
|
||||||
* It is also valid (though deprecated) to leave the settings unset.
|
|
||||||
*/
|
|
||||||
CdmResponseType CertificateProvisioning::SetSpoidParameter(
|
CdmResponseType CertificateProvisioning::SetSpoidParameter(
|
||||||
const std::string& origin, const std::string& spoid,
|
const std::string& origin, const std::string& spoid,
|
||||||
ProvisioningRequest* request) {
|
ProvisioningRequest* request) {
|
||||||
@@ -135,14 +129,13 @@ CdmResponseType CertificateProvisioning::SetSpoidParameter(
|
|||||||
// Use the SPOID that has been pre-provided
|
// Use the SPOID that has been pre-provided
|
||||||
request->set_spoid(spoid);
|
request->set_spoid(spoid);
|
||||||
} else if (Properties::UseProviderIdInProvisioningRequest()) {
|
} else if (Properties::UseProviderIdInProvisioningRequest()) {
|
||||||
if (!service_certificate_->provider_id().empty()) {
|
if (service_certificate_->provider_id().empty()) {
|
||||||
request->set_provider_id(service_certificate_->provider_id());
|
|
||||||
} else {
|
|
||||||
LOGE(
|
LOGE(
|
||||||
"Failed to set provider ID: "
|
"Failed to set provider ID: "
|
||||||
"Service certificate provider ID is empty");
|
"Service certificate provider ID is empty");
|
||||||
return SERVICE_CERTIFICATE_PROVIDER_ID_EMPTY;
|
return SERVICE_CERTIFICATE_PROVIDER_ID_EMPTY;
|
||||||
}
|
}
|
||||||
|
request->set_provider_id(service_certificate_->provider_id());
|
||||||
} else if (origin != EMPTY_ORIGIN) {
|
} else if (origin != EMPTY_ORIGIN) {
|
||||||
// Legacy behavior - Concatenate Unique ID with Origin
|
// Legacy behavior - Concatenate Unique ID with Origin
|
||||||
std::string device_unique_id;
|
std::string device_unique_id;
|
||||||
@@ -159,10 +152,8 @@ CdmResponseType CertificateProvisioning::SetSpoidParameter(
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Return the provisioning protocol version - dictated by OEMCrypto
|
||||||
* Return the provisioning protocol version - dictated by OEMCrypto
|
// support for OEM certificates.
|
||||||
* support for OEM certificates.
|
|
||||||
*/
|
|
||||||
SignedProvisioningMessage::ProvisioningType
|
SignedProvisioningMessage::ProvisioningType
|
||||||
CertificateProvisioning::GetProvisioningType() {
|
CertificateProvisioning::GetProvisioningType() {
|
||||||
switch (crypto_session_->GetPreProvisionTokenType()) {
|
switch (crypto_session_->GetPreProvisionTokenType()) {
|
||||||
@@ -175,13 +166,11 @@ CertificateProvisioning::GetProvisioningType() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Compose a device provisioning request and output *request in a
|
||||||
* Compose a device provisioning request and output *request in a
|
// JSON-compatible format (web-safe base64).
|
||||||
* JSON-compatible format (web-safe base64).
|
// Also return *default_url of the provisioning server.
|
||||||
* Also return *default_url of the provisioning server.
|
//
|
||||||
*
|
// Returns NO_ERROR for success and CERT_PROVISIONING_REQUEST_ERROR_? if fails.
|
||||||
* Returns NO_ERROR for success and CERT_PROVISIONING_REQUEST_ERROR_? if fails.
|
|
||||||
*/
|
|
||||||
CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
||||||
wvutil::FileSystem* file_system,
|
wvutil::FileSystem* file_system,
|
||||||
RequestedSecurityLevel requested_security_level,
|
RequestedSecurityLevel requested_security_level,
|
||||||
@@ -240,18 +229,17 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal(
|
|||||||
|
|
||||||
// The provisioning server does not convert the nonce to uint32_t, it just
|
// The provisioning server does not convert the nonce to uint32_t, it just
|
||||||
// passes the binary data to the response message.
|
// passes the binary data to the response message.
|
||||||
std::string the_nonce(reinterpret_cast<char*>(&nonce), sizeof(nonce));
|
const std::string encoded_nonce(reinterpret_cast<char*>(&nonce),
|
||||||
provisioning_request.set_nonce(the_nonce);
|
sizeof(nonce));
|
||||||
|
provisioning_request.set_nonce(encoded_nonce);
|
||||||
|
|
||||||
ProvisioningOptions* options = provisioning_request.mutable_options();
|
ProvisioningOptions* options = provisioning_request.mutable_options();
|
||||||
switch (cert_type) {
|
switch (cert_type) {
|
||||||
case kCertificateWidevine:
|
case kCertificateWidevine:
|
||||||
options->set_certificate_type(
|
options->set_certificate_type(ProvisioningOptions::WIDEVINE_DRM);
|
||||||
video_widevine::ProvisioningOptions_CertificateType_WIDEVINE_DRM);
|
|
||||||
break;
|
break;
|
||||||
case kCertificateX509:
|
case kCertificateX509:
|
||||||
options->set_certificate_type(
|
options->set_certificate_type(ProvisioningOptions::X509);
|
||||||
video_widevine::ProvisioningOptions_CertificateType_X509);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOGE("Unknown certificate type: %d", static_cast<int>(cert_type));
|
LOGE("Unknown certificate type: %d", static_cast<int>(cert_type));
|
||||||
@@ -288,14 +276,9 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal(
|
|||||||
signed_provisioning_msg.set_message(serialized_message);
|
signed_provisioning_msg.set_message(serialized_message);
|
||||||
signed_provisioning_msg.set_signature(request_signature);
|
signed_provisioning_msg.set_signature(request_signature);
|
||||||
signed_provisioning_msg.set_provisioning_type(GetProvisioningType());
|
signed_provisioning_msg.set_provisioning_type(GetProvisioningType());
|
||||||
if (core_message.empty()) {
|
signed_provisioning_msg.set_oemcrypto_core_message(core_message);
|
||||||
// OEMCrypto does not support core messages.
|
|
||||||
supports_core_messages_ = false;
|
|
||||||
} else {
|
|
||||||
signed_provisioning_msg.set_oemcrypto_core_message(core_message);
|
|
||||||
}
|
|
||||||
signed_provisioning_msg.set_protocol_version(
|
signed_provisioning_msg.set_protocol_version(
|
||||||
SignedProvisioningMessage_ProvisioningProtocolVersion_VERSION_1_1);
|
SignedProvisioningMessage::VERSION_1_1);
|
||||||
|
|
||||||
std::string serialized_request;
|
std::string serialized_request;
|
||||||
signed_provisioning_msg.SerializeToString(&serialized_request);
|
signed_provisioning_msg.SerializeToString(&serialized_request);
|
||||||
@@ -421,7 +404,7 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
|
|||||||
signed_provisioning_msg.mutable_message());
|
signed_provisioning_msg.mutable_message());
|
||||||
signed_provisioning_msg.set_provisioning_type(GetProvisioningType());
|
signed_provisioning_msg.set_provisioning_type(GetProvisioningType());
|
||||||
signed_provisioning_msg.set_protocol_version(
|
signed_provisioning_msg.set_protocol_version(
|
||||||
SignedProvisioningMessage_ProvisioningProtocolVersion_VERSION_1_1);
|
SignedProvisioningMessage::VERSION_1_1);
|
||||||
|
|
||||||
std::string serialized_request;
|
std::string serialized_request;
|
||||||
signed_provisioning_msg.SerializeToString(&serialized_request);
|
signed_provisioning_msg.SerializeToString(&serialized_request);
|
||||||
@@ -541,13 +524,13 @@ CdmResponseType CertificateProvisioning::HandleProvisioning40Response(
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// The response message consists of a device certificate and the
|
||||||
* The response message consists of a device certificate and the device RSA key.
|
// wrapped device private key (either RSA or ECC). The wrapped device
|
||||||
* The device RSA key is stored in the T.E.E. The device certificate is stored
|
// private key is loaded into the TEE, unwrapped, verified and
|
||||||
* in the device.
|
// re-wrapped. The device certificate and re-wrapped device private
|
||||||
*
|
// key are stored on the device.
|
||||||
* Returns NO_ERROR for success and CERT_PROVISIONING_RESPONSE_ERROR_? if fails.
|
//
|
||||||
*/
|
// Returns NO_ERROR for success and CERT_PROVISIONING_RESPONSE_ERROR_? if fails.
|
||||||
CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
||||||
wvutil::FileSystem* file_system,
|
wvutil::FileSystem* file_system,
|
||||||
const CdmProvisioningResponse& response_message, std::string* cert,
|
const CdmProvisioningResponse& response_message, std::string* cert,
|
||||||
@@ -597,30 +580,16 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
|||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supports_core_messages() &&
|
if (!signed_response.has_oemcrypto_core_message()) {
|
||||||
(!signed_response.has_oemcrypto_core_message() ||
|
|
||||||
signed_response.oemcrypto_core_message().empty())) {
|
|
||||||
LOGE("Signed response does not have core message");
|
LOGE("Signed response does not have core message");
|
||||||
error = true;
|
error = true;
|
||||||
} else if (!supports_core_messages() &&
|
|
||||||
(signed_response.has_oemcrypto_core_message() &&
|
|
||||||
!signed_response.oemcrypto_core_message().empty())) {
|
|
||||||
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;
|
if (error) return CERT_PROVISIONING_RESPONSE_ERROR_3;
|
||||||
|
|
||||||
const std::string& signed_message = signed_response.message();
|
const std::string& signed_message = signed_response.message();
|
||||||
const std::string& signature = signed_response.signature();
|
const std::string& signature = signed_response.signature();
|
||||||
const std::string core_message =
|
const std::string& core_message = signed_response.oemcrypto_core_message();
|
||||||
supports_core_messages() ? signed_response.oemcrypto_core_message()
|
|
||||||
: std::string();
|
|
||||||
|
|
||||||
ProvisioningResponse provisioning_response;
|
ProvisioningResponse provisioning_response;
|
||||||
if (!provisioning_response.ParseFromString(signed_message)) {
|
if (!provisioning_response.ParseFromString(signed_message)) {
|
||||||
@@ -630,7 +599,7 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
|||||||
|
|
||||||
if (provisioning_response.has_status()) {
|
if (provisioning_response.has_status()) {
|
||||||
if (provisioning_response.status() != ProvisioningResponse::NO_ERROR) {
|
if (provisioning_response.status() != ProvisioningResponse::NO_ERROR) {
|
||||||
LOGE("Provisioning Response status: %d", provisioning_response.status());
|
LOGE("Provisioning response status: %d", provisioning_response.status());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (provisioning_response.status()) {
|
switch (provisioning_response.status()) {
|
||||||
@@ -699,7 +668,6 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
|
|||||||
|
|
||||||
// The certificate will be stored to the device as the final step in
|
// The certificate will be stored to the device as the final step in
|
||||||
// the device provisioning process.
|
// the device provisioning process.
|
||||||
|
|
||||||
DeviceFiles handle(file_system);
|
DeviceFiles handle(file_system);
|
||||||
if (!handle.Init(security_level)) {
|
if (!handle.Init(security_level)) {
|
||||||
LOGE("Failed to initialize DeviceFiles");
|
LOGE("Failed to initialize DeviceFiles");
|
||||||
@@ -785,7 +753,7 @@ bool CertificateProvisioning::ExtractDeviceInfo(
|
|||||||
DrmCertificate drm_certificate;
|
DrmCertificate drm_certificate;
|
||||||
if (!drm_certificate.ParseFromString(
|
if (!drm_certificate.ParseFromString(
|
||||||
signed_drm_certificate.drm_certificate()) ||
|
signed_drm_certificate.drm_certificate()) ||
|
||||||
(drm_certificate.type() != video_widevine::DrmCertificate::DEVICE)) {
|
(drm_certificate.type() != DrmCertificate::DEVICE)) {
|
||||||
LOGE("Failed to parse DRM device certificate message");
|
LOGE("Failed to parse DRM device certificate message");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user