Android CDM: Removed secure stop tests.

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

Support for secure stop licenses have been dropped.  The MediaDRM
APIs have already documented their deprecation.  Before support can
be removed from the plugin and CDM core implementation, the tests
associated with them must be removed.

This CL removes secure stop tests from the Android CDM integration
test `request_license_test` and from the MediaDRM plugin test
`libwvdrmdrmplugin_hal_test` and `libwvdrmdrmplugin_hidl_test`.

Bug: 242289743
Test: libwvdrmdrmplugin_hal_test request_license_test
Change-Id: Idb7ee53ab8115ce9b9a173eaf0a00f54325863a2
This commit is contained in:
Alex Dale
2022-10-12 17:59:50 -07:00
parent 56ee5f052c
commit d027236719
4 changed files with 40 additions and 1681 deletions

View File

@@ -984,68 +984,6 @@ TEST_F(WvCdmExtendedDurationTest, DecryptionCloseSessionConcurrencyTest) {
decryptor_->CloseSession(session_id);
}
// TODO(rfrias): Rewite this test when OEMCrypto v13 is the minimum version
// supported. The limitation of 50 usage entries are no longer present
// when using usage table header+entries.
TEST_F(WvCdmExtendedDurationTest, DISABLED_UsageOverflowTest) {
Provision();
TestWvCdmClientPropertySet client_property_set;
TestWvCdmClientPropertySet* property_set = nullptr;
CdmSecurityLevel security_level = GetDefaultSecurityLevel();
FileSystem file_system;
DeviceFiles handle(&file_system);
EXPECT_TRUE(handle.Init(security_level));
std::vector<std::string> provider_session_tokens;
EXPECT_TRUE(handle.DeleteAllUsageInfoForApp(
DeviceFiles::GetUsageInfoFileName(""), &provider_session_tokens));
for (size_t i = 0; i < kMaxUsageTableSize + 100; ++i) {
decryptor_->OpenSession(config_.key_system(), property_set,
kDefaultCdmIdentifier, nullptr, &session_id_);
std::string key_id = wvutil::a2bs_hex(
"000000427073736800000000" // blob size and pssh
"EDEF8BA979D64ACEA3C827DCD51D21ED00000022" // Widevine system id
"08011a0d7769646576696e655f74657374220f73" // pssh data
"747265616d696e675f636c697035");
GenerateKeyRequest(key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(config_.license_server(), config_.client_auth(),
false);
decryptor_->CloseSession(session_id_);
}
CdmUsageInfo usage_info;
CdmUsageInfoReleaseMessage release_msg;
CdmResponseType status =
decryptor_->GetUsageInfo("", kDefaultCdmIdentifier, &usage_info);
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
int error_count = 0;
while (usage_info.size() > 0) {
for (size_t i = 0; i < usage_info.size(); ++i) {
release_msg = GetUsageInfoResponse(config_.license_server(),
config_.client_auth(), usage_info[i]);
EXPECT_EQ(NO_ERROR,
decryptor_->ReleaseUsageInfo(release_msg, kDefaultCdmIdentifier))
<< i << "/" << usage_info.size() << " (err " << (error_count++) << ")"
<< release_msg;
}
ASSERT_LE(error_count, 100); // Give up after 100 failures.
status = decryptor_->GetUsageInfo("", kDefaultCdmIdentifier, &usage_info);
switch (status) {
case KEY_MESSAGE:
EXPECT_FALSE(usage_info.empty());
break;
case NO_ERROR:
EXPECT_TRUE(usage_info.empty());
break;
default:
FAIL() << "GetUsageInfo failed with error " << static_cast<int>(status);
break;
}
}
}
// This test verifies that sessions allocated internally during key release
// message generation are deallocated after their time to live period expires
// by timer events (if other sessions are open).
@@ -1342,215 +1280,6 @@ TEST_P(WvCdmStreamingNoPstTest, UsageTest) {
INSTANTIATE_TEST_CASE_P(Cdm, WvCdmStreamingNoPstTest,
::testing::Values(0, 1, 2));
class WvCdmStreamingPstTest : public WvCdmExtendedDurationTest,
public ::testing::WithParamInterface<size_t> {};
TEST_P(WvCdmStreamingPstTest, UsageTest) {
Unprovision();
Provision();
decryptor_->OpenSession(config_.key_system(), nullptr, kDefaultCdmIdentifier,
nullptr, &session_id_);
GenerateKeyRequest(kStreamingClip8PstInitData, kLicenseTypeStreaming);
VerifyKeyRequestResponse(config_.license_server(), config_.client_auth(),
false);
ValidateResponse(video_widevine::STREAMING, true);
int64_t initial_license_duration_remaining = 0;
int64_t initial_playback_duration_remaining = 0;
QueryKeyStatus(true, false, &initial_license_duration_remaining,
&initial_playback_duration_remaining);
sleep(kMinute);
int64_t expected_seconds_since_license_received = kMinute;
int64_t expected_seconds_since_initial_playback = 0;
int64_t expected_seconds_since_last_playback = 0;
for (size_t i = 0; i < GetParam(); ++i) {
// Decrypt data
SubSampleInfo* data = &kEncryptedStreamingClip8SubSample;
for (size_t i = 0; i < data->num_of_subsamples; i++) {
std::vector<uint8_t> decrypt_buffer((data + i)->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(
&(data + i)->key_id, &(data + i)->encrypt_data.front(),
(data + i)->encrypt_data.size(), &(data + i)->iv,
(data + i)->block_offset, &decrypt_buffer[0]);
decryption_parameters.is_encrypted = (data + i)->is_encrypted;
decryption_parameters.is_secure = (data + i)->is_secure;
decryption_parameters.subsample_flags = (data + i)->subsample_flags;
EXPECT_EQ(NO_ERROR,
decryptor_->Decrypt(session_id_, (data + i)->validate_key_id,
decryption_parameters));
EXPECT_EQ((data + i)->decrypt_data, decrypt_buffer);
}
sleep(kMinute);
expected_seconds_since_license_received += kMinute;
expected_seconds_since_initial_playback += kMinute;
expected_seconds_since_last_playback = kMinute;
}
// Query and validate usage information
int64_t license_duration_remaining = 0;
int64_t playback_duration_remaining = 0;
QueryKeyStatus(true, false, &license_duration_remaining,
&playback_duration_remaining);
if (initial_license_duration_remaining == kUnlimitedDurationValue) {
EXPECT_EQ(license_duration_remaining, kUnlimitedDurationValue);
} else {
EXPECT_NEAR(initial_license_duration_remaining - license_duration_remaining,
expected_seconds_since_license_received, kClockTolerance)
<< "initial_license_duration_remaining = "
<< initial_license_duration_remaining
<< ", license_duration_remaining = " << license_duration_remaining;
}
if (initial_playback_duration_remaining == kUnlimitedDurationValue) {
EXPECT_EQ(playback_duration_remaining, kUnlimitedDurationValue);
} else {
EXPECT_NEAR(initial_playback_duration_remaining - playback_duration_remaining,
expected_seconds_since_initial_playback, kClockTolerance)
<< "initial_playback_duration_remaining = "
<< initial_playback_duration_remaining
<< ", playback_duration_remaining = " << playback_duration_remaining;
}
decryptor_->CloseSession(session_id_);
}
INSTANTIATE_TEST_CASE_P(Cdm, WvCdmStreamingPstTest, ::testing::Values(0, 1, 2));
class WvCdmStreamingUsageReportTest
: public WvCdmExtendedDurationTest,
public ::testing::WithParamInterface<size_t> {};
TEST_P(WvCdmStreamingUsageReportTest, UsageTest) {
Unprovision();
Provision();
decryptor_->OpenSession(config_.key_system(), nullptr, kDefaultCdmIdentifier,
nullptr, &session_id_);
GenerateKeyRequest(kStreamingClip8PstInitData, kLicenseTypeStreaming);
VerifyKeyRequestResponse(config_.license_server(), config_.client_auth(),
false);
ValidateResponse(video_widevine::STREAMING, true);
int64_t initial_license_duration_remaining = 0;
int64_t initial_playback_duration_remaining = 0;
QueryKeyStatus(true, false, &initial_license_duration_remaining,
&initial_playback_duration_remaining);
sleep(kMinute);
int64_t expected_seconds_since_license_received = kMinute;
int64_t expected_seconds_since_initial_playback = 0;
int64_t expected_seconds_since_last_playback = 0;
for (size_t i = 0; i < GetParam(); ++i) {
// Decrypt data
SubSampleInfo* data = &kEncryptedStreamingClip8SubSample;
for (size_t i = 0; i < data->num_of_subsamples; i++) {
std::vector<uint8_t> decrypt_buffer((data + i)->encrypt_data.size());
CdmDecryptionParameters decryption_parameters(
&(data + i)->key_id, &(data + i)->encrypt_data.front(),
(data + i)->encrypt_data.size(), &(data + i)->iv,
(data + i)->block_offset, &decrypt_buffer[0]);
decryption_parameters.is_encrypted = (data + i)->is_encrypted;
decryption_parameters.is_secure = (data + i)->is_secure;
decryption_parameters.subsample_flags = (data + i)->subsample_flags;
EXPECT_EQ(NO_ERROR,
decryptor_->Decrypt(session_id_, (data + i)->validate_key_id,
decryption_parameters));
EXPECT_EQ((data + i)->decrypt_data, decrypt_buffer);
}
sleep(kMinute);
expected_seconds_since_license_received += kMinute;
expected_seconds_since_initial_playback += kMinute;
expected_seconds_since_last_playback = kMinute;
}
// Query and validate usage information
int64_t license_duration_remaining = 0;
int64_t playback_duration_remaining = 0;
QueryKeyStatus(true, false, &license_duration_remaining,
&playback_duration_remaining);
// For unlimited "rental durations", the "license duration" will
// effectively be unlimited. Remaining license duration in this
// case is represented by |kUnlimitedDurationValue| and will not
// change over time.
if (initial_license_duration_remaining == kUnlimitedDurationValue) {
EXPECT_EQ(license_duration_remaining, kUnlimitedDurationValue);
} else {
EXPECT_NEAR(initial_license_duration_remaining - license_duration_remaining,
expected_seconds_since_license_received, kClockTolerance)
<< "initial_license_duration_remaining = "
<< initial_license_duration_remaining
<< ", license_duration_remaining = " << license_duration_remaining;
}
if (initial_playback_duration_remaining == kUnlimitedDurationValue) {
EXPECT_EQ(playback_duration_remaining, kUnlimitedDurationValue);
} else {
EXPECT_NEAR(initial_playback_duration_remaining - playback_duration_remaining,
expected_seconds_since_initial_playback, kClockTolerance)
<< "initial_playback_duration_remaining = "
<< initial_playback_duration_remaining
<< ", playback_duration_remaining = " << playback_duration_remaining;
}
decryptor_->CloseSession(session_id_);
// Create usage report and validate
CdmUsageInfo usage_info;
CdmUsageInfoReleaseMessage release_msg;
CdmResponseType status =
decryptor_->GetUsageInfo("", kDefaultCdmIdentifier, &usage_info);
EXPECT_EQ(usage_info.empty() ? NO_ERROR : KEY_MESSAGE, status);
int error_count = 0;
while (usage_info.size() > 0) {
for (size_t i = 0; i < usage_info.size(); ++i) {
ValidateReleaseRequest(usage_info[i],
expected_seconds_since_initial_playback != 0,
expected_seconds_since_license_received,
expected_seconds_since_initial_playback,
expected_seconds_since_last_playback);
release_msg = GetUsageInfoResponse(config_.license_server(),
config_.client_auth(), usage_info[i]);
EXPECT_EQ(NO_ERROR,
decryptor_->ReleaseUsageInfo(release_msg, kDefaultCdmIdentifier))
<< i << "/" << usage_info.size() << " (err " << (error_count++) << ")"
<< release_msg;
}
ASSERT_LE(error_count, 100); // Give up after 100 failures.
status = decryptor_->GetUsageInfo("", kDefaultCdmIdentifier, &usage_info);
switch (status) {
case KEY_MESSAGE:
EXPECT_FALSE(usage_info.empty());
break;
case NO_ERROR:
EXPECT_TRUE(usage_info.empty());
break;
default:
FAIL() << "GetUsageInfo failed with error " << static_cast<int>(status);
break;
}
}
// Validate that update usage table entry is exercised.
drm_metrics::WvCdmMetrics metrics;
ASSERT_EQ(NO_ERROR, decryptor_->GetMetrics(kDefaultCdmIdentifier, &metrics));
ValidateHasUpdateUsageEntry(metrics);
}
INSTANTIATE_TEST_CASE_P(Cdm, WvCdmStreamingUsageReportTest,
::testing::Values(0, 1, 2));
class WvCdmOfflineUsageReportTest
: public WvCdmExtendedDurationTest,
public ::testing::WithParamInterface<size_t> {};

File diff suppressed because it is too large Load Diff

View File

@@ -47,8 +47,6 @@ using ::aidl::android::hardware::drm::KeyValue;
using ::aidl::android::hardware::drm::OfflineLicenseState;
using ::aidl::android::hardware::drm::ProvideProvisionResponseResult;
using ::aidl::android::hardware::drm::ProvisionRequest;
using ::aidl::android::hardware::drm::SecureStop;
using ::aidl::android::hardware::drm::SecureStopId;
using ::aidl::android::hardware::drm::SecurityLevel;
using ::aidl::android::hardware::drm::Status;
@@ -91,10 +89,7 @@ using wvcdm::CdmOfflineLicenseState;
using wvcdm::CdmProvisioningRequest;
using wvcdm::CdmProvisioningResponse;
using wvcdm::CdmQueryMap;
using wvcdm::CdmSecureStopId;
using wvcdm::CdmSecurityLevel;
using wvcdm::CdmUsageInfo;
using wvcdm::CdmUsageInfoReleaseMessage;
using wvcdm::EMPTY_ORIGIN;
using wvcdm::kCertificateWidevine;
using wvcdm::KEY_ID_SIZE;
@@ -222,22 +217,6 @@ public:
bool),
(override));
MOCK_METHOD(CdmResponseType, GetUsageInfo,
(const std::string &, const CdmIdentifier &, CdmUsageInfo *),
(override));
MOCK_METHOD(CdmResponseType, GetUsageInfo,
(const std::string &, const CdmSecureStopId &,
const CdmIdentifier &, CdmUsageInfo *),
(override));
MOCK_METHOD(CdmResponseType, RemoveAllUsageInfo,
(const std::string &, const CdmIdentifier &), (override));
MOCK_METHOD(CdmResponseType, ReleaseUsageInfo,
(const CdmUsageInfoReleaseMessage &, const CdmIdentifier &),
(override));
MOCK_METHOD(bool, IsValidServiceCertificate, (const std::string &),
(override));
@@ -980,75 +959,6 @@ TEST_F(WVDrmPluginHalTest, RejectsAtscUnprovisionDeviceRequests) {
ASSERT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
}
TEST_F(WVDrmPluginHalTest, GetsSecureStops) {
static const uint32_t kStopSize = 53;
static const uint32_t kStopCount = 7;
uint8_t stopsRaw[kStopCount][kStopSize];
FILE *fp = fopen("/dev/urandom", "r");
ASSERT_NE(fp, nullptr) << "Failed to open /dev/urandom";
for (uint32_t i = 0; i < kStopCount; ++i) {
fread(stopsRaw[i], sizeof(uint8_t), kStopSize, fp);
}
fclose(fp);
CdmUsageInfo mCdmStops;
for (uint32_t i = 0; i < kStopCount; ++i) {
mCdmStops.push_back(std::string(stopsRaw[i], stopsRaw[i] + kStopSize));
}
const char *app_id = "my_app_id";
EXPECT_CALL(*mCdm, GetUsageInfo(StrEq(app_id), _, _))
.WillOnce(
DoAll(SetArgPointee<2>(mCdmStops), testing::Return(wvcdm::NO_ERROR)));
auto ret =
mPlugin->setPropertyString(std::string("appId"), std::string(app_id));
EXPECT_TRUE(ret.isOk());
std::vector<SecureStop> secureStops;
ret = mPlugin->getSecureStops(&secureStops);
EXPECT_TRUE(ret.isOk());
std::vector<std::vector<uint8_t>> stops;
for (const auto &stop : secureStops) {
stops.push_back(stop.opaqueData);
}
size_t index = 0;
for (const auto &stop : stops) {
EXPECT_THAT(stop, ElementsAreArray(stopsRaw[index++], kStopSize));
}
EXPECT_EQ(kStopCount, index);
}
TEST_F(WVDrmPluginHalTest, ReleasesAllSecureStops) {
EXPECT_CALL(*mCdm, RemoveAllUsageInfo(StrEq(""), _)).Times(1);
auto ret = mPlugin->setPropertyString(std::string("appId"), "");
EXPECT_TRUE(ret.isOk());
ret = mPlugin->releaseAllSecureStops();
EXPECT_TRUE(ret.isOk());
}
TEST_F(WVDrmPluginHalTest, ReleasesSecureStop) {
static const uint32_t kMessageSize = 128;
uint8_t messageRaw[kMessageSize];
FILE *fp = fopen("/dev/urandom", "r");
ASSERT_NE(fp, nullptr) << "Failed to open /dev/urandom";
fread(messageRaw, sizeof(uint8_t), kMessageSize, fp);
fclose(fp);
EXPECT_CALL(*mCdm,
ReleaseUsageInfo(ElementsAreArray(messageRaw, kMessageSize), _))
.Times(1);
SecureStopId stopId;
stopId.secureStopId.assign(messageRaw, messageRaw + kMessageSize);
auto ret = mPlugin->releaseSecureStop(stopId);
EXPECT_TRUE(ret.isOk());
}
TEST_F(WVDrmPluginHalTest, ReturnsExpectedPropertyValues) {
CdmQueryMap l1Map;
l1Map[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;

View File

@@ -59,16 +59,6 @@ using ::testing::Values;
using ::testing::WithParamInterface;
using ::testing::internal::ElementsAreArrayMatcher;
using wvcdm::kCertificateWidevine;
using wvcdm::kKeyRequestTypeInitial;
using wvcdm::kKeyRequestTypeRelease;
using wvcdm::kKeyRequestTypeRenewal;
using wvcdm::kLicenseTypeOffline;
using wvcdm::kLicenseTypeRelease;
using wvcdm::kLicenseTypeStreaming;
using wvcdm::kSecurityLevelL1;
using wvcdm::kSecurityLevelL3;
using wvutil::Base64Encode;
using wvcdm::CdmAppParameterMap;
using wvcdm::CdmCertificateType;
using wvcdm::CdmClientPropertySet;
@@ -84,10 +74,7 @@ using wvcdm::CdmOfflineLicenseState;
using wvcdm::CdmProvisioningRequest;
using wvcdm::CdmProvisioningResponse;
using wvcdm::CdmQueryMap;
using wvcdm::CdmSecureStopId;
using wvcdm::CdmSecurityLevel;
using wvcdm::CdmUsageInfo;
using wvcdm::CdmUsageInfoReleaseMessage;
using wvcdm::EMPTY_ORIGIN;
using wvcdm::kCertificateWidevine;
using wvcdm::KEY_ID_SIZE;
@@ -121,6 +108,7 @@ using wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1;
using wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3;
using wvcdm::SESSION_ID_PREFIX;
using wvcdm::WvCdmEventListener;
using wvutil::Base64Encode;
namespace {
const std::string kEmptyString;
@@ -204,21 +192,6 @@ class MockCDM : public WvContentDecryptionModule {
MOCK_METHOD(bool, IsProvisioned, (CdmSecurityLevel, const std::string&,
const std::string&, bool), (override));
MOCK_METHOD(CdmResponseType, GetUsageInfo, (const std::string&,
const CdmIdentifier&,
CdmUsageInfo*), (override));
MOCK_METHOD(CdmResponseType, GetUsageInfo, (const std::string&,
const CdmSecureStopId&,
const CdmIdentifier&,
CdmUsageInfo*), (override));
MOCK_METHOD(CdmResponseType, RemoveAllUsageInfo, (const std::string&,
const CdmIdentifier&), (override));
MOCK_METHOD(CdmResponseType, ReleaseUsageInfo,
(const CdmUsageInfoReleaseMessage&, const CdmIdentifier&), (override));
MOCK_METHOD(bool, IsValidServiceCertificate, (const std::string&), (override));
MOCK_METHOD(CdmResponseType, GetMetrics, (const CdmIdentifier&,
@@ -1144,96 +1117,6 @@ TEST_F(WVDrmPluginTest, RejectsAtscUnprovisionDeviceRequests) {
ASSERT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
}
TEST_F(WVDrmPluginTest, GetsSecureStops) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
static const uint32_t kStopSize = 53;
static const uint32_t kStopCount = 7;
uint8_t stopsRaw[kStopCount][kStopSize];
FILE* fp = fopen("/dev/urandom", "r");
for (uint32_t i = 0; i < kStopCount; ++i) {
fread(stopsRaw[i], sizeof(uint8_t), kStopSize, fp);
}
fclose(fp);
CdmUsageInfo cdmStops;
for (uint32_t i = 0; i < kStopCount; ++i) {
cdmStops.push_back(std::string(stopsRaw[i], stopsRaw[i] + kStopSize));
}
const char* app_id = "my_app_id";
EXPECT_CALL(*cdm, GetUsageInfo(StrEq(app_id), _, _))
.WillOnce(
DoAll(SetArgPointee<2>(cdmStops), testing::Return(wvcdm::NO_ERROR)));
std::vector<std::vector<uint8_t>> stops;
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false);
Status status =
plugin.setPropertyString(hidl_string("appId"), hidl_string(app_id));
ASSERT_EQ(Status::OK, status);
plugin.getSecureStops([&](Status status, hidl_vec<SecureStop> hSecureStops) {
ASSERT_EQ(Status::OK, status);
std::vector<SecureStop> secureStops(hSecureStops);
std::vector<SecureStop>::iterator iter = secureStops.begin();
std::vector<uint8_t> stop;
while (iter != secureStops.end()) {
stop = (*iter++).opaqueData;
stops.push_back(stop);
}
});
size_t index = 0;
for (auto stop : stops) {
EXPECT_THAT(stop, ElementsAreArray(stopsRaw[index++], kStopSize));
}
EXPECT_EQ(kStopCount, index);
}
TEST_F(WVDrmPluginTest, ReleasesAllSecureStops) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
EXPECT_CALL(*cdm, RemoveAllUsageInfo(StrEq(""), _)).Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false);
Status status =
plugin.setPropertyString(hidl_string("appId"), hidl_string(""));
ASSERT_EQ(Status::OK, status);
status = plugin.releaseAllSecureStops();
ASSERT_EQ(Status::OK, status);
}
TEST_F(WVDrmPluginTest, ReleasesSecureStop) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;
std::string appPackageName;
static const uint32_t kMessageSize = 128;
uint8_t messageRaw[kMessageSize];
FILE* fp = fopen("/dev/urandom", "r");
fread(messageRaw, sizeof(uint8_t), kMessageSize, fp);
fclose(fp);
std::vector<uint8_t> message;
message.assign(messageRaw, messageRaw + kMessageSize);
EXPECT_CALL(*cdm,
ReleaseUsageInfo(ElementsAreArray(messageRaw, kMessageSize), _))
.Times(1);
WVDrmPlugin plugin(cdm.get(), appPackageName, &crypto, false);
Status status = plugin.releaseSecureStop(toHidlVec(message));
ASSERT_EQ(Status::OK, status);
}
TEST_F(WVDrmPluginTest, ReturnsExpectedPropertyValues) {
android::sp<StrictMock<MockCDM>> cdm = new StrictMock<MockCDM>();
StrictMock<MockCrypto> crypto;