[ Merge of http://go/wvgerrit/181152 ]
[ Cherry-pick of http://ag/24137228 ]
Partners have requested that we log HDCP information during certain
operation:
1) Current and max HDCP capability when calls to decrypt or select
key failure due to insufficient or mixed HDCP levels.
2) Current, desired and default HDCP level when video contraints
are not met.
To avoid spamming the logs, decrypt failures are only logged on their
first occurrence, and unmet video constrains when one of the
requirements change.
Bug: 276686656
Bug: 292005982
Test: license_keys_unittest
Test: Android WVTS on oriole
Change-Id: I98b18e66d7ce1c474a018ae83af4f1c0b03308df
(cherry picked from commit c84b9afd38)
582 lines
25 KiB
C++
582 lines
25 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_CRYPTO_SESSION_H_
|
|
#define WVCDM_CORE_CRYPTO_SESSION_H_
|
|
|
|
#include <atomic>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "OEMCryptoCENC.h"
|
|
#include "crypto_wrapped_key.h"
|
|
#include "disallow_copy_and_assign.h"
|
|
#include "key_session.h"
|
|
#include "metrics_collections.h"
|
|
#include "oemcrypto_adapter.h"
|
|
#include "rw_lock.h"
|
|
#include "timer_metric.h"
|
|
#include "wv_cdm_types.h"
|
|
|
|
namespace wvcdm {
|
|
class CryptoKey;
|
|
class CryptoSessionFactory;
|
|
class OtaKeyboxProvisioner;
|
|
class CdmUsageTable;
|
|
|
|
namespace okp {
|
|
class SystemFallbackPolicy;
|
|
} // namespace okp
|
|
|
|
using CryptoKeyMap = std::map<std::string, CryptoKey*>;
|
|
|
|
// Crypto session utility functions used by KeySession implementations.
|
|
void GenerateMacContext(const std::string& input_context,
|
|
std::string* deriv_context);
|
|
void GenerateEncryptContext(const std::string& input_context,
|
|
std::string* deriv_context);
|
|
size_t GetOffset(std::string message, std::string field);
|
|
OEMCrypto_Substring GetSubstring(const std::string& message = "",
|
|
const std::string& field = "",
|
|
bool set_zero = false);
|
|
OEMCryptoCipherMode ToOEMCryptoCipherMode(CdmCipherMode cipher_mode);
|
|
|
|
class CryptoSession {
|
|
public:
|
|
using HdcpCapability = OEMCrypto_HDCP_Capability;
|
|
enum UsageDurationStatus {
|
|
kUsageDurationsInvalid = 0,
|
|
kUsageDurationPlaybackNotBegun = 1,
|
|
kUsageDurationsValid = 2,
|
|
};
|
|
|
|
struct SupportedCertificateTypes {
|
|
bool rsa_2048_bit;
|
|
bool rsa_3072_bit;
|
|
bool rsa_cast;
|
|
bool ecc_secp256r1;
|
|
bool ecc_secp384r1;
|
|
bool ecc_secp521r1;
|
|
};
|
|
|
|
// Creates an instance of CryptoSession with the given |crypto_metrics|.
|
|
// |crypto_metrics| is owned by the caller, must NOT be null, and must
|
|
// exist as long as the new CryptoSession exists.
|
|
static CryptoSession* MakeCryptoSession(
|
|
metrics::CryptoMetrics* crypto_metrics);
|
|
|
|
static const char* HdcpCapabilityToString(HdcpCapability hdcp_level);
|
|
|
|
virtual ~CryptoSession();
|
|
|
|
// This method will try to terminate OEMCrypto if |session_size_| is 0.
|
|
// A platform configured property |delay_oem_crypto_termination| will
|
|
// determine if termination occurs immediately or after a delay.
|
|
// If termination is delayed, a countdown mechanism is employed.
|
|
// Call |TryTerminate| periodically until it no longer returns true.
|
|
// To immediately terminate call |DisableDelayedTermination| before calling
|
|
// |TryTerminate|.
|
|
static bool TryTerminate();
|
|
|
|
static void DisableDelayedTermination();
|
|
|
|
virtual CdmResponseType GetProvisioningToken(
|
|
RequestedSecurityLevel requested_security_level, std::string* token,
|
|
std::string* additional_token);
|
|
// Must be called after session is open.
|
|
virtual CdmResponseType GetProvisioningToken(std::string* token,
|
|
std::string* additional_token);
|
|
|
|
virtual CdmClientTokenType GetPreProvisionTokenType() {
|
|
return pre_provision_token_type_;
|
|
}
|
|
|
|
// Retrieves the key data portion of the OEMCrypto keybox.
|
|
// Only valid for keybox-based based devices.
|
|
// May return NEED_PROVISIONING if the device is keybox-based, but
|
|
// OTA keybox provisioning is required.
|
|
virtual CdmResponseType GetTokenFromKeybox(
|
|
RequestedSecurityLevel requested_security_level, std::string* key_data);
|
|
// Retrieves the public OEM certificate chain from OEMCrypto.
|
|
// Only valid for OEM certificate-based based devices.
|
|
virtual CdmResponseType GetTokenFromOemCert(
|
|
RequestedSecurityLevel requested_security_level, std::string* oem_cert);
|
|
|
|
// The overloaded methods with |requested_level| may be called
|
|
// without a preceding call to Open. The other method must call Open first.
|
|
virtual CdmSecurityLevel GetSecurityLevel();
|
|
virtual CdmSecurityLevel GetSecurityLevel(
|
|
RequestedSecurityLevel requested_level);
|
|
virtual bool GetApiVersion(uint32_t* version);
|
|
virtual bool GetApiVersion(RequestedSecurityLevel requested_level,
|
|
uint32_t* version);
|
|
virtual bool GetApiMinorVersion(RequestedSecurityLevel requested_level,
|
|
uint32_t* minor_version);
|
|
|
|
// This method will return, for devices with a
|
|
// * keybox: the 32 byte device ID from the keybox.
|
|
// * OEM certificate:
|
|
// - that implements |OEMCrypto_GetDeviceID|: the (1 to 64 byte) device ID.
|
|
// - that does not implement |OEMCrypto_GetDeviceID|: the OEM public
|
|
// certificate.
|
|
virtual CdmResponseType GetInternalDeviceUniqueId(std::string* device_id);
|
|
|
|
// This method will return, for devices with a
|
|
// * keybox: the 32 byte device ID from the keybox.
|
|
// * OEM certificate:
|
|
// - that implements |OEMCrypto_GetDeviceID|: the (1 to 64 byte) device ID.
|
|
// - that does not implement |OEMCrypto_GetDeviceID|: the 32 byte hash
|
|
// of the OEM public certificate.
|
|
virtual CdmResponseType GetExternalDeviceUniqueId(std::string* device_id);
|
|
virtual CdmResponseType GetProvisioningId(std::string* provisioning_id);
|
|
virtual uint8_t GetSecurityPatchLevel();
|
|
|
|
virtual bool GetCachedSystemId(uint32_t* system_id);
|
|
// With provisioning 4.0, the system ID cannot reliably be found within
|
|
// OEMCrypto. The system ID can be assigned to the CryptoSession instance
|
|
// after the ID has been determined.
|
|
virtual void SetSystemId(uint32_t system_id);
|
|
|
|
virtual CdmResponseType Open() { return Open(kLevelDefault); }
|
|
virtual CdmResponseType Open(RequestedSecurityLevel requested_security_level);
|
|
virtual void Close();
|
|
|
|
virtual bool IsOpen() { return open_; }
|
|
virtual CryptoSessionId oec_session_id() { return oec_session_id_; }
|
|
|
|
// All request/responses
|
|
virtual const std::string& request_id() { return request_id_; }
|
|
virtual CdmResponseType GenerateNonce(uint32_t* nonce);
|
|
|
|
// License request/responses
|
|
virtual CdmResponseType PrepareAndSignLicenseRequest(
|
|
const std::string& message, std::string* core_message,
|
|
std::string* signature, bool& should_specify_algorithm,
|
|
OEMCrypto_SignatureHashAlgorithm& algorithm);
|
|
virtual CdmResponseType UseSecondaryKey(bool dual_key);
|
|
// V16 licenses.
|
|
virtual CdmResponseType LoadLicense(const std::string& signed_message,
|
|
const std::string& core_message,
|
|
const std::string& signature,
|
|
CdmLicenseKeyType key_type);
|
|
|
|
// Renewal request/responses
|
|
virtual CdmResponseType PrepareAndSignRenewalRequest(
|
|
const std::string& message, std::string* core_message,
|
|
std::string* signature);
|
|
// V16 licenses.
|
|
virtual CdmResponseType LoadRenewal(const std::string& signed_message,
|
|
const std::string& core_message,
|
|
const std::string& signature);
|
|
|
|
// Entitled content Keys.
|
|
virtual CdmResponseType LoadEntitledContentKeys(
|
|
const std::vector<CryptoKey>& key_array);
|
|
|
|
// Provisioning request/responses
|
|
virtual CdmResponseType GenerateDerivedKeys(const std::string& message);
|
|
virtual CdmResponseType GenerateDerivedKeys(const std::string& message,
|
|
const std::string& session_key);
|
|
virtual CdmResponseType PrepareAndSignProvisioningRequest(
|
|
const std::string& message, std::string* core_message,
|
|
std::string* signature, bool& should_specify_algorithm,
|
|
OEMCrypto_SignatureHashAlgorithm& algorithm);
|
|
virtual CdmResponseType LoadProvisioning(const std::string& signed_message,
|
|
const std::string& core_message,
|
|
const std::string& signature,
|
|
std::string* wrapped_private_key);
|
|
virtual CdmResponseType LoadCertificatePrivateKey(
|
|
const CryptoWrappedKey& private_key);
|
|
virtual CdmResponseType GetBootCertificateChain(
|
|
RequestedSecurityLevel requested_security_level, std::string* bcc,
|
|
std::string* additional_signature);
|
|
virtual CdmResponseType GetBootCertificateChain(
|
|
std::string* bcc, std::string* additional_signature);
|
|
virtual CdmResponseType GenerateCertificateKeyPair(
|
|
std::string* public_key, std::string* public_key_signature,
|
|
std::string* wrapped_private_key, CryptoWrappedKey::Type* key_type);
|
|
virtual CdmResponseType LoadOemCertificatePrivateKey(
|
|
const CryptoWrappedKey& private_key);
|
|
|
|
// Media data path
|
|
virtual CdmResponseType Decrypt(const CdmDecryptionParametersV16& params);
|
|
|
|
virtual bool IsAntiRollbackHwPresent();
|
|
|
|
// The overloaded methods with |security_level| may be called without a
|
|
// preceding call to Open. The other methods must call Open first.
|
|
virtual CdmResponseType GetHdcpCapabilities(HdcpCapability* current,
|
|
HdcpCapability* max);
|
|
virtual CdmResponseType GetHdcpCapabilities(
|
|
RequestedSecurityLevel security_level, HdcpCapability* current,
|
|
HdcpCapability* max);
|
|
virtual bool GetResourceRatingTier(uint32_t* tier);
|
|
virtual bool GetResourceRatingTier(RequestedSecurityLevel security_level,
|
|
uint32_t* tier);
|
|
|
|
virtual bool GetSupportedCertificateTypes(SupportedCertificateTypes* support);
|
|
virtual CdmResponseType GetNumberOfOpenSessions(
|
|
RequestedSecurityLevel security_level, size_t* count);
|
|
virtual CdmResponseType GetMaxNumberOfSessions(
|
|
RequestedSecurityLevel security_level, size_t* max);
|
|
|
|
virtual CdmResponseType GetSrmVersion(uint16_t* srm_version);
|
|
|
|
virtual bool GetBuildInformation(RequestedSecurityLevel security_level,
|
|
std::string* info);
|
|
virtual bool GetBuildInformation(std::string* info);
|
|
|
|
virtual bool GetWatermarkingSupport(CdmWatermarkingSupport* support);
|
|
virtual bool GetWatermarkingSupport(
|
|
RequestedSecurityLevel requested_security_level,
|
|
CdmWatermarkingSupport* support);
|
|
|
|
virtual bool GetProductionReadiness(CdmProductionReadiness* readiness);
|
|
virtual bool GetProductionReadiness(
|
|
RequestedSecurityLevel requested_security_level,
|
|
CdmProductionReadiness* readiness);
|
|
|
|
virtual bool GetMaximumUsageTableEntries(
|
|
RequestedSecurityLevel security_level, size_t* number_of_entries);
|
|
|
|
virtual bool GetDecryptHashSupport(RequestedSecurityLevel security_level,
|
|
uint32_t* hash_support);
|
|
|
|
virtual CdmResponseType SetDecryptHash(uint32_t frame_number,
|
|
const std::string& hash);
|
|
|
|
virtual CdmResponseType GetDecryptHashError(std::string* error_string);
|
|
|
|
virtual CdmResponseType GenericEncrypt(const std::string& in_buffer,
|
|
const std::string& key_id,
|
|
const std::string& iv,
|
|
CdmEncryptionAlgorithm algorithm,
|
|
std::string* out_buffer);
|
|
virtual CdmResponseType GenericDecrypt(const std::string& in_buffer,
|
|
const std::string& key_id,
|
|
const std::string& iv,
|
|
CdmEncryptionAlgorithm algorithm,
|
|
std::string* out_buffer);
|
|
virtual CdmResponseType GenericSign(const std::string& message,
|
|
const std::string& key_id,
|
|
CdmSigningAlgorithm algorithm,
|
|
std::string* signature);
|
|
virtual CdmResponseType GenericVerify(const std::string& message,
|
|
const std::string& key_id,
|
|
CdmSigningAlgorithm algorithm,
|
|
const std::string& signature);
|
|
|
|
// Usage table API related methods.
|
|
// Used to manipulate the CDM managed usage table header & entries,
|
|
// delegating calls to OEMCrypto.
|
|
|
|
// Determines whether the OEMCrypto library supports usage table.
|
|
// As of V16, the only valid type of support is usage table header +
|
|
// usage entries.
|
|
// The first method will use a cached value if present.
|
|
virtual bool HasUsageTableSupport(bool* has_support);
|
|
virtual bool HasUsageTableSupport(RequestedSecurityLevel security_level,
|
|
bool* has_support);
|
|
|
|
// Usage report.
|
|
virtual CdmResponseType DeactivateUsageInformation(
|
|
const std::string& provider_session_token);
|
|
virtual CdmResponseType GenerateUsageReport(
|
|
const std::string& provider_session_token, std::string* usage_report,
|
|
UsageDurationStatus* usage_duration_status,
|
|
int64_t* seconds_since_started, int64_t* seconds_since_last_played);
|
|
|
|
// Usage table header.
|
|
virtual CdmUsageTable* GetUsageTable() { return usage_table_; }
|
|
// The following crypto methods do not require an open session to
|
|
// complete the operations.
|
|
virtual CdmResponseType CreateUsageTableHeader(
|
|
RequestedSecurityLevel requested_security_level,
|
|
UsageTableHeader* usage_table_header);
|
|
virtual CdmResponseType LoadUsageTableHeader(
|
|
RequestedSecurityLevel requested_security_level,
|
|
const UsageTableHeader& usage_table_header);
|
|
virtual CdmResponseType ShrinkUsageTableHeader(
|
|
RequestedSecurityLevel requested_security_level, uint32_t new_entry_count,
|
|
UsageTableHeader* usage_table_header);
|
|
|
|
// Usage entry.
|
|
virtual CdmResponseType CreateUsageEntry(UsageEntryIndex* entry_index);
|
|
virtual CdmResponseType LoadUsageEntry(UsageEntryIndex entry_index,
|
|
const UsageEntry& usage_entry);
|
|
virtual CdmResponseType UpdateUsageEntry(UsageTableHeader* usage_table_header,
|
|
UsageEntry* usage_entry);
|
|
|
|
// Adjust usage entries in usage table header.
|
|
virtual CdmResponseType MoveUsageEntry(UsageEntryIndex new_entry_index);
|
|
|
|
virtual bool GetAnalogOutputCapabilities(bool* can_support_output,
|
|
bool* can_disable_output,
|
|
bool* can_support_cgms_a);
|
|
virtual metrics::CryptoMetrics* GetCryptoMetrics() { return metrics_; }
|
|
|
|
virtual CdmResponseType GetProvisioningMethod(
|
|
RequestedSecurityLevel requested_security_level,
|
|
CdmClientTokenType* token_type);
|
|
|
|
// OTA Provisioning
|
|
|
|
static bool needs_keybox_provisioning() { return needs_keybox_provisioning_; }
|
|
|
|
// This tells the OEMCrypto adapter to ignore the next |count| keyboxes and
|
|
// report that it needs provisioning instead.
|
|
static CdmResponseType SetDebugIgnoreKeyboxCount(uint32_t count);
|
|
|
|
// This tells the OEMCrypto adapter to allow the device to continue with a
|
|
// test keybox. Otherwise, the keybox is reported as invalid.
|
|
static CdmResponseType SetAllowTestKeybox(bool allow);
|
|
|
|
// Returns a system-wide singleton instance of SystemFallbackPolicy
|
|
// to be used for communicating OTA keybox provisioning state between
|
|
// apps. Returns a null pointer if OTA provisioning is not supported,
|
|
// or not required.
|
|
static okp::SystemFallbackPolicy* GetOkpFallbackPolicy();
|
|
|
|
// Generates an OTA provisioning request.
|
|
// This should only be called by an instance of OtaKeyboxProvisioner.
|
|
virtual CdmResponseType PrepareOtaProvisioningRequest(bool use_test_key,
|
|
std::string* request);
|
|
|
|
// Loads an OTA provisioning response.
|
|
// This should only be called by an instance of OtaKeyboxProvisioner.
|
|
virtual CdmResponseType LoadOtaProvisioning(bool use_test_key,
|
|
const std::string& response);
|
|
|
|
protected:
|
|
// Creates an instance of CryptoSession with the given |crypto_metrics|.
|
|
// |crypto_metrics| is owned by the caller, must NOT be null, and must
|
|
// exist as long as the new CryptoSession exists.
|
|
explicit CryptoSession(metrics::CryptoMetrics* crypto_metrics);
|
|
|
|
int session_count() const { return session_count_; }
|
|
// Cache api version and fallback policy. Call this once at initialization.
|
|
void CacheVersion();
|
|
// Re-initialize for running tests with a test keybox.
|
|
void ReinitializeForTest();
|
|
|
|
private:
|
|
friend class CryptoSessionForTest;
|
|
friend class CryptoSessionFactory;
|
|
#if defined(UNIT_TEST)
|
|
friend class CertificateProvisioningTest;
|
|
friend class WvCdmTestBase;
|
|
friend class CdmOtaKeyboxTest;
|
|
#endif
|
|
|
|
// The global factory method can be set to generate special crypto sessions
|
|
// just for testing. These sessions will avoid nonce floods and will ask
|
|
// OEMCrypto to use a test keybox.
|
|
// Ownership of the object is transferred to CryptoSession.
|
|
static void SetCryptoSessionFactory(CryptoSessionFactory* factory) {
|
|
std::unique_lock<std::mutex> auto_lock(factory_mutex_);
|
|
factory_.reset(factory);
|
|
}
|
|
|
|
void Init();
|
|
|
|
// Will set up the CdmUsageTable for this session. This may require
|
|
// creating a new CdmUsageTable if the global instance has not
|
|
// been initialized.
|
|
// Note: This function will lock the global static field lock in write mode.
|
|
bool SetUpUsageTable(RequestedSecurityLevel requested_security_level);
|
|
|
|
CdmResponseType GenerateRsaSignature(const std::string& message,
|
|
std::string* signature);
|
|
size_t GetMaxSubsampleRegionSize();
|
|
|
|
bool SetDestinationBufferType();
|
|
|
|
CdmResponseType SelectKey(const std::string& key_id,
|
|
CdmCipherMode cipher_mode);
|
|
|
|
// Retrieves the OEMCrypto usage table support for the specified
|
|
// |requested_security_level|.
|
|
// Caller should acquire the OEMCrypto read lock before calling.
|
|
bool HasUsageTableSupportInternal(
|
|
RequestedSecurityLevel requested_security_level, bool* has_support);
|
|
|
|
// These methods fall back into each other in the order given, depending on
|
|
// how much data they were given and how much data OEMCrypto can accept in one
|
|
// call.
|
|
OEMCryptoResult DecryptMultipleSamples(
|
|
const std::vector<OEMCrypto_SampleDescription>& samples,
|
|
CdmCipherMode cipher_mode,
|
|
const OEMCrypto_CENCEncryptPatternDesc& pattern);
|
|
OEMCryptoResult DecryptSample(
|
|
const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode,
|
|
const OEMCrypto_CENCEncryptPatternDesc& pattern);
|
|
OEMCryptoResult LegacyDecrypt(
|
|
const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode,
|
|
const OEMCrypto_CENCEncryptPatternDesc& pattern);
|
|
OEMCryptoResult LegacyCopyBufferInChunks(
|
|
const OEMCrypto_SampleDescription& sample, size_t max_chunk_size);
|
|
OEMCryptoResult LegacyDecryptInChunks(
|
|
const OEMCrypto_SampleDescription& sample, CdmCipherMode cipher_mode,
|
|
const OEMCrypto_CENCEncryptPatternDesc& pattern, size_t max_chunk_size);
|
|
|
|
// These methods should be used to take the various CryptoSession mutexes in
|
|
// preference to taking the mutexes directly.
|
|
//
|
|
// A lock should be taken on the Static Field Mutex before accessing
|
|
// any of CryptoSession's non-atomic static fields with the exception
|
|
// of the Usage Table Mutex. The Static Field Mutex can be taken as
|
|
// a reader or as a writer, depending on how you will be accessing
|
|
// the static fields. The Usage Table Mutex should be taken when
|
|
// reading and writing to the static usage table fields (creating,
|
|
// destroying or taking a pointer of the handles). The purpose of
|
|
// having a separate mutex for usage table is due to the recursive
|
|
// nature of initializing the global usage table.
|
|
//
|
|
// Before calling into OEMCrypto, code must take locks on the OEMCrypto Mutex
|
|
// and/or the OEMCrypto Session Mutex. Which of them should be taken and how
|
|
// depends on the OEMCrypto function being called; consult the OEMCrypto
|
|
// specification's threading guarantees before making any calls. The OEMCrypto
|
|
// specification defines several classes of functions for the purposes of
|
|
// parallelism. The methods below lock the OEMCrypto Mutex and OEMCrypto
|
|
// Session Mutex in the correct order and manner to fulfill the guarantees in
|
|
// the specification.
|
|
//
|
|
// For this function class... | ...use this locking method
|
|
// ------------------------------+---------------------------
|
|
// Initialization & Termination | WithOecWriteLock()
|
|
// Property | WithOecReadLock()
|
|
// Session Initialization | WithOecWriteLock()
|
|
// Usage Table Header & Entries | WithOecWriteLock()
|
|
// Session | WithOecSessionLock()
|
|
//
|
|
// Note that accessing |key_session_| often accesses the OEMCrypto session, so
|
|
// WithOecSessionLock() should be used before accessing |key_session_| as
|
|
// well.
|
|
//
|
|
// If a function needs to take a lock on both the Static Field Mutex and some
|
|
// of the OEMCrypto mutexes simultaneously, it must *always* lock the Static
|
|
// Field Mutex before the OEMCrypto mutexes.
|
|
//
|
|
// In general, all locks should only be held for the minimum time necessary
|
|
// (e.g. a lock on the OEMCrypto mutexes should only be held for the duration
|
|
// of a single call into OEMCrypto) unless there is a compelling argument
|
|
// otherwise, such as making two calls into OEMCrypto immediately after each
|
|
// other.
|
|
template <class Func>
|
|
static auto WithStaticFieldWriteLock(const char* tag, Func body)
|
|
-> decltype(body());
|
|
|
|
template <class Func>
|
|
static auto WithStaticFieldReadLock(const char* tag, Func body)
|
|
-> decltype(body());
|
|
|
|
template <class Func>
|
|
static auto WithOecWriteLock(const char* tag, Func body) -> decltype(body());
|
|
|
|
template <class Func>
|
|
static auto WithOecReadLock(const char* tag, Func body) -> decltype(body());
|
|
|
|
template <class Func>
|
|
auto WithOecSessionLock(const char* tag, Func body) -> decltype(body());
|
|
|
|
static bool IsInitialized();
|
|
|
|
// The locking methods above should be used in preference to taking these
|
|
// mutexes directly. If code takes these manually and needs to take more
|
|
// than one, it must *always* take them in the order they are defined here.
|
|
static wvutil::shared_mutex static_field_mutex_;
|
|
static wvutil::shared_mutex oem_crypto_mutex_;
|
|
std::mutex oem_crypto_session_mutex_;
|
|
// Usage table mutex used only when performing write operations on
|
|
// the static usage table pointers.
|
|
static std::recursive_mutex usage_table_mutex_;
|
|
|
|
static bool initialized_;
|
|
static int session_count_;
|
|
static int termination_counter_;
|
|
static bool needs_keybox_provisioning_;
|
|
|
|
enum CachedBooleanProperty {
|
|
// Property has not yet been checked/cached.
|
|
kBooleanUnset,
|
|
// Property has been cached as false.
|
|
kBooleanFalse,
|
|
// Property has been cached as true.
|
|
kBooleanTrue
|
|
};
|
|
|
|
metrics::CryptoMetrics* metrics_;
|
|
metrics::Timer life_span_;
|
|
uint32_t system_id_;
|
|
|
|
bool open_;
|
|
CdmClientTokenType pre_provision_token_type_;
|
|
std::string oem_token_; // Cached OEMCrypto Public Key
|
|
bool update_usage_table_after_close_session_;
|
|
CryptoSessionId oec_session_id_;
|
|
std::unique_ptr<KeySession> key_session_;
|
|
|
|
OEMCryptoBufferType destination_buffer_type_;
|
|
bool is_destination_buffer_type_valid_;
|
|
RequestedSecurityLevel requested_security_level_;
|
|
|
|
// Open session-cached result of OEMCrypto_SupportsUsageTable().
|
|
CachedBooleanProperty has_usage_table_support_ = kBooleanUnset;
|
|
CdmUsageTable* usage_table_ = nullptr;
|
|
// These fields are protected by |usage_table_mutex_| and not
|
|
// |static_field_mutex_|.
|
|
static std::unique_ptr<CdmUsageTable> usage_table_l1_;
|
|
static std::unique_ptr<CdmUsageTable> usage_table_l3_;
|
|
|
|
std::string request_id_;
|
|
static std::atomic<uint64_t> request_id_index_source_;
|
|
|
|
uint32_t api_version_;
|
|
size_t max_subsample_region_size_;
|
|
|
|
// Stores the most recent error code returned from a call to
|
|
// OEMCrypto_DecryptCENC. This is used to reduce the total number of
|
|
// error logs for decrypt calls, as there could be a large number of
|
|
// same error code in sequence of each other. A value of
|
|
// OEMCrypto_SUCCESS indicates that no error have yet occurred.
|
|
OEMCryptoResult last_decrypt_error_ = OEMCrypto_SUCCESS;
|
|
// Similar to |last_decrypt_error_|, but intended for calls to
|
|
// SelectKey().
|
|
OEMCryptoResult last_select_key_error_ = OEMCrypto_SUCCESS;
|
|
|
|
// In order to avoid creating a deadlock if instantiation needs to take any
|
|
// of the CryptoSession static mutexes, |factory_| is protected by its own
|
|
// mutex that is only used in the two functions that interact with it.
|
|
static std::mutex factory_mutex_;
|
|
static std::unique_ptr<CryptoSessionFactory> factory_;
|
|
|
|
// A singleton instance of SystemFallbackPolicy. Only one will
|
|
// be created for the system if OTA keybox provisioning is both
|
|
// required and supported by L1.
|
|
static std::unique_ptr<okp::SystemFallbackPolicy> okp_fallback_policy_l1_;
|
|
|
|
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
|
|
}; // class CryptoSession
|
|
|
|
class CryptoSessionFactory {
|
|
public:
|
|
virtual ~CryptoSessionFactory() {}
|
|
virtual CryptoSession* MakeCryptoSession(
|
|
metrics::CryptoMetrics* crypto_metrics);
|
|
|
|
protected:
|
|
friend class CryptoSession;
|
|
CryptoSessionFactory() {}
|
|
|
|
private:
|
|
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSessionFactory);
|
|
};
|
|
|
|
} // namespace wvcdm
|
|
|
|
#endif // WVCDM_CORE_CRYPTO_SESSION_H_
|