Specify DRM certificate duration in tests.

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

Certain integration tests were depending on the provisioning server
only sending short duration (~2 minute) certificates when testing
the CDM's ability to enforce expiration periods.  This behavior of
the server was not reliable, resulting in device test failures from
server behavior changes.

The DRM certificate provisioning server allows the requester to
optionally provide a desired certificate duration in the request
URL.  The tests which test the CDM's ability to enforce certificate
durations will now explicitly specify the certificate duration
required by the test.

Bug: 228547158
Test: request_license_test
Change-Id: Ib9ebfdba1451104be0e59baca0b2f23a94cd51e6
This commit is contained in:
Alex Dale
2022-04-15 20:14:51 -07:00
parent 47ebc28f6a
commit cc35c64757
4 changed files with 71 additions and 27 deletions

View File

@@ -92,7 +92,7 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
CdmProvisioningRequest* request, std::string* default_url);
virtual CdmResponseType HandleProvisioningResponse(
const CdmIdentifier& identifier, CdmProvisioningResponse& response,
const CdmIdentifier& identifier, const CdmProvisioningResponse& response,
RequestedSecurityLevel requested_security_level, std::string* cert,
std::string* wrapped_key);

View File

@@ -227,7 +227,7 @@ CdmResponseType WvContentDecryptionModule::GetProvisioningRequest(
}
CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse(
const CdmIdentifier& identifier, CdmProvisioningResponse& response,
const CdmIdentifier& identifier, const CdmProvisioningResponse& response,
RequestedSecurityLevel requested_security_level, std::string* cert,
std::string* wrapped_key) {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);

View File

@@ -52,7 +52,11 @@ namespace {
// HTTP response codes.
const int kHttpOk = 200;
const int kDrmCertificateExpiryPeriod = 150;
// For tests checking functionality of expiring.
constexpr uint32_t kDrmCertificateExpiryPeriod = 120;
constexpr uint32_t kDrmCertificateExpirySleepPeriod =
kDrmCertificateExpiryPeriod + 30;
const wvcdm::CdmIdentifier kExampleIdentifier = {
wvcdm::EMPTY_SPOID, "com.example", "com.example", 7, 9};
@@ -1868,11 +1872,26 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
// Post a request and extract the signed provisioning message from
// the HTTP response.
std::string GetCertRequestResponse(const std::string& server_url) {
// Setting a non-zero value to |duration_seconds| will request a
// limited duration DRM certificate.
std::string GetCertRequestResponse(const std::string& server_url,
uint32_t duration_seconds = 0) {
// Use secure connection and chunk transfer coding.
UrlRequest url_request(server_url);
std::string actual_url = server_url;
if (duration_seconds > 0) {
const auto query_start = actual_url.find('?');
if (query_start == std::string::npos) {
actual_url.push_back('?');
} else {
actual_url.push_back('&');
}
actual_url.append("options.expiration_delta_seconds=");
actual_url.append(std::to_string(duration_seconds));
}
UrlRequest url_request(actual_url);
EXPECT_TRUE(url_request.is_connected())
<< "Fail to connect to " << server_url;
<< "Fail to connect to " << actual_url;
url_request.PostCertRequestInQueryString(key_msg_);
std::string message;
EXPECT_TRUE(url_request.GetResponse(&message));
@@ -2573,6 +2592,10 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningRevocationTest) {
}
}
// Test checks that the CDM correctly reports provisioning status when
// a certificate has expired. It is expected that the CDM reports that
// the specified CDM engine is provisioned only during the certificate's
// validity period.
TEST_F(WvCdmRequestLicenseTest, ProvisioningWithExpiringCertTest) {
EXPECT_EQ(NO_ERROR,
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
@@ -2584,7 +2607,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningWithExpiringCertTest) {
// Provision
std::string provisioning_server;
CdmCertificateType cert_type = kCertificateWidevine;
const CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
@@ -2592,18 +2615,19 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningWithExpiringCertTest) {
kEmptyServiceCertificate, kLevelDefault,
&key_msg_, &provisioning_server));
std::string response = GetCertRequestResponse(config.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
const std::string response = GetCertRequestResponse(
config.provisioning_server(), kDrmCertificateExpiryPeriod);
EXPECT_FALSE(response.empty()) << "Failed to get DRM provisioning response";
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
kExampleIdentifier, response, kLevelDefault,
&cert, &wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
decryptor_->CloseSession(session_id_);
EXPECT_TRUE(cert.empty()) << "Widevine certs should not be returned";
EXPECT_TRUE(wrapped_key.empty())
<< "Keys from Widevine certs should not be returned";
// Make sure it is provisioned, then wait for certificate expiry period
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
sleep(kDrmCertificateExpiryPeriod);
sleep(kDrmCertificateExpirySleepPeriod);
// Verify that it is no longer provisioned after the certificate expires
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
@@ -2781,6 +2805,8 @@ TEST_F(WvCdmRequestLicenseTest, AddStreamingKeyTest) {
decryptor_->CloseSession(session_id_);
}
// Test checks that the CDM does not allow key request generations
// if the DRM certificate is expired.
TEST_F(WvCdmRequestLicenseTest, StreamingWithExpiringCertTest) {
EXPECT_EQ(NO_ERROR,
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
@@ -2800,13 +2826,15 @@ TEST_F(WvCdmRequestLicenseTest, StreamingWithExpiringCertTest) {
kEmptyServiceCertificate, kLevelDefault,
&key_msg_, &provisioning_server));
std::string response = GetCertRequestResponse(config.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
const std::string response = GetCertRequestResponse(
config.provisioning_server(), kDrmCertificateExpiryPeriod);
EXPECT_FALSE(response.empty()) << "Failed to get DRM provisioning response";
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
kExampleIdentifier, response, kLevelDefault,
&cert, &wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
EXPECT_TRUE(cert.empty()) << "Widevine certs should not be returned";
EXPECT_TRUE(wrapped_key.empty())
<< "Keys from Widevine certs should not be returned";
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
@@ -2821,6 +2849,17 @@ TEST_F(WvCdmRequestLicenseTest, StreamingWithExpiringCertTest) {
nullptr);
VerifyKeyRequestResponse(config_.license_server(), config_.client_auth());
decryptor_->CloseSession(session_id_);
sleep(kDrmCertificateExpirySleepPeriod);
// Fetch another stream license, after expiry.
EXPECT_EQ(NO_ERROR,
decryptor_->OpenSession(config_.key_system(), nullptr,
kExampleIdentifier, nullptr, &session_id_));
GenerateKeyRequest(NEED_PROVISIONING, ISO_BMFF_VIDEO_MIME_TYPE,
binary_key_id(), app_parameters, kLicenseTypeStreaming,
kExampleIdentifier, nullptr);
decryptor_->CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
@@ -2864,6 +2903,8 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
decryptor_->CloseSession(session_id_);
}
// Test checks that the CDM allows reloading of previously acquired offline
// licenses even if the DRM certificate has expired.
TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
EXPECT_EQ(NO_ERROR,
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
@@ -2875,7 +2916,7 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
// Provision
std::string provisioning_server;
CdmCertificateType cert_type = kCertificateWidevine;
const CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
@@ -2883,13 +2924,15 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
kEmptyServiceCertificate, kLevelDefault,
&key_msg_, &provisioning_server));
std::string response = GetCertRequestResponse(config.provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
const std::string response = GetCertRequestResponse(
config.provisioning_server(), kDrmCertificateExpiryPeriod);
EXPECT_FALSE(response.empty()) << "Failed to get DRM provisioning response";
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
kExampleIdentifier, response, kLevelDefault,
&cert, &wrapped_key));
EXPECT_EQ(0, static_cast<int>(cert.size()));
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
EXPECT_TRUE(cert.empty()) << "Widevine certs should not be returned";
EXPECT_TRUE(wrapped_key.empty())
<< "Keys from Widevine certs should not be returned";
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
@@ -2908,19 +2951,20 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
nullptr);
VerifyKeyRequestResponse(config_.license_server(), client_auth);
CdmKeySetId key_set_id = key_set_id_;
const CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_->CloseSession(session_id_);
session_id_.clear();
// Wait till certificate expires
sleep(kDrmCertificateExpiryPeriod);
sleep(kDrmCertificateExpirySleepPeriod);
// Make sure the certificate has expired and the device is not provisioned
// Make sure the certificate has expired and the device is not provisioned.
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
// Restore offline license
// Restore offline license. Key restoration should not be prevented
// by the expired DRM certificate.
decryptor_->OpenSession(config_.key_system(), nullptr, kExampleIdentifier,
nullptr, &session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_->RestoreKey(session_id_, key_set_id));

View File

@@ -194,7 +194,7 @@ class MockCDM : public WvContentDecryptionModule {
std::string*), (override));
MOCK_METHOD(CdmResponseType, HandleProvisioningResponse,
(const CdmIdentifier&, CdmProvisioningResponse&,
(const CdmIdentifier&, const CdmProvisioningResponse&,
wvcdm::RequestedSecurityLevel, std::string*, std::string*), (override));
MOCK_METHOD(CdmResponseType, Unprovision, (CdmSecurityLevel,