Files
media_cas_client/plugin/include/widevine_cas_api.h
Lu Chen 5f209e6980 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.
2024-02-22 13:45:32 -08:00

211 lines
9.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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_API_H
#define WIDEVINE_CAS_API_H
#include <memory>
#include <mutex>
#include <set>
#include "cas_license.h"
#include "cas_media_id.h"
#include "cas_status.h"
#include "cas_types.h"
#include "crypto_session.h"
#include "ecm_parser.h"
#include "emm_parser.h"
#include "file_store.h"
#include "media_cas.pb.h"
#include "timer.h"
#include "widevine_cas_session.h"
namespace wvcas {
// TODO(jfore): Fix the function name inconsistency in this class. These
// functions were migrated from the android plugin api implementation. They
// should not follow Android's style.
class WidevineCas : public wvutil::TimerHandler {
public:
WidevineCas() {}
virtual ~WidevineCas() {}
virtual CasStatus initialize(CasEventListener* event_listener);
// Open a session for descrambling a program, or one or more elementary
// streams.
virtual CasStatus openSession(WvCasSessionId* sessionId);
// Close a previously opened session.
virtual CasStatus closeSession(const WvCasSessionId& sessionId);
// Process an EMM which may contain fingerprinting and service blocking info.
virtual CasStatus processEmm(const CasEmm& emm);
// Process an ECM from the ECM stream for this sessions elementary
// stream.
virtual CasStatus processEcm(const WvCasSessionId& sessionId,
const CasEcm& ecm);
// Generates a device provisioning request message in |provisioning_request|.
virtual CasStatus generateDeviceProvisioningRequest(
std::string* provisioning_request);
// Processes a |response| to provisioning request.
virtual CasStatus handleProvisioningResponse(const std::string& response);
// Generates an entitlement license request in |entitlement_request| for the
// media described in |init_data|.
virtual CasStatus generateEntitlementRequest(const std::string& init_data,
std::string* entitlement_request,
std::string& license_id);
// Processes the entitlement |response| to a entitlement license request.
// |license_id| is the id of the license installed. Can be used to select
// which license to install.
// |multi_content_license_info| contains the message that can be sent to the
// app if the installed license is a multi content license.
// |group_license_info| contains the message that can be sent to the app if
// the installed license is a group license.
virtual CasStatus handleEntitlementResponse(
const std::string& response, std::string& license_id,
std::string& multi_content_license_info, std::string& group_license_info);
// Generates an entitlement license request in |entitlement_request| for the
// media described in |init_data|.
virtual CasStatus generateEntitlementRenewalRequest(
std::string* entitlement_renewal_request);
// Processes the entitlement renewal |response| to a entitlement license
// request.
virtual CasStatus handleEntitlementRenewalResponse(
const std::string& response, std::string& license_id);
// Generates an entitlement license request in a new crypto session, and send
// the license request as an event to the app.
virtual CasStatus generateEntitlementPeriodUpdateRequest(
const std::string& init_data);
// Processes the license |response| to switch the current license to this
// new one.
virtual CasStatus handleEntitlementPeriodUpdateResponse(
const std::string& response, std::string& license_id);
// Returns true if the device has been provisioned with a device certificate.
virtual bool is_provisioned() const;
// Processes the CAS |private_data| from a CAT table. If successful a
// serialized pssh data is retured in |init_data|.
virtual CasStatus ProcessCAPrivateData(const CasData& private_data,
std::string* init_data);
// Processes the CAS |private_data| from a PMT table. If successful a
// serialized pssh data is retured in |init_data|. The CA private data can be
// unique to the ecm session indicated by |session_id|.
virtual CasStatus ProcessSessionCAPrivateData(
const WvCasSessionId& session_id, const CasData& private_data,
std::string* init_data);
// Returns the device unique identifier.
virtual CasStatus GetUniqueID(std::string* buffer);
// Set the minimum age required to process ECM.
virtual CasStatus HandleSetParentalControlAge(const CasData& data);
// Remove the license file given the filename user provides.
virtual CasStatus RemoveLicense(const std::string& file_name);
// Record the license id that user provides. This license id will be used to
// select license if multiple licenses exist.
virtual CasStatus RecordLicenseId(const std::string& license_id);
void OnTimerEvent() override;
// Stops the timer thread. Called by CAS plugin destructor to avoid race.
void StopTimer();
private:
virtual CasStatus HandleStoredDrmCert(const std::string& certificate);
virtual CasStatus HandleProcessEcm(const WvCasSessionId& sessionId,
const CasEcm& ecm);
virtual CasStatus HandleDeferredECMs();
// Extracts the entitlement rotation period index from ECM if specified, and
// store it. The function should be called before any license request and the
// extracted index will be included in the license request.
virtual void TryExtractEntitlementPeriodIndex(const CasEcm& ecm);
// Returns true if an offline license with |filename| is successfully loaded.
virtual bool TryReuseStoredLicense(const std::string& filename);
// Check if a new license is needed due to entitlement period changes. If so,
// it will call generateEntitlementPeriodUpdateRequest().
void CheckEntitlementPeriodUpdate(uint32_t period_index,
uint32_t window_left);
virtual std::shared_ptr<CryptoSession> getCryptoSession();
virtual std::unique_ptr<CasLicense> getCasLicense();
virtual std::unique_ptr<wvutil::FileSystem> getFileSystem();
virtual std::shared_ptr<WidevineCasSession> newCasSession();
virtual std::unique_ptr<EcmParser> getEcmParser(const CasEcm& ecm) const;
// Creates an EmmParser. Marked as virtual for easier unit test.
virtual std::unique_ptr<const EmmParser> getEmmParser(
const CasEmm& emm) const;
std::vector<uint8_t> GenerateFingerprintingEventMessage(
const video_widevine::Fingerprinting& fingerprinting) const;
std::vector<uint8_t> GenerateServiceBlockingEventMessage(
const video_widevine::ServiceBlocking& service_blocking) const;
// The CryptoSession will be shared by the all cas sessions. It is also needed
// by the cas api to generate EMM requests.
std::shared_ptr<CryptoSession> crypto_session_;
std::unique_ptr<CasLicense> cas_license_;
std::unique_ptr<wvutil::FileSystem> file_system_;
std::string device_certificate_;
std::string wrapped_rsa_key_;
CasEventListener* event_listener_ = nullptr;
std::mutex lock_;
wvutil::Timer policy_timer_;
LicenseType license_type_;
std::unique_ptr<CasMediaId> media_id_;
// Sometimes delays in receiving a license or the format in which the content
// is encoded my result in ecms being processed before a valid license has
// been loaded. In this cas |has_license_| will be false and the ecm will be
// stored in |deferred_ecms_|. Once a license has been loaded, the stored ecms
// are processed to set the current content keys.
std::map<WvCasSessionId, const CasEcm> deferred_ecms_;
// The value |has_license_| will be false when the plugin is created. Once a
// license is loaded, |has_license_| will be set to true.
bool has_license_ = false;
// The age_restriction field in ECM must be greater or equal to
// |parental_control_min_age|. Otherwise, ECM will stop being processed.
uint parental_control_age_ = 0;
// The requested_license_id helps to indicate which license file current
// content will use if multiple licenses exist.
std::string requested_license_id_;
// The current in use license_id.
std::string license_id_;
// The group id of a Group license. Empty if the license is not a Group
// license (multi content license is not a group license). Used in processECM
// to select group keys that can be decrypted by the license.
std::string license_group_id_;
// Fingerprinting events sent in processing last ECM/EMM. Used to avoid
// sending a same event again.
std::set<CasData> last_fingerprinting_events_;
// Service blocking events sent in processing last ECM/EMM. Used to avoid
// sending a same event again.
std::set<CasData> last_service_blocking_events_;
// Indicates if |entitlement_period_index_| below is valid or not.
bool is_entitlement_rotation_enabled_ = false;
// The entitlement period index in the last received ECM.
uint32_t entitlement_period_index_;
// |next_*| used to handle entitlement key rotation. They will be moved to
// normal ones once the license switch completed.
std::shared_ptr<CryptoSession> next_crypto_session_;
std::unique_ptr<CasLicense> next_cas_license_;
std::unique_ptr<CasMediaId> next_media_id_;
}; // namespace wvcas
} // namespace wvcas
#endif // WIDEVINE_CAS_API_H