Always store the Prov 4.0 OEM cert in global storage
(This is a merge of http://go/wvgerrit/153550.) On CE CDM, storage is split between global and per-origin storage, and one type of storage cannot be used to access the other. (Though, until an upcoming commit lands, the tests will allow it.) On Android, both types of storage access the same filesystem. This means that code may run fine on Android but fail on CE CDM. The OEM Cert in Provisioning 4.0 is a global file that should only exist once, but it was being accessed through the per-origin storage, which would result in a separate OEM Cert being provisioned for each app & origin on CE CDM. This patch changes the Prov 4.0 code to access it through the global storage, using techniques similar to how the Usage Table Header code does this. Test: x86-64 w/ storage separated Test: build_and_run_all_unit_tests.sh Bug: 236400627 Change-Id: I301d250fc9543e62949a4d9fdcbdd109bd941384
This commit is contained in:
@@ -441,6 +441,7 @@ enum CdmResponseType : int32_t {
|
|||||||
PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_2 = 383,
|
PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_2 = 383,
|
||||||
PROVISIONING_4_FAILED_TO_STORE_OEM_CERTIFICATE = 384,
|
PROVISIONING_4_FAILED_TO_STORE_OEM_CERTIFICATE = 384,
|
||||||
PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE = 385,
|
PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE = 385,
|
||||||
|
PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_3 = 386,
|
||||||
// Don't forget to add new values to
|
// Don't forget to add new values to
|
||||||
// * core/test/test_printers.cpp.
|
// * core/test/test_printers.cpp.
|
||||||
// * android/include/mapErrors-inl.h
|
// * android/include/mapErrors-inl.h
|
||||||
|
|||||||
@@ -841,8 +841,9 @@ CdmResponseType CdmEngine::QueryStatus(RequestedSecurityLevel security_level,
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
if (query_token == QUERY_KEY_SYSTEM_ID) {
|
if (query_token == QUERY_KEY_SYSTEM_ID) {
|
||||||
|
wvutil::FileSystem global_file_system;
|
||||||
SystemIdExtractor extractor(security_level, crypto_session.get(),
|
SystemIdExtractor extractor(security_level, crypto_session.get(),
|
||||||
file_system_);
|
&global_file_system);
|
||||||
uint32_t system_id;
|
uint32_t system_id;
|
||||||
if (!extractor.ExtractSystemId(&system_id)) {
|
if (!extractor.ExtractSystemId(&system_id)) {
|
||||||
LOGW("ExtractSystemId failed");
|
LOGW("ExtractSystemId failed");
|
||||||
@@ -1203,9 +1204,16 @@ CdmProvisioningStatus CdmEngine::GetProvisioningStatus(
|
|||||||
if (handle.HasCertificate(property_set.use_atsc_mode())) {
|
if (handle.HasCertificate(property_set.use_atsc_mode())) {
|
||||||
return kProvisioned;
|
return kProvisioned;
|
||||||
}
|
}
|
||||||
if (crypto_session->GetPreProvisionTokenType() == kClientTokenBootCertChain &&
|
if (crypto_session->GetPreProvisionTokenType() == kClientTokenBootCertChain) {
|
||||||
!handle.HasOemCertificate()) {
|
wvutil::FileSystem global_file_system;
|
||||||
return kNeedsOemCertProvisioning;
|
DeviceFiles global_handle(&global_file_system);
|
||||||
|
if (!global_handle.Init(cdm_security_level)) {
|
||||||
|
LOGE("Failed to initialize global device files.");
|
||||||
|
return kUnknownProvisionStatus;
|
||||||
|
}
|
||||||
|
if (!global_handle.HasOemCertificate()) {
|
||||||
|
return kNeedsOemCertProvisioning;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return kNeedsDrmCertProvisioning;
|
return kNeedsDrmCertProvisioning;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -323,24 +323,25 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
|
|||||||
return PROVISIONING_4_FILE_SYSTEM_IS_NULL;
|
return PROVISIONING_4_FILE_SYSTEM_IS_NULL;
|
||||||
}
|
}
|
||||||
const CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();
|
const CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();
|
||||||
DeviceFiles file_handle(file_system);
|
wvutil::FileSystem global_file_system;
|
||||||
if (!file_handle.Init(security_level)) {
|
DeviceFiles global_file_handle(&global_file_system);
|
||||||
LOGE("Failed to initialize DeviceFiles");
|
if (!global_file_handle.Init(security_level)) {
|
||||||
|
LOGE("Failed to initialize global DeviceFiles");
|
||||||
return PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES;
|
return PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProvisioningRequest provisioning_request;
|
ProvisioningRequest provisioning_request;
|
||||||
// Determine the current stage by checking if OEM cert exists.
|
// Determine the current stage by checking if OEM cert exists.
|
||||||
std::string stored_oem_cert;
|
std::string stored_oem_cert;
|
||||||
if (file_handle.HasOemCertificate()) {
|
if (global_file_handle.HasOemCertificate()) {
|
||||||
// This is second stage requesting for DRM cert. We try to use the stored
|
// This is second stage requesting for DRM cert. We try to use the stored
|
||||||
// OEM cert. In case of error, we just fall back to the first stage
|
// OEM cert. In case of error, we just fall back to the first stage
|
||||||
// provisioning (request for an OEM cert).
|
// provisioning (request for an OEM cert).
|
||||||
if (!RetrieveOemCertificateAndLoadPrivateKey(*crypto_session_, file_handle,
|
if (!RetrieveOemCertificateAndLoadPrivateKey(
|
||||||
stored_oem_cert)) {
|
*crypto_session_, global_file_handle, stored_oem_cert)) {
|
||||||
stored_oem_cert.clear();
|
stored_oem_cert.clear();
|
||||||
LOGD("Deleting the stored OEM certificate due to unsuccessful read");
|
LOGD("Deleting the stored OEM certificate due to unsuccessful read");
|
||||||
if (!file_handle.RemoveOemCertificate()) {
|
if (!global_file_handle.RemoveOemCertificate()) {
|
||||||
// This should not happen.
|
// This should not happen.
|
||||||
LOGE("Failed to delete the OEM certificate certificate");
|
LOGE("Failed to delete the OEM certificate certificate");
|
||||||
}
|
}
|
||||||
@@ -507,23 +508,31 @@ CdmResponseType CertificateProvisioning::HandleProvisioning40Response(
|
|||||||
|
|
||||||
const CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();
|
const CdmSecurityLevel security_level = crypto_session_->GetSecurityLevel();
|
||||||
CloseSession();
|
CloseSession();
|
||||||
DeviceFiles file_handle(file_system);
|
wvutil::FileSystem global_file_system;
|
||||||
if (!file_handle.Init(security_level)) {
|
DeviceFiles global_file_handle(&global_file_system);
|
||||||
LOGE("Failed to initialize DeviceFiles");
|
if (!global_file_handle.Init(security_level)) {
|
||||||
|
LOGE("Failed to initialize global DeviceFiles");
|
||||||
return PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_2;
|
return PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the stage of the provisioning by checking if an OEM cert is already
|
// Check the stage of the provisioning by checking if an OEM cert is already
|
||||||
// stored in the file system.
|
// stored in the file system.
|
||||||
if (!file_handle.HasOemCertificate()) {
|
if (!global_file_handle.HasOemCertificate()) {
|
||||||
// No OEM cert already stored => the response is expected to be an OEM cert.
|
// No OEM cert already stored => the response is expected to be an OEM cert.
|
||||||
if (!file_handle.StoreOemCertificate(device_certificate, private_key)) {
|
if (!global_file_handle.StoreOemCertificate(device_certificate,
|
||||||
|
private_key)) {
|
||||||
LOGE("Failed to store provisioning 4 OEM certificate");
|
LOGE("Failed to store provisioning 4 OEM certificate");
|
||||||
return PROVISIONING_4_FAILED_TO_STORE_OEM_CERTIFICATE;
|
return PROVISIONING_4_FAILED_TO_STORE_OEM_CERTIFICATE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The response is assumed to be an DRM cert.
|
// The response is assumed to be an DRM cert.
|
||||||
if (!file_handle.StoreCertificate(device_certificate, private_key)) {
|
DeviceFiles per_origin_file_handle(file_system);
|
||||||
|
if (!per_origin_file_handle.Init(security_level)) {
|
||||||
|
LOGE("Failed to initialize per-origin DeviceFiles");
|
||||||
|
return PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_3;
|
||||||
|
}
|
||||||
|
if (!per_origin_file_handle.StoreCertificate(device_certificate,
|
||||||
|
private_key)) {
|
||||||
LOGE("Failed to store provisioning 4 DRM certificate");
|
LOGE("Failed to store provisioning 4 DRM certificate");
|
||||||
return PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE;
|
return PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -991,6 +991,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
|||||||
case PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE:
|
case PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE:
|
||||||
*os << "PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE";
|
*os << "PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE";
|
||||||
break;
|
break;
|
||||||
|
case PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_3:
|
||||||
|
*os << "PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_3";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*os << "Unknown CdmResponseType";
|
*os << "Unknown CdmResponseType";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -379,6 +379,7 @@ static Status mapCdmResponseType_1_0(wvcdm::CdmResponseType res) {
|
|||||||
case wvcdm::PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_2:
|
case wvcdm::PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_2:
|
||||||
case wvcdm::PROVISIONING_4_FAILED_TO_STORE_OEM_CERTIFICATE:
|
case wvcdm::PROVISIONING_4_FAILED_TO_STORE_OEM_CERTIFICATE:
|
||||||
case wvcdm::PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE:
|
case wvcdm::PROVISIONING_4_FAILED_TO_STORE_DRM_CERTIFICATE:
|
||||||
|
case wvcdm::PROVISIONING_4_FAILED_TO_INITIALIZE_DEVICE_FILES_3:
|
||||||
ALOGW("Returns UNKNOWN error for legacy status: %d", res);
|
ALOGW("Returns UNKNOWN error for legacy status: %d", res);
|
||||||
return Status::ERROR_DRM_UNKNOWN;
|
return Status::ERROR_DRM_UNKNOWN;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user