Suppress error for removing lingering offline licenses.

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

There are situations where an offline license file will remain on the
system after it's usage entry has been deleted.  This would result in
its key set ID being reported as present by the CDM, but any
operations acting upon it will result in an error.

The app should be able to remove the license without error, so long
as the license file exists and no other OEMCrypto operations fail.

This change introduces a new error code LICENSE_USAGE_ENTRY_MISSING,
which indicates that a license's usage entry cannot be found.

A new integration test checks that the CDM can handle the calls to
removeOfflineLicense().

Bug: 137034719
Test: Android unit and integration tests
Change-Id: Ibdbe963b7f7e3ac97b446300d8e3896cdee7abc5
This commit is contained in:
Alex Dale
2020-04-13 14:27:20 -07:00
parent e27bc4ba6a
commit 2a16d70a06
9 changed files with 160 additions and 7 deletions

View File

@@ -5997,6 +5997,107 @@ TEST_F(WvCdmRequestLicenseTest, DISABLED_DecryptPathTest) {
decryptor_->CloseSession(session_id_);
}
// This tests checks that if a valid offline license file is found on
// the device but is missing the usage entry associated with it, that
// the CDM can still remove the license without issuing an error back
// to the calling app.
// This checks two cases:
// 1) The license's entry is outside the range of the table
// 2) The entry in the usage table that the license points to does
// not match the license's key set ID (possible for entry to have
// been overwritten).
TEST_F(WvCdmRequestLicenseTest, RemoveOfflineLicenseWithMissingUsageEntry) {
Unprovision();
Provision();
const CdmSecurityLevel security_level = GetDefaultSecurityLevel();
FileSystem file_system;
DeviceFiles handle(&file_system);
EXPECT_TRUE(handle.Init(security_level));
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
// Setup: Request an offline license to create a valid license file.
// This license will be used to test how the CDM handles request to
// remove it when its entry has been deleted.
decryptor_->OpenSession(config_.key_system(), nullptr, kDefaultCdmIdentifier,
nullptr, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(config_.license_server(), client_auth);
// Save the key set ID for check below.
const std::string original_key_set_id(key_set_id_);
decryptor_->CloseSession(session_id_);
// Retrieve license from storage for later.
DeviceFiles::CdmLicenseData license_data;
DeviceFiles::ResponseType sub_result = DeviceFiles::kNoError;
EXPECT_TRUE(
handle.RetrieveLicense(original_key_set_id, &license_data, &sub_result));
EXPECT_EQ(DeviceFiles::kNoError, sub_result);
// Re-provision.
Unprovision();
handle.DeleteAllFiles();
Provision();
// Part 1: Test when usage entry is out of range of the table.
// Store license from earlier, this will cause ListStoredLicenses() to
// return the key set ID of the setup license.
EXPECT_TRUE(handle.StoreLicense(license_data, &sub_result));
EXPECT_EQ(DeviceFiles::kNoError, sub_result);
std::vector<CdmSecureStopId> key_set_ids;
EXPECT_EQ(NO_ERROR, decryptor_->ListStoredLicenses(
security_level, kDefaultCdmIdentifier, &key_set_ids));
// Note: It is possible that future changes to the CDM will cause this
// check to fail (such by filtering results from ListStoreLicenses).
EXPECT_THAT(key_set_ids, Contains(original_key_set_id));
EXPECT_EQ(NO_ERROR,
decryptor_->RemoveOfflineLicense(
original_key_set_id, security_level, kDefaultCdmIdentifier));
// Verify license has been removed.
EXPECT_EQ(NO_ERROR, decryptor_->ListStoredLicenses(
security_level, kDefaultCdmIdentifier, &key_set_ids));
EXPECT_THAT(key_set_ids, Not(Contains(original_key_set_id)));
// Re-provision.
Unprovision();
handle.DeleteAllFiles();
Provision();
// Part 2: Test when the entry does not match the license's key set ID.
EXPECT_TRUE(handle.StoreLicense(license_data, &sub_result));
EXPECT_EQ(DeviceFiles::kNoError, sub_result);
// Request another license so that the usage table is not empty.
decryptor_->OpenSession(config_.key_system(), nullptr, kDefaultCdmIdentifier,
nullptr, &session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(config_.license_server(), client_auth);
decryptor_->CloseSession(session_id_);
// Get list of existing offline licenses.
EXPECT_EQ(NO_ERROR, decryptor_->ListStoredLicenses(
security_level, kDefaultCdmIdentifier, &key_set_ids));
EXPECT_THAT(key_set_ids, Contains(original_key_set_id));
EXPECT_EQ(NO_ERROR,
decryptor_->RemoveOfflineLicense(
original_key_set_id, security_level, kDefaultCdmIdentifier));
// Verify license has been removed.
EXPECT_EQ(NO_ERROR, decryptor_->ListStoredLicenses(
security_level, kDefaultCdmIdentifier, &key_set_ids));
EXPECT_THAT(key_set_ids, Not(Contains(original_key_set_id)));
}
class WvCdmRequestLicenseRollbackTest
: public WvCdmRequestLicenseTest,
public ::testing::WithParamInterface<SubSampleInfo*> {