From 2437fde7a69f867430b617c972ec5121b8d320bf Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Mon, 8 Mar 2021 11:30:11 -0800 Subject: Keystore 2.0: Remove Keystore 1.0 and remaining references * Remove superseded keystore engine backends. * Remove keystore_cli. * Update keystoer_cli_v2 to use Keystore 2.0. * Update confirmationui invocation test. * Remove reference to enable keystore2 property from keystore2.rc. Test: N/A Bug: 171305684 Change-Id: I855dead9d95c2c8cfa451944087bc8290871c0e5 --- keystore/Android.bp | 251 +--- keystore/KeyStore.cpp | 512 ------- keystore/KeyStore.h | 200 --- keystore/KeymasterArguments.cpp | 45 - keystore/KeystoreResponse.cpp | 43 - keystore/OperationResult.cpp | 66 - keystore/auth_token_table.cpp | 302 ---- keystore/auth_token_table.h | 177 --- .../security/IConfirmationPromptCallback.aidl | 27 - .../android/security/keymaster/ExportResult.aidl | 20 - .../security/keymaster/KeyCharacteristics.aidl | 20 - .../security/keymaster/KeymasterArguments.aidl | 20 - .../android/security/keymaster/KeymasterBlob.aidl | 20 - .../keymaster/KeymasterCertificateChain.aidl | 20 - .../security/keymaster/OperationResult.aidl | 20 - .../security/keystore/ICredstoreTokenCallback.aidl | 25 - .../IKeystoreCertificateChainCallback.aidl | 27 - .../keystore/IKeystoreExportKeyCallback.aidl | 27 - .../IKeystoreKeyCharacteristicsCallback.aidl | 27 - .../keystore/IKeystoreOperationResultCallback.aidl | 28 - .../keystore/IKeystoreResponseCallback.aidl | 26 - .../security/keystore/IKeystoreService.aidl | 106 -- .../security/keystore/KeystoreResponse.aidl | 20 - keystore/blob.cpp | 791 ----------- keystore/blob.h | 285 ---- keystore/confirmation_manager.cpp | 214 --- keystore/confirmation_manager.h | 108 -- keystore/confirmationui_rate_limiting.h | 134 -- keystore/defaults.h | 42 - keystore/grant_store.cpp | 106 -- keystore/grant_store.h | 83 -- keystore/key_attestation_log_handler.cpp | 29 - keystore/key_attestation_log_handler.h | 26 - keystore/key_creation_log_handler.cpp | 211 --- keystore/key_creation_log_handler.h | 71 - keystore/key_operation_log_handler.cpp | 136 -- keystore/key_operation_log_handler.h | 28 - keystore/key_store_service.cpp | 1480 -------------------- keystore/key_store_service.h | 240 ---- keystore/keyblob_utils.cpp | 65 - keystore/keymaster_enforcement.cpp | 555 -------- keystore/keymaster_enforcement.h | 213 --- keystore/keymaster_worker.cpp | 1144 --------------- keystore/keymaster_worker.h | 307 ---- keystore/keystore.rc | 5 - keystore/keystore_aidl_hidl_marshalling_utils.cpp | 257 ---- keystore/keystore_aidl_hidl_marshalling_utils.h | 79 -- keystore/keystore_cli.cpp | 248 ---- keystore/keystore_cli_v2.cpp | 1069 ++++++++++---- keystore/keystore_client_impl.cpp | 629 --------- keystore/keystore_main.cpp | 162 --- keystore/legacy_keymaster_device_wrapper.cpp | 547 -------- keystore/legacy_keymaster_device_wrapper.h | 90 -- keystore/operation.cpp | 103 -- keystore/operation.h | 77 - keystore/operation_struct.h | 65 - keystore/permissions.cpp | 213 --- keystore/permissions.h | 117 -- keystore/tests/Android.bp | 12 +- keystore/tests/confirmationui_invocation_test.cpp | 70 +- 60 files changed, 804 insertions(+), 11236 deletions(-) delete mode 100644 keystore/KeyStore.cpp delete mode 100644 keystore/KeyStore.h delete mode 100644 keystore/KeymasterArguments.cpp delete mode 100644 keystore/KeystoreResponse.cpp delete mode 100644 keystore/OperationResult.cpp delete mode 100644 keystore/auth_token_table.cpp delete mode 100644 keystore/auth_token_table.h delete mode 100644 keystore/binder/android/security/IConfirmationPromptCallback.aidl delete mode 100644 keystore/binder/android/security/keymaster/ExportResult.aidl delete mode 100644 keystore/binder/android/security/keymaster/KeyCharacteristics.aidl delete mode 100644 keystore/binder/android/security/keymaster/KeymasterArguments.aidl delete mode 100644 keystore/binder/android/security/keymaster/KeymasterBlob.aidl delete mode 100644 keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl delete mode 100644 keystore/binder/android/security/keymaster/OperationResult.aidl delete mode 100644 keystore/binder/android/security/keystore/ICredstoreTokenCallback.aidl delete mode 100644 keystore/binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl delete mode 100644 keystore/binder/android/security/keystore/IKeystoreExportKeyCallback.aidl delete mode 100644 keystore/binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl delete mode 100644 keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl delete mode 100644 keystore/binder/android/security/keystore/IKeystoreResponseCallback.aidl delete mode 100644 keystore/binder/android/security/keystore/IKeystoreService.aidl delete mode 100644 keystore/binder/android/security/keystore/KeystoreResponse.aidl delete mode 100644 keystore/blob.cpp delete mode 100644 keystore/blob.h delete mode 100644 keystore/confirmation_manager.cpp delete mode 100644 keystore/confirmation_manager.h delete mode 100644 keystore/confirmationui_rate_limiting.h delete mode 100644 keystore/defaults.h delete mode 100644 keystore/grant_store.cpp delete mode 100644 keystore/grant_store.h delete mode 100644 keystore/key_attestation_log_handler.cpp delete mode 100644 keystore/key_attestation_log_handler.h delete mode 100644 keystore/key_creation_log_handler.cpp delete mode 100644 keystore/key_creation_log_handler.h delete mode 100644 keystore/key_operation_log_handler.cpp delete mode 100644 keystore/key_operation_log_handler.h delete mode 100644 keystore/key_store_service.cpp delete mode 100644 keystore/key_store_service.h delete mode 100644 keystore/keyblob_utils.cpp delete mode 100644 keystore/keymaster_enforcement.cpp delete mode 100644 keystore/keymaster_enforcement.h delete mode 100644 keystore/keymaster_worker.cpp delete mode 100644 keystore/keymaster_worker.h delete mode 100644 keystore/keystore.rc delete mode 100644 keystore/keystore_aidl_hidl_marshalling_utils.cpp delete mode 100644 keystore/keystore_aidl_hidl_marshalling_utils.h delete mode 100644 keystore/keystore_cli.cpp delete mode 100644 keystore/keystore_client_impl.cpp delete mode 100644 keystore/keystore_main.cpp delete mode 100644 keystore/legacy_keymaster_device_wrapper.cpp delete mode 100644 keystore/legacy_keymaster_device_wrapper.h delete mode 100644 keystore/operation.cpp delete mode 100644 keystore/operation.h delete mode 100644 keystore/operation_struct.h delete mode 100644 keystore/permissions.cpp delete mode 100644 keystore/permissions.h (limited to 'keystore') diff --git a/keystore/Android.bp b/keystore/Android.bp index 7278cee6..0f2000cd 100644 --- a/keystore/Android.bp +++ b/keystore/Android.bp @@ -34,97 +34,6 @@ cc_defaults { clang: true, } -cc_binary { - name: "keystore", - defaults: ["keystore_defaults"], - - srcs: [ - "KeyStore.cpp", - "auth_token_table.cpp", - "blob.cpp", - "confirmation_manager.cpp", - "grant_store.cpp", - "key_creation_log_handler.cpp", - "key_operation_log_handler.cpp", - "key_attestation_log_handler.cpp", - "key_store_service.cpp", - "keyblob_utils.cpp", - "keymaster_enforcement.cpp", - "keymaster_worker.cpp", - "keystore_main.cpp", - "keystore_utils.cpp", - "legacy_keymaster_device_wrapper.cpp", - "operation.cpp", - "permissions.cpp", - "user_state.cpp", - ], - shared_libs: [ - "android.hardware.confirmationui@1.0", - "android.hardware.keymaster@3.0", - "android.hardware.keymaster@4.0", - "android.hardware.keymaster@4.1", - "libbase", - "libbinder", - "libcrypto", - "libcutils", - "libhardware", - "libhidlbase", - "libkeymaster4support", - "libkeymaster4_1support", - "libkeymaster_messages", - "libkeymaster_portable", - "libkeystore-attestation-application-id", - "libkeystore_aidl", - "libkeystore_binder", - "libkeystore_parcelables", - "liblog", - "libprotobuf-cpp-lite", - "libselinux", - "libservices", - "libsoftkeymasterdevice", - "libutils", - "libstatslog", - ], - init_rc: ["keystore.rc"], - aidl: { - include_dirs: ["frameworks/base/core/java/"], - }, - - product_variables: { - pdk: { - enabled: false, - }, - debuggable: { - cflags: [ - // Allow VTS tests running as root to have - // additional permissions. - "-DGRANT_ROOT_ALL_PERMISSIONS", - ], - }, - }, - - required: ["keystore_cli_v2"], -} - -cc_binary { - name: "keystore_cli", - defaults: ["keystore_defaults"], - - srcs: ["keystore_cli.cpp"], - shared_libs: [ - "android.hardware.keymaster@4.0", - "libbinder", - "libcrypto", - "libcutils", - "libhidlbase", - "libkeystore_aidl", // for IKeyStoreService.asInterface() - "libkeystore_binder", - "libkeystore_parcelables", - "liblog", - "libutils", - ], -} - cc_binary { name: "keystore_cli_v2", defaults: ["keystore_defaults"], @@ -133,93 +42,23 @@ cc_binary { "-DKEYMASTER_NAME_TAGS", "-Wno-unused-parameter", ], - srcs: ["keystore_cli_v2.cpp"], - shared_libs: [ - "android.hardware.confirmationui@1.0", - "libbinder", - "android.hardware.keymaster@4.0", - "libchrome", - "libutils", - "libhidlbase", - "libkeymaster4support", - "libkeystore_aidl", - "libkeystore_binder", - "libkeystore_parcelables", - ], - - local_include_dirs: ["include"], -} - -cc_library_shared { - name: "libkeystore_parcelables", - defaults: ["keystore_defaults"], - export_include_dirs: ["include"], - srcs: [ - "KeymasterArguments.cpp", - "keystore_aidl_hidl_marshalling_utils.cpp", - "KeystoreResponse.cpp", - "OperationResult.cpp", - ], - shared_libs: [ - "android.hardware.keymaster@4.0", - "android.hardware.keymaster@4.1", - "libbinder", - "libhardware", - "libhidlbase", - "libkeymaster4support", - "libkeymaster4_1support", - "liblog", - "libprotobuf-cpp-lite", - "libutils", - "libkeystore-attestation-application-id", - ], - export_shared_lib_headers: [ - "android.hardware.keymaster@4.0", - "android.hardware.keymaster@4.1", - "libbinder", - "libhidlbase", - "libkeymaster4_1support", - ], -} -// Library for keystore clients -cc_library_shared { - name: "libkeystore_binder", - defaults: ["keystore_defaults"], - srcs: [ - "keyblob_utils.cpp", + "keystore_cli_v2.cpp", "keystore_client.proto", - "keystore_client_impl.cpp", - "keystore_get.cpp", ], shared_libs: [ - "android.hardware.keymaster@4.0", + "android.security.apc-ndk_platform", + "android.system.keystore2-V1-ndk_platform", "libbinder", - "libhidlbase", - "libkeymaster4support", - "libkeystore_aidl", - "libkeystore_parcelables", - "liblog", + "libbinder_ndk", + "libchrome", + "libcrypto", + "libkeymint_support", "libprotobuf-cpp-lite", "libutils", ], - proto: { - type: "lite", - export_proto_headers: true, - }, - aidl: { - export_aidl_headers: true, - include_dirs: ["frameworks/base/core/java/"], - }, - export_include_dirs: ["include"], - export_shared_lib_headers: [ - "android.hardware.keymaster@4.0", - "libbinder", - "libhidlbase", - "libkeystore_aidl", - "libkeystore_parcelables", - ], + local_include_dirs: ["include"], } // Library used by both keystore and credstore for generating the ASN.1 stored @@ -265,77 +104,3 @@ cc_library_shared { vendor: true, } - -// Library for unit tests -cc_library_static { - name: "libkeystore_test", - defaults: ["keystore_defaults"], - - srcs: [ - "auth_token_table.cpp", - "blob.cpp", - ], - cflags: [ "-O0", ], - static_libs: ["libgtest_main"], - shared_libs: [ - "android.hardware.keymaster@4.0", - "libbinder", - "libcrypto", - "libhidlbase", - "libkeymaster4support", - "libkeystore-attestation-application-id", - "libutils", - "libkeystore_aidl", - "libkeystore_parcelables", - ], - export_shared_lib_headers: [ - "android.hardware.keymaster@4.0", - "libhidlbase", - "libkeymaster4support", - ], - - aidl: { - include_dirs: ["frameworks/base/core/java/"], - }, - export_include_dirs: ["include"], -} - -filegroup { - name: "keystore_aidl", - srcs: [ - "binder/android/security/IConfirmationPromptCallback.aidl", - "binder/android/security/keystore/ICredstoreTokenCallback.aidl", - "binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl", - "binder/android/security/keystore/IKeystoreExportKeyCallback.aidl", - "binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl", - "binder/android/security/keystore/IKeystoreOperationResultCallback.aidl", - "binder/android/security/keystore/IKeystoreResponseCallback.aidl", - "binder/android/security/keystore/IKeystoreService.aidl", - ], - path: "binder", -} - -cc_library_shared { - name: "libkeystore_aidl", - srcs: [":keystore_aidl"], - aidl: { - export_aidl_headers: true, - include_dirs: [ - "system/security/keystore/binder", - ], - }, - shared_libs: [ - "libbinder", - "libcutils", - "libhardware", - "libhidlbase", - "libkeystore_parcelables", - "liblog", - "libselinux", - "libutils", - ], - export_shared_lib_headers: [ - "libbinder", - "libkeystore_parcelables", - ], -} diff --git a/keystore/KeyStore.cpp b/keystore/KeyStore.cpp deleted file mode 100644 index 1f808997..00000000 --- a/keystore/KeyStore.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#define LOG_TAG "keystore" - -#include "KeyStore.h" - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include "keystore_utils.h" -#include "permissions.h" -#include - -#include "keymaster_worker.h" - -namespace keystore { - -const char* KeyStore::kOldMasterKey = ".masterkey"; -const char* KeyStore::kMetaDataFile = ".metadata"; - -const android::String16 KeyStore::kRsaKeyType("RSA"); -const android::String16 KeyStore::kEcKeyType("EC"); - -using android::String8; - -KeyStore::KeyStore(const KeymasterDevices& kmDevices, - SecurityLevel minimalAllowedSecurityLevelForNewKeys) - : mAllowNewFallback(minimalAllowedSecurityLevelForNewKeys == SecurityLevel::SOFTWARE), - mConfirmationManager(new ConfirmationManager(this)) { - memset(&mMetaData, '\0', sizeof(mMetaData)); - - static_assert(std::tuple_size>::value == - std::tuple_size::value, - "KmasterDevices and KeymasterWorkers must have the same size"); - for (size_t i = 0; i < kmDevices.size(); ++i) { - if (kmDevices[SecurityLevel(i)]) { - mKmDevices[SecurityLevel(i)] = std::make_shared( - kmDevices[SecurityLevel(i)], this, SecurityLevel(i)); - } - } -} - -KeyStore::~KeyStore() { -} - -ResponseCode KeyStore::initialize() { - readMetaData(); - if (upgradeKeystore()) { - writeMetaData(); - } - - return ResponseCode::NO_ERROR; -} - -ResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) { - auto userState = mUserStateDB.getUserState(userId); - return userState->initialize(pw); -} - -ResponseCode KeyStore::copyMasterKey(uid_t srcUser, uid_t dstUser) { - auto userState = mUserStateDB.getUserState(dstUser); - auto initState = mUserStateDB.getUserState(srcUser); - return userState->copyMasterKey(&initState); -} - -ResponseCode KeyStore::writeMasterKey(const android::String8& pw, uid_t userId) { - auto userState = mUserStateDB.getUserState(userId); - return userState->writeMasterKey(pw); -} - -ResponseCode KeyStore::readMasterKey(const android::String8& pw, uid_t userId) { - auto userState = mUserStateDB.getUserState(userId); - return userState->readMasterKey(pw); -} - -LockedKeyBlobEntry KeyStore::getLockedBlobEntryIfNotExists(const std::string& alias, uid_t uid) { - KeyBlobEntry kbe(alias, mUserStateDB.getUserStateByUid(uid)->getUserDirName(), uid); - auto result = LockedKeyBlobEntry::get(std::move(kbe)); - if (result->hasKeyBlob()) return {}; - return result; -} - -std::optional KeyStore::getBlobEntryIfExists(const std::string& alias, uid_t uid) { - KeyBlobEntry kbe(alias, mUserStateDB.getUserStateByUid(uid)->getUserDirName(), uid); - if (kbe.hasKeyBlob()) return kbe; - - // If this is one of the legacy UID->UID mappings, use it. - uid_t euid = get_keystore_euid(uid); - if (euid != uid) { - kbe = KeyBlobEntry(alias, mUserStateDB.getUserStateByUid(euid)->getUserDirName(), euid); - if (kbe.hasKeyBlob()) return kbe; - } - - // They might be using a granted key. - auto grant = mGrants.get(uid, alias); - if (grant) { - kbe = grant->entry_; - if (kbe.hasKeyBlob()) return kbe; - } - return {}; -} -LockedKeyBlobEntry KeyStore::getLockedBlobEntryIfExists(const std::string& alias, uid_t uid) { - auto blobentry = getBlobEntryIfExists(alias, uid); - if (!blobentry) return {}; - LockedKeyBlobEntry lockedentry = LockedKeyBlobEntry::get(std::move(*blobentry)); - if (!lockedentry || !lockedentry->hasKeyBlob()) return {}; - return lockedentry; -} - -void KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) { - android::String8 prefix(""); - android::Vector aliases; - - auto userState = mUserStateDB.getUserState(userId); - std::string userDirName = userState->getUserDirName(); - auto encryptionKey = userState->getEncryptionKey(); - auto state = userState->getState(); - // userState is a proxy that holds a lock which may be required by a worker. - // LockedKeyBlobEntry::list has a fence that waits until all workers have finished which may - // not happen if a user state lock is held. The following line relinquishes the lock. - userState = {}; - - ResponseCode rc; - std::list matches; - - // must not be called by a keymaster worker. List waits for workers to relinquish all access - // to blob entries - std::tie(rc, matches) = LockedKeyBlobEntry::list(userDirName); - if (rc != ResponseCode::NO_ERROR) { - return; - } - - for (LockedKeyBlobEntry& lockedEntry : matches) { - bool shouldDelete = true; - - if (keepUnenryptedEntries) { - Blob blob; - Blob charBlob; - ResponseCode rc; - - std::tie(rc, blob, charBlob) = lockedEntry.readBlobs(encryptionKey, state); - - switch (rc) { - case ResponseCode::SYSTEM_ERROR: - case ResponseCode::VALUE_CORRUPTED: - // If we can't read blobs, delete them. - shouldDelete = true; - break; - - case ResponseCode::NO_ERROR: - case ResponseCode::LOCKED: - // Delete encrypted blobs but keep unencrypted blobs and super-encrypted blobs. We - // need to keep super-encrypted blobs so we can report that the user is - // unauthenticated if a caller tries to use them, rather than reporting that they - // don't exist. - shouldDelete = blob.isEncrypted(); - break; - - default: - ALOGE("Got unexpected return code %d from readBlobs", rc); - // This shouldn't happen. To be on the safe side, delete it. - shouldDelete = true; - break; - } - } - if (shouldDelete) { - del(lockedEntry); - } - } - - userState = mUserStateDB.getUserState(userId); - if (!userState->deleteMasterKey()) { - ALOGE("Failed to delete user %d's master key", userId); - } - if (!keepUnenryptedEntries) { - if (!userState->reset()) { - ALOGE("Failed to remove user %d's directory", userId); - } - } -} - -bool KeyStore::isEmpty(uid_t userId) const { - std::string userDirName; - { - // userState holds a lock which must be relinquished before list is called. This scope - // prevents deadlocks. - auto userState = mUserStateDB.getUserState(userId); - if (!userState) { - return true; - } - userDirName = userState->getUserDirName(); - } - - ResponseCode rc; - std::list matches; - - // must not be called by a keymaster worker. List waits for workers to relinquish all access - // to blob entries - std::tie(rc, matches) = LockedKeyBlobEntry::list(userDirName); - - return rc == ResponseCode::SYSTEM_ERROR || matches.size() == 0; -} - -void KeyStore::lock(uid_t userId) { - auto userState = mUserStateDB.getUserState(userId); - userState->zeroizeMasterKeysInMemory(); - userState->setState(STATE_LOCKED); -} - -static void maybeLogKeyIntegrityViolation(const LockedKeyBlobEntry& lockedEntry, - const BlobType type) { - if (!__android_log_security() || (type != TYPE_KEY_PAIR && type != TYPE_KEYMASTER_10)) return; - log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid()); -} - -std::tuple KeyStore::get(const LockedKeyBlobEntry& blobfile) { - std::tuple result; - - uid_t userId = get_user_id(blobfile->uid()); - Blob& keyBlob = std::get<1>(result); - ResponseCode& rc = std::get<0>(result); - - auto userState = mUserStateDB.getUserState(userId); - BlobType type = BlobType::TYPE_ANY; - auto logOnScopeExit = android::base::make_scope_guard([&] { - if (rc == ResponseCode::VALUE_CORRUPTED) { - maybeLogKeyIntegrityViolation(blobfile, type); - } - }); - - result = blobfile.readBlobs(userState->getEncryptionKey(), userState->getState()); - if (rc != ResponseCode::NO_ERROR) { - return result; - } - - // update the type for logging (see scope_guard above) - type = keyBlob.getType(); - - const uint8_t version = keyBlob.getVersion(); - if (version < CURRENT_BLOB_VERSION) { - /* If we upgrade the key, we need to write it to disk again. Then - * it must be read it again since the blob is encrypted each time - * it's written. - */ - if (upgradeBlob(&keyBlob, version)) { - if ((rc = this->put(blobfile, keyBlob, {})) != ResponseCode::NO_ERROR || - (result = blobfile.readBlobs(userState->getEncryptionKey(), userState->getState()), - rc) != ResponseCode::NO_ERROR) { - return result; - } - } - } - - return result; -} - -ResponseCode KeyStore::put(const LockedKeyBlobEntry& blobfile, Blob keyBlob, - Blob characteristicsBlob) { - auto userState = mUserStateDB.getUserStateByUid(blobfile->uid()); - return blobfile.writeBlobs(std::move(keyBlob), std::move(characteristicsBlob), - userState->getEncryptionKey(), userState->getState()); -} - -ResponseCode KeyStore::del(const LockedKeyBlobEntry& blobfile) { - Blob keyBlob; - Blob charactaristicsBlob; - ResponseCode rc; - uid_t uid = blobfile->uid(); - std::string alias = blobfile->alias(); - - std::tie(rc, keyBlob, charactaristicsBlob) = get(blobfile); - - // after getting the blob from the file system we scrub the filesystem. - mGrants.removeAllGrantsToKey(uid, alias); - auto result = blobfile.deleteBlobs(); - - if (rc != ResponseCode::NO_ERROR) { - LOG(ERROR) << "get keyblob failed " << int(rc); - return rc; - } - - // if we got the blob successfully, we try and delete it from the keymaster device - auto dev = getDevice(keyBlob); - - if (keyBlob.getType() == ::TYPE_KEYMASTER_10) { - dev->deleteKey(blob2hidlVec(keyBlob), [dev, alias, uid](Return rc) { - auto ret = KS_HANDLE_HIDL_ERROR(dev, rc); - // A device doesn't have to implement delete_key. - bool success = ret == ErrorCode::OK || ret == ErrorCode::UNIMPLEMENTED; - if (__android_log_security()) { - android_log_event_list(SEC_TAG_KEY_DESTROYED) - << int32_t(success) << alias << int32_t(uid) << LOG_ID_SECURITY; - } - if (!success) { - LOG(ERROR) << "Keymaster delete for key " << alias << " of uid " << uid - << " failed"; - } - }); - } - - return result; -} - -std::string KeyStore::addGrant(const LockedKeyBlobEntry& blobfile, uid_t granteeUid) { - return mGrants.put(granteeUid, blobfile); -} - -bool KeyStore::removeGrant(const LockedKeyBlobEntry& blobfile, const uid_t granteeUid) { - return mGrants.removeByFileAlias(granteeUid, blobfile); -} -void KeyStore::removeAllGrantsToUid(const uid_t granteeUid) { - mGrants.removeAllGrantsToUid(granteeUid); -} - -bool KeyStore::isHardwareBacked(const android::String16& keyType) const { - // if strongbox device is present TEE must also be present and of sufficiently high version - // to support all keys in hardware - if (getDevice(SecurityLevel::STRONGBOX)) return true; - if (!getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)) { - ALOGW("can't get keymaster device"); - return false; - } - - auto version = getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)->halVersion(); - if (keyType == kRsaKeyType) return true; // All versions support RSA - return keyType == kEcKeyType && version.supportsEc; -} - -std::tuple -KeyStore::getKeyForName(const android::String8& keyName, const uid_t uid, const BlobType type) { - std::tuple result; - auto& [rc, keyBlob, charBlob, lockedEntry] = result; - - lockedEntry = getLockedBlobEntryIfExists(keyName.string(), uid); - - if (!lockedEntry) return rc = ResponseCode::KEY_NOT_FOUND, std::move(result); - - std::tie(rc, keyBlob, charBlob) = get(lockedEntry); - - if (rc == ResponseCode::NO_ERROR) { - if (keyBlob.getType() != type) return rc = ResponseCode::KEY_NOT_FOUND, std::move(result); - } - return result; -} - -bool KeyStore::upgradeBlob(Blob* blob, const uint8_t oldVersion) { - bool updated = false; - uint8_t version = oldVersion; - - if (!blob || !(*blob)) return false; - - /* From V0 -> V1: All old types were unknown */ - if (version == 0) { - ALOGE("Failed to upgrade key blob. Ancient blob version 0 is no longer supported"); - - return false; - } - - /* From V1 -> V2: All old keys were encrypted */ - if (version == 1) { - ALOGV("upgrading to version 2"); - - blob->setEncrypted(true); - version = 2; - updated = true; - } - - /* - * If we've updated, set the key blob to the right version - * and write it. - */ - if (updated) { - blob->setVersion(version); - } - - return updated; -} - -void KeyStore::readMetaData() { - int in = TEMP_FAILURE_RETRY(open(kMetaDataFile, O_RDONLY)); - if (in < 0) { - return; - } - size_t fileLength = readFully(in, (uint8_t*)&mMetaData, sizeof(mMetaData)); - if (fileLength != sizeof(mMetaData)) { - ALOGI("Metadata file is %zd bytes (%zd experted); upgrade?", fileLength, sizeof(mMetaData)); - } - close(in); -} - -void KeyStore::writeMetaData() { - const char* tmpFileName = ".metadata.tmp"; - int out = - TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)); - if (out < 0) { - ALOGE("couldn't write metadata file: %s", strerror(errno)); - return; - } - size_t fileLength = writeFully(out, (uint8_t*)&mMetaData, sizeof(mMetaData)); - if (fileLength != sizeof(mMetaData)) { - ALOGI("Could only write %zd bytes to metadata file (%zd expected)", fileLength, - sizeof(mMetaData)); - } - close(out); - rename(tmpFileName, kMetaDataFile); -} - -bool KeyStore::upgradeKeystore() { - bool upgraded = false; - - if (mMetaData.version == 0) { - auto userState = getUserStateDB().getUserStateByUid(0); - - // Initialize first so the directory is made. - userState->initialize(); - - // Migrate the old .masterkey file to user 0. - if (access(kOldMasterKey, R_OK) == 0) { - if (rename(kOldMasterKey, userState->getMasterKeyFileName().c_str()) < 0) { - ALOGE("couldn't migrate old masterkey: %s", strerror(errno)); - return false; - } - } - - // Initialize again in case we had a key. - userState->initialize(); - - // Try to migrate existing keys. - DIR* dir = opendir("."); - if (!dir) { - // Give up now; maybe we can upgrade later. - ALOGE("couldn't open keystore's directory; something is wrong"); - return false; - } - - struct dirent* file; - while ((file = readdir(dir)) != nullptr) { - // We only care about files. - if (file->d_type != DT_REG) { - continue; - } - - // Skip anything that starts with a "." - if (file->d_name[0] == '.') { - continue; - } - - // Find the current file's user. - char* end; - unsigned long thisUid = strtoul(file->d_name, &end, 10); - if (end[0] != '_' || end[1] == 0) { - continue; - } - auto otherUser = getUserStateDB().getUserStateByUid(thisUid); - if (otherUser->getUserId() != 0) { - unlinkat(dirfd(dir), file->d_name, 0); - } - - // Rename the file into user directory. - DIR* otherdir = opendir(otherUser->getUserDirName().c_str()); - if (otherdir == nullptr) { - ALOGW("couldn't open user directory for rename"); - continue; - } - if (renameat(dirfd(dir), file->d_name, dirfd(otherdir), file->d_name) < 0) { - ALOGW("couldn't rename blob: %s: %s", file->d_name, strerror(errno)); - } - closedir(otherdir); - } - closedir(dir); - - mMetaData.version = 1; - upgraded = true; - } - - return upgraded; -} - -void KeyStore::binderDied(const ::android::wp& who) { - for (unsigned i = 0; i < mKmDevices.size(); ++i) { - if (mKmDevices[SecurityLevel(i)]) mKmDevices[SecurityLevel(i)]->binderDied(who); - } - getConfirmationManager().binderDied(who); -} - -} // namespace keystore diff --git a/keystore/KeyStore.h b/keystore/KeyStore.h deleted file mode 100644 index 7841a800..00000000 --- a/keystore/KeyStore.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2016 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_KEYSTORE_H_ -#define KEYSTORE_KEYSTORE_H_ - -#include -#include -#include - -#include - -#include "auth_token_table.h" -#include "blob.h" -#include "confirmation_manager.h" -#include "grant_store.h" -#include "keymaster_worker.h" -#include "keystore_keymaster_enforcement.h" -#include "operation.h" -#include "user_state.h" - -#include -#include -#include - -namespace keystore { - -using ::android::sp; -using keymaster::support::Keymaster; - -template class Devices : public std::array { - public: - T& operator[](SecurityLevel secLevel) { - static_assert(uint32_t(SecurityLevel::SOFTWARE) == 0 && - uint32_t(SecurityLevel::TRUSTED_ENVIRONMENT) == 1 && - uint32_t(SecurityLevel::STRONGBOX) == 2, - "Numeric values of security levels have changed"); - return std::array::at(static_cast(secLevel)); - } - T operator[](SecurityLevel secLevel) const { - if (static_cast(secLevel) > static_cast(SecurityLevel::STRONGBOX)) { - LOG(ERROR) << "Invalid security level requested"; - return {}; - } - return (*const_cast(this))[secLevel]; - } -}; - -} // namespace keystore - -namespace std { -template struct tuple_size> { - public: - static constexpr size_t value = std::tuple_size>::value; -}; -} // namespace std - -namespace keystore { - -using KeymasterWorkers = Devices, 3>; -using KeymasterDevices = Devices, 3>; - -class KeyStore : public ::android::IBinder::DeathRecipient { - public: - KeyStore(const KeymasterDevices& kmDevices, - SecurityLevel minimalAllowedSecurityLevelForNewKeys); - ~KeyStore(); - - std::shared_ptr getDevice(SecurityLevel securityLevel) const { - return mKmDevices[securityLevel]; - } - - std::shared_ptr getFallbackDevice() const { - // we only return the fallback device if the creation of new fallback key blobs is - // allowed. (also see getDevice below) - if (mAllowNewFallback) { - return mKmDevices[SecurityLevel::SOFTWARE]; - } else { - return nullptr; - } - } - - std::shared_ptr getDevice(const Blob& blob) { - return mKmDevices[blob.getSecurityLevel()]; - } - - ResponseCode initialize(); - - State getState(uid_t userId) { return mUserStateDB.getUserState(userId)->getState(); } - - ResponseCode initializeUser(const android::String8& pw, uid_t userId); - - ResponseCode copyMasterKey(uid_t srcUser, uid_t dstUser); - ResponseCode writeMasterKey(const android::String8& pw, uid_t userId); - ResponseCode readMasterKey(const android::String8& pw, uid_t userId); - - LockedKeyBlobEntry getLockedBlobEntryIfNotExists(const std::string& alias, uid_t uid); - std::optional getBlobEntryIfExists(const std::string& alias, uid_t uid); - LockedKeyBlobEntry getLockedBlobEntryIfExists(const std::string& alias, uid_t uid); - /* - * Delete entries owned by userId. If keepUnencryptedEntries is true - * then only encrypted entries will be removed, otherwise all entries will - * be removed. - */ - void resetUser(uid_t userId, bool keepUnenryptedEntries); - bool isEmpty(uid_t userId) const; - - void lock(uid_t userId); - - std::tuple get(const LockedKeyBlobEntry& blobfile); - ResponseCode put(const LockedKeyBlobEntry& blobfile, Blob keyBlob, Blob characteristicsBlob); - ResponseCode del(const LockedKeyBlobEntry& blobfile); - - std::string addGrant(const LockedKeyBlobEntry& blobfile, uid_t granteeUid); - bool removeGrant(const LockedKeyBlobEntry& blobfile, const uid_t granteeUid); - void removeAllGrantsToUid(const uid_t granteeUid); - - ResponseCode importKey(const uint8_t* key, size_t keyLen, const LockedKeyBlobEntry& blobfile, - uid_t userId, int32_t flags); - - bool isHardwareBacked(const android::String16& keyType) const; - - std::tuple - getKeyForName(const android::String8& keyName, const uid_t uid, const BlobType type); - - void binderDied(const ::android::wp& who) override; - - UserStateDB& getUserStateDB() { return mUserStateDB; } - AuthTokenTable& getAuthTokenTable() { return mAuthTokenTable; } - KeystoreKeymasterEnforcement& getEnforcementPolicy() { return mEnforcementPolicy; } - ConfirmationManager& getConfirmationManager() { return *mConfirmationManager; } - - void addOperationDevice(sp token, std::shared_ptr dev) { - std::lock_guard lock(operationDeviceMapMutex_); - operationDeviceMap_.emplace(std::move(token), std::move(dev)); - } - std::shared_ptr getOperationDevice(const sp& token) { - std::lock_guard lock(operationDeviceMapMutex_); - auto it = operationDeviceMap_.find(token); - if (it != operationDeviceMap_.end()) { - return it->second; - } - return {}; - } - void removeOperationDevice(const sp& token) { - std::lock_guard lock(operationDeviceMapMutex_); - operationDeviceMap_.erase(token); - } - - private: - static const char* kOldMasterKey; - static const char* kMetaDataFile; - static const android::String16 kRsaKeyType; - static const android::String16 kEcKeyType; - - KeymasterWorkers mKmDevices; - - bool mAllowNewFallback; - - UserStateDB mUserStateDB; - AuthTokenTable mAuthTokenTable; - KeystoreKeymasterEnforcement mEnforcementPolicy; - sp mConfirmationManager; - - ::keystore::GrantStore mGrants; - - typedef struct { uint32_t version; } keystore_metadata_t; - - keystore_metadata_t mMetaData; - - /** - * Upgrade the key from the current version to whatever is newest. - */ - bool upgradeBlob(Blob* blob, const uint8_t oldVersion); - - void readMetaData(); - void writeMetaData(); - - bool upgradeKeystore(); - - std::mutex operationDeviceMapMutex_; - std::map, std::shared_ptr> operationDeviceMap_; -}; - -} // namespace keystore - -#endif // KEYSTORE_KEYSTORE_H_ diff --git a/keystore/KeymasterArguments.cpp b/keystore/KeymasterArguments.cpp deleted file mode 100644 index 60b86cc9..00000000 --- a/keystore/KeymasterArguments.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* -** -** Copyright 2017, 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. -*/ - -#include "include/keystore/KeymasterArguments.h" -#include "keystore_aidl_hidl_marshalling_utils.h" - -#include - -namespace android { -namespace security { -namespace keymaster { - -using ::android::status_t; -status_t KeymasterArguments::readFromParcel(const android::Parcel* in) { - data_ = keystore::readParamSetFromParcel(*in); - return OK; -}; - -status_t KeymasterArguments::writeToParcel(android::Parcel* out) const { - return keystore::writeParamSetToParcel(data_, out); -}; - -KeymasterArguments::KeymasterArguments(hardware::hidl_vec&& other) - : data_(std::move(other)) {} - -KeymasterArguments::KeymasterArguments(const hardware::hidl_vec& other) - : data_(other) {} - -} // namespace keymaster -} // namespace security -} // namespace android diff --git a/keystore/KeystoreResponse.cpp b/keystore/KeystoreResponse.cpp deleted file mode 100644 index c46973a5..00000000 --- a/keystore/KeystoreResponse.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* -** -** 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. -*/ - -#include -#include -#include -#include - -#include "include/keystore/KeystoreResponse.h" - -namespace android { -namespace security { -namespace keystore { - -status_t KeystoreResponse::readFromParcel(const Parcel* in) { - auto rc = in->readInt32(&response_code_); - if (rc != NO_ERROR) return rc; - return in->readString16(&error_msg_); -} - -status_t KeystoreResponse::writeToParcel(Parcel* out) const { - auto rc = out->writeInt32(response_code_); - if (rc != NO_ERROR) return rc; - return out->writeString16(error_msg_); -} - -} // namespace keystore -} // namespace security -} // namespace android diff --git a/keystore/OperationResult.cpp b/keystore/OperationResult.cpp deleted file mode 100644 index dec4d40c..00000000 --- a/keystore/OperationResult.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* -** -** Copyright 2017, 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. -*/ - -#include "include/keystore/OperationResult.h" - -#include - -#include - -#include - -#include "keystore_aidl_hidl_marshalling_utils.h" - -namespace android { -namespace security { -namespace keymaster { - -using ::android::status_t; -using ::keystore::ErrorCode; - -OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {} - -status_t OperationResult::readFromParcel(const Parcel* inn) { - const Parcel& in = *inn; - resultCode = ErrorCode(in.readInt32()); - token = in.readStrongBinder(); - handle = static_cast(in.readInt64()); - inputConsumed = in.readInt32(); - data = keystore::readKeymasterBlob(in); - outParams = keystore::readParamSetFromParcel(in); - return OK; -} - -status_t OperationResult::writeToParcel(Parcel* out) const { - out->writeInt32(resultCode.getErrorCode()); - out->writeStrongBinder(token); - out->writeInt64(handle); - out->writeInt32(inputConsumed); - keystore::writeKeymasterBlob(data, out); - keystore::writeParamSetToParcel(outParams, out); - return OK; -} - -OperationResult operationFailed(const ::keystore::KeyStoreServiceReturnCode& error) { - OperationResult opResult = {}; - opResult.resultCode = error; - return opResult; -} - -} // namespace keymaster -} // namespace security -} // namespace android diff --git a/keystore/auth_token_table.cpp b/keystore/auth_token_table.cpp deleted file mode 100644 index 971f9eff..00000000 --- a/keystore/auth_token_table.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -#define LOG_TAG "keystore" - -#include "auth_token_table.h" - -#include -#include - -#include - -#include - -namespace keystore { - -template struct choose_hton; - -template struct choose_hton { - inline static IntType hton(const IntType& value) { - IntType result = 0; - const unsigned char* inbytes = reinterpret_cast(&value); - unsigned char* outbytes = reinterpret_cast(&result); - for (int i = sizeof(IntType) - 1; i >= 0; --i) { - *(outbytes++) = inbytes[i]; - } - return result; - } -}; - -template struct choose_hton { - inline static IntType hton(const IntType& value) { return value; } -}; - -template inline IntType hton(const IntType& value) { - return choose_hton::hton(value); -} - -template inline IntType ntoh(const IntType& value) { - // same operation and hton - return choose_hton::hton(value); -} - -// -// Some trivial template wrappers around std algorithms, so they take containers not ranges. -// -template -typename Container::iterator find_if(Container& container, Predicate pred) { - return std::find_if(container.begin(), container.end(), pred); -} - -template -typename Container::iterator remove_if(Container& container, Predicate pred) { - return std::remove_if(container.begin(), container.end(), pred); -} - -template typename Container::iterator min_element(Container& container) { - return std::min_element(container.begin(), container.end()); -} - -time_t clock_gettime_raw() { - struct timespec time; - clock_gettime(CLOCK_MONOTONIC_RAW, &time); - return time.tv_sec; -} - -void AuthTokenTable::AddAuthenticationToken(HardwareAuthToken&& auth_token) { - Entry new_entry(std::move(auth_token), clock_function_()); - // STOPSHIP: debug only, to be removed - ALOGD("AddAuthenticationToken: timestamp = %llu, time_received = %lld", - static_cast(new_entry.token().timestamp), - static_cast(new_entry.time_received())); - - std::lock_guard lock(entries_mutex_); - RemoveEntriesSupersededBy(new_entry); - if (entries_.size() >= max_entries_) { - ALOGW("Auth token table filled up; replacing oldest entry"); - *min_element(entries_) = std::move(new_entry); - } else { - entries_.push_back(std::move(new_entry)); - } -} - -inline bool is_secret_key_operation(Algorithm algorithm, KeyPurpose purpose) { - if ((algorithm != Algorithm::RSA && algorithm != Algorithm::EC)) return true; - if (purpose == KeyPurpose::SIGN || purpose == KeyPurpose::DECRYPT) return true; - return false; -} - -inline bool KeyRequiresAuthentication(const AuthorizationSet& key_info, KeyPurpose purpose) { - auto algorithm = defaultOr(key_info.GetTagValue(TAG_ALGORITHM), Algorithm::AES); - return is_secret_key_operation(algorithm, purpose) && - key_info.find(Tag::NO_AUTH_REQUIRED) == -1; -} - -inline bool KeyRequiresAuthPerOperation(const AuthorizationSet& key_info, KeyPurpose purpose) { - auto algorithm = defaultOr(key_info.GetTagValue(TAG_ALGORITHM), Algorithm::AES); - return is_secret_key_operation(algorithm, purpose) && key_info.find(Tag::AUTH_TIMEOUT) == -1; -} - -std::tuple -AuthTokenTable::FindAuthorization(const AuthorizationSet& key_info, KeyPurpose purpose, - uint64_t op_handle) { - - std::lock_guard lock(entries_mutex_); - - if (!KeyRequiresAuthentication(key_info, purpose)) return {AUTH_NOT_REQUIRED, {}}; - - auto auth_type = - defaultOr(key_info.GetTagValue(TAG_USER_AUTH_TYPE), HardwareAuthenticatorType::NONE); - - std::vector key_sids; - ExtractSids(key_info, &key_sids); - - if (KeyRequiresAuthPerOperation(key_info, purpose)) - return FindAuthPerOpAuthorization(key_sids, auth_type, op_handle); - else - return FindTimedAuthorization(key_sids, auth_type, key_info); -} - -std::tuple AuthTokenTable::FindAuthPerOpAuthorization( - const std::vector& sids, HardwareAuthenticatorType auth_type, uint64_t op_handle) { - if (op_handle == 0) return {OP_HANDLE_REQUIRED, {}}; - - auto matching_op = find_if( - entries_, [&](Entry& e) { return e.token().challenge == op_handle && !e.completed(); }); - - if (matching_op == entries_.end()) return {AUTH_TOKEN_NOT_FOUND, {}}; - - if (!matching_op->SatisfiesAuth(sids, auth_type)) return {AUTH_TOKEN_WRONG_SID, {}}; - - return {OK, matching_op->token()}; -} - -std::tuple -AuthTokenTable::FindTimedAuthorization(const std::vector& sids, - HardwareAuthenticatorType auth_type, - const AuthorizationSet& key_info) { - Entry* newest_match = nullptr; - for (auto& entry : entries_) - if (entry.SatisfiesAuth(sids, auth_type) && entry.is_newer_than(newest_match)) - newest_match = &entry; - - if (!newest_match) return {AUTH_TOKEN_NOT_FOUND, {}}; - - auto timeout = defaultOr(key_info.GetTagValue(TAG_AUTH_TIMEOUT), 0); - - time_t now = clock_function_(); - if (static_cast(newest_match->time_received()) + timeout < static_cast(now)) - return {AUTH_TOKEN_EXPIRED, {}}; - - if (key_info.GetTagValue(TAG_ALLOW_WHILE_ON_BODY).isOk()) { - if (static_cast(newest_match->time_received()) < - static_cast(last_off_body_)) { - return {AUTH_TOKEN_EXPIRED, {}}; - } - } - - newest_match->UpdateLastUse(now); - return {OK, newest_match->token()}; -} - -std::tuple -AuthTokenTable::FindAuthorizationForCredstore(uint64_t challenge, uint64_t secureUserId, - int64_t authTokenMaxAgeMillis) { - std::vector sids = {secureUserId}; - HardwareAuthenticatorType auth_type = HardwareAuthenticatorType::ANY; - time_t now = clock_function_(); - int64_t nowMillis = now * 1000; - - // It's an error to call this without a non-zero challenge. - if (challenge == 0) { - return {OP_HANDLE_REQUIRED, {}}; - } - - // First see if we can find a token which matches the given challenge. If we - // can, return the newest one. We specifically don't care about its age. - // - Entry* newest_match_for_challenge = nullptr; - for (auto& entry : entries_) { - if (entry.token().challenge == challenge && !entry.completed() && - entry.SatisfiesAuth(sids, auth_type)) { - if (newest_match_for_challenge == nullptr || - entry.is_newer_than(newest_match_for_challenge)) { - newest_match_for_challenge = &entry; - } - } - } - if (newest_match_for_challenge != nullptr) { - newest_match_for_challenge->UpdateLastUse(now); - return {OK, newest_match_for_challenge->token()}; - } - - // If that didn't work, we'll take the most recent token within the specified - // deadline, if any. Of course if the deadline is zero it doesn't make sense - // to look at all. - if (authTokenMaxAgeMillis == 0) { - return {AUTH_TOKEN_NOT_FOUND, {}}; - } - - Entry* newest_match = nullptr; - for (auto& entry : entries_) { - if (entry.SatisfiesAuth(sids, auth_type) && entry.is_newer_than(newest_match)) { - newest_match = &entry; - } - } - - if (newest_match == nullptr) { - return {AUTH_TOKEN_NOT_FOUND, {}}; - } - - int64_t tokenAgeMillis = nowMillis - newest_match->time_received() * 1000; - if (tokenAgeMillis >= authTokenMaxAgeMillis) { - return {AUTH_TOKEN_EXPIRED, {}}; - } - - newest_match->UpdateLastUse(now); - return {OK, newest_match->token()}; -} - -void AuthTokenTable::ExtractSids(const AuthorizationSet& key_info, std::vector* sids) { - assert(sids); - for (auto& param : key_info) - if (param.tag == Tag::USER_SECURE_ID) - sids->push_back(authorizationValue(TAG_USER_SECURE_ID, param).value()); -} - -void AuthTokenTable::RemoveEntriesSupersededBy(const Entry& entry) { - entries_.erase(remove_if(entries_, [&](Entry& e) { return entry.Supersedes(e); }), - entries_.end()); -} - -void AuthTokenTable::onDeviceOffBody() { - last_off_body_ = clock_function_(); -} - -void AuthTokenTable::Clear() { - std::lock_guard lock(entries_mutex_); - - entries_.clear(); -} - -size_t AuthTokenTable::size() const { - std::lock_guard lock(entries_mutex_); - return entries_.size(); -} - -bool AuthTokenTable::IsSupersededBySomeEntry(const Entry& entry) { - return std::any_of(entries_.begin(), entries_.end(), - [&](Entry& e) { return e.Supersedes(entry); }); -} - -void AuthTokenTable::MarkCompleted(const uint64_t op_handle) { - std::lock_guard lock(entries_mutex_); - - auto found = find_if(entries_, [&](Entry& e) { return e.token().challenge == op_handle; }); - if (found == entries_.end()) return; - - assert(!IsSupersededBySomeEntry(*found)); - found->mark_completed(); - - if (IsSupersededBySomeEntry(*found)) entries_.erase(found); -} - -AuthTokenTable::Entry::Entry(HardwareAuthToken&& token, time_t current_time) - : token_(std::move(token)), time_received_(current_time), last_use_(current_time), - operation_completed_(token_.challenge == 0) {} - -bool AuthTokenTable::Entry::SatisfiesAuth(const std::vector& sids, - HardwareAuthenticatorType auth_type) { - for (auto sid : sids) { - if (SatisfiesAuth(sid, auth_type)) return true; - } - return false; -} - -void AuthTokenTable::Entry::UpdateLastUse(time_t time) { - this->last_use_ = time; -} - -bool AuthTokenTable::Entry::Supersedes(const Entry& entry) const { - if (!entry.completed()) return false; - - return (token_.userId == entry.token_.userId && - token_.authenticatorType == entry.token_.authenticatorType && - token_.authenticatorId == entry.token_.authenticatorId && is_newer_than(&entry)); -} - -} // namespace keystore diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h deleted file mode 100644 index 787b9b15..00000000 --- a/keystore/auth_token_table.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -#include -#include -#include - -#include - -#ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_ -#define KEYSTORE_AUTH_TOKEN_TABLE_H_ - -namespace keystore { - -namespace test { -class AuthTokenTableTest; -} // namespace test - -time_t clock_gettime_raw(); - -/** - * AuthTokenTable manages a set of received authorization tokens and can provide the appropriate - * token for authorizing a key operation. - * - * To keep the table from growing without bound, superseded entries are removed when possible, and - * least recently used entries are automatically pruned when when the table exceeds a size limit, - * which is expected to be relatively small, since the implementation uses a linear search. - */ -class AuthTokenTable { - public: - explicit AuthTokenTable(size_t max_entries = 32, time_t (*clock_function)() = clock_gettime_raw) - : max_entries_(max_entries), last_off_body_(clock_function()), - clock_function_(clock_function) {} - - enum Error { - OK, - AUTH_NOT_REQUIRED = -1, - AUTH_TOKEN_EXPIRED = -2, // Found a matching token, but it's too old. - AUTH_TOKEN_WRONG_SID = -3, // Found a token with the right challenge, but wrong SID. This - // most likely indicates that the authenticator was updated - // (e.g. new fingerprint enrolled). - OP_HANDLE_REQUIRED = -4, // The key requires auth per use but op_handle was zero. - AUTH_TOKEN_NOT_FOUND = -5, - }; - - /** - * Add an authorization token to the table. - */ - void AddAuthenticationToken(HardwareAuthToken&& auth_token); - - /** - * Find an authorization token that authorizes the operation specified by \p operation_handle on - * a key with the characteristics specified in \p key_info. - * - * This method is O(n * m), where n is the number of KM_TAG_USER_SECURE_ID entries in key_info - * and m is the number of entries in the table. It could be made better, but n and m should - * always be small. - * - * The table retains ownership of the returned object. - */ - std::tuple FindAuthorization(const AuthorizationSet& key_info, - KeyPurpose purpose, uint64_t op_handle); - - std::tuple - FindAuthorizationForCredstore(uint64_t challenge, uint64_t secureUserId, - int64_t authTokenMaxAgeMillis); - - /** - * Mark operation completed. This allows tokens associated with the specified operation to be - * superseded by new tokens. - */ - void MarkCompleted(const uint64_t op_handle); - - /** - * Update the last_off_body_ timestamp so that tokens which remain authorized only so long as - * the device stays on body can be revoked. - */ - void onDeviceOffBody(); - - void Clear(); - - /** - * This function shall only be used for testing. - * - * BEWARE: Since the auth token table can be accessed - * concurrently, the size may be out dated as soon as it returns. - */ - size_t size() const; - - private: - friend class AuthTokenTableTest; - - class Entry { - public: - Entry(HardwareAuthToken&& token, time_t current_time); - Entry(Entry&& entry) noexcept { *this = std::move(entry); } - - void operator=(Entry&& rhs) noexcept { - token_ = std::move(rhs.token_); - time_received_ = rhs.time_received_; - last_use_ = rhs.last_use_; - operation_completed_ = rhs.operation_completed_; - } - - bool operator<(const Entry& rhs) const { return last_use_ < rhs.last_use_; } - - void UpdateLastUse(time_t time); - - bool Supersedes(const Entry& entry) const; - bool SatisfiesAuth(const std::vector& sids, HardwareAuthenticatorType auth_type); - - bool is_newer_than(const Entry* entry) const { - if (!entry) return true; - uint64_t ts = token_.timestamp; - uint64_t other_ts = entry->token_.timestamp; - // Normally comparing timestamp_host_order alone is sufficient, but here is an - // additional hack to compare time_received value for some devices where their auth - // tokens contain fixed timestamp (due to the a stuck secure RTC on them) - return (ts > other_ts) || - ((ts == other_ts) && (time_received_ > entry->time_received_)); - } - - void mark_completed() { operation_completed_ = true; } - - const HardwareAuthToken& token() const & { return token_; } - time_t time_received() const { return time_received_; } - bool completed() const { return operation_completed_; } - - private: - bool SatisfiesAuth(uint64_t sid, HardwareAuthenticatorType auth_type) const { - return (sid == token_.userId || sid == token_.authenticatorId) && - (auth_type & token_.authenticatorType) != 0; - } - - HardwareAuthToken token_; - time_t time_received_; - time_t last_use_; - bool operation_completed_; - }; - - std::tuple - FindAuthPerOpAuthorization(const std::vector& sids, - HardwareAuthenticatorType auth_type, uint64_t op_handle); - std::tuple FindTimedAuthorization(const std::vector& sids, - HardwareAuthenticatorType auth_type, - const AuthorizationSet& key_info); - void ExtractSids(const AuthorizationSet& key_info, std::vector* sids); - void RemoveEntriesSupersededBy(const Entry& entry); - bool IsSupersededBySomeEntry(const Entry& entry); - - /** - * Guards the entries_ vector against concurrent modification. All public facing methods - * reading of modifying the vector must grab this mutex. - */ - mutable std::mutex entries_mutex_; - std::vector entries_; - size_t max_entries_; - time_t last_off_body_; - time_t (*clock_function_)(); -}; - -} // namespace keystore - -#endif // KEYSTORE_AUTH_TOKEN_TABLE_H_ diff --git a/keystore/binder/android/security/IConfirmationPromptCallback.aidl b/keystore/binder/android/security/IConfirmationPromptCallback.aidl deleted file mode 100644 index 96a1a048..00000000 --- a/keystore/binder/android/security/IConfirmationPromptCallback.aidl +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2017, 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. - */ - -package android.security; - -/** - * This must be kept manually in sync with system/security/keystore until AIDL - * can generate both Java and C++ bindings. - * - * @hide - */ -interface IConfirmationPromptCallback { - oneway void onConfirmationPromptCompleted(in int result, in byte[] dataThatWasConfirmed); -} diff --git a/keystore/binder/android/security/keymaster/ExportResult.aidl b/keystore/binder/android/security/keymaster/ExportResult.aidl deleted file mode 100644 index 17486531..00000000 --- a/keystore/binder/android/security/keymaster/ExportResult.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable ExportResult cpp_header "keystore/ExportResult.h"; diff --git a/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl b/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl deleted file mode 100644 index 32e75ad2..00000000 --- a/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable KeyCharacteristics cpp_header "keystore/KeyCharacteristics.h"; diff --git a/keystore/binder/android/security/keymaster/KeymasterArguments.aidl b/keystore/binder/android/security/keymaster/KeymasterArguments.aidl deleted file mode 100644 index 44d9f095..00000000 --- a/keystore/binder/android/security/keymaster/KeymasterArguments.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable KeymasterArguments cpp_header "keystore/KeymasterArguments.h"; diff --git a/keystore/binder/android/security/keymaster/KeymasterBlob.aidl b/keystore/binder/android/security/keymaster/KeymasterBlob.aidl deleted file mode 100644 index 5c5db9ec..00000000 --- a/keystore/binder/android/security/keymaster/KeymasterBlob.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable KeymasterBlob cpp_header "keystore/KeymasterBlob.h"; diff --git a/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl b/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl deleted file mode 100644 index ddb5cae1..00000000 --- a/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable KeymasterCertificateChain cpp_header "keystore/KeymasterCertificateChain.h"; diff --git a/keystore/binder/android/security/keymaster/OperationResult.aidl b/keystore/binder/android/security/keymaster/OperationResult.aidl deleted file mode 100644 index db689d46..00000000 --- a/keystore/binder/android/security/keymaster/OperationResult.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -package android.security.keymaster; - -/* @hide */ -parcelable OperationResult cpp_header "keystore/OperationResult.h"; diff --git a/keystore/binder/android/security/keystore/ICredstoreTokenCallback.aidl b/keystore/binder/android/security/keystore/ICredstoreTokenCallback.aidl deleted file mode 100644 index b42e3d4c..00000000 --- a/keystore/binder/android/security/keystore/ICredstoreTokenCallback.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2020, 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. - */ - -package android.security.keystore; - - -/** - * @hide - */ -oneway interface ICredstoreTokenCallback { - void onFinished(boolean success, in byte[] authToken, in byte[] verificationToken); -} diff --git a/keystore/binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl deleted file mode 100644 index dca928d9..00000000 --- a/keystore/binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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. - */ - -package android.security.keystore; - -import android.security.keystore.KeystoreResponse; -import android.security.keymaster.KeymasterCertificateChain; - -/** - * @hide - */ -oneway interface IKeystoreCertificateChainCallback { - void onFinished(in KeystoreResponse response, in KeymasterCertificateChain chain); -} \ No newline at end of file diff --git a/keystore/binder/android/security/keystore/IKeystoreExportKeyCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreExportKeyCallback.aidl deleted file mode 100644 index e42e9274..00000000 --- a/keystore/binder/android/security/keystore/IKeystoreExportKeyCallback.aidl +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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. - */ - -package android.security.keystore; - -import android.security.keystore.KeystoreResponse; -import android.security.keymaster.ExportResult; - -/** - * @hide - */ -oneway interface IKeystoreExportKeyCallback { - void onFinished(in ExportResult result); -} \ No newline at end of file diff --git a/keystore/binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl deleted file mode 100644 index e1f0ffed..00000000 --- a/keystore/binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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. - */ - -package android.security.keystore; - -import android.security.keystore.KeystoreResponse; -import android.security.keymaster.KeyCharacteristics; - -/** - * @hide - */ -oneway interface IKeystoreKeyCharacteristicsCallback { - void onFinished(in KeystoreResponse response, in KeyCharacteristics charactersistics); -} \ No newline at end of file diff --git a/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl deleted file mode 100644 index f37b8381..00000000 --- a/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/** - * 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. - */ - -package android.security.keystore; - -import android.security.keystore.KeystoreResponse; -import android.security.keymaster.OperationResult; - -/** - * @hide - */ -@SensitiveData -oneway interface IKeystoreOperationResultCallback { - void onFinished(in OperationResult result); -} diff --git a/keystore/binder/android/security/keystore/IKeystoreResponseCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreResponseCallback.aidl deleted file mode 100644 index 912e6054..00000000 --- a/keystore/binder/android/security/keystore/IKeystoreResponseCallback.aidl +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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. - */ - -package android.security.keystore; - -import android.security.keystore.KeystoreResponse; - -/** - * @hide - */ -oneway interface IKeystoreResponseCallback { - void onFinished(in KeystoreResponse response); -} \ No newline at end of file diff --git a/keystore/binder/android/security/keystore/IKeystoreService.aidl b/keystore/binder/android/security/keystore/IKeystoreService.aidl deleted file mode 100644 index 3b9a1b45..00000000 --- a/keystore/binder/android/security/keystore/IKeystoreService.aidl +++ /dev/null @@ -1,106 +0,0 @@ -/** - * 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. - */ - -package android.security.keystore; - -import android.security.keymaster.KeymasterArguments; -import android.security.keymaster.KeymasterBlob; -import android.security.keymaster.OperationResult; -import android.security.keystore.ICredstoreTokenCallback; -import android.security.keystore.IKeystoreResponseCallback; -import android.security.keystore.IKeystoreKeyCharacteristicsCallback; -import android.security.keystore.IKeystoreExportKeyCallback; -import android.security.keystore.IKeystoreOperationResultCallback; -import android.security.keystore.IKeystoreCertificateChainCallback; - -/** - * @hide - */ -@SensitiveData -interface IKeystoreService { - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - int getState(int userId); - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - byte[] get(String name, int uid); - @UnsupportedAppUsage - int insert(String name, in byte[] item, int uid, int flags); - @UnsupportedAppUsage - int del(String name, int uid); - @UnsupportedAppUsage - int exist(String name, int uid); - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - String[] list(String namePrefix, int uid); - int onUserPasswordChanged(int userId, String newPassword); - int lock(int userId); - int unlock(int userId, String userPassword); - int isEmpty(int userId); - String grant(String name, int granteeUid); - @UnsupportedAppUsage - int ungrant(String name, int granteeUid); - long getmtime(String name, int uid); - @UnsupportedAppUsage - int is_hardware_backed(String string); - @UnsupportedAppUsage - int clear_uid(long uid); - - int addRngEntropy(IKeystoreResponseCallback cb, in byte[] data, int flags); - int generateKey(IKeystoreKeyCharacteristicsCallback cb, String alias, in KeymasterArguments arguments, in byte[] entropy, int uid, - int flags); - int getKeyCharacteristics (IKeystoreKeyCharacteristicsCallback cb, String alias, in KeymasterBlob clientId, in KeymasterBlob appData, - int uid); - int importKey(IKeystoreKeyCharacteristicsCallback cb, String alias, in KeymasterArguments arguments, int format, - in byte[] keyData, int uid, int flags); - int exportKey(IKeystoreExportKeyCallback cb, String alias, int format, in KeymasterBlob clientId, - in KeymasterBlob appData, int uid); - int begin(in IKeystoreOperationResultCallback cb, IBinder appToken, String alias, int purpose, boolean pruneable, - in KeymasterArguments params, in byte[] entropy, int uid); - int update(in IKeystoreOperationResultCallback cb, IBinder token, in KeymasterArguments params, in byte[] input); - int finish(in IKeystoreOperationResultCallback cb, IBinder token, in KeymasterArguments params, in byte[] input, in byte[] signature, - in byte[] entropy); - int abort(in IKeystoreResponseCallback cb, IBinder token); - int addAuthToken(in byte[] authToken); - int onUserAdded(int userId, int parentId); - int onUserRemoved(int userId); - int attestKey(in IKeystoreCertificateChainCallback cb, String alias, in KeymasterArguments params); - int attestDeviceIds(in IKeystoreCertificateChainCallback cb, in KeymasterArguments params); - int onDeviceOffBody(); - int importWrappedKey(in IKeystoreKeyCharacteristicsCallback cb, String wrappedKeyAlias, in byte[] wrappedKey, - in String wrappingKeyAlias, in byte[] maskingKey, in KeymasterArguments arguments, - in long rootSid, in long fingerprintSid); - int presentConfirmationPrompt(IBinder listener, String promptText, in byte[] extraData, - in String locale, in int uiOptionsAsFlags); - int cancelConfirmationPrompt(IBinder listener); - boolean isConfirmationPromptSupported(); - int onKeyguardVisibilityChanged(in boolean isShowing, in int userId); - int listUidsOfAuthBoundKeys(out @utf8InCpp List uids); - - // This method looks through auth-tokens cached by keystore which match - // the passed-in |secureUserId|. - // - // If one or more of these tokens has a |challenge| field which matches - // the passed-in |challenge| parameter, the most recent is returned. In - // this case the |authTokenMaxAgeMillis| parameter is not used. - // - // Otherwise, the most recent auth-token of these tokens which is younger - // than |authTokenMaxAgeMillis| is returned. - // - // The passed in |challenge| parameter must always be non-zero. - // - // This method is called by credstore (and only credstore). - // - void getTokensForCredstore(in long challenge, in long secureUserId, in int authTokenMaxAgeMillis, - in ICredstoreTokenCallback cb); -} diff --git a/keystore/binder/android/security/keystore/KeystoreResponse.aidl b/keystore/binder/android/security/keystore/KeystoreResponse.aidl deleted file mode 100644 index 128b4569..00000000 --- a/keystore/binder/android/security/keystore/KeystoreResponse.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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. - */ - -package android.security.keystore; - -/* @hide */ -parcelable KeystoreResponse cpp_header "keystore/KeystoreResponse.h"; diff --git a/keystore/blob.cpp b/keystore/blob.cpp deleted file mode 100644 index ffdb454b..00000000 --- a/keystore/blob.cpp +++ /dev/null @@ -1,791 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -#define LOG_TAG "keystore" - -#include -#include -#include -#include - -#include - -#include "blob.h" - -#include "keystore_utils.h" - -#include -#include - -#include -#include -#include -#include - -#include -#include - -namespace { - -constexpr size_t kGcmIvSizeBytes = 96 / 8; - -#if defined(__clang__) -#define OPTNONE __attribute__((optnone)) -#elif defined(__GNUC__) -#define OPTNONE __attribute__((optimize("O0"))) -#else -#error Need a definition for OPTNONE -#endif - -class ArrayEraser { - public: - ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {} - OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); } - - private: - volatile uint8_t* mArr; - size_t mSize; -}; - -/** - * Returns a EVP_CIPHER appropriate for the given key, based on the key's size. - */ -const EVP_CIPHER* getAesCipherForKey(const std::vector& key) { - const EVP_CIPHER* cipher = EVP_aes_256_gcm(); - if (key.size() == kAes128KeySizeBytes) { - cipher = EVP_aes_128_gcm(); - } - return cipher; -} - -/* - * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at - * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to - * 'tag'. - */ -ResponseCode AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, - const std::vector& key, const uint8_t* iv, uint8_t* tag) { - - // There can be 128-bit and 256-bit keys - const EVP_CIPHER* cipher = getAesCipherForKey(key); - - bssl::UniquePtr ctx(EVP_CIPHER_CTX_new()); - - EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv); - EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */); - - std::unique_ptr out_tmp(new uint8_t[len]); - uint8_t* out_pos = out_tmp.get(); - int out_len; - - EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len); - out_pos += out_len; - EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len); - out_pos += out_len; - if (out_pos - out_tmp.get() != static_cast(len)) { - ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len, - out_pos - out_tmp.get()); - return ResponseCode::SYSTEM_ERROR; - } - - std::copy(out_tmp.get(), out_pos, out); - EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag); - - return ResponseCode::NO_ERROR; -} - -/* - * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at - * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same - * location as 'in'). - */ -ResponseCode AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, - const std::vector key, const uint8_t* iv, - const uint8_t* tag) { - - // There can be 128-bit and 256-bit keys - const EVP_CIPHER* cipher = getAesCipherForKey(key); - - bssl::UniquePtr ctx(EVP_CIPHER_CTX_new()); - - EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv); - EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */); - EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast(tag)); - - std::unique_ptr out_tmp(new uint8_t[len]); - ArrayEraser out_eraser(out_tmp.get(), len); - uint8_t* out_pos = out_tmp.get(); - int out_len; - - EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len); - out_pos += out_len; - if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) { - ALOGE("Failed to decrypt blob; ciphertext or tag is likely corrupted"); - return ResponseCode::VALUE_CORRUPTED; - } - out_pos += out_len; - if (out_pos - out_tmp.get() != static_cast(len)) { - ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len, - out_pos - out_tmp.get()); - return ResponseCode::VALUE_CORRUPTED; - } - - std::copy(out_tmp.get(), out_pos, out); - - return ResponseCode::NO_ERROR; -} - -class ArrayStreamBuffer : public std::streambuf { - public: - template explicit ArrayStreamBuffer(const T (&data)[size]) { - static_assert(sizeof(T) == 1, "Array element size too large"); - std::streambuf::char_type* d = const_cast( - reinterpret_cast(&data[0])); - setg(d, d, d + size); - setp(d, d + size); - } - - protected: - pos_type seekoff(off_type off, std::ios_base::seekdir dir, - std::ios_base::openmode which = std::ios_base::in | - std::ios_base::out) override { - bool in = which & std::ios_base::in; - bool out = which & std::ios_base::out; - if ((!in && !out) || (in && out && dir == std::ios_base::cur)) return -1; - std::streambuf::char_type* newPosPtr; - switch (dir) { - case std::ios_base::beg: - newPosPtr = pbase(); - break; - case std::ios_base::cur: - // if dir == cur then in xor out due to - // if ((!in && !out) || (in && out && dir == std::ios_base::cur)) return -1; above - if (in) - newPosPtr = gptr(); - else - newPosPtr = pptr(); - break; - case std::ios_base::end: - // in and out bounds are the same and cannot change, so we can take either range - // regardless of the value of "which" - newPosPtr = epptr(); - break; - } - newPosPtr += off; - if (newPosPtr < pbase() || newPosPtr > epptr()) return -1; - if (in) { - gbump(newPosPtr - gptr()); - } - if (out) { - pbump(newPosPtr - pptr()); - } - return newPosPtr - pbase(); - } -}; - -} // namespace - -Blob::Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength, - BlobType type) { - mBlob = std::make_unique(); - memset(mBlob.get(), 0, sizeof(blobv3)); - if (valueLength > kValueSize) { - valueLength = kValueSize; - ALOGW("Provided blob length too large"); - } - if (infoLength + valueLength > kValueSize) { - infoLength = kValueSize - valueLength; - ALOGW("Provided info length too large"); - } - mBlob->length = valueLength; - memcpy(mBlob->value, value, valueLength); - - mBlob->info = infoLength; - memcpy(mBlob->value + valueLength, info, infoLength); - - mBlob->version = CURRENT_BLOB_VERSION; - mBlob->type = uint8_t(type); - - if (type == TYPE_MASTER_KEY || type == TYPE_MASTER_KEY_AES256) { - mBlob->flags = KEYSTORE_FLAG_ENCRYPTED; - } else { - mBlob->flags = KEYSTORE_FLAG_NONE; - } -} - -Blob::Blob(blobv3 b) { - mBlob = std::make_unique(b); -} - -Blob::Blob() { - if (mBlob) *mBlob = {}; -} - -Blob::Blob(const Blob& rhs) { - if (rhs.mBlob) { - mBlob = std::make_unique(*rhs.mBlob); - } -} - -Blob::Blob(Blob&& rhs) : mBlob(std::move(rhs.mBlob)) {} - -Blob& Blob::operator=(const Blob& rhs) { - if (&rhs != this) { - if (mBlob) *mBlob = {}; - if (rhs) { - mBlob = std::make_unique(*rhs.mBlob); - } else { - mBlob = {}; - } - } - return *this; -} - -Blob& Blob::operator=(Blob&& rhs) { - if (mBlob) *mBlob = {}; - mBlob = std::move(rhs.mBlob); - return *this; -} - -template static bool rawBlobIsEncrypted(const BlobType& blob) { - if (blob.version < 2) return true; - - return blob.flags & (KEYSTORE_FLAG_ENCRYPTED | KEYSTORE_FLAG_SUPER_ENCRYPTED); -} - -bool Blob::isEncrypted() const { - if (mBlob->version < 2) { - return true; - } - - return mBlob->flags & KEYSTORE_FLAG_ENCRYPTED; -} - -bool Blob::isSuperEncrypted() const { - return mBlob->flags & KEYSTORE_FLAG_SUPER_ENCRYPTED; -} - -bool Blob::isCriticalToDeviceEncryption() const { - return mBlob->flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION; -} - -inline uint8_t setFlag(uint8_t flags, bool set, KeyStoreFlag flag) { - return set ? (flags | flag) : (flags & ~flag); -} - -void Blob::setEncrypted(bool encrypted) { - mBlob->flags = setFlag(mBlob->flags, encrypted, KEYSTORE_FLAG_ENCRYPTED); -} - -void Blob::setSuperEncrypted(bool superEncrypted) { - mBlob->flags = setFlag(mBlob->flags, superEncrypted, KEYSTORE_FLAG_SUPER_ENCRYPTED); -} - -void Blob::setCriticalToDeviceEncryption(bool critical) { - mBlob->flags = setFlag(mBlob->flags, critical, KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION); -} - -void Blob::setFallback(bool fallback) { - if (fallback) { - mBlob->flags |= KEYSTORE_FLAG_FALLBACK; - } else { - mBlob->flags &= ~KEYSTORE_FLAG_FALLBACK; - } -} - -static ResponseCode writeBlob(const std::string& filename, Blob blob, blobv3* rawBlob, - const std::vector& aes_key, State state) { - ALOGV("writing blob %s", filename.c_str()); - - const size_t dataLength = rawBlob->length; - rawBlob->length = htonl(rawBlob->length); - - if (blob.isEncrypted() || blob.isSuperEncrypted()) { - if (state != STATE_NO_ERROR) { - ALOGD("couldn't insert encrypted blob while not unlocked"); - return ResponseCode::LOCKED; - } - - memset(rawBlob->initialization_vector, 0, AES_BLOCK_SIZE); - if (!RAND_bytes(rawBlob->initialization_vector, kGcmIvSizeBytes)) { - ALOGW("Could not read random data for: %s", filename.c_str()); - return ResponseCode::SYSTEM_ERROR; - } - - auto rc = AES_gcm_encrypt(rawBlob->value /* in */, rawBlob->value /* out */, dataLength, - aes_key, rawBlob->initialization_vector, rawBlob->aead_tag); - if (rc != ResponseCode::NO_ERROR) return rc; - } - - size_t fileLength = offsetof(blobv3, value) + dataLength + rawBlob->info; - - char tmpFileName[] = ".tmpXXXXXX"; - { - android::base::unique_fd out(TEMP_FAILURE_RETRY(mkstemp(tmpFileName))); - if (out < 0) { - LOG(ERROR) << "could not open temp file: " << tmpFileName - << " for writing blob file: " << filename.c_str() - << " because: " << strerror(errno); - return ResponseCode::SYSTEM_ERROR; - } - - const size_t writtenBytes = - writeFully(out, reinterpret_cast(rawBlob), fileLength); - - if (writtenBytes != fileLength) { - LOG(ERROR) << "blob not fully written " << writtenBytes << " != " << fileLength; - unlink(tmpFileName); - return ResponseCode::SYSTEM_ERROR; - } - } - - if (rename(tmpFileName, filename.c_str()) == -1) { - LOG(ERROR) << "could not rename blob file to " << filename - << " because: " << strerror(errno); - unlink(tmpFileName); - return ResponseCode::SYSTEM_ERROR; - } - - fsyncDirectory(getContainingDirectory(filename)); - - return ResponseCode::NO_ERROR; -} - -ResponseCode LockedKeyBlobEntry::writeBlobs(Blob keyBlob, Blob characteristicsBlob, - const std::vector& aes_key, - State state) const { - if (entry_ == nullptr) { - return ResponseCode::SYSTEM_ERROR; - } - ResponseCode rc; - if (keyBlob) { - blobv3* rawBlob = keyBlob.mBlob.get(); - rc = writeBlob(entry_->getKeyBlobPath(), std::move(keyBlob), rawBlob, aes_key, state); - if (rc != ResponseCode::NO_ERROR) { - return rc; - } - } - - if (characteristicsBlob) { - blobv3* rawBlob = characteristicsBlob.mBlob.get(); - rc = writeBlob(entry_->getCharacteristicsBlobPath(), std::move(characteristicsBlob), - rawBlob, aes_key, state); - } - return rc; -} - -ResponseCode Blob::readBlob(const std::string& filename, const std::vector& aes_key, - State state) { - ResponseCode rc; - ALOGV("reading blob %s", filename.c_str()); - std::unique_ptr rawBlob = std::make_unique(); - - const int in = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY)); - if (in < 0) { - return (errno == ENOENT) ? ResponseCode::KEY_NOT_FOUND : ResponseCode::SYSTEM_ERROR; - } - - // fileLength may be less than sizeof(mBlob) - const size_t fileLength = readFully(in, (uint8_t*)rawBlob.get(), sizeof(blobv3)); - if (close(in) != 0) { - return ResponseCode::SYSTEM_ERROR; - } - - if (fileLength == 0) { - LOG(ERROR) << __func__ << " VALUE_CORRUPTED file length == 0"; - return ResponseCode::VALUE_CORRUPTED; - } - - if (rawBlobIsEncrypted(*rawBlob)) { - if (state == STATE_LOCKED) { - mBlob = std::move(rawBlob); - return ResponseCode::LOCKED; - } - if (state == STATE_UNINITIALIZED) return ResponseCode::UNINITIALIZED; - } - - if (fileLength < offsetof(blobv3, value)) { - LOG(ERROR) << __func__ << " VALUE_CORRUPTED blob file too short: " << fileLength; - return ResponseCode::VALUE_CORRUPTED; - } - - if (rawBlob->version == 3) { - const ssize_t encryptedLength = ntohl(rawBlob->length); - - if (rawBlobIsEncrypted(*rawBlob)) { - rc = AES_gcm_decrypt(rawBlob->value /* in */, rawBlob->value /* out */, encryptedLength, - aes_key, rawBlob->initialization_vector, rawBlob->aead_tag); - if (rc != ResponseCode::NO_ERROR) { - // If the blob was superencrypted and decryption failed, it is - // almost certain that decryption is failing due to a user's - // changed master key. - if ((rawBlob->flags & KEYSTORE_FLAG_SUPER_ENCRYPTED) && - (rc == ResponseCode::VALUE_CORRUPTED)) { - return ResponseCode::KEY_PERMANENTLY_INVALIDATED; - } - LOG(ERROR) << __func__ << " AES_gcm_decrypt returned: " << uint32_t(rc); - - return rc; - } - } - } else if (rawBlob->version < 3) { - blobv2& v2blob = reinterpret_cast(*rawBlob); - const size_t headerLength = offsetof(blobv2, encrypted); - const ssize_t encryptedLength = fileLength - headerLength - v2blob.info; - if (encryptedLength < 0) { - LOG(ERROR) << __func__ << " VALUE_CORRUPTED v2blob file too short"; - return ResponseCode::VALUE_CORRUPTED; - } - - if (rawBlobIsEncrypted(*rawBlob)) { - if (encryptedLength % AES_BLOCK_SIZE != 0) { - LOG(ERROR) << __func__ - << " VALUE_CORRUPTED encrypted length is not a multiple" - " of the AES block size"; - return ResponseCode::VALUE_CORRUPTED; - } - - AES_KEY key; - AES_set_decrypt_key(aes_key.data(), kAesKeySize * 8, &key); - AES_cbc_encrypt(v2blob.encrypted, v2blob.encrypted, encryptedLength, &key, - v2blob.vector, AES_DECRYPT); - key = {}; // clear key - - uint8_t computedDigest[MD5_DIGEST_LENGTH]; - ssize_t digestedLength = encryptedLength - MD5_DIGEST_LENGTH; - MD5(v2blob.digested, digestedLength, computedDigest); - if (memcmp(v2blob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) { - LOG(ERROR) << __func__ << " v2blob MD5 digest mismatch"; - return ResponseCode::VALUE_CORRUPTED; - } - } - } - - const ssize_t maxValueLength = fileLength - offsetof(blobv3, value) - rawBlob->info; - rawBlob->length = ntohl(rawBlob->length); - if (rawBlob->length < 0 || rawBlob->length > maxValueLength || - rawBlob->length + rawBlob->info + AES_BLOCK_SIZE > - static_cast(sizeof(rawBlob->value))) { - LOG(ERROR) << __func__ << " raw blob length is out of bounds"; - return ResponseCode::VALUE_CORRUPTED; - } - - if (rawBlob->info != 0 && rawBlob->version < 3) { - // move info from after padding to after data - memmove(rawBlob->value + rawBlob->length, rawBlob->value + maxValueLength, rawBlob->info); - } - - mBlob = std::move(rawBlob); - return ResponseCode::NO_ERROR; -} - -std::tuple -LockedKeyBlobEntry::readBlobs(const std::vector& aes_key, State state) const { - std::tuple result; - auto& [rc, keyBlob, characteristicsBlob] = result; - if (entry_ == nullptr) return rc = ResponseCode::SYSTEM_ERROR, result; - - rc = keyBlob.readBlob(entry_->getKeyBlobPath(), aes_key, state); - if (rc != ResponseCode::NO_ERROR && rc != ResponseCode::UNINITIALIZED) { - return result; - } - - if (entry_->hasCharacteristicsBlob()) { - characteristicsBlob.readBlob(entry_->getCharacteristicsBlobPath(), aes_key, state); - } - return result; -} - -ResponseCode LockedKeyBlobEntry::deleteBlobs() const { - if (entry_ == nullptr) return ResponseCode::NO_ERROR; - - // always try to delete both - ResponseCode rc1 = (unlink(entry_->getKeyBlobPath().c_str()) && errno != ENOENT) - ? ResponseCode::SYSTEM_ERROR - : ResponseCode::NO_ERROR; - if (rc1 != ResponseCode::NO_ERROR) { - ALOGW("Failed to delete key blob file \"%s\"", entry_->getKeyBlobPath().c_str()); - } - ResponseCode rc2 = (unlink(entry_->getCharacteristicsBlobPath().c_str()) && errno != ENOENT) - ? ResponseCode::SYSTEM_ERROR - : ResponseCode::NO_ERROR; - if (rc2 != ResponseCode::NO_ERROR) { - ALOGW("Failed to delete key characteristics file \"%s\"", - entry_->getCharacteristicsBlobPath().c_str()); - } - // then report the first error that occured - if (rc1 != ResponseCode::NO_ERROR) return rc1; - return rc2; -} - -keystore::SecurityLevel Blob::getSecurityLevel() const { - return keystore::flagsToSecurityLevel(mBlob->flags); -} - -void Blob::setSecurityLevel(keystore::SecurityLevel secLevel) { - mBlob->flags &= ~(KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX); - mBlob->flags |= keystore::securityLevelToFlags(secLevel); -} - -std::tuple -Blob::getKeyCharacteristics() const { - std::tuple result; - auto& [success, hwEnforced, swEnforced] = result; - success = false; - ArrayStreamBuffer buf(mBlob->value); - std::istream in(&buf); - - // only the characteristics cache has both sets - if (getType() == TYPE_KEY_CHARACTERISTICS_CACHE) { - hwEnforced.Deserialize(&in); - } else if (getType() != TYPE_KEY_CHARACTERISTICS) { - // if its not the cache and not the legacy characteristics file we have no business - // here - return result; - } - swEnforced.Deserialize(&in); - success = !in.bad(); - - return result; -} -bool Blob::putKeyCharacteristics(const keystore::AuthorizationSet& hwEnforced, - const keystore::AuthorizationSet& swEnforced) { - if (!mBlob) mBlob = std::make_unique(); - mBlob->version = CURRENT_BLOB_VERSION; - ArrayStreamBuffer buf(mBlob->value); - std::ostream out(&buf); - hwEnforced.Serialize(&out); - swEnforced.Serialize(&out); - if (out.bad()) return false; - setType(TYPE_KEY_CHARACTERISTICS_CACHE); - mBlob->length = out.tellp(); - return true; -} - -void LockedKeyBlobEntry::put(const KeyBlobEntry& entry) { - std::unique_lock lock(locked_blobs_mutex_); - locked_blobs_.erase(entry); - lock.unlock(); - locked_blobs_mutex_cond_var_.notify_all(); -} - -LockedKeyBlobEntry::~LockedKeyBlobEntry() { - if (entry_ != nullptr) put(*entry_); -} - -LockedKeyBlobEntry LockedKeyBlobEntry::get(KeyBlobEntry entry) { - std::unique_lock lock(locked_blobs_mutex_); - locked_blobs_mutex_cond_var_.wait( - lock, [&] { return locked_blobs_.find(entry) == locked_blobs_.end(); }); - auto [iterator, success] = locked_blobs_.insert(std::move(entry)); - if (!success) return {}; - return LockedKeyBlobEntry(*iterator); -} - -std::set LockedKeyBlobEntry::locked_blobs_; -std::mutex LockedKeyBlobEntry::locked_blobs_mutex_; -std::condition_variable LockedKeyBlobEntry::locked_blobs_mutex_cond_var_; - -/* Here is the encoding of key names. This is necessary in order to allow arbitrary - * characters in key names. Characters in [0-~] are not encoded. Others are encoded - * into two bytes. The first byte is one of [+-.] which represents the first - * two bits of the character. The second byte encodes the rest of the bits into - * [0-o]. Therefore in the worst case the length of a key gets doubled. Note - * that Base64 cannot be used here due to the need of prefix match on keys. */ - -std::string encodeKeyName(const std::string& keyName) { - std::string encodedName; - encodedName.reserve(keyName.size() * 2); - auto in = keyName.begin(); - while (in != keyName.end()) { - // Input character needs to be encoded. - if (*in < '0' || *in > '~') { - // Encode the two most-significant bits of the input char in the first - // output character, by counting up from 43 ('+'). - encodedName.append(1, '+' + (uint8_t(*in) >> 6)); - // Encode the six least-significant bits of the input char in the second - // output character, by counting up from 48 ('0'). - // This is safe because the maximum value is 112, which is the - // character 'p'. - encodedName.append(1, '0' + (*in & 0x3F)); - } else { - // No need to encode input char - append as-is. - encodedName.append(1, *in); - } - ++in; - } - return encodedName; -} - -std::string decodeKeyName(const std::string& encodedName) { - std::string decodedName; - decodedName.reserve(encodedName.size()); - auto in = encodedName.begin(); - bool multichar = false; - char c; - while (in != encodedName.end()) { - if (multichar) { - // Second part of a multi-character encoding. Turn off the multichar - // flag and set the six least-significant bits of c to the value originally - // encoded by counting up from '0'. - multichar = false; - decodedName.append(1, c | (uint8_t(*in) - '0')); - } else if (*in >= '+' && *in <= '.') { - // First part of a multi-character encoding. Set the multichar flag - // and set the two most-significant bits of c to be the two bits originally - // encoded by counting up from '+'. - multichar = true; - c = (*in - '+') << 6; - } else { - // Regular character, append as-is. - decodedName.append(1, *in); - } - ++in; - } - // mulitchars at the end get truncated - return decodedName; -} - -std::string KeyBlobEntry::getKeyBlobBaseName() const { - std::stringstream s; - if (masterkey_) { - s << alias_; - } else { - s << uid_ << "_" << encodeKeyName(alias_); - } - return s.str(); -} - -std::string KeyBlobEntry::getKeyBlobPath() const { - std::stringstream s; - if (masterkey_) { - s << user_dir_ << "/" << alias_; - } else { - s << user_dir_ << "/" << uid_ << "_" << encodeKeyName(alias_); - } - return s.str(); -} - -std::string KeyBlobEntry::getCharacteristicsBlobBaseName() const { - std::stringstream s; - if (!masterkey_) s << "." << uid_ << "_chr_" << encodeKeyName(alias_); - return s.str(); -} - -std::string KeyBlobEntry::getCharacteristicsBlobPath() const { - std::stringstream s; - if (!masterkey_) - s << user_dir_ << "/" - << "." << uid_ << "_chr_" << encodeKeyName(alias_); - return s.str(); -} - -bool KeyBlobEntry::hasKeyBlob() const { - int trys = 3; - while (trys--) { - if (!access(getKeyBlobPath().c_str(), R_OK | W_OK)) return true; - if (errno == ENOENT) return false; - LOG(WARNING) << "access encountered " << strerror(errno) << " (" << errno << ")" - << " while checking for key blob"; - if (errno != EAGAIN) break; - } - return false; -} - -bool KeyBlobEntry::hasCharacteristicsBlob() const { - int trys = 3; - while (trys--) { - if (!access(getCharacteristicsBlobPath().c_str(), R_OK | W_OK)) return true; - if (errno == ENOENT) return false; - LOG(WARNING) << "access encountered " << strerror(errno) << " (" << errno << ")" - << " while checking for key characteristics blob"; - if (errno != EAGAIN) break; - } - return false; -} - -static std::tuple filename2UidAlias(const std::string& filepath) { - std::tuple result; - - auto& [success, uid, alias] = result; - - success = false; - - auto filenamebase = filepath.find_last_of('/'); - std::string filename = - filenamebase == std::string::npos ? filepath : filepath.substr(filenamebase + 1); - - if (filename[0] == '.') return result; - - auto sep = filename.find('_'); - if (sep == std::string::npos) return result; - - std::stringstream s(filename.substr(0, sep)); - s >> uid; - if (!s) return result; - - alias = decodeKeyName(filename.substr(sep + 1)); - success = true; - return result; -} - -std::tuple> -LockedKeyBlobEntry::list(const std::string& user_dir, - std::function filter) { - std::list matches; - - // This is a fence against any concurrent database accesses during database iteration. - // Only the keystore thread can lock entries. So it cannot be starved - // by workers grabbing new individual locks. We just wait here until all - // workers have relinquished their locked files. - std::unique_lock lock(locked_blobs_mutex_); - locked_blobs_mutex_cond_var_.wait(lock, [&] { return locked_blobs_.empty(); }); - - DIR* dir = opendir(user_dir.c_str()); - if (!dir) { - ALOGW("can't open directory for user: %s", strerror(errno)); - return std::tuple&&>{ResponseCode::SYSTEM_ERROR, - std::move(matches)}; - } - - struct dirent* file; - while ((file = readdir(dir)) != nullptr) { - // We only care about files. - if (file->d_type != DT_REG) { - continue; - } - - // Skip anything that starts with a "." - if (file->d_name[0] == '.') { - continue; - } - - auto [success, uid, alias] = filename2UidAlias(file->d_name); - - if (!success) { - ALOGW("could not parse key filename \"%s\"", file->d_name); - continue; - } - - if (!filter(uid, alias)) continue; - - auto [iterator, dummy] = locked_blobs_.emplace(alias, user_dir, uid); - matches.push_back(*iterator); - } - closedir(dir); - return std::tuple&&>{ResponseCode::NO_ERROR, - std::move(matches)}; -} diff --git a/keystore/blob.h b/keystore/blob.h deleted file mode 100644 index e0bd1469..00000000 --- a/keystore/blob.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 2015 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_BLOB_H_ -#define KEYSTORE_BLOB_H_ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -constexpr size_t kValueSize = 32768; -constexpr size_t kAesKeySize = 128 / 8; -constexpr size_t kGcmTagLength = 128 / 8; -constexpr size_t kGcmIvLength = 96 / 8; -constexpr size_t kAes128KeySizeBytes = 128 / 8; -constexpr size_t kAes256KeySizeBytes = 256 / 8; - -/* Here is the file format. There are two parts in blob.value, the secret and - * the description. The secret is stored in ciphertext, and its original size - * can be found in blob.length. The description is stored after the secret in - * plaintext, and its size is specified in blob.info. The total size of the two - * parts must be no more than kValueSize bytes. The first field is the version, - * the second is the blob's type, and the third byte is flags. Fields other - * than blob.info, blob.length, and blob.value are modified by encryptBlob() - * and decryptBlob(). Thus they should not be accessed from outside. */ - -struct __attribute__((packed)) blobv3 { - uint8_t version; - uint8_t type; - uint8_t flags; - uint8_t info; - uint8_t initialization_vector[AES_BLOCK_SIZE]; // Only 96 bits is used, rest is zeroed. - uint8_t aead_tag[kGcmTagLength]; - int32_t length; // in network byte order, only for backward compatibility - uint8_t value[kValueSize + AES_BLOCK_SIZE]; -}; - -struct __attribute__((packed)) blobv2 { - uint8_t version; - uint8_t type; - uint8_t flags; - uint8_t info; - uint8_t vector[AES_BLOCK_SIZE]; - uint8_t encrypted[0]; // Marks offset to encrypted data. - uint8_t digest[MD5_DIGEST_LENGTH]; - uint8_t digested[0]; // Marks offset to digested data. - int32_t length; // in network byte order - uint8_t value[kValueSize + AES_BLOCK_SIZE]; -}; - -static_assert(sizeof(blobv3) == sizeof(blobv2) && - offsetof(blobv3, initialization_vector) == offsetof(blobv2, vector) && - offsetof(blobv3, aead_tag) == offsetof(blobv2, digest) && - offsetof(blobv3, aead_tag) == offsetof(blobv2, encrypted) && - offsetof(blobv3, length) == offsetof(blobv2, length) && - offsetof(blobv3, value) == offsetof(blobv2, value), - "Oops. Blob layout changed."); - -static const uint8_t CURRENT_BLOB_VERSION = 3; - -typedef enum { - TYPE_ANY = 0, // meta type that matches anything - TYPE_GENERIC = 1, - TYPE_MASTER_KEY = 2, - TYPE_KEY_PAIR = 3, - TYPE_KEYMASTER_10 = 4, - TYPE_KEY_CHARACTERISTICS = 5, - TYPE_KEY_CHARACTERISTICS_CACHE = 6, - TYPE_MASTER_KEY_AES256 = 7, -} BlobType; - -class LockedKeyBlobEntry; - -/** - * The Blob represents the content of a KeyBlobEntry. - * - * BEWARE: It is only save to call any member function of a Blob b if bool(b) yields true. - * Exceptions are putKeyCharacteristics(), the assignment operators and operator bool. - */ -class Blob { - friend LockedKeyBlobEntry; - - public: - Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength, - BlobType type); - explicit Blob(blobv3 b); - Blob(); - Blob(const Blob& rhs); - Blob(Blob&& rhs); - - ~Blob() { - if (mBlob) *mBlob = {}; - } - - Blob& operator=(const Blob& rhs); - Blob& operator=(Blob&& rhs); - explicit operator bool() const { return bool(mBlob); } - - const uint8_t* getValue() const { return mBlob->value; } - - int32_t getLength() const { return mBlob->length; } - - const uint8_t* getInfo() const { return mBlob->value + mBlob->length; } - uint8_t getInfoLength() const { return mBlob->info; } - - uint8_t getVersion() const { return mBlob->version; } - - bool isEncrypted() const; - void setEncrypted(bool encrypted); - - bool isSuperEncrypted() const; - void setSuperEncrypted(bool superEncrypted); - - bool isCriticalToDeviceEncryption() const; - void setCriticalToDeviceEncryption(bool critical); - - bool isFallback() const { return mBlob->flags & KEYSTORE_FLAG_FALLBACK; } - void setFallback(bool fallback); - - void setVersion(uint8_t version) { mBlob->version = version; } - BlobType getType() const { return BlobType(mBlob->type); } - void setType(BlobType type) { mBlob->type = uint8_t(type); } - - keystore::SecurityLevel getSecurityLevel() const; - void setSecurityLevel(keystore::SecurityLevel); - - std::tuple - getKeyCharacteristics() const; - - bool putKeyCharacteristics(const keystore::AuthorizationSet& hwEnforced, - const keystore::AuthorizationSet& swEnforced); - - private: - std::unique_ptr mBlob; - - ResponseCode readBlob(const std::string& filename, const std::vector& aes_key, - State state); -}; - -/** - * A KeyBlobEntry represents a full qualified key blob as known by Keystore. The key blob - * is given by the uid of the owning app and the alias used by the app to refer to this key. - * The user_dir_ is technically implied by the uid, but computation of the user directory is - * done in the user state database. Which is why we also cache it here. - * - * The KeyBlobEntry knows the location of the key blob files (which may include a characteristics - * cache file) but does not allow read or write access to the content. It also does not imply - * the existence of the files. - * - * KeyBlobEntry abstracts, to some extent, from the the file system based storage of key blobs. - * An evolution of KeyBlobEntry may be used for key blob storage based on a back end other than - * file system, e.g., SQL database or other. - * - * For access to the key blob content the programmer has to acquire a LockedKeyBlobEntry (see - * below). - */ -class KeyBlobEntry { - private: - std::string alias_; - std::string user_dir_; - uid_t uid_; - bool masterkey_; - - public: - KeyBlobEntry(std::string alias, std::string user_dir, uid_t uid, bool masterkey = false) - : alias_(std::move(alias)), user_dir_(std::move(user_dir)), uid_(uid), - masterkey_(masterkey) {} - - std::string getKeyBlobBaseName() const; - std::string getKeyBlobPath() const; - - std::string getCharacteristicsBlobBaseName() const; - std::string getCharacteristicsBlobPath() const; - - bool hasKeyBlob() const; - bool hasCharacteristicsBlob() const; - - bool operator<(const KeyBlobEntry& rhs) const { - return std::tie(uid_, alias_, user_dir_) < std::tie(rhs.uid_, rhs.alias_, rhs.user_dir_); - } - bool operator==(const KeyBlobEntry& rhs) const { - return std::tie(uid_, alias_, user_dir_) == std::tie(rhs.uid_, rhs.alias_, rhs.user_dir_); - } - bool operator!=(const KeyBlobEntry& rhs) const { return !(*this == rhs); } - - inline const std::string& alias() const { return alias_; } - inline const std::string& user_dir() const { return user_dir_; } - inline uid_t uid() const { return uid_; } -}; - -/** - * The LockedKeyBlobEntry is a proxy object to KeyBlobEntry that expresses exclusive ownership - * of a KeyBlobEntry. LockedKeyBlobEntries can be acquired by calling - * LockedKeyBlobEntry::get() or LockedKeyBlobEntry::list(). - * - * LockedKeyBlobEntries are movable but not copyable. By convention they can only - * be taken by the dispatcher thread of keystore, but not by any keymaster worker thread. - * The dispatcher thread may transfer ownership of a locked entry to a keymaster worker thread. - * - * Locked entries are tracked on the stack or as members of movable functor objects passed to the - * keymaster worker request queues. Locks are relinquished as the locked entry gets destroyed, e.g., - * when it goes out of scope or when the owning request functor gets destroyed. - * - * LockedKeyBlobEntry::list(), which must only be called by the dispatcher, blocks until all - * LockedKeyBlobEntries have been destroyed. Thereby list acts as a fence to make sure it gets a - * consistent view of the key blob database. Under the assumption that keymaster worker requests - * cannot run or block indefinitely and cannot grab new locked entries, progress is guaranteed. - * It then grabs locked entries in accordance with the given filter rule. - * - * LockedKeyBlobEntry allow access to the proxied KeyBlobEntry interface through the operator->. - * They add additional functionality to access and modify the key blob's content on disk. - * LockedKeyBlobEntry ensures atomic operations on the persistently stored key blobs on a per - * entry granularity. - */ -class LockedKeyBlobEntry { - private: - static std::set locked_blobs_; - static std::mutex locked_blobs_mutex_; - static std::condition_variable locked_blobs_mutex_cond_var_; - - const KeyBlobEntry* entry_; - // NOLINTNEXTLINE(google-explicit-constructor) - LockedKeyBlobEntry(const KeyBlobEntry& entry) : entry_(&entry) {} - - static void put(const KeyBlobEntry& entry); - LockedKeyBlobEntry(const LockedKeyBlobEntry&) = delete; - LockedKeyBlobEntry& operator=(const LockedKeyBlobEntry&) = delete; - - public: - LockedKeyBlobEntry() : entry_(nullptr){}; - ~LockedKeyBlobEntry(); - LockedKeyBlobEntry(LockedKeyBlobEntry&& rhs) : entry_(rhs.entry_) { rhs.entry_ = nullptr; } - LockedKeyBlobEntry& operator=(LockedKeyBlobEntry&& rhs) { - // as dummy goes out of scope it relinquishes the lock on this - LockedKeyBlobEntry dummy(std::move(*this)); - entry_ = rhs.entry_; - rhs.entry_ = nullptr; - return *this; - } - static LockedKeyBlobEntry get(KeyBlobEntry entry); - static std::tuple> - list(const std::string& user_dir, - std::function filter = - [](uid_t, const std::string&) -> bool { return true; }); - - ResponseCode writeBlobs(Blob keyBlob, Blob characteristicsBlob, - const std::vector& aes_key, State state) const; - std::tuple readBlobs(const std::vector& aes_key, - State state) const; - ResponseCode deleteBlobs() const; - - inline explicit operator bool() const { return entry_ != nullptr; } - inline const KeyBlobEntry& operator*() const { return *entry_; } - inline const KeyBlobEntry* operator->() const { return entry_; } -}; - -// Visible for testing -std::string encodeKeyName(const std::string& keyName); -std::string decodeKeyName(const std::string& encodedName); - -#endif // KEYSTORE_BLOB_H_ diff --git a/keystore/confirmation_manager.cpp b/keystore/confirmation_manager.cpp deleted file mode 100644 index 76df1cc6..00000000 --- a/keystore/confirmation_manager.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#define LOG_TAG "ConfirmationManager" - -#include "confirmation_manager.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "keystore_aidl_hidl_marshalling_utils.h" - -namespace keystore { - -using android::IBinder; -using android::sp; -using android::String16; -using android::String8; -using android::wp; -using android::binder::Status; -using android::hardware::hidl_vec; -using android::hardware::Return; -using android::hardware::confirmationui::V1_0::IConfirmationResultCallback; -using android::hardware::confirmationui::V1_0::IConfirmationUI; -using android::hardware::confirmationui::V1_0::UIOption; - -using android::security::BpConfirmationPromptCallback; -using std::lock_guard; -using std::mutex; -using std::vector; - -ConfirmationManager::ConfirmationManager(IBinder::DeathRecipient* deathRecipient) - : IConfirmationResultCallback(), mDeathRecipient(deathRecipient) {} - -// Called by keystore main thread. -Status ConfirmationManager::presentConfirmationPrompt(const sp& listener, - const String16& promptText, - const hidl_vec& extraData, - const String16& locale, int uiOptionsAsFlags, - int32_t* aidl_return) { - lock_guard lock(mMutex); - - if (mCurrentListener != nullptr) { - *aidl_return = static_cast(ConfirmationResponseCode::OperationPending); - return Status::ok(); - } - - sp confirmationUI = IConfirmationUI::tryGetService(); - if (confirmationUI == nullptr) { - ALOGW("Error getting confirmationUI service\n"); - *aidl_return = static_cast(ConfirmationResponseCode::Unimplemented); - return Status::ok(); - } - - uid_t callingUid = android::IPCThreadState::self()->getCallingUid(); - if (!mRateLimiting.tryPrompt(callingUid)) { - *aidl_return = static_cast(ConfirmationResponseCode::SystemError); - return Status::ok(); - } - - String8 promptText8(promptText); - String8 locale8(locale); - vector uiOptionsVector; - for (int n = 0; n < 32; n++) { - if (uiOptionsAsFlags & (1 << n)) { - uiOptionsVector.push_back(UIOption(n)); - } - } - ConfirmationResponseCode responseCode; - responseCode = confirmationUI->promptUserConfirmation(sp(this), - promptText8.string(), extraData, - locale8.string(), uiOptionsVector); - if (responseCode != ConfirmationResponseCode::OK) { - ALOGW("Unexpecxted responseCode %d from promptUserConfirmation\n", responseCode); - *aidl_return = static_cast(responseCode); - return Status::ok(); - } - - listener->linkToDeath(mDeathRecipient); - confirmationUI->linkToDeath(this, 0); - mCurrentListener = listener; - mCurrentConfirmationUI = confirmationUI; - - *aidl_return = static_cast(ConfirmationResponseCode::OK); - return Status::ok(); -} - -// Called by keystore main thread. -Status ConfirmationManager::cancelConfirmationPrompt(const sp& listener, - int32_t* aidl_return) { - mMutex.lock(); - if (mCurrentListener != listener) { - // If the prompt was displayed by another application, return - // OperationPending. - mMutex.unlock(); - *aidl_return = static_cast(ConfirmationResponseCode::OperationPending); - return Status::ok(); - } - mMutex.unlock(); - - cancelPrompt(); - - *aidl_return = static_cast(ConfirmationResponseCode::OK); - return Status::ok(); -} - -void ConfirmationManager::cancelPrompt() { - mMutex.lock(); - mRateLimiting.cancelPrompt(); - sp confirmationUI = mCurrentConfirmationUI; - mMutex.unlock(); - if (confirmationUI != nullptr) { - confirmationUI->abort(); - } -} - -// Called by keystore main thread. -Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) { - sp confirmationUI = IConfirmationUI::tryGetService(); - if (confirmationUI == nullptr) { - ALOGW("Error getting confirmationUI service\n"); - *aidl_return = false; - return Status::ok(); - } - - *aidl_return = true; - return Status::ok(); -} - -void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseCode, - hidl_vec dataThatWasConfirmed) { - mMutex.lock(); - mRateLimiting.processResult(responseCode); - sp listener = mCurrentListener; - if (mCurrentListener != nullptr) { - mCurrentListener->unlinkToDeath(mDeathRecipient); - mCurrentListener = nullptr; - } - if (mCurrentConfirmationUI != nullptr) { - mCurrentConfirmationUI->unlinkToDeath(this); - mCurrentConfirmationUI = nullptr; - } - mMutex.unlock(); - - // Deliver result to the application that started the operation. - if (listener != nullptr) { - sp obj = new BpConfirmationPromptCallback(listener); - Status status = obj->onConfirmationPromptCompleted(static_cast(responseCode), - dataThatWasConfirmed); - if (!status.isOk()) { - ALOGW("Error sending onConfirmationPromptCompleted - status: %s\n", - status.toString8().c_str()); - } - } -} - -// Called by hwbinder thread (not keystore main thread). -Return ConfirmationManager::result(ConfirmationResponseCode responseCode, - const hidl_vec& dataThatWasConfirmed, - const hidl_vec& confirmationToken) { - finalizeTransaction(responseCode, dataThatWasConfirmed); - lock_guard lock(mMutex); - mLatestConfirmationToken = confirmationToken; - return Return(); -} - -// Called by keystore main thread or keymaster worker -hidl_vec ConfirmationManager::getLatestConfirmationToken() { - lock_guard lock(mMutex); - return mLatestConfirmationToken; -} - -void ConfirmationManager::binderDied(const wp& who) { - // This is also called for other binders so need to check it's for - // us before acting on it. - mMutex.lock(); - if (who == mCurrentListener) { - // Clear this so we don't call back into the already dead - // binder in finalizeTransaction(). - mCurrentListener->unlinkToDeath(mDeathRecipient); - mCurrentListener = nullptr; - mMutex.unlock(); - ALOGW("The process which requested the confirmation dialog died.\n"); - cancelPrompt(); - } else { - mMutex.unlock(); - } -} - -void ConfirmationManager::serviceDied(uint64_t /* cookie */, - const wp& /* who */) { - ALOGW("The ConfirmationUI HAL died.\n"); - finalizeTransaction(ConfirmationResponseCode::SystemError, {}); -} - -} // namespace keystore diff --git a/keystore/confirmation_manager.h b/keystore/confirmation_manager.h deleted file mode 100644 index 7f0a11da..00000000 --- a/keystore/confirmation_manager.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2017 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_CONFIRMATION_MANAGER_H_ -#define KEYSTORE_CONFIRMATION_MANAGER_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "confirmationui_rate_limiting.h" - -namespace keystore { - -using android::binder::Status; -using android::hardware::confirmationui::V1_0::IConfirmationResultCallback; -using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode; - -class ConfirmationManager; - -class ConfirmationManager : public android::hardware::hidl_death_recipient, - public IConfirmationResultCallback { - public: - explicit ConfirmationManager(android::IBinder::DeathRecipient* deathRecipient); - - // Calls into the confirmationui HAL to start a new prompt. - // - // Returns OperationPending if another application is already - // showing a confirmation. Otherwise returns the return code from - // the HAL. - Status presentConfirmationPrompt(const android::sp& listener, - const android::String16& promptText, - const hidl_vec& extraData, - const android::String16& locale, int uiOptionsAsFlags, - int32_t* aidl_return); - - // Calls into the confirmationui HAL to cancel displaying a - // prompt. - // - // Returns OperatingPending if another application is showing a - // confirmation. Otherwise returns the return code from the HAL. - Status cancelConfirmationPrompt(const android::sp& listener, - int32_t* aidl_return); - - // Checks if the confirmationUI HAL is available. - Status isConfirmationPromptSupported(bool* aidl_return); - - // Gets the latest confirmation token received from the ConfirmationUI HAL. - hidl_vec getLatestConfirmationToken(); - - // Called by KeyStoreService when a client binder has died. - void binderDied(const android::wp& who); - - // hidl_death_recipient overrides: - virtual void serviceDied(uint64_t cookie, - const android::wp& who) override; - - // IConfirmationResultCallback overrides: - android::hardware::Return result(ConfirmationResponseCode responseCode, - const hidl_vec& dataThatWasConfirmed, - const hidl_vec& confirmationToken) override; - - private: - friend class ConfirmationResultCallback; - - // Set rate limiting to not decrement on next abort and aborts - // confirmationui. - void cancelPrompt(); - - void finalizeTransaction(ConfirmationResponseCode responseCode, - hidl_vec dataThatWasConfirmed); - - // This mutex protects all data below it. - std::mutex mMutex; - - // The mCurrentListener and mCurrentConfirmationUI fields are set - // if and only if a prompt is currently showing. - android::sp mCurrentListener; - android::sp mCurrentConfirmationUI; - android::IBinder::DeathRecipient* mDeathRecipient; - hidl_vec mLatestConfirmationToken; - RateLimiting<> mRateLimiting; -}; - -} // namespace keystore - -#endif // KEYSTORE_CONFIRMATION_MANAGER_H_ diff --git a/keystore/confirmationui_rate_limiting.h b/keystore/confirmationui_rate_limiting.h deleted file mode 100644 index 658bf416..00000000 --- a/keystore/confirmationui_rate_limiting.h +++ /dev/null @@ -1,134 +0,0 @@ -/* -** -** 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_CONFIRMATIONUI_RATE_LIMITING_H_ -#define KEYSTORE_CONFIRMATIONUI_RATE_LIMITING_H_ - -#include -#include -#include -#include -#include -#include - -namespace keystore { - -using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode; - -using std::chrono::duration; -using std::chrono::time_point; - -template class RateLimiting { - private: - struct Slot { - Slot() : previous_start{}, prompt_start{}, counter(0) {} - typename Clock::time_point previous_start; - typename Clock::time_point prompt_start; - uint32_t counter; - }; - - std::unordered_map slots_; - - uint_t latest_requester_; - - static std::chrono::seconds getBackoff(uint32_t counter) { - using namespace std::chrono_literals; - switch (counter) { - case 0: - case 1: - case 2: - return 0s; - case 3: - case 4: - case 5: - return 30s; - default: - return 60s * (1ULL << (counter - 6)); - } - } - - public: - // Exposes the number of used slots. This is only used by the test to verify the assumption - // about used counter slots. - size_t usedSlots() const { return slots_.size(); } - void doGC() { - using namespace std::chrono_literals; - using std::chrono::system_clock; - using std::chrono::time_point_cast; - auto then = Clock::now() - 24h; - auto iter = slots_.begin(); - while (iter != slots_.end()) { - if (iter->second.prompt_start <= then) { - iter = slots_.erase(iter); - } else { - ++iter; - } - } - } - - bool tryPrompt(uid_t id) { - using namespace std::chrono_literals; - // remove slots that have not been touched in 24 hours - doGC(); - auto& slot = slots_[id]; - auto now = Clock::now(); - if (!slot.counter || slot.prompt_start <= now - getBackoff(slot.counter)) { - latest_requester_ = id; - slot.counter += 1; - slot.previous_start = slot.prompt_start; - slot.prompt_start = now; - return true; - } - return false; - } - - // The app is penalized for cancelling a request. Request are rolled back only if - // the prompt was cancelled by the system: e.g. a system error or asynchronous event. - // When the user cancels the prompt, it is subject to rate limiting. - static constexpr const uint_t kInvalidRequester = -1; - - void cancelPrompt() { latest_requester_ = kInvalidRequester; } - - void processResult(ConfirmationResponseCode rc) { - if (latest_requester_ == kInvalidRequester) { - return; - } - switch (rc) { - case ConfirmationResponseCode::OK: - // reset the counter slot - slots_.erase(latest_requester_); - return; - case ConfirmationResponseCode::Canceled: - // nothing to do here - return; - default:; - } - - // roll back latest request - auto& slot = slots_[latest_requester_]; - if (slot.counter <= 1) { - slots_.erase(latest_requester_); - return; - } - slot.counter -= 1; - slot.prompt_start = slot.previous_start; - } -}; - -} // namespace keystore - -#endif // KEYSTORE_CONFIRMATIONUI_RATE_LIMITING_H_ diff --git a/keystore/defaults.h b/keystore/defaults.h deleted file mode 100644 index 6f7ff2d7..00000000 --- a/keystore/defaults.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 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_DEFAULTS_H_ -#define KEYSTORE_DEFAULTS_H_ - -/* - * These must be kept in sync with - * frameworks/base/keystore/java/android/security/KeyPairGeneratorSpec.java - */ - -/* DSA */ -constexpr int32_t DSA_DEFAULT_KEY_SIZE = 1024; -constexpr int32_t DSA_MIN_KEY_SIZE = 512; -constexpr int32_t DSA_MAX_KEY_SIZE = 8192; - -/* EC */ -constexpr int32_t EC_DEFAULT_KEY_SIZE = 256; -constexpr int32_t EC_MIN_KEY_SIZE = 192; -constexpr int32_t EC_MAX_KEY_SIZE = 521; - -/* RSA */ -constexpr int32_t RSA_DEFAULT_KEY_SIZE = 2048; -constexpr int32_t RSA_DEFAULT_EXPONENT = 0x10001; -constexpr int32_t RSA_MIN_KEY_SIZE = 512; -constexpr int32_t RSA_MAX_KEY_SIZE = 8192; - -#endif /* KEYSTORE_DEFAULTS_H_ */ diff --git a/keystore/grant_store.cpp b/keystore/grant_store.cpp deleted file mode 100644 index 9e627ce4..00000000 --- a/keystore/grant_store.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#include "grant_store.h" - -#include "blob.h" -#include -#include - -namespace keystore { - -static constexpr uint64_t kInvalidGrantNo = std::numeric_limits::max(); -static const char* kKeystoreGrantInfix = "_KEYSTOREGRANT_"; -static constexpr size_t kKeystoreGrantInfixLength = 15; - -Grant::Grant(const KeyBlobEntry& entry, const uint64_t grant_no) - : entry_(entry), grant_no_(grant_no) {} - -static std::pair parseGrantAlias(const std::string& grantAlias) { - auto pos = grantAlias.rfind(kKeystoreGrantInfix); - if (pos == std::string::npos) return {kInvalidGrantNo, ""}; - std::stringstream s(grantAlias.substr(pos + kKeystoreGrantInfixLength)); - std::string wrapped_alias = grantAlias.substr(0, pos); - uint64_t grant_no = kInvalidGrantNo; - s >> grant_no; - if (s.fail() || grant_no == kInvalidGrantNo) return {kInvalidGrantNo, ""}; - return {grant_no, wrapped_alias}; -} - -std::string GrantStore::put(const uid_t uid, const LockedKeyBlobEntry& lockedEntry) { - std::unique_lock lock(mutex_); - std::stringstream s; - KeyBlobEntry blobEntry = *lockedEntry; - s << blobEntry.alias() << kKeystoreGrantInfix; - - std::set>& uid_grant_list = grants_[uid]; - - bool success = false; - auto iterator = - std::find_if(uid_grant_list.begin(), uid_grant_list.end(), - [&](const Grant& entry) { return success = entry.entry_ == blobEntry; }); - while (!success) { - std::tie(iterator, success) = uid_grant_list.emplace(blobEntry, std::rand()); - } - s << iterator->grant_no_; - return s.str(); -} - -ReadLockedGrant GrantStore::get(const uid_t uid, const std::string& alias) const { - std::shared_lock lock(mutex_); - uint64_t grant_no; - std::string wrappedAlias; - std::tie(grant_no, wrappedAlias) = parseGrantAlias(alias); - if (grant_no == kInvalidGrantNo) return {}; - auto uid_set_iter = grants_.find(uid); - if (uid_set_iter == grants_.end()) return {}; - auto& uid_grant_list = uid_set_iter->second; - auto grant = uid_grant_list.find(grant_no); - if (grant == uid_grant_list.end()) return {}; - if (grant->entry_.alias() != wrappedAlias) return {}; - return {&(*grant), std::move(lock)}; -} - -bool GrantStore::removeByFileAlias(const uid_t granteeUid, const LockedKeyBlobEntry& lockedEntry) { - std::unique_lock lock(mutex_); - auto& uid_grant_list = grants_[granteeUid]; - for (auto i = uid_grant_list.begin(); i != uid_grant_list.end(); ++i) { - if (i->entry_ == *lockedEntry) { - uid_grant_list.erase(i); - return true; - } - } - return false; -} - -void GrantStore::removeAllGrantsToKey(const uid_t granterUid, const std::string& alias) { - std::unique_lock lock(mutex_); - for (auto& uid_grant_list : grants_) { - for (auto i = uid_grant_list.second.begin(); i != uid_grant_list.second.end(); ++i) { - if (i->entry_.alias() == alias && i->entry_.uid() == granterUid) { - uid_grant_list.second.erase(i); - break; - } - } - } -} - -void GrantStore::removeAllGrantsToUid(const uid_t granteeUid) { - std::unique_lock lock(mutex_); - grants_.erase(granteeUid); -} - -} // namespace keystore diff --git a/keystore/grant_store.h b/keystore/grant_store.h deleted file mode 100644 index 1baf32c3..00000000 --- a/keystore/grant_store.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2017 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_GRANT_STORE_H_ -#define KEYSTORE_GRANT_STORE_H_ - -#include -#include -#include -#include -#include - -#include - -#include "blob.h" - -namespace keystore { - -class Grant; - -using ReadLockedGrant = - ProxyLock>; - -/** - * Grant represents a mapping from an alias to a key file. - * Normally, key file names are derived from the alias chosen by the client - * and the clients UID, to generate a per client name space. - * Grants allow assotiating a key file with a new name, thereby making - * it visible in another client's - the grantee's - namespace. - */ -class Grant { -public: - Grant(const KeyBlobEntry& entry, const uint64_t grant_no); - KeyBlobEntry entry_; - - uint64_t grant_no_; ///< numeric grant identifier - randomly assigned - - // NOLINTNEXTLINE(google-explicit-constructor) - operator const uint64_t&() const { return grant_no_; } -}; - -/** - * The GrantStore holds a set of sets of Grants. One set of Grants for each grantee. - * The uid parameter to each of the GrantStore function determines the grantee's - * name space. The methods put, get, and removeByAlias/ByFileName create, lookup, and - * remove a Grant, respectively. - * put also returns a new alias for the newly granted key which has to be returned - * to the granter. The grantee, and only the grantee, can use the granted key - * by this new alias. - */ -class GrantStore { -public: - GrantStore() : grants_() {} - std::string put(const uid_t uid, const LockedKeyBlobEntry& blobfile); - ReadLockedGrant get(const uid_t uid, const std::string& alias) const; - bool removeByFileAlias(const uid_t granteeUid, const LockedKeyBlobEntry& lockedEntry); - void removeAllGrantsToKey(const uid_t granterUid, const std::string& alias); - void removeAllGrantsToUid(const uid_t granteeUid); - - // GrantStore is neither copyable nor movable. - GrantStore(const GrantStore&) = delete; - GrantStore& operator=(const GrantStore&) = delete; -private: - std::unordered_map>> grants_; - mutable std::shared_mutex mutex_; -}; - -} // namespace keystore - -#endif // KEYSTORE_GRANT_STORE_H_ diff --git a/keystore/key_attestation_log_handler.cpp b/keystore/key_attestation_log_handler.cpp deleted file mode 100644 index c3278cb5..00000000 --- a/keystore/key_attestation_log_handler.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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. - */ -#include -namespace keystore { - -void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode) { - // Due to a requirement in stats-write() method, the optional fields - // which are not required for attestation logging, are marked with -1 for - // non-repeated fields and 0 for repeated fields. - android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED, -1, -1, -1, -1, -1, 0, 0, - 0, 0, -1, -1, - android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_ATTESTATION, - wasSuccessful, errorCode); -} - -} // namespace keystore \ No newline at end of file diff --git a/keystore/key_attestation_log_handler.h b/keystore/key_attestation_log_handler.h deleted file mode 100644 index a418bfa3..00000000 --- a/keystore/key_attestation_log_handler.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 _KEY_ATTESTATION_LOG_HANDLER_H_ -#define _KEY_ATTESTATION_LOG_HANDLER_H_ - -namespace keystore { - -void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode); - -} - -#endif //_KEY_ATTESTATION_LOG_HANDLER_H_ diff --git a/keystore/key_creation_log_handler.cpp b/keystore/key_creation_log_handler.cpp deleted file mode 100644 index d8462576..00000000 --- a/keystore/key_creation_log_handler.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "KeystoreOperation" - -#include "key_creation_log_handler.h" -#include - -namespace keystore { - -template -int32_t getEnumTagValue(const AuthorizationSet& authorization_set, Tag tag) { - auto tagValue = authorization_set.GetTagValue(tag); - if (tagValue.isOk()) { - static_assert(sizeof(decltype(tagValue.value())) <= sizeof(int32_t), - "Tag type value will be truncated, if cast to int32_t"); - return static_cast(tagValue.value()); - } - // Usually, if the value is not present, 0 is set. However, since 0 is a valid - // enum value, -1 is set for single enum fields. - return -1; -} - -int32_t generateBitMapForPaddingModeValues(const AuthorizationSet& authorization_set) { - int32_t bitMap = 0; - int32_t tagValueCount = authorization_set.GetTagCount(TAG_PADDING); - if (tagValueCount == 0) { - // unlike in the single enum fields, if no value is provided, - // 0 is set for the bitmap - return bitMap; - } - int current_offset = -1; - while (tagValueCount > 0) { - current_offset = authorization_set.find(TAG_PADDING, current_offset); - KeyParameter keyParam = authorization_set[current_offset]; - auto tagValue = accessTagValue(TAG_PADDING, keyParam); - switch (tagValue) { - case PaddingMode::NONE: - bitMap |= (1 << NONE_BIT_POS); - break; - case PaddingMode::RSA_OAEP: - bitMap |= (1 << PaddingModeBitPosition::RSA_OAEP_BIT_POS); - break; - case PaddingMode::RSA_PSS: - bitMap |= (1 << PaddingModeBitPosition::RSA_PSS_BIT_POS); - break; - case PaddingMode::RSA_PKCS1_1_5_ENCRYPT: - bitMap |= (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_ENCRYPT_BIT_POS); - break; - case PaddingMode::RSA_PKCS1_1_5_SIGN: - bitMap |= (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_SIGN_BIT_POS); - break; - case PaddingMode::PKCS7: - bitMap |= (1 << PaddingModeBitPosition::PKCS7_BIT_POS); - break; - default: - break; - } - tagValueCount -= 1; - } - return bitMap; -} - -int32_t generateBitMapForDigestValues(const AuthorizationSet& authorization_set) { - int32_t bitMap = 0; - int32_t tagValueCount = authorization_set.GetTagCount(TAG_DIGEST); - if (tagValueCount == 0) { - // unlike in the single enum fields, if no value is provided, - // 0 is set for the bitmap - return bitMap; - } - int current_offset = -1; - while (tagValueCount > 0) { - current_offset = authorization_set.find(TAG_DIGEST, current_offset); - KeyParameter keyParam = authorization_set[current_offset]; - auto tagValue = accessTagValue(TAG_DIGEST, keyParam); - switch (tagValue) { - case Digest::NONE: - bitMap |= (1 << NONE_BIT_POS); - break; - case Digest::MD5: - bitMap |= (1 << DigestBitPosition::MD5_BIT_POS); - break; - case Digest::SHA1: - bitMap |= (1 << DigestBitPosition::SHA1_BIT_POS); - break; - case Digest::SHA_2_224: - bitMap |= (1 << DigestBitPosition::SHA_2_224_BIT_POS); - break; - case Digest::SHA_2_256: - bitMap |= (1 << DigestBitPosition::SHA_2_256_BIT_POS); - break; - case Digest::SHA_2_384: - bitMap |= (1 << DigestBitPosition::SHA_2_384_BIT_POS); - break; - case Digest::SHA_2_512: - bitMap |= (1 << DigestBitPosition::SHA_2_512_BIT_POS); - break; - default: - break; - } - tagValueCount -= 1; - } - return bitMap; -} - -int32_t generateBitMapForBlockModeValues(const AuthorizationSet& authorization_set) { - int32_t bitMap = 0; - int32_t tagValueCount = authorization_set.GetTagCount(TAG_BLOCK_MODE); - if (tagValueCount == 0) { - // unlike in the single enum fields, if no value is provided, - // 0 is set for the bitmap - return bitMap; - } - int current_offset = -1; - while (tagValueCount > 0) { - current_offset = authorization_set.find(TAG_BLOCK_MODE, current_offset); - KeyParameter keyParam = authorization_set[current_offset]; - auto tagValue = accessTagValue(TAG_BLOCK_MODE, keyParam); - switch (tagValue) { - case BlockMode::ECB: - bitMap |= (1 << BlockModeBitPosition::ECB_BIT_POS); - break; - case BlockMode::CBC: - bitMap |= (1 << BlockModeBitPosition::CBC_BIT_POS); - break; - case BlockMode::CTR: - bitMap |= (1 << BlockModeBitPosition::CTR_BIT_POS); - break; - case BlockMode::GCM: - bitMap |= (1 << BlockModeBitPosition::GCM_BIT_POS); - break; - default: - break; - } - tagValueCount -= 1; - } - return bitMap; -} - -int32_t generateBitMapForKeyPurposeValues(const AuthorizationSet& authorization_set) { - int32_t bitMap = 0; - int32_t tagValueCount = authorization_set.GetTagCount(TAG_PURPOSE); - if (tagValueCount == 0) { - // unlike in the single enum fields, if no value is provided, - // 0 is set for the bitmap - return bitMap; - } - int current_offset = -1; - while (tagValueCount > 0) { - current_offset = authorization_set.find(TAG_PURPOSE, current_offset); - KeyParameter keyParam = authorization_set[current_offset]; - auto tagValue = accessTagValue(TAG_PURPOSE, keyParam); - switch (tagValue) { - case KeyPurpose::ENCRYPT: - bitMap |= (1 << KeyPurposeBitPosition::ENCRYPT_BIT_POS); - break; - case KeyPurpose::DECRYPT: - bitMap |= (1 << KeyPurposeBitPosition::DECRYPT_BIT_POS); - break; - case KeyPurpose::SIGN: - bitMap |= (1 << KeyPurposeBitPosition::SIGN_BIT_POS); - break; - case KeyPurpose::VERIFY: - bitMap |= (1 << KeyPurposeBitPosition::VERIFY_BIT_POS); - break; - case KeyPurpose::WRAP_KEY: - bitMap |= (1 << KeyPurposeBitPosition::WRAP_KEY_BIT_POS); - break; - default: - break; - } - tagValueCount -= 1; - } - return bitMap; -} - -void logKeystoreKeyCreationEvent(const hidl_vec& keyParams, - bool wasCreationSuccessful, int32_t errorCode) { - AuthorizationSet authorization_set(keyParams); - authorization_set.Deduplicate(); - - android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED, - getEnumTagValue(authorization_set, TAG_ALGORITHM), - getEnumTagValue(authorization_set, TAG_KEY_SIZE), - getEnumTagValue(authorization_set, TAG_ORIGIN), - getEnumTagValue(authorization_set, TAG_USER_AUTH_TYPE), - getEnumTagValue(authorization_set, TAG_AUTH_TIMEOUT), - generateBitMapForPaddingModeValues(authorization_set), - generateBitMapForDigestValues(authorization_set), - generateBitMapForBlockModeValues(authorization_set), - generateBitMapForKeyPurposeValues(authorization_set), - getEnumTagValue(authorization_set, TAG_EC_CURVE), - getEnumTagValue(authorization_set, TAG_BLOB_USAGE_REQUIREMENTS), - android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_CREATION, - wasCreationSuccessful, errorCode); -} - -} // namespace keystore diff --git a/keystore/key_creation_log_handler.h b/keystore/key_creation_log_handler.h deleted file mode 100644 index a314eb11..00000000 --- a/keystore/key_creation_log_handler.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 KEY_CREATION_LOG_HANDLER_H_ -#define KEY_CREATION_LOG_HANDLER_H_ - -#include - -namespace keystore { - -/** - * Following enums are defined as a part of the workaround to log the repeated - * values of ENUM_REP type. The workaround is to represent the repeated values - * of ENUM_REP type as a bitmap and the following enums define their positions - * in the bitmap. - */ - -enum PaddingModeBitPosition : int32_t { - RSA_OAEP_BIT_POS = 1, - RSA_PSS_BIT_POS = 2, - RSA_PKCS1_1_5_ENCRYPT_BIT_POS = 3, - RSA_PKCS1_1_5_SIGN_BIT_POS = 4, - PKCS7_BIT_POS = 5, -}; - -enum DigestBitPosition : int32_t { - MD5_BIT_POS = 1, - SHA1_BIT_POS = 2, - SHA_2_224_BIT_POS = 3, - SHA_2_256_BIT_POS = 4, - SHA_2_384_BIT_POS = 5, - SHA_2_512_BIT_POS = 6, -}; - -enum BlockModeBitPosition : int32_t { - ECB_BIT_POS = 1, - CBC_BIT_POS = 2, - CTR_BIT_POS = 3, - GCM_BIT_POS = 4, -}; - -enum KeyPurposeBitPosition : int32_t { - ENCRYPT_BIT_POS = 1, - DECRYPT_BIT_POS = 2, - SIGN_BIT_POS = 3, - VERIFY_BIT_POS = 4, - WRAP_KEY_BIT_POS = 5, -}; - -// None is an enum value for digest and a deprecated value for padding mode -const int32_t NONE_BIT_POS = 0; - -void logKeystoreKeyCreationEvent(const hidl_vec& keyParams, - bool wasCreationSuccessful, int32_t errorCode); - -} // namespace keystore - -#endif // KEY_CREATION_LOG_HANDLER_H_ diff --git a/keystore/key_operation_log_handler.cpp b/keystore/key_operation_log_handler.cpp deleted file mode 100644 index e7f43457..00000000 --- a/keystore/key_operation_log_handler.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "KeystoreOperation" - -#include "key_operation_log_handler.h" -#include "key_creation_log_handler.h" - -#include -#include - -namespace keystore { - -template -int32_t getOptionalEnumTagValue(const AuthorizationSet& authorization_set, Tag tag) { - auto tagValue = authorization_set.GetTagValue(tag); - if (tagValue.isOk()) { - static_assert(sizeof(decltype(tagValue.value())) <= sizeof(int32_t), - "Tag type value will be truncated, if cast to int32_t"); - return static_cast(tagValue.value()); - } - //-1 is an invalid value for all enum types. - return -1; -} - -int32_t generateBitMapForPaddingModeValue(const AuthorizationSet& authorization_set) { - auto tagValue = authorization_set.GetTagValue(TAG_PADDING); - if (tagValue.isOk()) { - auto value = tagValue.value(); - switch (value) { - case PaddingMode::NONE: - return (1 << NONE_BIT_POS); - case PaddingMode::RSA_OAEP: - return (1 << PaddingModeBitPosition::RSA_OAEP_BIT_POS); - case PaddingMode::RSA_PSS: - return (1 << PaddingModeBitPosition::RSA_PSS_BIT_POS); - case PaddingMode::RSA_PKCS1_1_5_ENCRYPT: - return (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_ENCRYPT_BIT_POS); - case PaddingMode::RSA_PKCS1_1_5_SIGN: - return (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_SIGN_BIT_POS); - case PaddingMode::PKCS7: - return (1 << PaddingModeBitPosition::PKCS7_BIT_POS); - default: - break; - } - } - // unlike in the single enum fields, if no value is provided, - // 0 is set for the bitmap - return 0; -} - -int32_t generateBitMapForDigestValue(const AuthorizationSet& authorization_set) { - auto tagValue = authorization_set.GetTagValue(TAG_DIGEST); - if (tagValue.isOk()) { - auto value = tagValue.value(); - switch (value) { - case Digest::NONE: - return (1 << NONE_BIT_POS); - case Digest::MD5: - return (1 << DigestBitPosition::MD5_BIT_POS); - case Digest::SHA1: - return (1 << DigestBitPosition::SHA1_BIT_POS); - case Digest::SHA_2_224: - return (1 << DigestBitPosition::SHA_2_224_BIT_POS); - case Digest::SHA_2_256: - return (1 << DigestBitPosition::SHA_2_256_BIT_POS); - case Digest::SHA_2_384: - return (1 << DigestBitPosition::SHA_2_384_BIT_POS); - case Digest::SHA_2_512: - return (1 << DigestBitPosition::SHA_2_512_BIT_POS); - default: - break; - } - } - // unlike in the single enum fields, if no value is provided, - // 0 is set for the bitmap - return 0; -} - -int32_t generateBitMapForBlockModeValue(const AuthorizationSet& authorization_set) { - auto tagValue = authorization_set.GetTagValue(TAG_BLOCK_MODE); - if (tagValue.isOk()) { - auto value = tagValue.value(); - switch (value) { - case BlockMode::ECB: - return (1 << BlockModeBitPosition::ECB_BIT_POS); - case BlockMode::CBC: - return (1 << BlockModeBitPosition::CBC_BIT_POS); - case BlockMode::CTR: - return (1 << BlockModeBitPosition::CTR_BIT_POS); - case BlockMode::GCM: - return (1 << BlockModeBitPosition::GCM_BIT_POS); - default: - break; - } - } - // unlike in the single enum fields, if no value is provided, - // 0 is set for the bitmap - return 0; -} - -void logKeystoreKeyOperationEvent(const Operation& op, bool wasOperationSuccessful, - int32_t responseCode) { - AuthorizationSet authorization_set(op.characteristics.softwareEnforced); - authorization_set.Union(op.characteristics.hardwareEnforced); - AuthorizationSet operation_params(op.params); - - android::util::stats_write( - android::util::KEYSTORE_KEY_EVENT_REPORTED, - getOptionalEnumTagValue(authorization_set, TAG_ALGORITHM), - getOptionalEnumTagValue(authorization_set, TAG_KEY_SIZE), - getOptionalEnumTagValue(authorization_set, TAG_ORIGIN), - getOptionalEnumTagValue(authorization_set, TAG_USER_AUTH_TYPE), - getOptionalEnumTagValue(authorization_set, TAG_AUTH_TIMEOUT), - generateBitMapForPaddingModeValue(operation_params), - generateBitMapForDigestValue(operation_params), - generateBitMapForBlockModeValue(operation_params), static_cast(op.purpose), - getOptionalEnumTagValue(authorization_set, TAG_EC_CURVE), - getOptionalEnumTagValue(authorization_set, TAG_BLOB_USAGE_REQUIREMENTS), - android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_OPERATION, wasOperationSuccessful, - responseCode); -} - -} // namespace keystore \ No newline at end of file diff --git a/keystore/key_operation_log_handler.h b/keystore/key_operation_log_handler.h deleted file mode 100644 index ba277470..00000000 --- a/keystore/key_operation_log_handler.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 KEY_OPERATION_LOG_HANDLER_H_ -#define KEY_OPERATION_LOG_HANDLER_H_ - -#include "operation_struct.h" - -namespace keystore { - -void logKeystoreKeyOperationEvent(const Operation& op, bool wasSuccessful, int32_t errorCode); - -} // namespace keystore - -#endif // KEY_OPERATION_LOG_HANDLER_H_ \ No newline at end of file diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp deleted file mode 100644 index 4e5bc48c..00000000 --- a/keystore/key_store_service.cpp +++ /dev/null @@ -1,1480 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#define LOG_TAG "keystore" - -#include "key_store_service.h" - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "defaults.h" -#include "key_attestation_log_handler.h" -#include "keystore_keymaster_enforcement.h" -#include "keystore_utils.h" -#include -#include -#include - -#include - -namespace keystore { - -using namespace android; - -namespace { - -using ::android::binder::Status; -using android::hardware::keymaster::V4_0::support::authToken2HidlVec; -using android::hardware::keymaster::V4_0::support::serializeVerificationToken; -using android::security::keymaster::ExportResult; -using android::security::keymaster::KeymasterArguments; -using android::security::keymaster::KeymasterBlob; -using android::security::keymaster::KeymasterCertificateChain; -using android::security::keymaster::operationFailed; -using android::security::keymaster::OperationResult; -using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode; -using ::android::security::keystore::ICredstoreTokenCallback; -using ::android::security::keystore::IKeystoreOperationResultCallback; -using ::android::security::keystore::IKeystoreResponseCallback; -using ::android::security::keystore::KeystoreResponse; - -constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */ -const char* kTimestampFilePath = "timestamp"; - -bool containsTag(const hidl_vec& params, Tag tag) { - return params.end() != - std::find_if(params.begin(), params.end(), - [&](const KeyParameter& param) { return param.tag == tag; }); -} - -#define AIDL_RETURN(rc) (*_aidl_return = KeyStoreServiceReturnCode(rc).getErrorCode(), Status::ok()) - -std::pair hadFactoryResetSinceIdRotation() { - struct stat sbuf; - if (stat(kTimestampFilePath, &sbuf) == 0) { - double diff_secs = difftime(time(nullptr), sbuf.st_ctime); - return {ResponseCode::NO_ERROR, diff_secs < kIdRotationPeriod}; - } - - if (errno != ENOENT) { - ALOGE("Failed to stat \"timestamp\" file, with error %d", errno); - return {ResponseCode::SYSTEM_ERROR, false /* don't care */}; - } - - int fd = creat(kTimestampFilePath, 0600); - if (fd < 0) { - ALOGE("Couldn't create \"timestamp\" file, with error %d", errno); - return {ResponseCode::SYSTEM_ERROR, false /* don't care */}; - } - - if (close(fd)) { - ALOGE("Couldn't close \"timestamp\" file, with error %d", errno); - return {ResponseCode::SYSTEM_ERROR, false /* don't care */}; - } - - return {ResponseCode::NO_ERROR, true}; -} - -using ::android::security::KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE; - -KeyStoreServiceReturnCode updateParamsForAttestation(uid_t callingUid, AuthorizationSet* params) { - KeyStoreServiceReturnCode responseCode; - bool factoryResetSinceIdRotation; - std::tie(responseCode, factoryResetSinceIdRotation) = hadFactoryResetSinceIdRotation(); - - if (!responseCode.isOk()) return responseCode; - if (factoryResetSinceIdRotation) params->push_back(TAG_RESET_SINCE_ID_ROTATION); - - auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid); - if (!asn1_attestation_id_result.isOk()) { - ALOGE("failed to gather attestation_id"); - // Couldn't get attestation ID; just use an empty one rather than failing. - asn1_attestation_id_result = std::vector(); - } - std::vector& asn1_attestation_id = asn1_attestation_id_result; - - /* - * The attestation application ID must not be longer than - * KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, error out if gather_attestation_application_id - * returned such an invalid vector. - */ - if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE) { - ALOGE("BUG: Gathered Attestation Application ID is too big (%d)", - static_cast(asn1_attestation_id.size())); - return ErrorCode::CANNOT_ATTEST_IDS; - } - - params->push_back(TAG_ATTESTATION_APPLICATION_ID, asn1_attestation_id); - - return ResponseCode::NO_ERROR; -} - -} // anonymous namespace - -Status KeyStoreService::getState(int32_t userId, int32_t* aidl_return) { - if (!checkBinderPermission(P_GET_STATE)) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - *aidl_return = mKeyStore->getState(userId); - return Status::ok(); -} - -Status KeyStoreService::get(const String16& name, int32_t uid, ::std::vector* item) { - uid_t targetUid = getEffectiveUid(uid); - if (!checkBinderPermission(P_GET, targetUid)) { - // see keystore/keystore.h - return Status::fromServiceSpecificError( - static_cast(ResponseCode::PERMISSION_DENIED)); - } - - String8 name8(name); - ResponseCode rc; - Blob keyBlob; - Blob charBlob; - LockedKeyBlobEntry lockedEntry; - - std::tie(rc, keyBlob, charBlob, lockedEntry) = - mKeyStore->getKeyForName(name8, targetUid, TYPE_GENERIC); - if (rc != ResponseCode::NO_ERROR) { - *item = ::std::vector(); - // Return empty array if key is not found - // TODO: consider having returned value nullable or parse exception on the client. - return Status::fromServiceSpecificError(static_cast(rc)); - } - auto resultBlob = blob2hidlVec(keyBlob); - // The static_cast here is needed to prevent a move, forcing a deep copy. - if (item) *item = static_cast&>(blob2hidlVec(keyBlob)); - return Status::ok(); -} - -Status KeyStoreService::insert(const String16& name, const ::std::vector& item, - int targetUid, int32_t flags, int32_t* aidl_return) { - targetUid = getEffectiveUid(targetUid); - KeyStoreServiceReturnCode result = - checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED); - if (!result.isOk()) { - *aidl_return = result.getErrorCode(); - return Status::ok(); - } - - String8 name8(name); - auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), targetUid); - - if (!lockedEntry) { - ALOGE("failed to grab lock on blob entry %u_%s", targetUid, name8.string()); - *aidl_return = static_cast(ResponseCode::KEY_ALREADY_EXISTS); - return Status::ok(); - } - - Blob keyBlob(&item[0], item.size(), nullptr, 0, ::TYPE_GENERIC); - keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED); - - *aidl_return = static_cast(mKeyStore->put(lockedEntry, keyBlob, {})); - return Status::ok(); -} - -Status KeyStoreService::del(const String16& name, int targetUid, int32_t* aidl_return) { - targetUid = getEffectiveUid(targetUid); - if (!checkBinderPermission(P_DELETE, targetUid)) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - String8 name8(name); - ALOGI("del %s %d", name8.string(), targetUid); - auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), targetUid); - if (!lockedEntry) { - *aidl_return = static_cast(ResponseCode::KEY_NOT_FOUND); - return Status::ok(); - } - - ResponseCode result = mKeyStore->del(lockedEntry); - - *aidl_return = static_cast(result); - return Status::ok(); -} - -Status KeyStoreService::exist(const String16& name, int targetUid, int32_t* aidl_return) { - targetUid = getEffectiveUid(targetUid); - if (!checkBinderPermission(P_EXIST, targetUid)) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - - LockedKeyBlobEntry lockedEntry = - mKeyStore->getLockedBlobEntryIfExists(String8(name).string(), targetUid); - *aidl_return = - static_cast(lockedEntry ? ResponseCode::NO_ERROR : ResponseCode::KEY_NOT_FOUND); - return Status::ok(); -} - -Status KeyStoreService::list(const String16& prefix, int32_t targetUid, - ::std::vector<::android::String16>* matches) { - targetUid = getEffectiveUid(targetUid); - if (!checkBinderPermission(P_LIST, targetUid)) { - return Status::fromServiceSpecificError( - static_cast(ResponseCode::PERMISSION_DENIED)); - } - const String8 prefix8(prefix); - const std::string stdPrefix(prefix8.string()); - - ResponseCode rc; - std::list internal_matches; - auto userDirName = mKeyStore->getUserStateDB().getUserStateByUid(targetUid)->getUserDirName(); - - std::tie(rc, internal_matches) = - LockedKeyBlobEntry::list(userDirName, [&](uid_t uid, const std::string& alias) { - std::mismatch(stdPrefix.begin(), stdPrefix.end(), alias.begin(), alias.end()); - return uid == static_cast(targetUid) && - std::mismatch(stdPrefix.begin(), stdPrefix.end(), alias.begin(), alias.end()) - .first == stdPrefix.end(); - }); - - if (rc != ResponseCode::NO_ERROR) { - return Status::fromServiceSpecificError(static_cast(rc)); - } - - for (LockedKeyBlobEntry& entry : internal_matches) { - matches->push_back(String16(entry->alias().substr(prefix8.size()).c_str())); - } - return Status::ok(); -} - -/* - * This method will return the uids of all auth bound keys for the calling user. - * This is intended to be used for alerting the user about which apps will be affected - * if the password/pin is removed. Only allowed to be called by system. - * The output is bound by the initial size of uidsOut to be compatible with Java. - */ -Status KeyStoreService::listUidsOfAuthBoundKeys(std::vector* uidsOut, - int32_t* aidl_return) { - const int32_t callingUid = IPCThreadState::self()->getCallingUid(); - const int32_t userId = get_user_id(callingUid); - const int32_t appId = get_app_id(callingUid); - if (appId != AID_SYSTEM) { - ALOGE("Permission listUidsOfAuthBoundKeys denied for aid %d", appId); - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - - const String8 prefix8(""); - auto userState = mKeyStore->getUserStateDB().getUserState(userId); - const std::string userDirName = userState->getUserDirName(); - auto encryptionKey = userState->getEncryptionKey(); - auto state = userState->getState(); - // unlock the user state - userState = {}; - - ResponseCode rc; - std::list internal_matches; - std::tie(rc, internal_matches) = - LockedKeyBlobEntry::list(userDirName, [&](uid_t, const std::string&) { - // Need to filter on auth bound state, so just return true. - return true; - }); - if (rc != ResponseCode::NO_ERROR) { - ALOGE("Error listing blob entries for user %d", userId); - return Status::fromServiceSpecificError(static_cast(rc)); - } - - for (LockedKeyBlobEntry& entry : internal_matches) { - // Need to store uids as a list of strings because integer list output - // parameters is not supported in aidl-cpp. - std::string entryUid = std::to_string(entry->uid()); - if (std::find(uidsOut->begin(), uidsOut->end(), entryUid) != uidsOut->end()) { - // uid already in list, skip - continue; - } - - auto [rc, blob, charBlob] = entry.readBlobs(encryptionKey, state); - if (rc != ResponseCode::NO_ERROR && rc != ResponseCode::LOCKED) { - ALOGE("Error reading blob for key %s", entry->alias().c_str()); - continue; - } - - if (blob && blob.isEncrypted()) { - uidsOut->push_back(entryUid); - } else if (charBlob) { - auto [success, hwEnforced, swEnforced] = charBlob.getKeyCharacteristics(); - if (!success) { - ALOGE("Error reading blob characteristics for key %s", entry->alias().c_str()); - continue; - } - if (hwEnforced.Contains(TAG_USER_SECURE_ID) || - swEnforced.Contains(TAG_USER_SECURE_ID)) { - uidsOut->push_back(entryUid); - } - } - } - *aidl_return = static_cast(ResponseCode::NO_ERROR); - return Status::ok(); -} - -Status KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password, - int32_t* aidl_return) { - if (!checkBinderPermission(P_PASSWORD)) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - - if (password.size() == 0) { - ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId); - mKeyStore->resetUser(userId, true); - *aidl_return = static_cast(ResponseCode::NO_ERROR); - return Status::ok(); - } else { - const String8 password8(password); - switch (mKeyStore->getState(userId)) { - case ::STATE_UNINITIALIZED: { - // generate master key, encrypt with password, write to file, - // initialize mMasterKey*. - *aidl_return = static_cast(mKeyStore->initializeUser(password8, userId)); - return Status::ok(); - } - case ::STATE_NO_ERROR: { - // rewrite master key with new password. - *aidl_return = static_cast(mKeyStore->writeMasterKey(password8, userId)); - return Status::ok(); - } - case ::STATE_LOCKED: { - ALOGE("Changing user %d's password while locked, clearing old encryption", userId); - mKeyStore->resetUser(userId, true); - *aidl_return = static_cast(mKeyStore->initializeUser(password8, userId)); - return Status::ok(); - } - } - *aidl_return = static_cast(ResponseCode::SYSTEM_ERROR); - return Status::ok(); - } -} - -Status KeyStoreService::onUserAdded(int32_t userId, int32_t parentId, int32_t* aidl_return) { - if (!checkBinderPermission(P_USER_CHANGED)) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - - // Sanity check that the new user has an empty keystore. - if (!mKeyStore->isEmpty(userId)) { - ALOGW("New user %d's keystore not empty. Clearing old entries.", userId); - } - // Unconditionally clear the keystore, just to be safe. - mKeyStore->resetUser(userId, false); - if (parentId != -1) { - // This profile must share the same master key password as the parent profile. Because the - // password of the parent profile is not known here, the best we can do is copy the parent's - // master key and master key file. This makes this profile use the same master key as the - // parent profile, forever. - *aidl_return = static_cast(mKeyStore->copyMasterKey(parentId, userId)); - return Status::ok(); - } else { - *aidl_return = static_cast(ResponseCode::NO_ERROR); - return Status::ok(); - } -} - -Status KeyStoreService::onUserRemoved(int32_t userId, int32_t* aidl_return) { - if (!checkBinderPermission(P_USER_CHANGED)) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - - mKeyStore->resetUser(userId, false); - *aidl_return = static_cast(ResponseCode::NO_ERROR); - return Status::ok(); -} - -Status KeyStoreService::lock(int32_t userId, int32_t* aidl_return) { - if (!checkBinderPermission(P_LOCK)) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - - State state = mKeyStore->getState(userId); - if (state != ::STATE_NO_ERROR) { - ALOGD("calling lock in state: %d", state); - *aidl_return = static_cast(ResponseCode(state)); - return Status::ok(); - } - - mKeyStore->getEnforcementPolicy().set_device_locked(true, userId); - mKeyStore->lock(userId); - *aidl_return = static_cast(ResponseCode::NO_ERROR); - return Status::ok(); -} - -Status KeyStoreService::unlock(int32_t userId, const String16& pw, int32_t* aidl_return) { - if (!checkBinderPermission(P_UNLOCK)) { - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - - State state = mKeyStore->getState(userId); - if (state != ::STATE_LOCKED) { - switch (state) { - case ::STATE_NO_ERROR: - ALOGI("calling unlock when already unlocked, ignoring."); - break; - case ::STATE_UNINITIALIZED: - ALOGE("unlock called on uninitialized keystore."); - break; - default: - ALOGE("unlock called on keystore in unknown state: %d", state); - break; - } - *aidl_return = static_cast(ResponseCode(state)); - return Status::ok(); - } - - mKeyStore->getEnforcementPolicy().set_device_locked(false, userId); - const String8 password8(pw); - // read master key, decrypt with password, initialize mMasterKey*. - *aidl_return = static_cast(mKeyStore->readMasterKey(password8, userId)); - return Status::ok(); -} - -Status KeyStoreService::isEmpty(int32_t userId, int32_t* aidl_return) { - if (!checkBinderPermission(P_IS_EMPTY)) { - *aidl_return = static_cast(false); - return Status::ok(); - } - - *aidl_return = static_cast(mKeyStore->isEmpty(userId)); - return Status::ok(); -} - -Status KeyStoreService::grant(const String16& name, int32_t granteeUid, - ::android::String16* aidl_return) { - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - auto result = - checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false); - if (!result.isOk()) { - *aidl_return = String16(); - return Status::ok(); - } - - String8 name8(name); - auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), callingUid); - if (!lockedEntry) { - *aidl_return = String16(); - return Status::ok(); - } - - *aidl_return = String16(mKeyStore->addGrant(lockedEntry, granteeUid).c_str()); - return Status::ok(); -} - -Status KeyStoreService::ungrant(const String16& name, int32_t granteeUid, int32_t* aidl_return) { - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - KeyStoreServiceReturnCode result = - checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false); - if (!result.isOk()) { - *aidl_return = result.getErrorCode(); - return Status::ok(); - } - - String8 name8(name); - - auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), callingUid); - if (!lockedEntry) { - *aidl_return = static_cast(ResponseCode::KEY_NOT_FOUND); - } - - *aidl_return = mKeyStore->removeGrant(lockedEntry, granteeUid); - return Status::ok(); -} - -Status KeyStoreService::getmtime(const String16& name, int32_t uid, int64_t* time) { - uid_t targetUid = getEffectiveUid(uid); - if (!checkBinderPermission(P_GET, targetUid)) { - ALOGW("permission denied for %d: getmtime", targetUid); - *time = -1L; - return Status::ok(); - } - String8 name8(name); - - auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), targetUid); - if (!lockedEntry) { - ALOGW("could not access key with alias %s for getmtime", name8.string()); - *time = -1L; - return Status::ok(); - } - - std::string filename = lockedEntry->getKeyBlobPath(); - - int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_NOFOLLOW, O_RDONLY)); - if (fd < 0) { - ALOGW("could not open %s for getmtime", filename.c_str()); - *time = -1L; - return Status::ok(); - } - - struct stat s; - int ret = fstat(fd, &s); - close(fd); - if (ret == -1) { - ALOGW("could not stat %s for getmtime", filename.c_str()); - *time = -1L; - return Status::ok(); - } - - *time = static_cast(s.st_mtime); - return Status::ok(); -} - -Status KeyStoreService::is_hardware_backed(const String16& keyType, int32_t* aidl_return) { - *aidl_return = static_cast(mKeyStore->isHardwareBacked(keyType) ? 1 : 0); - return Status::ok(); -} - -Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* _aidl_return) { - uid_t targetUid = getEffectiveUid(targetUid64); - if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) { - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - ALOGI("clear_uid %" PRId64, targetUid64); - - mKeyStore->removeAllGrantsToUid(targetUid); - - ResponseCode rc; - std::list entries; - auto userDirName = mKeyStore->getUserStateDB().getUserStateByUid(targetUid)->getUserDirName(); - - // list has a fence making sure no workers are modifying blob files before iterating the - // data base. All returned entries are locked. - std::tie(rc, entries) = LockedKeyBlobEntry::list( - userDirName, [&](uid_t uid, const std::string&) -> bool { return uid == targetUid; }); - - if (rc != ResponseCode::NO_ERROR) { - return AIDL_RETURN(rc); - } - - for (LockedKeyBlobEntry& lockedEntry : entries) { - if (get_app_id(targetUid) == AID_SYSTEM) { - Blob keyBlob; - Blob charBlob; - std::tie(rc, keyBlob, charBlob) = mKeyStore->get(lockedEntry); - if (rc == ResponseCode::NO_ERROR && keyBlob.isCriticalToDeviceEncryption()) { - // Do not clear keys critical to device encryption under system uid. - continue; - } - } - mKeyStore->del(lockedEntry); - } - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::addRngEntropy( - const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb, - const ::std::vector& entropy, int32_t flags, int32_t* _aidl_return) { - auto device = mKeyStore->getDevice(flagsToSecurityLevel(flags)); - if (!device) { - return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); - } - - device->addRngEntropy(entropy, [device, cb](Return rc) { - cb->onFinished(KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(device, rc))); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::generateKey( - const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, - const String16& name, const KeymasterArguments& params, const ::std::vector& entropy, - int uid, int flags, int32_t* _aidl_return) { - uid = getEffectiveUid(uid); - auto logOnScopeExit = android::base::make_scope_guard([&] { - if (__android_log_security()) { - android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED) - << int32_t(*_aidl_return == static_cast(ResponseCode::NO_ERROR)) - << String8(name) << int32_t(uid) << LOG_ID_SECURITY; - } - }); - KeyStoreServiceReturnCode rc = - checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED); - if (!rc.isOk()) { - return AIDL_RETURN(rc); - } - if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) { - ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid); - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - - if (containsTag(params.getParameters(), Tag::INCLUDE_UNIQUE_ID)) { - if (!checkBinderPermission(P_GEN_UNIQUE_ID)) { - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - } - - SecurityLevel securityLevel = flagsToSecurityLevel(flags); - auto dev = mKeyStore->getDevice(securityLevel); - if (!dev) { - return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); - } - - String8 name8(name); - auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), uid); - if (!lockedEntry) { - return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS); - } - - logOnScopeExit.Disable(); - - dev->generateKey( - std::move(lockedEntry), params.getParameters(), entropy, flags, - [cb, uid, name](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { - if (__android_log_security()) { - android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED) - << rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY; - } - cb->onFinished(rc, - android::security::keymaster::KeyCharacteristics(keyCharacteristics)); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::getKeyCharacteristics( - const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, - const String16& name, const ::android::security::keymaster::KeymasterBlob& clientId, - const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid, - int32_t* _aidl_return) { - - uid_t targetUid = getEffectiveUid(uid); - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - if (!is_granted_to(callingUid, targetUid)) { - ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid, - targetUid); - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - - String8 name8(name); - - ResponseCode rc; - Blob keyBlob; - Blob charBlob; - LockedKeyBlobEntry lockedEntry; - - std::tie(rc, keyBlob, charBlob, lockedEntry) = - mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10); - - if (rc != ResponseCode::NO_ERROR) { - return AIDL_RETURN(rc); - } - - auto dev = mKeyStore->getDevice(keyBlob); - if (!dev) { - return AIDL_RETURN(ResponseCode::SYSTEM_ERROR); - } - - // If the charBlob is up to date, it simply moves the argument blobs to the returned blobs - // and extracts the characteristics on the way. Otherwise it updates the cache file with data - // from keymaster. It may also upgrade the key blob. - dev->getKeyCharacteristics( - std::move(lockedEntry), clientId.getData(), appData.getData(), std::move(keyBlob), - std::move(charBlob), - [cb](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { - cb->onFinished(rc, - android::security::keymaster::KeyCharacteristics(keyCharacteristics)); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::importKey( - const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, - const String16& name, const KeymasterArguments& params, int32_t format, - const ::std::vector& keyData, int uid, int flags, int32_t* _aidl_return) { - uid = getEffectiveUid(uid); - auto logOnScopeExit = android::base::make_scope_guard([&] { - if (__android_log_security()) { - android_log_event_list(SEC_TAG_KEY_IMPORTED) - << int32_t(*_aidl_return == static_cast(ResponseCode::NO_ERROR)) - << String8(name) << int32_t(uid) << LOG_ID_SECURITY; - } - }); - KeyStoreServiceReturnCode rc = - checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED); - if (!rc.isOk()) { - LOG(ERROR) << "permissission denied"; - return AIDL_RETURN(rc); - } - if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) { - ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid); - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - - SecurityLevel securityLevel = flagsToSecurityLevel(flags); - auto dev = mKeyStore->getDevice(securityLevel); - if (!dev) { - LOG(ERROR) << "importKey - cound not get keymaster device"; - return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); - } - - String8 name8(name); - auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), uid); - if (!lockedEntry) { - LOG(ERROR) << "importKey - key: " << name8.string() << " " << int(uid) - << " already exists."; - return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS); - } - - logOnScopeExit.Disable(); - - dev->importKey( - std::move(lockedEntry), params.getParameters(), KeyFormat(format), keyData, flags, - [cb, uid, name](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { - if (__android_log_security()) { - android_log_event_list(SEC_TAG_KEY_IMPORTED) - << rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY; - } - cb->onFinished(rc, - android::security::keymaster::KeyCharacteristics(keyCharacteristics)); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::exportKey( - const ::android::sp<::android::security::keystore::IKeystoreExportKeyCallback>& cb, - const String16& name, int32_t format, - const ::android::security::keymaster::KeymasterBlob& clientId, - const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid, - int32_t* _aidl_return) { - - uid_t targetUid = getEffectiveUid(uid); - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - if (!is_granted_to(callingUid, targetUid)) { - ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid); - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - - String8 name8(name); - - KeyStoreServiceReturnCode rc; - Blob keyBlob; - Blob charBlob; - LockedKeyBlobEntry lockedEntry; - - std::tie(rc, keyBlob, charBlob, lockedEntry) = - mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10); - if (!rc.isOk()) { - return AIDL_RETURN(rc); - } - - auto dev = mKeyStore->getDevice(keyBlob); - - dev->exportKey(std::move(lockedEntry), KeyFormat(format), clientId.getData(), appData.getData(), - std::move(keyBlob), std::move(charBlob), - [cb](ExportResult exportResult) { cb->onFinished(exportResult); }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::begin(const sp& cb, - const sp& appToken, const String16& name, int32_t purpose, - bool pruneable, const KeymasterArguments& params, - const ::std::vector& entropy, int32_t uid, - int32_t* _aidl_return) { - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - uid_t targetUid = getEffectiveUid(uid); - if (!is_granted_to(callingUid, targetUid)) { - ALOGW("uid %d not permitted to act for uid %d in begin", callingUid, targetUid); - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) { - ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid); - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - if (!checkAllowedOperationParams(params.getParameters())) { - return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); - } - - String8 name8(name); - Blob keyBlob; - Blob charBlob; - LockedKeyBlobEntry lockedEntry; - ResponseCode rc; - - std::tie(rc, keyBlob, charBlob, lockedEntry) = - mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10); - - if (rc == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) { - return AIDL_RETURN(ErrorCode::KEY_USER_NOT_AUTHENTICATED); - } - if (rc != ResponseCode::NO_ERROR) return AIDL_RETURN(rc); - - auto dev = mKeyStore->getDevice(keyBlob); - AuthorizationSet opParams = params.getParameters(); - - dev->begin(std::move(lockedEntry), appToken, std::move(keyBlob), std::move(charBlob), pruneable, - static_cast(purpose), std::move(opParams), entropy, - [this, cb, dev](OperationResult result_) { - if (result_.resultCode.isOk() || - result_.resultCode == ResponseCode::OP_AUTH_NEEDED) { - mKeyStore->addOperationDevice(result_.token, dev); - } - cb->onFinished(result_); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::update(const ::android::sp& cb, - const ::android::sp<::android::IBinder>& token, - const ::android::security::keymaster::KeymasterArguments& params, - const ::std::vector& input, int32_t* _aidl_return) { - if (!checkAllowedOperationParams(params.getParameters())) { - return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); - } - - auto dev = mKeyStore->getOperationDevice(token); - if (!dev) { - return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE); - } - - dev->update(token, params.getParameters(), input, [this, cb, token](OperationResult result_) { - if (!result_.resultCode.isOk()) { - mKeyStore->removeOperationDevice(token); - } - cb->onFinished(result_); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::finish(const ::android::sp& cb, - const ::android::sp<::android::IBinder>& token, - const ::android::security::keymaster::KeymasterArguments& params, - const ::std::vector& input, - const ::std::vector& signature, - const ::std::vector& entropy, int32_t* _aidl_return) { - if (!checkAllowedOperationParams(params.getParameters())) { - return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); - } - - auto dev = mKeyStore->getOperationDevice(token); - if (!dev) { - return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE); - } - - dev->finish(token, params.getParameters(), input, signature, entropy, - [this, cb, token](OperationResult result_) { - mKeyStore->removeOperationDevice(token); - cb->onFinished(result_); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::abort(const ::android::sp& cb, - const ::android::sp<::android::IBinder>& token, - int32_t* _aidl_return) { - auto dev = mKeyStore->getOperationDevice(token); - if (!dev) { - return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE); - } - - dev->abort(token, [this, cb, token](KeyStoreServiceReturnCode rc) { - mKeyStore->removeOperationDevice(token); - cb->onFinished(rc); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::addAuthToken(const ::std::vector& authTokenAsVector, - int32_t* aidl_return) { - - // TODO(swillden): When gatekeeper and fingerprint are ready, this should be updated to - // receive a HardwareAuthToken, rather than an opaque byte array. - - if (!checkBinderPermission(P_ADD_AUTH)) { - ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid()); - *aidl_return = static_cast(ResponseCode::PERMISSION_DENIED); - return Status::ok(); - } - if (authTokenAsVector.size() != sizeof(hw_auth_token_t)) { - *aidl_return = KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT).getErrorCode(); - return Status::ok(); - } - - hw_auth_token_t authToken; - memcpy(reinterpret_cast(&authToken), authTokenAsVector.data(), sizeof(hw_auth_token_t)); - if (authToken.version != 0) { - *aidl_return = KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT).getErrorCode(); - return Status::ok(); - } - - mKeyStore->getAuthTokenTable().AddAuthenticationToken( - hidlVec2AuthToken(hidl_vec(authTokenAsVector))); - *aidl_return = static_cast(ResponseCode::NO_ERROR); - return Status::ok(); -} - -Status KeyStoreService::getTokensForCredstore(int64_t challenge, int64_t secureUserId, - int32_t authTokenMaxAgeMillis, - const ::android::sp& cb) { - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - if (callingUid != AID_CREDSTORE) { - return Status::fromServiceSpecificError(static_cast(0)); - } - - auto [err, authToken] = mKeyStore->getAuthTokenTable().FindAuthorizationForCredstore( - challenge, secureUserId, authTokenMaxAgeMillis); - // It's entirely possible we couldn't find an authToken (e.g. no user auth - // happened within the requested deadline) and in that case, we just - // callback immediately signaling success but just not returning any tokens. - if (err != AuthTokenTable::OK) { - cb->onFinished(true, {} /* serializedAuthToken */, {} /* serializedVerificationToken */); - return Status::ok(); - } - - // If we did find an authToken, get a verificationToken as well... - // - std::vector serializedAuthToken = authToken2HidlVec(authToken); - std::vector serializedVerificationToken; - std::shared_ptr dev = mKeyStore->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT); - if (!dev) { - LOG(ERROR) << "Unable to get KM device for SecurityLevel::TRUSTED_ENVIRONMENT"; - dev = mKeyStore->getDevice(SecurityLevel::SOFTWARE); - if (!dev) { - LOG(ERROR) << "Unable to get KM device for SecurityLevel::SOFTWARE"; - cb->onFinished(false, {}, {}); - return Status::fromServiceSpecificError(static_cast(0)); - } - } - - dev->verifyAuthorization( - challenge, {} /* params */, authToken, - [serializedAuthToken, cb](KeyStoreServiceReturnCode rc, HardwareAuthToken, - VerificationToken verificationToken) { - if (rc != ErrorCode::OK) { - LOG(ERROR) << "verifyAuthorization failed, rc=" << rc; - cb->onFinished(false, {}, {}); - return; - } - std::optional> serializedVerificationToken = - serializeVerificationToken(verificationToken); - if (!serializedVerificationToken) { - LOG(ERROR) << "Error serializing verificationToken"; - cb->onFinished(false, {}, {}); - return; - } - cb->onFinished(true, serializedAuthToken, serializedVerificationToken.value()); - }); - - return Status::ok(); -} - -bool isDeviceIdAttestationTag(Tag tag) { - switch (tag) { - case Tag::ATTESTATION_ID_BRAND: - case Tag::ATTESTATION_ID_DEVICE: - case Tag::ATTESTATION_ID_MANUFACTURER: - case Tag::ATTESTATION_ID_MODEL: - case Tag::ATTESTATION_ID_PRODUCT: - case Tag::ATTESTATION_ID_IMEI: - case Tag::ATTESTATION_ID_MEID: - case Tag::ATTESTATION_ID_SERIAL: - return true; - case Tag::INVALID: - case Tag::PURPOSE: - case Tag::ALGORITHM: - case Tag::KEY_SIZE: - case Tag::BLOCK_MODE: - case Tag::DIGEST: - case Tag::PADDING: - case Tag::CALLER_NONCE: - case Tag::MIN_MAC_LENGTH: - case Tag::EC_CURVE: - case Tag::RSA_PUBLIC_EXPONENT: - case Tag::INCLUDE_UNIQUE_ID: - case Tag::BLOB_USAGE_REQUIREMENTS: - case Tag::BOOTLOADER_ONLY: - case Tag::ROLLBACK_RESISTANCE: - case Tag::HARDWARE_TYPE: - case Tag::ACTIVE_DATETIME: - case Tag::ORIGINATION_EXPIRE_DATETIME: - case Tag::USAGE_EXPIRE_DATETIME: - case Tag::MIN_SECONDS_BETWEEN_OPS: - case Tag::MAX_USES_PER_BOOT: - case Tag::USER_ID: - case Tag::USER_SECURE_ID: - case Tag::NO_AUTH_REQUIRED: - case Tag::USER_AUTH_TYPE: - case Tag::AUTH_TIMEOUT: - case Tag::ALLOW_WHILE_ON_BODY: - case Tag::TRUSTED_USER_PRESENCE_REQUIRED: - case Tag::TRUSTED_CONFIRMATION_REQUIRED: - case Tag::UNLOCKED_DEVICE_REQUIRED: - case Tag::APPLICATION_ID: - case Tag::APPLICATION_DATA: - case Tag::CREATION_DATETIME: - case Tag::ORIGIN: - case Tag::ROOT_OF_TRUST: - case Tag::OS_VERSION: - case Tag::OS_PATCHLEVEL: - case Tag::UNIQUE_ID: - case Tag::ATTESTATION_CHALLENGE: - case Tag::ATTESTATION_APPLICATION_ID: - case Tag::VENDOR_PATCHLEVEL: - case Tag::BOOT_PATCHLEVEL: - case Tag::ASSOCIATED_DATA: - case Tag::NONCE: - case Tag::MAC_LENGTH: - case Tag::RESET_SINCE_ID_ROTATION: - case Tag::CONFIRMATION_TOKEN: - return false; - // no default, all values must be present in the switch, in this way the compiler ensures - // that new values added in the Tag enum are also added here. - } -} - -// These are attestation id tags that are not unique per device and don't require special permission -// to be attested. Any addition to this list needs privacy review and approval (PWG). -bool isDevicePropertyAttestationTag(Tag tag) { - switch (tag) { - case Tag::ATTESTATION_ID_BRAND: - case Tag::ATTESTATION_ID_DEVICE: - case Tag::ATTESTATION_ID_MANUFACTURER: - case Tag::ATTESTATION_ID_MODEL: - case Tag::ATTESTATION_ID_PRODUCT: - return true; - default: - return false; - } -} - -bool isDeviceIdAttestationRequested(const KeymasterArguments& params) { - const hardware::hidl_vec& paramsVec = params.getParameters(); - for (size_t i = 0; i < paramsVec.size(); ++i) { - if (isDeviceIdAttestationTag(paramsVec[i].tag)) { - return true; - } - } - return false; -} - -// Device properties can be attested safely without special permission -bool needsPermissionToAttestDeviceIds(const KeymasterArguments& params) { - const hardware::hidl_vec& paramsVec = params.getParameters(); - for (size_t i = 0; i < paramsVec.size(); ++i) { - if (isDeviceIdAttestationTag(paramsVec[i].tag) && - !isDevicePropertyAttestationTag(paramsVec[i].tag)) { - return true; - } - } - return false; -} - -Status KeyStoreService::attestKey( - const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb, - const String16& name, const KeymasterArguments& params, int32_t* _aidl_return) { - // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL - if (!checkAllowedOperationParams(params.getParameters())) { - return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); - } - - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - - if (needsPermissionToAttestDeviceIds(params) && (get_app_id(callingUid) != AID_SYSTEM)) { - return AIDL_RETURN(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT)); - } - - AuthorizationSet mutableParams = params.getParameters(); - KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams); - - auto logErrorOnReturn = android::base::make_scope_guard( - [&] { logKeystoreKeyAttestationEvent(false /*wasSuccessful*/, rc.getErrorCode()); }); - - if (!rc.isOk()) { - return AIDL_RETURN(rc); - } - - String8 name8(name); - Blob keyBlob; - Blob charBlob; - LockedKeyBlobEntry lockedEntry; - - std::tie(rc, keyBlob, charBlob, lockedEntry) = - mKeyStore->getKeyForName(name8, callingUid, TYPE_KEYMASTER_10); - - if (!rc.isOk()) { - return AIDL_RETURN(rc); - } - - logErrorOnReturn.Disable(); - - auto dev = mKeyStore->getDevice(keyBlob); - auto hidlKey = blob2hidlVec(keyBlob); - dev->attestKey( - std::move(hidlKey), mutableParams.hidl_data(), - [dev, cb](Return rc, - std::tuple>>&& hidlResult) { - auto& [ret, certChain] = hidlResult; - if (!rc.isOk()) { - logKeystoreKeyAttestationEvent(false /*wasSuccessful*/, - static_cast(ResponseCode::SYSTEM_ERROR)); - cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {}); - } else if (ret != ErrorCode::OK) { - KeyStoreServiceReturnCode ksrc(ret); - logKeystoreKeyAttestationEvent(false /*wasSuccessful*/, ksrc.getErrorCode()); - dev->logIfKeymasterVendorError(ret); - cb->onFinished(ksrc, {}); - } else { - KeyStoreServiceReturnCode ksrc(ret); - logKeystoreKeyAttestationEvent(true /*wasSuccessful*/, ksrc.getErrorCode()); - cb->onFinished(ksrc, KeymasterCertificateChain(std::move(certChain))); - } - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -// My IDE defines "CAPTURE_MOVE(x) x" because it does not understand generalized lambda captures. -// It should never be redefined by a build system though. -#ifndef CAPTURE_MOVE -#define CAPTURE_MOVE(x) x = std::move(x) -#endif - -Status KeyStoreService::attestDeviceIds( - const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb, - const KeymasterArguments& params, int32_t* _aidl_return) { - // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL - - if (!checkAllowedOperationParams(params.getParameters())) { - return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); - } - - if (!isDeviceIdAttestationRequested(params)) { - // There is an attestKey() method for attesting keys without device ID attestation. - return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT); - } - - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - - // Request special permission only for unique ids - if (needsPermissionToAttestDeviceIds(params)) { - sp binder = defaultServiceManager()->getService(String16("permission")); - if (binder == nullptr) { - return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS); - } - - if (!interface_cast(binder)->checkPermission( - String16("android.permission.READ_PRIVILEGED_PHONE_STATE"), - IPCThreadState::self()->getCallingPid(), callingUid)) { - return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS); - } - } - - AuthorizationSet mutableParams = params.getParameters(); - KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams); - if (!rc.isOk()) { - return AIDL_RETURN(rc); - } - - // Generate temporary key. - auto dev = mKeyStore->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT); - - if (!dev) { - return AIDL_RETURN(ResponseCode::SYSTEM_ERROR); - } - - - AuthorizationSet keyCharacteristics; - keyCharacteristics.push_back(TAG_PURPOSE, KeyPurpose::VERIFY); - keyCharacteristics.push_back(TAG_ALGORITHM, Algorithm::EC); - keyCharacteristics.push_back(TAG_DIGEST, Digest::SHA_2_256); - keyCharacteristics.push_back(TAG_NO_AUTH_REQUIRED); - keyCharacteristics.push_back(TAG_EC_CURVE, EcCurve::P_256); - - std::promise resultPromise; - auto resultFuture = resultPromise.get_future(); - - dev->generateKey( - keyCharacteristics.hidl_data(), - [cb, dev, CAPTURE_MOVE(mutableParams)]( - Return rc, - std::tuple, KeyCharacteristics>&& hidlResult) { - auto& [ret, hidlKeyBlob_, dummyCharacteristics] = hidlResult; - auto hidlKeyBlob = std::move(hidlKeyBlob_); - if (!rc.isOk()) { - cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {}); - return; - } - if (ret != ErrorCode::OK) { - dev->logIfKeymasterVendorError(ret); - cb->onFinished(KeyStoreServiceReturnCode(ret), {}); - return; - } - dev->attestKey( - hidlKeyBlob, mutableParams.hidl_data(), - [cb, dev, - hidlKeyBlob](Return rc, - std::tuple>>&& hidlResult) { - auto& [ret, certChain] = hidlResult; - // schedule temp key for deletion - dev->deleteKey(std::move(hidlKeyBlob), [dev](Return rc) { - // log error but don't return an error - KS_HANDLE_HIDL_ERROR(dev, rc); - }); - if (!rc.isOk()) { - cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {}); - return; - } - if (ret == ErrorCode::OK) { - cb->onFinished( - KeyStoreServiceReturnCode(ret), - ::android::security::keymaster::KeymasterCertificateChain(certChain)); - } else { - dev->logIfKeymasterVendorError(ret); - cb->onFinished(KeyStoreServiceReturnCode(ret), {}); - } - }); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) { - // TODO(tuckeris): add permission check. This should be callable from ClockworkHome only. - mKeyStore->getAuthTokenTable().onDeviceOffBody(); - *aidl_return = static_cast(ResponseCode::NO_ERROR); - return Status::ok(); -} - -Status KeyStoreService::importWrappedKey( - const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, - const ::android::String16& wrappedKeyAlias, const ::std::vector& wrappedKey, - const ::android::String16& wrappingKeyAlias, const ::std::vector& maskingKey, - const KeymasterArguments& params, int64_t rootSid, int64_t fingerprintSid, - int32_t* _aidl_return) { - - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - - if (!checkBinderPermission(P_INSERT, callingUid)) { - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - - String8 wrappingKeyName8(wrappingKeyAlias); - - KeyStoreServiceReturnCode rc; - Blob wrappingKeyBlob; - Blob wrappingCharBlob; - LockedKeyBlobEntry wrappingLockedEntry; - - std::tie(rc, wrappingKeyBlob, wrappingCharBlob, wrappingLockedEntry) = - mKeyStore->getKeyForName(wrappingKeyName8, callingUid, TYPE_KEYMASTER_10); - if (!rc.isOk()) { - return AIDL_RETURN(rc); - } - - String8 wrappedKeyName8(wrappedKeyAlias); - auto wrappedLockedEntry = - mKeyStore->getLockedBlobEntryIfNotExists(wrappedKeyName8.string(), callingUid); - if (!wrappedLockedEntry) { - return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS); - } - - SecurityLevel securityLevel = wrappingKeyBlob.getSecurityLevel(); - auto dev = mKeyStore->getDevice(securityLevel); - if (!dev) { - return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE); - } - - dev->importWrappedKey( - std::move(wrappingLockedEntry), std::move(wrappedLockedEntry), wrappedKey, maskingKey, - params.getParameters(), std::move(wrappingKeyBlob), std::move(wrappingCharBlob), rootSid, - fingerprintSid, [cb](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) { - cb->onFinished(rc, - ::android::security::keymaster::KeyCharacteristics(keyCharacteristics)); - }); - - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -Status KeyStoreService::presentConfirmationPrompt(const sp& listener, - const String16& promptText, - const ::std::vector& extraData, - const String16& locale, int32_t uiOptionsAsFlags, - int32_t* aidl_return) { - return mKeyStore->getConfirmationManager().presentConfirmationPrompt( - listener, promptText, extraData, locale, uiOptionsAsFlags, aidl_return); -} - -Status KeyStoreService::cancelConfirmationPrompt(const sp& listener, - int32_t* aidl_return) { - return mKeyStore->getConfirmationManager().cancelConfirmationPrompt(listener, aidl_return); -} - -Status KeyStoreService::isConfirmationPromptSupported(bool* aidl_return) { - return mKeyStore->getConfirmationManager().isConfirmationPromptSupported(aidl_return); -} - -/** - * Get the effective target uid for a binder operation that takes an - * optional uid as the target. - */ -uid_t KeyStoreService::getEffectiveUid(int32_t targetUid) { - if (targetUid == UID_SELF) { - return IPCThreadState::self()->getCallingUid(); - } - return static_cast(targetUid); -} - -/** - * Check if the caller of the current binder method has the required - * permission and if acting on other uids the grants to do so. - */ -bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid) { - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - pid_t spid = IPCThreadState::self()->getCallingPid(); - const char* ssid = IPCThreadState::self()->getCallingSid(); - if (!has_permission(callingUid, permission, spid, ssid)) { - ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid); - return false; - } - if (!is_granted_to(callingUid, getEffectiveUid(targetUid))) { - ALOGW("uid %d not granted to act for %d", callingUid, targetUid); - return false; - } - return true; -} - -/** - * Check if the caller of the current binder method has the required - * permission and the target uid is the caller or the caller is system. - */ -bool KeyStoreService::checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) { - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - pid_t spid = IPCThreadState::self()->getCallingPid(); - const char* ssid = IPCThreadState::self()->getCallingSid(); - if (!has_permission(callingUid, permission, spid, ssid)) { - ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid); - return false; - } - return getEffectiveUid(targetUid) == callingUid || callingUid == AID_SYSTEM; -} - -/** - * Check if the caller of the current binder method has the required - * permission or the target of the operation is the caller's uid. This is - * for operation where the permission is only for cross-uid activity and all - * uids are allowed to act on their own (ie: clearing all entries for a - * given uid). - */ -bool KeyStoreService::checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid) { - uid_t callingUid = IPCThreadState::self()->getCallingUid(); - if (getEffectiveUid(targetUid) == callingUid) { - return true; - } else { - return checkBinderPermission(permission, targetUid); - } -} - -/** - * Helper method to check that the caller has the required permission as - * well as the keystore is in the unlocked state if checkUnlocked is true. - * - * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and - * otherwise the state of keystore when not unlocked and checkUnlocked is - * true. - */ -KeyStoreServiceReturnCode -KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid, - bool checkUnlocked) { - if (!checkBinderPermission(permission, targetUid)) { - return ResponseCode::PERMISSION_DENIED; - } - State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid))); - if (checkUnlocked && !isKeystoreUnlocked(state)) { - // All State values coincide with ResponseCodes - return static_cast(state); - } - - return ResponseCode::NO_ERROR; -} - -bool KeyStoreService::isKeystoreUnlocked(State state) { - switch (state) { - case ::STATE_NO_ERROR: - return true; - case ::STATE_UNINITIALIZED: - case ::STATE_LOCKED: - return false; - } - return false; -} - -/** - * Check that all KeyParameters provided by the application are allowed. Any parameter that keystore - * adds itself should be disallowed here. - */ -bool KeyStoreService::checkAllowedOperationParams(const hidl_vec& params) { - for (size_t i = 0; i < params.size(); ++i) { - switch (params[i].tag) { - case Tag::ATTESTATION_APPLICATION_ID: - case Tag::RESET_SINCE_ID_ROTATION: - return false; - default: - break; - } - } - return true; -} - -Status KeyStoreService::onKeyguardVisibilityChanged(bool isShowing, int32_t userId, - int32_t* _aidl_return) { - if (isShowing) { - if (!checkBinderPermission(P_LOCK, UID_SELF)) { - LOG(WARNING) << "onKeyguardVisibilityChanged called with isShowing == true but " - "without LOCK permission"; - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - } else { - if (!checkBinderPermission(P_UNLOCK, UID_SELF)) { - LOG(WARNING) << "onKeyguardVisibilityChanged called with isShowing == false but " - "without UNLOCK permission"; - return AIDL_RETURN(ResponseCode::PERMISSION_DENIED); - } - } - mKeyStore->getEnforcementPolicy().set_device_locked(isShowing, userId); - return AIDL_RETURN(ResponseCode::NO_ERROR); -} - -} // namespace keystore diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h deleted file mode 100644 index 5fdddb99..00000000 --- a/keystore/key_store_service.h +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2016 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_KEYSTORE_SERVICE_H_ -#define KEYSTORE_KEYSTORE_SERVICE_H_ - -#include - -#include "auth_token_table.h" -#include "confirmation_manager.h" - -#include "KeyStore.h" -#include "keystore_keymaster_enforcement.h" -#include "operation.h" -#include "permissions.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace keystore { - -// Class provides implementation for generated BnKeystoreService.h based on -// gen/aidl/android/security/BnKeystoreService.h generated from -// java/android/security/IKeystoreService.aidl Note that all generated methods return binder::Status -// and use last arguments to send actual result to the caller. Private methods don't need to handle -// binder::Status. Input parameters cannot be null unless annotated with @nullable in .aidl file. -class KeyStoreService : public android::security::keystore::BnKeystoreService { - public: - explicit KeyStoreService(sp keyStore) : mKeyStore(keyStore) {} - virtual ~KeyStoreService() = default; - - void binderDied(const android::wp& who); - - ::android::binder::Status getState(int32_t userId, int32_t* _aidl_return) override; - ::android::binder::Status get(const ::android::String16& name, int32_t uid, - ::std::vector* _aidl_return) override; - ::android::binder::Status insert(const ::android::String16& name, - const ::std::vector& item, int32_t uid, int32_t flags, - int32_t* _aidl_return) override; - ::android::binder::Status del(const ::android::String16& name, int32_t uid, - int32_t* _aidl_return) override; - ::android::binder::Status exist(const ::android::String16& name, int32_t uid, - int32_t* _aidl_return) override; - ::android::binder::Status list(const ::android::String16& namePrefix, int32_t uid, - ::std::vector<::android::String16>* _aidl_return) override; - ::android::binder::Status listUidsOfAuthBoundKeys(std::vector<::std::string>* uids, - int32_t* _aidl_return) override; - - ::android::binder::Status onUserPasswordChanged(int32_t userId, - const ::android::String16& newPassword, - int32_t* _aidl_return) override; - ::android::binder::Status lock(int32_t userId, int32_t* _aidl_return) override; - ::android::binder::Status unlock(int32_t userId, const ::android::String16& userPassword, - int32_t* _aidl_return) override; - ::android::binder::Status isEmpty(int32_t userId, int32_t* _aidl_return) override; - ::android::binder::Status grant(const ::android::String16& name, int32_t granteeUid, - ::android::String16* _aidl_return) override; - ::android::binder::Status ungrant(const ::android::String16& name, int32_t granteeUid, - int32_t* _aidl_return) override; - ::android::binder::Status getmtime(const ::android::String16& name, int32_t uid, - int64_t* _aidl_return) override; - ::android::binder::Status is_hardware_backed(const ::android::String16& string, - int32_t* _aidl_return) override; - ::android::binder::Status clear_uid(int64_t uid, int32_t* _aidl_return) override; - ::android::binder::Status - addRngEntropy(const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb, - const ::std::vector& data, int32_t flags, - int32_t* _aidl_return) override; - ::android::binder::Status generateKey( - const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, - const ::android::String16& alias, - const ::android::security::keymaster::KeymasterArguments& arguments, - const ::std::vector& entropy, int32_t uid, int32_t flags, - int32_t* _aidl_return) override; - ::android::binder::Status getKeyCharacteristics( - const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, - const ::android::String16& alias, - const ::android::security::keymaster::KeymasterBlob& clientId, - const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid, - int32_t* _aidl_return) override; - ::android::binder::Status importKey( - const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, - const ::android::String16& alias, - const ::android::security::keymaster::KeymasterArguments& arguments, int32_t format, - const ::std::vector& keyData, int32_t uid, int32_t flags, - int32_t* _aidl_return) override; - ::android::binder::Status - exportKey(const ::android::sp<::android::security::keystore::IKeystoreExportKeyCallback>& cb, - const ::android::String16& alias, int32_t format, - const ::android::security::keymaster::KeymasterBlob& clientId, - const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid, - int32_t* _aidl_return) override; - ::android::binder::Status - begin(const ::android::sp<::android::security::keystore::IKeystoreOperationResultCallback>& cb, - const ::android::sp<::android::IBinder>& appToken, const ::android::String16& alias, - int32_t purpose, bool pruneable, - const ::android::security::keymaster::KeymasterArguments& params, - const ::std::vector& entropy, int32_t uid, int32_t* _aidl_return) override; - ::android::binder::Status - update(const ::android::sp<::android::security::keystore::IKeystoreOperationResultCallback>& cb, - const ::android::sp<::android::IBinder>& token, - const ::android::security::keymaster::KeymasterArguments& params, - const ::std::vector& input, int32_t* _aidl_return) override; - ::android::binder::Status - finish(const ::android::sp<::android::security::keystore::IKeystoreOperationResultCallback>& cb, - const ::android::sp<::android::IBinder>& token, - const ::android::security::keymaster::KeymasterArguments& params, - const ::std::vector& input, const ::std::vector& signature, - const ::std::vector& entropy, int32_t* _aidl_return) override; - ::android::binder::Status - abort(const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb, - const ::android::sp<::android::IBinder>& token, int32_t* _aidl_return) override; - ::android::binder::Status addAuthToken(const ::std::vector& authToken, - int32_t* _aidl_return) override; - ::android::binder::Status getTokensForCredstore( - int64_t challenge, int64_t secureUserId, int32_t authTokenMaxAge, - const ::android::sp<::android::security::keystore::ICredstoreTokenCallback>& cb) override; - ::android::binder::Status onUserAdded(int32_t userId, int32_t parentId, - int32_t* _aidl_return) override; - ::android::binder::Status onUserRemoved(int32_t userId, int32_t* _aidl_return) override; - ::android::binder::Status attestKey( - const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb, - const ::android::String16& alias, - const ::android::security::keymaster::KeymasterArguments& params, - int32_t* _aidl_return) override; - ::android::binder::Status attestDeviceIds( - const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb, - const ::android::security::keymaster::KeymasterArguments& params, - int32_t* _aidl_return) override; - ::android::binder::Status onDeviceOffBody(int32_t* _aidl_return) override; - - ::android::binder::Status importWrappedKey( - const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb, - const ::android::String16& wrappedKeyAlias, const ::std::vector& wrappedKey, - const ::android::String16& wrappingKeyAlias, const ::std::vector& maskingKey, - const ::android::security::keymaster::KeymasterArguments& params, int64_t rootSid, - int64_t fingerprintSid, int32_t* _aidl_return) override; - - ::android::binder::Status presentConfirmationPrompt( - const ::android::sp<::android::IBinder>& listener, const ::android::String16& promptText, - const ::std::vector& extraData, const ::android::String16& locale, - int32_t uiOptionsAsFlags, int32_t* _aidl_return) override; - ::android::binder::Status - cancelConfirmationPrompt(const ::android::sp<::android::IBinder>& listener, - int32_t* _aidl_return) override; - ::android::binder::Status isConfirmationPromptSupported(bool* _aidl_return) override; - - ::android::binder::Status onKeyguardVisibilityChanged(bool isShowing, int32_t userId, - int32_t* _aidl_return) override; - - private: - static const int32_t UID_SELF = -1; - - /** - * Get the effective target uid for a binder operation that takes an - * optional uid as the target. - */ - uid_t getEffectiveUid(int32_t targetUid); - - /** - * Check if the caller of the current binder method has the required - * permission and if acting on other uids the grants to do so. - */ - bool checkBinderPermission(perm_t permission, int32_t targetUid = UID_SELF); - - /** - * Check if the caller of the current binder method has the required - * permission and the target uid is the caller or the caller is system. - */ - bool checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid); - - /** - * Check if the caller of the current binder method has the required - * permission or the target of the operation is the caller's uid. This is - * for operation where the permission is only for cross-uid activity and all - * uids are allowed to act on their own (ie: clearing all entries for a - * given uid). - */ - bool checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid); - - /** - * Helper method to check that the caller has the required permission as - * well as the keystore is in the unlocked state if checkUnlocked is true. - * - * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and - * otherwise the state of keystore when not unlocked and checkUnlocked is - * true. - */ - KeyStoreServiceReturnCode checkBinderPermissionAndKeystoreState(perm_t permission, - int32_t targetUid = -1, - bool checkUnlocked = true); - - bool isKeystoreUnlocked(State state); - - /** - * Check that all keymaster_key_param_t's provided by the application are - * allowed. Any parameter that keystore adds itself should be disallowed here. - */ - bool checkAllowedOperationParams(const hidl_vec& params); - - void addLegacyBeginParams(const android::String16& name, AuthorizationSet* params); - - KeyStoreServiceReturnCode doLegacySignVerify(const android::String16& name, - const hidl_vec& data, - hidl_vec* out, - const hidl_vec& signature, - KeyPurpose purpose); - - /** - * Adds a Confirmation Token to the key parameters if needed. - */ - void appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics, - std::vector* params); - - sp mKeyStore; -}; - -}; // namespace keystore - -#endif // KEYSTORE_KEYSTORE_SERVICE_H_ diff --git a/keystore/keyblob_utils.cpp b/keystore/keyblob_utils.cpp deleted file mode 100644 index 6c2fac90..00000000 --- a/keystore/keyblob_utils.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#include -#include -#include -#include - -#include - -/** - * When a key is being migrated from a software keymaster implementation - * to a hardware keymaster implementation, the first 4 bytes of the key_blob - * given to the hardware implementation will be equal to SOFT_KEY_MAGIC. - * The hardware implementation should import these PKCS#8 format keys which - * are encoded like this: - * - * 4-byte SOFT_KEY_MAGIC - * - * 4-byte 32-bit integer big endian for public_key_length. This may be zero - * length which indicates the public key should be derived from the - * private key. - * - * public_key_length bytes of public key (may be empty) - * - * 4-byte 32-bit integer big endian for private_key_length - * - * private_key_length bytes of private key - */ -static const uint8_t SOFT_KEY_MAGIC[] = { 'P', 'K', '#', '8' }; - -size_t get_softkey_header_size() { - return sizeof(SOFT_KEY_MAGIC); -} - -uint8_t* add_softkey_header(uint8_t* key_blob, size_t key_blob_length) { - if (key_blob_length < sizeof(SOFT_KEY_MAGIC)) { - return nullptr; - } - - memcpy(key_blob, SOFT_KEY_MAGIC, sizeof(SOFT_KEY_MAGIC)); - - return key_blob + sizeof(SOFT_KEY_MAGIC); -} - -bool is_softkey(const uint8_t* key_blob, const size_t key_blob_length) { - if (key_blob_length < sizeof(SOFT_KEY_MAGIC)) { - return false; - } - - return !memcmp(key_blob, SOFT_KEY_MAGIC, sizeof(SOFT_KEY_MAGIC)); -} diff --git a/keystore/keymaster_enforcement.cpp b/keystore/keymaster_enforcement.cpp deleted file mode 100644 index a17cd946..00000000 --- a/keystore/keymaster_enforcement.cpp +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (C) 2014 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. - */ - -#define LOG_TAG "keystore" - -#include "keymaster_enforcement.h" - -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#include - -namespace keystore { - -bool is_public_key_algorithm(const AuthorizationSet& auth_set) { - auto algorithm = auth_set.GetTagValue(TAG_ALGORITHM); - return algorithm.isOk() && - (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC); -} - -static ErrorCode authorized_purpose(const KeyPurpose purpose, const AuthorizationSet& auth_set) { - switch (purpose) { - case KeyPurpose::VERIFY: - case KeyPurpose::ENCRYPT: - case KeyPurpose::SIGN: - case KeyPurpose::DECRYPT: - if (auth_set.Contains(TAG_PURPOSE, purpose)) return ErrorCode::OK; - return ErrorCode::INCOMPATIBLE_PURPOSE; - - default: - return ErrorCode::UNSUPPORTED_PURPOSE; - } -} - -inline bool is_origination_purpose(KeyPurpose purpose) { - return purpose == KeyPurpose::ENCRYPT || purpose == KeyPurpose::SIGN; -} - -inline bool is_usage_purpose(KeyPurpose purpose) { - return purpose == KeyPurpose::DECRYPT || purpose == KeyPurpose::VERIFY; -} - -KeymasterEnforcement::KeymasterEnforcement(uint32_t max_access_time_map_size, - uint32_t max_access_count_map_size) - : access_time_map_(max_access_time_map_size), access_count_map_(max_access_count_map_size) {} - -KeymasterEnforcement::~KeymasterEnforcement() { -} - -ErrorCode KeymasterEnforcement::AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid, - const AuthorizationSet& auth_set, - const AuthorizationSet& operation_params, - const HardwareAuthToken& auth_token, - uint64_t op_handle, bool is_begin_operation) { - if (is_public_key_algorithm(auth_set)) { - switch (purpose) { - case KeyPurpose::ENCRYPT: - case KeyPurpose::VERIFY: - /* Public key operations are always authorized. */ - return ErrorCode::OK; - - case KeyPurpose::DECRYPT: - case KeyPurpose::SIGN: - break; - - case KeyPurpose::WRAP_KEY: - return ErrorCode::INCOMPATIBLE_PURPOSE; - }; - }; - - if (is_begin_operation) - return AuthorizeBegin(purpose, keyid, auth_set, operation_params, auth_token); - else - return AuthorizeUpdateOrFinish(auth_set, auth_token, op_handle); -} - -// For update and finish the only thing to check is user authentication, and then only if it's not -// timeout-based. -ErrorCode KeymasterEnforcement::AuthorizeUpdateOrFinish(const AuthorizationSet& auth_set, - const HardwareAuthToken& auth_token, - uint64_t op_handle) { - int auth_type_index = -1; - for (size_t pos = 0; pos < auth_set.size(); ++pos) { - switch (auth_set[pos].tag) { - case Tag::NO_AUTH_REQUIRED: - case Tag::AUTH_TIMEOUT: - // If no auth is required or if auth is timeout-based, we have nothing to check. - return ErrorCode::OK; - - case Tag::USER_AUTH_TYPE: - auth_type_index = pos; - break; - - default: - break; - } - } - - // Note that at this point we should be able to assume that authentication is required, because - // authentication is required if KM_TAG_NO_AUTH_REQUIRED is absent. However, there are legacy - // keys which have no authentication-related tags, so we assume that absence is equivalent to - // presence of KM_TAG_NO_AUTH_REQUIRED. - // - // So, if we found KM_TAG_USER_AUTH_TYPE or if we find KM_TAG_USER_SECURE_ID then authentication - // is required. If we find neither, then we assume authentication is not required and return - // success. - bool authentication_required = (auth_type_index != -1); - for (auto& param : auth_set) { - auto user_secure_id = authorizationValue(TAG_USER_SECURE_ID, param); - if (user_secure_id.isOk()) { - authentication_required = true; - int auth_timeout_index = -1; - if (auth_token.mac.size() && - AuthTokenMatches(auth_set, auth_token, user_secure_id.value(), auth_type_index, - auth_timeout_index, op_handle, false /* is_begin_operation */)) - return ErrorCode::OK; - } - } - - if (authentication_required) return ErrorCode::KEY_USER_NOT_AUTHENTICATED; - - return ErrorCode::OK; -} - -ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid, - const AuthorizationSet& auth_set, - const AuthorizationSet& operation_params, - NullOr auth_token) { - // Find some entries that may be needed to handle KM_TAG_USER_SECURE_ID - int auth_timeout_index = -1; - int auth_type_index = -1; - int no_auth_required_index = -1; - for (size_t pos = 0; pos < auth_set.size(); ++pos) { - switch (auth_set[pos].tag) { - case Tag::AUTH_TIMEOUT: - auth_timeout_index = pos; - break; - case Tag::USER_AUTH_TYPE: - auth_type_index = pos; - break; - case Tag::NO_AUTH_REQUIRED: - no_auth_required_index = pos; - break; - default: - break; - } - } - - ErrorCode error = authorized_purpose(purpose, auth_set); - if (error != ErrorCode::OK) return error; - - // If successful, and if key has a min time between ops, this will be set to the time limit - uint32_t min_ops_timeout = UINT32_MAX; - - bool update_access_count = false; - bool caller_nonce_authorized_by_key = false; - bool authentication_required = false; - bool auth_token_matched = false; - bool unlocked_device_required = false; - int32_t user_id = -1; - - for (auto& param : auth_set) { - - // KM_TAG_PADDING_OLD and KM_TAG_DIGEST_OLD aren't actually members of the enum, so we can't - // switch on them. There's nothing to validate for them, though, so just ignore them. - if (int32_t(param.tag) == KM_TAG_PADDING_OLD || int32_t(param.tag) == KM_TAG_DIGEST_OLD) - continue; - - switch (param.tag) { - - case Tag::ACTIVE_DATETIME: { - auto date = authorizationValue(TAG_ACTIVE_DATETIME, param); - if (date.isOk() && !activation_date_valid(date.value())) - return ErrorCode::KEY_NOT_YET_VALID; - break; - } - case Tag::ORIGINATION_EXPIRE_DATETIME: { - auto date = authorizationValue(TAG_ORIGINATION_EXPIRE_DATETIME, param); - if (is_origination_purpose(purpose) && date.isOk() && - expiration_date_passed(date.value())) - return ErrorCode::KEY_EXPIRED; - break; - } - case Tag::USAGE_EXPIRE_DATETIME: { - auto date = authorizationValue(TAG_USAGE_EXPIRE_DATETIME, param); - if (is_usage_purpose(purpose) && date.isOk() && expiration_date_passed(date.value())) - return ErrorCode::KEY_EXPIRED; - break; - } - case Tag::MIN_SECONDS_BETWEEN_OPS: { - auto min_ops_timeout = authorizationValue(TAG_MIN_SECONDS_BETWEEN_OPS, param); - if (min_ops_timeout.isOk() && !MinTimeBetweenOpsPassed(min_ops_timeout.value(), keyid)) - return ErrorCode::KEY_RATE_LIMIT_EXCEEDED; - break; - } - case Tag::MAX_USES_PER_BOOT: { - auto max_users = authorizationValue(TAG_MAX_USES_PER_BOOT, param); - update_access_count = true; - if (max_users.isOk() && !MaxUsesPerBootNotExceeded(keyid, max_users.value())) - return ErrorCode::KEY_MAX_OPS_EXCEEDED; - break; - } - case Tag::USER_SECURE_ID: - if (no_auth_required_index != -1) { - // Key has both KM_TAG_USER_SECURE_ID and KM_TAG_NO_AUTH_REQUIRED - return ErrorCode::INVALID_KEY_BLOB; - } - - if (auth_timeout_index != -1) { - auto secure_id = authorizationValue(TAG_USER_SECURE_ID, param); - authentication_required = true; - if (secure_id.isOk() && auth_token.isOk() && - AuthTokenMatches(auth_set, auth_token.value(), secure_id.value(), - auth_type_index, auth_timeout_index, 0 /* op_handle */, - true /* is_begin_operation */)) - auth_token_matched = true; - } - break; - - case Tag::USER_ID: - user_id = authorizationValue(TAG_USER_ID, param).value(); - break; - - case Tag::CALLER_NONCE: - caller_nonce_authorized_by_key = true; - break; - - case Tag::UNLOCKED_DEVICE_REQUIRED: - unlocked_device_required = true; - break; - - /* Tags should never be in key auths. */ - case Tag::INVALID: - case Tag::ROOT_OF_TRUST: - case Tag::APPLICATION_DATA: - case Tag::ATTESTATION_CHALLENGE: - case Tag::ATTESTATION_APPLICATION_ID: - case Tag::ATTESTATION_ID_BRAND: - case Tag::ATTESTATION_ID_DEVICE: - case Tag::ATTESTATION_ID_PRODUCT: - case Tag::ATTESTATION_ID_SERIAL: - case Tag::ATTESTATION_ID_IMEI: - case Tag::ATTESTATION_ID_MEID: - case Tag::ATTESTATION_ID_MANUFACTURER: - case Tag::ATTESTATION_ID_MODEL: - return ErrorCode::INVALID_KEY_BLOB; - - /* Tags used for cryptographic parameters in keygen. Nothing to enforce. */ - case Tag::PURPOSE: - case Tag::ALGORITHM: - case Tag::KEY_SIZE: - case Tag::BLOCK_MODE: - case Tag::DIGEST: - case Tag::MAC_LENGTH: - case Tag::PADDING: - case Tag::NONCE: - case Tag::MIN_MAC_LENGTH: - case Tag::EC_CURVE: - - /* Tags not used for operations. */ - case Tag::BLOB_USAGE_REQUIREMENTS: - - /* Algorithm specific parameters not used for access control. */ - case Tag::RSA_PUBLIC_EXPONENT: - - /* Informational tags. */ - case Tag::CREATION_DATETIME: - case Tag::ORIGIN: - case Tag::ROLLBACK_RESISTANCE: - - /* Tags handled when KM_TAG_USER_SECURE_ID is handled */ - case Tag::NO_AUTH_REQUIRED: - case Tag::USER_AUTH_TYPE: - case Tag::AUTH_TIMEOUT: - - /* Tag to provide data to operations. */ - case Tag::ASSOCIATED_DATA: - - /* Tags that are implicitly verified by secure side */ - case Tag::APPLICATION_ID: - case Tag::BOOT_PATCHLEVEL: - case Tag::OS_PATCHLEVEL: - case Tag::OS_VERSION: - case Tag::TRUSTED_USER_PRESENCE_REQUIRED: - case Tag::VENDOR_PATCHLEVEL: - - /* TODO(swillden): Handle these */ - case Tag::INCLUDE_UNIQUE_ID: - case Tag::UNIQUE_ID: - case Tag::RESET_SINCE_ID_ROTATION: - case Tag::ALLOW_WHILE_ON_BODY: - case Tag::HARDWARE_TYPE: - case Tag::TRUSTED_CONFIRMATION_REQUIRED: - case Tag::CONFIRMATION_TOKEN: - break; - - case Tag::BOOTLOADER_ONLY: - return ErrorCode::INVALID_KEY_BLOB; - } - } - - if (unlocked_device_required && is_device_locked(user_id)) { - switch (purpose) { - case KeyPurpose::ENCRYPT: - case KeyPurpose::VERIFY: - /* These are okay */ - break; - case KeyPurpose::DECRYPT: - case KeyPurpose::SIGN: - case KeyPurpose::WRAP_KEY: - return ErrorCode::DEVICE_LOCKED; - }; - } - - if (authentication_required && !auth_token_matched) { - ALOGE("Auth required but no matching auth token found"); - return ErrorCode::KEY_USER_NOT_AUTHENTICATED; - } - - if (!caller_nonce_authorized_by_key && is_origination_purpose(purpose) && - operation_params.Contains(Tag::NONCE)) - return ErrorCode::CALLER_NONCE_PROHIBITED; - - if (min_ops_timeout != UINT32_MAX) { - if (!access_time_map_.UpdateKeyAccessTime(keyid, get_current_time(), min_ops_timeout)) { - ALOGE("Rate-limited keys table full. Entries will time out."); - return ErrorCode::TOO_MANY_OPERATIONS; - } - } - - if (update_access_count) { - if (!access_count_map_.IncrementKeyAccessCount(keyid)) { - ALOGE("Usage count-limited keys table full, until reboot."); - return ErrorCode::TOO_MANY_OPERATIONS; - } - } - - return ErrorCode::OK; -} - -class EvpMdCtx { - public: - EvpMdCtx() { EVP_MD_CTX_init(&ctx_); } - ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); } - - EVP_MD_CTX* get() { return &ctx_; } - - private: - EVP_MD_CTX ctx_; -}; - -/* static */ -std::optional KeymasterEnforcement::CreateKeyId(const hidl_vec& key_blob) { - EvpMdCtx ctx; - km_id_t keyid; - - uint8_t hash[EVP_MAX_MD_SIZE]; - unsigned int hash_len; - if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) && - EVP_DigestUpdate(ctx.get(), &key_blob[0], key_blob.size()) && - EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) { - assert(hash_len >= sizeof(keyid)); - memcpy(&keyid, hash, sizeof(keyid)); - return keyid; - } - - return {}; -} - -bool KeymasterEnforcement::MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid) { - uint32_t last_access_time; - if (!access_time_map_.LastKeyAccessTime(keyid, &last_access_time)) return true; - return min_time_between <= static_cast(get_current_time()) - last_access_time; -} - -bool KeymasterEnforcement::MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses) { - uint32_t key_access_count; - if (!access_count_map_.KeyAccessCount(keyid, &key_access_count)) return true; - return key_access_count < max_uses; -} - -template struct choose_hton; - -template struct choose_hton { - inline static IntType hton(const IntType& value) { - IntType result = 0; - const unsigned char* inbytes = reinterpret_cast(&value); - unsigned char* outbytes = reinterpret_cast(&result); - for (int i = sizeof(IntType) - 1; i >= 0; --i) { - *(outbytes++) = inbytes[i]; - } - return result; - } -}; - -template struct choose_hton { - inline static IntType hton(const IntType& value) { return value; } -}; - -template inline IntType hton(const IntType& value) { - return choose_hton::hton(value); -} - -template inline IntType ntoh(const IntType& value) { - // same operation and hton - return choose_hton::hton(value); -} - -bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set, - const HardwareAuthToken& auth_token, - const uint64_t user_secure_id, - const int auth_type_index, const int auth_timeout_index, - const uint64_t op_handle, - bool is_begin_operation) const { - assert(auth_type_index < static_cast(auth_set.size())); - assert(auth_timeout_index < static_cast(auth_set.size())); - - if (!ValidateTokenSignature(auth_token)) { - ALOGE("Auth token signature invalid"); - return false; - } - - if (auth_timeout_index == -1 && op_handle && op_handle != auth_token.challenge) { - ALOGE("Auth token has the challenge %" PRIu64 ", need %" PRIu64, auth_token.challenge, - op_handle); - return false; - } - - if (user_secure_id != auth_token.userId && user_secure_id != auth_token.authenticatorId) { - ALOGI("Auth token SIDs %" PRIu64 " and %" PRIu64 " do not match key SID %" PRIu64, - auth_token.userId, auth_token.authenticatorId, user_secure_id); - return false; - } - - if (auth_type_index < 0 || auth_type_index > static_cast(auth_set.size())) { - ALOGE("Auth required but no auth type found"); - return false; - } - - assert(auth_set[auth_type_index].tag == TAG_USER_AUTH_TYPE); - auto key_auth_type_mask = authorizationValue(TAG_USER_AUTH_TYPE, auth_set[auth_type_index]); - if (!key_auth_type_mask.isOk()) return false; - - if ((uint32_t(key_auth_type_mask.value()) & auth_token.authenticatorType) == 0) { - ALOGE("Key requires match of auth type mask 0%uo, but token contained 0%uo", - key_auth_type_mask.value(), auth_token.authenticatorType); - return false; - } - - if (auth_timeout_index != -1 && is_begin_operation) { - assert(auth_set[auth_timeout_index].tag == TAG_AUTH_TIMEOUT); - auto auth_token_timeout = - authorizationValue(TAG_AUTH_TIMEOUT, auth_set[auth_timeout_index]); - if (!auth_token_timeout.isOk()) return false; - - if (auth_token_timed_out(auth_token, auth_token_timeout.value())) { - ALOGE("Auth token has timed out"); - return false; - } - } - - // Survived the whole gauntlet. We have authentage! - return true; -} - -bool AccessTimeMap::LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const { - std::lock_guard lock(list_lock_); - for (auto& entry : last_access_list_) - if (entry.keyid == keyid) { - *last_access_time = entry.access_time; - return true; - } - return false; -} - -bool AccessTimeMap::UpdateKeyAccessTime(km_id_t keyid, uint32_t current_time, uint32_t timeout) { - std::lock_guard lock(list_lock_); - for (auto iter = last_access_list_.begin(); iter != last_access_list_.end();) { - if (iter->keyid == keyid) { - iter->access_time = current_time; - return true; - } - - // Expire entry if possible. - assert(current_time >= iter->access_time); - if (current_time - iter->access_time >= iter->timeout) - iter = last_access_list_.erase(iter); - else - ++iter; - } - - if (last_access_list_.size() >= max_size_) return false; - - AccessTime new_entry; - new_entry.keyid = keyid; - new_entry.access_time = current_time; - new_entry.timeout = timeout; - last_access_list_.push_front(new_entry); - return true; -} - -bool AccessCountMap::KeyAccessCount(km_id_t keyid, uint32_t* count) const { - std::lock_guard lock(list_lock_); - for (auto& entry : access_count_list_) - if (entry.keyid == keyid) { - *count = entry.access_count; - return true; - } - return false; -} - -bool AccessCountMap::IncrementKeyAccessCount(km_id_t keyid) { - std::lock_guard lock(list_lock_); - for (auto& entry : access_count_list_) - if (entry.keyid == keyid) { - // Note that the 'if' below will always be true because KM_TAG_MAX_USES_PER_BOOT is a - // uint32_t, and as soon as entry.access_count reaches the specified maximum value - // operation requests will be rejected and access_count won't be incremented any more. - // And, besides, UINT64_MAX is huge. But we ensure that it doesn't wrap anyway, out of - // an abundance of caution. - if (entry.access_count < UINT64_MAX) ++entry.access_count; - return true; - } - - if (access_count_list_.size() >= max_size_) return false; - - AccessCount new_entry; - new_entry.keyid = keyid; - new_entry.access_count = 1; - access_count_list_.push_front(new_entry); - return true; -} -}; /* namespace keystore */ diff --git a/keystore/keymaster_enforcement.h b/keystore/keymaster_enforcement.h deleted file mode 100644 index 9bfb2256..00000000 --- a/keystore/keymaster_enforcement.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2014 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_ENFORCEMENT_H -#define KEYSTORE_KEYMASTER_ENFORCEMENT_H - -#include - -#include - -#include -#include -#include - -namespace keystore { - -typedef uint64_t km_id_t; - -class KeymasterEnforcementContext { - public: - virtual ~KeymasterEnforcementContext() {} - /* - * Get current time. - */ -}; - -class AccessTimeMap { - public: - explicit AccessTimeMap(uint32_t max_size) : max_size_(max_size) {} - - /* If the key is found, returns true and fills \p last_access_time. If not found returns - * false. */ - bool LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const; - - /* Updates the last key access time with the currentTime parameter. Adds the key if - * needed, returning false if key cannot be added because list is full. */ - bool UpdateKeyAccessTime(km_id_t keyid, uint32_t current_time, uint32_t timeout); - - private: - mutable std::mutex list_lock_; - struct AccessTime { - km_id_t keyid; - uint32_t access_time; - uint32_t timeout; - }; - std::list last_access_list_; - const uint32_t max_size_; -}; - -class AccessCountMap { - public: - explicit AccessCountMap(uint32_t max_size) : max_size_(max_size) {} - - /* If the key is found, returns true and fills \p count. If not found returns - * false. */ - bool KeyAccessCount(km_id_t keyid, uint32_t* count) const; - - /* Increments key access count, adding an entry if the key has never been used. Returns - * false if the list has reached maximum size. */ - bool IncrementKeyAccessCount(km_id_t keyid); - - private: - mutable std::mutex list_lock_; - struct AccessCount { - km_id_t keyid; - uint64_t access_count; - }; - std::list access_count_list_; - const uint32_t max_size_; -}; - -class KeymasterEnforcement { - public: - /** - * Construct a KeymasterEnforcement. - */ - KeymasterEnforcement(uint32_t max_access_time_map_size, uint32_t max_access_count_map_size); - virtual ~KeymasterEnforcement(); - - /** - * Iterates through the authorization set and returns the corresponding keymaster error. Will - * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with - * the given operation params and handle. Used for encrypt, decrypt sign, and verify. - */ - ErrorCode AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid, - const AuthorizationSet& auth_set, - const AuthorizationSet& operation_params, - const HardwareAuthToken& auth_token, uint64_t op_handle, - bool is_begin_operation); - - /** - * Iterates through the authorization set and returns the corresponding keymaster error. Will - * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with - * the given operation params. Used for encrypt, decrypt sign, and verify. - */ - ErrorCode AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid, - const AuthorizationSet& auth_set, - const AuthorizationSet& operation_params, - NullOr auth_token); - - /** - * Iterates through the authorization set and returns the corresponding keymaster error. Will - * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with - * the given operation params and handle. Used for encrypt, decrypt sign, and verify. - */ - ErrorCode AuthorizeUpdate(const AuthorizationSet& auth_set, const HardwareAuthToken& auth_token, - uint64_t op_handle) { - return AuthorizeUpdateOrFinish(auth_set, auth_token, op_handle); - } - - /** - * Iterates through the authorization set and returns the corresponding keymaster error. Will - * return KM_ERROR_OK if all criteria is met for the given purpose in the authorization set with - * the given operation params and handle. Used for encrypt, decrypt sign, and verify. - */ - ErrorCode AuthorizeFinish(const AuthorizationSet& auth_set, const HardwareAuthToken& auth_token, - uint64_t op_handle) { - return AuthorizeUpdateOrFinish(auth_set, auth_token, op_handle); - } - - /** - * Creates a key ID for use in subsequent calls to AuthorizeOperation. Clients needn't use this - * method of creating key IDs, as long as they use something consistent and unique. This method - * hashes the key blob. - * - * Returns false if an error in the crypto library prevents creation of an ID. - */ - static std::optional CreateKeyId(const hidl_vec& key_blob); - - // - // Methods that must be implemented by subclasses - // - // The time-related methods address the fact that different enforcement contexts may have - // different time-related capabilities. In particular: - // - // - They may or may not be able to check dates against real-world clocks. - // - // - They may or may not be able to check timestampls against authentication trustlets (minters - // of hw_auth_token_t structs). - // - // - They must have some time source for relative times, but may not be able to provide more - // than reliability and monotonicity. - - /* - * Returns true if the specified activation date has passed, or if activation cannot be - * enforced. - */ - virtual bool activation_date_valid(uint64_t activation_date) const = 0; - - /* - * Returns true if the specified expiration date has passed. Returns false if it has not, or if - * expiration cannot be enforced. - */ - virtual bool expiration_date_passed(uint64_t expiration_date) const = 0; - - /* - * Returns true if the specified auth_token is older than the specified timeout. - */ - virtual bool auth_token_timed_out(const HardwareAuthToken& token, uint32_t timeout) const = 0; - - /* - * Get current time in seconds from some starting point. This value is used to compute relative - * times between events. It must be monotonically increasing, and must not skip or lag. It - * need not have any relation to any external time standard (other than the duration of - * "second"). - * - * On POSIX systems, it's recommented to use clock_gettime(CLOCK_MONOTONIC, ...) to implement - * this method. - */ - virtual uint32_t get_current_time() const = 0; - - /* - * Returns true if the specified auth_token has a valid signature, or if signature validation is - * not available. - */ - virtual bool ValidateTokenSignature(const HardwareAuthToken& token) const = 0; - - /* - * Returns true if the device screen is currently locked for the specified user. - */ - virtual bool is_device_locked(int32_t userId) const = 0; - - private: - ErrorCode AuthorizeUpdateOrFinish(const AuthorizationSet& auth_set, - const HardwareAuthToken& auth_token, uint64_t op_handle); - - bool MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid); - bool MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses); - bool AuthTokenMatches(const AuthorizationSet& auth_set, const HardwareAuthToken& auth_token, - const uint64_t user_secure_id, const int auth_type_index, - const int auth_timeout_index, const uint64_t op_handle, - bool is_begin_operation) const; - - AccessTimeMap access_time_map_; - AccessCountMap access_count_map_; -}; - -}; /* namespace keystore */ - -#endif // KEYSTORE_KEYMASTER_ENFORCEMENT_H diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp deleted file mode 100644 index cbb184c2..00000000 --- a/keystore/keymaster_worker.cpp +++ /dev/null @@ -1,1144 +0,0 @@ -/* -** -** 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. -*/ -#define LOG_TAG "keymaster_worker" - -#include "keymaster_worker.h" - -#include "keystore_utils.h" - -#include - -#include - -#include - -#include "KeyStore.h" -#include "keymaster_enforcement.h" - -#include "key_creation_log_handler.h" -#include "keystore_utils.h" - -#include - -namespace keystore { - -using namespace std::chrono; - -constexpr size_t kMaxOperations = 15; - -using AndroidKeymasterArguments = android::security::keymaster::KeymasterArguments; -using android::security::keymaster::ExportResult; -using android::security::keymaster::operationFailed; -using android::security::keymaster::OperationResult; - -Worker::Worker() {} -Worker::~Worker() { - std::unique_lock lock(pending_requests_mutex_); - terminate_ = true; - pending_requests_cond_var_.notify_all(); - pending_requests_cond_var_.wait(lock, [this] { return !running_; }); -} -void Worker::addRequest(WorkerTask request) { - std::unique_lock lock(pending_requests_mutex_); - bool start_thread = !running_; - running_ = true; - pending_requests_.push(std::move(request)); - lock.unlock(); - pending_requests_cond_var_.notify_all(); - if (start_thread) { - auto worker = std::thread([this] { - std::unique_lock lock(pending_requests_mutex_); - while (running_) { - // Wait for 30s if the request queue is empty, then kill die. - // Die immediately if termiate_ was set which happens in the destructor. - auto status = pending_requests_cond_var_.wait_for( - lock, 30s, [this]() { return !pending_requests_.empty() || terminate_; }); - if (status && !terminate_) { - auto request = std::move(pending_requests_.front()); - lock.unlock(); - request(); - lock.lock(); - pending_requests_.pop(); - } else { - running_ = false; - } - pending_requests_cond_var_.notify_all(); - } - }); - worker.detach(); - } -} - -KeymasterWorker::KeymasterWorker(sp keymasterDevice, KeyStore* keyStore, - SecurityLevel internalSecurityLevel) - : keymasterDevice_(std::move(keymasterDevice)), operationMap_(keyStore), keyStore_(keyStore), - internalSecurityLevel_(internalSecurityLevel) { - // make sure that hal version is cached. - if (keymasterDevice_) keymasterDevice_->halVersion(); -} - -void KeymasterWorker::logIfKeymasterVendorError(ErrorCode ec) const { - keymasterDevice_->logIfKeymasterVendorError(ec); -} - -void KeymasterWorker::deleteOldKeyOnUpgrade(const LockedKeyBlobEntry& blobfile, Blob keyBlob) { - // if we got the blob successfully, we try and delete it from the keymaster device - auto& dev = keymasterDevice_; - uid_t uid = blobfile->uid(); - const auto& alias = blobfile->alias(); - - if (keyBlob.getType() == ::TYPE_KEYMASTER_10) { - auto ret = KS_HANDLE_HIDL_ERROR(dev, dev->deleteKey(blob2hidlVec(keyBlob))); - // A device doesn't have to implement delete_key. - bool success = ret == ErrorCode::OK || ret == ErrorCode::UNIMPLEMENTED; - if (__android_log_security()) { - android_log_event_list(SEC_TAG_KEY_DESTROYED) - << int32_t(success) << alias << int32_t(uid) << LOG_ID_SECURITY; - } - if (!success) { - LOG(ERROR) << "Keymaster delete for key " << alias << " of uid " << uid << " failed"; - } - } -} - -std::tuple -KeymasterWorker::upgradeKeyBlob(const LockedKeyBlobEntry& lockedEntry, - const AuthorizationSet& params) { - LOG(INFO) << "upgradeKeyBlob " << lockedEntry->alias() << " " << (uint32_t)lockedEntry->uid(); - - std::tuple result; - - auto userState = keyStore_->getUserStateDB().getUserStateByUid(lockedEntry->uid()); - - Blob& blob = std::get<1>(result); - KeyStoreServiceReturnCode& error = std::get<0>(result); - - Blob charBlob; - ResponseCode rc; - - std::tie(rc, blob, charBlob) = - lockedEntry.readBlobs(userState->getEncryptionKey(), userState->getState()); - - userState = {}; - - if (rc != ResponseCode::NO_ERROR) { - return error = rc, result; - } - - auto hidlKey = blob2hidlVec(blob); - auto& dev = keymasterDevice_; - - auto hidlCb = [&](ErrorCode ret, const ::std::vector& upgradedKeyBlob) { - dev->logIfKeymasterVendorError(ret); - error = ret; - if (!error.isOk()) { - if (error == ErrorCode::INVALID_KEY_BLOB) { - log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid()); - } - return; - } - - Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */, - 0 /* infoLength */, ::TYPE_KEYMASTER_10); - newBlob.setSecurityLevel(blob.getSecurityLevel()); - newBlob.setEncrypted(blob.isEncrypted()); - newBlob.setSuperEncrypted(blob.isSuperEncrypted()); - newBlob.setCriticalToDeviceEncryption(blob.isCriticalToDeviceEncryption()); - - error = keyStore_->put(lockedEntry, newBlob, charBlob); - if (!error.isOk()) { - ALOGI("upgradeKeyBlob keystore->put failed %d", error.getErrorCode()); - return; - } - - deleteOldKeyOnUpgrade(lockedEntry, std::move(blob)); - blob = std::move(newBlob); - }; - - KeyStoreServiceReturnCode error2; - error2 = KS_HANDLE_HIDL_ERROR(dev, dev->upgradeKey(hidlKey, params.hidl_data(), hidlCb)); - if (!error2.isOk()) { - return error = error2, result; - } - - return result; -} - -std::tuple -KeymasterWorker::createKeyCharacteristicsCache(const LockedKeyBlobEntry& lockedEntry, - const hidl_vec& clientId, - const hidl_vec& appData, Blob keyBlob, - Blob charBlob) { - std::tuple result; - -#if __cplusplus == 201703L - auto& [rc, resultCharacteristics, outBlob, charOutBlob] = result; -#else - KeyStoreServiceReturnCode& rc = std::get<0>(result); - KeyCharacteristics& resultCharacteristics = std::get<1>(result); - Blob& outBlob = std::get<2>(result); - Blob& charOutBlob = std::get<3>(result); -#endif - - rc = ResponseCode::SYSTEM_ERROR; - if (!keyBlob) return result; - auto hidlKeyBlob = blob2hidlVec(keyBlob); - auto& dev = keymasterDevice_; - - KeyStoreServiceReturnCode error; - - AuthorizationSet hwEnforced, swEnforced; - bool success = true; - - if (charBlob) { - std::tie(success, hwEnforced, swEnforced) = charBlob.getKeyCharacteristics(); - } - if (!success) { - LOG(ERROR) << "Failed to read cached key characteristics"; - return rc = ResponseCode::SYSTEM_ERROR, result; - } - - auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) { - dev->logIfKeymasterVendorError(ret); - error = ret; - if (!error.isOk()) { - if (error == ErrorCode::INVALID_KEY_BLOB) { - log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid()); - } - return; - } - - // Replace the sw_enforced set with those persisted to disk, minus hw_enforced - AuthorizationSet softwareEnforced = keyCharacteristics.softwareEnforced; - hwEnforced = keyCharacteristics.hardwareEnforced; - swEnforced.Union(softwareEnforced); - softwareEnforced.Subtract(hwEnforced); - - // We only get the characteristics from keymaster if there was no cache file or the - // the chach file was a legacy cache file. So lets write a new cache file for the next time. - Blob newCharBlob; - success = newCharBlob.putKeyCharacteristics(hwEnforced, swEnforced); - if (!success) { - error = ResponseCode::SYSTEM_ERROR; - LOG(ERROR) << "Failed to serialize cached key characteristics"; - return; - } - - error = keyStore_->put(lockedEntry, {}, newCharBlob); - if (!error.isOk()) { - ALOGE("Failed to write key characteristics cache"); - return; - } - charBlob = std::move(newCharBlob); - }; - - if (!charBlob || charBlob.getType() == TYPE_KEY_CHARACTERISTICS) { - // this updates the key characteristics cache file to the new format or creates one in - // in the first place - rc = KS_HANDLE_HIDL_ERROR( - dev, dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb)); - if (!rc.isOk()) { - return result; - } - - if (error == ErrorCode::KEY_REQUIRES_UPGRADE) { - AuthorizationSet upgradeParams; - if (clientId.size()) { - upgradeParams.push_back(TAG_APPLICATION_ID, clientId); - } - if (appData.size()) { - upgradeParams.push_back(TAG_APPLICATION_DATA, appData); - } - std::tie(rc, keyBlob) = upgradeKeyBlob(lockedEntry, upgradeParams); - if (!rc.isOk()) { - return result; - } - - auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob); - - rc = KS_HANDLE_HIDL_ERROR( - dev, dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb)); - if (!rc.isOk()) { - return result; - } - } - } - - resultCharacteristics.hardwareEnforced = hwEnforced.hidl_data(); - resultCharacteristics.softwareEnforced = swEnforced.hidl_data(); - - outBlob = std::move(keyBlob); - charOutBlob = std::move(charBlob); - rc = error; - return result; -} - -/** - * Get the auth token for this operation from the auth token table. - * - * Returns ResponseCode::NO_ERROR if the auth token was set or none was required. - * ::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 -KeymasterWorker::getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle, - KeyPurpose purpose, bool failOnTokenMissing) { - - AuthorizationSet allCharacteristics(characteristics.softwareEnforced); - allCharacteristics.append(characteristics.hardwareEnforced.begin(), - characteristics.hardwareEnforced.end()); - - HardwareAuthToken authToken; - AuthTokenTable::Error err; - std::tie(err, authToken) = keyStore_->getAuthTokenTable().FindAuthorization( - allCharacteristics, static_cast(purpose), handle); - - KeyStoreServiceReturnCode rc; - - switch (err) { - case AuthTokenTable::OK: - case AuthTokenTable::AUTH_NOT_REQUIRED: - rc = ResponseCode::NO_ERROR; - break; - - case AuthTokenTable::AUTH_TOKEN_NOT_FOUND: - case AuthTokenTable::AUTH_TOKEN_EXPIRED: - case AuthTokenTable::AUTH_TOKEN_WRONG_SID: - ALOGE("getAuthToken failed: %d", err); // STOPSHIP: debug only, to be removed - rc = ErrorCode::KEY_USER_NOT_AUTHENTICATED; - break; - - case AuthTokenTable::OP_HANDLE_REQUIRED: - rc = failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED) - : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED); - break; - - default: - ALOGE("Unexpected FindAuthorization return value %d", err); - rc = ErrorCode::INVALID_ARGUMENT; - } - - return {rc, std::move(authToken)}; -} - -KeyStoreServiceReturnCode KeymasterWorker::abort(const sp& token, - ResponseCode reason_for_abort) { - auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */, - static_cast(reason_for_abort)); - if (op) { - keyStore_->getAuthTokenTable().MarkCompleted(op->handle); - return KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle)); - } else { - return ErrorCode::INVALID_OPERATION_HANDLE; - } -} - -/** - * Prune the oldest pruneable operation. - */ -bool KeymasterWorker::pruneOperation() { - sp oldest = operationMap_.getOldestPruneableOperation(); - ALOGD("Trying to prune operation %p", oldest.get()); - size_t op_count_before_abort = operationMap_.getOperationCount(); - // We mostly ignore errors from abort() because all we care about is whether at least - // one operation has been removed. - auto rc = abort(oldest, ResponseCode::PRUNED); - keyStore_->removeOperationDevice(oldest); - if (operationMap_.getOperationCount() >= op_count_before_abort) { - ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), rc.getErrorCode()); - return false; - } - return true; -} - -// My IDE defines "CAPTURE_MOVE(x) x" because it does not understand generalized lambda captures. -// It should never be redefined by a build system though. -#ifndef CAPTURE_MOVE -#define CAPTURE_MOVE(x) x = std::move(x) -#endif - -void KeymasterWorker::begin(LockedKeyBlobEntry lockedEntry, sp appToken, Blob keyBlob, - Blob charBlob, bool pruneable, KeyPurpose purpose, - AuthorizationSet opParams, hidl_vec entropy, - worker_begin_cb worker_cb) { - - Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(appToken), - CAPTURE_MOVE(keyBlob), CAPTURE_MOVE(charBlob), pruneable, purpose, - CAPTURE_MOVE(opParams), CAPTURE_MOVE(entropy), - CAPTURE_MOVE(worker_cb)]() mutable { - // Concurrently executed - - auto& dev = keymasterDevice_; - - KeyCharacteristics characteristics; - - { - hidl_vec clientId; - hidl_vec appData; - for (const auto& param : opParams) { - if (param.tag == Tag::APPLICATION_ID) { - clientId = authorizationValue(TAG_APPLICATION_ID, param).value(); - } else if (param.tag == Tag::APPLICATION_DATA) { - appData = authorizationValue(TAG_APPLICATION_DATA, param).value(); - } - } - KeyStoreServiceReturnCode error; - std::tie(error, characteristics, keyBlob, charBlob) = createKeyCharacteristicsCache( - lockedEntry, clientId, appData, std::move(keyBlob), std::move(charBlob)); - if (!error.isOk()) { - worker_cb(operationFailed(error)); - return; - } - } - - KeyStoreServiceReturnCode rc, authRc; - HardwareAuthToken authToken; - std::tie(authRc, authToken) = getAuthToken(characteristics, 0 /* no challenge */, purpose, - /*failOnTokenMissing*/ false); - - // If per-operation auth is needed we need to begin the operation and - // the client will need to authorize that operation before calling - // update. Any other auth issues stop here. - if (!authRc.isOk() && authRc != ResponseCode::OP_AUTH_NEEDED) { - return worker_cb(operationFailed(authRc)); - } - - // Add entropy to the device first. - if (entropy.size()) { - rc = KS_HANDLE_HIDL_ERROR(dev, dev->addRngEntropy(entropy)); - if (!rc.isOk()) { - return worker_cb(operationFailed(rc)); - } - } - - // Create a keyid for this key. - auto keyid = KeymasterEnforcement::CreateKeyId(blob2hidlVec(keyBlob)); - if (!keyid) { - ALOGE("Failed to create a key ID for authorization checking."); - return worker_cb(operationFailed(ErrorCode::UNKNOWN_ERROR)); - } - - // Check that all key authorization policy requirements are met. - AuthorizationSet key_auths = characteristics.hardwareEnforced; - key_auths.append(characteristics.softwareEnforced.begin(), - characteristics.softwareEnforced.end()); - - rc = keyStore_->getEnforcementPolicy().AuthorizeOperation( - purpose, *keyid, key_auths, opParams, authToken, 0 /* op_handle */, - true /* is_begin_operation */); - if (!rc.isOk()) { - return worker_cb(operationFailed(rc)); - } - - // If there are more than kMaxOperations, abort the oldest operation that was started as - // pruneable. - while (operationMap_.getOperationCount() >= kMaxOperations) { - ALOGD("Reached or exceeded concurrent operations limit"); - if (!pruneOperation()) { - break; - } - } - - android::security::keymaster::OperationResult result; - - auto hidlCb = [&](ErrorCode ret, const hidl_vec& outParams, - uint64_t operationHandle) { - dev->logIfKeymasterVendorError(ret); - result.resultCode = ret; - if (!result.resultCode.isOk()) { - if (result.resultCode == ErrorCode::INVALID_KEY_BLOB) { - log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid()); - } - return; - } - result.handle = operationHandle; - result.outParams = outParams; - }; - - do { - rc = KS_HANDLE_HIDL_ERROR(dev, dev->begin(purpose, blob2hidlVec(keyBlob), - opParams.hidl_data(), authToken, hidlCb)); - if (!rc.isOk()) { - LOG(ERROR) << "Got error " << rc << " from begin()"; - return worker_cb(operationFailed(ResponseCode::SYSTEM_ERROR)); - } - - if (result.resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) { - std::tie(rc, keyBlob) = upgradeKeyBlob(lockedEntry, opParams); - if (!rc.isOk()) { - return worker_cb(operationFailed(rc)); - } - - rc = KS_HANDLE_HIDL_ERROR(dev, dev->begin(purpose, blob2hidlVec(keyBlob), - opParams.hidl_data(), authToken, hidlCb)); - if (!rc.isOk()) { - LOG(ERROR) << "Got error " << rc << " from begin()"; - return worker_cb(operationFailed(ResponseCode::SYSTEM_ERROR)); - } - } - // If there are too many operations abort the oldest operation that was - // started as pruneable and try again. - } while (result.resultCode == ErrorCode::TOO_MANY_OPERATIONS && pruneOperation()); - - rc = result.resultCode; - if (!rc.isOk()) { - return worker_cb(operationFailed(rc)); - } - - // Note: The operation map takes possession of the contents of "characteristics". - // It is safe to use characteristics after the following line but it will be empty. - sp operationToken = - operationMap_.addOperation(result.handle, *keyid, purpose, dev, appToken, - std::move(characteristics), opParams.hidl_data(), pruneable); - assert(characteristics.hardwareEnforced.size() == 0); - assert(characteristics.softwareEnforced.size() == 0); - result.token = operationToken; - - auto operation = operationMap_.getOperation(operationToken); - if (!operation) { - return worker_cb(operationFailed(ResponseCode::SYSTEM_ERROR)); - } - - if (authRc.isOk() && authToken.mac.size() && - dev->halVersion().securityLevel == SecurityLevel::STRONGBOX) { - operation->authTokenFuture = operation->authTokenPromise.get_future(); - std::weak_ptr weak_operation = operation; - - auto verifyTokenCB = [weak_operation](KeyStoreServiceReturnCode rc, - HardwareAuthToken authToken, - VerificationToken verificationToken) { - auto operation = weak_operation.lock(); - if (!operation) { - // operation aborted, nothing to do - return; - } - if (rc.isOk()) { - operation->authToken = std::move(authToken); - operation->verificationToken = std::move(verificationToken); - } - operation->authTokenPromise.set_value(rc); - }; - auto teeKmDevice = keyStore_->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT); - teeKmDevice->verifyAuthorization(result.handle, {}, std::move(authToken), - std::move(verifyTokenCB)); - } - - // Return the authentication lookup result. If this is a per operation - // auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the - // application should get an auth token using the handle before the - // first call to update, which will fail if keystore hasn't received the - // auth token. - if (result.resultCode.isOk()) { - result.resultCode = authRc; - } - return worker_cb(result); - }); -} - -KeyStoreServiceReturnCode -KeymasterWorker::getOperationAuthTokenIfNeeded(std::shared_ptr op) { - if (!op) return ErrorCode::INVALID_OPERATION_HANDLE; - - if (op->authTokenFuture.valid()) { - LOG(INFO) << "Waiting for verification token"; - op->authTokenFuture.wait(); - auto rc = op->authTokenFuture.get(); - if (!rc.isOk()) { - return rc; - } - op->authTokenFuture = {}; - } else if (!op->hasAuthToken()) { - KeyStoreServiceReturnCode rc; - HardwareAuthToken found; - std::tie(rc, found) = getAuthToken(op->characteristics, op->handle, op->purpose); - if (!rc.isOk()) return rc; - op->authToken = std::move(found); - } - - return ResponseCode::NO_ERROR; -} - -namespace { - -class Finalize { - private: - std::function f_; - - public: - explicit Finalize(std::function f) : f_(f) {} - ~Finalize() { - if (f_) f_(); - } - void release() { f_ = {}; } -}; - -} // namespace - -void KeymasterWorker::update(sp token, AuthorizationSet params, hidl_vec data, - update_cb worker_cb) { - Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(params), CAPTURE_MOVE(data), - CAPTURE_MOVE(worker_cb)]() { - KeyStoreServiceReturnCode rc; - auto op = operationMap_.getOperation(token); - if (!op) { - return worker_cb(operationFailed(ErrorCode::INVALID_OPERATION_HANDLE)); - } - - Finalize abort_operation_in_case_of_error([&] { - operationMap_.removeOperation(token, false, rc.getErrorCode()); - keyStore_->getAuthTokenTable().MarkCompleted(op->handle); - KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle)); - }); - - rc = getOperationAuthTokenIfNeeded(op); - if (!rc.isOk()) return worker_cb(operationFailed(rc)); - - // Check that all key authorization policy requirements are met. - AuthorizationSet key_auths(op->characteristics.hardwareEnforced); - key_auths.append(op->characteristics.softwareEnforced.begin(), - op->characteristics.softwareEnforced.end()); - - rc = keyStore_->getEnforcementPolicy().AuthorizeOperation(op->purpose, op->keyid, key_auths, - params, op->authToken, op->handle, - false /* is_begin_operation */); - if (!rc.isOk()) return worker_cb(operationFailed(rc)); - - OperationResult result; - auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed, - const hidl_vec& outParams, - const ::std::vector& output) { - op->device->logIfKeymasterVendorError(ret); - result.resultCode = ret; - if (result.resultCode.isOk()) { - result.inputConsumed = inputConsumed; - result.outParams = outParams; - result.data = output; - } - }; - - rc = KS_HANDLE_HIDL_ERROR(op->device, - op->device->update(op->handle, params.hidl_data(), data, - op->authToken, op->verificationToken, hidlCb)); - - // just a reminder: on success result->resultCode was set in the callback. So we only - // overwrite it if there was a communication error indicated by the ErrorCode. - if (!rc.isOk()) result.resultCode = rc; - if (result.resultCode.isOk()) { - // if everything went well we don't abort the operation. - abort_operation_in_case_of_error.release(); - } - return worker_cb(std::move(result)); - }); -} - -/** - * Check that all KeyParameters provided by the application are allowed. Any parameter that keystore - * adds itself should be disallowed here. - */ -template -static bool checkAllowedOperationParams(ParamsIter begin, const ParamsIter end) { - while (begin != end) { - switch (begin->tag) { - case Tag::ATTESTATION_APPLICATION_ID: - case Tag::RESET_SINCE_ID_ROTATION: - return false; - default: - break; - } - ++begin; - } - return true; -} - -void KeymasterWorker::finish(sp token, AuthorizationSet params, hidl_vec input, - hidl_vec signature, hidl_vec entropy, - finish_cb worker_cb) { - Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(params), CAPTURE_MOVE(input), - CAPTURE_MOVE(signature), CAPTURE_MOVE(entropy), - CAPTURE_MOVE(worker_cb)]() mutable { - KeyStoreServiceReturnCode rc; - auto op = operationMap_.getOperation(token); - if (!op) { - return worker_cb(operationFailed(ErrorCode::INVALID_OPERATION_HANDLE)); - } - - bool finished = false; - Finalize abort_operation_in_case_of_error([&] { - operationMap_.removeOperation(token, finished && rc.isOk(), rc.getErrorCode()); - keyStore_->getAuthTokenTable().MarkCompleted(op->handle); - if (!finished) - KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle)); - }); - - if (!checkAllowedOperationParams(params.begin(), params.end())) { - return worker_cb(operationFailed(ErrorCode::INVALID_ARGUMENT)); - } - - rc = getOperationAuthTokenIfNeeded(op); - if (!rc.isOk()) return worker_cb(operationFailed(rc)); - - // Check that all key authorization policy requirements are met. - AuthorizationSet key_auths(op->characteristics.hardwareEnforced); - key_auths.append(op->characteristics.softwareEnforced.begin(), - op->characteristics.softwareEnforced.end()); - - if (key_auths.Contains(Tag::TRUSTED_CONFIRMATION_REQUIRED)) { - hidl_vec confirmationToken = - keyStore_->getConfirmationManager().getLatestConfirmationToken(); - if (confirmationToken.size() == 0) { - LOG(ERROR) << "Confirmation token required but none found"; - return worker_cb(operationFailed(ErrorCode::NO_USER_CONFIRMATION)); - } - params.push_back(keymaster::TAG_CONFIRMATION_TOKEN, std::move(confirmationToken)); - } - - rc = keyStore_->getEnforcementPolicy().AuthorizeOperation(op->purpose, op->keyid, key_auths, - params, op->authToken, op->handle, - false /* is_begin_operation */); - if (!rc.isOk()) return worker_cb(operationFailed(rc)); - - if (entropy.size()) { - rc = KS_HANDLE_HIDL_ERROR(op->device, op->device->addRngEntropy(entropy)); - if (!rc.isOk()) { - return worker_cb(operationFailed(rc)); - } - } - - OperationResult result; - auto hidlCb = [&](ErrorCode ret, const hidl_vec& outParams, - const ::std::vector& output) { - op->device->logIfKeymasterVendorError(ret); - result.resultCode = ret; - if (result.resultCode.isOk()) { - result.outParams = outParams; - result.data = output; - } - }; - - rc = KS_HANDLE_HIDL_ERROR(op->device, op->device->finish(op->handle, params.hidl_data(), - input, signature, op->authToken, - op->verificationToken, hidlCb)); - - if (rc.isOk()) { - // inform the finalizer that the finish call went through - finished = true; - // and what the result was - rc = result.resultCode; - } else { - return worker_cb(operationFailed(rc)); - } - return worker_cb(std::move(result)); - }); -} - -void KeymasterWorker::abort(sp token, abort_cb worker_cb) { - Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(worker_cb)]() { - return worker_cb(abort(token, ResponseCode::ABORT_CALLED)); - }); -} - -void KeymasterWorker::verifyAuthorization(uint64_t challenge, hidl_vec params, - HardwareAuthToken token, - verifyAuthorization_cb worker_cb) { - Worker::addRequest([this, challenge, CAPTURE_MOVE(params), CAPTURE_MOVE(token), - CAPTURE_MOVE(worker_cb)]() { - KeyStoreServiceReturnCode error; - VerificationToken verificationToken; - KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR( - keymasterDevice_, - keymasterDevice_->verifyAuthorization( - challenge, params, token, [&](ErrorCode ret, const VerificationToken& vToken) { - keymasterDevice_->logIfKeymasterVendorError(ret); - error = ret; - verificationToken = vToken; - })); - worker_cb(rc.isOk() ? error : rc, std::move(token), std::move(verificationToken)); - }); -} - -void KeymasterWorker::addRngEntropy(hidl_vec data, addRngEntropy_cb _hidl_cb) { - addRequest(&Keymaster::addRngEntropy, std::move(_hidl_cb), std::move(data)); -} - -namespace { -bool containsTag(const hidl_vec& params, Tag tag) { - return params.end() != - std::find_if(params.begin(), params.end(), - [&](const KeyParameter& param) { return param.tag == tag; }); -} - -bool isAuthenticationBound(const hidl_vec& params) { - return !containsTag(params, Tag::NO_AUTH_REQUIRED); -} -} // namespace - -void KeymasterWorker::generateKey(LockedKeyBlobEntry lockedEntry, hidl_vec keyParams, - hidl_vec entropy, int flags, generateKey_cb worker_cb) { - Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(keyParams), - CAPTURE_MOVE(entropy), CAPTURE_MOVE(worker_cb), flags]() mutable { - KeyStoreServiceReturnCode rc = - KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->addRngEntropy(entropy)); - if (!rc.isOk()) { - return worker_cb(rc, {}); - } - - SecurityLevel securityLevel = keymasterDevice_->halVersion().securityLevel; - - // Fallback cannot be considered for Strongbox. Further versions restrictions are enforced - // by KeyStore::getFallbackDevice() - bool consider_fallback = securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT; - - Finalize logOnFail([&] { - logKeystoreKeyCreationEvent(keyParams, false /*wasCreationSuccessful*/, - rc.getErrorCode()); - }); - - KeyCharacteristics outCharacteristics; - KeyStoreServiceReturnCode error; - auto hidl_cb = [&](ErrorCode ret, const hidl_vec& hidlKeyBlob, - const KeyCharacteristics& keyCharacteristics) { - keymasterDevice_->logIfKeymasterVendorError(ret); - error = ret; - if (!error.isOk()) { - return; - } - consider_fallback = false; - outCharacteristics = keyCharacteristics; - - Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10); - keyBlob.setSecurityLevel(internalSecurityLevel_); - keyBlob.setCriticalToDeviceEncryption(flags & - KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION); - if (isAuthenticationBound(keyParams) && !keyBlob.isCriticalToDeviceEncryption()) { - keyBlob.setSuperEncrypted(true); - } - keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED); - - AuthorizationSet sw_enforced = keyParams; - sw_enforced.Subtract(outCharacteristics.hardwareEnforced); - sw_enforced.Union(outCharacteristics.softwareEnforced); - sw_enforced.Filter([](const KeyParameter& param) -> bool { - return !(param.tag == Tag::APPLICATION_DATA || param.tag == Tag::APPLICATION_ID); - }); - if (!sw_enforced.Contains(Tag::USER_ID)) { - // Most Java processes don't have access to this tag - sw_enforced.push_back(keymaster::TAG_USER_ID, get_user_id(lockedEntry->uid())); - } - Blob keyCharBlob; - keyCharBlob.putKeyCharacteristics(outCharacteristics.hardwareEnforced, sw_enforced); - error = keyStore_->put(lockedEntry, std::move(keyBlob), std::move(keyCharBlob)); - }; - - rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_, - keymasterDevice_->generateKey(keyParams, hidl_cb)); - if (!rc.isOk()) { - return worker_cb(rc, {}); - } - - if (consider_fallback && !error.isOk()) { - auto fallback = keyStore_->getFallbackDevice(); - if (!fallback) { - return worker_cb(error, {}); - } - // No fallback for 3DES - for (auto& param : keyParams) { - auto algorithm = authorizationValue(TAG_ALGORITHM, param); - if (algorithm.isOk() && algorithm.value() == Algorithm::TRIPLE_DES) { - return worker_cb(ErrorCode::UNSUPPORTED_ALGORITHM, {}); - } - } - - // delegate to fallback worker - fallback->generateKey(std::move(lockedEntry), std::move(keyParams), std::move(entropy), - flags, std::move(worker_cb)); - // let fallback do the logging - logOnFail.release(); - return; - } - - if (!error.isOk()) return worker_cb(error, {}); - - // log on success - logOnFail.release(); - logKeystoreKeyCreationEvent(keyParams, true /*wasCreationSuccessful*/, - error.getErrorCode()); - - return worker_cb(error, std::move(outCharacteristics)); - }); -} - -void KeymasterWorker::generateKey(hidl_vec keyParams, generateKey2_cb worker_cb) { - addRequest(&Keymaster::generateKey, std::move(worker_cb), std::move(keyParams)); -} - -void KeymasterWorker::getKeyCharacteristics(LockedKeyBlobEntry lockedEntry, - hidl_vec clientId, hidl_vec appData, - Blob keyBlob, Blob charBlob, - getKeyCharacteristics_cb worker_cb) { - Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(clientId), - CAPTURE_MOVE(appData), CAPTURE_MOVE(keyBlob), CAPTURE_MOVE(charBlob), - CAPTURE_MOVE(worker_cb)]() { - auto result = createKeyCharacteristicsCache(lockedEntry, clientId, appData, - std::move(keyBlob), std::move(charBlob)); - return worker_cb(std::get<0>(result), std::move(std::get<1>(result))); - }); -} - -void KeymasterWorker::importKey(LockedKeyBlobEntry lockedEntry, hidl_vec keyParams, - KeyFormat keyFormat, hidl_vec keyData, int flags, - importKey_cb worker_cb) { - Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(keyParams), keyFormat, - CAPTURE_MOVE(keyData), flags, CAPTURE_MOVE(worker_cb)]() mutable { - SecurityLevel securityLevel = keymasterDevice_->halVersion().securityLevel; - - // Fallback cannot be considered for Strongbox. Further versions restrictions are enforced - // by KeyStore::getFallbackDevice() - bool consider_fallback = securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT; - - KeyStoreServiceReturnCode error; - Finalize logOnFail([&] { - logKeystoreKeyCreationEvent(keyParams, false /*wasCreationSuccessful*/, - error.getErrorCode()); - }); - - KeyCharacteristics outCharacteristics; - auto hidl_cb = [&](ErrorCode ret, const hidl_vec& hidlKeyBlob, - const KeyCharacteristics& keyCharacteristics) { - keymasterDevice_->logIfKeymasterVendorError(ret); - error = ret; - if (!error.isOk()) { - LOG(INFO) << "importKey failed"; - return; - } - consider_fallback = false; - outCharacteristics = keyCharacteristics; - - Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10); - keyBlob.setSecurityLevel(internalSecurityLevel_); - keyBlob.setCriticalToDeviceEncryption(flags & - KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION); - if (isAuthenticationBound(keyParams) && !keyBlob.isCriticalToDeviceEncryption()) { - keyBlob.setSuperEncrypted(true); - } - keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED); - - AuthorizationSet sw_enforced = keyParams; - sw_enforced.Subtract(outCharacteristics.hardwareEnforced); - sw_enforced.Union(outCharacteristics.softwareEnforced); - sw_enforced.Filter([](const KeyParameter& param) -> bool { - return !(param.tag == Tag::APPLICATION_DATA || param.tag == Tag::APPLICATION_ID); - }); - if (!sw_enforced.Contains(Tag::USER_ID)) { - // Most Java processes don't have access to this tag - sw_enforced.push_back(keymaster::TAG_USER_ID, get_user_id(lockedEntry->uid())); - } - Blob keyCharBlob; - keyCharBlob.putKeyCharacteristics(outCharacteristics.hardwareEnforced, sw_enforced); - error = keyStore_->put(lockedEntry, std::move(keyBlob), std::move(keyCharBlob)); - }; - - KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR( - keymasterDevice_, keymasterDevice_->importKey(keyParams, keyFormat, keyData, hidl_cb)); - if (!rc.isOk()) { - return worker_cb(rc, {}); - } - - if (consider_fallback && !error.isOk()) { - auto fallback = keyStore_->getFallbackDevice(); - if (!fallback) { - return worker_cb(error, {}); - } - // No fallback for 3DES - for (auto& param : keyParams) { - auto algorithm = authorizationValue(TAG_ALGORITHM, param); - if (algorithm.isOk() && algorithm.value() == Algorithm::TRIPLE_DES) { - return worker_cb(ErrorCode::UNSUPPORTED_ALGORITHM, {}); - } - } - - // delegate to fallback worker - fallback->importKey(std::move(lockedEntry), std::move(keyParams), keyFormat, - std::move(keyData), flags, std::move(worker_cb)); - // let fallback to the logging - logOnFail.release(); - return; - } - - if (!error.isOk()) return worker_cb(error, {}); - - // log on success - logOnFail.release(); - logKeystoreKeyCreationEvent(keyParams, true /*wasCreationSuccessful*/, - error.getErrorCode()); - - return worker_cb(error, std::move(outCharacteristics)); - }); -} - -void KeymasterWorker::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) { - Worker::addRequest([this, CAPTURE_MOVE(wrappingLockedEntry), CAPTURE_MOVE(wrapppedLockedEntry), - CAPTURE_MOVE(wrappedKeyData), CAPTURE_MOVE(maskingKey), - CAPTURE_MOVE(unwrappingParams), CAPTURE_MOVE(wrappingBlob), - CAPTURE_MOVE(wrappingCharBlob), passwordSid, biometricSid, - CAPTURE_MOVE(worker_cb)]() mutable { - auto hidlWrappingKey = blob2hidlVec(wrappingBlob); - - KeyCharacteristics outCharacteristics; - KeyStoreServiceReturnCode error; - - auto hidlCb = [&](ErrorCode ret, const hidl_vec& hidlKeyBlob, - const KeyCharacteristics& keyCharacteristics) { - keymasterDevice_->logIfKeymasterVendorError(ret); - error = ret; - if (!error.isOk()) { - return; - } - outCharacteristics = keyCharacteristics; - - Blob keyBlob(hidlKeyBlob.data(), hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10); - keyBlob.setSecurityLevel(internalSecurityLevel_); - if (isAuthenticationBound(keyCharacteristics.hardwareEnforced)) { - keyBlob.setSuperEncrypted(true); - } - - AuthorizationSet sw_enforced = outCharacteristics.softwareEnforced; - if (!sw_enforced.Contains(Tag::USER_ID)) { - // Most Java processes don't have access to this tag - sw_enforced.push_back(keymaster::TAG_USER_ID, - get_user_id(wrapppedLockedEntry->uid())); - } - Blob keyCharBlob; - keyCharBlob.putKeyCharacteristics(outCharacteristics.hardwareEnforced, sw_enforced); - error = keyStore_->put(wrapppedLockedEntry, std::move(keyBlob), std::move(keyCharBlob)); - }; - - KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR( - keymasterDevice_, keymasterDevice_->importWrappedKey( - wrappedKeyData, hidlWrappingKey, maskingKey, unwrappingParams, - passwordSid, biometricSid, hidlCb)); - - // possible hidl error - if (!rc.isOk()) { - return worker_cb(rc, {}); - } - - if (error == ErrorCode::KEY_REQUIRES_UPGRADE) { - std::tie(rc, wrappingBlob) = upgradeKeyBlob(wrappingLockedEntry, {}); - if (!rc.isOk()) { - return worker_cb(rc, {}); - } - - auto upgradedHidlKeyBlob = blob2hidlVec(wrappingBlob); - - rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_, - keymasterDevice_->importWrappedKey( - wrappedKeyData, upgradedHidlKeyBlob, maskingKey, - unwrappingParams, passwordSid, biometricSid, hidlCb)); - if (!rc.isOk()) { - error = rc; - } - } - return worker_cb(error, std::move(outCharacteristics)); - }); -} - -void KeymasterWorker::exportKey(LockedKeyBlobEntry lockedEntry, KeyFormat exportFormat, - hidl_vec clientId, hidl_vec appData, Blob keyBlob, - Blob charBlob, exportKey_cb worker_cb) { - Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), exportFormat, CAPTURE_MOVE(clientId), - CAPTURE_MOVE(appData), CAPTURE_MOVE(keyBlob), CAPTURE_MOVE(charBlob), - CAPTURE_MOVE(worker_cb)]() mutable { - auto key = blob2hidlVec(keyBlob); - - ExportResult result; - auto hidlCb = [&](ErrorCode ret, - const ::android::hardware::hidl_vec& keyMaterial) { - keymasterDevice_->logIfKeymasterVendorError(ret); - result.resultCode = ret; - if (!result.resultCode.isOk()) { - if (result.resultCode == ErrorCode::INVALID_KEY_BLOB) { - log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid()); - } - return; - } - result.exportData = keyMaterial; - }; - KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR( - keymasterDevice_, - keymasterDevice_->exportKey(exportFormat, key, clientId, appData, hidlCb)); - - // Overwrite result->resultCode only on HIDL error. Otherwise we want the result set in the - // callback hidlCb. - if (!rc.isOk()) { - result.resultCode = rc; - } - - if (result.resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) { - AuthorizationSet upgradeParams; - if (clientId.size()) { - upgradeParams.push_back(TAG_APPLICATION_ID, clientId); - } - if (appData.size()) { - upgradeParams.push_back(TAG_APPLICATION_DATA, appData); - } - std::tie(rc, keyBlob) = upgradeKeyBlob(lockedEntry, upgradeParams); - if (!rc.isOk()) { - return worker_cb(std::move(result)); - } - - auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob); - - rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_, - keymasterDevice_->exportKey(exportFormat, upgradedHidlKeyBlob, - clientId, appData, hidlCb)); - if (!rc.isOk()) { - result.resultCode = rc; - } - } - return worker_cb(std::move(result)); - }); -} -void KeymasterWorker::attestKey(hidl_vec keyToAttest, hidl_vec attestParams, - attestKey_cb worker_cb) { - addRequest(&Keymaster::attestKey, std::move(worker_cb), std::move(keyToAttest), - std::move(attestParams)); -} - -void KeymasterWorker::deleteKey(hidl_vec keyBlob, deleteKey_cb _hidl_cb) { - addRequest(&Keymaster::deleteKey, std::move(_hidl_cb), std::move(keyBlob)); -} - -void KeymasterWorker::binderDied(android::wp who) { - Worker::addRequest([this, who]() { - auto operations = operationMap_.getOperationsForToken(who.unsafe_get()); - for (const auto& token : operations) { - abort(token, ResponseCode::BINDER_DIED); - keyStore_->removeOperationDevice(token); - } - }); -} - -} // namespace keystore diff --git a/keystore/keymaster_worker.h b/keystore/keymaster_worker.h deleted file mode 100644 index fbd52b4d..00000000 --- a/keystore/keymaster_worker.h +++ /dev/null @@ -1,307 +0,0 @@ -/* -** -** 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_; - - /** - * Models the security level of this worker internal to KeyStore. - * - * When the device has only a software Keymaster, KeyStore will set it on the TEE slot and - * instantiate a new in-process software Keymaster. In that case there is a mismatch between the - * security level used by KeyStore and what is reported from the HAL. This represents the level - * used internally by KeyStore. - * - * This value is used to associate blobs to the corresponding Keymaster backend. It does not - * indicate an actual Keymaster HAL security level and should never be exposed to users. - */ - SecurityLevel internalSecurityLevel_; - - 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, ResponseCode reason_for_abort); - - bool pruneOperation(); - - KeyStoreServiceReturnCode getOperationAuthTokenIfNeeded(std::shared_ptr op); - - void appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics, - hidl_vec* params); - - public: - KeymasterWorker(sp keymasterDevice, KeyStore* keyStore, - SecurityLevel internalSecurityLevel); - - 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_ diff --git a/keystore/keystore.rc b/keystore/keystore.rc deleted file mode 100644 index 132039a8..00000000 --- a/keystore/keystore.rc +++ /dev/null @@ -1,5 +0,0 @@ -service keystore /system/bin/keystore /data/misc/keystore - class main - user keystore - group keystore drmrpc readproc log - writepid /dev/cpuset/foreground/tasks diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.cpp b/keystore/keystore_aidl_hidl_marshalling_utils.cpp deleted file mode 100644 index 823ca587..00000000 --- a/keystore/keystore_aidl_hidl_marshalling_utils.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* -** -** Copyright 2016, 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. -*/ - -#include "keystore_aidl_hidl_marshalling_utils.h" - -#include -#include -#include -#include -#include -#include - -namespace keystore { - -// reads byte[] -hidl_vec readKeymasterBlob(const android::Parcel& in) { - - ssize_t length = in.readInt32(); - if (length <= 0) { - return {}; - } - - const void* buf = in.readInplace(length); - if (!buf) return {}; - - return blob2hidlVec(reinterpret_cast(buf), size_t(length)); -} - -android::status_t writeKeymasterBlob(const hidl_vec& blob, android::Parcel* out) { - int32_t size = int32_t(std::min(blob.size(), std::numeric_limits::max())); - - auto rc = out->writeInt32(size); - if (rc != ::android::OK) return rc; - - if (!size) return ::android::OK; - - return out->write(blob.data(), size); -} - -android::status_t writeKeymasterBlob(const ::std::vector& blob, android::Parcel* out) { - - int32_t size = int32_t(std::min(blob.size(), std::numeric_limits::max())); - - auto rc = out->writeInt32(size); - if (rc != ::android::OK) return rc; - - if (!size) return ::android::OK; - - return out->write(blob.data(), size); -} - -NullOr readKeyParameterFromParcel(const android::Parcel& in) { - // Method must be in sync with KeymasterArgument.java - if (in.readInt32() == 0) { - return {}; - } - KeyParameter result; - - Tag tag = static_cast(in.readInt32()); - result.tag = tag; - switch (typeFromTag(tag)) { - case TagType::ENUM: - case TagType::ENUM_REP: - case TagType::UINT: - case TagType::UINT_REP: - result.f.integer = in.readInt32(); - break; - case TagType::ULONG: - case TagType::ULONG_REP: - case TagType::DATE: - result.f.longInteger = in.readInt64(); - break; - case TagType::BOOL: - result.f.boolValue = true; - break; - case TagType::BIGNUM: - case TagType::BYTES: - result.blob = readKeymasterBlob(in); // byte array - break; - default: - ALOGE("Unsupported KeyParameter tag %d", tag); - return {}; - } - return result; -} - -android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out) { - // Method must be in sync with with KeymasterArgument.java - // Presence flag must be written by caller. - - auto tag = param.tag; - auto rc = out->writeInt32(uint32_t(tag)); - if (rc != ::android::OK) return rc; - switch (typeFromTag(param.tag)) { - case TagType::ENUM: - case TagType::ENUM_REP: - case TagType::UINT: - case TagType::UINT_REP: - rc = out->writeInt32(param.f.integer); - break; - case TagType::ULONG: - case TagType::ULONG_REP: - case TagType::DATE: - rc = out->writeInt64(param.f.longInteger); - break; - case TagType::BOOL: - // nothing to do here presence indicates true - break; - case TagType::BIGNUM: - case TagType::BYTES: - rc = writeKeymasterBlob(param.blob, out); - break; - default: - ALOGE("Failed to write KeyParameter: Unsupported tag %d", param.tag); - rc = android::BAD_VALUE; - break; - } - return rc; -} - -hidl_vec readParamSetFromParcel(const android::Parcel& in) { - - ssize_t length = in.readInt32(); // -1 for null - size_t ulength = (size_t)length; - if (length < 0) { - ulength = 0; - } - hidl_vec result; - result.resize(ulength); - for (size_t i = 0; i < ulength; ++i) { - auto param = readKeyParameterFromParcel(in); - if (!param.isOk()) { - ALOGE("Error reading KeyParameter from parcel"); - return {}; - } - result[i] = param.value(); - } - return result; -} - -android::status_t writeParamSetToParcel(const hidl_vec& params, - android::Parcel* out) { - int32_t size = int32_t(std::min(params.size(), std::numeric_limits::max())); - - auto rc = out->writeInt32(size); - if (rc != ::android::OK) return rc; - for (int32_t i = 0; i < size; ++i) { - rc = out->writeInt32(1); // writeTypedObject presence flag. - if (rc != ::android::OK) return rc; - rc = writeKeyParameterToParcel(params[i], out); - if (rc != ::android::OK) return rc; - } - return rc; -} - -hidl_vec> readCertificateChainFromParcel(const android::Parcel& in) { - hidl_vec> result; - - ssize_t count = in.readInt32(); - size_t ucount = count; - if (count <= 0) { - return result; - } - - result.resize(ucount); - - for (size_t i = 0; i < ucount; ++i) { - result[i] = readKeymasterBlob(in); - } - return result; -}; - -android::status_t writeCertificateChainToParcel(const hidl_vec>& certs, - android::Parcel* out) { - int32_t count = int32_t(std::min(certs.size(), std::numeric_limits::max())); - auto rc = out->writeInt32(count); - - for (int32_t i = 0; i < count; ++i) { - rc = writeKeymasterBlob(certs[i], out); - if (rc != ::android::OK) return rc; - } - return rc; -} - -}; // namespace keystore - -// Implementation for keystore parcelables. -// TODO: split implementation into separate classes -namespace android { -namespace security { -namespace keymaster { - -using ::android::status_t; -using ::keystore::ErrorCode; - -ExportResult::ExportResult() : resultCode() {} - -ExportResult::~ExportResult() {} - -status_t ExportResult::readFromParcel(const Parcel* inn) { - const Parcel& in = *inn; - resultCode = ErrorCode(in.readInt32()); - exportData = keystore::readKeymasterBlob(in); - return OK; -} - -status_t ExportResult::writeToParcel(Parcel* out) const { - out->writeInt32(resultCode.getErrorCode()); - return keystore::writeKeymasterBlob(exportData, out); -} - -status_t KeyCharacteristics::readFromParcel(const Parcel* in) { - softwareEnforced.readFromParcel(in); - return hardwareEnforced.readFromParcel(in); -} - -status_t KeyCharacteristics::writeToParcel(Parcel* out) const { - softwareEnforced.writeToParcel(out); - return hardwareEnforced.writeToParcel(out); -} - -status_t KeymasterBlob::readFromParcel(const Parcel* in) { - data_ = keystore::readKeymasterBlob(*in); - return OK; -} - -status_t KeymasterBlob::writeToParcel(Parcel* out) const { - return keystore::writeKeymasterBlob(data_, out); -} - -status_t KeymasterCertificateChain::readFromParcel(const Parcel* in) { - chain = keystore::readCertificateChainFromParcel(*in); - return OK; -} - -status_t KeymasterCertificateChain::writeToParcel(Parcel* out) const { - return keystore::writeCertificateChainToParcel(chain, out); -} - -} // namespace keymaster -} // namespace security - -} // namespace android diff --git a/keystore/keystore_aidl_hidl_marshalling_utils.h b/keystore/keystore_aidl_hidl_marshalling_utils.h deleted file mode 100644 index ea72197a..00000000 --- a/keystore/keystore_aidl_hidl_marshalling_utils.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -** -** Copyright 2016, 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_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_ -#define KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_ - -#include - -#include - -#include - -namespace keystore { - -template -inline auto nullable(Fn fn, const android::Parcel& in, Args&&... args) - -> NullOr(args)...))> { - if (in.readInt32() != 1) { - return {}; - } - - return fn(in, std::forward(args)...); -} -template -inline android::status_t nullable(Fn fn, const NullOr& arg, android::Parcel* out) { - if (!arg.isOk()) { - return out->writeInt32(0); - } - auto rc = out->writeInt32(1); - if (rc != ::android::OK) return rc; - - return fn(arg.value(), out); -} -template -inline android::status_t nullable(Fn fn, Arg&& arg, android::Parcel* out) { - auto rc = out->writeInt32(1); - if (rc != ::android::OK) return rc; - - return fn(std::forward(arg), out); -} - -inline android::status_t nullable(android::Parcel* out) { - return out->writeInt32(0); -} - -/** - * makes a copy only if inPlace is false - */ -hidl_vec readKeymasterBlob(const android::Parcel& in); -android::status_t writeKeymasterBlob(const hidl_vec& blob, android::Parcel* out); - -NullOr> readBlobAsByteArray(const android::Parcel& in, bool inPlace = true); -android::status_t writeBlobAsByteArray(const NullOr&>& blob, - android::Parcel* out); - -NullOr readKeyParameterFromParcel(const android::Parcel& in); -android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out); - -hidl_vec readParamSetFromParcel(const android::Parcel& in); -android::status_t writeParamSetToParcel(const hidl_vec& params, android::Parcel* out); - -hidl_vec> readCertificateChainFromParcel(const android::Parcel& in); -} - -#endif // KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_ diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp deleted file mode 100644 index 428a9bc1..00000000 --- a/keystore/keystore_cli.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -using namespace android; -using namespace keystore; -using android::security::keystore::IKeystoreService; - -static const char* responses[] = { - nullptr, - /* [NO_ERROR] = */ "No error", - /* [LOCKED] = */ "Locked", - /* [UNINITIALIZED] = */ "Uninitialized", - /* [SYSTEM_ERROR] = */ "System error", - /* [PROTOCOL_ERROR] = */ "Protocol error", - /* [PERMISSION_DENIED] = */ "Permission denied", - /* [KEY_NOT_FOUND] = */ "Key not found", - /* [VALUE_CORRUPTED] = */ "Value corrupted", - /* [UNDEFINED_ACTION] = */ "Undefined action", - /* [WRONG_PASSWORD] = */ "Wrong password (last chance)", - /* [WRONG_PASSWORD + 1] = */ "Wrong password (2 tries left)", - /* [WRONG_PASSWORD + 2] = */ "Wrong password (3 tries left)", - /* [WRONG_PASSWORD + 3] = */ "Wrong password (4 tries left)", -}; - -#define SINGLE_ARG_INT_RETURN(cmd) \ - do { \ - if (strcmp(argv[1], #cmd) == 0) { \ - if (argc < 3) { \ - fprintf(stderr, "Usage: %s " #cmd " \n", argv[0]); \ - return 1; \ - } \ - int32_t ret = -1; \ - service->cmd(String16(argv[2]), &ret); \ - if (ret < 0) { \ - fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \ - return 1; \ - } else { \ - printf(#cmd ": %s (%d)\n", responses[ret], ret); \ - return 0; \ - } \ - } \ - } while (0) - -#define SINGLE_INT_ARG_INT_RETURN(cmd) \ - do { \ - if (strcmp(argv[1], #cmd) == 0) { \ - if (argc < 3) { \ - fprintf(stderr, "Usage: %s " #cmd " \n", argv[0]); \ - return 1; \ - } \ - int32_t ret = -1; \ - service->cmd(atoi(argv[2]), &ret); \ - if (ret < 0) { \ - fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \ - return 1; \ - } else { \ - printf(#cmd ": %s (%d)\n", responses[ret], ret); \ - return 0; \ - } \ - } \ - } while (0) - -#define SINGLE_ARG_PLUS_UID_INT_RETURN(cmd) \ - do { \ - if (strcmp(argv[1], #cmd) == 0) { \ - if (argc < 3) { \ - fprintf(stderr, "Usage: %s " #cmd " \n", argv[0]); \ - return 1; \ - } \ - int uid = -1; \ - if (argc > 3) { \ - uid = atoi(argv[3]); \ - fprintf(stderr, "Running as uid %d\n", uid); \ - } \ - int32_t ret = -1; \ - service->cmd(String16(argv[2]), uid, &ret); \ - if (ret < 0) { \ - fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \ - return 1; \ - } else { \ - printf(#cmd ": %s (%d)\n", responses[ret], ret); \ - return 0; \ - } \ - } \ - } while (0) - -#define SINGLE_ARG_PLUS_UID_DATA_RETURN(cmd) \ - do { \ - if (strcmp(argv[1], #cmd) == 0) { \ - if (argc < 3) { \ - fprintf(stderr, "Usage: %s " #cmd " \n", argv[0]); \ - return 1; \ - } \ - std::vector data; \ - int uid = -1; \ - if (argc > 3) { \ - uid = atoi(argv[3]); \ - fprintf(stderr, "Running as uid %d\n", uid); \ - } \ - ::android::binder::Status ret = service->cmd(String16(argv[2]), uid, &data); \ - if (!ret.isOk()) { \ - fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \ - return 1; \ - } else { \ - fwrite(&data[0], data.size(), 1, stdout); \ - fflush(stdout); \ - return 0; \ - } \ - } \ - } while (0) - -#define STRING_ARG_DATA_STDIN_INT_RETURN(cmd) \ - do { \ - if (strcmp(argv[1], #cmd) == 0) { \ - if (argc < 3) { \ - fprintf(stderr, "Usage: %s " #cmd " \n", argv[0]); \ - return 1; \ - } \ - uint8_t* data; \ - size_t dataSize; \ - read_input(&data, &dataSize); \ - int32_t ret = -1; \ - service->cmd(String16(argv[2]), data, dataSize, &ret); \ - if (ret < 0) { \ - fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \ - return 1; \ - } else { \ - printf(#cmd ": %s (%d)\n", responses[ret], ret); \ - return 0; \ - } \ - } \ - } while (0) - -#define SINGLE_ARG_DATA_RETURN(cmd) \ - do { \ - if (strcmp(argv[1], #cmd) == 0) { \ - if (argc < 3) { \ - fprintf(stderr, "Usage: %s " #cmd " \n", argv[0]); \ - return 1; \ - } \ - std::vector data; \ - ::android::binder::Status ret = service->cmd(String16(argv[2]), &data); \ - if (!ret.isOk()) { \ - fprintf(stderr, "Exception code: %d\n", ret.exceptionCode()); \ - return 1; \ - } else { \ - fwrite(&data[0], data.size(), 1, stdout); \ - fflush(stdout); \ - return 0; \ - } \ - } \ - } while (0) - -static int list(const sp& service, const String16& name, int uid) { - std::vector matches; - ::android::binder::Status ret = service->list(name, uid, &matches); - - if (!ret.isOk()) { - fprintf(stderr, "list: exception (%d)\n", ret.exceptionCode()); - return 1; - } else { - std::vector::const_iterator it = matches.begin(); - for (; it != matches.end(); ++it) { - printf("%s\n", String8(*it).string()); - } - return 0; - } -} - -int main(int argc, char* argv[]) -{ - if (argc < 2) { - fprintf(stderr, "Usage: %s action [parameter ...]\n", argv[0]); - return 1; - } - - sp sm = defaultServiceManager(); - sp binder = sm->getService(String16("android.security.keystore")); - sp service = interface_cast(binder); - - if (service == nullptr) { - fprintf(stderr, "%s: error: could not connect to keystore service\n", argv[0]); - return 1; - } - - /* - * All the commands should return a value - */ - - SINGLE_INT_ARG_INT_RETURN(getState); - - SINGLE_ARG_PLUS_UID_DATA_RETURN(get); - - // TODO: insert - - SINGLE_ARG_PLUS_UID_INT_RETURN(del); - - SINGLE_ARG_PLUS_UID_INT_RETURN(exist); - - if (strcmp(argv[1], "list") == 0) { - return list(service, argc < 3 ? String16("") : String16(argv[2]), - argc < 4 ? -1 : atoi(argv[3])); - } - - // TODO: notifyUserPasswordChanged - - SINGLE_INT_ARG_INT_RETURN(lock); - - // TODO: unlock - - SINGLE_INT_ARG_INT_RETURN(isEmpty); - - // TODO: generate - - // TODO: grant - - // TODO: ungrant - - // TODO: getmtime - - fprintf(stderr, "%s: unknown command: %s\n", argv[0], argv[1]); - return 1; -} diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp index 4f69eb02..6e45ee27 100644 --- a/keystore/keystore_cli_v2.cpp +++ b/keystore/keystore_cli_v2.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -24,38 +26,56 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include -#include -#include +#include +#include +#include -//#include +#include "keystore_client.pb.h" -using base::CommandLine; -using keystore::KeystoreClient; +namespace apc = ::aidl::android::security::apc; +namespace keymint = ::aidl::android::hardware::security::keymint; +namespace ks2 = ::aidl::android::system::keystore2; -using android::sp; -using android::String16; -using android::security::keystore::IKeystoreService; using base::CommandLine; -using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode; +using keystore::EncryptedData; namespace { -using namespace keystore; struct TestCase { std::string name; bool required_for_brillo_pts; - AuthorizationSet parameters; + keymint::AuthorizationSet parameters; }; +constexpr const char keystore2_service_name[] = "android.system.keystore2"; + +int unwrapError(const ndk::ScopedAStatus& status) { + if (status.isOk()) return 0; + if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) { + return status.getServiceSpecificError(); + } else { + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } +} + +ks2::KeyDescriptor keyDescriptor(const std::string& alias) { + return { + .domain = ks2::Domain::APP, + .nspace = -1, // ignored - should be -1. + .alias = alias, + .blob = {}, + }; +} + void PrintUsageAndExit() { printf("Usage: keystore_client_v2 [options]\n"); printf("Commands: brillo-platform-test [--prefix=] [--test_for_0_3]\n" @@ -78,52 +98,487 @@ void PrintUsageAndExit() { exit(1); } -std::unique_ptr CreateKeystoreInstance() { - return std::unique_ptr( - static_cast(new keystore::KeystoreClientImpl)); +std::shared_ptr CreateKeystoreInstance() { + ::ndk::SpAIBinder keystoreBinder(AServiceManager_checkService(keystore2_service_name)); + auto result = ks2::IKeystoreService::fromBinder(keystoreBinder); + if (result) return result; + std::cerr << "Unable to connect to Keystore."; + exit(-1); +} + +std::shared_ptr +GetSecurityLevelInterface(std::shared_ptr keystore, + keymint::SecurityLevel securitylevel) { + std::shared_ptr sec_level; + auto rc = keystore->getSecurityLevel(securitylevel, &sec_level); + if (rc.isOk()) return sec_level; + std::cerr << "Unable to get security level interface from Keystore: " << rc.getDescription(); + exit(-1); +} + +bool isHardwareEnforced(const ks2::Authorization& a) { + return !(a.securityLevel == keymint::SecurityLevel::SOFTWARE || + a.securityLevel == keymint::SecurityLevel::KEYSTORE); } -void PrintTags(const AuthorizationSet& parameters) { - for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) { - auto tag_str = toString(iter->tag); - printf(" %s\n", tag_str.c_str()); +void PrintTags(const std::vector& characteristics, bool printHardwareEnforced) { + for (const auto& a : characteristics) { + if (isHardwareEnforced(a) == printHardwareEnforced) { + std::cout << toString(a.keyParameter.tag) << "\n"; + } } } -void PrintKeyCharacteristics(const AuthorizationSet& hardware_enforced_characteristics, - const AuthorizationSet& software_enforced_characteristics) { +void PrintKeyCharacteristics(const std::vector& characteristics) { printf("Hardware:\n"); - PrintTags(hardware_enforced_characteristics); + PrintTags(characteristics, true /* printHardwareEnforced */); printf("Software:\n"); - PrintTags(software_enforced_characteristics); + PrintTags(characteristics, false /* printHardwareEnforced */); +} + +const char kEncryptSuffix[] = "_ENC"; +const char kAuthenticateSuffix[] = "_AUTH"; +constexpr uint32_t kAESKeySize = 256; // bits +constexpr uint32_t kHMACKeySize = 256; // bits +constexpr uint32_t kHMACOutputSize = 256; // bits + +bool verifyEncryptionKeyAttributes(const std::vector authorizations) { + bool verified = true; + verified = + verified && + std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) { + return a.keyParameter.tag == keymint::Tag::ALGORITHM && + a.keyParameter.value == + keymint::KeyParameterValue::make( + keymint::Algorithm::AES); + }); + + verified = + verified && + std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) { + return a.keyParameter.tag == keymint::Tag::KEY_SIZE && + a.keyParameter.value == + keymint::KeyParameterValue::make( + kAESKeySize); + }); + + verified = + verified && + std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) { + return a.keyParameter.tag == keymint::Tag::BLOCK_MODE && + a.keyParameter.value == + keymint::KeyParameterValue::make( + keymint::BlockMode::CBC); + }); + + verified = + verified && + std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) { + return a.keyParameter.tag == keymint::Tag::PADDING && + a.keyParameter.value == + keymint::KeyParameterValue::make( + keymint::PaddingMode::PKCS7); + }); + + return verified; +} + +bool verifyAuthenticationKeyAttributes(const std::vector authorizations) { + bool verified = true; + verified = + verified && + std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) { + return a.keyParameter.tag == keymint::Tag::ALGORITHM && + a.keyParameter.value == + keymint::KeyParameterValue::make( + keymint::Algorithm::HMAC); + }); + + verified = + verified && + std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) { + return a.keyParameter.tag == keymint::Tag::KEY_SIZE && + a.keyParameter.value == + keymint::KeyParameterValue::make( + kHMACKeySize); + }); + + verified = + verified && + std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) { + return a.keyParameter.tag == keymint::Tag::MIN_MAC_LENGTH && + a.keyParameter.value == + keymint::KeyParameterValue::make( + kHMACOutputSize); + }); + + verified = + verified && + std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) { + return a.keyParameter.tag == keymint::Tag::DIGEST && + a.keyParameter.value == + keymint::KeyParameterValue::make( + keymint::Digest::SHA_2_256); + }); + return verified; +} + +std::variant +loadOrCreateAndVerifyEncryptionKey(const std::string& name, keymint::SecurityLevel securityLevel, + bool create) { + auto keystore = CreateKeystoreInstance(); + + ks2::KeyEntryResponse keyEntryResponse; + + bool foundKey = true; + auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse); + if (!rc.isOk()) { + auto error = unwrapError(rc); + if (ks2::ResponseCode(error) == ks2::ResponseCode::KEY_NOT_FOUND && create) { + foundKey = false; + } else { + std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl; + return error; + } + } + + if (!foundKey) { + auto sec_level = GetSecurityLevelInterface(keystore, securityLevel); + auto params = keymint::AuthorizationSetBuilder() + .AesEncryptionKey(kAESKeySize) + .Padding(keymint::PaddingMode::PKCS7) + .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC) + .Authorization(keymint::TAG_NO_AUTH_REQUIRED); + + ks2::KeyMetadata keyMetadata; + + rc = sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */, + params.vector_data(), 0 /* flags */, {} /* entropy */, + &keyMetadata); + if (!rc.isOk()) { + std::cerr << "Failed to generate key: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse); + if (!rc.isOk()) { + std::cerr << "Failed to get key entry (second try): " << rc.getDescription() + << std::endl; + return unwrapError(rc); + } + } + + if (!verifyEncryptionKeyAttributes(keyEntryResponse.metadata.authorizations)) { + std::cerr << "Key has wrong set of parameters." << std::endl; + return static_cast(ks2::ResponseCode::INVALID_ARGUMENT); + } + + return keyEntryResponse; +} + +std::variant +loadOrCreateAndVerifyAuthenticationKey(const std::string& name, + keymint::SecurityLevel securityLevel, bool create) { + auto keystore = CreateKeystoreInstance(); + + ks2::KeyEntryResponse keyEntryResponse; + + bool foundKey = true; + auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse); + if (!rc.isOk()) { + auto error = unwrapError(rc); + if (ks2::ResponseCode(error) == ks2::ResponseCode::KEY_NOT_FOUND && create) { + foundKey = false; + } else { + std::cerr << "Failed to get HMAC key entry: " << rc.getDescription() << std::endl; + return error; + } + } + + if (!foundKey) { + auto sec_level = GetSecurityLevelInterface(keystore, securityLevel); + auto params = keymint::AuthorizationSetBuilder() + .HmacKey(kHMACKeySize) + .Digest(keymint::Digest::SHA_2_256) + .Authorization(keymint::TAG_MIN_MAC_LENGTH, kHMACOutputSize) + .Authorization(keymint::TAG_NO_AUTH_REQUIRED); + + ks2::KeyMetadata keyMetadata; + + rc = sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */, + params.vector_data(), 0 /* flags */, {} /* entropy */, + &keyMetadata); + if (!rc.isOk()) { + std::cerr << "Failed to generate HMAC key: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse); + if (!rc.isOk()) { + std::cerr << "Failed to get HMAC key entry (second try): " << rc.getDescription() + << std::endl; + return unwrapError(rc); + } + } + + if (!verifyAuthenticationKeyAttributes(keyEntryResponse.metadata.authorizations)) { + std::cerr << "Key has wrong set of parameters." << std::endl; + return static_cast(ks2::ResponseCode::INVALID_ARGUMENT); + } + + return keyEntryResponse; +} + +std::variant> +encryptWithAuthentication(const std::string& name, const std::vector& data, + keymint::SecurityLevel securityLevel) { + // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random + // IV. The authentication algorithm is HMAC-SHA256 and is computed over the + // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM + // because hardware support for GCM is not mandatory for all Brillo devices. + std::string encryption_key_name = name + kEncryptSuffix; + auto encryption_key_result = + loadOrCreateAndVerifyEncryptionKey(encryption_key_name, securityLevel, true /* create */); + if (auto error = std::get_if(&encryption_key_result)) { + return *error; + } + auto encryption_key = std::get(encryption_key_result); + + std::string authentication_key_name = name + kAuthenticateSuffix; + auto authentication_key_result = loadOrCreateAndVerifyAuthenticationKey( + authentication_key_name, securityLevel, true /* create */); + if (auto error = std::get_if(&authentication_key_result)) { + return *error; + } + auto authentication_key = std::get(authentication_key_result); + + ks2::CreateOperationResponse encOperationResponse; + auto encrypt_params = keymint::AuthorizationSetBuilder() + .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::ENCRYPT) + .Padding(keymint::PaddingMode::PKCS7) + .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC); + + auto rc = encryption_key.iSecurityLevel->createOperation( + encryption_key.metadata.key, encrypt_params.vector_data(), false /* forced */, + &encOperationResponse); + if (!rc.isOk()) { + std::cerr << "Failed to begin encryption operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + std::optional> optCiphertext; + + rc = encOperationResponse.iOperation->finish(data, {}, &optCiphertext); + if (!rc.isOk()) { + std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + std::vector initVector; + if (auto params = encOperationResponse.parameters) { + for (auto& p : params->keyParameter) { + if (auto iv = keymint::authorizationValue(keymint::TAG_NONCE, p)) { + initVector = std::move(iv->get()); + break; + } + } + if (initVector.empty()) { + std::cerr << "Encryption operation did not return an IV." << std::endl; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + } + + if (!optCiphertext) { + std::cerr << "Encryption succeeded but no ciphertext returned." << std::endl; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + + auto ciphertext = std::move(*optCiphertext); + auto toBeSigned = initVector; + toBeSigned.insert(toBeSigned.end(), ciphertext.begin(), ciphertext.end()); + + ks2::CreateOperationResponse signOperationResponse; + auto sign_params = keymint::AuthorizationSetBuilder() + .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::SIGN) + .Digest(keymint::Digest::SHA_2_256) + .Authorization(keymint::TAG_MAC_LENGTH, kHMACOutputSize); + + rc = authentication_key.iSecurityLevel->createOperation( + authentication_key.metadata.key, sign_params.vector_data(), false /* forced */, + &signOperationResponse); + if (!rc.isOk()) { + std::cerr << "Failed to begin signing operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + std::optional> optMac; + + rc = signOperationResponse.iOperation->finish(toBeSigned, {}, &optMac); + if (!rc.isOk()) { + std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + if (!optMac) { + std::cerr << "Signing succeeded but no MAC returned." << std::endl; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + + auto mac = std::move(*optMac); + + EncryptedData protobuf; + protobuf.set_init_vector(initVector.data(), initVector.size()); + protobuf.set_authentication_data(mac.data(), mac.size()); + protobuf.set_encrypted_data(ciphertext.data(), ciphertext.size()); + std::string resultString; + if (!protobuf.SerializeToString(&resultString)) { + std::cerr << "Encrypt: Failed to serialize EncryptedData protobuf."; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + + std::vector result(reinterpret_cast(resultString.data()), + reinterpret_cast(resultString.data()) + + resultString.size()); + return result; +} + +std::variant> +decryptWithAuthentication(const std::string& name, const std::vector& data) { + + // Decode encrypted data + EncryptedData protobuf; + if (!protobuf.ParseFromArray(data.data(), data.size())) { + std::cerr << "Decrypt: Failed to parse EncryptedData protobuf." << std::endl; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + + // Load encryption and authentication keys. + std::string encryption_key_name = name + kEncryptSuffix; + auto encryption_key_result = loadOrCreateAndVerifyEncryptionKey( + encryption_key_name, keymint::SecurityLevel::KEYSTORE /* ignored */, false /* create */); + if (auto error = std::get_if(&encryption_key_result)) { + return *error; + } + auto encryption_key = std::get(encryption_key_result); + + std::string authentication_key_name = name + kAuthenticateSuffix; + auto authentication_key_result = loadOrCreateAndVerifyAuthenticationKey( + authentication_key_name, keymint::SecurityLevel::KEYSTORE /* ignored */, + false /* create */); + if (auto error = std::get_if(&authentication_key_result)) { + return *error; + } + auto authentication_key = std::get(authentication_key_result); + + // Begin authentication operation + ks2::CreateOperationResponse signOperationResponse; + auto sign_params = keymint::AuthorizationSetBuilder() + .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::VERIFY) + .Digest(keymint::Digest::SHA_2_256) + .Authorization(keymint::TAG_MAC_LENGTH, kHMACOutputSize); + + auto rc = authentication_key.iSecurityLevel->createOperation( + authentication_key.metadata.key, sign_params.vector_data(), false /* forced */, + &signOperationResponse); + if (!rc.isOk()) { + std::cerr << "Failed to begin verify operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + const uint8_t* p = reinterpret_cast(protobuf.init_vector().data()); + std::vector toBeVerified(p, p + protobuf.init_vector().size()); + + p = reinterpret_cast(protobuf.encrypted_data().data()); + toBeVerified.insert(toBeVerified.end(), p, p + protobuf.encrypted_data().size()); + + p = reinterpret_cast(protobuf.authentication_data().data()); + std::vector signature(p, p + protobuf.authentication_data().size()); + + std::optional> optOut; + rc = signOperationResponse.iOperation->finish(toBeVerified, signature, &optOut); + if (!rc.isOk()) { + std::cerr << "Decrypt: HMAC verification failed: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + // Begin decryption operation + ks2::CreateOperationResponse encOperationResponse; + auto encrypt_params = keymint::AuthorizationSetBuilder() + .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::DECRYPT) + .Authorization(keymint::TAG_NONCE, protobuf.init_vector().data(), + protobuf.init_vector().size()) + .Padding(keymint::PaddingMode::PKCS7) + .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC); + + rc = encryption_key.iSecurityLevel->createOperation(encryption_key.metadata.key, + encrypt_params.vector_data(), + false /* forced */, &encOperationResponse); + if (!rc.isOk()) { + std::cerr << "Failed to begin encryption operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + std::optional> optPlaintext; + + p = reinterpret_cast(protobuf.encrypted_data().data()); + std::vector cyphertext(p, p + protobuf.encrypted_data().size()); + + rc = encOperationResponse.iOperation->finish(cyphertext, {}, &optPlaintext); + if (!rc.isOk()) { + std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + if (!optPlaintext) { + std::cerr << "Decryption succeeded but no plaintext returned." << std::endl; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + + return *optPlaintext; } -bool TestKey(const std::string& name, bool required, const AuthorizationSet& parameters) { - std::unique_ptr keystore = CreateKeystoreInstance(); - AuthorizationSet hardware_enforced_characteristics; - AuthorizationSet software_enforced_characteristics; - auto result = - keystore->generateKey("tmp", parameters, 0 /*flags*/, &hardware_enforced_characteristics, - &software_enforced_characteristics); +bool TestKey(const std::string& name, bool required, + const std::vector& parameters) { + auto keystore = CreateKeystoreInstance(); + auto sec_level = + GetSecurityLevelInterface(keystore, keymint::SecurityLevel::TRUSTED_ENVIRONMENT); + + ks2::KeyDescriptor keyDescriptor = { + .domain = ks2::Domain::APP, + .nspace = -1, + .alias = "tmp", + .blob = {}, + }; + + ks2::KeyMetadata keyMetadata; + + auto rc = sec_level->generateKey(keyDescriptor, {} /* attestationKey */, parameters, + 0 /* flags */, {} /* entropy */, &keyMetadata); const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m"; - if (!result.isOk()) { - LOG(ERROR) << "Failed to generate key: " << result; + if (!rc.isOk()) { + LOG(ERROR) << "Failed to generate key: " << rc.getDescription(); printf("[%s] %s\n", kBoldRedAbort, name.c_str()); return false; } - result = keystore->deleteKey("tmp"); - if (!result.isOk()) { - LOG(ERROR) << "Failed to delete key: " << result; + + rc = keystore->deleteKey(keyDescriptor); + if (!rc.isOk()) { + LOG(ERROR) << "Failed to delete key: " << rc.getDescription(); printf("[%s] %s\n", kBoldRedAbort, name.c_str()); return false; } printf("===============================================================\n"); printf("%s Key Characteristics:\n", name.c_str()); - PrintKeyCharacteristics(hardware_enforced_characteristics, software_enforced_characteristics); - bool hardware_backed = (hardware_enforced_characteristics.size() > 0); - if (software_enforced_characteristics.GetTagCount(TAG_ALGORITHM) > 0 || - software_enforced_characteristics.GetTagCount(TAG_KEY_SIZE) > 0 || - software_enforced_characteristics.GetTagCount(TAG_RSA_PUBLIC_EXPONENT) > 0) { + PrintKeyCharacteristics(keyMetadata.authorizations); + bool hardware_backed = std::any_of(keyMetadata.authorizations.begin(), + keyMetadata.authorizations.end(), isHardwareEnforced); + if (std::any_of(keyMetadata.authorizations.begin(), keyMetadata.authorizations.end(), + [&](const auto& a) { + return !isHardwareEnforced(a) && + (a.keyParameter.tag == keymint::Tag::ALGORITHM || + a.keyParameter.tag == keymint::Tag::KEY_SIZE || + a.keyParameter.tag == keymint::Tag::RSA_PUBLIC_EXPONENT); + })) { VLOG(1) << "Hardware-backed key but required characteristics enforced in software."; hardware_backed = false; } @@ -137,60 +592,64 @@ bool TestKey(const std::string& name, bool required, const AuthorizationSet& par return (hardware_backed || !required); } -AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) { - AuthorizationSetBuilder parameters; +keymint::AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) { + keymint::AuthorizationSetBuilder parameters; parameters.RsaSigningKey(key_size, 65537) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN) - .Padding(PaddingMode::RSA_PSS) - .Authorization(TAG_NO_AUTH_REQUIRED); + .Digest(keymint::Digest::SHA_2_256) + .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN) + .Padding(keymint::PaddingMode::RSA_PSS) + .Authorization(keymint::TAG_NO_AUTH_REQUIRED); if (!sha256_only) { - parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512); + parameters.Digest(keymint::Digest::SHA_2_224) + .Digest(keymint::Digest::SHA_2_384) + .Digest(keymint::Digest::SHA_2_512); } return std::move(parameters); } -AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) { - AuthorizationSetBuilder parameters; +keymint::AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) { + keymint::AuthorizationSetBuilder parameters; parameters.RsaEncryptionKey(key_size, 65537) - .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT) - .Padding(PaddingMode::RSA_OAEP) - .Authorization(TAG_NO_AUTH_REQUIRED); + .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_ENCRYPT) + .Padding(keymint::PaddingMode::RSA_OAEP) + .Authorization(keymint::TAG_NO_AUTH_REQUIRED); return std::move(parameters); } -AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) { - AuthorizationSetBuilder parameters; +keymint::AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) { + keymint::AuthorizationSetBuilder parameters; parameters.EcdsaSigningKey(key_size) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_NO_AUTH_REQUIRED); + .Digest(keymint::Digest::SHA_2_256) + .Authorization(keymint::TAG_NO_AUTH_REQUIRED); if (!sha256_only) { - parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512); + parameters.Digest(keymint::Digest::SHA_2_224) + .Digest(keymint::Digest::SHA_2_384) + .Digest(keymint::Digest::SHA_2_512); } return std::move(parameters); } -AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) { - AuthorizationSetBuilder parameters; - parameters.AesEncryptionKey(key_size).Authorization(TAG_NO_AUTH_REQUIRED); +keymint::AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) { + keymint::AuthorizationSetBuilder parameters; + parameters.AesEncryptionKey(key_size).Authorization(keymint::TAG_NO_AUTH_REQUIRED); if (with_gcm_mode) { - parameters.Authorization(TAG_BLOCK_MODE, BlockMode::GCM) - .Authorization(TAG_MIN_MAC_LENGTH, 128); + parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::GCM) + .Authorization(keymint::TAG_MIN_MAC_LENGTH, 128); } else { - parameters.Authorization(TAG_BLOCK_MODE, BlockMode::ECB); - parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CBC); - parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CTR); - parameters.Padding(PaddingMode::NONE); + parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::ECB); + parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC); + parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CTR); + parameters.Padding(keymint::PaddingMode::NONE); } return std::move(parameters); } -AuthorizationSet GetHMACParameters(uint32_t key_size, Digest digest) { - AuthorizationSetBuilder parameters; +keymint::AuthorizationSet GetHMACParameters(uint32_t key_size, keymint::Digest digest) { + keymint::AuthorizationSetBuilder parameters; parameters.HmacKey(key_size) .Digest(digest) - .Authorization(TAG_MIN_MAC_LENGTH, 224) - .Authorization(TAG_NO_AUTH_REQUIRED); + .Authorization(keymint::TAG_MIN_MAC_LENGTH, 224) + .Authorization(keymint::TAG_NO_AUTH_REQUIRED); return std::move(parameters); } @@ -212,12 +671,12 @@ std::vector GetTestCases() { {"AES-256", true, GetAESParameters(256, false)}, {"AES-128-GCM", false, GetAESParameters(128, true)}, {"AES-256-GCM", false, GetAESParameters(256, true)}, - {"HMAC-SHA256-16", true, GetHMACParameters(16, Digest::SHA_2_256)}, - {"HMAC-SHA256-32", true, GetHMACParameters(32, Digest::SHA_2_256)}, - {"HMAC-SHA256-64", false, GetHMACParameters(64, Digest::SHA_2_256)}, - {"HMAC-SHA224-32", false, GetHMACParameters(32, Digest::SHA_2_224)}, - {"HMAC-SHA384-32", false, GetHMACParameters(32, Digest::SHA_2_384)}, - {"HMAC-SHA512-32", false, GetHMACParameters(32, Digest::SHA_2_512)}, + {"HMAC-SHA256-16", true, GetHMACParameters(16, keymint::Digest::SHA_2_256)}, + {"HMAC-SHA256-32", true, GetHMACParameters(32, keymint::Digest::SHA_2_256)}, + {"HMAC-SHA256-64", false, GetHMACParameters(64, keymint::Digest::SHA_2_256)}, + {"HMAC-SHA224-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_224)}, + {"HMAC-SHA384-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_384)}, + {"HMAC-SHA512-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_512)}, }; return std::vector(&test_cases[0], &test_cases[arraysize(test_cases)]); } @@ -243,7 +702,8 @@ int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) { continue; } ++test_count; - if (!TestKey(test_case.name, test_case.required_for_brillo_pts, test_case.parameters)) { + if (!TestKey(test_case.name, test_case.required_for_brillo_pts, + test_case.parameters.vector_data())) { VLOG(1) << "Test failed: " << test_case.name; ++fail_count; } @@ -262,248 +722,274 @@ int ListTestCases() { return 0; } -std::string ReadFile(const std::string& filename) { +std::vector ReadFile(const std::string& filename) { std::string content; base::FilePath path(filename); if (!base::ReadFileToString(path, &content)) { printf("Failed to read file: %s\n", filename.c_str()); exit(1); } - return content; + std::vector buffer(reinterpret_cast(content.data()), + reinterpret_cast(content.data()) + content.size()); + return buffer; } -void WriteFile(const std::string& filename, const std::string& content) { +void WriteFile(const std::string& filename, const std::vector& content) { base::FilePath path(filename); int size = content.size(); - if (base::WriteFile(path, content.data(), size) != size) { + if (base::WriteFile(path, reinterpret_cast(content.data()), size) != size) { printf("Failed to write file: %s\n", filename.c_str()); exit(1); } } -int AddEntropy(const std::string& input, int32_t flags) { - std::unique_ptr keystore = CreateKeystoreInstance(); - int32_t result = keystore->addRandomNumberGeneratorEntropy(input, flags).getErrorCode(); - printf("AddEntropy: %d\n", result); - return result; -} - // Note: auth_bound keys created with this tool will not be usable. -int GenerateKey(const std::string& name, int32_t flags, bool auth_bound) { - std::unique_ptr keystore = CreateKeystoreInstance(); - AuthorizationSetBuilder params; +int GenerateKey(const std::string& name, keymint::SecurityLevel securityLevel, bool auth_bound) { + auto keystore = CreateKeystoreInstance(); + auto sec_level = GetSecurityLevelInterface(keystore, securityLevel); + keymint::AuthorizationSetBuilder params; params.RsaSigningKey(2048, 65537) - .Digest(Digest::SHA_2_224) - .Digest(Digest::SHA_2_256) - .Digest(Digest::SHA_2_384) - .Digest(Digest::SHA_2_512) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN) - .Padding(PaddingMode::RSA_PSS); + .Digest(keymint::Digest::SHA_2_224) + .Digest(keymint::Digest::SHA_2_256) + .Digest(keymint::Digest::SHA_2_384) + .Digest(keymint::Digest::SHA_2_512) + .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN) + .Padding(keymint::PaddingMode::RSA_PSS); if (auth_bound) { // Gatekeeper normally generates the secure user id. // Using zero allows the key to be created, but it will not be usuable. - params.Authorization(TAG_USER_SECURE_ID, 0); + params.Authorization(keymint::TAG_USER_SECURE_ID, 0); } else { - params.Authorization(TAG_NO_AUTH_REQUIRED); + params.Authorization(keymint::TAG_NO_AUTH_REQUIRED); } - AuthorizationSet hardware_enforced_characteristics; - AuthorizationSet software_enforced_characteristics; - auto result = keystore->generateKey(name, params, flags, &hardware_enforced_characteristics, - &software_enforced_characteristics); - printf("GenerateKey: %d\n", result.getErrorCode()); - if (result.isOk()) { - PrintKeyCharacteristics(hardware_enforced_characteristics, - software_enforced_characteristics); + + ks2::KeyMetadata keyMetadata; + + auto rc = + sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */, params.vector_data(), + 0 /* flags */, {} /* entropy */, &keyMetadata); + + if (rc.isOk()) { + std::cerr << "GenerateKey failed: " << rc.getDescription() << std::endl; + return unwrapError(rc); } - return result.getErrorCode(); + std::cout << "GenerateKey: success" << std::endl; + PrintKeyCharacteristics(keyMetadata.authorizations); + return 0; } int GetCharacteristics(const std::string& name) { - std::unique_ptr keystore = CreateKeystoreInstance(); - AuthorizationSet hardware_enforced_characteristics; - AuthorizationSet software_enforced_characteristics; - auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics, - &software_enforced_characteristics); - printf("GetCharacteristics: %d\n", result.getErrorCode()); - if (result.isOk()) { - PrintKeyCharacteristics(hardware_enforced_characteristics, - software_enforced_characteristics); + auto keystore = CreateKeystoreInstance(); + + ks2::KeyEntryResponse keyEntryResponse; + + auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse); + if (!rc.isOk()) { + std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl; + return unwrapError(rc); } - return result.getErrorCode(); + + std::cout << "GetCharacteristics: success" << std::endl; + PrintKeyCharacteristics(keyEntryResponse.metadata.authorizations); + return 0; } int ExportKey(const std::string& name) { - std::unique_ptr keystore = CreateKeystoreInstance(); - std::string data; - int32_t result = keystore->exportKey(KeyFormat::X509, name, &data).getErrorCode(); - printf("ExportKey: %d (%zu)\n", result, data.size()); - return result; + auto keystore = CreateKeystoreInstance(); + + ks2::KeyEntryResponse keyEntryResponse; + + auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse); + if (!rc.isOk()) { + std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + + if (auto cert = keyEntryResponse.metadata.certificate) { + std::cout << "ExportKey: Got certificate of length (" << cert->size() << ")" << std::endl; + } else { + std::cout << "ExportKey: Key entry does not have a public component.\n"; + std::cout << "Possibly a symmetric key?" << std::endl; + } + return 0; } int DeleteKey(const std::string& name) { - std::unique_ptr keystore = CreateKeystoreInstance(); - int32_t result = keystore->deleteKey(name).getErrorCode(); - printf("DeleteKey: %d\n", result); - return result; -} + auto keystore = CreateKeystoreInstance(); -int DeleteAllKeys() { - std::unique_ptr keystore = CreateKeystoreInstance(); - int32_t result = keystore->deleteAllKeys().getErrorCode(); - printf("DeleteAllKeys: %d\n", result); - return result; + auto rc = keystore->deleteKey(keyDescriptor(name)); + if (!rc.isOk()) { + std::cerr << "Failed to delete key: " << rc.getDescription(); + return unwrapError(rc); + } + std::cout << "Successfully deleted key." << std::endl; + return 0; } int DoesKeyExist(const std::string& name) { - std::unique_ptr keystore = CreateKeystoreInstance(); - printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no"); + auto keystore = CreateKeystoreInstance(); + ks2::KeyEntryResponse keyEntryResponse; + + bool keyExists = true; + auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse); + if (!rc.isOk()) { + auto responseCode = unwrapError(rc); + if (ks2::ResponseCode(responseCode) == ks2::ResponseCode::KEY_NOT_FOUND) { + keyExists = false; + } else { + std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl; + return unwrapError(rc); + } + } + std::cout << "DoesKeyExists: " << (keyExists ? "yes" : "no") << std::endl; return 0; } -int List(const std::string& prefix) { - std::unique_ptr keystore = CreateKeystoreInstance(); - std::vector key_list; - if (!keystore->listKeys(prefix, &key_list)) { - printf("ListKeys failed.\n"); - return 1; +int List() { + auto keystore = CreateKeystoreInstance(); + std::vector key_list; + auto rc = keystore->listEntries(ks2::Domain::APP, -1 /* nspace ignored */, &key_list); + if (!rc.isOk()) { + std::cerr << "ListKeys failed: " << rc.getDescription() << std::endl; + return unwrapError(rc); } - printf("Keys:\n"); - for (const auto& key_name : key_list) { - printf(" %s\n", key_name.c_str()); + std::cout << "Keys:\n"; + for (const auto& key : key_list) { + std::cout << " " + << (key.alias ? *key.alias : "Whoopsi - no alias, this should not happen.") + << std::endl; } return 0; } -int ListAppsWithKeys() { +int SignAndVerify(const std::string& name) { + auto keystore = CreateKeystoreInstance(); + auto sign_params = keymint::AuthorizationSetBuilder() + .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::SIGN) + .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN) + .Digest(keymint::Digest::SHA_2_256); - sp sm = android::defaultServiceManager(); - sp binder = sm->getService(String16("android.security.keystore")); - sp service = android::interface_cast(binder); - if (service == nullptr) { - fprintf(stderr, "Error connecting to keystore service.\n"); - return 1; + keymint::AuthorizationSet output_params; + + ks2::KeyEntryResponse keyEntryResponse; + + auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse); + if (!rc.isOk()) { + std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl; + return unwrapError(rc); } - int32_t aidl_return; - ::std::vector<::std::string> uids; - android::binder::Status status = service->listUidsOfAuthBoundKeys(&uids, &aidl_return); - if (!status.isOk()) { - fprintf(stderr, "Requesting uids of auth bound keys failed with error %s.\n", - status.toString8().c_str()); - return 1; + + ks2::CreateOperationResponse operationResponse; + + rc = keyEntryResponse.iSecurityLevel->createOperation(keyEntryResponse.metadata.key, + sign_params.vector_data(), + false /* forced */, &operationResponse); + if (!rc.isOk()) { + std::cerr << "Failed to create operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); } - if (!KeyStoreNativeReturnCode(aidl_return).isOk()) { - fprintf(stderr, "Requesting uids of auth bound keys failed with code %d.\n", aidl_return); - return 1; + + const std::vector data_to_sign{0x64, 0x61, 0x74, 0x61, 0x5f, 0x74, + 0x6f, 0x5f, 0x73, 0x69, 0x67, 0x6e}; + std::optional> output_data; + rc = operationResponse.iOperation->finish(data_to_sign, {}, &output_data); + if (!rc.isOk()) { + std::cerr << "Failed to finalize operation: " << rc.getDescription() << std::endl; + return unwrapError(rc); } - printf("Apps with auth bound keys:\n"); - for (auto i = uids.begin(); i != uids.end(); ++i) { - printf("%s\n", i->c_str()); + + if (!output_data) { + std::cerr << "Odd signing succeeded but no signature was returned." << std::endl; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); } - return 0; -} + auto signature = std::move(*output_data); -int SignAndVerify(const std::string& name) { - std::unique_ptr keystore = CreateKeystoreInstance(); - AuthorizationSetBuilder sign_params; - sign_params.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN); - sign_params.Digest(Digest::SHA_2_256); - AuthorizationSet output_params; - uint64_t handle; - auto result = - keystore->beginOperation(KeyPurpose::SIGN, name, sign_params, &output_params, &handle); - if (!result.isOk()) { - printf("Sign: BeginOperation failed: %d\n", result.getErrorCode()); - return result.getErrorCode(); - } - AuthorizationSet empty_params; - std::string output_data; - result = keystore->finishOperation(handle, empty_params, "data_to_sign", - std::string() /*signature_to_verify*/, &output_params, - &output_data); - if (!result.isOk()) { - printf("Sign: FinishOperation failed: %d\n", result.getErrorCode()); - return result.getErrorCode(); - } - printf("Sign: %zu bytes.\n", output_data.size()); - // We have a signature, now verify it. - std::string signature_to_verify = output_data; - output_data.clear(); - result = - keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, &handle); - result = keystore->finishOperation(handle, empty_params, "data_to_sign", signature_to_verify, - &output_params, &output_data); - if (result == ErrorCode::VERIFICATION_FAILED) { - printf("Verify: Failed to verify signature.\n"); - return result.getErrorCode(); - } - if (!result.isOk()) { - printf("Verify: FinishOperation failed: %d\n", result.getErrorCode()); - return result.getErrorCode(); - } - printf("Verify: OK\n"); + std::cout << "Sign: " << signature.size() << " bytes." << std::endl; + + if (auto cert = keyEntryResponse.metadata.certificate) { + const uint8_t* p = cert->data(); + bssl::UniquePtr decoded_cert(d2i_X509(nullptr, &p, (long)cert->size())); + bssl::UniquePtr decoded_pkey(X509_get_pubkey(decoded_cert.get())); + bssl::UniquePtr ctx(EVP_MD_CTX_new()); + if (!ctx) { + std::cerr << "Failed to created EVP_MD context. << std::endl"; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + + if (!EVP_DigestVerifyInit(ctx.get(), nullptr, EVP_sha256(), nullptr, decoded_pkey.get()) || + !EVP_DigestVerifyUpdate(ctx.get(), data_to_sign.data(), data_to_sign.size()) || + EVP_DigestVerifyFinal(ctx.get(), signature.data(), signature.size()) != 1) { + std::cerr << "Failed to verify signature." << std::endl; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + } else { + std::cerr << "No public key to check signature against." << std::endl; + return static_cast(ks2::ResponseCode::SYSTEM_ERROR); + } + + std::cout << "Verify: OK" << std::endl; return 0; } int Encrypt(const std::string& key_name, const std::string& input_filename, - const std::string& output_filename, int32_t flags) { - std::unique_ptr keystore = CreateKeystoreInstance(); - std::string input = ReadFile(input_filename); - std::string output; - if (!keystore->encryptWithAuthentication(key_name, input, flags, &output)) { - printf("EncryptWithAuthentication failed.\n"); - return 1; + const std::string& output_filename, keymint::SecurityLevel securityLevel) { + auto input = ReadFile(input_filename); + auto result = encryptWithAuthentication(key_name, input, securityLevel); + if (auto error = std::get_if(&result)) { + std::cerr << "EncryptWithAuthentication failed." << std::endl; + return *error; } - WriteFile(output_filename, output); + WriteFile(output_filename, std::get>(result)); return 0; } int Decrypt(const std::string& key_name, const std::string& input_filename, const std::string& output_filename) { - std::unique_ptr keystore = CreateKeystoreInstance(); - std::string input = ReadFile(input_filename); - std::string output; - if (!keystore->decryptWithAuthentication(key_name, input, &output)) { - printf("DecryptWithAuthentication failed.\n"); - return 1; + auto input = ReadFile(input_filename); + auto result = decryptWithAuthentication(key_name, input); + if (auto error = std::get_if(&result)) { + std::cerr << "DecryptWithAuthentication failed." << std::endl; + return *error; } - WriteFile(output_filename, output); + WriteFile(output_filename, std::get>(result)); return 0; } -uint32_t securityLevelOption2Flags(const CommandLine& cmd) { +keymint::SecurityLevel securityLevelOption2SecurlityLevel(const CommandLine& cmd) { if (cmd.HasSwitch("seclevel")) { auto str = cmd.GetSwitchValueASCII("seclevel"); if (str == "strongbox") { - return KEYSTORE_FLAG_STRONGBOX; - } else if (str == "software") { - return KEYSTORE_FLAG_FALLBACK; + return keymint::SecurityLevel::STRONGBOX; + } else if (str == "tee") { + return keymint::SecurityLevel::TRUSTED_ENVIRONMENT; } + std::cerr << "Unknown Security level: " << str << std::endl; + std::cerr << "Supported security levels: \"strongbox\" or \"tee\" (default)" << std::endl; } - return KEYSTORE_FLAG_NONE; + return keymint::SecurityLevel::TRUSTED_ENVIRONMENT; } class ConfirmationListener - : public android::security::BnConfirmationPromptCallback, - public std::promise>> { + : public apc::BnConfirmationCallback, + public std::promise>>> { public: ConfirmationListener() {} - virtual ::android::binder::Status - onConfirmationPromptCompleted(int32_t result, - const ::std::vector& dataThatWasConfirmed) override { - this->set_value({static_cast(result), dataThatWasConfirmed}); - return ::android::binder::Status::ok(); - } + virtual ::ndk::ScopedAStatus + onCompleted(::aidl::android::security::apc::ResponseCode result, + const std::optional>& dataConfirmed) override { + this->set_value({result, dataConfirmed}); + return ::ndk::ScopedAStatus::ok(); + }; }; int Confirmation(const std::string& promptText, const std::string& extraDataHex, const std::string& locale, const std::string& uiOptionsStr, const std::string& cancelAfter) { - sp sm = android::defaultServiceManager(); - sp binder = sm->getService(String16("android.security.keystore")); - sp service = android::interface_cast(binder); - if (service == nullptr) { - printf("error: could not connect to keystore service.\n"); + ::ndk::SpAIBinder apcBinder(AServiceManager_getService("android.security.apc")); + auto apcService = apc::IProtectedConfirmation::fromBinder(apcBinder); + if (!apcService) { + std::cerr << "Error: could not connect to apc service." << std::endl; return 1; } @@ -537,44 +1023,28 @@ int Confirmation(const std::string& promptText, const std::string& extraDataHex, return 1; } - String16 promptText16(promptText.data(), promptText.size()); - String16 locale16(locale.data(), locale.size()); - - sp listener = new ConfirmationListener(); + auto listener = std::make_shared(); auto future = listener->get_future(); - int32_t aidl_return; - android::binder::Status status = service->presentConfirmationPrompt( - listener, promptText16, extraData, locale16, uiOptionsAsFlags, &aidl_return); - if (!status.isOk()) { - printf("Presenting confirmation prompt failed with binder status '%s'.\n", - status.toString8().c_str()); - return 1; - } - ConfirmationResponseCode responseCode = static_cast(aidl_return); - if (responseCode != ConfirmationResponseCode::OK) { - printf("Presenting confirmation prompt failed with response code %d.\n", responseCode); + auto rc = apcService->presentPrompt(listener, promptText, extraData, locale, uiOptionsAsFlags); + + if (!rc.isOk()) { + std::cerr << "Presenting confirmation prompt failed: " << rc.getDescription() << std::endl; return 1; } - printf("Waiting for prompt to complete - use Ctrl+C to abort...\n"); + + std::cerr << "Waiting for prompt to complete - use Ctrl+C to abort..." << std::endl; if (cancelAfterValue > 0.0) { - printf("Sleeping %.1f seconds before canceling prompt...\n", cancelAfterValue); + std::cerr << "Sleeping " << cancelAfterValue << " seconds before canceling prompt..." + << std::endl; auto fstatus = future.wait_for(std::chrono::milliseconds(uint64_t(cancelAfterValue * 1000))); if (fstatus == std::future_status::timeout) { - status = service->cancelConfirmationPrompt(listener, &aidl_return); - if (!status.isOk()) { - printf("Canceling confirmation prompt failed with binder status '%s'.\n", - status.toString8().c_str()); - return 1; - } - responseCode = static_cast(aidl_return); - if (responseCode == ConfirmationResponseCode::Ignored) { - // The confirmation was completed by the user so take the response - } else if (responseCode != ConfirmationResponseCode::OK) { - printf("Canceling confirmation prompt failed with response code %d.\n", - responseCode); + rc = apcService->cancelPrompt(listener); + if (!rc.isOk()) { + std::cerr << "Canceling confirmation prompt failed: " << rc.getDescription() + << std::endl; return 1; } } @@ -582,27 +1052,28 @@ int Confirmation(const std::string& promptText, const std::string& extraDataHex, future.wait(); - auto [rc, dataThatWasConfirmed] = future.get(); + auto [responseCode, dataThatWasConfirmed] = future.get(); - printf("Confirmation prompt completed\n" - "responseCode = %d\n", - rc); - printf("dataThatWasConfirmed[%zd] = {", dataThatWasConfirmed.size()); + std::cerr << "Confirmation prompt completed\n" + << "responseCode = " << toString(responseCode); size_t newLineCountDown = 16; bool hasPrinted = false; - for (uint8_t element : dataThatWasConfirmed) { - if (hasPrinted) { - printf(", "); - } - if (newLineCountDown == 0) { - printf("\n "); - newLineCountDown = 32; + if (dataThatWasConfirmed) { + std::cerr << "dataThatWasConfirmed[" << dataThatWasConfirmed->size() << "] = {"; + for (uint8_t element : *dataThatWasConfirmed) { + if (hasPrinted) { + std::cerr << ", "; + } + if (newLineCountDown == 0) { + std::cerr << "\n "; + newLineCountDown = 32; + } + std::cerr << "0x" << std::hex << std::setw(2) << std::setfill('0') << (unsigned)element; + + hasPrinted = true; } - printf("0x%02x", element); - hasPrinted = true; } - printf("}\n"); - + std::cerr << std::endl; return 0; } @@ -613,7 +1084,7 @@ int main(int argc, char** argv) { CommandLine* command_line = CommandLine::ForCurrentProcess(); CommandLine::StringVector args = command_line->GetArgs(); - android::ProcessState::self()->startThreadPool(); + ABinderProcess_startThreadPool(); if (args.empty()) { PrintUsageAndExit(); @@ -623,12 +1094,9 @@ int main(int argc, char** argv) { command_line->HasSwitch("test_for_0_3")); } else if (args[0] == "list-brillo-tests") { return ListTestCases(); - } else if (args[0] == "add-entropy") { - return AddEntropy(command_line->GetSwitchValueASCII("input"), - securityLevelOption2Flags(*command_line)); } else if (args[0] == "generate") { return GenerateKey(command_line->GetSwitchValueASCII("name"), - securityLevelOption2Flags(*command_line), + securityLevelOption2SecurlityLevel(*command_line), command_line->HasSwitch("auth_bound")); } else if (args[0] == "get-chars") { return GetCharacteristics(command_line->GetSwitchValueASCII("name")); @@ -636,20 +1104,17 @@ int main(int argc, char** argv) { return ExportKey(command_line->GetSwitchValueASCII("name")); } else if (args[0] == "delete") { return DeleteKey(command_line->GetSwitchValueASCII("name")); - } else if (args[0] == "delete-all") { - return DeleteAllKeys(); } else if (args[0] == "exists") { return DoesKeyExist(command_line->GetSwitchValueASCII("name")); } else if (args[0] == "list") { - return List(command_line->GetSwitchValueASCII("prefix")); - } else if (args[0] == "list-apps-with-keys") { - return ListAppsWithKeys(); + return List(); } else if (args[0] == "sign-verify") { return SignAndVerify(command_line->GetSwitchValueASCII("name")); } else if (args[0] == "encrypt") { - return Encrypt( - command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"), - command_line->GetSwitchValueASCII("out"), securityLevelOption2Flags(*command_line)); + return Encrypt(command_line->GetSwitchValueASCII("name"), + command_line->GetSwitchValueASCII("in"), + command_line->GetSwitchValueASCII("out"), + securityLevelOption2SecurlityLevel(*command_line)); } else if (args[0] == "decrypt") { return Decrypt(command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"), diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp deleted file mode 100644 index f8886839..00000000 --- a/keystore/keystore_client_impl.cpp +++ /dev/null @@ -1,629 +0,0 @@ -// Copyright 2015 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. - -#define LOG_TAG "keystore_client" - -#include "keystore/keystore_client_impl.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "keystore_client.pb.h" - -namespace { - -// Use the UID of the current process. -const int kDefaultUID = -1; -const char kEncryptSuffix[] = "_ENC"; -const char kAuthenticateSuffix[] = "_AUTH"; -constexpr uint32_t kAESKeySize = 256; // bits -constexpr uint32_t kHMACKeySize = 256; // bits -constexpr uint32_t kHMACOutputSize = 256; // bits - -using android::String16; -using android::security::keymaster::ExportResult; -using android::security::keymaster::OperationResult; -using android::security::keystore::KeystoreResponse; -using keystore::AuthorizationSet; -using keystore::AuthorizationSetBuilder; -using keystore::KeyCharacteristics; -using keystore::KeyStoreServiceReturnCode; -} // namespace - -namespace keystore { - -KeystoreClientImpl::KeystoreClientImpl() { - service_manager_ = android::defaultServiceManager(); - keystore_binder_ = service_manager_->getService(String16("android.security.keystore")); - keystore_ = - android::interface_cast(keystore_binder_); -} - -bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name, - const std::string& data, int32_t flags, - std::string* encrypted_data) { - // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random - // IV. The authentication algorithm is HMAC-SHA256 and is computed over the - // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM - // because hardware support for GCM is not mandatory for all Brillo devices. - std::string encryption_key_name = key_name + kEncryptSuffix; - if (!createOrVerifyEncryptionKey(encryption_key_name, flags)) { - return false; - } - std::string authentication_key_name = key_name + kAuthenticateSuffix; - if (!createOrVerifyAuthenticationKey(authentication_key_name, flags)) { - return false; - } - AuthorizationSetBuilder encrypt_params; - encrypt_params.Padding(PaddingMode::PKCS7); - encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::CBC); - AuthorizationSet output_params; - std::string raw_encrypted_data; - if (!oneShotOperation(KeyPurpose::ENCRYPT, encryption_key_name, encrypt_params, data, - std::string(), /* signature_to_verify */ - &output_params, &raw_encrypted_data)) { - ALOGE("Encrypt: AES operation failed."); - return false; - } - auto init_vector_blob = output_params.GetTagValue(TAG_NONCE); - if (!init_vector_blob.isOk()) { - ALOGE("Encrypt: Missing initialization vector."); - return false; - } - std::string init_vector = hidlVec2String(init_vector_blob.value()); - - AuthorizationSetBuilder authenticate_params; - authenticate_params.Digest(Digest::SHA_2_256); - authenticate_params.Authorization(TAG_MAC_LENGTH, kHMACOutputSize); - std::string raw_authentication_data; - if (!oneShotOperation(KeyPurpose::SIGN, authentication_key_name, authenticate_params, - init_vector + raw_encrypted_data, std::string(), /* signature_to_verify */ - &output_params, &raw_authentication_data)) { - ALOGE("Encrypt: HMAC operation failed."); - return false; - } - EncryptedData protobuf; - protobuf.set_init_vector(init_vector); - protobuf.set_authentication_data(raw_authentication_data); - protobuf.set_encrypted_data(raw_encrypted_data); - if (!protobuf.SerializeToString(encrypted_data)) { - ALOGE("Encrypt: Failed to serialize EncryptedData protobuf."); - return false; - } - return true; -} - -bool KeystoreClientImpl::decryptWithAuthentication(const std::string& key_name, - const std::string& encrypted_data, - std::string* data) { - EncryptedData protobuf; - if (!protobuf.ParseFromString(encrypted_data)) { - ALOGE("Decrypt: Failed to parse EncryptedData protobuf."); - } - // Verify authentication before attempting decryption. - std::string authentication_key_name = key_name + kAuthenticateSuffix; - AuthorizationSetBuilder authenticate_params; - authenticate_params.Digest(Digest::SHA_2_256); - AuthorizationSet output_params; - std::string output_data; - if (!oneShotOperation(KeyPurpose::VERIFY, authentication_key_name, authenticate_params, - protobuf.init_vector() + protobuf.encrypted_data(), - protobuf.authentication_data(), &output_params, &output_data)) { - ALOGE("Decrypt: HMAC operation failed."); - return false; - } - std::string encryption_key_name = key_name + kEncryptSuffix; - AuthorizationSetBuilder encrypt_params; - encrypt_params.Padding(PaddingMode::PKCS7); - encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::CBC); - encrypt_params.Authorization(TAG_NONCE, protobuf.init_vector().data(), - protobuf.init_vector().size()); - if (!oneShotOperation(KeyPurpose::DECRYPT, encryption_key_name, encrypt_params, - protobuf.encrypted_data(), std::string(), /* signature_to_verify */ - &output_params, data)) { - ALOGE("Decrypt: AES operation failed."); - return false; - } - return true; -} - -bool KeystoreClientImpl::oneShotOperation(KeyPurpose purpose, const std::string& key_name, - const AuthorizationSet& input_parameters, - const std::string& input_data, - const std::string& signature_to_verify, - AuthorizationSet* output_parameters, - std::string* output_data) { - uint64_t handle; - auto result = beginOperation(purpose, key_name, input_parameters, output_parameters, &handle); - if (!result.isOk()) { - ALOGE("BeginOperation failed: %d", result.getErrorCode()); - return false; - } - AuthorizationSet empty_params; - AuthorizationSet ignored_params; - result = finishOperation(handle, empty_params, input_data, signature_to_verify, &ignored_params, - output_data); - if (!result.isOk()) { - ALOGE("FinishOperation failed: %d", result.getErrorCode()); - return false; - } - return true; -} - -KeyStoreNativeReturnCode -KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy, int32_t flags) { - int32_t error_code; - - android::sp promise(new KeystoreResponsePromise()); - auto future = promise->get_future(); - - auto binder_result = - keystore_->addRngEntropy(promise, blob2hidlVec(entropy), flags, &error_code); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - - KeyStoreNativeReturnCode rc(error_code); - if (!rc.isOk()) return rc; - - auto result = future.get(); - - return KeyStoreNativeReturnCode(result.response_code()); -} - -KeyStoreNativeReturnCode -KeystoreClientImpl::generateKey(const std::string& key_name, const AuthorizationSet& key_parameters, - int32_t flags, AuthorizationSet* hardware_enforced_characteristics, - AuthorizationSet* software_enforced_characteristics) { - String16 key_name16(key_name.data(), key_name.size()); - int32_t error_code; - android::sp promise(new KeyCharacteristicsPromise); - auto future = promise->get_future(); - auto binder_result = keystore_->generateKey( - promise, key_name16, - ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()), - hidl_vec() /* entropy */, kDefaultUID, flags, &error_code); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - - KeyStoreNativeReturnCode rc(error_code); - if (!rc.isOk()) return rc; - - auto [km_response, characteristics] = future.get(); - - /* assignment (hidl_vec -> AuthorizationSet) makes a deep copy. - * There are no references to Parcel memory after that, and ownership of the newly acquired - * memory is with the AuthorizationSet objects. */ - *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters(); - *software_enforced_characteristics = characteristics.softwareEnforced.getParameters(); - return KeyStoreNativeReturnCode(km_response.response_code()); -} - -KeyStoreNativeReturnCode -KeystoreClientImpl::getKeyCharacteristics(const std::string& key_name, - AuthorizationSet* hardware_enforced_characteristics, - AuthorizationSet* software_enforced_characteristics) { - String16 key_name16(key_name.data(), key_name.size()); - int32_t error_code; - android::sp promise(new KeyCharacteristicsPromise); - auto future = promise->get_future(); - auto binder_result = keystore_->getKeyCharacteristics( - promise, key_name16, android::security::keymaster::KeymasterBlob(), - android::security::keymaster::KeymasterBlob(), kDefaultUID, &error_code); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - - KeyStoreNativeReturnCode rc(error_code); - if (!rc.isOk()) return rc; - - auto [km_response, characteristics] = future.get(); - - /* assignment (hidl_vec -> AuthorizationSet) makes a deep copy. - * There are no references to Parcel memory after that, and ownership of the newly acquired - * memory is with the AuthorizationSet objects. */ - *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters(); - *software_enforced_characteristics = characteristics.softwareEnforced.getParameters(); - return KeyStoreNativeReturnCode(km_response.response_code()); -} - -KeyStoreNativeReturnCode -KeystoreClientImpl::importKey(const std::string& key_name, const AuthorizationSet& key_parameters, - KeyFormat key_format, const std::string& key_data, - AuthorizationSet* hardware_enforced_characteristics, - AuthorizationSet* software_enforced_characteristics) { - String16 key_name16(key_name.data(), key_name.size()); - auto hidlKeyData = blob2hidlVec(key_data); - int32_t error_code; - android::sp promise(new KeyCharacteristicsPromise); - auto future = promise->get_future(); - auto binder_result = keystore_->importKey( - promise, key_name16, - ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()), - (int)key_format, hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &error_code); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - - KeyStoreNativeReturnCode rc(error_code); - if (!rc.isOk()) return rc; - - auto [km_response, characteristics] = future.get(); - - /* assignment (hidl_vec -> AuthorizationSet) makes a deep copy. - * There are no references to Parcel memory after that, and ownership of the newly acquired - * memory is with the AuthorizationSet objects. */ - *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters(); - *software_enforced_characteristics = characteristics.softwareEnforced.getParameters(); - return KeyStoreNativeReturnCode(km_response.response_code()); -} - -KeyStoreNativeReturnCode KeystoreClientImpl::exportKey(KeyFormat export_format, - const std::string& key_name, - std::string* export_data) { - String16 key_name16(key_name.data(), key_name.size()); - int32_t error_code; - android::sp promise(new KeystoreExportPromise); - auto future = promise->get_future(); - auto binder_result = keystore_->exportKey( - promise, key_name16, (int)export_format, android::security::keymaster::KeymasterBlob(), - android::security::keymaster::KeymasterBlob(), kDefaultUID, &error_code); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - - KeyStoreNativeReturnCode rc(error_code); - if (!rc.isOk()) return rc; - - auto export_result = future.get(); - if (!export_result.resultCode.isOk()) return export_result.resultCode; - - *export_data = hidlVec2String(export_result.exportData); - - return export_result.resultCode; -} - -KeyStoreNativeReturnCode KeystoreClientImpl::deleteKey(const std::string& key_name) { - String16 key_name16(key_name.data(), key_name.size()); - int32_t result; - auto binder_result = keystore_->del(key_name16, kDefaultUID, &result); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - return KeyStoreNativeReturnCode(result); -} - -KeyStoreNativeReturnCode KeystoreClientImpl::deleteAllKeys() { - int32_t result; - auto binder_result = keystore_->clear_uid(kDefaultUID, &result); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - return KeyStoreNativeReturnCode(result); -} - -KeyStoreNativeReturnCode -KeystoreClientImpl::beginOperation(KeyPurpose purpose, const std::string& key_name, - const AuthorizationSet& input_parameters, - AuthorizationSet* output_parameters, uint64_t* handle) { - android::sp token(new android::BBinder); - String16 key_name16(key_name.data(), key_name.size()); - int32_t error_code; - android::sp promise(new OperationResultPromise{}); - auto future = promise->get_future(); - auto binder_result = keystore_->begin( - promise, token, key_name16, (int)purpose, true /*pruneable*/, - android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()), - hidl_vec() /* entropy */, kDefaultUID, &error_code); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - KeyStoreNativeReturnCode rc(error_code); - if (!rc.isOk()) return rc; - - OperationResult result = future.get(); - if (result.resultCode.isOk()) { - *handle = getNextVirtualHandle(); - active_operations_[*handle] = result.token; - if (result.outParams.size()) { - *output_parameters = result.outParams; - } - } - return result.resultCode; -} - -KeyStoreNativeReturnCode -KeystoreClientImpl::updateOperation(uint64_t handle, const AuthorizationSet& input_parameters, - const std::string& input_data, size_t* num_input_bytes_consumed, - AuthorizationSet* output_parameters, std::string* output_data) { - if (active_operations_.count(handle) == 0) { - return ErrorCode::INVALID_OPERATION_HANDLE; - } - auto hidlInputData = blob2hidlVec(input_data); - int32_t error_code; - android::sp promise(new OperationResultPromise{}); - auto future = promise->get_future(); - auto binder_result = keystore_->update( - promise, active_operations_[handle], - android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()), - hidlInputData, &error_code); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - KeyStoreNativeReturnCode rc(error_code); - if (!rc.isOk()) return rc; - - OperationResult result = future.get(); - - if (result.resultCode.isOk()) { - *num_input_bytes_consumed = result.inputConsumed; - if (result.outParams.size()) { - *output_parameters = result.outParams; - } - // TODO verify that append should not be assign - output_data->append(hidlVec2String(result.data)); - } - return result.resultCode; -} - -KeyStoreNativeReturnCode -KeystoreClientImpl::finishOperation(uint64_t handle, const AuthorizationSet& input_parameters, - const std::string& input_data, - const std::string& signature_to_verify, - AuthorizationSet* output_parameters, std::string* output_data) { - if (active_operations_.count(handle) == 0) { - return ErrorCode::INVALID_OPERATION_HANDLE; - } - int32_t error_code; - auto hidlSignature = blob2hidlVec(signature_to_verify); - auto hidlInput = blob2hidlVec(input_data); - android::sp promise(new OperationResultPromise{}); - auto future = promise->get_future(); - auto binder_result = keystore_->finish( - promise, active_operations_[handle], - android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()), - (std::vector)hidlInput, (std::vector)hidlSignature, hidl_vec(), - &error_code); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - KeyStoreNativeReturnCode rc(error_code); - if (!rc.isOk()) return rc; - - OperationResult result = future.get(); - if (result.resultCode.isOk()) { - if (result.outParams.size()) { - *output_parameters = result.outParams; - } - // TODO verify that append should not be assign - output_data->append(hidlVec2String(result.data)); - active_operations_.erase(handle); - } - return result.resultCode; -} - -KeyStoreNativeReturnCode KeystoreClientImpl::abortOperation(uint64_t handle) { - if (active_operations_.count(handle) == 0) { - return ErrorCode::INVALID_OPERATION_HANDLE; - } - int32_t result; - android::sp promise(new KeystoreResponsePromise{}); - auto future = promise->get_future(); - // Current implementation does not return exceptions in android::binder::Status - auto binder_result = keystore_->abort(promise, active_operations_[handle], &result); - if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR; - KeyStoreNativeReturnCode rc(result); - if (!rc.isOk()) return rc; - rc = KeyStoreNativeReturnCode(future.get().response_code()); - if (rc.isOk()) { - active_operations_.erase(handle); - } - return rc; -} - -bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) { - String16 key_name16(key_name.data(), key_name.size()); - int32_t result; - auto binder_result = keystore_->exist(key_name16, kDefaultUID, &result); - if (!binder_result.isOk()) return false; // binder error - return result == static_cast(ResponseCode::NO_ERROR); -} - -bool KeystoreClientImpl::listKeys(const std::string& prefix, - std::vector* key_name_list) { - return listKeysOfUid(prefix, kDefaultUID, key_name_list); -} - -bool KeystoreClientImpl::listKeysOfUid(const std::string& prefix, int uid, - std::vector* key_name_list) { - String16 prefix16(prefix.data(), prefix.size()); - std::vector<::android::String16> matches; - auto binder_result = keystore_->list(prefix16, uid, &matches); - if (!binder_result.isOk()) return false; - - for (const auto& match : matches) { - android::String8 key_name(match); - key_name_list->push_back(prefix + std::string(key_name.string(), key_name.size())); - } - return true; -} - -std::optional> KeystoreClientImpl::getKey(const std::string& alias, int uid) { - String16 alias16(alias.data(), alias.size()); - std::vector output; - auto binder_result = keystore_->get(alias16, uid, &output); - if (!binder_result.isOk()) return std::nullopt; - return output; -} - -uint64_t KeystoreClientImpl::getNextVirtualHandle() { - return next_virtual_handle_++; -} - -bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name, int32_t flags) { - bool key_exists = doesKeyExist(key_name); - if (key_exists) { - bool verified = false; - if (!verifyEncryptionKeyAttributes(key_name, &verified)) { - return false; - } - if (!verified) { - auto result = deleteKey(key_name); - if (!result.isOk()) { - ALOGE("Failed to delete invalid encryption key: %d", result.getErrorCode()); - return false; - } - key_exists = false; - } - } - if (!key_exists) { - AuthorizationSetBuilder key_parameters; - key_parameters.AesEncryptionKey(kAESKeySize) - .Padding(PaddingMode::PKCS7) - .Authorization(TAG_BLOCK_MODE, BlockMode::CBC) - .Authorization(TAG_NO_AUTH_REQUIRED); - AuthorizationSet hardware_enforced_characteristics; - AuthorizationSet software_enforced_characteristics; - auto result = - generateKey(key_name, key_parameters, flags, &hardware_enforced_characteristics, - &software_enforced_characteristics); - if (!result.isOk()) { - ALOGE("Failed to generate encryption key: %d", result.getErrorCode()); - return false; - } - if (hardware_enforced_characteristics.size() == 0) { - ALOGW("WARNING: Encryption key is not hardware-backed."); - } - } - return true; -} - -bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name, - int32_t flags) { - bool key_exists = doesKeyExist(key_name); - if (key_exists) { - bool verified = false; - if (!verifyAuthenticationKeyAttributes(key_name, &verified)) { - return false; - } - if (!verified) { - auto result = deleteKey(key_name); - if (!result.isOk()) { - ALOGE("Failed to delete invalid authentication key: %d", result.getErrorCode()); - return false; - } - key_exists = false; - } - } - if (!key_exists) { - AuthorizationSetBuilder key_parameters; - key_parameters.HmacKey(kHMACKeySize) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_MIN_MAC_LENGTH, kHMACOutputSize) - .Authorization(TAG_NO_AUTH_REQUIRED); - AuthorizationSet hardware_enforced_characteristics; - AuthorizationSet software_enforced_characteristics; - auto result = - generateKey(key_name, key_parameters, flags, &hardware_enforced_characteristics, - &software_enforced_characteristics); - if (!result.isOk()) { - ALOGE("Failed to generate authentication key: %d", result.getErrorCode()); - return false; - } - if (hardware_enforced_characteristics.size() == 0) { - ALOGW("WARNING: Authentication key is not hardware-backed."); - } - } - return true; -} - -bool KeystoreClientImpl::verifyEncryptionKeyAttributes(const std::string& key_name, - bool* verified) { - AuthorizationSet hardware_enforced_characteristics; - AuthorizationSet software_enforced_characteristics; - auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics, - &software_enforced_characteristics); - if (!result.isOk()) { - ALOGE("Failed to query encryption key: %d", result.getErrorCode()); - return false; - } - *verified = true; - auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM), - software_enforced_characteristics.GetTagValue(TAG_ALGORITHM)); - if (!algorithm.isOk() || algorithm.value() != Algorithm::AES) { - ALOGW("Found encryption key with invalid algorithm."); - *verified = false; - } - auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE), - software_enforced_characteristics.GetTagValue(TAG_KEY_SIZE)); - if (!key_size.isOk() || key_size.value() != kAESKeySize) { - ALOGW("Found encryption key with invalid size."); - *verified = false; - } - auto block_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE), - software_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE)); - if (!block_mode.isOk() || block_mode.value() != BlockMode::CBC) { - ALOGW("Found encryption key with invalid block mode."); - *verified = false; - } - auto padding_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_PADDING), - software_enforced_characteristics.GetTagValue(TAG_PADDING)); - if (!padding_mode.isOk() || padding_mode.value() != PaddingMode::PKCS7) { - ALOGW("Found encryption key with invalid padding mode."); - *verified = false; - } - if (hardware_enforced_characteristics.size() == 0) { - ALOGW("WARNING: Encryption key is not hardware-backed."); - } - return true; -} - -bool KeystoreClientImpl::verifyAuthenticationKeyAttributes(const std::string& key_name, - bool* verified) { - AuthorizationSet hardware_enforced_characteristics; - AuthorizationSet software_enforced_characteristics; - auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics, - &software_enforced_characteristics); - if (!result.isOk()) { - ALOGE("Failed to query authentication key: %d", result.getErrorCode()); - return false; - } - *verified = true; - auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM), - software_enforced_characteristics.GetTagValue(TAG_ALGORITHM)); - if (!algorithm.isOk() || algorithm.value() != Algorithm::HMAC) { - ALOGW("Found authentication key with invalid algorithm."); - *verified = false; - } - auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE), - software_enforced_characteristics.GetTagValue(TAG_KEY_SIZE)); - if (!key_size.isOk() || key_size.value() != kHMACKeySize) { - ALOGW("Found authentication key with invalid size."); - *verified = false; - } - auto mac_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH), - software_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH)); - if (!mac_size.isOk() || mac_size.value() != kHMACOutputSize) { - ALOGW("Found authentication key with invalid minimum mac size."); - *verified = false; - } - auto digest = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_DIGEST), - software_enforced_characteristics.GetTagValue(TAG_DIGEST)); - if (!digest.isOk() || digest.value() != Digest::SHA_2_256) { - ALOGW("Found authentication key with invalid digest list."); - *verified = false; - } - if (hardware_enforced_characteristics.size() == 0) { - ALOGW("WARNING: Authentication key is not hardware-backed."); - } - return true; -} - -} // namespace keystore diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp deleted file mode 100644 index 02c2139a..00000000 --- a/keystore/keystore_main.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -#define LOG_TAG "keystore" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "KeyStore.h" -#include "key_store_service.h" -#include "legacy_keymaster_device_wrapper.h" -#include "permissions.h" - -/* KeyStore is a secured storage for key-value pairs. In this implementation, - * each file stores one key-value pair. Keys are encoded in file names, and - * values are encrypted with checksums. The encryption key is protected by a - * user-defined password. To keep things simple, buffers are always larger than - * the maximum space we needed, so boundary checks on buffers are omitted. */ - -using ::android::sp; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::keymaster::V4_0::ErrorCode; -using ::android::hardware::keymaster::V4_0::HmacSharingParameters; -using ::android::hardware::keymaster::V4_0::SecurityLevel; -using ::android::hidl::manager::V1_2::IServiceManager; - -using ::keystore::keymaster::support::Keymaster; -using ::keystore::keymaster::support::Keymaster3; -using ::keystore::keymaster::support::Keymaster4; - -using keystore::KeymasterDevices; - -template -KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) { - KeymasterDevices result; - serviceManager->listManifestByInterface( - Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec& names) { - auto try_get_device = [&](const auto& name, bool fail_silent) { - auto device = Wrapper::WrappedIKeymasterDevice::getService(name); - if (fail_silent && !device) return; - CHECK(device) << "Failed to get service for \"" - << Wrapper::WrappedIKeymasterDevice::descriptor - << "\" with interface name \"" << name << "\""; - - sp kmDevice(new Wrapper(device, name)); - auto halVersion = kmDevice->halVersion(); - SecurityLevel securityLevel = halVersion.securityLevel; - LOG(INFO) << "found " << Wrapper::WrappedIKeymasterDevice::descriptor - << " with interface name " << name << " and seclevel " - << toString(securityLevel); - CHECK(static_cast(securityLevel) < result.size()) - << "Security level of \"" << Wrapper::WrappedIKeymasterDevice::descriptor - << "\" with interface name \"" << name << "\" out of range"; - auto& deviceSlot = result[securityLevel]; - if (deviceSlot) { - if (!fail_silent) { - LOG(WARNING) << "Implementation of \"" - << Wrapper::WrappedIKeymasterDevice::descriptor - << "\" with interface name \"" << name - << "\" and security level: " << toString(securityLevel) - << " Masked by other implementation of Keymaster"; - } - } else { - deviceSlot = kmDevice; - } - }; - bool has_default = false; - for (auto& n : names) { - try_get_device(n, false); - if (n == "default") has_default = true; - } - // Make sure that we always check the default device. If we enumerate only what is - // known to hwservicemanager, we miss a possible passthrough HAL. - if (!has_default) { - try_get_device("default", true /* fail_silent */); - } - }); - return result; -} - -KeymasterDevices initializeKeymasters() { - auto serviceManager = IServiceManager::getService(); - CHECK(serviceManager.get()) << "Failed to get ServiceManager"; - auto result = enumerateKeymasterDevices(serviceManager.get()); - auto softKeymaster = result[SecurityLevel::SOFTWARE]; - if (!result[SecurityLevel::TRUSTED_ENVIRONMENT]) { - result = enumerateKeymasterDevices(serviceManager.get()); - } - if (softKeymaster) result[SecurityLevel::SOFTWARE] = softKeymaster; - if (result[SecurityLevel::SOFTWARE] && !result[SecurityLevel::TRUSTED_ENVIRONMENT]) { - LOG(WARNING) << "No secure Keymaster implementation found, but device offers insecure" - " Keymaster HAL. Using as default."; - result[SecurityLevel::TRUSTED_ENVIRONMENT] = result[SecurityLevel::SOFTWARE]; - result[SecurityLevel::SOFTWARE] = nullptr; - } - if (!result[SecurityLevel::SOFTWARE]) { - auto fbdev = android::keystore::makeSoftwareKeymasterDevice(); - CHECK(fbdev.get()) << "Unable to create Software Keymaster Device"; - result[SecurityLevel::SOFTWARE] = new Keymaster3(fbdev, "Software"); - } - return result; -} - -int main(int argc, char* argv[]) { - using android::hardware::hidl_string; - CHECK(argc >= 2) << "A directory must be specified!"; - CHECK(chdir(argv[1]) != -1) << "chdir: " << argv[1] << ": " << strerror(errno); - - auto kmDevices = initializeKeymasters(); - - CHECK(kmDevices[SecurityLevel::SOFTWARE]) << "Missing software Keymaster device"; - CHECK(kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]) - << "Error no viable keymaster device found"; - - CHECK(configure_selinux() != -1) << "Failed to configure SELinux."; - - auto halVersion = kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]->halVersion(); - - // If the hardware is keymaster 2.0 or higher we will not allow the fallback device for import - // or generation of keys. The fallback device is only used for legacy keys present on the - // device. - SecurityLevel minimalAllowedSecurityLevelForNewKeys = - halVersion.majorVersion >= 2 ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE; - - android::sp keyStore( - new keystore::KeyStore(kmDevices, minimalAllowedSecurityLevelForNewKeys)); - keyStore->initialize(); - android::sp sm = android::defaultServiceManager(); - android::sp service = new keystore::KeyStoreService(keyStore); - service->setRequestingSid(true); - android::status_t ret = sm->addService(android::String16("android.security.keystore"), service); - CHECK(ret == android::OK) << "Couldn't register binder service!"; - - /* - * This thread is just going to process Binder transactions. - */ - android::IPCThreadState::self()->joinThreadPool(); - return 1; -} diff --git a/keystore/legacy_keymaster_device_wrapper.cpp b/keystore/legacy_keymaster_device_wrapper.cpp deleted file mode 100644 index 052f3940..00000000 --- a/keystore/legacy_keymaster_device_wrapper.cpp +++ /dev/null @@ -1,547 +0,0 @@ -/* - ** - ** Copyright 2016, 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. - */ - -#define LOG_TAG "android.hardware.keymaster@3.0-impl" - -#include "legacy_keymaster_device_wrapper.h" - -#include - -#include -#include -#include -#include - -namespace android { -namespace keystore { - -using ::keymaster::SoftKeymasterDevice; - -LegacyKeymasterDeviceWrapper::LegacyKeymasterDeviceWrapper(keymaster2_device_t* dev) - : keymaster_device_(dev) {} - -LegacyKeymasterDeviceWrapper::~LegacyKeymasterDeviceWrapper() { - if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common); -} - -static inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) { - return keymaster_tag_get_type(tag); -} - -/** - * legacy_enum_conversion converts enums from hidl to keymaster and back. Currently, this is just a - * cast to make the compiler happy. One of two thigs should happen though: - * TODO The keymaster enums should become aliases for the hidl generated enums so that we have a - * single point of truth. Then this cast function can go away. - */ -inline static keymaster_tag_t legacy_enum_conversion(const Tag value) { - return keymaster_tag_t(value); -} -inline static Tag legacy_enum_conversion(const keymaster_tag_t value) { - return Tag(value); -} -inline static keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) { - return keymaster_purpose_t(value); -} -inline static keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) { - return keymaster_key_format_t(value); -} -inline static ErrorCode legacy_enum_conversion(const keymaster_error_t value) { - return ErrorCode(value); -} - -class KmParamSet : public keymaster_key_param_set_t { - public: - explicit KmParamSet(const hidl_vec& keyParams) { - params = new keymaster_key_param_t[keyParams.size()]; - length = keyParams.size(); - for (size_t i = 0; i < keyParams.size(); ++i) { - auto tag = legacy_enum_conversion(keyParams[i].tag); - switch (typeFromTag(tag)) { - case KM_ENUM: - case KM_ENUM_REP: - params[i] = keymaster_param_enum(tag, keyParams[i].f.integer); - break; - case KM_UINT: - case KM_UINT_REP: - params[i] = keymaster_param_int(tag, keyParams[i].f.integer); - break; - case KM_ULONG: - case KM_ULONG_REP: - params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger); - break; - case KM_DATE: - params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime); - break; - case KM_BOOL: - if (keyParams[i].f.boolValue) - params[i] = keymaster_param_bool(tag); - else - params[i].tag = KM_TAG_INVALID; - break; - case KM_BIGNUM: - case KM_BYTES: - params[i] = - keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size()); - break; - case KM_INVALID: - default: - params[i].tag = KM_TAG_INVALID; - /* just skip */ - break; - } - } - } - KmParamSet(KmParamSet&& other) noexcept - : keymaster_key_param_set_t{other.params, other.length} { - other.length = 0; - other.params = nullptr; - } - KmParamSet(const KmParamSet&) = delete; - ~KmParamSet() { delete[] params; } -}; - -inline static KmParamSet hidlParams2KmParamSet(const hidl_vec& params) { - return KmParamSet(params); -} - -inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec& blob) { - /* hidl unmarshals funny pointers if the the blob is empty */ - if (blob.size()) return {&blob[0], blob.size()}; - return {}; -} - -inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec& blob) { - /* hidl unmarshals funny pointers if the the blob is empty */ - if (blob.size()) return {&blob[0], blob.size()}; - return {}; -} - -inline static hidl_vec kmBlob2hidlVec(const keymaster_key_blob_t& blob) { - if (blob.key_material == nullptr || blob.key_material_size == 0) { - return {}; - } else { - return hidl_vec(blob.key_material, blob.key_material + blob.key_material_size); - } -} -inline static hidl_vec kmBlob2hidlVec(const keymaster_blob_t& blob) { - if (blob.data == nullptr || blob.data_length == 0) { - return {}; - } else { - return hidl_vec(blob.data, blob.data + blob.data_length); - } -} - -inline static hidl_vec> -kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) { - hidl_vec> result; - if (!cert_chain || cert_chain->entry_count == 0 || !cert_chain->entries) return result; - - result.resize(cert_chain->entry_count); - for (size_t i = 0; i < cert_chain->entry_count; ++i) { - auto& entry = cert_chain->entries[i]; - result[i] = kmBlob2hidlVec(entry); - } - - return result; -} - -static inline hidl_vec kmParamSet2Hidl(const keymaster_key_param_set_t& set) { - hidl_vec result; - if (set.length == 0 || set.params == nullptr) return result; - - result.resize(set.length); - keymaster_key_param_t* params = set.params; - for (size_t i = 0; i < set.length; ++i) { - auto tag = params[i].tag; - result[i].tag = legacy_enum_conversion(tag); - switch (typeFromTag(tag)) { - case KM_ENUM: - case KM_ENUM_REP: - result[i].f.integer = params[i].enumerated; - break; - case KM_UINT: - case KM_UINT_REP: - result[i].f.integer = params[i].integer; - break; - case KM_ULONG: - case KM_ULONG_REP: - result[i].f.longInteger = params[i].long_integer; - break; - case KM_DATE: - result[i].f.dateTime = params[i].date_time; - break; - case KM_BOOL: - result[i].f.boolValue = params[i].boolean; - break; - case KM_BIGNUM: - case KM_BYTES: - result[i].blob = kmBlob2hidlVec(params[i].blob); - break; - case KM_INVALID: - default: - params[i].tag = KM_TAG_INVALID; - /* just skip */ - break; - } - } - return result; -} - -// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow. -Return LegacyKeymasterDeviceWrapper::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) { - _hidl_cb(false, false, false, false, false, "Fallback Device", "Google Android Security"); - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::addRngEntropy(const hidl_vec& data) { - return legacy_enum_conversion( - keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size())); -} - -Return LegacyKeymasterDeviceWrapper::generateKey(const hidl_vec& keyParams, - generateKey_cb _hidl_cb) { - // result variables for the wire - KeyCharacteristics resultCharacteristics; - hidl_vec resultKeyBlob; - - // result variables the backend understands - keymaster_key_blob_t key_blob{nullptr, 0}; - keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}}; - - // convert the parameter set to something our backend understands - auto kmParams = hidlParams2KmParamSet(keyParams); - - auto rc = keymaster_device_->generate_key(keymaster_device_, &kmParams, &key_blob, - &key_characteristics); - - if (rc == KM_ERROR_OK) { - // on success convert the result to wire format - resultKeyBlob = kmBlob2hidlVec(key_blob); - resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced); - resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced); - } - - // send results off to the client - _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics); - - // free buffers that we are responsible for - if (key_blob.key_material) free(const_cast(key_blob.key_material)); - keymaster_free_characteristics(&key_characteristics); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::getKeyCharacteristics( - const hidl_vec& keyBlob, const hidl_vec& clientId, - const hidl_vec& appData, getKeyCharacteristics_cb _hidl_cb) { - // result variables for the wire - KeyCharacteristics resultCharacteristics; - - // result variables the backend understands - keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}}; - - auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob); - auto kmClientId = hidlVec2KmBlob(clientId); - auto kmAppData = hidlVec2KmBlob(appData); - - auto rc = keymaster_device_->get_key_characteristics( - keymaster_device_, keyBlob.size() ? &kmKeyBlob : nullptr, - clientId.size() ? &kmClientId : nullptr, appData.size() ? &kmAppData : nullptr, - &key_characteristics); - - if (rc == KM_ERROR_OK) { - resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced); - resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced); - } - - _hidl_cb(legacy_enum_conversion(rc), resultCharacteristics); - - keymaster_free_characteristics(&key_characteristics); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::importKey(const hidl_vec& params, - KeyFormat keyFormat, - const hidl_vec& keyData, - importKey_cb _hidl_cb) { - // result variables for the wire - KeyCharacteristics resultCharacteristics; - hidl_vec resultKeyBlob; - - // result variables the backend understands - keymaster_key_blob_t key_blob{nullptr, 0}; - keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}}; - - auto kmParams = hidlParams2KmParamSet(params); - auto kmKeyData = hidlVec2KmBlob(keyData); - - auto rc = keymaster_device_->import_key(keymaster_device_, &kmParams, - legacy_enum_conversion(keyFormat), &kmKeyData, - &key_blob, &key_characteristics); - - if (rc == KM_ERROR_OK) { - // on success convert the result to wire format - resultKeyBlob = kmBlob2hidlVec(key_blob); - resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced); - resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced); - } - - _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics); - - // free buffers that we are responsible for - if (key_blob.key_material) free(const_cast(key_blob.key_material)); - keymaster_free_characteristics(&key_characteristics); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::exportKey(KeyFormat exportFormat, - const hidl_vec& keyBlob, - const hidl_vec& clientId, - const hidl_vec& appData, - exportKey_cb _hidl_cb) { - - // result variables for the wire - hidl_vec resultKeyBlob; - - // result variables the backend understands - keymaster_blob_t out_blob = {}; - - auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob); - auto kmClientId = hidlVec2KmBlob(clientId); - auto kmAppData = hidlVec2KmBlob(appData); - - auto rc = keymaster_device_->export_key(keymaster_device_, legacy_enum_conversion(exportFormat), - keyBlob.size() ? &kmKeyBlob : nullptr, - clientId.size() ? &kmClientId : nullptr, - appData.size() ? &kmAppData : nullptr, &out_blob); - - if (rc == KM_ERROR_OK) { - // on success convert the result to wire format - // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?) - resultKeyBlob = kmBlob2hidlVec(out_blob); - } - - _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob); - - // free buffers that we are responsible for - if (out_blob.data) free(const_cast(out_blob.data)); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::attestKey(const hidl_vec& keyToAttest, - const hidl_vec& attestParams, - attestKey_cb _hidl_cb) { - - hidl_vec> resultCertChain; - - for (size_t i = 0; i < attestParams.size(); ++i) { - switch (attestParams[i].tag) { - case Tag::ATTESTATION_ID_BRAND: - case Tag::ATTESTATION_ID_DEVICE: - case Tag::ATTESTATION_ID_PRODUCT: - case Tag::ATTESTATION_ID_SERIAL: - case Tag::ATTESTATION_ID_IMEI: - case Tag::ATTESTATION_ID_MEID: - case Tag::ATTESTATION_ID_MANUFACTURER: - case Tag::ATTESTATION_ID_MODEL: - // Device id attestation may only be supported if the device is able to permanently - // destroy its knowledge of the ids. This device is unable to do this, so it must - // never perform any device id attestation. - _hidl_cb(ErrorCode::CANNOT_ATTEST_IDS, resultCertChain); - return Void(); - default: - break; - } - } - - keymaster_cert_chain_t cert_chain = {}; - - auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest); - auto kmAttestParams = hidlParams2KmParamSet(attestParams); - - auto rc = keymaster_device_->attest_key(keymaster_device_, &kmKeyToAttest, &kmAttestParams, - &cert_chain); - - if (rc == KM_ERROR_OK) { - resultCertChain = kmCertChain2Hidl(&cert_chain); - } - - _hidl_cb(legacy_enum_conversion(rc), resultCertChain); - - keymaster_free_cert_chain(&cert_chain); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::upgradeKey(const hidl_vec& keyBlobToUpgrade, - const hidl_vec& upgradeParams, - upgradeKey_cb _hidl_cb) { - - // result variables for the wire - hidl_vec resultKeyBlob; - - // result variables the backend understands - keymaster_key_blob_t key_blob = {}; - - auto kmKeyBlobToUpgrade = hidlVec2KmKeyBlob(keyBlobToUpgrade); - auto kmUpgradeParams = hidlParams2KmParamSet(upgradeParams); - - auto rc = keymaster_device_->upgrade_key(keymaster_device_, &kmKeyBlobToUpgrade, - &kmUpgradeParams, &key_blob); - - if (rc == KM_ERROR_OK) { - // on success convert the result to wire format - resultKeyBlob = kmBlob2hidlVec(key_blob); - } - - _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob); - - if (key_blob.key_material) free(const_cast(key_blob.key_material)); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::deleteKey(const hidl_vec& keyBlob) { - auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob); - return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob)); -} - -Return LegacyKeymasterDeviceWrapper::deleteAllKeys() { - return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_)); -} - -Return LegacyKeymasterDeviceWrapper::destroyAttestationIds() { - return ErrorCode::UNIMPLEMENTED; -} - -Return LegacyKeymasterDeviceWrapper::begin(KeyPurpose purpose, const hidl_vec& key, - const hidl_vec& inParams, - begin_cb _hidl_cb) { - - // result variables for the wire - hidl_vec resultParams; - uint64_t resultOpHandle = 0; - - // result variables the backend understands - keymaster_key_param_set_t out_params{nullptr, 0}; - keymaster_operation_handle_t& operation_handle = resultOpHandle; - - auto kmKey = hidlVec2KmKeyBlob(key); - auto kmInParams = hidlParams2KmParamSet(inParams); - - auto rc = keymaster_device_->begin(keymaster_device_, legacy_enum_conversion(purpose), &kmKey, - &kmInParams, &out_params, &operation_handle); - - if (rc == KM_ERROR_OK) resultParams = kmParamSet2Hidl(out_params); - - _hidl_cb(legacy_enum_conversion(rc), resultParams, resultOpHandle); - - keymaster_free_param_set(&out_params); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::update(uint64_t operationHandle, - const hidl_vec& inParams, - const hidl_vec& input, - update_cb _hidl_cb) { - // result variables for the wire - uint32_t resultConsumed = 0; - hidl_vec resultParams; - hidl_vec resultBlob; - - // result variables the backend understands - size_t consumed = 0; - keymaster_key_param_set_t out_params = {}; - keymaster_blob_t out_blob = {}; - - auto kmInParams = hidlParams2KmParamSet(inParams); - auto kmInput = hidlVec2KmBlob(input); - - auto rc = keymaster_device_->update(keymaster_device_, operationHandle, &kmInParams, &kmInput, - &consumed, &out_params, &out_blob); - - if (rc == KM_ERROR_OK) { - resultConsumed = consumed; - resultParams = kmParamSet2Hidl(out_params); - resultBlob = kmBlob2hidlVec(out_blob); - } - - _hidl_cb(legacy_enum_conversion(rc), resultConsumed, resultParams, resultBlob); - - keymaster_free_param_set(&out_params); - if (out_blob.data) free(const_cast(out_blob.data)); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::finish(uint64_t operationHandle, - const hidl_vec& inParams, - const hidl_vec& input, - const hidl_vec& signature, - finish_cb _hidl_cb) { - // result variables for the wire - hidl_vec resultParams; - hidl_vec resultBlob; - - // result variables the backend understands - keymaster_key_param_set_t out_params = {}; - keymaster_blob_t out_blob = {}; - - auto kmInParams = hidlParams2KmParamSet(inParams); - auto kmInput = hidlVec2KmBlob(input); - auto kmSignature = hidlVec2KmBlob(signature); - - auto rc = keymaster_device_->finish(keymaster_device_, operationHandle, &kmInParams, &kmInput, - &kmSignature, &out_params, &out_blob); - - if (rc == KM_ERROR_OK) { - resultParams = kmParamSet2Hidl(out_params); - resultBlob = kmBlob2hidlVec(out_blob); - } - - _hidl_cb(legacy_enum_conversion(rc), resultParams, resultBlob); - - keymaster_free_param_set(&out_params); - if (out_blob.data) free(const_cast(out_blob.data)); - - return Void(); -} - -Return LegacyKeymasterDeviceWrapper::abort(uint64_t operationHandle) { - return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle)); -} - -sp makeSoftwareKeymasterDevice() { - keymaster2_device_t* dev = nullptr; - dev = (new SoftKeymasterDevice(keymaster::KmVersion::KEYMASTER_2))->keymaster2_device(); - - auto kmrc = ::keymaster::ConfigureDevice(dev); - if (kmrc != KM_ERROR_OK) { - dev->common.close(&dev->common); - return nullptr; - } - - return new LegacyKeymasterDeviceWrapper(dev); -} - -} // namespace keystore -} // namespace android diff --git a/keystore/legacy_keymaster_device_wrapper.h b/keystore/legacy_keymaster_device_wrapper.h deleted file mode 100644 index cd2e5a77..00000000 --- a/keystore/legacy_keymaster_device_wrapper.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - ** - ** Copyright 2016, 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 LEGACY_KEYMASTER_DEVICE_WRAPPER_H_ -#define LEGACY_KEYMASTER_DEVICE_WRAPPER_H_ - -#include -#include -#include - -struct keymaster2_device; -typedef struct keymaster2_device keymaster2_device_t; - -namespace android { -namespace keystore { - -using ::android::hardware::keymaster::V3_0::ErrorCode; -using ::android::hardware::keymaster::V3_0::IKeymasterDevice; -using ::android::hardware::keymaster::V3_0::KeyCharacteristics; -using ::android::hardware::keymaster::V3_0::KeyFormat; -using ::android::hardware::keymaster::V3_0::KeyParameter; -using ::android::hardware::keymaster::V3_0::KeyPurpose; -using ::android::hardware::keymaster::V3_0::Tag; -using ::android::hardware::Return; -using ::android::hardware::Void; -using ::android::hardware::hidl_vec; -using ::android::hardware::hidl_string; -using ::android::sp; - -class LegacyKeymasterDeviceWrapper : public IKeymasterDevice { - public: - explicit LegacyKeymasterDeviceWrapper(keymaster2_device_t* dev); - virtual ~LegacyKeymasterDeviceWrapper(); - - // Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow. - Return getHardwareFeatures(getHardwareFeatures_cb _hidl_cb); - Return addRngEntropy(const hidl_vec& data) override; - Return generateKey(const hidl_vec& keyParams, - generateKey_cb _hidl_cb) override; - Return getKeyCharacteristics(const hidl_vec& keyBlob, - const hidl_vec& clientId, - const hidl_vec& appData, - getKeyCharacteristics_cb _hidl_cb) override; - Return importKey(const hidl_vec& params, KeyFormat keyFormat, - const hidl_vec& keyData, importKey_cb _hidl_cb) override; - Return exportKey(KeyFormat exportFormat, const hidl_vec& keyBlob, - const hidl_vec& clientId, const hidl_vec& appData, - exportKey_cb _hidl_cb) override; - Return attestKey(const hidl_vec& keyToAttest, - const hidl_vec& attestParams, - attestKey_cb _hidl_cb) override; - Return upgradeKey(const hidl_vec& keyBlobToUpgrade, - const hidl_vec& upgradeParams, - upgradeKey_cb _hidl_cb) override; - Return deleteKey(const hidl_vec& keyBlob) override; - Return deleteAllKeys() override; - Return destroyAttestationIds() override; - Return begin(KeyPurpose purpose, const hidl_vec& key, - const hidl_vec& inParams, begin_cb _hidl_cb) override; - Return update(uint64_t operationHandle, const hidl_vec& inParams, - const hidl_vec& input, update_cb _hidl_cb) override; - Return finish(uint64_t operationHandle, const hidl_vec& inParams, - const hidl_vec& input, const hidl_vec& signature, - finish_cb _hidl_cb) override; - Return abort(uint64_t operationHandle) override; - - private: - keymaster2_device_t* keymaster_device_; -}; - -sp makeSoftwareKeymasterDevice(); - -} // namespace keystore -} // namespace android - -#endif // LEGACY_KEYMASTER_DEVICE_WRAPPER_H_ diff --git a/keystore/operation.cpp b/keystore/operation.cpp deleted file mode 100644 index bd4bd5ef..00000000 --- a/keystore/operation.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ -#define LOG_TAG "KeystoreOperation" - -#include "operation.h" -#include "key_operation_log_handler.h" - -#include -#include -#include - -namespace keystore { - -OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient) - : mDeathRecipient(deathRecipient) {} - -sp OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose, - const sp& dev, const sp& appToken, - KeyCharacteristics&& characteristics, - const hidl_vec& params, bool pruneable) { - sp token = new ::android::BBinder(); - mMap.emplace(token, std::make_shared(handle, keyid, purpose, dev, - std::move(characteristics), appToken, params)); - if (pruneable) mLru.push_back(token); - if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) appToken->linkToDeath(mDeathRecipient); - mAppTokenMap[appToken].push_back(token); - return token; -} - -std::shared_ptr OperationMap::getOperation(const sp& token) { - auto entry = mMap.find(token); - if (entry == mMap.end()) return {}; - - auto op = entry->second; - - updateLru(token); - return op; -} - -void OperationMap::updateLru(const sp& token) { - auto lruEntry = std::find(mLru.begin(), mLru.end(), token); - if (lruEntry != mLru.end()) { - mLru.erase(lruEntry); - mLru.push_back(token); - } -} - -std::shared_ptr OperationMap::removeOperation(const sp& token, - bool wasSuccessful, int32_t responseCode) { - auto entry = mMap.find(token); - if (entry == mMap.end()) return {}; - - auto op = entry->second; - logKeystoreKeyOperationEvent(*op, wasSuccessful, responseCode); - mMap.erase(entry); - - auto lruEntry = std::find(mLru.begin(), mLru.end(), token); - if (lruEntry != mLru.end()) mLru.erase(lruEntry); - removeOperationTracking(token, op->appToken); - return op; -} - -void OperationMap::removeOperationTracking(const sp& token, const sp& appToken) { - auto appEntry = mAppTokenMap.find(appToken); - if (appEntry == mAppTokenMap.end()) { - ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get()); - return; - } - auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token); - appEntry->second.erase(tokenEntry); - // Stop listening for death if all operations tied to the token have finished. - if (appEntry->second.size() == 0) { - appToken->unlinkToDeath(mDeathRecipient); - mAppTokenMap.erase(appEntry); - } -} - -sp OperationMap::getOldestPruneableOperation() { - if (mLru.size() == 0) return {}; - - return {mLru.front()}; -} - -std::vector> OperationMap::getOperationsForToken(const sp& appToken) { - auto appEntry = mAppTokenMap.find(appToken); - if (appEntry == mAppTokenMap.end()) return {}; - return appEntry->second; -} - -} // namespace keystore diff --git a/keystore/operation.h b/keystore/operation.h deleted file mode 100644 index 8423db5b..00000000 --- a/keystore/operation.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2015 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_OPERATION_H_ -#define KEYSTORE_OPERATION_H_ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "operation_struct.h" - -namespace keystore { - -using ::android::IBinder; -using ::android::sp; -using keymaster::support::Keymaster; - -/** - * OperationMap handles the translation of uint64_t's and keymaster2_device_t's to opaque binder - * tokens that can be used to reference that operation at a later time by applications. It also does - * LRU tracking for operation pruning and keeps a mapping of clients to operations to allow for - * graceful handling of application death. - */ - -class OperationMap { - public: - explicit OperationMap(IBinder::DeathRecipient* deathRecipient); - sp addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose, - const sp& dev, const sp& appToken, - KeyCharacteristics&& characteristics, - const hidl_vec& params, bool pruneable); - std::shared_ptr getOperation(const sp& token); - std::shared_ptr removeOperation(const sp& token, bool wasSuccessful, - int32_t responseCode); - size_t getOperationCount() const { return mMap.size(); } - sp getOldestPruneableOperation(); - std::vector> getOperationsForToken(const sp& appToken); - - private: - void updateLru(const sp& token); - void removeOperationTracking(const sp& token, const sp& appToken); - - std::map, std::shared_ptr> mMap; - std::list> mLru; - std::map, std::vector>> mAppTokenMap; - IBinder::DeathRecipient* mDeathRecipient; -}; - -} // namespace keystore - -#endif diff --git a/keystore/operation_struct.h b/keystore/operation_struct.h deleted file mode 100644 index 23e79fc5..00000000 --- a/keystore/operation_struct.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 KEYSTORE_OPERATION_STRUCT_H_ -#define KEYSTORE_OPERATION_STRUCT_H_ - -#include -#include -#include -#include - -#include -#include -#include - -#include - -namespace keystore { - -using ::android::IBinder; -using ::android::sp; -using keymaster::support::Keymaster; - -struct Operation { - Operation() = default; - Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_, const sp& device_, - KeyCharacteristics&& characteristics_, sp appToken_, - const hidl_vec params_) - : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_), - characteristics(characteristics_), appToken(appToken_), authToken(), verificationToken(), - params(params_) {} - Operation(Operation&&) = default; - Operation(const Operation&) = delete; - - bool hasAuthToken() const { return authToken.mac.size() != 0; } - - uint64_t handle; - uint64_t keyid; - KeyPurpose purpose; - sp device; - KeyCharacteristics characteristics; - sp appToken; - std::promise authTokenPromise; - std::future authTokenFuture; - HardwareAuthToken authToken; - VerificationToken verificationToken; - const hidl_vec params; -}; - -} // namespace keystore - -#endif diff --git a/keystore/permissions.cpp b/keystore/permissions.cpp deleted file mode 100644 index 2cd42cf2..00000000 --- a/keystore/permissions.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#define LOG_TAG "keystore" - -#include "permissions.h" - -#include -#include -#include - -#include - -#include "keystore_utils.h" - -/* perm_labels associcated with keystore_key SELinux class verbs. */ -const char* perm_labels[] = { - "get_state", - "get", - "insert", - "delete", - "exist", - "list", - "reset", - "password", - "lock", - "unlock", - "is_empty", - "sign", - "verify", - "grant", - "duplicate", - "clear_uid", - "add_auth", - "user_changed", - "gen_unique_id", -}; - -struct user_euid { - uid_t uid; - uid_t euid; -}; - -user_euid user_euids[] = {{AID_VPN, AID_SYSTEM}, - {AID_WIFI, AID_SYSTEM}, - {AID_ROOT, AID_SYSTEM}, - -#ifdef GRANT_ROOT_ALL_PERMISSIONS - // Allow VTS tests to act on behalf of the wifi user - {AID_WIFI, AID_ROOT} -#endif -}; - -struct user_perm { - uid_t uid; - perm_t perms; -}; - -static user_perm user_perms[] = { - {AID_SYSTEM, static_cast((uint32_t)(~0))}, - {AID_VPN, static_cast(P_GET | P_SIGN | P_VERIFY)}, - {AID_WIFI, static_cast(P_GET | P_SIGN | P_VERIFY)}, - {AID_BLUETOOTH, static_cast(P_GET | P_INSERT | P_DELETE | P_EXIST | P_SIGN | P_VERIFY)}, - -#ifdef GRANT_ROOT_ALL_PERMISSIONS - // Allow VTS tests running as root to perform all operations - {AID_ROOT, static_cast((uint32_t)(~0))}, -#else - {AID_ROOT, static_cast(P_GET)}, -#endif -}; - -static const perm_t DEFAULT_PERMS = static_cast( - P_GET_STATE | P_GET | P_INSERT | P_DELETE | P_EXIST | P_LIST | P_SIGN | P_VERIFY | - P_GEN_UNIQUE_ID /* Only privileged apps can do this, but enforcement is done by SELinux */); - -struct audit_data { - pid_t pid; - uid_t uid; - const char* sid; -}; - -const char* get_perm_label(perm_t perm) { - unsigned int index = ffs(perm); - if (index > 0 && index <= (sizeof(perm_labels) / sizeof(perm_labels[0]))) { - return perm_labels[index - 1]; - } else { - ALOGE("Keystore: Failed to retrieve permission label.\n"); - abort(); - } -} - -static int audit_callback(void* data, security_class_t /* cls */, char* buf, size_t len) { - struct audit_data* ad = reinterpret_cast(data); - if (!ad) { - ALOGE("No keystore audit data"); - return 0; - } - - const char* sid = ad->sid ? ad->sid : "N/A"; - snprintf(buf, len, "pid=%d uid=%d sid=%s", ad->pid, ad->uid, sid); - return 0; -} - -static char* tctx; - -int configure_selinux() { - union selinux_callback cb; - cb.func_audit = audit_callback; - selinux_set_callback(SELINUX_CB_AUDIT, cb); - cb.func_log = selinux_log_callback; - selinux_set_callback(SELINUX_CB_LOG, cb); - if (getcon(&tctx) != 0) { - ALOGE("SELinux: Could not acquire target context. Aborting keystore.\n"); - return -1; - } - - return 0; -} - -static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid, const char* ssid) { - audit_data ad; - char* sctx = nullptr; - const char* selinux_class = "keystore_key"; - const char* str_perm = get_perm_label(perm); - - if (!str_perm) { - return false; - } - - if (ssid == nullptr && getpidcon(spid, &sctx) != 0) { - ALOGE("SELinux: Failed to get source pid context.\n"); - return false; - } - - const char* use_sid = ssid ? ssid : sctx; - - ad.pid = spid; - ad.uid = uid; - ad.sid = use_sid; - - bool allowed = selinux_check_access(use_sid, tctx, selinux_class, str_perm, - reinterpret_cast(&ad)) == 0; - freecon(sctx); - return allowed; -} - -/** - * Returns the UID that the callingUid should act as. This is here for - * legacy support of the WiFi and VPN systems and should be removed - * when WiFi can operate in its own namespace. - */ -uid_t get_keystore_euid(uid_t uid) { - for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) { - struct user_euid user = user_euids[i]; - if (user.uid == uid) { - return user.euid; - } - } - - return uid; -} - -bool has_permission(uid_t uid, perm_t perm, pid_t spid, const char* sid) { - // All system users are equivalent for multi-user support. - if (get_app_id(uid) == AID_SYSTEM) { - uid = AID_SYSTEM; - } - - if (sid == nullptr) { - android_errorWriteLog(0x534e4554, "121035042"); - } - - for (size_t i = 0; i < sizeof(user_perms) / sizeof(user_perms[0]); i++) { - struct user_perm user = user_perms[i]; - if (user.uid == uid) { - return (user.perms & perm) && keystore_selinux_check_access(uid, perm, spid, sid); - } - } - - return (DEFAULT_PERMS & perm) && keystore_selinux_check_access(uid, perm, spid, sid); -} - -/** - * Returns true if the callingUid is allowed to interact in the targetUid's - * namespace. - */ -bool is_granted_to(uid_t callingUid, uid_t targetUid) { - if (callingUid == targetUid) { - return true; - } - for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) { - struct user_euid user = user_euids[i]; - if (user.euid == callingUid && user.uid == targetUid) { - return true; - } - } - - return false; -} diff --git a/keystore/permissions.h b/keystore/permissions.h deleted file mode 100644 index 1dd0089a..00000000 --- a/keystore/permissions.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2016 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_PERMISSIONS_H_ -#define KEYSTORE_PERMISSIONS_H_ - -#include - -/* Here are the permissions, actions, users, and the main function. */ -enum perm_t { - P_GET_STATE = 1 << 0, - P_GET = 1 << 1, - P_INSERT = 1 << 2, - P_DELETE = 1 << 3, - P_EXIST = 1 << 4, - P_LIST = 1 << 5, - P_RESET = 1 << 6, - P_PASSWORD = 1 << 7, - P_LOCK = 1 << 8, - P_UNLOCK = 1 << 9, - P_IS_EMPTY = 1 << 10, - P_SIGN = 1 << 11, - P_VERIFY = 1 << 12, - P_GRANT = 1 << 13, - P_DUPLICATE = 1 << 14, - P_CLEAR_UID = 1 << 15, - P_ADD_AUTH = 1 << 16, - P_USER_CHANGED = 1 << 17, - P_GEN_UNIQUE_ID = 1 << 18, -}; - -const char* get_perm_label(perm_t perm); - -/** - * Returns the UID that the callingUid should act as. This is here for - * legacy support of the WiFi and VPN systems and should be removed - * when WiFi can operate in its own namespace. - */ -uid_t get_keystore_euid(uid_t uid); - -/** - * Returns true if the uid/pid/sid has a permission. Checks based on sid if available. - * - * sid may be null on older kernels - */ -bool has_permission(uid_t uid, perm_t perm, pid_t spid, const char* sid); - -/** - * Returns true if the callingUid is allowed to interact in the targetUid's - * namespace. - */ -bool is_granted_to(uid_t callingUid, uid_t targetUid); - -int configure_selinux(); - -/* - * Keystore grants. - * - * What are keystore grants? - * - * Keystore grants are a mechanism that allows an app to grant the permission to use one of its - * keys to an other app. - * - * Liftime of a grant: - * - * A keystore grant is ephemeral in that is never persistently stored. When the keystore process - * exits, all grants are lost. Also, grants can be explicitly revoked by the granter by invoking - * the ungrant operation. - * - * What happens when a grant is created? - * - * The grant operation expects a valid key alias and the uid of the grantee, i.e., the app that - * shall be allowed to use the key denoted by the alias. It then makes an entry in the grant store - * which generates a new alias of the form _KEYSTOREGRANT_. This grant - * alias is returned to the caller which can pass the new alias to the grantee. For every grantee, - * the grant store keeps a set of grants, an entry of which holds the following information: - * - the owner of the key by uid, aka granter uid, - * - the original alias of the granted key, and - * - the random grant number. - * (See "grant_store.h:class Grant") - * - * What happens when a grant is used? - * - * Upon any keystore operation that expects an alias, the alias and the caller's uid are used - * to retrieve a key file. If that fails some operations try to retrieve a key file indirectly - * through a grant. These operations include: - * - attestKey - * - begin - * - exportKey - * - get - * - getKeyCharacteristics - * - del - * - exist - * - getmtime - * Operations that DO NOT follow the grant indirection are: - * - import - * - generate - * - grant - * - ungrant - * Especially, the latter two mean that neither can a grantee transitively grant a granted key - * to a third, nor can they relinquish access to the key or revoke access to the key by a third. - */ - -#endif // KEYSTORE_PERMISSIONS_H_ diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp index 327eb935..249cb77a 100644 --- a/keystore/tests/Android.bp +++ b/keystore/tests/Android.bp @@ -18,10 +18,6 @@ cc_test { ], srcs: [ "aaid_truncation_test.cpp", - "auth_token_table_test.cpp", - "auth_token_formatting_test.cpp", - "blob_test.cpp", - "confirmationui_rate_limiting_test.cpp", "verification_token_seralization_test.cpp", "gtest_main.cpp", ], @@ -35,7 +31,6 @@ cc_test { "libhidlbase", "libkeymaster4support", "libkeymaster4_1support", - "libkeystore_test", "liblog", "libutils", ], @@ -63,17 +58,14 @@ cc_test { ], name: "confirmationui_invocation_test", static_libs: [ - "android.hardware.confirmationui@1.0", "libbase", "libgtest_main", "libutils", "liblog", ], shared_libs: [ - "libbinder", - "libkeystore_aidl", // for IKeyStoreService.asInterface() - "libkeystore_binder", - "libkeystore_parcelables", + "android.security.apc-ndk_platform", + "libbinder_ndk", ], sanitize: { cfi: false, diff --git a/keystore/tests/confirmationui_invocation_test.cpp b/keystore/tests/confirmationui_invocation_test.cpp index f5182b53..7f8a3738 100644 --- a/keystore/tests/confirmationui_invocation_test.cpp +++ b/keystore/tests/confirmationui_invocation_test.cpp @@ -15,11 +15,10 @@ ** limitations under the License. */ -#include -#include -#include -#include -#include +#include +#include +#include +#include #include @@ -28,65 +27,50 @@ #include #include -using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode; -using android::IBinder; -using android::IServiceManager; -using android::sp; -using android::String16; -using android::security::keystore::IKeystoreService; - using namespace std::literals::chrono_literals; +namespace apc = ::aidl::android::security::apc; class ConfirmationListener - : public android::security::BnConfirmationPromptCallback, - public std::promise>> { + : public apc::BnConfirmationCallback, + public std::promise>>> { public: ConfirmationListener() {} - virtual ::android::binder::Status - onConfirmationPromptCompleted(int32_t result, - const ::std::vector& dataThatWasConfirmed) override { - this->set_value({static_cast(result), dataThatWasConfirmed}); - return ::android::binder::Status::ok(); - } + virtual ::ndk::ScopedAStatus + onCompleted(::aidl::android::security::apc::ResponseCode result, + const std::optional>& dataConfirmed) override { + this->set_value({result, dataConfirmed}); + return ::ndk::ScopedAStatus::ok(); + }; }; TEST(ConfirmationInvocationTest, InvokeAndCancel) { - android::ProcessState::self()->startThreadPool(); + ABinderProcess_startThreadPool(); - sp sm = android::defaultServiceManager(); - sp binder = sm->getService(String16("android.security.keystore")); - sp service = android::interface_cast(binder); - ASSERT_TRUE(service); + ::ndk::SpAIBinder apcBinder(AServiceManager_getService("android.security.apc")); + auto apcService = apc::IProtectedConfirmation::fromBinder(apcBinder); + ASSERT_TRUE(apcService); - String16 promptText16("Just a little test!"); - String16 locale16("en"); + std::string promptText("Just a little test!"); + std::string locale("en"); std::vector extraData{0xaa, 0xff, 0x00, 0x55}; - sp listener = new ConfirmationListener(); + auto listener = std::make_shared(); auto future = listener->get_future(); - int32_t aidl_return; - android::binder::Status status = service->presentConfirmationPrompt( - listener, promptText16, extraData, locale16, 0, &aidl_return); - ASSERT_TRUE(status.isOk()) << "Presenting confirmation prompt failed with binder status '" - << status.toString8().c_str() << "'.\n"; - ConfirmationResponseCode responseCode = static_cast(aidl_return); - ASSERT_EQ(responseCode, ConfirmationResponseCode::OK) - << "Presenting confirmation prompt failed with response code " << aidl_return << ".\n"; + auto rc = apcService->presentPrompt(listener, promptText, extraData, locale, 0); + + ASSERT_TRUE(rc.isOk()); auto fstatus = future.wait_for(2s); EXPECT_EQ(fstatus, std::future_status::timeout); - status = service->cancelConfirmationPrompt(listener, &aidl_return); - ASSERT_TRUE(status.isOk()); - - responseCode = static_cast(aidl_return); - ASSERT_EQ(responseCode, ConfirmationResponseCode::OK); + rc = apcService->cancelPrompt(listener); + ASSERT_TRUE(rc.isOk()); future.wait(); - auto [rc, dataThatWasConfirmed] = future.get(); + auto [responseCode, dataThatWasConfirmed] = future.get(); - ASSERT_EQ(rc, ConfirmationResponseCode::Aborted); + ASSERT_EQ(responseCode, apc::ResponseCode::ABORTED); } -- cgit v1.2.3