summaryrefslogtreecommitdiff
path: root/keystore
diff options
context:
space:
mode:
authorJanis Danisevskis <jdanis@google.com>2021-03-08 11:30:11 -0800
committerJanis Danisevskis <jdanis@google.com>2021-03-22 14:34:45 -0700
commit2437fde7a69f867430b617c972ec5121b8d320bf (patch)
tree166105a0173b182c6d44d531556828ff3230a5ac /keystore
parent3c8ea06269dad4b15e7cc8ef6aa7c8d3aefead4f (diff)
downloadsecurity-2437fde7a69f867430b617c972ec5121b8d320bf.tar.gz
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
Diffstat (limited to 'keystore')
-rw-r--r--keystore/Android.bp251
-rw-r--r--keystore/KeyStore.cpp512
-rw-r--r--keystore/KeyStore.h200
-rw-r--r--keystore/KeymasterArguments.cpp45
-rw-r--r--keystore/KeystoreResponse.cpp43
-rw-r--r--keystore/OperationResult.cpp66
-rw-r--r--keystore/auth_token_table.cpp302
-rw-r--r--keystore/auth_token_table.h177
-rw-r--r--keystore/binder/android/security/IConfirmationPromptCallback.aidl27
-rw-r--r--keystore/binder/android/security/keymaster/ExportResult.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/KeyCharacteristics.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/KeymasterArguments.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/KeymasterBlob.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/OperationResult.aidl20
-rw-r--r--keystore/binder/android/security/keystore/ICredstoreTokenCallback.aidl25
-rw-r--r--keystore/binder/android/security/keystore/IKeystoreCertificateChainCallback.aidl27
-rw-r--r--keystore/binder/android/security/keystore/IKeystoreExportKeyCallback.aidl27
-rw-r--r--keystore/binder/android/security/keystore/IKeystoreKeyCharacteristicsCallback.aidl27
-rw-r--r--keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl28
-rw-r--r--keystore/binder/android/security/keystore/IKeystoreResponseCallback.aidl26
-rw-r--r--keystore/binder/android/security/keystore/IKeystoreService.aidl106
-rw-r--r--keystore/binder/android/security/keystore/KeystoreResponse.aidl20
-rw-r--r--keystore/blob.cpp791
-rw-r--r--keystore/blob.h285
-rw-r--r--keystore/confirmation_manager.cpp214
-rw-r--r--keystore/confirmation_manager.h108
-rw-r--r--keystore/confirmationui_rate_limiting.h134
-rw-r--r--keystore/defaults.h42
-rw-r--r--keystore/grant_store.cpp106
-rw-r--r--keystore/grant_store.h83
-rw-r--r--keystore/key_attestation_log_handler.cpp29
-rw-r--r--keystore/key_attestation_log_handler.h26
-rw-r--r--keystore/key_creation_log_handler.cpp211
-rw-r--r--keystore/key_creation_log_handler.h71
-rw-r--r--keystore/key_operation_log_handler.cpp136
-rw-r--r--keystore/key_operation_log_handler.h28
-rw-r--r--keystore/key_store_service.cpp1480
-rw-r--r--keystore/key_store_service.h240
-rw-r--r--keystore/keyblob_utils.cpp65
-rw-r--r--keystore/keymaster_enforcement.cpp555
-rw-r--r--keystore/keymaster_enforcement.h213
-rw-r--r--keystore/keymaster_worker.cpp1144
-rw-r--r--keystore/keymaster_worker.h307
-rw-r--r--keystore/keystore.rc5
-rw-r--r--keystore/keystore_aidl_hidl_marshalling_utils.cpp257
-rw-r--r--keystore/keystore_aidl_hidl_marshalling_utils.h79
-rw-r--r--keystore/keystore_cli.cpp248
-rw-r--r--keystore/keystore_cli_v2.cpp1069
-rw-r--r--keystore/keystore_client_impl.cpp629
-rw-r--r--keystore/keystore_main.cpp162
-rw-r--r--keystore/legacy_keymaster_device_wrapper.cpp547
-rw-r--r--keystore/legacy_keymaster_device_wrapper.h90
-rw-r--r--keystore/operation.cpp103
-rw-r--r--keystore/operation.h77
-rw-r--r--keystore/operation_struct.h65
-rw-r--r--keystore/permissions.cpp213
-rw-r--r--keystore/permissions.h117
-rw-r--r--keystore/tests/Android.bp12
-rw-r--r--keystore/tests/confirmationui_invocation_test.cpp70
60 files changed, 804 insertions, 11236 deletions
diff --git a/keystore/Android.bp b/keystore/Android.bp
index 7278cee6..0f2000cd 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -35,97 +35,6 @@ cc_defaults {
}
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 <dirent.h>
-#include <fcntl.h>
-
-#include <openssl/bio.h>
-
-#include <utils/String16.h>
-#include <utils/String8.h>
-
-#include <android-base/scopeguard.h>
-#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-#include <android/security/keystore/IKeystoreService.h>
-#include <log/log_event_list.h>
-
-#include <private/android_logger.h>
-
-#include "keystore_utils.h"
-#include "permissions.h"
-#include <keystore/keystore_hidl_support.h>
-
-#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<std::decay_t<decltype(kmDevices)>>::value ==
- std::tuple_size<decltype(mKmDevices)>::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<KeymasterWorker>(
- 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<KeyBlobEntry> 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<android::String16> 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<LockedKeyBlobEntry> 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<LockedKeyBlobEntry> 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<ResponseCode, Blob, Blob> KeyStore::get(const LockedKeyBlobEntry& blobfile) {
- std::tuple<ResponseCode, Blob, Blob> 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<ErrorCode> 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<ResponseCode, Blob, Blob, LockedKeyBlobEntry>
-KeyStore::getKeyForName(const android::String8& keyName, const uid_t uid, const BlobType type) {
- std::tuple<ResponseCode, Blob, Blob, LockedKeyBlobEntry> 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<IBinder>& 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 <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <utils/Vector.h>
-
-#include <keystore/keymaster_types.h>
-
-#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 <array>
-#include <optional>
-#include <tuple>
-
-namespace keystore {
-
-using ::android::sp;
-using keymaster::support::Keymaster;
-
-template <typename T, size_t count> class Devices : public std::array<T, count> {
- 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<T, count>::at(static_cast<uint32_t>(secLevel));
- }
- T operator[](SecurityLevel secLevel) const {
- if (static_cast<uint32_t>(secLevel) > static_cast<uint32_t>(SecurityLevel::STRONGBOX)) {
- LOG(ERROR) << "Invalid security level requested";
- return {};
- }
- return (*const_cast<Devices*>(this))[secLevel];
- }
-};
-
-} // namespace keystore
-
-namespace std {
-template <typename T, size_t N> struct tuple_size<keystore::Devices<T, N>> {
- public:
- static constexpr size_t value = std::tuple_size<std::array<T, N>>::value;
-};
-} // namespace std
-
-namespace keystore {
-
-using KeymasterWorkers = Devices<std::shared_ptr<KeymasterWorker>, 3>;
-using KeymasterDevices = Devices<sp<Keymaster>, 3>;
-
-class KeyStore : public ::android::IBinder::DeathRecipient {
- public:
- KeyStore(const KeymasterDevices& kmDevices,
- SecurityLevel minimalAllowedSecurityLevelForNewKeys);
- ~KeyStore();
-
- std::shared_ptr<KeymasterWorker> getDevice(SecurityLevel securityLevel) const {
- return mKmDevices[securityLevel];
- }
-
- std::shared_ptr<KeymasterWorker> 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<KeymasterWorker> 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<KeyBlobEntry> 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<ResponseCode, Blob, Blob> 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<ResponseCode, Blob, Blob, LockedKeyBlobEntry>
- getKeyForName(const android::String8& keyName, const uid_t uid, const BlobType type);
-
- void binderDied(const ::android::wp<IBinder>& who) override;
-
- UserStateDB& getUserStateDB() { return mUserStateDB; }
- AuthTokenTable& getAuthTokenTable() { return mAuthTokenTable; }
- KeystoreKeymasterEnforcement& getEnforcementPolicy() { return mEnforcementPolicy; }
- ConfirmationManager& getConfirmationManager() { return *mConfirmationManager; }
-
- void addOperationDevice(sp<IBinder> token, std::shared_ptr<KeymasterWorker> dev) {
- std::lock_guard<std::mutex> lock(operationDeviceMapMutex_);
- operationDeviceMap_.emplace(std::move(token), std::move(dev));
- }
- std::shared_ptr<KeymasterWorker> getOperationDevice(const sp<IBinder>& token) {
- std::lock_guard<std::mutex> lock(operationDeviceMapMutex_);
- auto it = operationDeviceMap_.find(token);
- if (it != operationDeviceMap_.end()) {
- return it->second;
- }
- return {};
- }
- void removeOperationDevice(const sp<IBinder>& token) {
- std::lock_guard<std::mutex> 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<ConfirmationManager> 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<sp<IBinder>, std::shared_ptr<KeymasterWorker>> 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 <binder/Parcel.h>
-
-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<keystore::KeyParameter>&& other)
- : data_(std::move(other)) {}
-
-KeymasterArguments::KeymasterArguments(const hardware::hidl_vec<keystore::KeyParameter>& 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 <binder/Parcel.h>
-#include <keystore/keymaster_types.h>
-#include <utility>
-#include <utils/String16.h>
-
-#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 <utility>
-
-#include <binder/Parcel.h>
-
-#include <keystore/keymaster_types.h>
-
-#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<uint64_t>(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 <assert.h>
-#include <time.h>
-
-#include <algorithm>
-
-#include <log/log.h>
-
-namespace keystore {
-
-template <typename IntType, uint32_t byteOrder> struct choose_hton;
-
-template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
- inline static IntType hton(const IntType& value) {
- IntType result = 0;
- const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
- unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
- for (int i = sizeof(IntType) - 1; i >= 0; --i) {
- *(outbytes++) = inbytes[i];
- }
- return result;
- }
-};
-
-template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
- inline static IntType hton(const IntType& value) { return value; }
-};
-
-template <typename IntType> inline IntType hton(const IntType& value) {
- return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
-}
-
-template <typename IntType> inline IntType ntoh(const IntType& value) {
- // same operation and hton
- return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
-}
-
-//
-// Some trivial template wrappers around std algorithms, so they take containers not ranges.
-//
-template <typename Container, typename Predicate>
-typename Container::iterator find_if(Container& container, Predicate pred) {
- return std::find_if(container.begin(), container.end(), pred);
-}
-
-template <typename Container, typename Predicate>
-typename Container::iterator remove_if(Container& container, Predicate pred) {
- return std::remove_if(container.begin(), container.end(), pred);
-}
-
-template <typename Container> 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<unsigned long long>(new_entry.token().timestamp),
- static_cast<long long>(new_entry.time_received()));
-
- std::lock_guard<std::mutex> 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::Error, HardwareAuthToken>
-AuthTokenTable::FindAuthorization(const AuthorizationSet& key_info, KeyPurpose purpose,
- uint64_t op_handle) {
-
- std::lock_guard<std::mutex> 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<uint64_t> 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::Error, HardwareAuthToken> AuthTokenTable::FindAuthPerOpAuthorization(
- const std::vector<uint64_t>& 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::Error, HardwareAuthToken>
-AuthTokenTable::FindTimedAuthorization(const std::vector<uint64_t>& 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<int64_t>(newest_match->time_received()) + timeout < static_cast<int64_t>(now))
- return {AUTH_TOKEN_EXPIRED, {}};
-
- if (key_info.GetTagValue(TAG_ALLOW_WHILE_ON_BODY).isOk()) {
- if (static_cast<int64_t>(newest_match->time_received()) <
- static_cast<int64_t>(last_off_body_)) {
- return {AUTH_TOKEN_EXPIRED, {}};
- }
- }
-
- newest_match->UpdateLastUse(now);
- return {OK, newest_match->token()};
-}
-
-std::tuple<AuthTokenTable::Error, HardwareAuthToken>
-AuthTokenTable::FindAuthorizationForCredstore(uint64_t challenge, uint64_t secureUserId,
- int64_t authTokenMaxAgeMillis) {
- std::vector<uint64_t> 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<uint64_t>* 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<std::mutex> lock(entries_mutex_);
-
- entries_.clear();
-}
-
-size_t AuthTokenTable::size() const {
- std::lock_guard<std::mutex> 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<std::mutex> 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<uint64_t>& 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 <memory>
-#include <mutex>
-#include <vector>
-
-#include <keystore/keymaster_types.h>
-
-#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<Error, HardwareAuthToken> FindAuthorization(const AuthorizationSet& key_info,
- KeyPurpose purpose, uint64_t op_handle);
-
- std::tuple<Error, HardwareAuthToken>
- 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<uint64_t>& 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<Error, HardwareAuthToken>
- FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
- HardwareAuthenticatorType auth_type, uint64_t op_handle);
- std::tuple<Error, HardwareAuthToken> FindTimedAuthorization(const std::vector<uint64_t>& sids,
- HardwareAuthenticatorType auth_type,
- const AuthorizationSet& key_info);
- void ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* 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<Entry> 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<String> 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 <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include <log/log.h>
-
-#include "blob.h"
-
-#include "keystore_utils.h"
-
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-
-#include <istream>
-#include <ostream>
-#include <streambuf>
-#include <string>
-
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-
-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<uint8_t>& 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<uint8_t>& 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<EVP_CIPHER_CTX> 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<uint8_t[]> 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<ssize_t>(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<uint8_t> 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<EVP_CIPHER_CTX> 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<uint8_t*>(tag));
-
- std::unique_ptr<uint8_t[]> 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<ssize_t>(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 <typename T, size_t size> explicit ArrayStreamBuffer(const T (&data)[size]) {
- static_assert(sizeof(T) == 1, "Array element size too large");
- std::streambuf::char_type* d = const_cast<std::streambuf::char_type*>(
- reinterpret_cast<const std::streambuf::char_type*>(&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<blobv3>();
- 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<blobv3>(b);
-}
-
-Blob::Blob() {
- if (mBlob) *mBlob = {};
-}
-
-Blob::Blob(const Blob& rhs) {
- if (rhs.mBlob) {
- mBlob = std::make_unique<blobv3>(*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<blobv3>(*rhs.mBlob);
- } else {
- mBlob = {};
- }
- }
- return *this;
-}
-
-Blob& Blob::operator=(Blob&& rhs) {
- if (mBlob) *mBlob = {};
- mBlob = std::move(rhs.mBlob);
- return *this;
-}
-
-template <typename BlobType> 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<uint8_t>& 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<uint8_t*>(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<uint8_t>& 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<uint8_t>& aes_key,
- State state) {
- ResponseCode rc;
- ALOGV("reading blob %s", filename.c_str());
- std::unique_ptr<blobv3> rawBlob = std::make_unique<blobv3>();
-
- 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<blobv2&>(*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<ssize_t>(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<ResponseCode, Blob, Blob>
-LockedKeyBlobEntry::readBlobs(const std::vector<uint8_t>& aes_key, State state) const {
- std::tuple<ResponseCode, Blob, Blob> 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<bool, keystore::AuthorizationSet, keystore::AuthorizationSet>
-Blob::getKeyCharacteristics() const {
- std::tuple<bool, keystore::AuthorizationSet, keystore::AuthorizationSet> 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<blobv3>();
- 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<std::mutex> 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<std::mutex> 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<KeyBlobEntry> 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<bool, uid_t, std::string> filename2UidAlias(const std::string& filepath) {
- std::tuple<bool, uid_t, std::string> 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<ResponseCode, std::list<LockedKeyBlobEntry>>
-LockedKeyBlobEntry::list(const std::string& user_dir,
- std::function<bool(uid_t, const std::string&)> filter) {
- std::list<LockedKeyBlobEntry> 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<std::mutex> 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, std::list<LockedKeyBlobEntry>&&>{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, std::list<LockedKeyBlobEntry>&&>{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 <stdint.h>
-
-#include <openssl/aes.h>
-#include <openssl/md5.h>
-
-#include <condition_variable>
-#include <functional>
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore.h>
-#include <list>
-#include <mutex>
-#include <set>
-#include <sstream>
-#include <vector>
-
-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<bool, keystore::AuthorizationSet, keystore::AuthorizationSet>
- getKeyCharacteristics() const;
-
- bool putKeyCharacteristics(const keystore::AuthorizationSet& hwEnforced,
- const keystore::AuthorizationSet& swEnforced);
-
- private:
- std::unique_ptr<blobv3> mBlob;
-
- ResponseCode readBlob(const std::string& filename, const std::vector<uint8_t>& 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<KeyBlobEntry> 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<ResponseCode, std::list<LockedKeyBlobEntry>>
- list(const std::string& user_dir,
- std::function<bool(uid_t, const std::string&)> filter =
- [](uid_t, const std::string&) -> bool { return true; });
-
- ResponseCode writeBlobs(Blob keyBlob, Blob characteristicsBlob,
- const std::vector<uint8_t>& aes_key, State state) const;
- std::tuple<ResponseCode, Blob, Blob> readBlobs(const std::vector<uint8_t>& 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 <android/hardware/confirmationui/1.0/IConfirmationResultCallback.h>
-#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
-#include <android/hardware/confirmationui/1.0/types.h>
-#include <android/security/BpConfirmationPromptCallback.h>
-#include <binder/BpBinder.h>
-#include <binder/IPCThreadState.h>
-#include <binder/Parcel.h>
-
-#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<IBinder>& listener,
- const String16& promptText,
- const hidl_vec<uint8_t>& extraData,
- const String16& locale, int uiOptionsAsFlags,
- int32_t* aidl_return) {
- lock_guard<mutex> lock(mMutex);
-
- if (mCurrentListener != nullptr) {
- *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OperationPending);
- return Status::ok();
- }
-
- sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
- if (confirmationUI == nullptr) {
- ALOGW("Error getting confirmationUI service\n");
- *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::Unimplemented);
- return Status::ok();
- }
-
- uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
- if (!mRateLimiting.tryPrompt(callingUid)) {
- *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::SystemError);
- return Status::ok();
- }
-
- String8 promptText8(promptText);
- String8 locale8(locale);
- vector<UIOption> uiOptionsVector;
- for (int n = 0; n < 32; n++) {
- if (uiOptionsAsFlags & (1 << n)) {
- uiOptionsVector.push_back(UIOption(n));
- }
- }
- ConfirmationResponseCode responseCode;
- responseCode = confirmationUI->promptUserConfirmation(sp<IConfirmationResultCallback>(this),
- promptText8.string(), extraData,
- locale8.string(), uiOptionsVector);
- if (responseCode != ConfirmationResponseCode::OK) {
- ALOGW("Unexpecxted responseCode %d from promptUserConfirmation\n", responseCode);
- *aidl_return = static_cast<int32_t>(responseCode);
- return Status::ok();
- }
-
- listener->linkToDeath(mDeathRecipient);
- confirmationUI->linkToDeath(this, 0);
- mCurrentListener = listener;
- mCurrentConfirmationUI = confirmationUI;
-
- *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
- return Status::ok();
-}
-
-// Called by keystore main thread.
-Status ConfirmationManager::cancelConfirmationPrompt(const sp<IBinder>& 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<int32_t>(ConfirmationResponseCode::OperationPending);
- return Status::ok();
- }
- mMutex.unlock();
-
- cancelPrompt();
-
- *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
- return Status::ok();
-}
-
-void ConfirmationManager::cancelPrompt() {
- mMutex.lock();
- mRateLimiting.cancelPrompt();
- sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
- mMutex.unlock();
- if (confirmationUI != nullptr) {
- confirmationUI->abort();
- }
-}
-
-// Called by keystore main thread.
-Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) {
- sp<IConfirmationUI> 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<uint8_t> dataThatWasConfirmed) {
- mMutex.lock();
- mRateLimiting.processResult(responseCode);
- sp<IBinder> 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<BpConfirmationPromptCallback> obj = new BpConfirmationPromptCallback(listener);
- Status status = obj->onConfirmationPromptCompleted(static_cast<int32_t>(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<void> ConfirmationManager::result(ConfirmationResponseCode responseCode,
- const hidl_vec<uint8_t>& dataThatWasConfirmed,
- const hidl_vec<uint8_t>& confirmationToken) {
- finalizeTransaction(responseCode, dataThatWasConfirmed);
- lock_guard<mutex> lock(mMutex);
- mLatestConfirmationToken = confirmationToken;
- return Return<void>();
-}
-
-// Called by keystore main thread or keymaster worker
-hidl_vec<uint8_t> ConfirmationManager::getLatestConfirmationToken() {
- lock_guard<mutex> lock(mMutex);
- return mLatestConfirmationToken;
-}
-
-void ConfirmationManager::binderDied(const wp<IBinder>& 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<android::hidl::base::V1_0::IBase>& /* 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 <android/hardware/confirmationui/1.0/IConfirmationUI.h>
-#include <android/hardware/confirmationui/1.0/types.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binder/Status.h>
-#include <keystore/keymaster_types.h>
-#include <map>
-#include <mutex>
-#include <utils/LruCache.h>
-#include <utils/StrongPointer.h>
-#include <vector>
-
-#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<android::IBinder>& listener,
- const android::String16& promptText,
- const hidl_vec<uint8_t>& 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<android::IBinder>& 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<uint8_t> getLatestConfirmationToken();
-
- // Called by KeyStoreService when a client binder has died.
- void binderDied(const android::wp<android::IBinder>& who);
-
- // hidl_death_recipient overrides:
- virtual void serviceDied(uint64_t cookie,
- const android::wp<android::hidl::base::V1_0::IBase>& who) override;
-
- // IConfirmationResultCallback overrides:
- android::hardware::Return<void> result(ConfirmationResponseCode responseCode,
- const hidl_vec<uint8_t>& dataThatWasConfirmed,
- const hidl_vec<uint8_t>& 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<uint8_t> 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<android::IBinder> mCurrentListener;
- android::sp<android::hardware::confirmationui::V1_0::IConfirmationUI> mCurrentConfirmationUI;
- android::IBinder::DeathRecipient* mDeathRecipient;
- hidl_vec<uint8_t> 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 <android/hardware/confirmationui/1.0/types.h>
-#include <chrono>
-#include <stdint.h>
-#include <sys/types.h>
-#include <tuple>
-#include <unordered_map>
-
-namespace keystore {
-
-using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
-
-using std::chrono::duration;
-using std::chrono::time_point;
-
-template <typename Clock = std::chrono::steady_clock> 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<uid_t, Slot> 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 <algorithm>
-#include <sstream>
-
-namespace keystore {
-
-static constexpr uint64_t kInvalidGrantNo = std::numeric_limits<uint64_t>::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<uint64_t, std::string> 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<std::shared_mutex> lock(mutex_);
- std::stringstream s;
- KeyBlobEntry blobEntry = *lockedEntry;
- s << blobEntry.alias() << kKeystoreGrantInfix;
-
- std::set<Grant, std::less<>>& 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<std::shared_mutex> 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<std::shared_mutex> 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<std::shared_mutex> 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<std::shared_mutex> 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 <mutex>
-#include <set>
-#include <shared_mutex>
-#include <string>
-#include <unordered_map>
-
-#include <keystore/keystore_concurrency.h>
-
-#include "blob.h"
-
-namespace keystore {
-
-class Grant;
-
-using ReadLockedGrant =
- ProxyLock<MutexProxyLockHelper<const Grant, std::shared_mutex, std::shared_lock>>;
-
-/**
- * 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<uid_t, std::set<Grant, std::less<>>> 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 <statslog.h>
-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 <statslog.h>
-
-namespace keystore {
-
-template <typename Tag>
-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<int32_t>(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<KeyParameter>& 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 <keystore/keystore_hidl_support.h>
-
-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<KeyParameter>& 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 <keystore/keystore_hidl_support.h>
-#include <statslog.h>
-
-namespace keystore {
-
-template <typename Tag>
-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<int32_t>(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<int32_t>(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 <fcntl.h>
-#include <sys/stat.h>
-
-#include <algorithm>
-#include <atomic>
-#include <sstream>
-
-#include <android-base/scopeguard.h>
-#include <binder/IInterface.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IPermissionController.h>
-#include <binder/IServiceManager.h>
-#include <cutils/multiuser.h>
-#include <log/log_event_list.h>
-
-#include <private/android_filesystem_config.h>
-#include <private/android_logger.h>
-
-#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
-#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
-#include <keymasterV4_0/keymaster_utils.h>
-
-#include "defaults.h"
-#include "key_attestation_log_handler.h"
-#include "keystore_keymaster_enforcement.h"
-#include "keystore_utils.h"
-#include <keystore/keystore_attestation_id.h>
-#include <keystore/keystore_hidl_support.h>
-#include <keystore/keystore_return_types.h>
-
-#include <hardware/hw_auth_token.h>
-
-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<KeyParameter>& 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<KeyStoreServiceReturnCode, bool> 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<uint8_t>();
- }
- std::vector<uint8_t>& 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<int32_t>(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<int32_t>(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<uint8_t>* item) {
- uid_t targetUid = getEffectiveUid(uid);
- if (!checkBinderPermission(P_GET, targetUid)) {
- // see keystore/keystore.h
- return Status::fromServiceSpecificError(
- static_cast<int32_t>(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<uint8_t>();
- // 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<int32_t>(rc));
- }
- auto resultBlob = blob2hidlVec(keyBlob);
- // The static_cast here is needed to prevent a move, forcing a deep copy.
- if (item) *item = static_cast<const hidl_vec<uint8_t>&>(blob2hidlVec(keyBlob));
- return Status::ok();
-}
-
-Status KeyStoreService::insert(const String16& name, const ::std::vector<uint8_t>& 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<int32_t>(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<int32_t>(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<int32_t>(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<int32_t>(ResponseCode::KEY_NOT_FOUND);
- return Status::ok();
- }
-
- ResponseCode result = mKeyStore->del(lockedEntry);
-
- *aidl_return = static_cast<int32_t>(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<int32_t>(ResponseCode::PERMISSION_DENIED);
- return Status::ok();
- }
-
- LockedKeyBlobEntry lockedEntry =
- mKeyStore->getLockedBlobEntryIfExists(String8(name).string(), targetUid);
- *aidl_return =
- static_cast<int32_t>(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<int32_t>(ResponseCode::PERMISSION_DENIED));
- }
- const String8 prefix8(prefix);
- const std::string stdPrefix(prefix8.string());
-
- ResponseCode rc;
- std::list<LockedKeyBlobEntry> 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<uid_t>(targetUid) &&
- std::mismatch(stdPrefix.begin(), stdPrefix.end(), alias.begin(), alias.end())
- .first == stdPrefix.end();
- });
-
- if (rc != ResponseCode::NO_ERROR) {
- return Status::fromServiceSpecificError(static_cast<int32_t>(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<std::string>* 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<int32_t>(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<LockedKeyBlobEntry> 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<int32_t>(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<int32_t>(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<int32_t>(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<int32_t>(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<int32_t>(mKeyStore->initializeUser(password8, userId));
- return Status::ok();
- }
- case ::STATE_NO_ERROR: {
- // rewrite master key with new password.
- *aidl_return = static_cast<int32_t>(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<int32_t>(mKeyStore->initializeUser(password8, userId));
- return Status::ok();
- }
- }
- *aidl_return = static_cast<int32_t>(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<int32_t>(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<int32_t>(mKeyStore->copyMasterKey(parentId, userId));
- return Status::ok();
- } else {
- *aidl_return = static_cast<int32_t>(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<int32_t>(ResponseCode::PERMISSION_DENIED);
- return Status::ok();
- }
-
- mKeyStore->resetUser(userId, false);
- *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
- return Status::ok();
-}
-
-Status KeyStoreService::lock(int32_t userId, int32_t* aidl_return) {
- if (!checkBinderPermission(P_LOCK)) {
- *aidl_return = static_cast<int32_t>(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<int32_t>(ResponseCode(state));
- return Status::ok();
- }
-
- mKeyStore->getEnforcementPolicy().set_device_locked(true, userId);
- mKeyStore->lock(userId);
- *aidl_return = static_cast<int32_t>(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<int32_t>(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<int32_t>(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<int32_t>(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<int32_t>(false);
- return Status::ok();
- }
-
- *aidl_return = static_cast<int32_t>(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<int32_t>(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<int64_t>(s.st_mtime);
- return Status::ok();
-}
-
-Status KeyStoreService::is_hardware_backed(const String16& keyType, int32_t* aidl_return) {
- *aidl_return = static_cast<int32_t>(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<LockedKeyBlobEntry> 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<uint8_t>& 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<ErrorCode> 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<uint8_t>& 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<int32_t>(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<uint8_t>& 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<int32_t>(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<IKeystoreOperationResultCallback>& cb,
- const sp<IBinder>& appToken, const String16& name, int32_t purpose,
- bool pruneable, const KeymasterArguments& params,
- const ::std::vector<uint8_t>& 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<KeyPurpose>(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<IKeystoreOperationResultCallback>& cb,
- const ::android::sp<::android::IBinder>& token,
- const ::android::security::keymaster::KeymasterArguments& params,
- const ::std::vector<uint8_t>& 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<IKeystoreOperationResultCallback>& cb,
- const ::android::sp<::android::IBinder>& token,
- const ::android::security::keymaster::KeymasterArguments& params,
- const ::std::vector<uint8_t>& input,
- const ::std::vector<uint8_t>& signature,
- const ::std::vector<uint8_t>& 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<IKeystoreResponseCallback>& 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<uint8_t>& 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<int32_t>(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<void*>(&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<uint8_t>(authTokenAsVector)));
- *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
- return Status::ok();
-}
-
-Status KeyStoreService::getTokensForCredstore(int64_t challenge, int64_t secureUserId,
- int32_t authTokenMaxAgeMillis,
- const ::android::sp<ICredstoreTokenCallback>& cb) {
- uid_t callingUid = IPCThreadState::self()->getCallingUid();
- if (callingUid != AID_CREDSTORE) {
- return Status::fromServiceSpecificError(static_cast<int32_t>(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<uint8_t> serializedAuthToken = authToken2HidlVec(authToken);
- std::vector<uint8_t> serializedVerificationToken;
- std::shared_ptr<KeymasterWorker> 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<int32_t>(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<std::vector<uint8_t>> 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<KeyParameter>& 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<KeyParameter>& 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<void> rc,
- std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
- auto& [ret, certChain] = hidlResult;
- if (!rc.isOk()) {
- logKeystoreKeyAttestationEvent(false /*wasSuccessful*/,
- static_cast<int32_t>(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<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
- if (binder == nullptr) {
- return AIDL_RETURN(ErrorCode::CANNOT_ATTEST_IDS);
- }
-
- if (!interface_cast<IPermissionController>(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<KeyStoreServiceReturnCode> resultPromise;
- auto resultFuture = resultPromise.get_future();
-
- dev->generateKey(
- keyCharacteristics.hidl_data(),
- [cb, dev, CAPTURE_MOVE(mutableParams)](
- Return<void> rc,
- std::tuple<ErrorCode, ::std::vector<uint8_t>, 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<void> rc,
- std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
- auto& [ret, certChain] = hidlResult;
- // schedule temp key for deletion
- dev->deleteKey(std::move(hidlKeyBlob), [dev](Return<ErrorCode> 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<int32_t>(ResponseCode::NO_ERROR);
- return Status::ok();
-}
-
-Status KeyStoreService::importWrappedKey(
- const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
- const ::android::String16& wrappedKeyAlias, const ::std::vector<uint8_t>& wrappedKey,
- const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& 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<IBinder>& listener,
- const String16& promptText,
- const ::std::vector<uint8_t>& 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<IBinder>& 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<uid_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 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<ResponseCode>(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<KeyParameter>& 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 <android/security/keystore/BnKeystoreService.h>
-
-#include "auth_token_table.h"
-#include "confirmation_manager.h"
-
-#include "KeyStore.h"
-#include "keystore_keymaster_enforcement.h"
-#include "operation.h"
-#include "permissions.h"
-
-#include <keystore/ExportResult.h>
-#include <keystore/KeyCharacteristics.h>
-#include <keystore/KeymasterArguments.h>
-#include <keystore/KeymasterBlob.h>
-#include <keystore/KeymasterCertificateChain.h>
-#include <keystore/OperationResult.h>
-#include <keystore/keystore_return_types.h>
-
-#include <mutex>
-
-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> keyStore) : mKeyStore(keyStore) {}
- virtual ~KeyStoreService() = default;
-
- void binderDied(const android::wp<android::IBinder>& 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<uint8_t>* _aidl_return) override;
- ::android::binder::Status insert(const ::android::String16& name,
- const ::std::vector<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& input, const ::std::vector<uint8_t>& signature,
- const ::std::vector<uint8_t>& 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<uint8_t>& 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<uint8_t>& wrappedKey,
- const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& 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<uint8_t>& 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<KeyParameter>& params);
-
- void addLegacyBeginParams(const android::String16& name, AuthorizationSet* params);
-
- KeyStoreServiceReturnCode doLegacySignVerify(const android::String16& name,
- const hidl_vec<uint8_t>& data,
- hidl_vec<uint8_t>* out,
- const hidl_vec<uint8_t>& signature,
- KeyPurpose purpose);
-
- /**
- * Adds a Confirmation Token to the key parameters if needed.
- */
- void appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics,
- std::vector<KeyParameter>* params);
-
- sp<KeyStore> 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 <stdint.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <keystore/keystore.h>
-
-/**
- * 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 <assert.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <string.h>
-
-#include <openssl/evp.h>
-
-#include <hardware/hw_auth_token.h>
-#include <log/log.h>
-
-#include <list>
-
-#include <keystore/keystore_hidl_support.h>
-
-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<const HardwareAuthToken&> 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<km_id_t> KeymasterEnforcement::CreateKeyId(const hidl_vec<uint8_t>& 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<int64_t>(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 <typename IntType, uint32_t byteOrder> struct choose_hton;
-
-template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
- inline static IntType hton(const IntType& value) {
- IntType result = 0;
- const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
- unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
- for (int i = sizeof(IntType) - 1; i >= 0; --i) {
- *(outbytes++) = inbytes[i];
- }
- return result;
- }
-};
-
-template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
- inline static IntType hton(const IntType& value) { return value; }
-};
-
-template <typename IntType> inline IntType hton(const IntType& value) {
- return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
-}
-
-template <typename IntType> inline IntType ntoh(const IntType& value) {
- // same operation and hton
- return choose_hton<IntType, __BYTE_ORDER__>::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<int>(auth_set.size()));
- assert(auth_timeout_index < static_cast<int>(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<int>(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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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 <stdio.h>
-
-#include <keystore/keymaster_types.h>
-
-#include <list>
-#include <mutex>
-#include <optional>
-
-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<AccessTime> 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<AccessCount> 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<const HardwareAuthToken&> 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<km_id_t> CreateKeyId(const hidl_vec<uint8_t>& 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 <android-base/logging.h>
-
-#include <log/log_event_list.h>
-
-#include <private/android_logger.h>
-
-#include "KeyStore.h"
-#include "keymaster_enforcement.h"
-
-#include "key_creation_log_handler.h"
-#include "keystore_utils.h"
-
-#include <chrono>
-
-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<std::mutex> 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<std::mutex> 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<std::mutex> 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<Keymaster> 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<KeyStoreServiceReturnCode, Blob>
-KeymasterWorker::upgradeKeyBlob(const LockedKeyBlobEntry& lockedEntry,
- const AuthorizationSet& params) {
- LOG(INFO) << "upgradeKeyBlob " << lockedEntry->alias() << " " << (uint32_t)lockedEntry->uid();
-
- std::tuple<KeyStoreServiceReturnCode, Blob> 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<uint8_t>& 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<KeyStoreServiceReturnCode, KeyCharacteristics, Blob, Blob>
-KeymasterWorker::createKeyCharacteristicsCache(const LockedKeyBlobEntry& lockedEntry,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData, Blob keyBlob,
- Blob charBlob) {
- std::tuple<KeyStoreServiceReturnCode, KeyCharacteristics, Blob, Blob> 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<KeyStoreServiceReturnCode, HardwareAuthToken>
-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<KeyPurpose>(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<IBinder>& token,
- ResponseCode reason_for_abort) {
- auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */,
- static_cast<int32_t>(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<IBinder> 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<IBinder> appToken, Blob keyBlob,
- Blob charBlob, bool pruneable, KeyPurpose purpose,
- AuthorizationSet opParams, hidl_vec<uint8_t> 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<uint8_t> clientId;
- hidl_vec<uint8_t> 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<KeyParameter>& 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<IBinder> 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<Operation> 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<Operation> 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<void()> f_;
-
- public:
- explicit Finalize(std::function<void()> f) : f_(f) {}
- ~Finalize() {
- if (f_) f_();
- }
- void release() { f_ = {}; }
-};
-
-} // namespace
-
-void KeymasterWorker::update(sp<IBinder> token, AuthorizationSet params, hidl_vec<uint8_t> 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<KeyParameter>& outParams,
- const ::std::vector<uint8_t>& 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 <typename ParamsIter>
-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<IBinder> token, AuthorizationSet params, hidl_vec<uint8_t> input,
- hidl_vec<uint8_t> signature, hidl_vec<uint8_t> 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<uint8_t> 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<KeyParameter>& outParams,
- const ::std::vector<uint8_t>& 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<IBinder> 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<KeyParameter> 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<uint8_t> data, addRngEntropy_cb _hidl_cb) {
- addRequest(&Keymaster::addRngEntropy, std::move(_hidl_cb), std::move(data));
-}
-
-namespace {
-bool containsTag(const hidl_vec<KeyParameter>& 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<KeyParameter>& params) {
- return !containsTag(params, Tag::NO_AUTH_REQUIRED);
-}
-} // namespace
-
-void KeymasterWorker::generateKey(LockedKeyBlobEntry lockedEntry, hidl_vec<KeyParameter> keyParams,
- hidl_vec<uint8_t> 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<uint8_t>& 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<KeyParameter> keyParams, generateKey2_cb worker_cb) {
- addRequest(&Keymaster::generateKey, std::move(worker_cb), std::move(keyParams));
-}
-
-void KeymasterWorker::getKeyCharacteristics(LockedKeyBlobEntry lockedEntry,
- hidl_vec<uint8_t> clientId, hidl_vec<uint8_t> 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<KeyParameter> keyParams,
- KeyFormat keyFormat, hidl_vec<uint8_t> 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<uint8_t>& 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<uint8_t> wrappedKeyData,
- hidl_vec<uint8_t> maskingKey,
- hidl_vec<KeyParameter> 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<uint8_t>& 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<uint8_t> clientId, hidl_vec<uint8_t> 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<uint8_t>& 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<uint8_t> keyToAttest, hidl_vec<KeyParameter> attestParams,
- attestKey_cb worker_cb) {
- addRequest(&Keymaster::attestKey, std::move(worker_cb), std::move(keyToAttest),
- std::move(attestParams));
-}
-
-void KeymasterWorker::deleteKey(hidl_vec<uint8_t> keyBlob, deleteKey_cb _hidl_cb) {
- addRequest(&Keymaster::deleteKey, std::move(_hidl_cb), std::move(keyBlob));
-}
-
-void KeymasterWorker::binderDied(android::wp<IBinder> 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 <condition_variable>
-#include <functional>
-#include <keymasterV4_1/Keymaster.h>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <queue>
-#include <thread>
-#include <tuple>
-
-#include <keystore/ExportResult.h>
-#include <keystore/KeyCharacteristics.h>
-#include <keystore/KeymasterBlob.h>
-#include <keystore/OperationResult.h>
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore_return_types.h>
-
-#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 <typename Fn> class NonCopyableFunction;
-
- template <typename Ret, typename... Args> class NonCopyableFunction<Ret(Args...)> {
-
- class NonCopyableFunctionBase {
- public:
- NonCopyableFunctionBase() = default;
- virtual ~NonCopyableFunctionBase() {}
- virtual Ret operator()(Args... args) = 0;
- NonCopyableFunctionBase(const NonCopyableFunctionBase&) = delete;
- NonCopyableFunctionBase& operator=(const NonCopyableFunctionBase&) = delete;
- };
-
- template <typename Fn>
- 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<NonCopyableFunctionBase> f_;
-
- public:
- NonCopyableFunction() = default;
- // NOLINTNEXTLINE(google-explicit-constructor)
- template <typename F> NonCopyableFunction(F f) {
- f_ = std::make_unique<NonCopyableFunctionTypeEraser<F>>(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<void()>;
-
- std::queue<WorkerTask> 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 <typename... Args> struct MakeKeymasterWorkerCB;
-
-template <typename ErrorType, typename... Args>
-struct MakeKeymasterWorkerCB<ErrorType, std::function<void(Args...)>> {
- using type = std::function<void(ErrorType, std::tuple<std::decay_t<Args>...>&&)>;
-};
-
-template <typename ErrorType> struct MakeKeymasterWorkerCB<ErrorType> {
- using type = std::function<void(ErrorType)>;
-};
-
-template <typename... Args>
-using MakeKeymasterWorkerCB_t = typename MakeKeymasterWorkerCB<Args...>::type;
-
-class KeymasterWorker : protected Worker {
- private:
- sp<Keymaster> 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 <typename KMFn, typename ErrorType, typename... Args, size_t... I>
- void unwrap_tuple(KMFn kmfn, std::function<void(ErrorType)> cb,
- const std::tuple<Args...>& tuple, std::index_sequence<I...>) {
- cb(((*keymasterDevice_).*kmfn)(std::get<I>(tuple)...));
- }
-
- template <typename KMFn, typename ErrorType, typename... ReturnTypes, typename... Args,
- size_t... I>
- void unwrap_tuple(KMFn kmfn, std::function<void(ErrorType, std::tuple<ReturnTypes...>&&)> cb,
- const std::tuple<Args...>& tuple, std::index_sequence<I...>) {
- std::tuple<ReturnTypes...> returnValue;
- auto result = ((*keymasterDevice_).*kmfn)(
- std::get<I>(tuple)...,
- [&returnValue](const ReturnTypes&... args) { returnValue = std::make_tuple(args...); });
- cb(std::move(result), std::move(returnValue));
- }
-
- template <typename KMFn, typename ErrorType, typename... Args>
- void addRequest(KMFn kmfn, std::function<void(ErrorType)> cb, Args&&... args) {
- Worker::addRequest([this, kmfn, cb = std::move(cb),
- tuple = std::make_tuple(std::forward<Args>(args)...)]() {
- unwrap_tuple(kmfn, std::move(cb), tuple, std::index_sequence_for<Args...>{});
- });
- }
-
- template <typename KMFn, typename ErrorType, typename... ReturnTypes, typename... Args>
- void addRequest(KMFn kmfn, std::function<void(ErrorType, std::tuple<ReturnTypes...>&&)> cb,
- Args&&... args) {
- Worker::addRequest([this, kmfn, cb = std::move(cb),
- tuple = std::make_tuple(std::forward<Args>(args)...)]() {
- unwrap_tuple(kmfn, std::move(cb), tuple, std::index_sequence_for<Args...>{});
- });
- }
-
- void deleteOldKeyOnUpgrade(const LockedKeyBlobEntry& blobfile, Blob keyBlob);
- std::tuple<KeyStoreServiceReturnCode, Blob>
- upgradeKeyBlob(const LockedKeyBlobEntry& lockedEntry, const AuthorizationSet& params);
- std::tuple<KeyStoreServiceReturnCode, KeyCharacteristics, Blob, Blob>
- createKeyCharacteristicsCache(const LockedKeyBlobEntry& lockedEntry,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& 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<KeyStoreServiceReturnCode, HardwareAuthToken>
- getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle, KeyPurpose purpose,
- bool failOnTokenMissing = true);
-
- KeyStoreServiceReturnCode abort(const sp<IBinder>& token, ResponseCode reason_for_abort);
-
- bool pruneOperation();
-
- KeyStoreServiceReturnCode getOperationAuthTokenIfNeeded(std::shared_ptr<Operation> op);
-
- void appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics,
- hidl_vec<KeyParameter>* params);
-
- public:
- KeymasterWorker(sp<Keymaster> keymasterDevice, KeyStore* keyStore,
- SecurityLevel internalSecurityLevel);
-
- void logIfKeymasterVendorError(ErrorCode ec) const;
-
- using worker_begin_cb = std::function<void(::android::security::keymaster::OperationResult)>;
- void begin(LockedKeyBlobEntry, sp<IBinder> appToken, Blob keyBlob, Blob charBlob,
- bool pruneable, KeyPurpose purpose, AuthorizationSet opParams,
- hidl_vec<uint8_t> entropy, worker_begin_cb worker_cb);
-
- using update_cb = std::function<void(::android::security::keymaster::OperationResult)>;
- void update(sp<IBinder> token, AuthorizationSet params, hidl_vec<uint8_t> data,
- update_cb _hidl_cb);
-
- using finish_cb = std::function<void(::android::security::keymaster::OperationResult)>;
- void finish(sp<IBinder> token, AuthorizationSet params, hidl_vec<uint8_t> input,
- hidl_vec<uint8_t> signature, hidl_vec<uint8_t> entorpy, finish_cb worker_cb);
-
- using abort_cb = std::function<void(KeyStoreServiceReturnCode)>;
- void abort(sp<IBinder> token, abort_cb _hidl_cb);
-
- using getHardwareInfo_cb = MakeKeymasterWorkerCB_t<Return<void>, Keymaster::getHardwareInfo_cb>;
- void getHardwareInfo(getHardwareInfo_cb _hidl_cb);
-
- using getHmacSharingParameters_cb =
- MakeKeymasterWorkerCB_t<Return<void>, Keymaster::getHmacSharingParameters_cb>;
- void getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb);
-
- using computeSharedHmac_cb =
- MakeKeymasterWorkerCB_t<Return<void>, Keymaster::computeSharedHmac_cb>;
- void computeSharedHmac(hidl_vec<HmacSharingParameters> params, computeSharedHmac_cb _hidl_cb);
-
- using verifyAuthorization_cb =
- std::function<void(KeyStoreServiceReturnCode ec, HardwareAuthToken, VerificationToken)>;
- void verifyAuthorization(uint64_t challenge, hidl_vec<KeyParameter> params,
- HardwareAuthToken token, verifyAuthorization_cb _hidl_cb);
-
- using addRngEntropy_cb = MakeKeymasterWorkerCB_t<Return<ErrorCode>>;
- void addRngEntropy(hidl_vec<uint8_t> data, addRngEntropy_cb _hidl_cb);
-
- using generateKey_cb = std::function<void(
- KeyStoreServiceReturnCode, ::android::hardware::keymaster::V4_0::KeyCharacteristics)>;
- void generateKey(LockedKeyBlobEntry, hidl_vec<KeyParameter> keyParams,
- hidl_vec<uint8_t> entropy, int flags, generateKey_cb _hidl_cb);
-
- using generateKey2_cb = MakeKeymasterWorkerCB_t<Return<void>, Keymaster::generateKey_cb>;
- void generateKey(hidl_vec<KeyParameter> keyParams, generateKey2_cb _hidl_cb);
-
- using getKeyCharacteristics_cb = std::function<void(
- KeyStoreServiceReturnCode, ::android::hardware::keymaster::V4_0::KeyCharacteristics)>;
- void getKeyCharacteristics(LockedKeyBlobEntry lockedEntry, hidl_vec<uint8_t> clientId,
- hidl_vec<uint8_t> appData, Blob keyBlob, Blob charBlob,
- getKeyCharacteristics_cb _hidl_cb);
-
- using importKey_cb = std::function<void(
- KeyStoreServiceReturnCode, ::android::hardware::keymaster::V4_0::KeyCharacteristics)>;
- void importKey(LockedKeyBlobEntry lockedEntry, hidl_vec<KeyParameter> params,
- KeyFormat keyFormat, hidl_vec<uint8_t> keyData, int flags,
- importKey_cb _hidl_cb);
-
- using importWrappedKey_cb = std::function<void(
- KeyStoreServiceReturnCode, ::android::hardware::keymaster::V4_0::KeyCharacteristics)>;
- void importWrappedKey(LockedKeyBlobEntry wrappingLockedEntry,
- LockedKeyBlobEntry wrapppedLockedEntry, hidl_vec<uint8_t> wrappedKeyData,
- hidl_vec<uint8_t> maskingKey, hidl_vec<KeyParameter> unwrappingParams,
- Blob wrappingBlob, Blob wrappingCharBlob, uint64_t passwordSid,
- uint64_t biometricSid, importWrappedKey_cb worker_cb);
-
- using exportKey_cb = std::function<void(::android::security::keymaster::ExportResult)>;
- void exportKey(LockedKeyBlobEntry lockedEntry, KeyFormat exportFormat,
- hidl_vec<uint8_t> clientId, hidl_vec<uint8_t> appData, Blob keyBlob,
- Blob charBlob, exportKey_cb _hidl_cb);
-
- using attestKey_cb = MakeKeymasterWorkerCB_t<Return<void>, Keymaster::attestKey_cb>;
- void attestKey(hidl_vec<uint8_t> keyToAttest, hidl_vec<KeyParameter> attestParams,
- attestKey_cb _hidl_cb);
-
- using deleteKey_cb = MakeKeymasterWorkerCB_t<Return<ErrorCode>>;
- void deleteKey(hidl_vec<uint8_t> keyBlob, deleteKey_cb _hidl_cb);
-
- using begin_cb = MakeKeymasterWorkerCB_t<Return<void>, Keymaster::begin_cb>;
- void begin(KeyPurpose purpose, hidl_vec<uint8_t> key, hidl_vec<KeyParameter> inParams,
- HardwareAuthToken authToken, begin_cb _hidl_cb);
-
- void binderDied(android::wp<IBinder> 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 <keystore/ExportResult.h>
-#include <keystore/KeyCharacteristics.h>
-#include <keystore/KeymasterBlob.h>
-#include <keystore/KeymasterCertificateChain.h>
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore_hidl_support.h>
-
-namespace keystore {
-
-// reads byte[]
-hidl_vec<uint8_t> 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<const uint8_t*>(buf), size_t(length));
-}
-
-android::status_t writeKeymasterBlob(const hidl_vec<uint8_t>& blob, android::Parcel* out) {
- int32_t size = int32_t(std::min<size_t>(blob.size(), std::numeric_limits<int32_t>::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<int32_t>& blob, android::Parcel* out) {
-
- int32_t size = int32_t(std::min<size_t>(blob.size(), std::numeric_limits<int32_t>::max()));
-
- auto rc = out->writeInt32(size);
- if (rc != ::android::OK) return rc;
-
- if (!size) return ::android::OK;
-
- return out->write(blob.data(), size);
-}
-
-NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in) {
- // Method must be in sync with KeymasterArgument.java
- if (in.readInt32() == 0) {
- return {};
- }
- KeyParameter result;
-
- Tag tag = static_cast<Tag>(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<KeyParameter> 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<KeyParameter> 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<KeyParameter>& params,
- android::Parcel* out) {
- int32_t size = int32_t(std::min<size_t>(params.size(), std::numeric_limits<int32_t>::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<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel& in) {
- hidl_vec<hidl_vec<uint8_t>> 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<hidl_vec<uint8_t>>& certs,
- android::Parcel* out) {
- int32_t count = int32_t(std::min<size_t>(certs.size(), std::numeric_limits<int32_t>::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 <utility>
-
-#include <binder/Parcel.h>
-
-#include <keystore/keymaster_types.h>
-
-namespace keystore {
-
-template <typename Fn, typename... Args>
-inline auto nullable(Fn fn, const android::Parcel& in, Args&&... args)
- -> NullOr<decltype(fn(in, std::forward<Args>(args)...))> {
- if (in.readInt32() != 1) {
- return {};
- }
-
- return fn(in, std::forward<Args>(args)...);
-}
-template <typename Fn, typename Arg>
-inline android::status_t nullable(Fn fn, const NullOr<Arg>& 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 <typename Fn, typename Arg>
-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>(arg), out);
-}
-
-inline android::status_t nullable(android::Parcel* out) {
- return out->writeInt32(0);
-}
-
-/**
- * makes a copy only if inPlace is false
- */
-hidl_vec<uint8_t> readKeymasterBlob(const android::Parcel& in);
-android::status_t writeKeymasterBlob(const hidl_vec<uint8_t>& blob, android::Parcel* out);
-
-NullOr<hidl_vec<uint8_t>> readBlobAsByteArray(const android::Parcel& in, bool inPlace = true);
-android::status_t writeBlobAsByteArray(const NullOr<const hidl_vec<uint8_t>&>& blob,
- android::Parcel* out);
-
-NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in);
-android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out);
-
-hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in);
-android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params, android::Parcel* out);
-
-hidl_vec<hidl_vec<uint8_t>> 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 <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/types.h>
-#include <vector>
-
-#include <android/security/keystore/IKeystoreService.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-
-#include <keystore/keystore.h>
-
-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 " <name>\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 " <name>\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 " <name> <uid>\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 " <name> <uid>\n", argv[0]); \
- return 1; \
- } \
- std::vector<uint8_t> 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 " <name>\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 " <name>\n", argv[0]); \
- return 1; \
- } \
- std::vector<uint8_t> 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<IKeystoreService>& service, const String16& name, int uid) {
- std::vector<String16> 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<String16>::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<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
- sp<IKeystoreService> service = interface_cast<IKeystoreService>(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 <chrono>
#include <cstdio>
#include <future>
+#include <iomanip>
+#include <iostream>
#include <memory>
#include <string>
#include <vector>
@@ -24,38 +26,56 @@
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
-#include <base/strings/utf_string_conversions.h>
-#include <base/threading/platform_thread.h>
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore_client_impl.h>
-#include <android/hardware/confirmationui/1.0/types.h>
-#include <android/security/BnConfirmationPromptCallback.h>
-#include <android/security/keystore/IKeystoreService.h>
+#include <aidl/android/security/apc/BnConfirmationCallback.h>
+#include <aidl/android/security/apc/IProtectedConfirmation.h>
+#include <aidl/android/system/keystore2/IKeystoreService.h>
+#include <aidl/android/system/keystore2/ResponseCode.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <keymint_support/authorization_set.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
-//#include <keystore/keystore.h>
+#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<int>(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 <command> [options]\n");
printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
@@ -78,52 +98,487 @@ void PrintUsageAndExit() {
exit(1);
}
-std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
- return std::unique_ptr<KeystoreClient>(
- static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
+std::shared_ptr<ks2::IKeystoreService> 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<ks2::IKeystoreSecurityLevel>
+GetSecurityLevelInterface(std::shared_ptr<ks2::IKeystoreService> keystore,
+ keymint::SecurityLevel securitylevel) {
+ std::shared_ptr<ks2::IKeystoreSecurityLevel> 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<ks2::Authorization>& 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<ks2::Authorization>& 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<ks2::Authorization> 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::KeyParameterValue::algorithm>(
+ 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<keymint::KeyParameterValue::integer>(
+ 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::KeyParameterValue::blockMode>(
+ 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::KeyParameterValue::paddingMode>(
+ keymint::PaddingMode::PKCS7);
+ });
+
+ return verified;
+}
+
+bool verifyAuthenticationKeyAttributes(const std::vector<ks2::Authorization> 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::KeyParameterValue::algorithm>(
+ 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<keymint::KeyParameterValue::integer>(
+ 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<keymint::KeyParameterValue::integer>(
+ 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::KeyParameterValue::digest>(
+ keymint::Digest::SHA_2_256);
+ });
+ return verified;
+}
+
+std::variant<int, ks2::KeyEntryResponse>
+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<int>(ks2::ResponseCode::INVALID_ARGUMENT);
+ }
+
+ return keyEntryResponse;
+}
+
+std::variant<int, ks2::KeyEntryResponse>
+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<int>(ks2::ResponseCode::INVALID_ARGUMENT);
+ }
+
+ return keyEntryResponse;
+}
+
+std::variant<int, std::vector<uint8_t>>
+encryptWithAuthentication(const std::string& name, const std::vector<uint8_t>& 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<int>(&encryption_key_result)) {
+ return *error;
+ }
+ auto encryption_key = std::get<ks2::KeyEntryResponse>(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<int>(&authentication_key_result)) {
+ return *error;
+ }
+ auto authentication_key = std::get<ks2::KeyEntryResponse>(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<std::vector<uint8_t>> 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<uint8_t> 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<int>(ks2::ResponseCode::SYSTEM_ERROR);
+ }
+ }
+
+ if (!optCiphertext) {
+ std::cerr << "Encryption succeeded but no ciphertext returned." << std::endl;
+ return static_cast<int>(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<std::vector<uint8_t>> 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<int>(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<int>(ks2::ResponseCode::SYSTEM_ERROR);
+ }
+
+ std::vector<uint8_t> result(reinterpret_cast<const uint8_t*>(resultString.data()),
+ reinterpret_cast<const uint8_t*>(resultString.data()) +
+ resultString.size());
+ return result;
+}
+
+std::variant<int, std::vector<uint8_t>>
+decryptWithAuthentication(const std::string& name, const std::vector<uint8_t>& 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<int>(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<int>(&encryption_key_result)) {
+ return *error;
+ }
+ auto encryption_key = std::get<ks2::KeyEntryResponse>(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<int>(&authentication_key_result)) {
+ return *error;
+ }
+ auto authentication_key = std::get<ks2::KeyEntryResponse>(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<const uint8_t*>(protobuf.init_vector().data());
+ std::vector<uint8_t> toBeVerified(p, p + protobuf.init_vector().size());
+
+ p = reinterpret_cast<const uint8_t*>(protobuf.encrypted_data().data());
+ toBeVerified.insert(toBeVerified.end(), p, p + protobuf.encrypted_data().size());
+
+ p = reinterpret_cast<const uint8_t*>(protobuf.authentication_data().data());
+ std::vector<uint8_t> signature(p, p + protobuf.authentication_data().size());
+
+ std::optional<std::vector<uint8_t>> 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<std::vector<uint8_t>> optPlaintext;
+
+ p = reinterpret_cast<const uint8_t*>(protobuf.encrypted_data().data());
+ std::vector<uint8_t> 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<int>(ks2::ResponseCode::SYSTEM_ERROR);
+ }
+
+ return *optPlaintext;
}
-bool TestKey(const std::string& name, bool required, const AuthorizationSet& parameters) {
- std::unique_ptr<KeystoreClient> 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<keymint::KeyParameter>& 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<TestCase> 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<TestCase>(&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<uint8_t> 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<uint8_t> buffer(reinterpret_cast<const uint8_t*>(content.data()),
+ reinterpret_cast<const uint8_t*>(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<uint8_t>& content) {
base::FilePath path(filename);
int size = content.size();
- if (base::WriteFile(path, content.data(), size) != size) {
+ if (base::WriteFile(path, reinterpret_cast<const char*>(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<KeystoreClient> 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<KeystoreClient> 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<KeystoreClient> 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<KeystoreClient> 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<KeystoreClient> keystore = CreateKeystoreInstance();
- int32_t result = keystore->deleteKey(name).getErrorCode();
- printf("DeleteKey: %d\n", result);
- return result;
-}
+ auto keystore = CreateKeystoreInstance();
-int DeleteAllKeys() {
- std::unique_ptr<KeystoreClient> 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<KeystoreClient> 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<KeystoreClient> keystore = CreateKeystoreInstance();
- std::vector<std::string> key_list;
- if (!keystore->listKeys(prefix, &key_list)) {
- printf("ListKeys failed.\n");
- return 1;
+int List() {
+ auto keystore = CreateKeystoreInstance();
+ std::vector<ks2::KeyDescriptor> 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<android::IServiceManager> sm = android::defaultServiceManager();
- sp<android::IBinder> binder = sm->getService(String16("android.security.keystore"));
- sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(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<uint8_t> data_to_sign{0x64, 0x61, 0x74, 0x61, 0x5f, 0x74,
+ 0x6f, 0x5f, 0x73, 0x69, 0x67, 0x6e};
+ std::optional<std::vector<uint8_t>> 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<int>(ks2::ResponseCode::SYSTEM_ERROR);
}
- return 0;
-}
+ auto signature = std::move(*output_data);
-int SignAndVerify(const std::string& name) {
- std::unique_ptr<KeystoreClient> 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<X509> decoded_cert(d2i_X509(nullptr, &p, (long)cert->size()));
+ bssl::UniquePtr<EVP_PKEY> decoded_pkey(X509_get_pubkey(decoded_cert.get()));
+ bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_new());
+ if (!ctx) {
+ std::cerr << "Failed to created EVP_MD context. << std::endl";
+ return static_cast<int>(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<int>(ks2::ResponseCode::SYSTEM_ERROR);
+ }
+ } else {
+ std::cerr << "No public key to check signature against." << std::endl;
+ return static_cast<int>(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<KeystoreClient> 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<int>(&result)) {
+ std::cerr << "EncryptWithAuthentication failed." << std::endl;
+ return *error;
}
- WriteFile(output_filename, output);
+ WriteFile(output_filename, std::get<std::vector<uint8_t>>(result));
return 0;
}
int Decrypt(const std::string& key_name, const std::string& input_filename,
const std::string& output_filename) {
- std::unique_ptr<KeystoreClient> 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<int>(&result)) {
+ std::cerr << "DecryptWithAuthentication failed." << std::endl;
+ return *error;
}
- WriteFile(output_filename, output);
+ WriteFile(output_filename, std::get<std::vector<uint8_t>>(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<std::tuple<ConfirmationResponseCode, std::vector<uint8_t>>> {
+ : public apc::BnConfirmationCallback,
+ public std::promise<std::tuple<apc::ResponseCode, std::optional<std::vector<uint8_t>>>> {
public:
ConfirmationListener() {}
- virtual ::android::binder::Status
- onConfirmationPromptCompleted(int32_t result,
- const ::std::vector<uint8_t>& dataThatWasConfirmed) override {
- this->set_value({static_cast<ConfirmationResponseCode>(result), dataThatWasConfirmed});
- return ::android::binder::Status::ok();
- }
+ virtual ::ndk::ScopedAStatus
+ onCompleted(::aidl::android::security::apc::ResponseCode result,
+ const std::optional<std::vector<uint8_t>>& 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<android::IServiceManager> sm = android::defaultServiceManager();
- sp<android::IBinder> binder = sm->getService(String16("android.security.keystore"));
- sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(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<ConfirmationListener> listener = new ConfirmationListener();
+ auto listener = std::make_shared<ConfirmationListener>();
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<ConfirmationResponseCode>(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<ConfirmationResponseCode>(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 <future>
-#include <optional>
-#include <string>
-#include <vector>
-
-#include <android/security/keystore/IKeystoreService.h>
-#include <binder/IBinder.h>
-#include <binder/IInterface.h>
-#include <binder/IServiceManager.h>
-#include <keystore/keystore.h>
-#include <log/log.h>
-#include <utils/String16.h>
-#include <utils/String8.h>
-
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore_hidl_support.h>
-#include <keystore/keystore_promises.h>
-
-#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<android::security::keystore::IKeystoreService>(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<KeystoreResponsePromise> 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<KeyCharacteristicsPromise> 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<uint8_t>() /* 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<KeyParameter> -> 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<KeyCharacteristicsPromise> 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<KeyParameter> -> 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<KeyCharacteristicsPromise> 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<KeyParameter> -> 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<KeystoreExportPromise> 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<android::IBinder> token(new android::BBinder);
- String16 key_name16(key_name.data(), key_name.size());
- int32_t error_code;
- android::sp<OperationResultPromise> 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<uint8_t>() /* 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<OperationResultPromise> 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<OperationResultPromise> 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<uint8_t>)hidlInput, (std::vector<uint8_t>)hidlSignature, hidl_vec<uint8_t>(),
- &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<KeystoreResponsePromise> 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<int32_t>(ResponseCode::NO_ERROR);
-}
-
-bool KeystoreClientImpl::listKeys(const std::string& prefix,
- std::vector<std::string>* key_name_list) {
- return listKeysOfUid(prefix, kDefaultUID, key_name_list);
-}
-
-bool KeystoreClientImpl::listKeysOfUid(const std::string& prefix, int uid,
- std::vector<std::string>* 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<std::vector<uint8_t>> KeystoreClientImpl::getKey(const std::string& alias, int uid) {
- String16 alias16(alias.data(), alias.size());
- std::vector<uint8_t> 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 <android-base/logging.h>
-#include <android/hidl/manager/1.2/IServiceManager.h>
-#include <android/security/keystore/IKeystoreService.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <keymasterV4_1/Keymaster3.h>
-#include <keymasterV4_1/Keymaster4.h>
-#include <utils/StrongPointer.h>
-
-#include <keystore/keystore_hidl_support.h>
-#include <keystore/keystore_return_types.h>
-
-#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 <typename Wrapper>
-KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) {
- KeymasterDevices result;
- serviceManager->listManifestByInterface(
- Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& 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<Keymaster> 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<uint32_t>(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<Keymaster4>(serviceManager.get());
- auto softKeymaster = result[SecurityLevel::SOFTWARE];
- if (!result[SecurityLevel::TRUSTED_ENVIRONMENT]) {
- result = enumerateKeymasterDevices<Keymaster3>(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::KeyStore> keyStore(
- new keystore::KeyStore(kmDevices, minimalAllowedSecurityLevelForNewKeys));
- keyStore->initialize();
- android::sp<android::IServiceManager> sm = android::defaultServiceManager();
- android::sp<keystore::KeyStoreService> 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 <log/log.h>
-
-#include <hardware/keymaster2.h>
-#include <hardware/keymaster_defs.h>
-#include <keymaster/keymaster_configuration.h>
-#include <keymaster/soft_keymaster_device.h>
-
-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<KeyParameter>& 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<KeyParameter>& params) {
- return KmParamSet(params);
-}
-
-inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec<uint8_t>& 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<uint8_t>& blob) {
- /* hidl unmarshals funny pointers if the the blob is empty */
- if (blob.size()) return {&blob[0], blob.size()};
- return {};
-}
-
-inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
- if (blob.key_material == nullptr || blob.key_material_size == 0) {
- return {};
- } else {
- return hidl_vec<uint8_t>(blob.key_material, blob.key_material + blob.key_material_size);
- }
-}
-inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
- if (blob.data == nullptr || blob.data_length == 0) {
- return {};
- } else {
- return hidl_vec<uint8_t>(blob.data, blob.data + blob.data_length);
- }
-}
-
-inline static hidl_vec<hidl_vec<uint8_t>>
-kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) {
- hidl_vec<hidl_vec<uint8_t>> 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<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
- hidl_vec<KeyParameter> 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<void> LegacyKeymasterDeviceWrapper::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
- _hidl_cb(false, false, false, false, false, "Fallback Device", "Google Android Security");
- return Void();
-}
-
-Return<ErrorCode> LegacyKeymasterDeviceWrapper::addRngEntropy(const hidl_vec<uint8_t>& data) {
- return legacy_enum_conversion(
- keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));
-}
-
-Return<void> LegacyKeymasterDeviceWrapper::generateKey(const hidl_vec<KeyParameter>& keyParams,
- generateKey_cb _hidl_cb) {
- // result variables for the wire
- KeyCharacteristics resultCharacteristics;
- hidl_vec<uint8_t> 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<uint8_t*>(key_blob.key_material));
- keymaster_free_characteristics(&key_characteristics);
-
- return Void();
-}
-
-Return<void> LegacyKeymasterDeviceWrapper::getKeyCharacteristics(
- const hidl_vec<uint8_t>& keyBlob, const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& 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<void> LegacyKeymasterDeviceWrapper::importKey(const hidl_vec<KeyParameter>& params,
- KeyFormat keyFormat,
- const hidl_vec<uint8_t>& keyData,
- importKey_cb _hidl_cb) {
- // result variables for the wire
- KeyCharacteristics resultCharacteristics;
- hidl_vec<uint8_t> 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<uint8_t*>(key_blob.key_material));
- keymaster_free_characteristics(&key_characteristics);
-
- return Void();
-}
-
-Return<void> LegacyKeymasterDeviceWrapper::exportKey(KeyFormat exportFormat,
- const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData,
- exportKey_cb _hidl_cb) {
-
- // result variables for the wire
- hidl_vec<uint8_t> 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<uint8_t*>(out_blob.data));
-
- return Void();
-}
-
-Return<void> LegacyKeymasterDeviceWrapper::attestKey(const hidl_vec<uint8_t>& keyToAttest,
- const hidl_vec<KeyParameter>& attestParams,
- attestKey_cb _hidl_cb) {
-
- hidl_vec<hidl_vec<uint8_t>> 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<void> LegacyKeymasterDeviceWrapper::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
- const hidl_vec<KeyParameter>& upgradeParams,
- upgradeKey_cb _hidl_cb) {
-
- // result variables for the wire
- hidl_vec<uint8_t> 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<uint8_t*>(key_blob.key_material));
-
- return Void();
-}
-
-Return<ErrorCode> LegacyKeymasterDeviceWrapper::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
- auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
- return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
-}
-
-Return<ErrorCode> LegacyKeymasterDeviceWrapper::deleteAllKeys() {
- return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
-}
-
-Return<ErrorCode> LegacyKeymasterDeviceWrapper::destroyAttestationIds() {
- return ErrorCode::UNIMPLEMENTED;
-}
-
-Return<void> LegacyKeymasterDeviceWrapper::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
- const hidl_vec<KeyParameter>& inParams,
- begin_cb _hidl_cb) {
-
- // result variables for the wire
- hidl_vec<KeyParameter> 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<void> LegacyKeymasterDeviceWrapper::update(uint64_t operationHandle,
- const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input,
- update_cb _hidl_cb) {
- // result variables for the wire
- uint32_t resultConsumed = 0;
- hidl_vec<KeyParameter> resultParams;
- hidl_vec<uint8_t> 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<uint8_t*>(out_blob.data));
-
- return Void();
-}
-
-Return<void> LegacyKeymasterDeviceWrapper::finish(uint64_t operationHandle,
- const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input,
- const hidl_vec<uint8_t>& signature,
- finish_cb _hidl_cb) {
- // result variables for the wire
- hidl_vec<KeyParameter> resultParams;
- hidl_vec<uint8_t> 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<uint8_t*>(out_blob.data));
-
- return Void();
-}
-
-Return<ErrorCode> LegacyKeymasterDeviceWrapper::abort(uint64_t operationHandle) {
- return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
-}
-
-sp<IKeymasterDevice> 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 <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-#include <hidl/Status.h>
-#include <hidl/MQDescriptor.h>
-
-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<void> getHardwareFeatures(getHardwareFeatures_cb _hidl_cb);
- Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
- Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
- generateKey_cb _hidl_cb) override;
- Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData,
- getKeyCharacteristics_cb _hidl_cb) override;
- Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
- const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
- Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
- exportKey_cb _hidl_cb) override;
- Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
- const hidl_vec<KeyParameter>& attestParams,
- attestKey_cb _hidl_cb) override;
- Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
- const hidl_vec<KeyParameter>& upgradeParams,
- upgradeKey_cb _hidl_cb) override;
- Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
- Return<ErrorCode> deleteAllKeys() override;
- Return<ErrorCode> destroyAttestationIds() override;
- Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
- const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) override;
- Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input, update_cb _hidl_cb) override;
- Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
- finish_cb _hidl_cb) override;
- Return<ErrorCode> abort(uint64_t operationHandle) override;
-
- private:
- keymaster2_device_t* keymaster_device_;
-};
-
-sp<IKeymasterDevice> 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 <algorithm>
-#include <android-base/logging.h>
-#include <mutex>
-
-namespace keystore {
-
-OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
- : mDeathRecipient(deathRecipient) {}
-
-sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
- const sp<Keymaster>& dev, const sp<IBinder>& appToken,
- KeyCharacteristics&& characteristics,
- const hidl_vec<KeyParameter>& params, bool pruneable) {
- sp<IBinder> token = new ::android::BBinder();
- mMap.emplace(token, std::make_shared<Operation>(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<Operation> OperationMap::getOperation(const sp<IBinder>& token) {
- auto entry = mMap.find(token);
- if (entry == mMap.end()) return {};
-
- auto op = entry->second;
-
- updateLru(token);
- return op;
-}
-
-void OperationMap::updateLru(const sp<IBinder>& token) {
- auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
- if (lruEntry != mLru.end()) {
- mLru.erase(lruEntry);
- mLru.push_back(token);
- }
-}
-
-std::shared_ptr<Operation> OperationMap::removeOperation(const sp<IBinder>& 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<IBinder>& token, const sp<IBinder>& 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<IBinder> OperationMap::getOldestPruneableOperation() {
- if (mLru.size() == 0) return {};
-
- return {mLru.front()};
-}
-
-std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& 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 <list>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <vector>
-
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <utils/StrongPointer.h>
-
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore_concurrency.h>
-#include <keystore/keystore_hidl_support.h>
-
-#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<IBinder> addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
- const sp<Keymaster>& dev, const sp<IBinder>& appToken,
- KeyCharacteristics&& characteristics,
- const hidl_vec<KeyParameter>& params, bool pruneable);
- std::shared_ptr<Operation> getOperation(const sp<IBinder>& token);
- std::shared_ptr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful,
- int32_t responseCode);
- size_t getOperationCount() const { return mMap.size(); }
- sp<IBinder> getOldestPruneableOperation();
- std::vector<sp<IBinder>> getOperationsForToken(const sp<IBinder>& appToken);
-
- private:
- void updateLru(const sp<IBinder>& token);
- void removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken);
-
- std::map<sp<IBinder>, std::shared_ptr<Operation>> mMap;
- std::list<sp<IBinder>> mLru;
- std::map<sp<IBinder>, std::vector<sp<IBinder>>> 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 <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <utils/StrongPointer.h>
-
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore_hidl_support.h>
-#include <keystore/keystore_return_types.h>
-
-#include <future>
-
-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<Keymaster>& device_,
- KeyCharacteristics&& characteristics_, sp<IBinder> appToken_,
- const hidl_vec<KeyParameter> 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<Keymaster> device;
- KeyCharacteristics characteristics;
- sp<IBinder> appToken;
- std::promise<KeyStoreServiceReturnCode> authTokenPromise;
- std::future<KeyStoreServiceReturnCode> authTokenFuture;
- HardwareAuthToken authToken;
- VerificationToken verificationToken;
- const hidl_vec<KeyParameter> 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 <cutils/sockets.h>
-#include <log/log.h>
-#include <private/android_filesystem_config.h>
-
-#include <selinux/android.h>
-
-#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<perm_t>((uint32_t)(~0))},
- {AID_VPN, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
- {AID_WIFI, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
- {AID_BLUETOOTH, static_cast<perm_t>(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<perm_t>((uint32_t)(~0))},
-#else
- {AID_ROOT, static_cast<perm_t>(P_GET)},
-#endif
-};
-
-static const perm_t DEFAULT_PERMS = static_cast<perm_t>(
- 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<struct audit_data*>(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<void*>(&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 <unistd.h>
-
-/* 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 <alias>_KEYSTOREGRANT_<random_grant_no_>. 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 <android/hardware/confirmationui/1.0/types.h>
-#include <android/security/BnConfirmationPromptCallback.h>
-#include <android/security/keystore/IKeystoreService.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
+#include <aidl/android/security/apc/BnConfirmationCallback.h>
+#include <aidl/android/security/apc/IProtectedConfirmation.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include <gtest/gtest.h>
@@ -28,65 +27,50 @@
#include <tuple>
#include <vector>
-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<std::tuple<ConfirmationResponseCode, std::vector<uint8_t>>> {
+ : public apc::BnConfirmationCallback,
+ public std::promise<std::tuple<apc::ResponseCode, std::optional<std::vector<uint8_t>>>> {
public:
ConfirmationListener() {}
- virtual ::android::binder::Status
- onConfirmationPromptCompleted(int32_t result,
- const ::std::vector<uint8_t>& dataThatWasConfirmed) override {
- this->set_value({static_cast<ConfirmationResponseCode>(result), dataThatWasConfirmed});
- return ::android::binder::Status::ok();
- }
+ virtual ::ndk::ScopedAStatus
+ onCompleted(::aidl::android::security::apc::ResponseCode result,
+ const std::optional<std::vector<uint8_t>>& dataConfirmed) override {
+ this->set_value({result, dataConfirmed});
+ return ::ndk::ScopedAStatus::ok();
+ };
};
TEST(ConfirmationInvocationTest, InvokeAndCancel) {
- android::ProcessState::self()->startThreadPool();
+ ABinderProcess_startThreadPool();
- sp<IServiceManager> sm = android::defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
- sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(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<uint8_t> extraData{0xaa, 0xff, 0x00, 0x55};
- sp<ConfirmationListener> listener = new ConfirmationListener();
+ auto listener = std::make_shared<ConfirmationListener>();
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<ConfirmationResponseCode>(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<ConfirmationResponseCode>(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);
}