Files
android/libwvdrmengine/cdm/include/wv_content_decryption_module.h
Cong Lin 6327211db6 WVDrmPlugin changes to query device CSR payload for prov 4
Plugin to provide getPropertyByteArray("deviceSignedCsrPayload")
which returns the signed CSR payload for device registration. It
queries both BCC and device info to be set in plugin before calling this
getPropertyByteArray("deviceSignedCsrPayload") method. The returned csr
payload will be used by assemble the device CSR by the caller for device
registration.

Bug: 286556950
Test: build WV DRM plugin
Merged from https://widevine-internal-review.googlesource.com/178891

Merged from https://widevine-internal-review.googlesource.com/179731

Change-Id: I65d89ed998dd292fc656af2f91f4472c1b5ec33c
2024-02-01 13:40:52 -08:00

376 lines
16 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 CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_
#define CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_
#include <time.h>
#include <map>
#include <memory>
#include <mutex>
#include "utils/RefBase.h"
#include "cdm_identifier.h"
#include "disallow_copy_and_assign.h"
#include "file_store.h"
#include "timer.h"
#include "wv_cdm_types.h"
#include "wv_metrics.pb.h"
namespace wvcdm {
class CdmClientPropertySet;
class CdmEngine;
class WvCdmEventListener;
class WvMetricsSnapshot {
public:
WvMetricsSnapshot(const CdmIdentifier& identifier,
drm_metrics::WvCdmMetrics&& metrics, ::time_t ts);
// Acts as a constructor, but uses the current time.
static WvMetricsSnapshot MakeSnapshot(const CdmIdentifier& identifier,
drm_metrics::WvCdmMetrics&& metrics);
WvMetricsSnapshot() = default;
WvMetricsSnapshot(const WvMetricsSnapshot&) = default;
WvMetricsSnapshot(WvMetricsSnapshot&&) = default;
WvMetricsSnapshot& operator=(const WvMetricsSnapshot&) = default;
WvMetricsSnapshot& operator=(WvMetricsSnapshot&&) = default;
const CdmIdentifier& cdm_id() const { return cdm_id_; }
const drm_metrics::WvCdmMetrics& metrics() const { return metrics_; }
::time_t timestamp() const { return timestamp_; }
std::string GetFormattedTimestamp() const;
private:
CdmIdentifier cdm_id_;
drm_metrics::WvCdmMetrics metrics_;
::time_t timestamp_ = 0;
};
class WvMetricsSnapshotQueue
: public android::LightRefBase<WvMetricsSnapshotQueue> {
public:
WvMetricsSnapshotQueue();
explicit WvMetricsSnapshotQueue(size_t capacity) : capacity_(capacity) {}
size_t capacity() const { return capacity_; }
size_t size() const { return snapshots_.size(); }
WvMetricsSnapshotQueue(const WvMetricsSnapshotQueue&) = delete;
WvMetricsSnapshotQueue(WvMetricsSnapshotQueue&&) = delete;
WvMetricsSnapshotQueue& operator=(const WvMetricsSnapshotQueue&) = delete;
WvMetricsSnapshotQueue& operator=(WvMetricsSnapshotQueue&&) = delete;
void PushMetrics(WvMetricsSnapshot&& snapshot);
void PushMetrics(const WvMetricsSnapshot& snapshot);
bool GetAll(std::vector<WvMetricsSnapshot>* snapshots) const;
void Clear();
private:
void ReFit();
const size_t capacity_;
mutable std::mutex mutex_;
std::deque<WvMetricsSnapshot> snapshots_;
};
class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
public:
WvContentDecryptionModule();
explicit WvContentDecryptionModule(WvMetricsSnapshotQueue* metrics_queue);
virtual ~WvContentDecryptionModule();
// Static methods
static bool IsSupported(const std::string& init_data_type);
static bool IsCenc(const std::string& init_data_type);
static bool IsWebm(const std::string& init_data_type);
static bool IsHls(const std::string& init_data_type);
static bool IsAudio(const std::string& init_data_type);
// Session related methods
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,
CdmClientPropertySet* property_set,
const CdmIdentifier& identifier,
WvCdmEventListener* event_listener,
CdmSessionId* session_id);
virtual CdmResponseType CloseSession(const CdmSessionId& session_id);
virtual bool IsOpenSession(const CdmSessionId& session_id);
// Construct a valid license request.
virtual CdmResponseType GenerateKeyRequest(
const CdmSessionId& session_id, const CdmKeySetId& key_set_id,
const std::string& init_data_type, const CdmInitData& init_data,
const CdmLicenseType license_type, CdmAppParameterMap& app_parameters,
CdmClientPropertySet* property_set, const CdmIdentifier& identifier,
CdmKeyRequest* key_request);
// Accept license response and extract key info.
virtual CdmResponseType AddKey(const CdmSessionId& session_id,
const CdmKeyResponse& key_data,
CdmKeySetId* key_set_id);
// Setup keys for offline usage which were retrived in an earlier key request
virtual CdmResponseType RestoreKey(const CdmSessionId& session_id,
const CdmKeySetId& key_set_id);
// Cancel session
virtual CdmResponseType RemoveKeys(const CdmSessionId& session_id);
// Query system information
virtual CdmResponseType QueryStatus(RequestedSecurityLevel security_level,
const std::string& key,
std::string* value);
// Query session information
virtual CdmResponseType QuerySessionStatus(const CdmSessionId& session_id,
CdmQueryMap* key_info);
// Query license information
virtual CdmResponseType QueryKeyStatus(const CdmSessionId& session_id,
CdmQueryMap* key_info);
// Query device CSR information for Provisioning 4.0
virtual CdmResponseType QueryDeviceSignedCsrPayload(
const std::string& challenge, const std::string& device_info,
std::string* value);
// Query OEMCrypto session ID
virtual CdmResponseType QueryOemCryptoSessionId(
const CdmSessionId& session_id, CdmQueryMap* response);
// Query security level support
static bool IsSecurityLevelSupported(CdmSecurityLevel level);
// Provisioning related methods
virtual CdmResponseType GetProvisioningRequest(
CdmCertificateType cert_type, const std::string& cert_authority,
const CdmIdentifier& identifier, const std::string& service_certificate,
RequestedSecurityLevel requested_security_level,
CdmProvisioningRequest* request, std::string* default_url);
virtual CdmResponseType HandleProvisioningResponse(
const CdmIdentifier& identifier, const CdmProvisioningResponse& response,
RequestedSecurityLevel requested_security_level, std::string* cert,
std::string* wrapped_key);
virtual CdmResponseType Unprovision(CdmSecurityLevel level,
const CdmIdentifier& identifier);
virtual bool IsProvisioned(CdmSecurityLevel level, const std::string& origin,
const std::string& spoid, bool atsc_mode_enabled);
// Secure stop related methods
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
const CdmIdentifier& identifier,
CdmUsageReportList* usage_reports);
virtual CdmResponseType GetUsageInfo(const std::string& app_id,
const CdmSecureStopId& ssid,
const CdmIdentifier& identifier,
CdmUsageReport* usage_report);
virtual CdmResponseType RemoveAllUsageInfo(const std::string& app_id,
const CdmIdentifier& identifier);
virtual CdmResponseType RemoveUsageInfo(
const std::string& app_id, const CdmIdentifier& identifier,
const CdmSecureStopId& secure_stop_id);
virtual CdmResponseType ReleaseUsageInfo(const CdmKeyResponse& message,
const CdmIdentifier& identifier);
virtual CdmResponseType GetSecureStopIds(const std::string& app_id,
const CdmIdentifier& identifier,
std::vector<CdmSecureStopId>* ssids);
// Accept encrypted buffer and decrypt data.
// Decryption parameters that need to be specified are
// is_encrypted, is_secure, key_id, encrypt_buffer, encrypt_length,
// iv, block_offset, decrypt_buffer, decrypt_buffer_length,
// decrypt_buffer_offset and subsample_flags
virtual CdmResponseType Decrypt(const CdmSessionId& session_id,
bool validate_key_id,
const CdmDecryptionParameters& parameters);
// Accept encrypted sample and decrypt data.
virtual CdmResponseType DecryptV16(
const CdmSessionId& session_id, bool validate_key_id,
const CdmDecryptionParametersV16& parameters);
virtual void NotifyResolution(const CdmSessionId& session_id, uint32_t width,
uint32_t height);
// Validate a passed-in service certificate
virtual bool IsValidServiceCertificate(const std::string& certificate);
// Fill the |metrics| parameter with the engine metrics data for the
// CdmEngine associated with the given CdmIdentifier.
// If the CdmEngine instance does not exist, this will return an error.
virtual CdmResponseType GetCurrentMetrics(const CdmIdentifier& identifier,
drm_metrics::WvCdmMetrics* metrics);
// Fill the |snapshots| parameter wrapped engine metrics for all CdmEngine
// instances that currently enabled (actively decrypting or performing
// other engine-level operations).
// Current metrics snapshots contain the engine identifier, metrics data
// and time (roughly current time).
// |full_list_returned| will indicate whether all existing enginers were
// able to report their metrics successfully.
virtual CdmResponseType GetAllCurrentMetricsSnapshots(
std::vector<WvMetricsSnapshot>* snapshots, bool* full_list_returned);
// Fill the |snapshots| parameter wrapped engine metrics for several of
// the most recently closed CdmEngine instances.
// Saved metrics snapshots contain the engine identifier, metrics data
// and time of closing.
// The same engine identifier may appear multiple times in the list (
// depending on how the app utilizes the MediaDrm plugin).
virtual CdmResponseType GetAllSavedMetricsSnapshots(
std::vector<WvMetricsSnapshot>* snapshots);
// Closes the CdmEngine and sessions associated with the given CdmIdentifier.
virtual CdmResponseType CloseCdm(const CdmIdentifier& identifier);
// When positive, the keybox will be ignored at initialization and force the
// device to request a keybox OTA reprovisioning.
virtual CdmResponseType SetDebugIgnoreKeyboxCount(uint32_t count);
virtual CdmResponseType SetDecryptHash(const std::string& hash_data,
CdmSessionId* session_id);
virtual CdmResponseType GetDecryptHashError(const CdmSessionId& session_id,
std::string* hash_error_string);
// Return the list of key_set_ids stored on the current (origin-specific)
// file system.
virtual CdmResponseType ListStoredLicenses(
CdmSecurityLevel security_level, const CdmIdentifier& identifier,
std::vector<CdmKeySetId>* key_set_ids);
// Retrieve offline license state using key_set_id.
virtual CdmResponseType GetOfflineLicenseState(
const CdmKeySetId& key_set_id, CdmSecurityLevel security_level,
const CdmIdentifier& identifier, CdmOfflineLicenseState* licenseState);
// Remove offline license using key_set_id.
virtual CdmResponseType RemoveOfflineLicense(const CdmKeySetId& key_set_id,
CdmSecurityLevel security_level,
const CdmIdentifier& identifier);
virtual CdmResponseType SetPlaybackId(const CdmSessionId& session_id,
const std::string& playback_id);
virtual CdmResponseType GetSessionUserId(const CdmSessionId& session_id,
uint32_t* user_id);
virtual CdmResponseType StoreAtscLicense(
const CdmIdentifier& identifier, RequestedSecurityLevel security_level,
const CdmKeySetId& key_set_id,
const std::string& serialized_license_data);
virtual bool SetDefaultOtaKeyboxFallbackDurationRules();
virtual bool SetFastOtaKeyboxFallbackDurationRules();
// Generic crypto API.
virtual CdmResponseType GenericEncrypt(const CdmSessionId& session_id,
const KeyId& key_id,
const std::string& input,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* output);
virtual CdmResponseType GenericDecrypt(const CdmSessionId& session_id,
const KeyId& key_id,
const std::string& input,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* output);
virtual CdmResponseType GenericSign(const CdmSessionId& session_id,
const KeyId& key_id,
const std::string& input,
CdmSigningAlgorithm algorithm,
std::string* signature);
virtual CdmResponseType GenericVerify(const CdmSessionId& session_id,
const KeyId& key_id,
const std::string& input,
CdmSigningAlgorithm algorithm,
const std::string& signature);
private:
struct CdmInfo {
CdmInfo();
wvutil::FileSystem file_system;
std::unique_ptr<CdmEngine> cdm_engine;
};
// Finds the CdmEngine instance for the given identifier, creating one if
// needed.
CdmEngine* EnsureCdmForIdentifier(const CdmIdentifier& identifier);
// Finds the CdmEngine instance for the given session id, returning nullptr
// if not found.
CdmEngine* GetCdmForSessionId(const std::string& session_id);
// Close all of the open CdmEngine instances. This is used when ready to close
// the WvContentDecryptionModule instance.
void CloseAllCdms();
uint32_t GenerateSessionSharingId();
// Timer related methods to drive policy decisions
void EnableTimer();
void DisableTimer();
// Call this method only if invoked from a thread other than the timer thread.
// Otherwise this might result in deadlock.
void DisableTimerAndWaitForExit();
void OnTimerEvent();
// Fill the |metrics| parameter with the metrics data for the CdmEngine
// associated with the given |identifier|. If the CdmEngine instance does
// not exist, this will return an error.
// This methods assumes that |metrics| is not null and that the |cdms_lock_|
// has already been acquired.
CdmResponseType GetCurrentMetricsInternal(const CdmIdentifier& identifier,
drm_metrics::WvCdmMetrics* metrics);
void SaveMetrics(const CdmIdentifier& identifier,
drm_metrics::WvCdmMetrics&& metrics);
static std::mutex session_sharing_id_generation_lock_;
std::mutex timer_lock_;
Timer timer_;
// instance variables
// This manages the lifetime of the CDM instances.
std::map<CdmIdentifier, CdmInfo> cdms_;
// This contains weak pointers to the CDM instances contained in |cdms_|.
std::map<std::string, CdmEngine*> cdm_by_session_id_;
// Lock for accessing either |cdms_| or |cdm_by_session_id_|.
// This lock should be acquired for any of the following:
// 1) Getting a CDM instance from |cdms_| or |cdm_by_session_id_|
// - Hold lock while searching, release lock once pointer is acquired
// 2) Iterating over |cdms_| or |cdm_by_session_id_|
// - Hold lock for the entire duration of iterating over CDMs
// - DO NOT release the lock until all operations are complete
// - This MUST be done regardless of whether |cdms_| or
// |cdm_by_session_id_| is being modified
// 3) Creating a new CDM instance with |cdms_|
// - Hold lock when creating AND initializing the CDM
// - Release once CDM is fully initialized
// 4) Linking a session to a CDM with |cdm_by_session_id_|
// - Hold lock when mapping a session ID to a CDM, release once set
// 5) Unlinking a session from a CDM with |cdm_by_session_id_|
// - Hold lock when erasing, release once erased.
std::mutex cdms_lock_;
// Contains a finite list of histories of different CDM engine instances.
// When a CDM engine is closed, its metrics will be saved.
// Only used if not null.
WvMetricsSnapshotQueue* saved_metrics_snapshots_ = nullptr;
CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule);
};
} // namespace wvcdm
#endif // CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_