Disallow Blank App Package Name on Q and Later

(This is a merge of http://go/wvgerrit/78105)

The Widevine Android CDM should not allow itself to be instantiated
without an app package name, as this breaks SPOID protection.
Unfortunately, pathways exist prior to Android Q that allow this to
happen, and we cannot break these devices by changing the behavior now.
As such, we will only refuse to allow instantiation without an app
package name on devices first launched with Q and later.

This change also migrates the WVDrmFactory and its tests away from
explicitly naming friend classes for individual test, in favor of the
now-recommended "test peer" pattern.

Bug: 65680731
Test: libwvdrmengine_hidl_test
Test: CTS NativeMediaDrmClearkeyTest
Change-Id: Icccd1d8b9972ef6ad7e5b0dbf2d37ec987656385
This commit is contained in:
John W. Bruce
2019-05-03 20:32:52 -07:00
committed by John Bruce
parent a1e94e2eb1
commit edccc13510
3 changed files with 43 additions and 3 deletions

View File

@@ -43,8 +43,10 @@ struct WVDrmFactory : public IDrmFactory {
static WVGenericCryptoInterface sOemCryptoInterface;
static bool areSpoidsEnabled();
static bool isBlankAppPackageNameAllowed();
static int32_t firstApiLevel();
friend class WVDrmFactoryTest_CalculatesSpoidUseCorrectly_Test;
friend class WVDrmFactoryTestPeer;
};
extern "C" IDrmFactory* HIDL_FETCH_IDrmFactory(const char* name);

View File

@@ -71,6 +71,13 @@ Return<void> WVDrmFactory::createPlugin(
return Void();
}
if (!isBlankAppPackageNameAllowed() && appPackageName.empty()) {
ALOGE("Widevine Drm HAL: Failed to create DRM Plugin, blank App Package "
"Name disallowed.");
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, plugin);
return Void();
}
plugin = new WVDrmPlugin(getCDM(), appPackageName.c_str(),
&sOemCryptoInterface, areSpoidsEnabled());
_hidl_cb(Status::OK, plugin);
@@ -78,6 +85,14 @@ Return<void> WVDrmFactory::createPlugin(
}
bool WVDrmFactory::areSpoidsEnabled() {
return firstApiLevel() >= 26; // Android O
}
bool WVDrmFactory::isBlankAppPackageNameAllowed() {
return firstApiLevel() < 29; // Android Q
}
int32_t WVDrmFactory::firstApiLevel() {
// Check what this device's first API level was.
int32_t firstApiLevel =
android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
@@ -87,7 +102,7 @@ bool WVDrmFactory::areSpoidsEnabled() {
firstApiLevel =
android::base::GetIntProperty<int32_t>("ro.build.version.sdk", 0);
}
return firstApiLevel >= 26; // Android O
return firstApiLevel;
}

View File

@@ -33,6 +33,12 @@ const uint8_t kUnknownUUID[16] = {
0x08,0xBC,0xEF,0x32,0x34,0x1A,0x9A,0x26
};
class WVDrmFactoryTestPeer : public WVDrmFactory {
public:
using WVDrmFactory::areSpoidsEnabled;
using WVDrmFactory::isBlankAppPackageNameAllowed;
};
TEST(WVDrmFactoryTest, SupportsSupportedCryptoSchemes) {
WVDrmFactory factory;
@@ -104,7 +110,7 @@ TEST(WVDrmFactoryTest, SupportsSupportedCryptoSchemeWithLevel) {
}
TEST(WVDrmFactoryTest, CalculatesSpoidUseCorrectly) {
WVDrmFactory factory;
WVDrmFactoryTestPeer factory;
int32_t firstApiLevel =
android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
@@ -120,6 +126,23 @@ TEST(WVDrmFactoryTest, CalculatesSpoidUseCorrectly) {
"WVDrmFactory calculated a different SPOID state than expected.";
}
TEST(WVDrmFactoryTest, CalculatesBlankAppPackageNamePermissibilityCorrectly) {
WVDrmFactoryTestPeer factory;
int32_t firstApiLevel =
android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
if (firstApiLevel == 0) {
// First API Level is 0 on factory ROMs, but we can assume the current SDK
// version is the first if it's a factory ROM.
firstApiLevel =
android::base::GetIntProperty<int32_t>("ro.build.version.sdk", 0);
}
bool shouldAllow = (firstApiLevel < 29); // Android Q
EXPECT_EQ(shouldAllow, factory.isBlankAppPackageNameAllowed()) <<
"WVDrmFactory calculated a different Blank App Package Name state than expected.";
}
} // namespace widevine
} // namespace V1_2
} // namespace drm