Snap for 8519467 from da1e3c5de2 to tm-release
Change-Id: Ib8ff956fa579072e7887a7edbe4eab3f0aa22413
This commit is contained in:
@@ -86,7 +86,8 @@ class CertificateProvisioning {
|
|||||||
std::string* default_url);
|
std::string* default_url);
|
||||||
CdmResponseType FillEncryptedClientId(
|
CdmResponseType FillEncryptedClientId(
|
||||||
const std::string& client_token,
|
const std::string& client_token,
|
||||||
video_widevine::ProvisioningRequest& provisioning_request);
|
video_widevine::ProvisioningRequest& provisioning_request,
|
||||||
|
const ServiceCertificate& service_certificate);
|
||||||
CdmResponseType HandleProvisioning40Response(
|
CdmResponseType HandleProvisioning40Response(
|
||||||
wvutil::FileSystem* file_system, const std::string& response_message);
|
wvutil::FileSystem* file_system, const std::string& response_message);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#ifndef WVCDM_CORE_DEVICE_FILES_H_
|
#ifndef WVCDM_CORE_DEVICE_FILES_H_
|
||||||
#define WVCDM_CORE_DEVICE_FILES_H_
|
#define WVCDM_CORE_DEVICE_FILES_H_
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -369,6 +370,7 @@ class DeviceFiles {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::set<std::string> reserved_license_ids_;
|
static std::set<std::string> reserved_license_ids_;
|
||||||
|
static std::mutex reserved_license_ids_mutex_;
|
||||||
|
|
||||||
wvutil::FileSystem* file_system_;
|
wvutil::FileSystem* file_system_;
|
||||||
CdmSecurityLevel security_level_;
|
CdmSecurityLevel security_level_;
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ class ServiceCertificate {
|
|||||||
const std::string& provider_id() const { return provider_id_; }
|
const std::string& provider_id() const { return provider_id_; }
|
||||||
|
|
||||||
// Verify the signature for a message.
|
// Verify the signature for a message.
|
||||||
virtual CdmResponseType VerifySignedMessage(const std::string& message,
|
virtual CdmResponseType VerifySignedMessage(
|
||||||
const std::string& signature);
|
const std::string& message, const std::string& signature) const;
|
||||||
|
|
||||||
// Encrypt the ClientIdentification message for a provisioning or
|
// Encrypt the ClientIdentification message for a provisioning or
|
||||||
// licensing request. Encryption is performed using the current
|
// licensing request. Encryption is performed using the current
|
||||||
@@ -50,7 +50,7 @@ class ServiceCertificate {
|
|||||||
virtual CdmResponseType EncryptClientId(
|
virtual CdmResponseType EncryptClientId(
|
||||||
CryptoSession* crypto_session,
|
CryptoSession* crypto_session,
|
||||||
const video_widevine::ClientIdentification* clear_client_id,
|
const video_widevine::ClientIdentification* clear_client_id,
|
||||||
video_widevine::EncryptedClientIdentification* encrypted_client_id);
|
video_widevine::EncryptedClientIdentification* encrypted_client_id) const;
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
static bool GetRequest(CdmKeyMessage* request);
|
static bool GetRequest(CdmKeyMessage* request);
|
||||||
@@ -63,7 +63,7 @@ class ServiceCertificate {
|
|||||||
// string to contain the decrypted data on return, and may not be null.
|
// string to contain the decrypted data on return, and may not be null.
|
||||||
// returns NO_ERROR if successful or an appropriate error code otherwise.
|
// returns NO_ERROR if successful or an appropriate error code otherwise.
|
||||||
virtual CdmResponseType EncryptRsaOaep(const std::string& plaintext,
|
virtual CdmResponseType EncryptRsaOaep(const std::string& plaintext,
|
||||||
std::string* ciphertext);
|
std::string* ciphertext) const;
|
||||||
|
|
||||||
// Track whether object holds valid certificate
|
// Track whether object holds valid certificate
|
||||||
bool has_certificate_;
|
bool has_certificate_;
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal(
|
|||||||
// Prepare device provisioning request.
|
// Prepare device provisioning request.
|
||||||
ProvisioningRequest provisioning_request;
|
ProvisioningRequest provisioning_request;
|
||||||
|
|
||||||
status = FillEncryptedClientId(/*client_token=*/"", provisioning_request);
|
status = FillEncryptedClientId(/*client_token=*/"", provisioning_request,
|
||||||
|
*service_certificate_);
|
||||||
if (status != NO_ERROR) return status;
|
if (status != NO_ERROR) return status;
|
||||||
|
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
@@ -339,23 +340,32 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CdmResponseType status = NO_ERROR;
|
||||||
if (stored_oem_cert.empty()) {
|
if (stored_oem_cert.empty()) {
|
||||||
// This is the first stage provisioning.
|
// This is the first stage provisioning.
|
||||||
default_url->assign(kProvisioningServerUrl +
|
default_url->assign(kProvisioningServerUrl +
|
||||||
kProv40FirstStageServerUrlSuffix);
|
kProv40FirstStageServerUrlSuffix);
|
||||||
|
|
||||||
|
// First-stage provisioning always uses the WV production service cert for
|
||||||
|
// encryption.
|
||||||
|
ServiceCertificate wv_service_cert;
|
||||||
|
status = wv_service_cert.Init(kCpProductionServiceCertificate);
|
||||||
|
if (status != NO_ERROR) return status;
|
||||||
|
|
||||||
|
// Since |stored_oem_cert| is empty, the client identification token will be
|
||||||
|
// retrieved from OEMCrypto, which is the BCC in this case.
|
||||||
|
status = FillEncryptedClientId(stored_oem_cert, provisioning_request,
|
||||||
|
wv_service_cert);
|
||||||
|
if (status != NO_ERROR) return status;
|
||||||
} else {
|
} else {
|
||||||
// This is the second stage provisioning.
|
// This is the second stage provisioning.
|
||||||
default_url->assign(kProvisioningServerUrl);
|
default_url->assign(kProvisioningServerUrl);
|
||||||
}
|
// Since |stored_oem_cert| is non-empty, it will be used as the client
|
||||||
|
// identification token.
|
||||||
// If this is the first stage, |stored_oem_cert| remains empty. In this case,
|
status = FillEncryptedClientId(stored_oem_cert, provisioning_request,
|
||||||
// the client identification token will be retrieved from OEMCrypto, which is
|
*service_certificate_);
|
||||||
// the BCC in this case.
|
|
||||||
// If this is the second stage, |stored_oem_cert| is non-empty and will be
|
|
||||||
// used as the client identification token.
|
|
||||||
CdmResponseType status =
|
|
||||||
FillEncryptedClientId(stored_oem_cert, provisioning_request);
|
|
||||||
if (status != NO_ERROR) return status;
|
if (status != NO_ERROR) return status;
|
||||||
|
}
|
||||||
|
|
||||||
std::string public_key;
|
std::string public_key;
|
||||||
std::string public_key_signature;
|
std::string public_key_signature;
|
||||||
@@ -396,8 +406,8 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CertificateProvisioning::FillEncryptedClientId(
|
CdmResponseType CertificateProvisioning::FillEncryptedClientId(
|
||||||
const std::string& client_token,
|
const std::string& client_token, ProvisioningRequest& provisioning_request,
|
||||||
ProvisioningRequest& provisioning_request) {
|
const ServiceCertificate& service_certificate) {
|
||||||
if (!crypto_session_->IsOpen()) {
|
if (!crypto_session_->IsOpen()) {
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
@@ -412,13 +422,13 @@ CdmResponseType CertificateProvisioning::FillEncryptedClientId(
|
|||||||
status = id.Prepare(app_parameter, kEmptyString, &client_id);
|
status = id.Prepare(app_parameter, kEmptyString, &client_id);
|
||||||
if (status != NO_ERROR) return status;
|
if (status != NO_ERROR) return status;
|
||||||
|
|
||||||
if (!service_certificate_->has_certificate()) {
|
if (!service_certificate.has_certificate()) {
|
||||||
LOGE("Service certificate not staged");
|
LOGE("Service certificate not staged");
|
||||||
return CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE;
|
return CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encrypt client identification
|
// Encrypt client identification
|
||||||
return service_certificate_->EncryptClientId(
|
return service_certificate.EncryptClientId(
|
||||||
crypto_session_.get(), &client_id,
|
crypto_session_.get(), &client_id,
|
||||||
provisioning_request.mutable_encrypted_client_id());
|
provisioning_request.mutable_encrypted_client_id());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ using video_widevine_client::sdk::
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
using UniqueLock = std::unique_lock<std::mutex>;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const char kEmptyFileName[] = "";
|
const char kEmptyFileName[] = "";
|
||||||
const char kFalse[] = "false";
|
const char kFalse[] = "false";
|
||||||
@@ -364,6 +366,7 @@ const char* DeviceFiles::ResponseTypeToString(ResponseType type) {
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
std::set<std::string> DeviceFiles::reserved_license_ids_;
|
std::set<std::string> DeviceFiles::reserved_license_ids_;
|
||||||
|
std::mutex DeviceFiles::reserved_license_ids_mutex_;
|
||||||
|
|
||||||
DeviceFiles::DeviceFiles(wvutil::FileSystem* file_system)
|
DeviceFiles::DeviceFiles(wvutil::FileSystem* file_system)
|
||||||
: file_system_(file_system),
|
: file_system_(file_system),
|
||||||
@@ -847,6 +850,7 @@ bool DeviceFiles::StoreLicense(const CdmLicenseData& license_data,
|
|||||||
std::string serialized_file;
|
std::string serialized_file;
|
||||||
file.SerializeToString(&serialized_file);
|
file.SerializeToString(&serialized_file);
|
||||||
|
|
||||||
|
UniqueLock lock(reserved_license_ids_mutex_);
|
||||||
reserved_license_ids_.erase(license_data.key_set_id);
|
reserved_license_ids_.erase(license_data.key_set_id);
|
||||||
*result = StoreFileWithHash(license_data.key_set_id + kLicenseFileNameExt,
|
*result = StoreFileWithHash(license_data.key_set_id + kLicenseFileNameExt,
|
||||||
serialized_file);
|
serialized_file);
|
||||||
@@ -984,18 +988,21 @@ bool DeviceFiles::DeleteAllFiles() {
|
|||||||
|
|
||||||
bool DeviceFiles::LicenseExists(const std::string& key_set_id) {
|
bool DeviceFiles::LicenseExists(const std::string& key_set_id) {
|
||||||
RETURN_FALSE_IF_UNINITIALIZED();
|
RETURN_FALSE_IF_UNINITIALIZED();
|
||||||
|
UniqueLock lock(reserved_license_ids_mutex_);
|
||||||
return reserved_license_ids_.count(key_set_id) ||
|
return reserved_license_ids_.count(key_set_id) ||
|
||||||
FileExists(key_set_id + kLicenseFileNameExt);
|
FileExists(key_set_id + kLicenseFileNameExt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceFiles::ReserveLicenseId(const std::string& key_set_id) {
|
bool DeviceFiles::ReserveLicenseId(const std::string& key_set_id) {
|
||||||
RETURN_FALSE_IF_UNINITIALIZED();
|
RETURN_FALSE_IF_UNINITIALIZED();
|
||||||
|
UniqueLock lock(reserved_license_ids_mutex_);
|
||||||
reserved_license_ids_.insert(key_set_id);
|
reserved_license_ids_.insert(key_set_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceFiles::UnreserveLicenseId(const std::string& key_set_id) {
|
bool DeviceFiles::UnreserveLicenseId(const std::string& key_set_id) {
|
||||||
RETURN_FALSE_IF_UNINITIALIZED();
|
RETURN_FALSE_IF_UNINITIALIZED();
|
||||||
|
UniqueLock lock(reserved_license_ids_mutex_);
|
||||||
reserved_license_ids_.erase(key_set_id);
|
reserved_license_ids_.erase(key_set_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ CdmResponseType ServiceCertificate::Init(const std::string& certificate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType ServiceCertificate::VerifySignedMessage(
|
CdmResponseType ServiceCertificate::VerifySignedMessage(
|
||||||
const std::string& message, const std::string& signature) {
|
const std::string& message, const std::string& signature) const {
|
||||||
if (!public_key_) {
|
if (!public_key_) {
|
||||||
LOGE("Service certificate not set");
|
LOGE("Service certificate not set");
|
||||||
return DEVICE_CERTIFICATE_ERROR_4;
|
return DEVICE_CERTIFICATE_ERROR_4;
|
||||||
@@ -218,8 +218,8 @@ CdmResponseType ServiceCertificate::VerifySignedMessage(
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType ServiceCertificate::EncryptRsaOaep(const std::string& plaintext,
|
CdmResponseType ServiceCertificate::EncryptRsaOaep(
|
||||||
std::string* ciphertext) {
|
const std::string& plaintext, std::string* ciphertext) const {
|
||||||
if (!public_key_) {
|
if (!public_key_) {
|
||||||
LOGE("Service certificate not set");
|
LOGE("Service certificate not set");
|
||||||
return DEVICE_CERTIFICATE_ERROR_4;
|
return DEVICE_CERTIFICATE_ERROR_4;
|
||||||
@@ -233,7 +233,7 @@ CdmResponseType ServiceCertificate::EncryptRsaOaep(const std::string& plaintext,
|
|||||||
|
|
||||||
CdmResponseType ServiceCertificate::EncryptClientId(
|
CdmResponseType ServiceCertificate::EncryptClientId(
|
||||||
CryptoSession* crypto_session, const ClientIdentification* clear_client_id,
|
CryptoSession* crypto_session, const ClientIdentification* clear_client_id,
|
||||||
EncryptedClientIdentification* encrypted_client_id) {
|
EncryptedClientIdentification* encrypted_client_id) const {
|
||||||
encrypted_client_id->set_provider_id(provider_id_);
|
encrypted_client_id->set_provider_id(provider_id_);
|
||||||
encrypted_client_id->set_service_certificate_serial_number(serial_number_);
|
encrypted_client_id->set_service_certificate_serial_number(serial_number_);
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
|||||||
CdmProvisioningRequest* request, std::string* default_url);
|
CdmProvisioningRequest* request, std::string* default_url);
|
||||||
|
|
||||||
virtual CdmResponseType HandleProvisioningResponse(
|
virtual CdmResponseType HandleProvisioningResponse(
|
||||||
const CdmIdentifier& identifier, CdmProvisioningResponse& response,
|
const CdmIdentifier& identifier, const CdmProvisioningResponse& response,
|
||||||
RequestedSecurityLevel requested_security_level, std::string* cert,
|
RequestedSecurityLevel requested_security_level, std::string* cert,
|
||||||
std::string* wrapped_key);
|
std::string* wrapped_key);
|
||||||
|
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ CdmResponseType WvContentDecryptionModule::GetProvisioningRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse(
|
CdmResponseType WvContentDecryptionModule::HandleProvisioningResponse(
|
||||||
const CdmIdentifier& identifier, CdmProvisioningResponse& response,
|
const CdmIdentifier& identifier, const CdmProvisioningResponse& response,
|
||||||
RequestedSecurityLevel requested_security_level, std::string* cert,
|
RequestedSecurityLevel requested_security_level, std::string* cert,
|
||||||
std::string* wrapped_key) {
|
std::string* wrapped_key) {
|
||||||
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
CdmEngine* cdm_engine = EnsureCdmForIdentifier(identifier);
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ namespace {
|
|||||||
|
|
||||||
// HTTP response codes.
|
// HTTP response codes.
|
||||||
const int kHttpOk = 200;
|
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 = {
|
const wvcdm::CdmIdentifier kExampleIdentifier = {
|
||||||
wvcdm::EMPTY_SPOID, "com.example", "com.example", 7, 9};
|
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
|
// Post a request and extract the signed provisioning message from
|
||||||
// the HTTP response.
|
// 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.
|
// 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())
|
EXPECT_TRUE(url_request.is_connected())
|
||||||
<< "Fail to connect to " << server_url;
|
<< "Fail to connect to " << actual_url;
|
||||||
url_request.PostCertRequestInQueryString(key_msg_);
|
url_request.PostCertRequestInQueryString(key_msg_);
|
||||||
std::string message;
|
std::string message;
|
||||||
EXPECT_TRUE(url_request.GetResponse(&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) {
|
TEST_F(WvCdmRequestLicenseTest, ProvisioningWithExpiringCertTest) {
|
||||||
EXPECT_EQ(NO_ERROR,
|
EXPECT_EQ(NO_ERROR,
|
||||||
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
||||||
@@ -2584,7 +2607,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningWithExpiringCertTest) {
|
|||||||
|
|
||||||
// Provision
|
// Provision
|
||||||
std::string provisioning_server;
|
std::string provisioning_server;
|
||||||
CdmCertificateType cert_type = kCertificateWidevine;
|
const CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
std::string cert_authority, cert, wrapped_key;
|
std::string cert_authority, cert, wrapped_key;
|
||||||
|
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
|
||||||
@@ -2592,18 +2615,19 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningWithExpiringCertTest) {
|
|||||||
kEmptyServiceCertificate, kLevelDefault,
|
kEmptyServiceCertificate, kLevelDefault,
|
||||||
&key_msg_, &provisioning_server));
|
&key_msg_, &provisioning_server));
|
||||||
|
|
||||||
std::string response = GetCertRequestResponse(config.provisioning_server());
|
const std::string response = GetCertRequestResponse(
|
||||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
config.provisioning_server(), kDrmCertificateExpiryPeriod);
|
||||||
|
EXPECT_FALSE(response.empty()) << "Failed to get DRM provisioning response";
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
||||||
kExampleIdentifier, response, kLevelDefault,
|
kExampleIdentifier, response, kLevelDefault,
|
||||||
&cert, &wrapped_key));
|
&cert, &wrapped_key));
|
||||||
EXPECT_EQ(0, static_cast<int>(cert.size()));
|
EXPECT_TRUE(cert.empty()) << "Widevine certs should not be returned";
|
||||||
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
EXPECT_TRUE(wrapped_key.empty())
|
||||||
decryptor_->CloseSession(session_id_);
|
<< "Keys from Widevine certs should not be returned";
|
||||||
|
|
||||||
// Make sure it is provisioned, then wait for certificate expiry period
|
// Make sure it is provisioned, then wait for certificate expiry period
|
||||||
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
sleep(kDrmCertificateExpiryPeriod);
|
sleep(kDrmCertificateExpirySleepPeriod);
|
||||||
|
|
||||||
// Verify that it is no longer provisioned after the certificate expires
|
// Verify that it is no longer provisioned after the certificate expires
|
||||||
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
@@ -2781,6 +2805,8 @@ TEST_F(WvCdmRequestLicenseTest, AddStreamingKeyTest) {
|
|||||||
decryptor_->CloseSession(session_id_);
|
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) {
|
TEST_F(WvCdmRequestLicenseTest, StreamingWithExpiringCertTest) {
|
||||||
EXPECT_EQ(NO_ERROR,
|
EXPECT_EQ(NO_ERROR,
|
||||||
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
||||||
@@ -2800,13 +2826,15 @@ TEST_F(WvCdmRequestLicenseTest, StreamingWithExpiringCertTest) {
|
|||||||
kEmptyServiceCertificate, kLevelDefault,
|
kEmptyServiceCertificate, kLevelDefault,
|
||||||
&key_msg_, &provisioning_server));
|
&key_msg_, &provisioning_server));
|
||||||
|
|
||||||
std::string response = GetCertRequestResponse(config.provisioning_server());
|
const std::string response = GetCertRequestResponse(
|
||||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
config.provisioning_server(), kDrmCertificateExpiryPeriod);
|
||||||
|
EXPECT_FALSE(response.empty()) << "Failed to get DRM provisioning response";
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
||||||
kExampleIdentifier, response, kLevelDefault,
|
kExampleIdentifier, response, kLevelDefault,
|
||||||
&cert, &wrapped_key));
|
&cert, &wrapped_key));
|
||||||
EXPECT_EQ(0, static_cast<int>(cert.size()));
|
EXPECT_TRUE(cert.empty()) << "Widevine certs should not be returned";
|
||||||
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
EXPECT_TRUE(wrapped_key.empty())
|
||||||
|
<< "Keys from Widevine certs should not be returned";
|
||||||
|
|
||||||
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
|
||||||
@@ -2821,6 +2849,17 @@ TEST_F(WvCdmRequestLicenseTest, StreamingWithExpiringCertTest) {
|
|||||||
nullptr);
|
nullptr);
|
||||||
VerifyKeyRequestResponse(config_.license_server(), config_.client_auth());
|
VerifyKeyRequestResponse(config_.license_server(), config_.client_auth());
|
||||||
decryptor_->CloseSession(session_id_);
|
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) {
|
TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) {
|
||||||
@@ -2864,6 +2903,8 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) {
|
|||||||
decryptor_->CloseSession(session_id_);
|
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) {
|
TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
|
||||||
EXPECT_EQ(NO_ERROR,
|
EXPECT_EQ(NO_ERROR,
|
||||||
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier));
|
||||||
@@ -2875,7 +2916,7 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
|
|||||||
|
|
||||||
// Provision
|
// Provision
|
||||||
std::string provisioning_server;
|
std::string provisioning_server;
|
||||||
CdmCertificateType cert_type = kCertificateWidevine;
|
const CdmCertificateType cert_type = kCertificateWidevine;
|
||||||
std::string cert_authority, cert, wrapped_key;
|
std::string cert_authority, cert, wrapped_key;
|
||||||
|
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest(
|
||||||
@@ -2883,13 +2924,15 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
|
|||||||
kEmptyServiceCertificate, kLevelDefault,
|
kEmptyServiceCertificate, kLevelDefault,
|
||||||
&key_msg_, &provisioning_server));
|
&key_msg_, &provisioning_server));
|
||||||
|
|
||||||
std::string response = GetCertRequestResponse(config.provisioning_server());
|
const std::string response = GetCertRequestResponse(
|
||||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
config.provisioning_server(), kDrmCertificateExpiryPeriod);
|
||||||
|
EXPECT_FALSE(response.empty()) << "Failed to get DRM provisioning response";
|
||||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
||||||
kExampleIdentifier, response, kLevelDefault,
|
kExampleIdentifier, response, kLevelDefault,
|
||||||
&cert, &wrapped_key));
|
&cert, &wrapped_key));
|
||||||
EXPECT_EQ(0, static_cast<int>(cert.size()));
|
EXPECT_TRUE(cert.empty()) << "Widevine certs should not be returned";
|
||||||
EXPECT_EQ(0, static_cast<int>(wrapped_key.size()));
|
EXPECT_TRUE(wrapped_key.empty())
|
||||||
|
<< "Keys from Widevine certs should not be returned";
|
||||||
|
|
||||||
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault));
|
||||||
|
|
||||||
@@ -2908,19 +2951,20 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) {
|
|||||||
nullptr);
|
nullptr);
|
||||||
VerifyKeyRequestResponse(config_.license_server(), client_auth);
|
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());
|
EXPECT_FALSE(key_set_id_.empty());
|
||||||
decryptor_->CloseSession(session_id_);
|
decryptor_->CloseSession(session_id_);
|
||||||
|
|
||||||
session_id_.clear();
|
session_id_.clear();
|
||||||
|
|
||||||
// Wait till certificate expires
|
// 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));
|
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,
|
decryptor_->OpenSession(config_.key_system(), nullptr, kExampleIdentifier,
|
||||||
nullptr, &session_id_);
|
nullptr, &session_id_);
|
||||||
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_->RestoreKey(session_id_, key_set_id));
|
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_->RestoreKey(session_id_, key_set_id));
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class MockCDM : public WvContentDecryptionModule {
|
|||||||
std::string*), (override));
|
std::string*), (override));
|
||||||
|
|
||||||
MOCK_METHOD(CdmResponseType, HandleProvisioningResponse,
|
MOCK_METHOD(CdmResponseType, HandleProvisioningResponse,
|
||||||
(const CdmIdentifier&, CdmProvisioningResponse&,
|
(const CdmIdentifier&, const CdmProvisioningResponse&,
|
||||||
wvcdm::RequestedSecurityLevel, std::string*, std::string*), (override));
|
wvcdm::RequestedSecurityLevel, std::string*, std::string*), (override));
|
||||||
|
|
||||||
MOCK_METHOD(CdmResponseType, Unprovision, (CdmSecurityLevel,
|
MOCK_METHOD(CdmResponseType, Unprovision, (CdmSecurityLevel,
|
||||||
|
|||||||
Reference in New Issue
Block a user