/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CLEARKEY_DRM_PLUGIN_H_ #define CLEARKEY_DRM_PLUGIN_H_ #include #include #include #include #include #include "DeviceFiles.h" #include "SessionLibrary.h" #include "Utils.h" namespace android { namespace hardware { namespace drm { namespace V1_4 { namespace clearkey { namespace drm = ::android::hardware::drm; using drm::V1_0::EventType; using drm::V1_0::IDrmPluginListener; using drm::V1_0::KeyRequestType; using drm::V1_0::KeyStatus; using drm::V1_0::KeyType; using drm::V1_0::KeyValue; using drm::V1_0::SecureStop; using drm::V1_0::SecureStopId; using drm::V1_0::SessionId; using drm::V1_0::Status; using drm::V1_1::DrmMetricGroup; using drm::V1_1::HdcpLevel; using drm::V1_1::SecureStopRelease; using drm::V1_1::SecurityLevel; using drm::V1_2::KeySetId; using drm::V1_2::OfflineLicenseState; using drm::V1_4::clearkey::DeviceFiles; using drm::V1_4::clearkey::Session; using drm::V1_4::clearkey::SessionLibrary; using drm::V1_4::IDrmPlugin; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1; typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2; typedef drm::V1_2::KeyStatus KeyStatus_V1_2; typedef drm::V1_2::Status Status_V1_2; typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2; struct DrmPlugin : public IDrmPlugin { explicit DrmPlugin(SessionLibrary* sessionLibrary); virtual ~DrmPlugin() { mFileHandle.DeleteAllLicenses(); } Return openSession(openSession_cb _hidl_cb) override; Return openSession_1_1(SecurityLevel securityLevel, openSession_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) { if (sessionId.size() == 0) { return Status::BAD_VALUE; } return Status::ERROR_DRM_CANNOT_HANDLE; } 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) { UNUSED(certificateType); UNUSED(certificateAuthority); hidl_string defaultUrl; _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec(), defaultUrl); return Void(); } Return getProvisionRequest_1_2( const hidl_string& certificateType, const hidl_string& certificateAuthority, getProvisionRequest_1_2_cb _hidl_cb) { UNUSED(certificateType); UNUSED(certificateAuthority); hidl_string defaultUrl; _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, hidl_vec(), defaultUrl); return Void(); } Return provideProvisionResponse( const hidl_vec& response, provideProvisionResponse_cb _hidl_cb) { if (response.size() == 0) { _hidl_cb(Status::BAD_VALUE, hidl_vec(), hidl_vec()); return Void(); } _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec(), hidl_vec()); return Void(); } Return getHdcpLevels(getHdcpLevels_cb _hidl_cb) { HdcpLevel connectedLevel = HdcpLevel::HDCP_NONE; HdcpLevel maxLevel = HdcpLevel::HDCP_NO_OUTPUT; _hidl_cb(Status::OK, connectedLevel, maxLevel); return Void(); } Return getHdcpLevels_1_2(getHdcpLevels_1_2_cb _hidl_cb) { HdcpLevel_V1_2 connectedLevel = HdcpLevel_V1_2::HDCP_NONE; HdcpLevel_V1_2 maxLevel = HdcpLevel_V1_2::HDCP_NO_OUTPUT; _hidl_cb(Status_V1_2::OK, connectedLevel, maxLevel); return Void(); } Return getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) override; Return getSecurityLevel(const hidl_vec& sessionId, getSecurityLevel_cb _hidl_cb) override; Return getMetrics(getMetrics_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& name, getPropertyString_cb _hidl_cb) override; Return getPropertyByteArray( const hidl_string& name, getPropertyByteArray_cb _hidl_cb) override; Return setPropertyString( const hidl_string& name, const hidl_string& value) override; Return setPropertyByteArray( const hidl_string& name, const hidl_vec& value) override; Return getLogMessages( getLogMessages_cb _hidl_cb) override; Return setPlaybackId( const hidl_vec& sessionId, const hidl_string& playbackId) override; Return requiresSecureDecoder( const hidl_string& mime, SecurityLevel level) override; Return requiresSecureDecoderDefault(const hidl_string& mime) override; Return setCipherAlgorithm( const hidl_vec& sessionId, const hidl_string& algorithm) { if (sessionId.size() == 0 || algorithm.size() == 0) { return Status::BAD_VALUE; } return Status::ERROR_DRM_CANNOT_HANDLE; } Return setMacAlgorithm( const hidl_vec& sessionId, const hidl_string& algorithm) { if (sessionId.size() == 0 || algorithm.size() == 0) { return Status::BAD_VALUE; } return Status::ERROR_DRM_CANNOT_HANDLE; } Return encrypt( const hidl_vec& sessionId, const hidl_vec& keyId, const hidl_vec& input, const hidl_vec& iv, encrypt_cb _hidl_cb) { if (sessionId.size() == 0 || keyId.size() == 0 || input.size() == 0 || iv.size() == 0) { _hidl_cb(Status::BAD_VALUE, hidl_vec()); return Void(); } _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec()); return Void(); } Return decrypt( const hidl_vec& sessionId, const hidl_vec& keyId, const hidl_vec& input, const hidl_vec& iv, decrypt_cb _hidl_cb) { if (sessionId.size() == 0 || keyId.size() == 0 || input.size() == 0 || iv.size() == 0) { _hidl_cb(Status::BAD_VALUE, hidl_vec()); return Void(); } _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec()); return Void(); } Return sign( const hidl_vec& sessionId, const hidl_vec& keyId, const hidl_vec& message, sign_cb _hidl_cb) { if (sessionId.size() == 0 || keyId.size() == 0 || message.size() == 0) { _hidl_cb(Status::BAD_VALUE, hidl_vec()); return Void(); } _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec()); return Void(); } Return verify( const hidl_vec& sessionId, const hidl_vec& keyId, const hidl_vec& message, const hidl_vec& signature, verify_cb _hidl_cb) { if (sessionId.size() == 0 || keyId.size() == 0 || message.size() == 0 || signature.size() == 0) { _hidl_cb(Status::BAD_VALUE, false); return Void(); } _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, false); return Void(); } Return signRSA( const hidl_vec& sessionId, const hidl_string& algorithm, const hidl_vec& message, const hidl_vec& wrappedKey, signRSA_cb _hidl_cb) { if (sessionId.size() == 0 || algorithm.size() == 0 || message.size() == 0 || wrappedKey.size() == 0) { _hidl_cb(Status::BAD_VALUE, hidl_vec()); return Void(); } _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec()); return Void(); } Return setListener(const sp& listener) { mListener = listener; mListenerV1_2 = IDrmPluginListener_V1_2::castFrom(listener); return Void(); }; Return sendEvent( EventType eventType, const hidl_vec& sessionId, const hidl_vec& data) { if (mListenerV1_2 != NULL) { mListenerV1_2->sendEvent(eventType, sessionId, data); } else if (mListener != NULL) { mListener->sendEvent(eventType, sessionId, data); } else { ALOGE("Null event listener, event not sent"); } return Void(); } Return sendExpirationUpdate( const hidl_vec& sessionId, int64_t expiryTimeInMS) { if (mListenerV1_2 != NULL) { mListenerV1_2->sendExpirationUpdate(sessionId, expiryTimeInMS); } else if (mListener != NULL) { mListener->sendExpirationUpdate(sessionId, expiryTimeInMS); } else { ALOGE("Null event listener, event not sent"); } return Void(); } Return sendKeysChange( const hidl_vec& sessionId, const hidl_vec& keyStatusList, bool hasNewUsableKey) { if (mListenerV1_2 != NULL) { mListenerV1_2->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey); } else if (mListener != NULL) { mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey); } else { ALOGE("Null event listener, event not sent"); } return Void(); } Return sendKeysChange_1_2( const hidl_vec& sessionId, const hidl_vec& keyStatusList, bool hasNewUsableKey) { if (mListenerV1_2 != NULL) { mListenerV1_2->sendKeysChange_1_2(sessionId, keyStatusList, hasNewUsableKey); } return Void(); } Return sendSessionLostState( const hidl_vec& sessionId) { if (mListenerV1_2 != NULL) { mListenerV1_2->sendSessionLostState(sessionId); } return Void(); } Return getSecureStops(getSecureStops_cb _hidl_cb); Return getSecureStop(const hidl_vec& secureStopId, getSecureStop_cb _hidl_cb); Return releaseSecureStop(const hidl_vec& ssRelease); Return releaseAllSecureStops(); Return getSecureStopIds(getSecureStopIds_cb _hidl_cb); Return releaseSecureStops(const SecureStopRelease& ssRelease); Return removeSecureStop(const hidl_vec& secureStopId); Return removeAllSecureStops(); private: void initProperties(); void installSecureStop(const hidl_vec& sessionId); bool makeKeySetId(std::string* keySetId); void setPlayPolicy(); Return setSecurityLevel(const hidl_vec& sessionId, SecurityLevel level); Status_V1_2 getKeyRequestCommon(const hidl_vec& scope, const hidl_vec& initData, const hidl_string& mimeType, KeyType keyType, const hidl_vec& optionalParameters, std::vector *request, KeyRequestType_V1_1 *getKeyRequestType, std::string *defaultUrl); struct ClearkeySecureStop { std::vector id; std::vector data; }; std::map, ClearkeySecureStop> mSecureStops; std::vector mPlayPolicy; std::map mStringProperties; std::map > mByteArrayProperties; std::map > mReleaseKeysMap; std::map, std::string> mPlaybackId; std::map, SecurityLevel> mSecurityLevel; sp mListener; sp mListenerV1_2; SessionLibrary *mSessionLibrary; int64_t mOpenSessionOkCount; int64_t mCloseSessionOkCount; int64_t mCloseSessionNotOpenedCount; uint32_t mNextSecureStopId; android::Mutex mPlayPolicyLock; // set by property to mock error scenarios Status_V1_2 mMockError; void processMockError(const sp &session) { session->setMockError(mMockError); mMockError = Status_V1_2::OK; } DeviceFiles mFileHandle GUARDED_BY(mFileHandleLock); Mutex mFileHandleLock; Mutex mSecureStopLock; CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin); }; } // namespace clearkey } // namespace V1_4 } // namespace drm } // namespace hardware } // namespace android #endif // CLEARKEY_DRM_PLUGIN_H_