/* ** ** Copyright 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 KEYSTORE_KEYMASTER_WORKER_H_ #define KEYSTORE_KEYMASTER_WORKER_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "blob.h" #include "operation.h" namespace keystore { using android::sp; using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; using android::hardware::keymaster::V4_1::support::Keymaster; using ::android::security::keymaster::KeymasterBlob; class KeyStore; class Worker { /* * NonCopyableFunction works similar to std::function in that it wraps callable objects and * erases their type. The rationale for using a custom class instead of * std::function is that std::function requires the wrapped object to be copy contructible. * NonCopyableFunction is itself not copyable and never attempts to copy the wrapped object. * TODO use similar optimization as std::function to remove the extra make_unique allocation. */ template class NonCopyableFunction; template class NonCopyableFunction { class NonCopyableFunctionBase { public: NonCopyableFunctionBase() = default; virtual ~NonCopyableFunctionBase() {} virtual Ret operator()(Args... args) = 0; NonCopyableFunctionBase(const NonCopyableFunctionBase&) = delete; NonCopyableFunctionBase& operator=(const NonCopyableFunctionBase&) = delete; }; template class NonCopyableFunctionTypeEraser : public NonCopyableFunctionBase { private: Fn f_; public: NonCopyableFunctionTypeEraser() = default; explicit NonCopyableFunctionTypeEraser(Fn f) : f_(std::move(f)) {} Ret operator()(Args... args) override { return f_(std::move(args)...); } }; private: std::unique_ptr f_; public: NonCopyableFunction() = default; // NOLINTNEXTLINE(google-explicit-constructor) template NonCopyableFunction(F f) { f_ = std::make_unique>(std::move(f)); } NonCopyableFunction(NonCopyableFunction&& other) = default; NonCopyableFunction& operator=(NonCopyableFunction&& other) = default; NonCopyableFunction(const NonCopyableFunction& other) = delete; NonCopyableFunction& operator=(const NonCopyableFunction& other) = delete; Ret operator()(Args... args) { if (f_) return (*f_)(std::move(args)...); } }; using WorkerTask = NonCopyableFunction; std::queue pending_requests_; std::mutex pending_requests_mutex_; std::condition_variable pending_requests_cond_var_; bool running_ = false; bool terminate_ = false; public: Worker(); ~Worker(); void addRequest(WorkerTask request); }; template struct MakeKeymasterWorkerCB; template struct MakeKeymasterWorkerCB> { using type = std::function...>&&)>; }; template struct MakeKeymasterWorkerCB { using type = std::function; }; template using MakeKeymasterWorkerCB_t = typename MakeKeymasterWorkerCB::type; class KeymasterWorker : protected Worker { private: sp keymasterDevice_; OperationMap operationMap_; KeyStore* keyStore_; template void unwrap_tuple(KMFn kmfn, std::function cb, const std::tuple& tuple, std::index_sequence) { cb(((*keymasterDevice_).*kmfn)(std::get(tuple)...)); } template void unwrap_tuple(KMFn kmfn, std::function&&)> cb, const std::tuple& tuple, std::index_sequence) { std::tuple returnValue; auto result = ((*keymasterDevice_).*kmfn)( std::get(tuple)..., [&returnValue](const ReturnTypes&... args) { returnValue = std::make_tuple(args...); }); cb(std::move(result), std::move(returnValue)); } template void addRequest(KMFn kmfn, std::function cb, Args&&... args) { Worker::addRequest([this, kmfn, cb = std::move(cb), tuple = std::make_tuple(std::forward(args)...)]() { unwrap_tuple(kmfn, std::move(cb), tuple, std::index_sequence_for{}); }); } template void addRequest(KMFn kmfn, std::function&&)> cb, Args&&... args) { Worker::addRequest([this, kmfn, cb = std::move(cb), tuple = std::make_tuple(std::forward(args)...)]() { unwrap_tuple(kmfn, std::move(cb), tuple, std::index_sequence_for{}); }); } void deleteOldKeyOnUpgrade(const LockedKeyBlobEntry& blobfile, Blob keyBlob); std::tuple upgradeKeyBlob(const LockedKeyBlobEntry& lockedEntry, const AuthorizationSet& params); std::tuple createKeyCharacteristicsCache(const LockedKeyBlobEntry& lockedEntry, const hidl_vec& clientId, const hidl_vec& appData, Blob keyBlob, Blob charBlob); /** * Get the auth token for this operation from the auth token table. * * Returns NO_ERROR if the auth token was found or none was required. If not needed, the * token will be empty (which keymaster interprets as no auth token). * OP_AUTH_NEEDED if it is a per op authorization, no authorization token exists for * that operation and failOnTokenMissing is false. * KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth token for the operation */ std::pair getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle, KeyPurpose purpose, bool failOnTokenMissing = true); KeyStoreServiceReturnCode abort(const sp& token); bool pruneOperation(); KeyStoreServiceReturnCode getOperationAuthTokenIfNeeded(std::shared_ptr op); void appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics, hidl_vec* params); public: KeymasterWorker(sp keymasterDevice, KeyStore* keyStore); void logIfKeymasterVendorError(ErrorCode ec) const; using worker_begin_cb = std::function; void begin(LockedKeyBlobEntry, sp appToken, Blob keyBlob, Blob charBlob, bool pruneable, KeyPurpose purpose, AuthorizationSet opParams, hidl_vec entropy, worker_begin_cb worker_cb); using update_cb = std::function; void update(sp token, AuthorizationSet params, hidl_vec data, update_cb _hidl_cb); using finish_cb = std::function; void finish(sp token, AuthorizationSet params, hidl_vec input, hidl_vec signature, hidl_vec entorpy, finish_cb worker_cb); using abort_cb = std::function; void abort(sp token, abort_cb _hidl_cb); using getHardwareInfo_cb = MakeKeymasterWorkerCB_t, Keymaster::getHardwareInfo_cb>; void getHardwareInfo(getHardwareInfo_cb _hidl_cb); using getHmacSharingParameters_cb = MakeKeymasterWorkerCB_t, Keymaster::getHmacSharingParameters_cb>; void getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb); using computeSharedHmac_cb = MakeKeymasterWorkerCB_t, Keymaster::computeSharedHmac_cb>; void computeSharedHmac(hidl_vec params, computeSharedHmac_cb _hidl_cb); using verifyAuthorization_cb = std::function; void verifyAuthorization(uint64_t challenge, hidl_vec params, HardwareAuthToken token, verifyAuthorization_cb _hidl_cb); using addRngEntropy_cb = MakeKeymasterWorkerCB_t>; void addRngEntropy(hidl_vec data, addRngEntropy_cb _hidl_cb); using generateKey_cb = std::function; void generateKey(LockedKeyBlobEntry, hidl_vec keyParams, hidl_vec entropy, int flags, generateKey_cb _hidl_cb); using generateKey2_cb = MakeKeymasterWorkerCB_t, Keymaster::generateKey_cb>; void generateKey(hidl_vec keyParams, generateKey2_cb _hidl_cb); using getKeyCharacteristics_cb = std::function; void getKeyCharacteristics(LockedKeyBlobEntry lockedEntry, hidl_vec clientId, hidl_vec appData, Blob keyBlob, Blob charBlob, getKeyCharacteristics_cb _hidl_cb); using importKey_cb = std::function; void importKey(LockedKeyBlobEntry lockedEntry, hidl_vec params, KeyFormat keyFormat, hidl_vec keyData, int flags, importKey_cb _hidl_cb); using importWrappedKey_cb = std::function; void importWrappedKey(LockedKeyBlobEntry wrappingLockedEntry, LockedKeyBlobEntry wrapppedLockedEntry, hidl_vec wrappedKeyData, hidl_vec maskingKey, hidl_vec unwrappingParams, Blob wrappingBlob, Blob wrappingCharBlob, uint64_t passwordSid, uint64_t biometricSid, importWrappedKey_cb worker_cb); using exportKey_cb = std::function; void exportKey(LockedKeyBlobEntry lockedEntry, KeyFormat exportFormat, hidl_vec clientId, hidl_vec appData, Blob keyBlob, Blob charBlob, exportKey_cb _hidl_cb); using attestKey_cb = MakeKeymasterWorkerCB_t, Keymaster::attestKey_cb>; void attestKey(hidl_vec keyToAttest, hidl_vec attestParams, attestKey_cb _hidl_cb); using deleteKey_cb = MakeKeymasterWorkerCB_t>; void deleteKey(hidl_vec keyBlob, deleteKey_cb _hidl_cb); using begin_cb = MakeKeymasterWorkerCB_t, Keymaster::begin_cb>; void begin(KeyPurpose purpose, hidl_vec key, hidl_vec inParams, HardwareAuthToken authToken, begin_cb _hidl_cb); void binderDied(android::wp who); const Keymaster::VersionResult& halVersion() { return keymasterDevice_->halVersion(); } }; } // namespace keystore #endif // KEYSTORE_KEYMASTER_WORKER_H_