Files
ce_cdm/core/include/cdm_session.h
Googler 6d36a0c93d Source release 19.6.0
GitOrigin-RevId: 13a33e34413c19da1bfe76abcc66be519c9ac9d1
2025-06-09 23:44:53 -07:00

354 lines
14 KiB
C++

// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_CORE_CDM_SESSION_H_
#define WVCDM_CORE_CDM_SESSION_H_
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "crypto_session.h"
#include "device_files.h"
#include "file_store.h"
#include "initialization_data.h"
#include "license.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "policy_engine.h"
#include "timer_metric.h"
#include "wv_cdm_types.h"
#include "wv_class_utils.h"
namespace wvcdm {
class CdmClientPropertySet;
class ServiceCertificate;
class WvCdmEventListener;
class CdmUsageTable;
class SystemIdExtractor;
class CdmSession {
public:
CdmSession() = delete;
WVCDM_DISALLOW_COPY_AND_MOVE(CdmSession);
// Creates a new instance of the CdmSession with the given |file_system|
// and |metrics| parameters. Both parameters are owned by the caller and
// must remain in scope throughout the scope of the new instance. |metrics|
// must not be null.
CdmSession(wvutil::FileSystem* file_system,
std::shared_ptr<metrics::SessionMetrics> metrics);
virtual ~CdmSession();
void Close() { closed_ = true; }
bool IsClosed() { return closed_; }
// Initializes this instance of CdmSession with the given property set.
//
// |cdm_client_property_set| is caller owned, may be null, but must be in
// scope as long as the session is in scope. The service certificate field is
// cached at the time Init() is called.
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set);
// Initializes this instance of CdmSession with the given parameters.
// All parameters are owned by the caller.
//
// |cdm_client_property_set| is caller owned, may be null, but must be in
// scope as long as the session is in scope. The service certificate field is
// cached at the time Init() is called.
//
// |forced_session_id| is caller owned and may be null.
//
// |event_listener| is caller owned, may be null, but must be in scope as long
// as the session is in scope.
//
// |forced_level3|_is used to specify whether the "default" security level
// should always use L3 even if L1 is available.
virtual CdmResponseType Init(CdmClientPropertySet* cdm_client_property_set,
const CdmSessionId* forced_session_id,
WvCdmEventListener* event_listener,
bool forced_level3);
// Restores an offline session identified by the |key_set_id| and
// |license_type|. The |error_detail| will be filled with an internal error
// code. The |error_detail| may be a CdmResponseType or other error code type.
// It is only suitable for additional logging or debugging.
virtual CdmResponseType RestoreOfflineSession(const CdmKeySetId& key_set_id,
CdmLicenseType license_type,
int* error_detail);
// Restores an usage session from the provided |usage_data|.
// The |error_detail| will be filled with an internal error code. The
// |error_detail| may be a CdmResponseType or other error code type. It is
// only suitable for additional logging or debugging.
virtual CdmResponseType RestoreUsageSession(
const DeviceFiles::CdmUsageData& usage_data, int* error_detail);
virtual const CdmSessionId& session_id() { return session_id_; }
virtual const CdmKeySetId& key_set_id() { return key_set_id_; }
virtual CdmResponseType GenerateKeyRequest(
const InitializationData& init_data, CdmLicenseType license_type,
const CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request);
// AddKey() - Accept license response and extract key info.
virtual CdmResponseType AddKey(const CdmKeyResponse& key_response);
// Override the currently-installed service certificate with a new service
// certificate.
virtual CdmResponseType SetServiceCertificate(
const std::string& service_certificate);
// Query session status
virtual CdmResponseType QueryStatus(CdmQueryMap* query_response);
// Query license information
virtual CdmResponseType QueryKeyStatus(CdmQueryMap* query_response);
// Query allowed usages for key
virtual CdmResponseType QueryKeyAllowedUsage(const std::string& key_id,
CdmKeyAllowedUsage* key_usage);
// Query OEMCrypto session ID
virtual CdmResponseType QueryOemCryptoSessionId(CdmQueryMap* query_response);
// Decrypt() - Accept encrypted buffer and return decrypted data.
virtual CdmResponseType Decrypt(const CdmDecryptionParametersV16& parameters);
// License renewal
// GenerateRenewalRequest() - Construct valid renewal request for the current
// session keys.
virtual CdmResponseType GenerateRenewalRequest(CdmKeyRequest* key_request);
// RenewKey() - Accept renewal response and update key info.
virtual CdmResponseType RenewKey(const CdmKeyResponse& key_response);
// License release
// GenerateReleaseRequest() - Construct valid release request for the current
// session keys.
virtual CdmResponseType GenerateReleaseRequest(CdmKeyRequest* key_request);
// ReleaseKey() - Accept response and release key.
virtual CdmResponseType ReleaseKey(const CdmKeyResponse& key_response);
virtual CdmResponseType DeleteUsageEntry(UsageEntryIndex entry_index);
virtual bool IsKeyLoaded(const KeyId& key_id);
virtual int64_t GetDurationRemaining();
// Used for notifying the Policy Engine of resolution changes
virtual void NotifyResolution(uint32_t width, uint32_t height);
virtual void OnTimerEvent(bool update_usage);
virtual void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
virtual void GetApplicationId(std::string* app_id);
virtual RequestedSecurityLevel GetRequestedSecurityLevel() {
return requested_security_level_;
}
virtual CdmSecurityLevel GetSecurityLevel() { return security_level_; }
virtual CdmResponseType UpdateUsageEntryInformation();
virtual bool is_initial_usage_update() { return is_initial_usage_update_; }
virtual bool is_usage_update_needed() { return is_usage_update_needed_; }
virtual void reset_usage_flags() {
is_initial_usage_update_ = false;
is_usage_update_needed_ = false;
}
virtual bool is_release() { return is_release_; }
virtual bool is_offline() { return is_offline_; }
virtual bool is_temporary() { return is_temporary_; }
virtual bool license_received() { return license_received_; }
virtual bool has_provider_session_token() {
return (license_parser_ &&
license_parser_->provider_session_token().size() > 0);
}
virtual bool SupportsUsageTable() const { return usage_table_ != nullptr; }
// This method will remove keys by resetting crypto resources and
// policy information. This renders the session mostly useless and it is
// preferable to simply delete this object rather than call this method.
virtual CdmResponseType RemoveKeys();
// Remove the current offline license and/or matching usage record, if any
// exist.
CdmResponseType RemoveLicense();
// Delete this session's associated license or usage record file. Note that,
// unlike RemoveLicense(), this method ONLY affects the file system and does
// not touch the usage table headers.
bool DeleteLicenseFile();
// Generate unique ID for each new session.
CdmSessionId GenerateSessionId();
// Generic crypto operations - provides basic crypto operations that an
// application can use outside of content stream processing
// Encrypts a buffer of app-level data.
virtual CdmResponseType GenericEncrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer);
// Decrypts a buffer of app-level data.
virtual CdmResponseType GenericDecrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer);
// Computes the signature for a message.
virtual CdmResponseType GenericSign(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
std::string* signature);
// Verifies the signature on a buffer of app-level data.
virtual CdmResponseType GenericVerify(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
const std::string& signature);
virtual CdmResponseType SetDecryptHash(uint32_t frame_number,
const std::string& hash);
virtual CdmResponseType GetDecryptHashError(std::string* hash_error_string);
virtual metrics::SessionMetrics* GetMetrics() { return metrics_.get(); }
virtual CdmResponseType LoadCastPrivateKey(
const CryptoWrappedKey& private_key);
virtual CdmResponseType GenerateRsaSignature(const std::string& message,
std::string* signature,
RSA_Padding_Scheme scheme);
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 method 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 std::string& certificate,
const CryptoWrappedKey& wrapped_private_key);
bool GenerateKeySetId(bool atsc_mode_enabled, CdmKeySetId* key_set_id);
CdmResponseType StoreLicense();
bool StoreLicense(CdmOfflineLicenseState state, int* error_detail);
bool UpdateUsageInfo();
CdmResponseType GenerateKeyRequestInternal(
const InitializationData& init_data, CdmLicenseType license_type,
const CdmAppParameterMap& app_parameters, CdmKeyRequest* key_request);
virtual CdmResponseType AddKeyInternal(const CdmKeyResponse& key_response);
void UpdateRequestLatencyTiming(CdmResponseType sts);
// Checks that the usage entry in the usage table header matches the
// information of the currently loaded license for this session.
// Returns false if there is any unexpected mismatch of information,
// true otherwise.
bool VerifyOfflineUsageEntry();
bool HasRootOfTrustBeenRenewed(bool is_load);
CdmResponseType ResetCryptoSession();
// These setters are for testing only. Takes ownership of the pointers.
void set_license_parser(CdmLicense* license_parser);
void set_crypto_session(CryptoSession* crypto_session);
void set_policy_engine(PolicyEngine* policy_engine);
void set_file_handle(DeviceFiles* file_handle);
void set_system_id_extractor(SystemIdExtractor* extractor);
// instance variables
std::shared_ptr<metrics::SessionMetrics> metrics_;
metrics::CryptoMetrics* crypto_metrics_;
metrics::Timer life_span_;
metrics::Timer license_request_latency_;
CdmKeyRequestType key_request_type_;
bool initialized_;
bool closed_; // Session closed, but final shared_ptr has not been released.
CdmSessionId session_id_;
wvutil::FileSystem* file_system_;
std::unique_ptr<CdmLicense> license_parser_;
std::unique_ptr<CryptoSession> crypto_session_;
std::unique_ptr<PolicyEngine> policy_engine_;
std::unique_ptr<DeviceFiles> file_handle_;
std::unique_ptr<SystemIdExtractor> mock_system_id_extractor_;
bool license_received_;
bool is_offline_;
bool is_release_;
bool is_temporary_;
CdmSecurityLevel security_level_;
RequestedSecurityLevel requested_security_level_;
// If |forced_level3_|, |security_level_| and |requested_security_level_|
// MUST be set to kSecurityLevelL3 and kLevel3, respectively.
bool forced_level3_ = false;
CdmAppParameterMap app_parameters_;
bool atsc_mode_enabled_ = false;
std::string drm_certificate_;
CryptoWrappedKey wrapped_private_key_;
// Decryption flags.
// Indiates that the next call to Decrypt will be the first for this
// license.
bool is_initial_decryption_ = true;
// Set to true if a successful call to Decrypt has occurred. Cleared
// when the policy engine has been notified about successful
// decryption.
bool has_decrypted_since_last_report_ = false;
// Set to true if the last call to Decrypt resulted in a failure.
// Cleared when the call to decrypt has succeeded.
bool last_decrypt_failed_ = false;
// Usage related flags and data
bool is_initial_usage_update_;
bool is_usage_update_needed_;
// Only assign |usage_table_| if capable of supporting usage
// information.
CdmUsageTable* usage_table_ = nullptr;
UsageEntryIndex usage_entry_index_ = 0;
UsageEntry usage_entry_;
std::string usage_provider_session_token_;
std::string exported_license_data_;
// information useful for offline and usage scenarios
CdmKeyMessage key_request_;
CdmKeyResponse key_response_;
// license type offline related information
CdmInitData offline_init_data_;
CdmKeyMessage offline_key_renewal_request_;
CdmKeyResponse offline_key_renewal_response_;
std::string offline_release_server_url_;
// license type release and offline related information
CdmKeySetId key_set_id_;
bool has_license_been_loaded_ = false;
bool has_license_been_restored_ = false;
bool mock_crypto_session_in_use_ = false;
bool mock_license_parser_in_use_ = false;
bool mock_policy_engine_in_use_ = false;
}; // class CdmSession
} // namespace wvcdm
#endif // WVCDM_CORE_CDM_SESSION_H_