removeOfflineLicense() respects plugin security level.

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

The MediaDrm plugin API removeOfflineLicense() would check both
L1 and L3 for the offline license.  While this is generally acceptable,
apps might force set L3 via the setStringProperty(), which should
cause the DRM plugin to behave as if it is L3 only.

This change will cause the WVDrmPlugin only remove L3 key set IDs while
in L3 mode.  L1 key set IDs in this case will be treated as non-existing.

Bug: 357863269
Bug: 372105842
Test: DRM Compliance ATP via ABTD
Test: libwvdrmdrmplugin_hal_test on Oriole
Change-Id: I81dddbacaee28da6c0a94527b0e390e86f55f81f
(cherry picked from commit 0aa6aad1af)
This commit is contained in:
Alex Dale
2024-10-08 15:36:39 -07:00
parent 71fce8f352
commit f1da7b637d
3 changed files with 72 additions and 8 deletions

View File

@@ -134,7 +134,8 @@ class WVDrmPlugin : public ::aidl::android::hardware::drm::BnDrmPlugin,
::ndk::ScopedAStatus removeKeys(
const std::vector<uint8_t>& in_sessionId) override;
::ndk::ScopedAStatus removeOfflineLicense(
const ::aidl::android::hardware::drm::KeySetId& in_keySetId) override;
const ::aidl::android::hardware::drm::KeySetId& in_keySetIdPackage)
override;
::ndk::ScopedAStatus removeSecureStop(
const ::aidl::android::hardware::drm::SecureStopId& in_secureStopId)
override;

View File

@@ -1071,8 +1071,9 @@ Status WVDrmPlugin::unprovisionDevice() {
}
::ndk::ScopedAStatus WVDrmPlugin::removeOfflineLicense(
const ::aidl::android::hardware::drm::KeySetId& in_keySetId) {
if (in_keySetId.keySetId.empty()) {
const ::aidl::android::hardware::drm::KeySetId& keySetIdPackage) {
const auto& keySetId = keySetIdPackage.keySetId;
if (keySetId.empty()) {
return toNdkScopedAStatus(Status::BAD_VALUE);
}
@@ -1082,12 +1083,18 @@ Status WVDrmPlugin::unprovisionDevice() {
return toNdkScopedAStatus(status);
}
const std::vector<CdmSecurityLevel> levels = {wvcdm::kSecurityLevelL1,
wvcdm::kSecurityLevelL3};
const CdmKeySetId cdmKeySetId(in_keySetId.keySetId.begin(),
in_keySetId.keySetId.end());
std::vector<CdmSecurityLevel> levelsToCheck;
if (mPropertySet.security_level() != wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3) {
// Do not attempt to remove an L1 offline licenses if the DRM plugin
// is in L3-only mode.
levelsToCheck.push_back(wvcdm::kSecurityLevelL1);
}
// Always check L3, as "default" may imply either.
levelsToCheck.push_back(wvcdm::kSecurityLevelL3);
for (const CdmSecurityLevel level : levels) {
const CdmKeySetId cdmKeySetId(keySetId.begin(), keySetId.end());
for (const CdmSecurityLevel level : levelsToCheck) {
std::vector<CdmKeySetId> keySetIds;
const CdmResponseType res =
mCDM->ListStoredLicenses(level, identifier, &keySetIds);

View File

@@ -3115,6 +3115,62 @@ TEST_F(WVDrmPluginHalTest, RemoveOfflineLicense_NotFound) {
ASSERT_FALSE(status.isOk());
}
TEST_F(WVDrmPluginHalTest, RemoveOfflineLicense_L3_OnlyMode) {
// Key set to remove.
const CdmKeySetId cdmKeySetId = "ksidDEADBEAF";
const KeySetId keySetId{
std::vector<uint8_t>(cdmKeySetId.begin(), cdmKeySetId.end())};
// Desired key set ID is found in L3.
const std::vector<CdmKeySetId> cdmKeySetIdsL3 = {
"ksidDEADC0DE", "ksid1337", cdmKeySetId, "ksidBAD", "ksidCAFEB0BA"};
// In L3 mode, there should be no call to L1.
EXPECT_CALL(*mCdm, ListStoredLicenses(kSecurityLevelL1, _, _)).Times(0);
EXPECT_CALL(*mCdm, ListStoredLicenses(kSecurityLevelL3, _, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(cdmKeySetIdsL3),
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
// Only call L3.
EXPECT_CALL(*mCdm, RemoveOfflineLicense(_, kSecurityLevelL1, _)).Times(0);
EXPECT_CALL(*mCdm, RemoveOfflineLicense(cdmKeySetId, kSecurityLevelL3, _))
.WillOnce(testing::Return(CdmResponseType(wvcdm::NO_ERROR)));
// After setting L3 mode, only L3 should be checked for removal.
mPlugin->setPropertyString("securityLevel",
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3);
const auto status = mPlugin->removeOfflineLicense(keySetId);
ASSERT_TRUE(status.isOk());
}
TEST_F(WVDrmPluginHalTest, RemoveOfflineLicense_L3_OnlyMode_NotFound) {
// Key set to remove.
const CdmKeySetId cdmKeySetId = "ksidDEADBEAF";
const KeySetId keySetId{
std::vector<uint8_t>(cdmKeySetId.begin(), cdmKeySetId.end())};
// Desired key set ID is not found in L3.
const std::vector<CdmKeySetId> cdmKeySetIdsL3 = {"ksidDEADC0DE", "ksid1337",
"ksidBAD", "ksidCAFEB0BA"};
// In L3 mode, there should be no call to L1.
EXPECT_CALL(*mCdm, ListStoredLicenses(kSecurityLevelL1, _, _)).Times(0);
EXPECT_CALL(*mCdm, ListStoredLicenses(kSecurityLevelL3, _, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(cdmKeySetIdsL3),
testing::Return(CdmResponseType(wvcdm::NO_ERROR))));
// No call to RemoveOfflineLicense should be made.
EXPECT_CALL(*mCdm, RemoveOfflineLicense(_, _, _)).Times(0);
// After setting L3 mode, only L3 should be checked for removal.
mPlugin->setPropertyString("securityLevel",
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3);
const auto status = mPlugin->removeOfflineLicense(keySetId);
ASSERT_FALSE(status.isOk());
}
TEST_F(WVDrmPluginHalTest, CanStoreAtscLicense) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;