Ignore certain errors on RemoveOfflineLicense().

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

The CDM API RemoveOfflineLicense() is used to remove an offline
license by key set ID.  From the app's perspective, removing the
offline license should not depend on an app to be provisioned, or
the license being loadable.  However, internally, the CDM attempts
to restore the license to lock out its usage entry.

An issue arises when the license is not able to be restored, which
will cause errors related to the restoration to be returned to the
app.  The license is still deleted in case of errors, but certain
partners have experienced GTS failures when using the MediaDRM API
removeOfflineLicense().

This change attempts to catch some of the common errors, but not all.
If certain errors are encountered during the restoration process, the
are not returned to the app.

Additional error cases may be added later, depending on vendor
feedback.

Bug: 319055420
Bug: 357863269
Bug: 370195605
Bug: 288118860
Bug: 302049654
Bug: 346845333
Bug: 312595506
Bug: 345232142
Bug: 303261245
Bug: 287735498
Bug: 372105842
Test: WVTS on Oriole
Change-Id: I020bbea30e5f6e0ae2777d8a1d4858c4f2af107b
This commit is contained in:
Alex Dale
2024-10-18 15:43:56 -07:00
parent 39c12039cb
commit 5194959c8c
6 changed files with 250 additions and 41 deletions

View File

@@ -1504,20 +1504,38 @@ CdmResponseType CdmEngine::RemoveOfflineLicense(
CdmResponseType sts = OpenKeySetSession(key_set_id, &property_set,
nullptr /* event listener */);
if (sts == NEED_PROVISIONING) {
// It is possible that an app unprovisioned after requesting some
// licenses. RemoveOfflineLicense() should be allowed to work
// with or without provisioning.
LOGW("Not provisioned, deleting license: %s", IdToString(key_set_id));
// TODO(b/372105842): Mark usage entry as unused.
handle.DeleteLicense(key_set_id);
return CdmResponseType(NO_ERROR);
}
if (sts != NO_ERROR) {
LOGE("OpenKeySetSession failed: status = %d", static_cast<int>(sts));
handle.DeleteLicense(key_set_id);
return sts;
}
// Attempt to lock out the license's usage entry to prevent file
// restoration by generating a release request.
// This step should not directly effect the app, as the app is not
// requesting the release. See enumerated errors below.
CdmSessionId session_id;
CdmAppParameterMap dummy_app_params;
const InitializationData dummy_init_data("", "", "");
CdmKeyRequest key_request;
// Calling with no session_id is okay
CdmKeyRequest release_request_unused;
// Calling with no session_id is okay.
// License will be restored by GenerateKeyRequest().
sts = GenerateKeyRequest(session_id, key_set_id, dummy_init_data,
kLicenseTypeRelease, dummy_app_params, &key_request);
kLicenseTypeRelease, dummy_app_params,
&release_request_unused);
if (sts == KEY_MESSAGE) {
// Release was successfully generated, use CDM session
// to properly delete all license data.
std::unique_lock<std::mutex> lock(release_key_sets_lock_);
CdmReleaseKeySetMap::iterator iter = release_key_sets_.find(key_set_id);
if (iter == release_key_sets_.end()) {
@@ -1535,10 +1553,32 @@ CdmResponseType CdmEngine::RemoveOfflineLicense(
LOGW("License usage entry is missing, deleting license file");
handle.DeleteLicense(key_set_id);
sts = CdmResponseType(NO_ERROR);
} else if (sts == LOAD_LICENSE_ERROR || sts == LOAD_DRM_PRIVATE_KEY_ERROR ||
sts == RELEASE_LICENSE_ERROR_1 || sts == NEED_PROVISIONING) {
// It is possible that the DRM certificate associated with this
// license has been replaced/updated or that the root of trust has
// been updated (invalidating the DRM certificate).
// it will no longer be possible to load the license for release;
// and the file should simply be deleted.
LOGW("License could not be restored, deleting license file: status = %s",
sts.ToString().c_str());
handle.DeleteLicense(key_set_id);
sts = CdmResponseType(NO_ERROR);
} else if (sts == GENERATE_SIGNATURE_ERROR) {
// It is possible that OEMCrypto does not have a key to generate
// a signature for release request. The app is trying to remove
// not release, so failure related to generating the release
// request should not cause this to fail.
LOGW("License could not be released, deleting license file: status = %s",
sts.ToString().c_str());
handle.DeleteLicense(key_set_id);
sts = CdmResponseType(NO_ERROR);
}
if (sts != NO_ERROR) {
LOGE("GenerateKeyRequest failed: status = %d", static_cast<int>(sts));
// Errors not caught above should be treated as an error,
// and the license file should be deleted.
LOGE("GenerateKeyRequest failed: status = %s", sts.ToString().c_str());
handle.DeleteLicense(key_set_id);
}
CloseKeySetSession(key_set_id);

View File

@@ -1391,7 +1391,7 @@ CdmResponseType CryptoSession::LoadCertificatePrivateKey(
metrics_, oemcrypto_load_device_drm_key_, sts);
});
return MapOEMCryptoResult(sts, LOAD_DEVICE_RSA_KEY_ERROR,
return MapOEMCryptoResult(sts, LOAD_DRM_PRIVATE_KEY_ERROR,
"LoadCertificatePrivateKey");
}

View File

@@ -719,8 +719,8 @@ const char* CdmResponseEnumToString(CdmResponseEnum cdm_response_enum) {
return "SESSION_LOST_STATE_ERROR";
case GENERATE_DERIVED_KEYS_ERROR_2:
return "GENERATE_DERIVED_KEYS_ERROR_2";
case LOAD_DEVICE_RSA_KEY_ERROR:
return "LOAD_DEVICE_RSA_KEY_ERROR";
case LOAD_DRM_PRIVATE_KEY_ERROR:
return "LOAD_DRM_PRIVATE_KEY_ERROR";
case NONCE_GENERATION_ERROR:
return "NONCE_GENERATION_ERROR";
case GENERATE_SIGNATURE_ERROR: