|
|
|
|
@@ -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));
|
|
|
|
|
|