diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index 58c6fd41..d88063e6 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -219,6 +219,19 @@ class CdmSession { private: friend class CdmSessionTest; + // Both these methods will attempt to load wrapped key material and + // cache values in |drm_certificate_| and |wrapped_private_key_| + // if successful. + // This methods will load the key from persistent storage. + CdmResponseType LoadPrivateKey(); + // This method will load the specified key if valid or otherwise load + // the information from the legacy certificate. + CdmResponseType LoadPrivateOrLegacyKey( + const std::string& certificate, + const CryptoWrappedKey& wrapped_private_key); + + CdmResponseType LoadPrivateKey(const CryptoWrappedKey& wrapped_private_key); + bool GenerateKeySetId(bool atsc_mode_enabled, CdmKeySetId* key_set_id); CdmResponseType StoreLicense(); @@ -273,6 +286,9 @@ class CdmSession { CdmSecurityLevel security_level_; SecurityLevel requested_security_level_; CdmAppParameterMap app_parameters_; + bool atsc_mode_enabled_ = false; + std::string drm_certificate_; + CryptoWrappedKey wrapped_private_key_; // decryption flags bool is_initial_decryption_; diff --git a/libwvdrmengine/cdm/core/include/license.h b/libwvdrmengine/cdm/core/include/license.h index c7d4567a..59b51ab1 100644 --- a/libwvdrmengine/cdm/core/include/license.h +++ b/libwvdrmengine/cdm/core/include/license.h @@ -38,8 +38,7 @@ class CdmLicense { CdmLicense(const CdmSessionId& session_id); virtual ~CdmLicense(); - virtual bool Init(const std::string& client_token, - CdmClientTokenType client_token_type, bool use_privacy_mode, + virtual bool Init(bool use_privacy_mode, const std::string& signed_service_certificate, CryptoSession* session, PolicyEngine* policy_engine); @@ -49,9 +48,9 @@ class CdmLicense { const std::string& signed_service_certificate); virtual CdmResponseType PrepareKeyRequest( - const InitializationData& init_data, CdmLicenseType license_type, - const CdmAppParameterMap& app_parameters, CdmKeyMessage* signed_request, - std::string* server_url); + const InitializationData& init_data, const std::string& client_token, + CdmLicenseType license_type, const CdmAppParameterMap& app_parameters, + CdmKeyMessage* signed_request, std::string* server_url); virtual CdmResponseType PrepareKeyUpdateRequest( bool is_renewal, const CdmAppParameterMap& app_parameters, CdmSession* cdm_session, CdmKeyMessage* signed_request, @@ -64,13 +63,13 @@ class CdmLicense { const InitializationData& init_data); virtual CdmResponseType RestoreOfflineLicense( - const CdmKeyMessage& license_request, + const std::string& client_token, const CdmKeyMessage& license_request, const CdmKeyResponse& license_response, const CdmKeyResponse& license_renewal_response, int64_t playback_start_time, int64_t last_playback_time, int64_t grace_period_end_time, CdmSession* cdm_session); virtual CdmResponseType RestoreLicenseForRelease( - const CdmKeyMessage& license_request, + const std::string& client_token, const CdmKeyMessage& license_request, const CdmKeyResponse& license_response); virtual bool HasInitData() { return static_cast(stored_init_data_); } virtual bool IsKeyLoaded(const KeyId& key_id); @@ -138,7 +137,6 @@ class CdmLicense { PolicyEngine* policy_engine_; std::string server_url_; std::string client_token_; - CdmClientTokenType client_token_type_; const CdmSessionId session_id_; std::unique_ptr stored_init_data_; bool initialized_; diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index ce171159..75ab65d4 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -977,7 +977,7 @@ CdmResponseType CdmEngine::HandleProvisioningResponse( const CdmProvisioningResponse& response, SecurityLevel requested_security_level, std::string* cert, std::string* wrapped_key) { - LOGI("Handling provision request"); + LOGI("Handling provision response"); if (response.empty()) { LOGE("Empty provisioning response"); cert_provisioning_.reset(); diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index aeb11a63..9d4bfb43 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -169,56 +169,16 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, usage_support_type_ = kNonSecureUsageSupport; } - // Device Provisioning state is not yet known. - // If not using certificates, then Keybox is client token for license - // requests. - // Otherwise, try to fetch device certificate. If not successful and - // provisioning is supported, return NEED_PROVISIONING. Otherwise, return - // an error. - // client_token and client_token_type are determined here; they are needed - // to initialize the license parser. - std::string client_token; - std::string serial_number; - CdmClientTokenType client_token_type = - crypto_session_->GetPreProvisionTokenType(); - - // License server client ID token is a stored certificate. Stage it or - // indicate that provisioning is needed. Get token from stored certificate - CryptoWrappedKey private_key; - bool atsc_mode_enabled = false; if (cdm_client_property_set != nullptr) - atsc_mode_enabled = cdm_client_property_set->use_atsc_mode(); - if (file_handle_->RetrieveCertificate( - atsc_mode_enabled, &client_token, &private_key, &serial_number, - nullptr) != DeviceFiles::kCertificateValid) { + atsc_mode_enabled_ = cdm_client_property_set->use_atsc_mode(); + + if (!file_handle_->HasCertificate(atsc_mode_enabled_)) return NEED_PROVISIONING; - } - CdmResponseType load_cert_sts; - M_TIME( - load_cert_sts = crypto_session_->LoadCertificatePrivateKey(private_key), - crypto_metrics_, crypto_session_load_certificate_private_key_, - load_cert_sts); - switch (load_cert_sts) { - case NO_ERROR: - metrics_->drm_certificate_key_type_.Record( - DrmKeyTypeToMetricValue(private_key.type())); - break; - case SESSION_LOST_STATE_ERROR: - case SYSTEM_INVALIDATED_ERROR: - return load_cert_sts; - default: - return NEED_PROVISIONING; - } - - client_token_type = kClientTokenDrmCert; - - // Session is provisioned with certificate needed to construct - // license request (or with keybox). if (forced_session_id) { key_set_id_ = *forced_session_id; } else { - const bool ok = GenerateKeySetId(atsc_mode_enabled, &key_set_id_); + const bool ok = GenerateKeySetId(atsc_mode_enabled_, &key_set_id_); assert(ok); if (!ok) { // Assertions may be disabled @@ -247,8 +207,7 @@ CdmResponseType CdmSession::Init(CdmClientPropertySet* cdm_client_property_set, if (!Properties::GetServiceCertificate(session_id_, &service_certificate)) service_certificate.clear(); - if (!license_parser_->Init(client_token, client_token_type, - Properties::UsePrivacyMode(session_id_), + if (!license_parser_->Init(Properties::UsePrivacyMode(session_id_), service_certificate, crypto_session_.get(), policy_engine_.get())) return LICENSE_PARSER_INIT_ERROR; @@ -337,6 +296,10 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id, usage_entry_ = std::move(license_data.usage_entry); usage_entry_number_ = license_data.usage_entry_number; + CdmResponseType status = LoadPrivateOrLegacyKey( + license_data.drm_certificate, license_data.wrapped_private_key); + if (status != NO_ERROR) return status; + // Attempts to restore a released offline license are treated as a release // retry. if (Properties::allow_restore_of_offline_licenses_with_release()) { @@ -396,8 +359,8 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id, CdmResponseType result; if (license_type == kLicenseTypeRelease) { - result = - license_parser_->RestoreLicenseForRelease(key_request_, key_response_); + result = license_parser_->RestoreLicenseForRelease( + license_data.drm_certificate, key_request_, key_response_); if (result != NO_ERROR) { SetErrorDetail(error_detail, result); @@ -405,9 +368,10 @@ CdmResponseType CdmSession::RestoreOfflineSession(const CdmKeySetId& key_set_id, } } else { result = license_parser_->RestoreOfflineLicense( - key_request_, key_response_, offline_key_renewal_response_, - license_data.playback_start_time, license_data.last_playback_time, - license_data.grace_period_end_time, this); + license_data.drm_certificate, key_request_, key_response_, + offline_key_renewal_response_, license_data.playback_start_time, + license_data.last_playback_time, license_data.grace_period_end_time, + this); if (result != NO_ERROR) { SetErrorDetail(error_detail, result); return RESTORE_OFFLINE_LICENSE_ERROR_2; @@ -449,6 +413,10 @@ CdmResponseType CdmSession::RestoreUsageSession( usage_entry_number_ = usage_data.usage_entry_number; usage_provider_session_token_ = usage_data.provider_session_token; + CdmResponseType status = LoadPrivateOrLegacyKey( + usage_data.drm_certificate, usage_data.wrapped_private_key); + if (status != NO_ERROR) return status; + CdmResponseType sts = NO_ERROR; if (usage_support_type_ == kUsageEntrySupport && usage_table_header_ != nullptr) { @@ -461,7 +429,8 @@ CdmResponseType CdmSession::RestoreUsageSession( } } - sts = license_parser_->RestoreLicenseForRelease(key_request_, key_response_); + sts = license_parser_->RestoreLicenseForRelease(usage_data.drm_certificate, + key_request_, key_response_); if (sts != NO_ERROR) { SetErrorDetail(error_detail, sts); @@ -568,10 +537,13 @@ CdmResponseType CdmSession::GenerateKeyRequestInternal( return KEY_REQUEST_ERROR_1; } + CdmResponseType status = LoadPrivateKey(); + if (status != NO_ERROR) return status; + app_parameters_ = app_parameters; - CdmResponseType status = license_parser_->PrepareKeyRequest( - init_data, license_type, app_parameters, &key_request->message, - &key_request->url); + status = license_parser_->PrepareKeyRequest( + init_data, drm_certificate_, license_type, app_parameters, + &key_request->message, &key_request->url); if (status != KEY_MESSAGE) return status; key_request_ = key_request->message; @@ -1018,12 +990,10 @@ CdmResponseType CdmSession::StoreLicense() { std::string app_id; GetApplicationId(&app_id); - std::string drm_certificate; - CryptoWrappedKey wrapped_private_key; if (!file_handle_->StoreUsageInfo( provider_session_token, key_request_, key_response_, DeviceFiles::GetUsageInfoFileName(app_id), key_set_id_, usage_entry_, - usage_entry_number_, drm_certificate, wrapped_private_key)) { + usage_entry_number_, drm_certificate_, wrapped_private_key_)) { LOGE("Unable to store usage info"); // Usage info file is corrupt. Delete current usage entry and file. if (usage_support_type_ == kUsageEntrySupport) { @@ -1044,7 +1014,6 @@ CdmResponseType CdmSession::StoreLicense() { bool CdmSession::StoreLicense(DeviceFiles::LicenseState state, int* error_detail) { DeviceFiles::ResponseType error_detail_alt = DeviceFiles::kNoError; - std::string drm_certificate; DeviceFiles::CdmLicenseData license_data{ key_set_id_, state, @@ -1060,8 +1029,8 @@ bool CdmSession::StoreLicense(DeviceFiles::LicenseState state, app_parameters_, usage_entry_, usage_entry_number_, - drm_certificate, - CryptoWrappedKey()}; + drm_certificate_, + wrapped_private_key_}; bool result = file_handle_->StoreLicense(license_data, &error_detail_alt); if (error_detail != nullptr) { @@ -1271,6 +1240,83 @@ bool CdmSession::VerifyOfflineUsageEntry() { return true; } +CdmResponseType CdmSession::LoadPrivateKey() { + std::string drm_certificate; + CryptoWrappedKey private_key; + uint32_t system_id; + + if (file_handle_->RetrieveCertificate(atsc_mode_enabled_, &drm_certificate, + &private_key, nullptr, &system_id) != + DeviceFiles::kCertificateValid) { + return NEED_PROVISIONING; + } + + CdmResponseType status = LoadPrivateKey(private_key); + + if (status == NO_ERROR) { + drm_certificate_ = drm_certificate; + wrapped_private_key_.set_type(private_key.type()); + wrapped_private_key_.set_key(private_key.key()); + } + + return status; +} + +CdmResponseType CdmSession::LoadPrivateOrLegacyKey( + const std::string& certificate, const CryptoWrappedKey& private_key) { + // Use provided key if valid + if (!certificate.empty() && private_key.IsValid()) { + CdmResponseType status = LoadPrivateKey(private_key); + + if (status == NO_ERROR) { + drm_certificate_ = certificate; + wrapped_private_key_.set_type(private_key.type()); + wrapped_private_key_.set_key(private_key.key()); + } + + return status; + } + + // Otherwise use key from legacy certificate + std::string drm_certificate; + CryptoWrappedKey wrapped_private_key; + if (file_handle_->RetrieveLegacyCertificate( + &drm_certificate, &wrapped_private_key, nullptr, nullptr) != + DeviceFiles::kCertificateValid) + return NEED_PROVISIONING; + + CdmResponseType status = LoadPrivateKey(wrapped_private_key); + + if (status == NO_ERROR) { + drm_certificate_ = drm_certificate; + wrapped_private_key_.set_type(wrapped_private_key.type()); + wrapped_private_key_.set_key(wrapped_private_key.key()); + } + + return status; +} + +CdmResponseType CdmSession::LoadPrivateKey( + const CryptoWrappedKey& private_key) { + CdmResponseType load_cert_sts; + M_TIME( + load_cert_sts = crypto_session_->LoadCertificatePrivateKey(private_key), + crypto_metrics_, crypto_session_load_certificate_private_key_, + load_cert_sts); + + switch (load_cert_sts) { + case NO_ERROR: + metrics_->drm_certificate_key_type_.Record( + DrmKeyTypeToMetricValue(private_key.type())); + return NO_ERROR; + case SESSION_LOST_STATE_ERROR: + case SYSTEM_INVALIDATED_ERROR: + return load_cert_sts; + default: + return NEED_PROVISIONING; + } +} + // For testing only - takes ownership of pointers void CdmSession::set_license_parser(CdmLicense* license_parser) { diff --git a/libwvdrmengine/cdm/core/src/license.cpp b/libwvdrmengine/cdm/core/src/license.cpp index 0f3e3d7b..9d43f1d4 100644 --- a/libwvdrmengine/cdm/core/src/license.cpp +++ b/libwvdrmengine/cdm/core/src/license.cpp @@ -200,9 +200,7 @@ CdmLicense::CdmLicense(const CdmSessionId& session_id, Clock* clock) CdmLicense::~CdmLicense() {} -bool CdmLicense::Init(const std::string& client_token, - CdmClientTokenType client_token_type, - bool use_privacy_mode, +bool CdmLicense::Init(bool use_privacy_mode, const std::string& signed_service_certificate, CryptoSession* session, PolicyEngine* policy_engine) { if (!clock_) { @@ -213,10 +211,6 @@ bool CdmLicense::Init(const std::string& client_token, LOGE("Session ID not provided"); return false; } - if (client_token.size() == 0) { - LOGE("Client token not provided"); - return false; - } if (session == nullptr || !session->IsOpen()) { LOGE("Crypto session not provided or not open"); return false; @@ -231,8 +225,6 @@ bool CdmLicense::Init(const std::string& client_token, return false; } - client_token_ = client_token; - client_token_type_ = client_token_type; crypto_session_ = session; policy_engine_ = policy_engine; use_privacy_mode_ = use_privacy_mode; @@ -247,18 +239,19 @@ CdmResponseType CdmLicense::SetServiceCertificate( } CdmResponseType CdmLicense::PrepareKeyRequest( - const InitializationData& init_data, CdmLicenseType license_type, - const CdmAppParameterMap& app_parameters, CdmKeyMessage* signed_request, - std::string* server_url) { + const InitializationData& init_data, const std::string& client_token, + CdmLicenseType license_type, const CdmAppParameterMap& app_parameters, + CdmKeyMessage* signed_request, std::string* server_url) { if (!initialized_) { LOGE("CdmLicense not initialized"); return LICENSE_PARSER_NOT_INITIALIZED_4; } + client_token_ = client_token; if (init_data.IsEmpty() && stored_init_data_) { InitializationData restored_init_data = *stored_init_data_; stored_init_data_.reset(); - return PrepareKeyRequest(restored_init_data, license_type, app_parameters, - signed_request, server_url); + return PrepareKeyRequest(restored_init_data, client_token, license_type, + app_parameters, signed_request, server_url); } wrapped_keys_ = init_data.ExtractWrappedKeys(); if (!init_data.is_supported()) { @@ -793,7 +786,7 @@ CdmResponseType CdmLicense::HandleEmbeddedKeyData( } CdmResponseType CdmLicense::RestoreOfflineLicense( - const CdmKeyMessage& license_request, + const std::string& client_token, const CdmKeyMessage& license_request, const CdmKeyResponse& license_response, const CdmKeyResponse& license_renewal_response, int64_t playback_start_time, int64_t last_playback_time, int64_t grace_period_end_time, @@ -808,6 +801,8 @@ CdmResponseType CdmLicense::RestoreOfflineLicense( return EMPTY_LICENSE_RESPONSE_3; } + client_token_ = client_token; + SignedMessage signed_request; if (!signed_request.ParseFromString(license_request)) { LOGE("Failed to parse license request"); @@ -889,7 +884,7 @@ CdmResponseType CdmLicense::RestoreOfflineLicense( } CdmResponseType CdmLicense::RestoreLicenseForRelease( - const CdmKeyMessage& license_request, + const std::string& client_token, const CdmKeyMessage& license_request, const CdmKeyResponse& license_response) { if (license_request.empty()) { LOGE("License request is empty"); @@ -901,6 +896,8 @@ CdmResponseType CdmLicense::RestoreLicenseForRelease( return EMPTY_LICENSE_RESPONSE_4; } + client_token_ = client_token; + SignedMessage signed_request; if (!signed_request.ParseFromString(license_request)) { LOGE("Failed to parse signed license request"); @@ -1046,6 +1043,11 @@ CdmResponseType CdmLicense::PrepareClientId( const CdmAppParameterMap& app_parameters, const std::string& provider_client_token, LicenseRequest* license_request) { wvcdm::ClientIdentification id; + if (client_token_.empty()) { + LOGE("Client token not set when preparing client ID"); + return CLIENT_TOKEN_NOT_SET; + } + CdmResponseType status = id.Init(client_token_, crypto_session_); if (status != NO_ERROR) return status; diff --git a/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp b/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp index 8d9624ae..6dbf61d2 100644 --- a/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/cdm_session_unittest.cpp @@ -120,6 +120,7 @@ class MockDeviceFiles : public DeviceFiles { DeviceFiles::CertificateState(bool, std::string*, CryptoWrappedKey*, std::string*, uint32_t*)); + MOCK_METHOD1(HasCertificate, bool(bool)); }; class MockUsageTableHeader : public UsageTableHeader { @@ -169,8 +170,8 @@ class MockCdmLicense : public CdmLicense { public: MockCdmLicense(const CdmSessionId& session_id) : CdmLicense(session_id) {} - MOCK_METHOD6(Init, bool(const std::string&, CdmClientTokenType, bool, - const std::string&, CryptoSession*, PolicyEngine*)); + MOCK_METHOD4(Init, + bool(bool, const std::string&, CryptoSession*, PolicyEngine*)); MOCK_METHOD0(provider_session_token, std::string()); }; @@ -218,19 +219,10 @@ TEST_F(CdmSessionTest, InitWithBuiltInCertificate) { EXPECT_CALL(*crypto_session_, GetSecurityLevel()) .InSequence(crypto_session_seq) .WillOnce(Return(level)); - EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType()) - .WillOnce(Return(kClientTokenDrmCert)); - EXPECT_CALL(*file_handle_, - RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _)) - .WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey), - Return(DeviceFiles::kCertificateValid))); - EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey)) - .InSequence(crypto_session_seq) - .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true)); - EXPECT_CALL(*license_parser_, - Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString), - Eq(crypto_session_), Eq(policy_engine_))) + EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true)); + EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString), + Eq(crypto_session_), Eq(policy_engine_))) .WillOnce(Return(true)); ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr)); @@ -245,19 +237,10 @@ TEST_F(CdmSessionTest, InitWithCertificate) { EXPECT_CALL(*crypto_session_, GetSecurityLevel()) .InSequence(crypto_session_seq) .WillOnce(Return(level)); - EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType()) - .WillOnce(Return(kClientTokenKeybox)); EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true)); - EXPECT_CALL(*file_handle_, - RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _)) - .WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey), - Return(DeviceFiles::kCertificateValid))); - EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey)) - .InSequence(crypto_session_seq) - .WillOnce(Return(NO_ERROR)); - EXPECT_CALL(*license_parser_, - Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString), - Eq(crypto_session_), Eq(policy_engine_))) + EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true)); + EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString), + Eq(crypto_session_), Eq(policy_engine_))) .WillOnce(Return(true)); ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr)); @@ -272,19 +255,10 @@ TEST_F(CdmSessionTest, ReInitFail) { EXPECT_CALL(*crypto_session_, GetSecurityLevel()) .InSequence(crypto_session_seq) .WillOnce(Return(level)); - EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType()) - .WillOnce(Return(kClientTokenKeybox)); EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true)); - EXPECT_CALL(*file_handle_, - RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _)) - .WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey), - Return(DeviceFiles::kCertificateValid))); - EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey)) - .InSequence(crypto_session_seq) - .WillOnce(Return(NO_ERROR)); - EXPECT_CALL(*license_parser_, - Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString), - Eq(crypto_session_), Eq(policy_engine_))) + EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true)); + EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString), + Eq(crypto_session_), Eq(policy_engine_))) .WillOnce(Return(true)); ASSERT_EQ(NO_ERROR, cdm_session_->Init(nullptr)); @@ -298,25 +272,6 @@ TEST_F(CdmSessionTest, InitFailCryptoError) { ASSERT_EQ(UNKNOWN_ERROR, cdm_session_->Init(nullptr)); } -TEST_F(CdmSessionTest, InitNeedsProvisioning) { - Sequence crypto_session_seq; - CdmSecurityLevel level = kSecurityLevelL1; - EXPECT_CALL(*crypto_session_, Open(Eq(kLevelDefault))) - .InSequence(crypto_session_seq) - .WillOnce(Return(NO_ERROR)); - EXPECT_CALL(*crypto_session_, GetSecurityLevel()) - .InSequence(crypto_session_seq) - .WillOnce(Return(level)); - EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType()) - .WillOnce(Return(kClientTokenKeybox)); - EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true)); - EXPECT_CALL(*file_handle_, - RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _)) - .WillOnce(Return(DeviceFiles::kCertificateInvalid)); - - ASSERT_EQ(NEED_PROVISIONING, cdm_session_->Init(nullptr)); -} - TEST_F(CdmSessionTest, UpdateUsageEntry) { // Setup common expectations for initializing the CdmSession object. Sequence crypto_session_seq; @@ -327,21 +282,12 @@ TEST_F(CdmSessionTest, UpdateUsageEntry) { EXPECT_CALL(*crypto_session_, GetSecurityLevel()) .InSequence(crypto_session_seq) .WillOnce(Return(level)); - EXPECT_CALL(*crypto_session_, GetPreProvisionTokenType()) - .WillOnce(Return(kClientTokenKeybox)); EXPECT_CALL(*file_handle_, Init(Eq(level))).WillOnce(Return(true)); - EXPECT_CALL(*file_handle_, - RetrieveCertificate(false, NotNull(), NotNull(), NotNull(), _)) - .WillOnce(DoAll(SetArgPointee<1>(kToken), SetArgPointee<2>(kWrappedKey), - Return(DeviceFiles::kCertificateValid))); - EXPECT_CALL(*crypto_session_, LoadCertificatePrivateKey(kWrappedKey)) - .InSequence(crypto_session_seq) - .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*file_handle_, HasCertificate(false)).WillOnce(Return(true)); EXPECT_CALL(*crypto_session_, GetUsageTableHeader()) .WillOnce(Return(&usage_table_header_)); - EXPECT_CALL(*license_parser_, - Init(Eq(kToken), Eq(kClientTokenDrmCert), false, Eq(kEmptyString), - Eq(crypto_session_), Eq(policy_engine_))) + EXPECT_CALL(*license_parser_, Init(false, Eq(kEmptyString), + Eq(crypto_session_), Eq(policy_engine_))) .WillOnce(Return(true)); // Set up mocks and expectations for the UpdateUsageEntryInformation call. diff --git a/libwvdrmengine/cdm/core/test/license_unittest.cpp b/libwvdrmengine/cdm/core/test/license_unittest.cpp index cf22f709..f4a304f1 100644 --- a/libwvdrmengine/cdm/core/test/license_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/license_unittest.cpp @@ -250,22 +250,13 @@ TEST_F(CdmLicenseTest, InitSuccess) { EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true)); CreateCdmLicense(); - EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, false, - kEmptyServiceCertificate, crypto_session_, - policy_engine_)); -} - -TEST_F(CdmLicenseTest, InitFail_EmptyToken) { - CreateCdmLicense(); - EXPECT_FALSE(cdm_license_->Init("", kClientTokenDrmCert, false, - kEmptyServiceCertificate, crypto_session_, - policy_engine_)); + EXPECT_TRUE(cdm_license_->Init(false, kEmptyServiceCertificate, + crypto_session_, policy_engine_)); } TEST_F(CdmLicenseTest, InitFail_CryptoSessionNull) { CreateCdmLicense(); - EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, false, - kEmptyServiceCertificate, nullptr, + EXPECT_FALSE(cdm_license_->Init(false, kEmptyServiceCertificate, nullptr, policy_engine_)); } @@ -273,36 +264,32 @@ TEST_F(CdmLicenseTest, InitFail_PolicyEngineNull) { EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true)); CreateCdmLicense(); - EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, false, - kEmptyServiceCertificate, crypto_session_, - nullptr)); + EXPECT_FALSE(cdm_license_->Init(false, kEmptyServiceCertificate, + crypto_session_, nullptr)); } TEST_F(CdmLicenseTest, InitWithEmptyServiceCert) { EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true)); CreateCdmLicense(); - EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true, - kEmptyServiceCertificate, crypto_session_, - policy_engine_)); + EXPECT_TRUE(cdm_license_->Init(true, kEmptyServiceCertificate, + crypto_session_, policy_engine_)); } TEST_F(CdmLicenseTest, InitWithInvalidServiceCert) { EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true)); CreateCdmLicense(); - EXPECT_FALSE(cdm_license_->Init(kToken, kClientTokenDrmCert, true, - kInvalidServiceCertificate, crypto_session_, - policy_engine_)); + EXPECT_FALSE(cdm_license_->Init(true, kInvalidServiceCertificate, + crypto_session_, policy_engine_)); } TEST_F(CdmLicenseTest, InitWithServiceCert) { EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true)); CreateCdmLicense(); - EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true, - kDefaultServiceCertificate, crypto_session_, - policy_engine_)); + EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate, + crypto_session_, policy_engine_)); } TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) { @@ -335,16 +322,15 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) { Return(NO_ERROR))); CreateCdmLicense(); - EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true, - kDefaultServiceCertificate, crypto_session_, - policy_engine_)); + EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate, + crypto_session_, policy_engine_)); CdmAppParameterMap app_parameters; CdmKeyMessage signed_request; std::string server_url; - EXPECT_EQ(cdm_license_->PrepareKeyRequest(*init_data_, kLicenseTypeStreaming, - app_parameters, &signed_request, - &server_url), + EXPECT_EQ(cdm_license_->PrepareKeyRequest( + *init_data_, kToken, kLicenseTypeStreaming, app_parameters, + &signed_request, &server_url), KEY_MESSAGE); EXPECT_TRUE(!signed_request.empty()); @@ -460,16 +446,15 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) { Return(NO_ERROR))); CreateCdmLicense(); - EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true, - kDefaultServiceCertificate, crypto_session_, - policy_engine_)); + EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate, + crypto_session_, policy_engine_)); CdmAppParameterMap app_parameters; CdmKeyMessage signed_request; std::string server_url; - EXPECT_EQ(cdm_license_->PrepareKeyRequest(*init_data_, kLicenseTypeStreaming, - app_parameters, &signed_request, - &server_url), + EXPECT_EQ(cdm_license_->PrepareKeyRequest( + *init_data_, kToken, kLicenseTypeStreaming, app_parameters, + &signed_request, &server_url), KEY_MESSAGE); EXPECT_TRUE(!signed_request.empty()); @@ -601,9 +586,8 @@ TEST_P(CdmLicenseEntitledKeyTest, LoadsEntitledKeys) { // Set up the CdmLicense with the mocks and fake entitlement key CreateCdmLicense(); - EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, true, - kDefaultServiceCertificate, crypto_session_, - policy_engine_)); + EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate, + crypto_session_, policy_engine_)); cdm_license_->set_entitlement_keys(entitlement_license); // Call the function under test and check its return value diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 97873e18..c0198cc6 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -51,6 +51,8 @@ namespace { // HTTP response codes. const int kHttpOk = 200; +const int kDrmCertificateExpiryPeriod = 150; +const std::string kCencMimeType = "video/mp4"; const wvcdm::CdmIdentifier kExampleIdentifier = { wvcdm::EMPTY_SPOID, "com.example", "com.example", 7, 9}; @@ -1747,6 +1749,13 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { client_auth->assign(config.client_auth()); } + CdmResponseType GenerateKeyRequest() { + CdmAppParameterMap app_parameters; + return GenerateKeyRequest(kCencMimeType, binary_key_id(), app_parameters, + kLicenseTypeStreaming, kDefaultCdmIdentifier, + nullptr); + } + void GenerateKeyRequest(const std::string& init_data, CdmLicenseType license_type) { GenerateKeyRequest(init_data, license_type, nullptr); @@ -1794,6 +1803,24 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { CdmLicenseType license_type, const CdmIdentifier& cdm_identifier, CdmClientPropertySet* property_set) { + CdmResponseType status = + GenerateKeyRequest(init_data_type, init_data, app_parameters, + license_type, cdm_identifier, property_set); + EXPECT_EQ(expected_response, status) + << "session_id_ " << session_id_ << std::endl + << "init_data (hex) " << wvcdm::b2a_hex(init_data) << std::endl + << "cdm_identifier.origin " << cdm_identifier.origin << std::endl + << "cdm_identifier.app_package_name " << cdm_identifier.app_package_name + << std::endl + << "cdm_identifier.unique_id " << cdm_identifier.unique_id << std::endl; + } + + CdmResponseType GenerateKeyRequest(const std::string& init_data_type, + const std::string& init_data, + CdmAppParameterMap& app_parameters, + CdmLicenseType license_type, + const CdmIdentifier& cdm_identifier, + CdmClientPropertySet* property_set) { CdmKeyRequest key_request; std::string key_set_id; license_type_ = license_type; @@ -1801,20 +1828,13 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { InitializationData parsed_init_data(init_data_type, init_data); parsed_init_data.DumpToLogs(); } - EXPECT_EQ( - expected_response, - decryptor_->GenerateKeyRequest( - session_id_, key_set_id, init_data_type, init_data, license_type, - app_parameters, property_set, cdm_identifier, &key_request)) - << "session_id_ " << session_id_ << std::endl - << "init_data (hex) " << wvcdm::b2a_hex(init_data) << std::endl - << "key_set_id " << key_set_id << std::endl - << "cdm_identifier.origin " << cdm_identifier.origin << std::endl - << "cdm_identifier.app_package_name " << cdm_identifier.app_package_name - << std::endl - << "cdm_identifier.unique_id " << cdm_identifier.unique_id << std::endl; + + CdmResponseType status = decryptor_->GenerateKeyRequest( + session_id_, key_set_id, init_data_type, init_data, license_type, + app_parameters, property_set, cdm_identifier, &key_request); key_msg_ = key_request.message; EXPECT_EQ(0u, key_request.url.size()); + return status; } void GenerateRenewalRequest(CdmLicenseType license_type, @@ -2027,6 +2047,40 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { decryptor_->Unprovision(kSecurityLevelL3, kDefaultCdmIdentifier)); } + bool IsProvisioned(const CdmIdentifier& identifier, + SecurityLevel requested_security_level) { + TestWvCdmClientPropertySet property_set_L3; + TestWvCdmClientPropertySet* property_set = nullptr; + + if (kLevel3 == requested_security_level) { + property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3); + property_set = &property_set_L3; + } + + CdmResponseType status = decryptor_->OpenSession( + config_.key_system(), property_set, identifier, nullptr, &session_id_); + + if (status == NO_ERROR) { + wvcdm::CdmAppParameterMap app_parameters; + status = + GenerateKeyRequest(kCencMimeType, binary_key_id(), app_parameters, + kLicenseTypeStreaming, identifier, nullptr); + } + + decryptor_->CloseSession(session_id_); + + switch (status) { + case NO_ERROR: + case KEY_MESSAGE: + return true; + case NEED_PROVISIONING: + return false; + default: + EXPECT_EQ(NO_ERROR, status); + return false; + } + } + void Provision() { Provision(kDefaultCdmIdentifier, kLevelDefault); } void Provision(const CdmIdentifier& identifier, @@ -2040,24 +2094,13 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { property_set = &property_set_L3; } - CdmResponseType status = decryptor_->OpenSession( - config_.key_system(), property_set, identifier, nullptr, &session_id_); - switch (status) { - case NO_ERROR: - decryptor_->CloseSession(session_id_); - return; - case NEED_PROVISIONING: - break; - default: - EXPECT_EQ(NO_ERROR, status); - return; - } + if (IsProvisioned(identifier, requested_security_level)) return; std::string provisioning_server; CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; - status = decryptor_->GetProvisioningRequest( + CdmResponseType status = decryptor_->GetProvisioningRequest( cert_type, cert_authority, identifier, kEmptyServiceCertificate, requested_security_level, &key_msg_, &provisioning_server); EXPECT_EQ(wvcdm::NO_ERROR, status); @@ -2169,10 +2212,8 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) { Unprovision(); - EXPECT_EQ( - NEED_PROVISIONING, - decryptor_->OpenSession(config_.key_system(), nullptr, - kDefaultCdmIdentifier, nullptr, &session_id_)); + EXPECT_FALSE(IsProvisioned(kDefaultCdmIdentifier, kLevelDefault)); + std::string provisioning_server; CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; @@ -2195,11 +2236,9 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) { } TEST_F(WvCdmRequestLicenseTest, ProvisioningTestWithServiceCertificate) { - CdmResponseType status = - decryptor_->OpenSession(config_.key_system(), nullptr, - kDefaultCdmIdentifier, nullptr, &session_id_); - EXPECT_TRUE(status == NEED_PROVISIONING || status == NO_ERROR) - << "Failure to open session. error: " << status; + Unprovision(); + EXPECT_FALSE(IsProvisioned(kDefaultCdmIdentifier, kLevelDefault)); + std::string provisioning_server; CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; @@ -2222,6 +2261,7 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningTestWithServiceCertificate) { } TEST_F(WvCdmRequestLicenseTest, L3ProvisioningTest) { + Unprovision(); TestWvCdmClientPropertySet property_set_L3; property_set_L3.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3); std::string provisioning_server; @@ -2246,19 +2286,28 @@ TEST_F(WvCdmRequestLicenseTest, L3ProvisioningTest) { } TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningTest) { + Unprovision(); EXPECT_EQ(NO_ERROR, decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier)); + Provision(); // Verify the global identifier is provisioned. EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->OpenSession( config_.key_system(), nullptr, kDefaultCdmIdentifier, nullptr, &session_id_)); + + CdmAppParameterMap app_parameters; + EXPECT_EQ(KEY_MESSAGE, + GenerateKeyRequest(kCencMimeType, binary_key_id(), app_parameters, + kLicenseTypeStreaming, kDefaultCdmIdentifier, + nullptr)); decryptor_->CloseSession(session_id_); // The other identifier should not be provisioned. EXPECT_EQ(wvcdm::NEED_PROVISIONING, decryptor_->OpenSession(config_.key_system(), nullptr, kExampleIdentifier, nullptr, &session_id_)); + EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault)); } TEST_F(WvCdmRequestLicenseTest, PerOriginProvisioningSupportsOldPaths) { @@ -2588,6 +2637,42 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningRevocationTest) { } } +TEST_F(WvCdmRequestLicenseTest, ProvisioningWithExpiringCertTest) { + EXPECT_EQ(NO_ERROR, + decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier)); + EXPECT_EQ(NO_ERROR, + decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier)); + + EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault)); + ConfigTestEnv config(kContentProtectionStagingServer, true); + + // Provision + std::string provisioning_server; + CdmCertificateType cert_type = kCertificateWidevine; + std::string cert_authority, cert, wrapped_key; + + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest( + cert_type, cert_authority, kExampleIdentifier, + kEmptyServiceCertificate, kLevelDefault, + &key_msg_, &provisioning_server)); + + std::string response = GetCertRequestResponse(config.provisioning_server()); + EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse( + kExampleIdentifier, response, kLevelDefault, + &cert, &wrapped_key)); + EXPECT_EQ(0, static_cast(cert.size())); + EXPECT_EQ(0, static_cast(wrapped_key.size())); + decryptor_->CloseSession(session_id_); + + // Make sure it is provisioned, then wait for certificate expiry period + EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault)); + sleep(kDrmCertificateExpiryPeriod); + + // Verify that it is no longer provisioned after the certificate expires + EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault)); +} + TEST_F(WvCdmRequestLicenseTest, PropertySetTest) { TestWvCdmClientPropertySet property_set_L1; TestWvCdmClientPropertySet property_set_L3; @@ -2760,6 +2845,48 @@ TEST_F(WvCdmRequestLicenseTest, AddStreamingKeyTest) { decryptor_->CloseSession(session_id_); } +TEST_F(WvCdmRequestLicenseTest, StreamingWithExpiringCertTest) { + EXPECT_EQ(NO_ERROR, + decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier)); + EXPECT_EQ(NO_ERROR, + decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier)); + + EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault)); + ConfigTestEnv config(kContentProtectionStagingServer, true); + + // Provision + std::string provisioning_server; + CdmCertificateType cert_type = kCertificateWidevine; + std::string cert_authority, cert, wrapped_key; + + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest( + cert_type, cert_authority, kExampleIdentifier, + kEmptyServiceCertificate, kLevelDefault, + &key_msg_, &provisioning_server)); + + std::string response = GetCertRequestResponse(config.provisioning_server()); + EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse( + kExampleIdentifier, response, kLevelDefault, + &cert, &wrapped_key)); + EXPECT_EQ(0, static_cast(cert.size())); + EXPECT_EQ(0, static_cast(wrapped_key.size())); + + EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault)); + + // Fetch a streaming license + EXPECT_EQ(NO_ERROR, + decryptor_->OpenSession(config_.key_system(), nullptr, + kExampleIdentifier, nullptr, &session_id_)); + + CdmAppParameterMap app_parameters; + GenerateKeyRequest(KEY_MESSAGE, kCencMimeType, binary_key_id(), + app_parameters, kLicenseTypeStreaming, kExampleIdentifier, + nullptr); + VerifyKeyRequestResponse(config_.license_server(), config_.client_auth()); + decryptor_->CloseSession(session_id_); +} + TEST_F(WvCdmRequestLicenseTest, AddKeyOfflineTest) { Unprovision(); Provision(); @@ -2801,6 +2928,68 @@ TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeyTest) { decryptor_->CloseSession(session_id_); } +TEST_F(WvCdmRequestLicenseTest, RestoreOfflineKeysWithExpiringCertTest) { + EXPECT_EQ(NO_ERROR, + decryptor_->Unprovision(kSecurityLevelL1, kExampleIdentifier)); + EXPECT_EQ(NO_ERROR, + decryptor_->Unprovision(kSecurityLevelL3, kExampleIdentifier)); + + EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault)); + ConfigTestEnv config(kContentProtectionStagingServer, true); + + // Provision + std::string provisioning_server; + CdmCertificateType cert_type = kCertificateWidevine; + std::string cert_authority, cert, wrapped_key; + + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->GetProvisioningRequest( + cert_type, cert_authority, kExampleIdentifier, + kEmptyServiceCertificate, kLevelDefault, + &key_msg_, &provisioning_server)); + + std::string response = GetCertRequestResponse(config.provisioning_server()); + EXPECT_NE(0, static_cast(response.size())); + EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse( + kExampleIdentifier, response, kLevelDefault, + &cert, &wrapped_key)); + EXPECT_EQ(0, static_cast(cert.size())); + EXPECT_EQ(0, static_cast(wrapped_key.size())); + + EXPECT_TRUE(IsProvisioned(kExampleIdentifier, kLevelDefault)); + + std::string key_id; + std::string client_auth; + GetOfflineConfiguration(&key_id, &client_auth); + + // Fetch offline license + EXPECT_EQ(NO_ERROR, + decryptor_->OpenSession(config_.key_system(), nullptr, + kExampleIdentifier, nullptr, &session_id_)); + + CdmAppParameterMap app_parameters; + GenerateKeyRequest(KEY_MESSAGE, kCencMimeType, key_id, app_parameters, + kLicenseTypeOffline, kExampleIdentifier, nullptr); + VerifyKeyRequestResponse(config_.license_server(), client_auth); + + 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); + + // Make sure the certificate has expired and the device is not provisioned + EXPECT_FALSE(IsProvisioned(kExampleIdentifier, kLevelDefault)); + + // Restore offline license + decryptor_->OpenSession(config_.key_system(), nullptr, kExampleIdentifier, + nullptr, &session_id_); + EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_->RestoreKey(session_id_, key_set_id)); + decryptor_->CloseSession(session_id_); +} + TEST_F(WvCdmRequestLicenseTest, DisallowMultipleRestoreOfflineKeyTest) { Unprovision(); Provision(); @@ -2987,11 +3176,7 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) { std::string client_auth; GetOfflineConfiguration(&key_id, &client_auth); - CdmResponseType sts = - decryptor_->OpenSession(config_.key_system(), &property_set, - kDefaultCdmIdentifier, nullptr, &session_id_); - - if (NEED_PROVISIONING == sts) { + if (!IsProvisioned(kDefaultCdmIdentifier, kLevel3)) { std::string provisioning_server; CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; @@ -3009,8 +3194,6 @@ TEST_F(WvCdmRequestLicenseTest, ReleaseRetryL3OfflineKeyTest) { EXPECT_EQ(NO_ERROR, decryptor_->OpenSession( config_.key_system(), &property_set, kDefaultCdmIdentifier, nullptr, &session_id_)); - } else { - EXPECT_EQ(NO_ERROR, sts); } decryptor_->OpenSession(config_.key_system(), &property_set, @@ -3063,11 +3246,7 @@ TEST_F(WvCdmRequestLicenseTest, GetOfflineConfiguration(&key_id, &client_auth); key_id[key_id.size() - 1] = '1'; - CdmResponseType sts = - decryptor_->OpenSession(config_.key_system(), &property_set, - kDefaultCdmIdentifier, nullptr, &session_id_); - - if (NEED_PROVISIONING == sts) { + if (!IsProvisioned(kDefaultCdmIdentifier, kLevel3)) { std::string provisioning_server_url; CdmCertificateType cert_type = kCertificateWidevine; std::string cert_authority, cert, wrapped_key; @@ -3085,8 +3264,6 @@ TEST_F(WvCdmRequestLicenseTest, EXPECT_EQ(NO_ERROR, decryptor_->OpenSession( config_.key_system(), &property_set, kDefaultCdmIdentifier, nullptr, &session_id_)); - } else { - EXPECT_EQ(NO_ERROR, sts); } decryptor_->OpenSession(config_.key_system(), &property_set, diff --git a/libwvdrmengine/cdm/test/wv_cdm_metrics_test.cpp b/libwvdrmengine/cdm/test/wv_cdm_metrics_test.cpp index f4db8233..66e9b436 100644 --- a/libwvdrmengine/cdm/test/wv_cdm_metrics_test.cpp +++ b/libwvdrmengine/cdm/test/wv_cdm_metrics_test.cpp @@ -103,7 +103,7 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineAndSessionMetrics) { wvcdm::CdmKeySystem key_system("com.widevine"); Unprovision(kDefaultCdmIdentifier); - // Openning the session will fail with NEEDS_PROVISIONING error. But it will + // Opening the session will fail with NEEDS_PROVISIONING error. But it will // still create some session-level stats. EXPECT_EQ(CdmResponseType::NEED_PROVISIONING, decryptor_.OpenSession(key_system, nullptr, kDefaultCdmIdentifier, @@ -133,11 +133,6 @@ TEST_F(WvContentDecryptionModuleMetricsTest, EngineAndSessionMetrics) { // Validate a session-level metric. ASSERT_THAT(metrics.session_metrics().size(), Eq(1)); - EXPECT_THAT( - metrics.session_metrics(0).cdm_session_life_span_ms().double_value(), - Gt(0.0)) - << "Unexpected failure with session_metrics: " - << wvcdm::b2a_hex(serialized_metrics); } TEST_F(WvContentDecryptionModuleMetricsTest, @@ -190,11 +185,6 @@ TEST_F(WvContentDecryptionModuleMetricsTest, ASSERT_THAT(metrics.session_metrics().size(), Eq(i + 1)) << "Unexpected failure with session_metrics: " << wvcdm::b2a_hex(serialized_metrics); - EXPECT_THAT( - metrics.session_metrics(0).cdm_session_life_span_ms().double_value(), - Gt(0.0)) - << "Unexpected failure with session_metrics: " - << wvcdm::b2a_hex(serialized_metrics); } }