Source release 17.1.0
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// 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.
|
||||
// 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_
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "crypto_wrapped_key.h"
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "key_session.h"
|
||||
#include "metrics_collections.h"
|
||||
@@ -22,10 +23,15 @@
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
class CryptoKey;
|
||||
class CryptoSessionFactory;
|
||||
class OtaKeyboxProvisioner;
|
||||
class UsageTableHeader;
|
||||
|
||||
namespace okp {
|
||||
class SystemFallbackPolicy;
|
||||
} // namespace okp
|
||||
|
||||
using CryptoKeyMap = std::map<std::string, CryptoKey*>;
|
||||
|
||||
// Crypto session utility functions used by KeySession implementations.
|
||||
@@ -39,8 +45,6 @@ OEMCrypto_Substring GetSubstring(const std::string& message = "",
|
||||
bool set_zero = false);
|
||||
OEMCryptoCipherMode ToOEMCryptoCipherMode(CdmCipherMode cipher_mode);
|
||||
|
||||
class CryptoSessionFactory;
|
||||
|
||||
class CryptoSession {
|
||||
public:
|
||||
using HdcpCapability = OEMCrypto_HDCP_Capability;
|
||||
@@ -54,6 +58,9 @@ class CryptoSession {
|
||||
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|.
|
||||
@@ -75,18 +82,37 @@ class CryptoSession {
|
||||
|
||||
static void DisableDelayedTermination();
|
||||
|
||||
virtual CdmResponseType GetProvisioningToken(std::string* client_token);
|
||||
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(SecurityLevel requested_level);
|
||||
virtual CdmSecurityLevel GetSecurityLevel(
|
||||
RequestedSecurityLevel requested_level);
|
||||
virtual bool GetApiVersion(uint32_t* version);
|
||||
virtual bool GetApiVersion(SecurityLevel requested_level, uint32_t* version);
|
||||
virtual bool GetApiMinorVersion(SecurityLevel requested_level,
|
||||
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
|
||||
@@ -104,12 +130,17 @@ class CryptoSession {
|
||||
// - that does not implement |OEMCrypto_GetDeviceID|: the 32 byte hash
|
||||
// of the OEM public certificate.
|
||||
virtual CdmResponseType GetExternalDeviceUniqueId(std::string* device_id);
|
||||
virtual bool GetSystemId(uint32_t* system_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(SecurityLevel requested_security_level);
|
||||
virtual CdmResponseType Open(RequestedSecurityLevel requested_security_level);
|
||||
virtual void Close();
|
||||
|
||||
virtual bool IsOpen() { return open_; }
|
||||
@@ -123,6 +154,7 @@ class CryptoSession {
|
||||
virtual CdmResponseType PrepareAndSignLicenseRequest(
|
||||
const std::string& message, std::string* core_message,
|
||||
std::string* signature);
|
||||
virtual CdmResponseType UseSecondaryKey(bool dual_key);
|
||||
// V15 licenses.
|
||||
virtual CdmResponseType LoadKeys(const std::string& message,
|
||||
const std::string& signature,
|
||||
@@ -167,7 +199,17 @@ class CryptoSession {
|
||||
const std::string& signature,
|
||||
std::string* wrapped_private_key);
|
||||
virtual CdmResponseType LoadCertificatePrivateKey(
|
||||
const std::string& wrapped_key);
|
||||
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);
|
||||
@@ -178,32 +220,40 @@ class CryptoSession {
|
||||
// preceding call to Open. The other methods must call Open first.
|
||||
virtual CdmResponseType GetHdcpCapabilities(HdcpCapability* current,
|
||||
HdcpCapability* max);
|
||||
virtual CdmResponseType GetHdcpCapabilities(SecurityLevel security_level,
|
||||
HdcpCapability* current,
|
||||
HdcpCapability* max);
|
||||
virtual CdmResponseType GetHdcpCapabilities(
|
||||
RequestedSecurityLevel security_level, HdcpCapability* current,
|
||||
HdcpCapability* max);
|
||||
virtual bool GetResourceRatingTier(uint32_t* tier);
|
||||
virtual bool GetResourceRatingTier(SecurityLevel security_level,
|
||||
virtual bool GetResourceRatingTier(RequestedSecurityLevel security_level,
|
||||
uint32_t* tier);
|
||||
|
||||
virtual bool GetSupportedCertificateTypes(SupportedCertificateTypes* support);
|
||||
virtual CdmResponseType GetRandom(size_t data_length, uint8_t* random_data);
|
||||
virtual CdmResponseType GetNumberOfOpenSessions(SecurityLevel security_level,
|
||||
size_t* count);
|
||||
virtual CdmResponseType GetMaxNumberOfSessions(SecurityLevel security_level,
|
||||
size_t* max);
|
||||
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 IsSrmUpdateSupported();
|
||||
virtual CdmResponseType LoadSrm(const std::string& srm);
|
||||
|
||||
virtual bool GetBuildInformation(SecurityLevel security_level,
|
||||
virtual bool GetBuildInformation(RequestedSecurityLevel security_level,
|
||||
std::string* info);
|
||||
virtual bool GetBuildInformation(std::string* info);
|
||||
|
||||
virtual bool GetMaximumUsageTableEntries(SecurityLevel security_level,
|
||||
size_t* number_of_entries);
|
||||
virtual bool GetWatermarkingSupport(CdmWatermarkingSupport* support);
|
||||
virtual bool GetWatermarkingSupport(
|
||||
RequestedSecurityLevel requested_security_level,
|
||||
CdmWatermarkingSupport* support);
|
||||
|
||||
virtual bool GetDecryptHashSupport(SecurityLevel security_level,
|
||||
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,
|
||||
@@ -234,14 +284,13 @@ class CryptoSession {
|
||||
// Used to manipulate the CDM managed usage table header & entries,
|
||||
// delegating calls to OEMCrypto.
|
||||
|
||||
// Usage support.
|
||||
virtual CdmResponseType GetUsageSupportType(CdmUsageSupportType* type);
|
||||
|
||||
// The overloaded method with |security_level| may be called without a
|
||||
// preceding call to Open. The other method must call Open first.
|
||||
virtual bool UsageInformationSupport(bool* has_support);
|
||||
virtual bool UsageInformationSupport(SecurityLevel security_level,
|
||||
bool* has_support);
|
||||
// Determines whether the OEMCrypto library supports usage info.
|
||||
// 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 HasUsageInfoSupport(bool* has_support);
|
||||
virtual bool HasUsageInfoSupport(RequestedSecurityLevel security_level,
|
||||
bool* has_support);
|
||||
|
||||
// Usage report.
|
||||
virtual CdmResponseType DeactivateUsageInformation(
|
||||
@@ -258,13 +307,13 @@ class CryptoSession {
|
||||
// The following crypto methods do not require an open session to
|
||||
// complete the operations.
|
||||
virtual CdmResponseType CreateUsageTableHeader(
|
||||
SecurityLevel requested_security_level,
|
||||
RequestedSecurityLevel requested_security_level,
|
||||
CdmUsageTableHeader* usage_table_header);
|
||||
virtual CdmResponseType LoadUsageTableHeader(
|
||||
SecurityLevel requested_security_level,
|
||||
RequestedSecurityLevel requested_security_level,
|
||||
const CdmUsageTableHeader& usage_table_header);
|
||||
virtual CdmResponseType ShrinkUsageTableHeader(
|
||||
SecurityLevel requested_security_level, uint32_t new_entry_count,
|
||||
RequestedSecurityLevel requested_security_level, uint32_t new_entry_count,
|
||||
CdmUsageTableHeader* usage_table_header);
|
||||
|
||||
// Usage entry.
|
||||
@@ -283,7 +332,36 @@ class CryptoSession {
|
||||
virtual metrics::CryptoMetrics* GetCryptoMetrics() { return metrics_; }
|
||||
|
||||
virtual CdmResponseType GetProvisioningMethod(
|
||||
SecurityLevel requested_security_level, CdmClientTokenType* token_type);
|
||||
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|.
|
||||
@@ -291,7 +369,11 @@ class CryptoSession {
|
||||
// exist as long as the new CryptoSession exists.
|
||||
explicit CryptoSession(metrics::CryptoMetrics* crypto_metrics);
|
||||
|
||||
int session_count() { return session_count_; }
|
||||
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;
|
||||
@@ -299,23 +381,26 @@ class CryptoSession {
|
||||
#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 transfered to CryptoSession.
|
||||
// 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();
|
||||
CdmResponseType GetTokenFromKeybox(std::string* token);
|
||||
CdmResponseType GetTokenFromOemCert(std::string* token);
|
||||
static bool ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||
uint32_t* system_id);
|
||||
CdmResponseType GetSystemIdInternal(uint32_t* system_id);
|
||||
|
||||
// Will set up the UsageTableHeader for this session. This may require
|
||||
// creating a new UsageTableHeader if the global instance has not
|
||||
// been initialized.
|
||||
// Note: This function will lock the global static field lock in write mode.
|
||||
bool SetUpUsageTableHeader(RequestedSecurityLevel requested_security_level);
|
||||
|
||||
CdmResponseType GenerateRsaSignature(const std::string& message,
|
||||
std::string* signature);
|
||||
size_t GetMaxSubsampleRegionSize();
|
||||
@@ -325,13 +410,11 @@ class CryptoSession {
|
||||
CdmResponseType SelectKey(const std::string& key_id,
|
||||
CdmCipherMode cipher_mode);
|
||||
|
||||
static const OEMCrypto_Algorithm kInvalidAlgorithm =
|
||||
static_cast<OEMCrypto_Algorithm>(-1);
|
||||
|
||||
OEMCrypto_Algorithm GenericSigningAlgorithm(CdmSigningAlgorithm algorithm);
|
||||
OEMCrypto_Algorithm GenericEncryptionAlgorithm(
|
||||
CdmEncryptionAlgorithm algorithm);
|
||||
size_t GenericEncryptionBlockSize(CdmEncryptionAlgorithm algorithm);
|
||||
// Retrieves the OEMCrypto usage info support for the specified
|
||||
// |requested_security_level|.
|
||||
// Caller should acquire the OEMCrypto read lock before calling.
|
||||
bool HasUsageInfoSupportInternal(
|
||||
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
|
||||
@@ -355,9 +438,15 @@ class CryptoSession {
|
||||
// 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. It can be taken as a reader or as
|
||||
// a writer, depending on how you will be accessing the static fields.
|
||||
// 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
|
||||
@@ -408,23 +497,32 @@ class CryptoSession {
|
||||
|
||||
static bool IsInitialized();
|
||||
|
||||
// Constants
|
||||
static const size_t kAes128BlockSize = 16; // Block size for AES_CBC_128
|
||||
static const size_t kSignatureSize = 32; // size for HMAC-SHA256 signature
|
||||
|
||||
// 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 shared_mutex static_field_mutex_;
|
||||
static shared_mutex oem_crypto_mutex_;
|
||||
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::TimerMetric life_span_;
|
||||
metrics::Timer life_span_;
|
||||
uint32_t system_id_;
|
||||
|
||||
bool open_;
|
||||
@@ -436,12 +534,15 @@ class CryptoSession {
|
||||
|
||||
OEMCryptoBufferType destination_buffer_type_;
|
||||
bool is_destination_buffer_type_valid_;
|
||||
SecurityLevel requested_security_level_;
|
||||
RequestedSecurityLevel requested_security_level_;
|
||||
|
||||
CdmUsageSupportType usage_support_type_;
|
||||
UsageTableHeader* usage_table_header_;
|
||||
static UsageTableHeader* usage_table_header_l1_;
|
||||
static UsageTableHeader* usage_table_header_l3_;
|
||||
// Open session-cached result of OEMCrypto_SupportsUsageTable().
|
||||
CachedBooleanProperty has_usage_info_support_ = kBooleanUnset;
|
||||
UsageTableHeader* usage_table_header_ = nullptr;
|
||||
// These fields are protected by |usage_table_mutex_| and not
|
||||
// |static_field_mutex_|.
|
||||
static std::unique_ptr<UsageTableHeader> usage_table_header_l1_;
|
||||
static std::unique_ptr<UsageTableHeader> usage_table_header_l3_;
|
||||
|
||||
std::string request_id_;
|
||||
static std::atomic<uint64_t> request_id_index_source_;
|
||||
@@ -458,10 +559,15 @@ class CryptoSession {
|
||||
|
||||
// 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 funtions that interact with it.
|
||||
// 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user