// 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 #include #include #include #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 WvContentDecryptionModule : public android::RefBase, public TimerHandler { public: WvContentDecryptionModule(); 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 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, 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, CdmUsageInfo* usage_info); virtual CdmResponseType GetUsageInfo(const std::string& app_id, const CdmSecureStopId& ssid, const CdmIdentifier& identifier, CdmUsageInfo* usage_info); 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 CdmUsageInfoReleaseMessage& message, const CdmIdentifier& identifier); virtual CdmResponseType GetSecureStopIds(const std::string& app_id, const CdmIdentifier& identifier, std::vector* 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 metrics data for the CdmEngine // associated with the given CdmIdentifier. If the CdmEngine instance does // not exist, this will return an error. virtual CdmResponseType GetMetrics(const CdmIdentifier& identifier, drm_metrics::WvCdmMetrics* metrics); // Fill the metrics parameter with the metrics data for all the CdmEngine // associated with the given CdmIdentifiers. If there are no CdmEngine // instances, this will return an error. virtual CdmResponseType GetMetrics( std::vector* metrics, bool* full_list_returned); // 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); // Allow the device to continue with a test keybox. Otherwise, it will fall // back to L3. virtual CdmResponseType SetAllowTestKeybox(bool allow); 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* 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 bool SetDefaultOtaKeyboxFallbackDurationRules(); virtual bool SetFastOtaKeyboxFallbackDurationRules(); private: struct CdmInfo { CdmInfo(); wvutil::FileSystem file_system; std::unique_ptr 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 GetMetricsInternal(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 cdms_; // This contains weak pointers to the CDM instances contained in |cdms_|. std::map 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_; CORE_DISALLOW_COPY_AND_ASSIGN(WvContentDecryptionModule); }; } // namespace wvcdm #endif // CDM_BASE_WV_CONTENT_DECRYPTION_MODULE_H_