// // 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 WV_DRM_PLUGIN_H_ #define WV_DRM_PLUGIN_H_ #include #include "cdm_client_property_set.h" #include "cdm_identifier.h" #include "wv_cdm_event_listener.h" #include "wv_content_decryption_module.h" #include "OEMCryptoCENC.h" #include "HidlTypes.h" #include "WVGenericCryptoInterface.h" #include "WVTypes.h" namespace wvdrm { namespace hardware { namespace drm { namespace V1_4 { namespace widevine { using std::map; using wvcdm::CdmIdentifier; using wvcdm::CdmKeyStatusMap; using wvcdm::CdmSessionId; using wvcdm::CdmResponseType; using wvcdm::WvContentDecryptionModule; const OEMCrypto_Algorithm kInvalidCryptoAlgorithm = static_cast(-1); struct WVDrmPlugin : public ::drm::V1_4::IDrmPlugin, IDrmPluginListener, wvcdm::WvCdmEventListener { WVDrmPlugin(const sp& cdm, const std::string& appPackageName, WVGenericCryptoInterface* crypto, bool useSpoid); virtual ~WVDrmPlugin(); Return openSession(openSession_cb _hidl_cb) override; Return openSession_1_1(SecurityLevel securityLevel, openSession_1_1_cb _hidl_cb) override; Return closeSession(const hidl_vec& sessionId) override; Return getKeyRequest( const hidl_vec& scope, const hidl_vec& initData, const hidl_string& mimeType, KeyType keyType, const hidl_vec& optionalParameters, getKeyRequest_cb _hidl_cb) override; Return getKeyRequest_1_1( const hidl_vec& scope, const hidl_vec& initData, const hidl_string& mimeType, KeyType keyType, const hidl_vec& optionalParameters, getKeyRequest_1_1_cb _hidl_cb) override; Return getKeyRequest_1_2( const hidl_vec& scope, const hidl_vec& initData, const hidl_string& mimeType, KeyType keyType, const hidl_vec& optionalParameters, getKeyRequest_1_2_cb _hidl_cb) override; Return provideKeyResponse( const hidl_vec& scope, const hidl_vec& response, provideKeyResponse_cb _hidl_cb) override; Return removeKeys(const hidl_vec& sessionId) override; Return restoreKeys( const hidl_vec& sessionId, const hidl_vec& keySetId) override; Return queryKeyStatus( const hidl_vec& sessionId, queryKeyStatus_cb _hidl_cb) override; Return getProvisionRequest( const hidl_string& certificateType, const hidl_string& certificateAuthority, getProvisionRequest_cb _hidl_cb) override; Return getProvisionRequest_1_2( const hidl_string& certificateType, const hidl_string& certificateAuthority, getProvisionRequest_1_2_cb _hidl_cb) override; Return provideProvisionResponse( const hidl_vec& response, provideProvisionResponse_cb _hidl_cb) override; Return getSecureStops(getSecureStops_cb _hidl_cb) override; Return getSecureStop( const hidl_vec& secureStopId, getSecureStop_cb _hidl_cb) override; Return releaseAllSecureStops() override; Return releaseSecureStop( const hidl_vec& secureStopId) override; Return getMetrics(getMetrics_cb _hidl_cb); Return getSecureStopIds(getSecureStopIds_cb _hidl_cb) override; Return releaseSecureStops(const SecureStopRelease& ssRelease) override; Return removeSecureStop(const hidl_vec& secureStopId) override; Return removeAllSecureStops() override; Return getHdcpLevels(getHdcpLevels_cb _hidl_cb) override; Return getHdcpLevels_1_2(getHdcpLevels_1_2_cb _hidl_cb) override; Return getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) override; Return getSecurityLevel(const hidl_vec& sessionId, getSecurityLevel_cb _hidl_cb) override; Return getOfflineLicenseKeySetIds( getOfflineLicenseKeySetIds_cb _hidl_cb) override; Return removeOfflineLicense(const KeySetId &keySetId) override; Return getOfflineLicenseState(const KeySetId &keySetId, getOfflineLicenseState_cb _hidl_cb) override; Return getPropertyString( const hidl_string& propertyName, getPropertyString_cb _hidl_cb) override; Return getPropertyByteArray( const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) override; Return setPropertyString( const hidl_string& propertyName, const hidl_string& value) override; Return setPropertyByteArray( const hidl_string& propertyName, const hidl_vec& value) override; Return setCipherAlgorithm( const hidl_vec& sessionId, const hidl_string& algorithm) override; Return setMacAlgorithm( const hidl_vec& sessionId, const hidl_string& algorithm) override; Return encrypt( const hidl_vec& sessionId, const hidl_vec& keyId, const hidl_vec& input, const hidl_vec& iv, encrypt_cb _hidl_cb) override; Return decrypt( const hidl_vec& sessionId, const hidl_vec& keyId, const hidl_vec& input, const hidl_vec& iv, decrypt_cb _hidl_cb) override; Return sign(const hidl_vec& sessionId, const hidl_vec& keyId, const hidl_vec& message, sign_cb _hidl_cb) override; Return verify( const hidl_vec& sessionId, const hidl_vec& keyId, const hidl_vec& message, const hidl_vec& signature, verify_cb _hidl_cb) override; Return signRSA( const hidl_vec& sessionId, const hidl_string& algorithm, const hidl_vec& message, const hidl_vec& wrappedkey, signRSA_cb _hidl_cb) override; Return setListener(const sp& listener) override; Return sendEvent( EventType eventType, const hidl_vec& sessionId, const hidl_vec& data) override; Return sendExpirationUpdate( const hidl_vec& sessionId, int64_t expiryTimeInMS) override; Return sendKeysChange( const hidl_vec& sessionId, const hidl_vec& keyStatusList, bool hasNewUsableKey) override; Return sendKeysChange_1_2( const hidl_vec& sessionId, const hidl_vec& keyStatusList, bool hasNewUsableKey) override; Return sendSessionLostState( const hidl_vec& sessionId) override; Return getLogMessages( getLogMessages_cb _hidl_cb) override; Return requiresSecureDecoder(const hidl_string& mime, SecurityLevel level) override; Return requiresSecureDecoderDefault(const hidl_string& mime) override; Return<::drm::V1_0::Status> setPlaybackId( const hidl_vec& sessionId, const hidl_string& playbackId) override; // The following methods do not use hidl interface, it is used internally. virtual Status unprovisionDevice(); virtual void OnSessionRenewalNeeded(const CdmSessionId& cdmSessionId); template void _sendKeysChange( const hidl_vec& sessionId, const hidl_vec& keyStatusList, bool hasNewUsableKey); template void _OnSessionKeysChange( const CdmSessionId&, const CdmKeyStatusMap&, bool hasNewUsableKey); virtual void OnSessionKeysChange( const CdmSessionId& cdmSessionId, const CdmKeyStatusMap& cdmKeysStatus, bool hasNewUsableKey); virtual void OnExpirationUpdate( const CdmSessionId& cdmSessionId, int64_t newExpiryTimeSeconds); virtual void OnSessionLostState( const CdmSessionId& cdmSessionId); private: WVDRM_DISALLOW_COPY_AND_ASSIGN_AND_NEW(WVDrmPlugin); struct CryptoSession { public: CryptoSession() : mOecSessionId(-1), mCipherAlgorithm(kInvalidCryptoAlgorithm), mMacAlgorithm(kInvalidCryptoAlgorithm) {} CryptoSession(OEMCrypto_SESSION sessionId) : mOecSessionId(sessionId), mCipherAlgorithm(kInvalidCryptoAlgorithm), mMacAlgorithm(kInvalidCryptoAlgorithm) {} OEMCrypto_SESSION oecSessionId() const { return mOecSessionId; } OEMCrypto_Algorithm cipherAlgorithm() const { return mCipherAlgorithm; } void setCipherAlgorithm(OEMCrypto_Algorithm newAlgorithm) { mCipherAlgorithm = newAlgorithm; } OEMCrypto_Algorithm macAlgorithm() const { return mMacAlgorithm; } void setMacAlgorithm(OEMCrypto_Algorithm newAlgorithm) { mMacAlgorithm = newAlgorithm; } private: OEMCrypto_SESSION mOecSessionId; OEMCrypto_Algorithm mCipherAlgorithm; OEMCrypto_Algorithm mMacAlgorithm; }; class WVClientPropertySet : public wvcdm::CdmClientPropertySet { public: WVClientPropertySet() : mUsePrivacyMode(false), mShareKeys(false), mSessionSharingId(0), mUseAtscMode(false) {} virtual ~WVClientPropertySet() {} virtual const std::string& security_level() const { return mSecurityLevel; } void set_security_level(const std::string& securityLevel) { mSecurityLevel = securityLevel; } virtual bool use_privacy_mode() const { return mUsePrivacyMode; } void set_use_privacy_mode(bool usePrivacyMode) { mUsePrivacyMode = usePrivacyMode; } virtual const std::string& service_certificate() const { return mServiceCertificate; } virtual void set_service_certificate( const std::string& serviceCertificate) { mServiceCertificate = serviceCertificate; } virtual const std::string& device_provisioning_service_certificate() const { // Android does not support service certificates for provisioning. return mEmptyString; } virtual void set_device_provisioning_service_certificate( const std::string& ) { // Ignore. Android does not support service certificates for provisioning // TODO(b/69562876): Android SHOULD support service cert for provisioning } virtual bool is_session_sharing_enabled() const { return mShareKeys; } void set_is_session_sharing_enabled(bool shareKeys) { mShareKeys = shareKeys; } virtual uint32_t session_sharing_id() const { return mSessionSharingId; } virtual void set_session_sharing_id(uint32_t id) { mSessionSharingId = id; } virtual const std::string& app_id() const { return mAppId; } void set_app_id(const std::string& appId) { mAppId = appId; } virtual bool use_atsc_mode() const { return mUseAtscMode; } void set_use_atsc_mode(bool useAtscMode) { mUseAtscMode = useAtscMode; } private: DISALLOW_EVIL_CONSTRUCTORS(WVClientPropertySet); std::string mSecurityLevel; bool mUsePrivacyMode; std::string mServiceCertificate; bool mShareKeys; uint32_t mSessionSharingId; std::string mAppId; bool mUseAtscMode; const std::string mEmptyString; } mPropertySet; class CdmIdentifierBuilder { public: CdmIdentifierBuilder(bool useSpoid, const WVDrmPlugin& parent, const std::string& appPackageName); // Fills in the passed-in struct with the CDM Identifier for the current // combination of Origin, Application, and Device. This is needed by some // calls into the CDM in order to identify which CDM instance should receive // the call. Calling this will seal the CDM Identifier Builder, thus making // it an error to change the origin. Status getCdmIdentifier(CdmIdentifier* identifier); // Gets the application-safe device-unique ID. On non-SPOID devices, this is // the device-unique ID from OEMCrypto. On SPOID devices, this is the SPOID. // On SPOID devices, calling this will seal the CDM Identifier Builder, thus // making it an error to change the origin. Status getDeviceUniqueId(std::string* id); Status getProvisioningUniqueId(std::string* id); const std::string& origin() const { return mCdmIdentifier.origin; } bool set_origin(const std::string& id); // This sets the app package name to allow apps to access ATSC licenses bool set_use_atsc_mode(bool enable); // Indicates whether the builder can still be modified. This returns false // until a call to getCdmIdentifier. bool is_sealed() { return mIsIdentifierSealed; } private: WVDRM_DISALLOW_COPY_AND_ASSIGN(CdmIdentifierBuilder); CdmIdentifier mCdmIdentifier; bool mIsIdentifierSealed; bool mUseSpoid; std::string mAppPackageName; const WVDrmPlugin& mParent; Status calculateSpoid(); Status calculateSpoid(const std::string& deviceID, std::string* spoid); // Gets the device-unique ID from OEMCrypto. This must be private, since // this value must not be exposed to applications on SPOID devices. Code // outside this class should use getDeviceUniqueId() to get the // application-safe device-unique ID. Status getOemcryptoDeviceId(std::string* id); Status getOemcryptoDeviceId(wvcdm::SecurityLevel securityLevel, std::string* id); // The unique identifier is meant to ensure that two clients with the // same spoid, origin and app package name still get different cdm engine // instances. This is a stepping stone to simplifying the implementation. // Note that we do not have a lock or mutex around this object. We assume // that locking is handled external to this object. uint32_t getNextUniqueId(); } mCdmIdentifierBuilder; sp const mCDM; WVGenericCryptoInterface* mCrypto; map mCryptoSessions; sp mListener; sp mListenerV1_2; std::string mProvisioningServiceCertificate; wvcdm::CdmSessionId mDecryptHashSessionId; std::string mAppPackageName; Status queryProperty(const std::string& property, std::string& stringValue) const; Status queryProperty(wvcdm::SecurityLevel securityLevel, const std::string& property, std::string& stringValue) const; Status queryProperty(const std::string& property, std::vector& vector_value) const; bool isProvisioned(wvcdm::CdmSecurityLevel securityLevel, const std::string& origin, const std::string& spoid, bool atsc_mode_enabled) const; Status mapAndNotifyOfCdmResponseType(const std::vector& sessionId, CdmResponseType res); Status_V1_2 mapAndNotifyOfCdmResponseType_1_2(const std::vector& sessionId, CdmResponseType res); void notifyOfCdmResponseType(const std::vector& sessionId, CdmResponseType res); Status mapAndNotifyOfOEMCryptoResult(const std::vector& sessionId, OEMCryptoResult res); Status mapOEMCryptoResult(OEMCryptoResult res); SecurityLevel mapSecurityLevel(const std::string& level); wvcdm::SecurityLevel getRequestedSecurityLevel() const; Status openSessionCommon(std::vector& sessionId); bool initDataResemblesPSSH(const std::vector& initData); Status unprovision(const CdmIdentifier& identifier); }; } // namespace widevine } // namespace V1_4 } // namespace drm } // namespace hardware } // namespace wvdrm #endif // WV_DRM_PLUGIN_H_