Add Cdm support for Cast provision 4.0 flow

[ Merge of http://go/wvgerrit/178135 ]

Bug: 259455235
Test: CorePIGTest.CastReceiverProvisioning*
Test: com.google.android.wvts
Change-Id: I8d546a73a64a71a4d61225d9c6d14d893decce22
(cherry picked from commit 494da3dddf0f47e516e6fc1a73e19b091e6c2abd)
This commit is contained in:
Kyle Zhang
2023-07-07 20:28:37 +00:00
parent b0c3e69962
commit 14f7594f5e
4 changed files with 128 additions and 23 deletions

View File

@@ -209,7 +209,8 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal(
if (crypto_session_->GetPreProvisionTokenType() ==
kClientTokenBootCertChain) {
return GetProvisioning40RequestInternal(file_system, origin, spoid, request,
default_url);
default_url, cert_type,
cert_authority);
}
// Prepare device provisioning request.
@@ -235,21 +236,8 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal(
sizeof(nonce));
provisioning_request.set_nonce(encoded_nonce);
ProvisioningOptions* options = provisioning_request.mutable_options();
switch (cert_type) {
case kCertificateWidevine:
options->set_certificate_type(ProvisioningOptions::WIDEVINE_DRM);
break;
case kCertificateX509:
options->set_certificate_type(ProvisioningOptions::X509);
break;
default:
LOGE("Unknown certificate type: %d", static_cast<int>(cert_type));
return CdmResponseType(CERT_PROVISIONING_INVALID_CERT_TYPE);
}
cert_type_ = cert_type;
options->set_certificate_authority(cert_authority);
status = CertTypeAssign(provisioning_request, cert_type, cert_authority);
if (status != NO_ERROR) return status;
status = SetSpoidParameter(origin, spoid, &provisioning_request);
if (status != NO_ERROR) return status;
@@ -308,7 +296,8 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal(
CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
wvutil::FileSystem* file_system, const std::string& origin,
const std::string& spoid, CdmProvisioningRequest* request,
std::string* default_url) {
std::string* default_url, CdmCertificateType cert_type,
const std::string& cert_authority) {
if (!crypto_session_->IsOpen()) {
LOGE("Crypto session is not open");
return CdmResponseType(PROVISIONING_4_CRYPTO_SESSION_NOT_OPEN);
@@ -391,6 +380,29 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
stored_oem_cert, additional_parameter, provisioning_request,
*service_certificate_);
if (status != NO_ERROR) return status;
// If cert type is X509, provisioning Cast cert.
if (cert_type == kCertificateX509) {
uint32_t nonce;
status = crypto_session_->GenerateNonce(&nonce);
if (status != NO_ERROR) {
LOGE("Failed to generate a nonce: status = %d",
static_cast<int>(status));
return status == NONCE_GENERATION_ERROR
? CdmResponseType(CERT_PROVISIONING_NONCE_GENERATION_ERROR)
: status;
}
// The provisioning server does not convert the nonce to uint32_t, it just
// passes the binary data to the response message.
const std::string encoded_nonce(reinterpret_cast<char*>(&nonce),
sizeof(nonce));
provisioning_request.set_nonce(encoded_nonce);
status = CertTypeAssign(provisioning_request, cert_type, cert_authority);
if (status != NO_ERROR) return status;
}
}
std::string public_key;
@@ -413,6 +425,7 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
std::string serialized_message;
provisioning_request.SerializeToString(&serialized_message);
provisioning_request_message_ = serialized_message;
SignedProvisioningMessage signed_provisioning_msg;
signed_provisioning_msg.set_message(serialized_message);
@@ -509,8 +522,11 @@ CertificateProvisioning::FillEncryptedClientIdWithAdditionalParameter(
}
CdmResponseType CertificateProvisioning::HandleProvisioning40Response(
wvutil::FileSystem* file_system, const std::string& response_message) {
wvutil::FileSystem* file_system,
const SignedProvisioningMessage& signed_response, std::string* cert,
std::string* wrapped_key) {
ProvisioningResponse provisioning_response;
const std::string response_message = signed_response.message();
if (response_message.empty() ||
!provisioning_response.ParseFromString(response_message)) {
return CdmResponseType(PROVISIONING_4_RESPONSE_FAILED_TO_PARSE_MESSAGE);
@@ -538,9 +554,44 @@ CdmResponseType CertificateProvisioning::HandleProvisioning40Response(
LOGE("No private key was generated");
return CdmResponseType(PROVISIONING_4_NO_PRIVATE_KEY);
}
const CryptoWrappedKey private_key(provisioning_40_key_type_,
provisioning_40_wrapped_private_key_);
if (cert_type_ == kCertificateX509) {
// Load csr private key to decrypt session key
auto status = crypto_session_->LoadCertificatePrivateKey(private_key);
if (status != NO_ERROR) {
LOGE("Failed to load x509 certificate.");
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());
if (status != NO_ERROR) {
LOGE("Failed to generate wrapped key for cast cert.");
return status;
}
CloseSession();
*cert = device_certificate;
*wrapped_key = cast_cert_private_key.key();
return CdmResponseType(NO_ERROR);
}
const CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();
CloseSession();
wvutil::FileSystem global_file_system;
@@ -619,7 +670,8 @@ CdmResponseType CertificateProvisioning::HandleProvisioningResponse(
if (signed_response.provisioning_type() ==
SignedProvisioningMessage::PROVISIONING_40) {
return HandleProvisioning40Response(file_system, signed_response.message());
return HandleProvisioning40Response(file_system, signed_response, cert,
wrapped_key);
}
bool error = false;
@@ -839,4 +891,25 @@ CdmResponseType CertificateProvisioning::CloseSessionOnError(
return status;
}
CdmResponseType CertificateProvisioning::CertTypeAssign(
video_widevine::ProvisioningRequest& provisioning_request,
CdmCertificateType cert_type, const std::string& cert_authority) {
ProvisioningOptions* options = provisioning_request.mutable_options();
switch (cert_type) {
case kCertificateWidevine:
options->set_certificate_type(ProvisioningOptions::WIDEVINE_DRM);
break;
case kCertificateX509:
options->set_certificate_type(ProvisioningOptions::X509);
break;
default:
LOGE("Unknown certificate type: %d", static_cast<int>(cert_type));
return CdmResponseType(CERT_PROVISIONING_INVALID_CERT_TYPE);
}
cert_type_ = cert_type;
options->set_certificate_authority(cert_authority);
return CdmResponseType(NO_ERROR);
}
} // namespace wvcdm