// 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 CAS_LICENSE_H #define CAS_LICENSE_H #include #include #include "cas_status.h" #include "crypto_session.h" #include "crypto_wrapped_key.h" #include "file_store.h" #include "policy_engine.h" #include "service_certificate.h" #include "timer.h" namespace wvcas { // CasLicense implements the core functionality needed to interact with service // to obtain and manage entitlements. class CasLicense : public wvutil::TimerHandler, public wvcas::CasEventListener { public: CasLicense() {} virtual ~CasLicense() {} // Initialize CasLicense with a |crypto_session|. |listener| may be null. virtual CasStatus initialize(std::shared_ptr crypto_session, CasEventListener* listener); // Generate a request to obtain a device certificate for requesting // entitlements. The generated message is set in |provisioning_request|. virtual CasStatus GenerateDeviceProvisioningRequest( wvutil::FileSystem& file_system, std::string* provisioning_request); // Process a server response containing a device certificate for use in // requesting entitlements. The contained certificate data will be extracted // and wrapped for storage. The public key cert will be returned in // |device_certificate|. The private key information will be wrapped by the // crypto session and returned in |wrapped_private_key|. // A secure binary file image containing the device cert is returned in // |device_file| if not nullptr. This file is suitable for storage on a device virtual CasStatus HandleDeviceProvisioningResponse( wvutil::FileSystem* file_system, const std::string& signed_provisioning_response, std::string* device_certificate, CryptoWrappedKey* wrapped_private_key) const; // Generate a request to obtain an EMM (Entitlement Management Message) to // use to enable processing of ECM(s) (Encryption Management Message). // |init_data| is widevine metadata about the stream needed in the request. // |private_key| and |signed_license_request| are the device certificate // obtained by HandleDeviceProvisioningResponse. virtual CasStatus GenerateEntitlementRequest( const std::string& init_data, const std::string& device_certificate, const CryptoWrappedKey& private_key, LicenseType license_type, std::string* signed_license_request); // Restores a stored license making the keys available for use. virtual CasStatus HandleStoredLicense(const CryptoWrappedKey& private_key, const std::string& license_file); // Process a server response containing a EMM for use in the processing of // ECM(s). // If |device_file| is not nullptr and the license policy allows a license to // be stored |device_file| is populated with the bytes of the license secured // for storage. virtual CasStatus HandleEntitlementResponse( const std::string& entitlement_response, std::string* device_file); // Process a previously stored device |certificate| and make it available // for use in an EMM request. virtual CasStatus HandleStoredDrmCert(const std::string& certificate, std::string* device_certificate, CryptoWrappedKey* private_key); // Generate an entitlement renewal request message in // |signed_renewal_request|. virtual CasStatus GenerateEntitlementRenewalRequest( const std::string& device_certificate, std::string* signed_renewal_request); // Process a server response containing a EMM renewal. If |device_file| is not // nullptr and the license policy allows a license renewal to be stored // |device_file| is populated with the bytes of the license secured for // storage. virtual CasStatus HandleEntitlementRenewalResponse( const std::string& renewal_response, std::string* device_file); // Query the license to see if a key is usable. virtual bool CanDecryptContent(const KeyId& key_id) const; // Update the license after handling license remove. Plugin is disabled to // playback stream, store and renew license. virtual void UpdateLicenseForLicenseRemove(); // Query the license to see if storage is allowed. virtual bool CanStoreLicense() const; // Returns the group id specified in the license. Group id is expected to be // non-empty if the license is MULTI_CONTENT_LICENSE or GROUP_LICENSE; and // empty if the license is SINGLE_CONTENT_LICENSE_DEFAULT. virtual std::string GetGroupId() const; // If the license is MULTI_CONTENT_LICENSE, the returned vector contains all // content ids that the license is for. Returns empty if the license if not // MULTI_CONTENT_LICENSE. virtual std::vector GetContentIdList() const; // Returns true if the license is MULTI_CONTENT_LICENSE, and false otherwise. virtual bool IsMultiContentLicense() const; // Returns true if the license is GROUP_LICENSE, and false otherwise. virtual bool IsGroupLicense() const; // Policy timer implentation. void OnTimerEvent() override; // Event listener implementation. void OnSessionRenewalNeeded() override; void OnSessionKeysChange(const KeyStatusMap& keys_status, bool has_new_usable_key) override; void OnExpirationUpdate(int64_t new_expiry_time_seconds) override; void OnLicenseExpiration() override; void OnNewRenewalServerUrl(const std::string& renewal_server_url) override; void OnAgeRestrictionUpdated(const WvCasSessionId& sessionId, uint8_t ecm_age_restriction) override; void OnFingerprintingUpdated(const CasData& fingerprinting) override; void OnServiceBlockingUpdated(const CasData& service_blocking) override; void OnSessionFingerprintingUpdated(const WvCasSessionId& sessionId, const CasData& fingerprinting) override; void OnSessionServiceBlockingUpdated( const WvCasSessionId& sessionId, const CasData& service_blocking) override; void OnEntitlementPeriodUpdateNeeded( const std::string& signed_license_request) override; // Query to see if the license is expired. virtual bool IsExpired() const; // Notify the license that playback decryption has begun. virtual void BeginDecryption(); // Returns NoError if a valid entitlement period index exists in // |license_file|. The index will be assigned to |entitlement_period_index|. static CasStatus GetEntitlementPeriodIndexFromStoredLicense( const std::string& license_file, uint32_t& entitlement_period_index); CasLicense(const CasLicense&) = delete; CasLicense& operator=(const CasLicense&) = delete; private: CasStatus GenerateDeviceProvisioningRequestWithKeybox( std::string* provisioning_request) const; CasStatus GetProvisioning40RequestInternal( wvutil::FileSystem& file_system, std::string* serialized_provisioning_request); CasStatus FillEncryptedClientId( const std::string& client_token, video_widevine::ProvisioningRequest& provisioning_request, const ServiceCertificate& service_certificate) const; void FillClientProperties( video_widevine::ClientIdentification& client_id) const; CasStatus HandleProvisioning40Response( wvutil::FileSystem* file_system, const video_widevine::SignedProvisioningMessage& signed_response, std::string* cert, CryptoWrappedKey* wrapped_key) const; CasStatus GenerateDeviceProvisioningRequestWithOEMCert() const; CasStatus InstallLicense(const std::string& session_key, const std::string& serialized_license, const std::string& core_message, const std::string& signature); CasStatus InstallLicenseRenewal(const std::string& serialized_license, const std::string& core_message, const std::string& signature); virtual std::unique_ptr GetPolicyEngine(); std::unique_ptr policy_engine_; std::shared_ptr crypto_session_; CasEventListener* event_listener_ = nullptr; video_widevine::License license_; std::string emm_request_; std::string emm_response_; std::string renewal_request_; std::string renewal_response_; std::string init_data_; bool is_renewal_in_license_file_ = false; std::unique_ptr wv_service_cert_; // The wrapped private key in provisioning 4 generated by calling // GenerateCertificateKeyPair. It will be saved to file system if a valid // response is received. std::string provisioning_40_wrapped_private_key_; // Key type of the generated key pair in provisioning 4. CryptoWrappedKey::Type provisioning_40_key_type_; }; } // namespace wvcas #endif // CAS_LICENSE_H