V18.4.0 CAS plugin
Note that this version does not have Widevine Provisioning 4.0 support. It is only suitable for device upgrades. A new patch with provisioning 4.0 support will be made later.
This commit is contained in:
214
plugin/include/policy_engine.h
Normal file
214
plugin/include/policy_engine.h
Normal file
@@ -0,0 +1,214 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#ifndef WIDEVINE_CAS_POLICY_ENGINE_H_
|
||||
#define WIDEVINE_CAS_POLICY_ENGINE_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "cas_util.h"
|
||||
#include "clock.h"
|
||||
#include "crypto_session.h"
|
||||
#include "license_key_status.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "timer.h"
|
||||
|
||||
namespace wvcas {
|
||||
|
||||
// This acts as an oracle that basically says "Yes(true) you may still decrypt
|
||||
// or no(false) you may not decrypt this data anymore."
|
||||
// TODO(jfore): Just pass in a function object? OnTimerEvent can be a
|
||||
class PolicyEngine : public wvutil::TimerHandler {
|
||||
typedef enum {
|
||||
kLicenseStateInitial,
|
||||
kLicenseStatePending, // if license is issued for sometime in the future
|
||||
kLicenseStateCanPlay,
|
||||
kLicenseStateNeedRenewal,
|
||||
kLicenseStateWaitingLicenseUpdate,
|
||||
kLicenseStateExpired
|
||||
} LicenseState;
|
||||
|
||||
public:
|
||||
// The default constructor.
|
||||
PolicyEngine() {}
|
||||
virtual ~PolicyEngine() {}
|
||||
|
||||
virtual void initialize(std::shared_ptr<CryptoSession> crypto_session,
|
||||
CasEventListener* event_listener) {
|
||||
license_keys_ = CreateLicenseKeys();
|
||||
clock_ = CreateClock();
|
||||
event_listener_ = event_listener;
|
||||
crypto_session_ = crypto_session;
|
||||
}
|
||||
|
||||
// The value returned should be taken as a hint rather than an absolute
|
||||
// status. It is computed during the last call to either SetLicense/
|
||||
// UpdateLicense/OnTimerEvent/BeginDecryption and may be out of sync
|
||||
// depending on the amount of time elapsed. The current decryption
|
||||
// status is not calculated to avoid overhead in the decryption path.
|
||||
virtual bool CanDecryptContent(const KeyId& key_id) const;
|
||||
|
||||
// The value returned indicates if a license renewal is allowed under the
|
||||
// current policy.
|
||||
virtual bool CanRenew() const { return policy_.can_renew(); }
|
||||
|
||||
// The value returned indicates if the license is persisted to non-volatile
|
||||
// storage for offline use.
|
||||
virtual bool CanPersist() const { return policy_.can_persist(); }
|
||||
|
||||
// The value returned indicates whether or not the client id should be
|
||||
// included in renewal requests.
|
||||
virtual bool always_include_client_id() const {
|
||||
return policy_.always_include_client_id();
|
||||
}
|
||||
|
||||
// The value returned is the current license id.
|
||||
virtual const video_widevine::LicenseIdentification& license_id() const {
|
||||
return license_id_;
|
||||
}
|
||||
|
||||
virtual const std::string& renewal_server_url() const {
|
||||
return policy_.renewal_server_url();
|
||||
}
|
||||
|
||||
// SetLicense is used in handling the initial license response. It stores
|
||||
// an exact copy of the policy information stored in the license.
|
||||
// The license state transitions to kLicenseStateCanPlay if the license
|
||||
// permits playback.
|
||||
virtual void SetLicense(const video_widevine::License& license);
|
||||
|
||||
// UpdateLicense is used in handling a license response for a renewal request.
|
||||
// The response may only contain any policy fields that have changed. In this
|
||||
// case an exact copy is not what we want to happen. We also will receive an
|
||||
// updated license_start_time from the server. The license will transition to
|
||||
// kLicenseStateCanPlay if the license permits playback.
|
||||
virtual void UpdateLicense(const video_widevine::License& license);
|
||||
|
||||
// Call this on first decrypt to set the start of playback.
|
||||
virtual void BeginDecryption(void);
|
||||
|
||||
// OnTimerEvent is called when a timer fires. It notifies the Policy Engine
|
||||
// that the timer has fired and dispatches the relevant events through
|
||||
// |event_listener_|.
|
||||
virtual void OnTimerEvent() override;
|
||||
|
||||
// Used to update the currently loaded entitled content keys.
|
||||
virtual void SetEntitledLicenseKeys(
|
||||
const std::vector<WidevinePsshData_EntitledKey>& entitled_keys);
|
||||
|
||||
// Used to query if the current license state is expired.
|
||||
virtual bool IsExpired() const {
|
||||
return license_state_ == kLicenseStateExpired;
|
||||
}
|
||||
|
||||
// for offline save and restore
|
||||
int64_t GetPlaybackStartTime() const { return playback_start_time_; }
|
||||
int64_t GetLastPlaybackTime() const { return last_playback_time_; }
|
||||
int64_t GetGracePeriodEndTime() const { return grace_period_end_time_; }
|
||||
void RestorePlaybackTimes(int64_t playback_start_time,
|
||||
int64_t last_playback_time,
|
||||
int64_t grace_period_end_time);
|
||||
|
||||
PolicyEngine(const PolicyEngine&) = delete;
|
||||
PolicyEngine& operator=(const PolicyEngine&) = delete;
|
||||
|
||||
private:
|
||||
// Notifies updates in keys information and fire OnKeysChange event if
|
||||
// key changes.
|
||||
void NotifyKeysChange(KeyStatus new_status);
|
||||
|
||||
void NotifyLicenseExpired(LicenseState key_status);
|
||||
|
||||
bool HasLicenseOrPlaybackDurationExpired(int64_t current_time);
|
||||
|
||||
// Notifies updates in expiry time and fire OnExpirationUpdate event if
|
||||
// expiry time changes.
|
||||
void NotifyExpirationUpdate(int64_t current_time);
|
||||
|
||||
// Notify listeners of the current renewal url.
|
||||
void NotifyRenewalServerUpdate();
|
||||
|
||||
// Guard against clock rollbacks
|
||||
int64_t GetCurrentTime();
|
||||
|
||||
LicenseState license_state_ = kLicenseStateInitial;
|
||||
|
||||
void CheckDeviceHdcpStatus();
|
||||
|
||||
// Gets the clock time that the license expires based on whether we have
|
||||
// started playing. This takes into account GetHardLicenseExpiryTime.
|
||||
int64_t GetExpiryTime(int64_t current_time,
|
||||
bool ignore_soft_enforce_playback_duration);
|
||||
|
||||
void CheckDeviceHdcpStatusOnTimer(int64_t current_time);
|
||||
|
||||
bool HasPlaybackStarted(int64_t current_time) {
|
||||
if (playback_start_time_ == 0) return false;
|
||||
|
||||
const int64_t playback_time = current_time - playback_start_time_;
|
||||
return playback_time >= policy_.play_start_grace_period_seconds();
|
||||
}
|
||||
|
||||
// Gets the clock time that the rental duration will expire, using the license
|
||||
// duration if one is not present.
|
||||
int64_t GetRentalExpiryTime();
|
||||
|
||||
// Gets the clock time that the license expires. This is the hard limit that
|
||||
// all license types must obey at all times.
|
||||
int64_t GetHardLicenseExpiryTime();
|
||||
|
||||
bool HasRenewalDelayExpired(int64_t current_time);
|
||||
|
||||
bool HasRenewalRetryIntervalExpired(int64_t current_time);
|
||||
|
||||
void UpdateRenewalRequest(int64_t current_time);
|
||||
|
||||
virtual std::unique_ptr<wvcas::LicenseKeys> CreateLicenseKeys();
|
||||
|
||||
virtual std::unique_ptr<wvutil::Clock> CreateClock();
|
||||
|
||||
// This is the current policy information for this license. This gets updated
|
||||
// as license renewals occur.
|
||||
video_widevine::License::Policy policy_;
|
||||
|
||||
// This is the license id field from server response. This data gets passed
|
||||
// back to the server in each renewal request. When we get a renewal response
|
||||
// from the license server we will get an updated id field.
|
||||
video_widevine::LicenseIdentification license_id_;
|
||||
|
||||
// The server returns the license start time in the license/license renewal
|
||||
// response based off the request time sent by the client in the
|
||||
// license request/renewal
|
||||
int64_t license_start_time_ = 0;
|
||||
int64_t playback_start_time_ = 0;
|
||||
int64_t last_playback_time_ = 0;
|
||||
int64_t grace_period_end_time_ = 0;
|
||||
bool last_expiry_time_set_ = false;
|
||||
bool was_expired_on_load_ = false;
|
||||
|
||||
// This is used as a reference point for policy management. This value
|
||||
// represents an offset from license_start_time_. This is used to
|
||||
// calculate the time where renewal retries should occur.
|
||||
int64_t next_renewal_time_ = 0;
|
||||
|
||||
CasEventListener* event_listener_ = nullptr;
|
||||
|
||||
// Keys associated with license - holds allowed usage, usage constraints,
|
||||
// and current status (KeyStatus)
|
||||
std::unique_ptr<LicenseKeys> license_keys_;
|
||||
std::unique_ptr<wvutil::Clock> clock_;
|
||||
// to assist in clock rollback checks
|
||||
int64_t last_recorded_current_time_ = 0;
|
||||
int64_t last_expiry_time_ = 0;
|
||||
int64_t next_device_check_ = 0;
|
||||
std::shared_ptr<wvcas::CryptoSession> crypto_session_;
|
||||
uint32_t current_resolution_ = 0;
|
||||
std::string renewal_server_url_;
|
||||
};
|
||||
|
||||
} // namespace wvcas
|
||||
|
||||
#endif // WIDEVINE_CAS_POLICY_ENGINE_H_
|
||||
Reference in New Issue
Block a user