[automerger skipped] Fix keystore wifi concurrency issue. am: 1d898d107c -s ours am: e583877904 -s ours
am: 7ba3854d5d -s ours
am skip reason: change_id I8c5602d2c2cb1dd9423df713037e99b247cee71f with SHA1 1849841b48 is in history
Change-Id: I01d77417e1400b7c7d4547920478c052826dce27
diff --git a/keystore/.clang-format b/.clang-format
similarity index 100%
copy from keystore/.clang-format
copy to .clang-format
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..b44c296
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1 @@
+subdirs = ["*"]
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..c8dbf77
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,5 @@
+[Builtin Hooks]
+clang_format = true
+
+[Builtin Hooks Options]
+clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
diff --git a/keystore/.clang-format b/keystore-engine/.clang-format
similarity index 100%
rename from keystore/.clang-format
rename to keystore-engine/.clang-format
diff --git a/keystore-engine/Android.mk b/keystore-engine/Android.mk
index 8988857..c995dfc 100644
--- a/keystore-engine/Android.mk
+++ b/keystore-engine/Android.mk
@@ -30,6 +30,7 @@
libcrypto \
libcutils \
libhidlbase \
+ libkeystore_aidl \
libkeystore_binder \
liblog \
libutils
diff --git a/keystore-engine/android_engine.cpp b/keystore-engine/android_engine.cpp
index 368590c..bb0356b 100644
--- a/keystore-engine/android_engine.cpp
+++ b/keystore-engine/android_engine.cpp
@@ -48,8 +48,8 @@
#endif
namespace {
-extern const RSA_METHOD keystore_rsa_method;
-extern const ECDSA_METHOD keystore_ecdsa_method;
+KeystoreBackend *g_keystore_backend;
+void ensure_keystore_engine();
/* key_id_dup is called when one of the RSA or EC_KEY objects is duplicated. */
int key_id_dup(CRYPTO_EX_DATA* /* to */,
@@ -76,60 +76,6 @@
free(key_id);
}
-/* KeystoreEngine is a BoringSSL ENGINE that implements RSA and ECDSA by
- * forwarding the requested operations to Keystore. */
-class KeystoreEngine {
- public:
- KeystoreEngine()
- : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
- NULL /* argp */,
- NULL /* new_func */,
- key_id_dup,
- key_id_free)),
- ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
- NULL /* argp */,
- NULL /* new_func */,
- key_id_dup,
- key_id_free)),
- engine_(ENGINE_new()) {
- ENGINE_set_RSA_method(
- engine_, &keystore_rsa_method, sizeof(keystore_rsa_method));
- ENGINE_set_ECDSA_method(
- engine_, &keystore_ecdsa_method, sizeof(keystore_ecdsa_method));
- }
-
- int rsa_ex_index() const { return rsa_index_; }
- int ec_key_ex_index() const { return ec_key_index_; }
-
- const ENGINE* engine() const { return engine_; }
-
- private:
- const int rsa_index_;
- const int ec_key_index_;
- ENGINE* const engine_;
-};
-
-pthread_once_t g_keystore_engine_once = PTHREAD_ONCE_INIT;
-KeystoreEngine *g_keystore_engine;
-KeystoreBackend *g_keystore_backend;
-
-/* init_keystore_engine is called to initialize |g_keystore_engine|. This
- * should only be called by |pthread_once|. */
-void init_keystore_engine() {
- g_keystore_engine = new KeystoreEngine;
-#ifndef BACKEND_WIFI_HIDL
- g_keystore_backend = new KeystoreBackendBinder;
-#else
- g_keystore_backend = new KeystoreBackendHidl;
-#endif
-}
-
-/* ensure_keystore_engine ensures that |g_keystore_engine| is pointing to a
- * valid |KeystoreEngine| object and creates one if not. */
-void ensure_keystore_engine() {
- pthread_once(&g_keystore_engine_once, init_keystore_engine);
-}
-
/* Many OpenSSL APIs take ownership of an argument on success but don't free
* the argument on failure. This means we need to tell our scoped pointers when
* we've transferred ownership, without triggering a warning by not using the
@@ -137,10 +83,7 @@
#define OWNERSHIP_TRANSFERRED(obj) \
typeof ((obj).release()) _dummy __attribute__((unused)) = (obj).release()
-const char* rsa_get_key_id(const RSA* rsa) {
- return reinterpret_cast<char*>(
- RSA_get_ex_data(rsa, g_keystore_engine->rsa_ex_index()));
-}
+const char* rsa_get_key_id(const RSA* rsa);
/* rsa_private_transform takes a big-endian integer from |in|, calculates the
* d'th power of it, modulo the RSA modulus, and writes the result as a
@@ -194,33 +137,7 @@
return 1;
}
-const struct rsa_meth_st keystore_rsa_method = {
- {
- 0 /* references */,
- 1 /* is_static */,
- },
- NULL /* app_data */,
-
- NULL /* init */,
- NULL /* finish */,
-
- NULL /* size */,
-
- NULL /* sign */,
-
- NULL /* encrypt */,
- NULL /* sign_raw */,
- NULL /* decrypt */,
-
- rsa_private_transform,
-
- RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_OPAQUE,
-};
-
-const char* ecdsa_get_key_id(const EC_KEY* ec_key) {
- return reinterpret_cast<char*>(
- EC_KEY_get_ex_data(ec_key, g_keystore_engine->ec_key_ex_index()));
-}
+const char* ecdsa_get_key_id(const EC_KEY* ec_key);
/* ecdsa_sign signs |digest_len| bytes from |digest| with |ec_key| and writes
* the resulting signature (an ASN.1 encoded blob) to |sig|. It returns one on
@@ -263,20 +180,78 @@
return 1;
}
-const ECDSA_METHOD keystore_ecdsa_method = {
- {
- 0 /* references */,
- 1 /* is_static */
- } /* common */,
- NULL /* app_data */,
+/* KeystoreEngine is a BoringSSL ENGINE that implements RSA and ECDSA by
+ * forwarding the requested operations to Keystore. */
+class KeystoreEngine {
+ public:
+ KeystoreEngine()
+ : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
+ NULL /* argp */,
+ NULL /* new_func */,
+ key_id_dup,
+ key_id_free)),
+ ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
+ NULL /* argp */,
+ NULL /* new_func */,
+ key_id_dup,
+ key_id_free)),
+ engine_(ENGINE_new()) {
+ memset(&rsa_method_, 0, sizeof(rsa_method_));
+ rsa_method_.common.is_static = 1;
+ rsa_method_.private_transform = rsa_private_transform;
+ rsa_method_.flags = RSA_FLAG_OPAQUE;
+ ENGINE_set_RSA_method(engine_, &rsa_method_, sizeof(rsa_method_));
- NULL /* init */,
- NULL /* finish */,
- NULL /* group_order_size */,
- ecdsa_sign,
- ECDSA_FLAG_OPAQUE,
+ memset(&ecdsa_method_, 0, sizeof(ecdsa_method_));
+ ecdsa_method_.common.is_static = 1;
+ ecdsa_method_.sign = ecdsa_sign;
+ ecdsa_method_.flags = ECDSA_FLAG_OPAQUE;
+ ENGINE_set_ECDSA_method(engine_, &ecdsa_method_, sizeof(ecdsa_method_));
+ }
+
+ int rsa_ex_index() const { return rsa_index_; }
+ int ec_key_ex_index() const { return ec_key_index_; }
+
+ const ENGINE* engine() const { return engine_; }
+
+ private:
+ const int rsa_index_;
+ const int ec_key_index_;
+ RSA_METHOD rsa_method_;
+ ECDSA_METHOD ecdsa_method_;
+ ENGINE* const engine_;
};
+pthread_once_t g_keystore_engine_once = PTHREAD_ONCE_INIT;
+KeystoreEngine *g_keystore_engine;
+
+/* init_keystore_engine is called to initialize |g_keystore_engine|. This
+ * should only be called by |pthread_once|. */
+void init_keystore_engine() {
+ g_keystore_engine = new KeystoreEngine;
+#ifndef BACKEND_WIFI_HIDL
+ g_keystore_backend = new KeystoreBackendBinder;
+#else
+ g_keystore_backend = new KeystoreBackendHidl;
+#endif
+}
+
+/* ensure_keystore_engine ensures that |g_keystore_engine| is pointing to a
+ * valid |KeystoreEngine| object and creates one if not. */
+void ensure_keystore_engine() {
+ pthread_once(&g_keystore_engine_once, init_keystore_engine);
+}
+
+const char* rsa_get_key_id(const RSA* rsa) {
+ return reinterpret_cast<char*>(
+ RSA_get_ex_data(rsa, g_keystore_engine->rsa_ex_index()));
+}
+
+const char* ecdsa_get_key_id(const EC_KEY* ec_key) {
+ return reinterpret_cast<char*>(
+ EC_KEY_get_ex_data(ec_key, g_keystore_engine->ec_key_ex_index()));
+}
+
struct EVP_PKEY_Delete {
void operator()(EVP_PKEY* p) const {
EVP_PKEY_free(p);
diff --git a/keystore-engine/keystore_backend_binder.cpp b/keystore-engine/keystore_backend_binder.cpp
index dce8242..f9e7be0 100644
--- a/keystore-engine/keystore_backend_binder.cpp
+++ b/keystore-engine/keystore_backend_binder.cpp
@@ -22,11 +22,12 @@
#include "keystore_backend_binder.h"
+#include <android/security/IKeystoreService.h>
#include <binder/IServiceManager.h>
#include <keystore/keystore.h>
-#include <keystore/IKeystoreService.h>
#include <keystore/keystore_hidl_support.h>
+using android::security::IKeystoreService;
using namespace android;
using keystore::blob2hidlVec;
using keystore::hidl_vec;
@@ -35,9 +36,8 @@
const char keystore_service_name[] = "android.security.keystore";
};
-int32_t KeystoreBackendBinder::sign(
- const char *key_id, const uint8_t* in, size_t len, uint8_t** reply,
- size_t* reply_len) {
+int32_t KeystoreBackendBinder::sign(const char* key_id, const uint8_t* in, size_t len,
+ uint8_t** reply, size_t* reply_len) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16(keystore_service_name));
sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
@@ -47,20 +47,21 @@
return -1;
}
- auto inBlob = blob2hidlVec(in ,len);
- hidl_vec<uint8_t> reply_vec;
+ auto inBlob = blob2hidlVec(in, len);
+ std::vector<uint8_t> reply_vec;
auto ret = service->sign(String16(key_id), inBlob, &reply_vec);
if (!ret.isOk()) {
return -1;
}
- *reply = reply_vec.releaseData();
+ hidl_vec<uint8_t> reply_hidl(reply_vec); // makes copy
+ *reply = reply_hidl.releaseData();
*reply_len = reply_vec.size();
return 0;
}
-int32_t KeystoreBackendBinder::get_pubkey(
- const char *key_id, uint8_t** pubkey, size_t* pubkey_len) {
+int32_t KeystoreBackendBinder::get_pubkey(const char* key_id, uint8_t** pubkey,
+ size_t* pubkey_len) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16(keystore_service_name));
sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
@@ -70,13 +71,14 @@
return -1;
}
- hidl_vec<uint8_t> pubkey_vec;
+ std::vector<uint8_t> pubkey_vec;
auto ret = service->get_pubkey(String16(key_id), &pubkey_vec);
if (!ret.isOk()) {
return -1;
}
- *pubkey = pubkey_vec.releaseData();
+ hidl_vec<uint8_t> hidl_pubkey(pubkey_vec); // makes copy
+ *pubkey = hidl_pubkey.releaseData(); // caller should clean up memory.
*pubkey_len = pubkey_vec.size();
return 0;
}
diff --git a/keystore/Android.bp b/keystore/Android.bp
new file mode 100644
index 0000000..8d095e1
--- /dev/null
+++ b/keystore/Android.bp
@@ -0,0 +1,296 @@
+cc_defaults {
+ name: "keystore_defaults",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wunused",
+ ],
+
+ sanitize: {
+ misc_undefined: ["integer"],
+ },
+
+ clang: true,
+}
+
+cc_binary {
+ name: "keystore",
+ defaults: ["keystore_defaults"],
+
+ srcs: [
+ ":IKeyAttestationApplicationIdProvider.aidl",
+ "KeyStore.cpp",
+ "auth_token_table.cpp",
+ "blob.cpp",
+ "confirmation_manager.cpp",
+ "grant_store.cpp",
+ "key_config.proto",
+ "key_proto_handler.cpp",
+ "key_store_service.cpp",
+ "keyblob_utils.cpp",
+ "keymaster_enforcement.cpp",
+ "keystore_attestation_id.cpp",
+ "keystore_main.cpp",
+ "keystore_utils.cpp",
+ "legacy_keymaster_device_wrapper.cpp",
+ "operation.cpp",
+ "operation_config.proto",
+ "operation_proto_handler.cpp",
+ "permissions.cpp",
+ "user_state.cpp",
+ ],
+ shared_libs: [
+ "android.hardware.confirmationui@1.0",
+ "android.hardware.keymaster@3.0",
+ "android.hardware.keymaster@4.0",
+ "android.system.wifi.keystore@1.0",
+ "libbase",
+ "libbinder",
+ "libcrypto",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "libkeymaster4support",
+ "libkeymaster_messages",
+ "libkeymaster_portable",
+ "libkeystore_aidl",
+ "libkeystore_binder",
+ "libkeystore_parcelables",
+ "liblog",
+ "libprotobuf-cpp-lite",
+ "libselinux",
+ "libservices",
+ "libsoftkeymasterdevice",
+ "libutils",
+ "libwifikeystorehal",
+ ],
+ 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"],
+ tags: ["debug"],
+
+ srcs: ["keystore_cli.cpp"],
+ shared_libs: [
+ "android.hardware.keymaster@4.0",
+ "libbinder",
+ "libcrypto",
+ "libcutils",
+ "libhidlbase",
+ "libhwbinder",
+ "libkeystore_aidl", // for IKeyStoreService.asInterface()
+ "libkeystore_binder",
+ "libkeystore_parcelables",
+ "liblog",
+ "libutils",
+ ],
+}
+
+cc_binary {
+ name: "keystore_cli_v2",
+ defaults: ["keystore_defaults"],
+ tags: ["debug"],
+
+ cflags: [
+ "-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",
+ "libhwbinder",
+ "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: [
+ "KeyAttestationApplicationId.cpp",
+ "KeyAttestationPackageInfo.cpp",
+ "KeymasterArguments.cpp",
+ "KeystoreArguments.cpp",
+ "OperationResult.cpp",
+ "Signature.cpp",
+ "keystore_aidl_hidl_marshalling_utils.cpp",
+ ],
+ shared_libs: [
+ "android.hardware.keymaster@4.0",
+ "libbinder",
+ "libhardware",
+ "libhidlbase",
+ "libhwbinder",
+ "libkeymaster4support",
+ "liblog",
+ "libprotobuf-cpp-lite",
+ "libutils",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.keymaster@4.0",
+ "libbinder",
+ "libhidlbase",
+ "libhwbinder",
+ "libkeymaster4support",
+ ],
+}
+// Library for keystore clients
+cc_library_shared {
+ name: "libkeystore_binder",
+ defaults: ["keystore_defaults"],
+
+ srcs: [
+ "keyblob_utils.cpp",
+ "keystore_client.proto",
+ "keystore_client_impl.cpp",
+ "keystore_get.cpp",
+ ],
+ shared_libs: [
+ "android.hardware.keymaster@4.0",
+ "libbinder",
+ "libhidlbase",
+ "libhwbinder",
+ "libkeymaster4support",
+ "libkeystore_aidl",
+ "libkeystore_parcelables",
+ "liblog",
+ "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",
+ "libhwbinder",
+ "libkeystore_aidl",
+ "libkeystore_parcelables",
+ ],
+}
+
+// Library for keystore clients using the WiFi HIDL interface
+cc_library_shared {
+ name: "libkeystore-wifi-hidl",
+ defaults: ["keystore_defaults"],
+
+ srcs: ["keystore_get_wifi_hidl.cpp"],
+ shared_libs: [
+ "android.system.wifi.keystore@1.0",
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+
+ export_include_dirs: ["include"],
+
+ vendor: true,
+}
+
+// Library for unit tests
+cc_library_static {
+ name: "libkeystore_test",
+ defaults: ["keystore_defaults"],
+
+ srcs: [
+ "auth_token_table.cpp",
+ ],
+ cflags: [ "-O0", ],
+ static_libs: ["libgtest_main"],
+ shared_libs: [
+ "android.hardware.keymaster@4.0",
+ "libhidlbase",
+ "libhwbinder",
+ "libkeymaster4support",
+ "libutils",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.keymaster@4.0",
+ "libhidlbase",
+ "libhwbinder",
+ "libkeymaster4support",
+ ],
+
+ export_include_dirs: ["include"],
+}
+
+filegroup {
+ name: "keystore_aidl",
+ srcs: [
+ "binder/android/security/IConfirmationPromptCallback.aidl",
+ "binder/android/security/IKeystoreService.aidl",
+ ],
+}
+
+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",
+ "libhidltransport",
+ "libhwbinder",
+ "libkeystore_parcelables",
+ "liblog",
+ "libselinux",
+ "libutils",
+ ],
+ export_shared_lib_headers: [
+ "libbinder",
+ "libkeystore_parcelables",
+ ],
+}
+
+subdirs = ["tests"]
diff --git a/keystore/Android.mk b/keystore/Android.mk
deleted file mode 100644
index 7dd5aef..0000000
--- a/keystore/Android.mk
+++ /dev/null
@@ -1,195 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-# This has to be lazy-resolved because it depends on the LOCAL_MODULE_CLASS
-# which varies depending on what is being built.
-define keystore_proto_include
-$(call local-generated-sources-dir)/proto/$(LOCAL_PATH)
-endef
-
-ifneq ($(TARGET_BUILD_PDK),true)
-include $(CLEAR_VARS)
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
-LOCAL_SRC_FILES := \
- auth_token_table.cpp \
- blob.cpp \
- entropy.cpp \
- key_store_service.cpp \
- keystore_attestation_id.cpp \
- keyblob_utils.cpp \
- keystore.cpp \
- keystore_main.cpp \
- keystore_utils.cpp \
- legacy_keymaster_device_wrapper.cpp \
- keymaster_enforcement.cpp \
- operation.cpp \
- permissions.cpp \
- user_state.cpp \
- grant_store.cpp \
- ../../../frameworks/base/core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libcutils \
- libcrypto \
- libhardware \
- libwifikeystorehal \
- libkeystore_binder \
- liblog \
- libsoftkeymaster \
- libutils \
- libselinux \
- libsoftkeymasterdevice \
- libkeymaster_messages \
- libkeymaster_portable \
- libkeymaster_staging \
- libhwbinder \
- libhidlbase \
- libhidltransport \
- android.hardware.keymaster@3.0 \
- android.system.wifi.keystore@1.0
-LOCAL_HEADER_LIBRARIES := libbase_headers
-LOCAL_MODULE := keystore
-LOCAL_MODULE_TAGS := optional
-LOCAL_INIT_RC := keystore.rc
-LOCAL_C_INCLUES := system/keymaster/
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_AIDL_INCLUDES := frameworks/base/core/java/
-include $(BUILD_EXECUTABLE)
-endif
-
-include $(CLEAR_VARS)
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_CFLAGS := -Wall -Wextra -Werror
-LOCAL_SRC_FILES := keystore_cli.cpp
-LOCAL_SHARED_LIBRARIES := libcutils libcrypto libkeystore_binder libutils liblog libbinder \
- libhwbinder \
- libhidlbase \
- android.hardware.keymaster@3.0
-LOCAL_MODULE := keystore_cli
-LOCAL_MODULE_TAGS := debug
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_CFLAGS := -Wall -Wextra -Werror -Wno-unused-parameter -DKEYMASTER_NAME_TAGS
-LOCAL_SRC_FILES := keystore_cli_v2.cpp
-LOCAL_SHARED_LIBRARIES := \
- libchrome \
- libkeystore_binder \
- libhwbinder \
- libhidlbase \
- android.hardware.keymaster@3.0
-
-LOCAL_MODULE := keystore_cli_v2
-LOCAL_MODULE_TAGS := debug
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include external/gtest/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_EXECUTABLE)
-
-# Library for keystore clients
-include $(CLEAR_VARS)
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_CFLAGS := -Wall -Wextra -Werror
-LOCAL_SRC_FILES := \
- IKeystoreService.cpp \
- KeyAttestationApplicationId.cpp \
- KeyAttestationPackageInfo.cpp \
- Signature.cpp \
- keyblob_utils.cpp \
- keystore_client.proto \
- keystore_client_impl.cpp \
- keystore_get.cpp \
- authorization_set.cpp \
- keystore_tags_utils.cpp \
- keystore_aidl_hidl_marshalling_utils.cpp
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- liblog \
- libprotobuf-cpp-lite \
- libutils \
- libhwbinder \
- libhidlbase \
- android.hardware.keymaster@3.0
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE := libkeystore_binder
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(call keystore_proto_include)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder \
- libhwbinder \
- libhidlbase \
- android.hardware.keymaster@3.0
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_SHARED_LIBRARY)
-
-# Library for keystore clients using the WiFi HIDL interface
-include $(CLEAR_VARS)
-LOCAL_CFLAGS := -Wall -Wextra -Werror
-LOCAL_SRC_FILES := \
- keystore_get_wifi_hidl.cpp
-LOCAL_SHARED_LIBRARIES := \
- android.system.wifi.keystore@1.0 \
- libbase \
- libhidlbase \
- libhidltransport \
- liblog \
- libutils
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE := libkeystore-wifi-hidl
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_VENDOR_MODULE := true
-include $(BUILD_SHARED_LIBRARY)
-
-# Library for unit tests
-include $(CLEAR_VARS)
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_CFLAGS := -Wall -Wextra -Werror
-LOCAL_SRC_FILES := auth_token_table.cpp
-LOCAL_MODULE := libkeystore_test
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libgtest_main
-LOCAL_SHARED_LIBRARIES := libkeymaster_messages \
- libutils \
- libhwbinder \
- libhidlbase \
- android.hardware.keymaster@3.0
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_STATIC_LIBRARY)
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
deleted file mode 100644
index eee9942..0000000
--- a/keystore/IKeystoreService.cpp
+++ /dev/null
@@ -1,1361 +0,0 @@
-/*
-**
-** Copyright 2008, 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 <sys/limits.h>
-#include <sys/types.h>
-
-#include <algorithm>
-#include <limits>
-
-#define LOG_TAG "KeystoreService"
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
-
-#include <keystore/IKeystoreService.h>
-#include <keystore/keystore_hidl_support.h>
-
-#include "keystore_aidl_hidl_marshalling_utils.h"
-
-namespace android {
-using namespace ::keystore;
-
-const ssize_t MAX_GENERATE_ARGS = 3;
-
-KeystoreArg::KeystoreArg(const void* data, size_t len) : mData(data), mSize(len) {}
-
-KeystoreArg::~KeystoreArg() {}
-
-const void* KeystoreArg::data() const {
- return mData;
-}
-
-size_t KeystoreArg::size() const {
- return mSize;
-}
-
-OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {}
-
-OperationResult::~OperationResult() {}
-
-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 = readKeymasterBlob(in);
- outParams = readParamSetFromParcel(in);
- return OK;
-}
-
-status_t OperationResult::writeToParcel(Parcel* out) const {
- out->writeInt32(resultCode);
- out->writeStrongBinder(token);
- out->writeInt64(handle);
- out->writeInt32(inputConsumed);
- writeKeymasterBlob(data, out);
- writeParamSetToParcel(outParams, out);
- return OK;
-}
-
-ExportResult::ExportResult() : resultCode() {}
-
-ExportResult::~ExportResult() {}
-
-status_t ExportResult::readFromParcel(const Parcel* inn) {
- const Parcel& in = *inn;
- resultCode = ErrorCode(in.readInt32());
- exportData = readKeymasterBlob(in);
- return OK;
-}
-
-status_t ExportResult::writeToParcel(Parcel* out) const {
- out->writeInt32(resultCode);
- writeKeymasterBlob(exportData, out);
- return OK;
-}
-
-/**
- * Read a byte array from in. The data at *data is still owned by the parcel
- */
-static void readByteArray(const Parcel& in, const uint8_t** data, size_t* length) {
- ssize_t slength = in.readInt32();
- if (slength > 0) {
- *data = reinterpret_cast<const uint8_t*>(in.readInplace(slength));
- if (*data) {
- *length = static_cast<size_t>(slength);
- } else {
- *length = 0;
- }
- } else {
- *data = NULL;
- *length = 0;
- }
-}
-
-class BpKeystoreService : public BpInterface<IKeystoreService> {
- public:
- explicit BpKeystoreService(const sp<IBinder>& impl) : BpInterface<IKeystoreService>(impl) {}
-
- // test ping
- KeyStoreServiceReturnCode getState(int32_t userId) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeInt32(userId);
- status_t status = remote()->transact(BnKeystoreService::GET_STATE, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("getState() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- ResponseCode ret = ResponseCode(reply.readInt32());
- if (err < 0) {
- ALOGD("getState() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ret;
- }
-
- KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
- hidl_vec<uint8_t>* item) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeInt32(uid);
- status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("get() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("get() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- auto resultItem = readBlobAsByteArray(reply);
- if (item) *item = resultItem.value();
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode insert(const String16& name, const hidl_vec<uint8_t>& item, int uid,
- int32_t flags) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- writeBlobAsByteArray(item, &data);
- data.writeInt32(uid);
- data.writeInt32(flags);
- status_t status = remote()->transact(BnKeystoreService::INSERT, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("import() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("import() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode del(const String16& name, int uid) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeInt32(uid);
- status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("del() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("del() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode exist(const String16& name, int uid) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeInt32(uid);
- status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("exist() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("exist() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode list(const String16& prefix, int uid,
- Vector<String16>* matches) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(prefix);
- data.writeInt32(uid);
- status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("list() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- int32_t numMatches = reply.readInt32();
- for (int32_t i = 0; i < numMatches; i++) {
- matches->push(reply.readString16());
- }
- if (err < 0) {
- ALOGD("list() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode reset() override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- status_t status = remote()->transact(BnKeystoreService::RESET, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("reset() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("reset() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode onUserPasswordChanged(int32_t userId,
- const String16& password) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeInt32(userId);
- data.writeString16(password);
- status_t status =
- remote()->transact(BnKeystoreService::ON_USER_PASSWORD_CHANGED, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("onUserPasswordChanged() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("onUserPasswordChanged() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode lock(int32_t userId) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeInt32(userId);
- status_t status = remote()->transact(BnKeystoreService::LOCK, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("lock() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("lock() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode unlock(int32_t userId, const String16& password) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeInt32(userId);
- data.writeString16(password);
- status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("unlock() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("unlock() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- bool isEmpty(int32_t userId) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeInt32(userId);
- status_t status = remote()->transact(BnKeystoreService::IS_EMPTY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("isEmpty() could not contact remote: %d\n", status);
- return false;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("isEmpty() caught exception %d\n", err);
- return false;
- }
- return reply.readInt32() != 0;
- }
-
- KeyStoreServiceReturnCode generate(const String16& name, int32_t uid, int32_t keyType,
- int32_t keySize, int32_t flags,
- Vector<sp<KeystoreArg>>* args) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeInt32(uid);
- data.writeInt32(keyType);
- data.writeInt32(keySize);
- data.writeInt32(flags);
- data.writeInt32(1);
- data.writeInt32(args->size());
- for (Vector<sp<KeystoreArg>>::iterator it = args->begin(); it != args->end(); ++it) {
- sp<KeystoreArg> item = *it;
- size_t keyLength = item->size();
- data.writeInt32(keyLength);
- void* buf = data.writeInplace(keyLength);
- memcpy(buf, item->data(), keyLength);
- }
- status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("generate() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("generate() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode import(const String16& name, const hidl_vec<uint8_t>& key, int uid,
- int flags) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- writeBlobAsByteArray(key, &data);
- data.writeInt32(uid);
- data.writeInt32(flags);
- status_t status = remote()->transact(BnKeystoreService::IMPORT, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("import() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("import() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode sign(const String16& name, const hidl_vec<uint8_t>& in,
- hidl_vec<uint8_t>* out) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- writeBlobAsByteArray(in, &data);
- status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("import() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("import() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- auto outBlob = readBlobAsByteArray(reply);
- if (out) {
- // don't need to check outBlob.isOk()
- // if !outBlob.isOk() the wrapped value is default constructed and therefore empty,
- // as expected.
- *out = outBlob.value();
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode verify(const String16& name, const hidl_vec<uint8_t>& in,
- const hidl_vec<uint8_t>& signature) override {
- Parcel data, reply;
-
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- writeBlobAsByteArray(in, &data);
- writeBlobAsByteArray(signature, &data);
- status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("verify() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("verify() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode get_pubkey(const String16& name, hidl_vec<uint8_t>* pubkey) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- status_t status = remote()->transact(BnKeystoreService::GET_PUBKEY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("get_pubkey() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("get_pubkey() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- auto resultKey = readBlobAsByteArray(reply);
- if (pubkey) *pubkey = resultKey.value();
- return ResponseCode(reply.readInt32());
- }
-
- String16 grant(const String16& name, int32_t granteeUid) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeInt32(granteeUid);
- status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("grant() could not contact remote: %d\n", status);
- return String16();
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("grant() caught exception %d\n", err);
- return String16();
- }
- return reply.readString16();
- }
-
- KeyStoreServiceReturnCode ungrant(const String16& name, int32_t granteeUid) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeInt32(granteeUid);
- status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("ungrant() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("ungrant() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- int64_t getmtime(const String16& name, int32_t uid) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeInt32(uid);
- status_t status = remote()->transact(BnKeystoreService::GETMTIME, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("getmtime() could not contact remote: %d\n", status);
- return -1;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("getmtime() caught exception %d\n", err);
- return -1;
- }
- return reply.readInt64();
- }
-
- KeyStoreServiceReturnCode duplicate(const String16& srcKey, int32_t srcUid,
- const String16& destKey, int32_t destUid) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(srcKey);
- data.writeInt32(srcUid);
- data.writeString16(destKey);
- data.writeInt32(destUid);
- status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("duplicate() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("duplicate() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- int32_t is_hardware_backed(const String16& keyType) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(keyType);
- status_t status = remote()->transact(BnKeystoreService::IS_HARDWARE_BACKED, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("is_hardware_backed() could not contact remote: %d\n", status);
- return -1;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("is_hardware_backed() caught exception %d\n", err);
- return -1;
- }
- return reply.readInt32();
- }
-
- KeyStoreServiceReturnCode clear_uid(int64_t uid) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeInt64(uid);
- status_t status = remote()->transact(BnKeystoreService::CLEAR_UID, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("clear_uid() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("clear_uid() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- writeBlobAsByteArray(entropy, &data);
- status_t status = remote()->transact(BnKeystoreService::ADD_RNG_ENTROPY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("addRngEntropy() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("addRngEntropy() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- };
-
- KeyStoreServiceReturnCode generateKey(const String16& name,
- const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& entropy, int uid, int flags,
- KeyCharacteristics* outCharacteristics) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- nullable(writeParamSetToParcel, params, &data);
- writeBlobAsByteArray(entropy, &data);
- data.writeInt32(uid);
- data.writeInt32(flags);
- status_t status = remote()->transact(BnKeystoreService::GENERATE_KEY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("generateKey() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- ResponseCode ret = ResponseCode(reply.readInt32());
- if (err < 0) {
- ALOGD("generateKey() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- if (outCharacteristics) {
- *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
- }
- return ret;
- }
- KeyStoreServiceReturnCode
- getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData, int32_t uid,
- KeyCharacteristics* outCharacteristics) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- writeBlobAsByteArray(clientId, &data);
- writeBlobAsByteArray(appData, &data);
- data.writeInt32(uid);
- status_t status =
- remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("getKeyCharacteristics() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- ResponseCode ret = ResponseCode(reply.readInt32());
- if (err < 0) {
- ALOGD("getKeyCharacteristics() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- if (outCharacteristics) {
- *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
- }
- return ret;
- }
- KeyStoreServiceReturnCode importKey(const String16& name, const hidl_vec<KeyParameter>& params,
- KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid,
- int flags,
- KeyCharacteristics* outCharacteristics) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- nullable(writeParamSetToParcel, params, &data);
- data.writeInt32(uint32_t(format));
- writeBlobAsByteArray(keyData, &data);
- data.writeInt32(uid);
- data.writeInt32(flags);
- status_t status = remote()->transact(BnKeystoreService::IMPORT_KEY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("importKey() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- ResponseCode ret = ResponseCode(reply.readInt32());
- if (err < 0) {
- ALOGD("importKey() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- if (outCharacteristics) {
- *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
- }
- return ret;
- }
-
- void exportKey(const String16& name, KeyFormat format, const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData, int32_t uid, ExportResult* result) override {
- if (!result) {
- return;
- }
-
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- data.writeInt32(int32_t(format));
- writeBlobAsByteArray(clientId, &data);
- writeBlobAsByteArray(appData, &data);
- data.writeInt32(uid);
- status_t status = remote()->transact(BnKeystoreService::EXPORT_KEY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("exportKey() could not contact remote: %d\n", status);
- result->resultCode = ResponseCode::SYSTEM_ERROR;
- return;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("exportKey() caught exception %d\n", err);
- result->resultCode = ResponseCode::SYSTEM_ERROR;
- return;
- }
-
- reply.readParcelable(result);
- }
-
- void begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
- bool pruneable, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& entropy, int32_t uid, OperationResult* result) override {
- if (!result) {
- return;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeStrongBinder(appToken);
- data.writeString16(name);
- data.writeInt32(int32_t(purpose));
- data.writeInt32(pruneable ? 1 : 0);
- nullable(writeParamSetToParcel, params, &data);
- writeBlobAsByteArray(entropy, &data);
- data.writeInt32(uid);
- status_t status = remote()->transact(BnKeystoreService::BEGIN, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("begin() could not contact remote: %d\n", status);
- result->resultCode = ResponseCode::SYSTEM_ERROR;
- return;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("begin() caught exception %d\n", err);
- result->resultCode = ResponseCode::SYSTEM_ERROR;
- return;
- }
-
- reply.readParcelable(result);
- }
-
- void update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& opData, OperationResult* result) override {
- if (!result) {
- return;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeStrongBinder(token);
- nullable(writeParamSetToParcel, params, &data);
- writeBlobAsByteArray(opData, &data);
- status_t status = remote()->transact(BnKeystoreService::UPDATE, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("update() could not contact remote: %d\n", status);
- result->resultCode = ResponseCode::SYSTEM_ERROR;
- return;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("update() caught exception %d\n", err);
- result->resultCode = ResponseCode::SYSTEM_ERROR;
- return;
- }
-
- reply.readParcelable(result);
- }
-
- void finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
- OperationResult* result) override {
- if (!result) {
- return;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeStrongBinder(token);
- nullable(writeParamSetToParcel, params, &data);
- writeBlobAsByteArray(signature, &data);
- writeBlobAsByteArray(entropy, &data);
- status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("finish() could not contact remote: %d\n", status);
- result->resultCode = ResponseCode::SYSTEM_ERROR;
- return;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("finish() caught exception %d\n", err);
- result->resultCode = ResponseCode::SYSTEM_ERROR;
- return;
- }
-
- reply.readParcelable(result);
- }
-
- KeyStoreServiceReturnCode abort(const sp<IBinder>& token) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeStrongBinder(token);
- status_t status = remote()->transact(BnKeystoreService::ABORT, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("abort() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("abort() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- bool isOperationAuthorized(const sp<IBinder>& token) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeStrongBinder(token);
- status_t status =
- remote()->transact(BnKeystoreService::IS_OPERATION_AUTHORIZED, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("isOperationAuthorized() could not contact remote: %d\n", status);
- return false;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("isOperationAuthorized() caught exception %d\n", err);
- return false;
- }
- return reply.readInt32() == 1;
- }
-
- KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeByteArray(length, token);
- status_t status = remote()->transact(BnKeystoreService::ADD_AUTH_TOKEN, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("addAuthToken() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("addAuthToken() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- };
-
- KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeInt32(userId);
- data.writeInt32(parentId);
- status_t status = remote()->transact(BnKeystoreService::ON_USER_ADDED, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("onUserAdded() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("onUserAdded() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode onUserRemoved(int32_t userId) override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeInt32(userId);
- status_t status = remote()->transact(BnKeystoreService::ON_USER_REMOVED, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("onUserRemoved() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("onUserRemoved() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-
- KeyStoreServiceReturnCode attestKey(const String16& name, const hidl_vec<KeyParameter>& params,
- hidl_vec<hidl_vec<uint8_t>>* outChain) override {
- if (!outChain) return ErrorCode::OUTPUT_PARAMETER_NULL;
-
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- data.writeString16(name);
- nullable(writeParamSetToParcel, params, &data);
-
- status_t status = remote()->transact(BnKeystoreService::ATTEST_KEY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("attestkey() count not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- ResponseCode ret = ResponseCode(reply.readInt32());
- if (err < 0) {
- ALOGD("attestKey() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- if (reply.readInt32() != 0) {
- *outChain = readCertificateChainFromParcel(reply);
- }
- return ret;
- }
-
- KeyStoreServiceReturnCode attestDeviceIds(const hidl_vec<KeyParameter>& params,
- hidl_vec<hidl_vec<uint8_t>>* outChain) override {
- if (!outChain) return ErrorCode::OUTPUT_PARAMETER_NULL;
-
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- nullable(writeParamSetToParcel, params, &data);
-
- status_t status = remote()->transact(BnKeystoreService::ATTEST_DEVICE_IDS, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("attestDeviceIds() count not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- ResponseCode ret = ResponseCode(reply.readInt32());
- if (err < 0) {
- ALOGD("attestDeviceIds() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- if (reply.readInt32() != 0) {
- *outChain = readCertificateChainFromParcel(reply);
- }
- return ret;
- }
-
- KeyStoreServiceReturnCode onDeviceOffBody() override {
- Parcel data, reply;
- data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
- status_t status = remote()->transact(BnKeystoreService::ON_DEVICE_OFF_BODY, data, &reply);
- if (status != NO_ERROR) {
- ALOGD("onDeviceOffBody() could not contact remote: %d\n", status);
- return ResponseCode::SYSTEM_ERROR;
- }
- int32_t err = reply.readExceptionCode();
- if (err < 0) {
- ALOGD("onDeviceOffBody() caught exception %d\n", err);
- return ResponseCode::SYSTEM_ERROR;
- }
- return ResponseCode(reply.readInt32());
- }
-};
-
-IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
-
-// ----------------------------------------------------------------------
-
-status_t BnKeystoreService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags) {
- switch (code) {
- case GET_STATE: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- int32_t ret = getState(userId);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case GET: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t uid = data.readInt32();
- hidl_vec<uint8_t> out;
- auto ret = get(name, uid, &out);
- reply->writeNoException();
- if (ret.isOk()) {
- writeBlobAsByteArray(out, reply);
- } else {
- reply->writeInt32(-1);
- }
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case INSERT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- auto in = readBlobAsByteArray(data);
- int uid = data.readInt32();
- int32_t flags = data.readInt32();
- int32_t ret = insert(name, in.value(), uid, flags);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case DEL: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int uid = data.readInt32();
- int32_t ret = del(name, uid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case EXIST: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int uid = data.readInt32();
- int32_t ret = exist(name, uid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case LIST: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 prefix = data.readString16();
- int uid = data.readInt32();
- Vector<String16> matches;
- int32_t ret = list(prefix, uid, &matches);
- reply->writeNoException();
- reply->writeInt32(matches.size());
- Vector<String16>::const_iterator it = matches.begin();
- for (; it != matches.end(); ++it) {
- reply->writeString16(*it);
- }
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case RESET: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t ret = reset();
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case ON_USER_PASSWORD_CHANGED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- String16 pass = data.readString16();
- int32_t ret = onUserPasswordChanged(userId, pass);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case LOCK: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- int32_t ret = lock(userId);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case UNLOCK: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- String16 pass = data.readString16();
- int32_t ret = unlock(userId, pass);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case IS_EMPTY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- bool ret = isEmpty(userId);
- reply->writeNoException();
- reply->writeInt32(ret ? 1 : 0);
- return NO_ERROR;
- } break;
- case GENERATE: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t uid = data.readInt32();
- int32_t keyType = data.readInt32();
- int32_t keySize = data.readInt32();
- int32_t flags = data.readInt32();
- Vector<sp<KeystoreArg>> args;
- int32_t argsPresent = data.readInt32();
- if (argsPresent == 1) {
- ssize_t numArgs = data.readInt32();
- if (numArgs > MAX_GENERATE_ARGS) {
- return BAD_VALUE;
- }
- if (numArgs > 0) {
- for (size_t i = 0; i < (size_t)numArgs; i++) {
- ssize_t inSize = data.readInt32();
- if (inSize >= 0 && (size_t)inSize <= data.dataAvail()) {
- sp<KeystoreArg> arg = new KeystoreArg(data.readInplace(inSize), inSize);
- args.push_back(arg);
- } else {
- args.push_back(NULL);
- }
- }
- }
- }
- int32_t ret = generate(name, uid, keyType, keySize, flags, &args);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case IMPORT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- auto in = readBlobAsByteArray(data);
- int uid = data.readInt32();
- int32_t flags = data.readInt32();
- auto ret = import(name, in.value(), uid, flags);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case SIGN: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- auto in = readBlobAsByteArray(data);
- hidl_vec<uint8_t> out;
- auto ret = sign(name, in.value(), &out);
- reply->writeNoException();
- writeBlobAsByteArray(out, reply);
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case VERIFY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- auto in = readBlobAsByteArray(data);
- auto signature = readBlobAsByteArray(data);
- auto ret = verify(name, in.value(), signature.value());
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case GET_PUBKEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- hidl_vec<uint8_t> out;
- auto ret = get_pubkey(name, &out);
- reply->writeNoException();
- writeBlobAsByteArray(out, reply);
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case GRANT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t granteeUid = data.readInt32();
- String16 ret = grant(name, granteeUid);
- reply->writeNoException();
- reply->writeString16(ret);
- return NO_ERROR;
- } break;
- case UNGRANT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t granteeUid = data.readInt32();
- int32_t ret = ungrant(name, granteeUid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case GETMTIME: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- int32_t uid = data.readInt32();
- int64_t ret = getmtime(name, uid);
- reply->writeNoException();
- reply->writeInt64(ret);
- return NO_ERROR;
- } break;
- case DUPLICATE: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 srcKey = data.readString16();
- int32_t srcUid = data.readInt32();
- String16 destKey = data.readString16();
- int32_t destUid = data.readInt32();
- int32_t ret = duplicate(srcKey, srcUid, destKey, destUid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- } break;
- case IS_HARDWARE_BACKED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 keyType = data.readString16();
- int32_t ret = is_hardware_backed(keyType);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- }
- case CLEAR_UID: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int64_t uid = data.readInt64();
- int32_t ret = clear_uid(uid);
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- }
- case ADD_RNG_ENTROPY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- auto entropy = readBlobAsByteArray(data);
- auto ret = addRngEntropy(entropy.value());
- reply->writeNoException();
- reply->writeInt32(ret);
- return NO_ERROR;
- }
- case GENERATE_KEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- auto params = nullable(readParamSetFromParcel, data);
- auto entropy = readBlobAsByteArray(data);
- int32_t uid = data.readInt32();
- int32_t flags = data.readInt32();
- KeyCharacteristics outCharacteristics;
- int32_t ret =
- generateKey(name, params.value(), entropy.value(), uid, flags, &outCharacteristics);
- reply->writeNoException();
- reply->writeInt32(ret);
- nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
- return NO_ERROR;
- }
- case GET_KEY_CHARACTERISTICS: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- auto clientId = nullable(readKeymasterBlob, data, true);
- auto appData = nullable(readKeymasterBlob, data, true);
- int32_t uid = data.readInt32();
- KeyCharacteristics outCharacteristics;
- int ret = getKeyCharacteristics(name, clientId.value(), appData.value(), uid,
- &outCharacteristics);
- reply->writeNoException();
- reply->writeInt32(ret);
- nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
- return NO_ERROR;
- }
- case IMPORT_KEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- auto args = nullable(readParamSetFromParcel, data);
- KeyFormat format = static_cast<KeyFormat>(data.readInt32());
- auto keyData = readBlobAsByteArray(data);
- int32_t uid = data.readInt32();
- int32_t flags = data.readInt32();
- KeyCharacteristics outCharacteristics;
- int32_t ret =
- importKey(name, args.value(), format, keyData.value(), uid, flags, &outCharacteristics);
- reply->writeNoException();
- reply->writeInt32(ret);
- nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
- return NO_ERROR;
- }
- case EXPORT_KEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- KeyFormat format = static_cast<KeyFormat>(data.readInt32());
- auto clientId = nullable(readKeymasterBlob, data, true);
- auto appData = nullable(readKeymasterBlob, data, true);
- int32_t uid = data.readInt32();
- ExportResult result;
- exportKey(name, format, clientId.value(), appData.value(), uid, &result);
- reply->writeNoException();
- reply->writeParcelable(result);
-
- return NO_ERROR;
- }
- case BEGIN: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- String16 name = data.readString16();
- KeyPurpose purpose = static_cast<KeyPurpose>(data.readInt32());
- bool pruneable = data.readInt32() != 0;
- auto args = nullable(readParamSetFromParcel, data);
- auto entropy = readBlobAsByteArray(data);
- int32_t uid = data.readInt32();
- OperationResult result;
- begin(token, name, purpose, pruneable, args.value(), entropy.value(), uid, &result);
- reply->writeNoException();
- reply->writeParcelable(result);
-
- return NO_ERROR;
- }
- case UPDATE: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- auto args = nullable(readParamSetFromParcel, data);
- auto buf = readBlobAsByteArray(data);
- OperationResult result;
- update(token, args.value(), buf.value(), &result);
- reply->writeNoException();
- reply->writeParcelable(result);
-
- return NO_ERROR;
- }
- case FINISH: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- auto args = nullable(readParamSetFromParcel, data);
- auto signature = readBlobAsByteArray(data);
- auto entropy = readBlobAsByteArray(data);
- OperationResult result;
- finish(token, args.value(), signature.value(), entropy.value(), &result);
- reply->writeNoException();
- reply->writeParcelable(result);
-
- return NO_ERROR;
- }
- case ABORT: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- int32_t result = abort(token);
- reply->writeNoException();
- reply->writeInt32(result);
-
- return NO_ERROR;
- }
- case IS_OPERATION_AUTHORIZED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- sp<IBinder> token = data.readStrongBinder();
- bool result = isOperationAuthorized(token);
- reply->writeNoException();
- reply->writeInt32(result ? 1 : 0);
-
- return NO_ERROR;
- }
- case ADD_AUTH_TOKEN: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- const uint8_t* token_bytes = NULL;
- size_t size = 0;
- readByteArray(data, &token_bytes, &size);
- int32_t result = addAuthToken(token_bytes, size);
- reply->writeNoException();
- reply->writeInt32(result);
-
- return NO_ERROR;
- }
- case ON_USER_ADDED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- int32_t parentId = data.readInt32();
- int32_t result = onUserAdded(userId, parentId);
- reply->writeNoException();
- reply->writeInt32(result);
-
- return NO_ERROR;
- }
- case ON_USER_REMOVED: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t userId = data.readInt32();
- int32_t result = onUserRemoved(userId);
- reply->writeNoException();
- reply->writeInt32(result);
-
- return NO_ERROR;
- }
- case ATTEST_KEY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- String16 name = data.readString16();
- auto params = nullable(readParamSetFromParcel, data);
- hidl_vec<hidl_vec<uint8_t>> chain;
- int ret = attestKey(name, params.value(), &chain);
- reply->writeNoException();
- reply->writeInt32(ret);
- nullable(writeCertificateChainToParcel, chain, reply);
-
- return NO_ERROR;
- }
-
- case ATTEST_DEVICE_IDS: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- auto params = nullable(readParamSetFromParcel, data);
- hidl_vec<hidl_vec<uint8_t>> chain;
- int ret = attestDeviceIds(params.value(), &chain);
- reply->writeNoException();
- reply->writeInt32(ret);
- nullable(writeCertificateChainToParcel, chain, reply);
-
- return NO_ERROR;
- }
-
- case ON_DEVICE_OFF_BODY: {
- CHECK_INTERFACE(IKeystoreService, data, reply);
- int32_t ret = onDeviceOffBody();
- reply->writeNoException();
- reply->writeInt32(ret);
-
- return NO_ERROR;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/keystore/KeyAttestationApplicationId.cpp b/keystore/KeyAttestationApplicationId.cpp
index 1352124..4bc939d 100644
--- a/keystore/KeyAttestationApplicationId.cpp
+++ b/keystore/KeyAttestationApplicationId.cpp
@@ -23,6 +23,14 @@
namespace security {
namespace keymaster {
+KeyAttestationApplicationId::KeyAttestationApplicationId() = default;
+
+KeyAttestationApplicationId::KeyAttestationApplicationId(
+ std::unique_ptr<KeyAttestationPackageInfo> package) :
+ packageInfos_(new std::vector<std::unique_ptr<KeyAttestationPackageInfo>>()) {
+ packageInfos_->push_back(std::move(package));
+}
+
status_t KeyAttestationApplicationId::writeToParcel(Parcel* parcel) const {
return parcel->writeParcelableVector(packageInfos_);
}
diff --git a/keystore/KeyAttestationPackageInfo.cpp b/keystore/KeyAttestationPackageInfo.cpp
index a84c246..75fbb7a 100644
--- a/keystore/KeyAttestationPackageInfo.cpp
+++ b/keystore/KeyAttestationPackageInfo.cpp
@@ -23,10 +23,17 @@
namespace security {
namespace keymaster {
+KeyAttestationPackageInfo::KeyAttestationPackageInfo() = default;
+
+KeyAttestationPackageInfo::KeyAttestationPackageInfo(const String16& packageName,
+ int64_t versionCode,
+ SharedSignaturesVector signatures)
+ : packageName_(new String16(packageName)), versionCode_(versionCode), signatures_(signatures) {}
+
status_t KeyAttestationPackageInfo::writeToParcel(Parcel* parcel) const {
auto rc = parcel->writeString16(packageName_);
if (rc != NO_ERROR) return rc;
- rc = parcel->writeInt32(versionCode_);
+ rc = parcel->writeInt64(versionCode_);
if (rc != NO_ERROR) return rc;
return parcel->writeParcelableVector(signatures_);
}
@@ -34,10 +41,10 @@
status_t KeyAttestationPackageInfo::readFromParcel(const Parcel* parcel) {
auto rc = parcel->readString16(&packageName_);
if (rc != NO_ERROR) return rc;
- rc = parcel->readInt32(&versionCode_);
+ rc = parcel->readInt64(&versionCode_);
if (rc != NO_ERROR) return rc;
- std::unique_ptr<std::vector<std::unique_ptr<content::pm::Signature>>> temp_vector;
+ std::unique_ptr<SignaturesVector> temp_vector;
rc = parcel->readParcelableVector(&temp_vector);
if (rc != NO_ERROR) return rc;
signatures_.reset(temp_vector.release());
diff --git a/keystore/keystore.cpp b/keystore/KeyStore.cpp
similarity index 81%
rename from keystore/keystore.cpp
rename to keystore/KeyStore.cpp
index a61ef73..428b51e 100644
--- a/keystore/keystore.cpp
+++ b/keystore/KeyStore.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "keystore"
-#include "keystore.h"
+#include "KeyStore.h"
#include <dirent.h>
#include <fcntl.h>
@@ -26,26 +26,47 @@
#include <utils/String16.h>
#include <utils/String8.h>
-#include <keystore/IKeystoreService.h>
-
+#include <android-base/scopeguard.h>
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <android/security/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>
-const char* KeyStore::sOldMasterKey = ".masterkey";
-const char* KeyStore::sMetaDataFile = ".metadata";
+namespace keystore {
-const android::String16 KeyStore::sRSAKeyType("RSA");
+const char* KeyStore::kOldMasterKey = ".masterkey";
+const char* KeyStore::kMetaDataFile = ".metadata";
-using namespace keystore;
+const android::String16 KeyStore::kRsaKeyType("RSA");
+const android::String16 KeyStore::kEcKeyType("EC");
+
using android::String8;
-KeyStore::KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
- bool allowNewFallback)
- : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback),
- mAllowNewFallback(allowNewFallback) {
+sp<Keymaster>& KeymasterDevices::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 at(static_cast<uint32_t>(secLevel));
+}
+
+sp<Keymaster> KeymasterDevices::operator[](SecurityLevel secLevel) const {
+ if (static_cast<uint32_t>(secLevel) > static_cast<uint32_t>(SecurityLevel::STRONGBOX)) {
+ LOG(ERROR) << "Invalid security level requested";
+ return nullptr;
+ }
+ return (*const_cast<KeymasterDevices*>(this))[secLevel];
+}
+
+KeyStore::KeyStore(const KeymasterDevices& kmDevices,
+ SecurityLevel minimalAllowedSecurityLevelForNewKeys)
+ : mKmDevices(kmDevices),
+ mAllowNewFallback(minimalAllowedSecurityLevelForNewKeys == SecurityLevel::SOFTWARE) {
memset(&mMetaData, '\0', sizeof(mMetaData));
}
@@ -68,7 +89,7 @@
ResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) {
UserState* userState = getUserState(userId);
- return userState->initialize(pw, mEntropy);
+ return userState->initialize(pw);
}
ResponseCode KeyStore::copyMasterKey(uid_t srcUser, uid_t dstUser) {
@@ -79,12 +100,12 @@
ResponseCode KeyStore::writeMasterKey(const android::String8& pw, uid_t userId) {
UserState* userState = getUserState(userId);
- return userState->writeMasterKey(pw, mEntropy);
+ return userState->writeMasterKey(pw);
}
ResponseCode KeyStore::readMasterKey(const android::String8& pw, uid_t userId) {
UserState* userState = getUserState(userId);
- return userState->readMasterKey(pw, mEntropy);
+ return userState->readMasterKey(pw);
}
/* Here is the encoding of keys. This is necessary in order to allow arbitrary
@@ -131,8 +152,8 @@
}
}
-android::String8 KeyStore::getKeyNameForUid(
- const android::String8& keyName, uid_t uid, const BlobType type) {
+android::String8 KeyStore::getKeyNameForUid(const android::String8& keyName, uid_t uid,
+ const BlobType type) {
std::vector<char> encoded(encode_key_length(keyName) + 1); // add 1 for null char
encode_key(encoded.data(), keyName);
if (type == TYPE_KEY_CHARACTERISTICS) {
@@ -142,8 +163,8 @@
}
}
-android::String8 KeyStore::getKeyNameForUidWithDir(
- const android::String8& keyName, uid_t uid, const BlobType type) {
+android::String8 KeyStore::getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid,
+ const BlobType type) {
std::vector<char> encoded(encode_key_length(keyName) + 1); // add 1 for null char
encode_key(encoded.data(), keyName);
@@ -157,7 +178,7 @@
}
NullOr<android::String8> KeyStore::getBlobFileNameIfExists(const android::String8& alias, uid_t uid,
- const BlobType type) {
+ const BlobType type) {
android::String8 filepath8(getKeyNameForUidWithDir(alias, uid, type));
if (!access(filepath8.string(), R_OK | W_OK)) return filepath8;
@@ -172,14 +193,14 @@
// They might be using a granted key.
auto grant = mGrants.get(uid, alias.string());
if (grant) {
- filepath8 = String8::format("%s/%s", grant->owner_dir_name_.c_str(),
- getKeyNameForUid(String8(grant->alias_.c_str()), grant->owner_uid_, type).c_str());
+ filepath8 = String8::format(
+ "%s/%s", grant->owner_dir_name_.c_str(),
+ getKeyNameForUid(String8(grant->alias_.c_str()), grant->owner_uid_, type).c_str());
if (!access(filepath8.string(), R_OK | W_OK)) return filepath8;
}
return {};
}
-
void KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) {
android::String8 prefix("");
android::Vector<android::String16> aliases;
@@ -224,9 +245,9 @@
// del() will fail silently if no cached characteristics are present for this alias.
android::String8 chr_filename(aliases[i]);
- chr_filename = android::String8::format("%s/%s", userState->getUserDirName(),
- getKeyName(chr_filename,
- TYPE_KEY_CHARACTERISTICS).string());
+ chr_filename = android::String8::format(
+ "%s/%s", userState->getUserDirName(),
+ getKeyName(chr_filename, TYPE_KEY_CHARACTERISTICS).string());
del(chr_filename, ::TYPE_KEY_CHARACTERISTICS, userId);
}
}
@@ -277,10 +298,19 @@
userState->setState(STATE_LOCKED);
}
+static void maybeLogKeyIntegrityViolation(const char* filename, const BlobType type);
+
ResponseCode KeyStore::get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId) {
UserState* userState = getUserState(userId);
- ResponseCode rc =
- keyBlob->readBlob(filename, userState->getEncryptionKey(), userState->getState());
+ ResponseCode rc;
+
+ auto logOnScopeExit = android::base::make_scope_guard([&] {
+ if (rc == ResponseCode::VALUE_CORRUPTED) {
+ maybeLogKeyIntegrityViolation(filename, type);
+ }
+ });
+
+ rc = keyBlob->readBlob(filename, userState->getEncryptionKey(), userState->getState());
if (rc != ResponseCode::NO_ERROR) {
return rc;
}
@@ -330,8 +360,7 @@
ResponseCode KeyStore::put(const char* filename, Blob* keyBlob, uid_t userId) {
UserState* userState = getUserState(userId);
- return keyBlob->writeBlob(filename, userState->getEncryptionKey(), userState->getState(),
- mEntropy);
+ return keyBlob->writeBlob(filename, userState->getEncryptionKey(), userState->getState());
}
static NullOr<std::tuple<uid_t, std::string>> filename2UidAlias(const std::string& filename);
@@ -351,25 +380,29 @@
// remove possible grants
mGrants.removeAllGrantsToKey(uid, alias);
}
- return (unlink(filename) && errno != ENOENT) ?
- ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
+ return (unlink(filename) && errno != ENOENT) ? ResponseCode::SYSTEM_ERROR
+ : ResponseCode::NO_ERROR;
}
if (rc != ResponseCode::NO_ERROR) {
return rc;
}
- auto& dev = getDevice(keyBlob);
+ auto dev = getDevice(keyBlob);
if (keyBlob.getType() == ::TYPE_KEY_PAIR || keyBlob.getType() == ::TYPE_KEYMASTER_10) {
auto ret = KS_HANDLE_HIDL_ERROR(dev->deleteKey(blob2hidlVec(keyBlob)));
// A device doesn't have to implement delete_key.
- if (ret != ErrorCode::OK && ret != ErrorCode::UNIMPLEMENTED)
- return ResponseCode::SYSTEM_ERROR;
+ bool success = ret == ErrorCode::OK || ret == ErrorCode::UNIMPLEMENTED;
+ if (__android_log_security() && uidAlias.isOk()) {
+ android_log_event_list(SEC_TAG_KEY_DESTROYED)
+ << int32_t(success) << alias << int32_t(uid) << LOG_ID_SECURITY;
+ }
+ if (!success) return ResponseCode::SYSTEM_ERROR;
}
- rc = (unlink(filename) && errno != ENOENT) ?
- ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
+ rc =
+ (unlink(filename) && errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
if (rc == ResponseCode::NO_ERROR && keyBlob.getType() != ::TYPE_KEY_CHARACTERISTICS) {
// now that we have successfully deleted a key, let's make sure there are no stale grants
@@ -419,8 +452,8 @@
static NullOr<std::tuple<uid_t, std::string>> filename2UidAlias(const std::string& filepath) {
auto filenamebase = filepath.find_last_of('/');
- std::string filename = filenamebase == std::string::npos ? filepath :
- filepath.substr(filenamebase + 1);
+ std::string filename =
+ filenamebase == std::string::npos ? filepath : filepath.substr(filenamebase + 1);
if (filename[0] == '.') return {};
@@ -524,16 +557,26 @@
hidl_vec<uint8_t> blob;
ErrorCode error;
- auto hidlCb = [&] (ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
- const KeyCharacteristics& /* ignored */) {
+ auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
+ const KeyCharacteristics& /* ignored */) {
error = ret;
if (error != ErrorCode::OK) return;
blob = keyBlob;
};
auto input = blob2hidlVec(key, keyLen);
+ SecurityLevel securityLevel = flagsToSecurityLevel(flags);
+ auto kmDevice = getDevice(securityLevel);
+ if (!kmDevice) {
+ // As of this writing the only caller is KeyStore::get in an attempt to import legacy
+ // software keys. It only ever requests TEE as target which must always be present.
+ // If we see this error, we probably have a new and unanticipated caller.
+ ALOGE("No implementation for security level %d. Cannot import key.", securityLevel);
+ return ResponseCode::SYSTEM_ERROR;
+ }
+
ErrorCode rc = KS_HANDLE_HIDL_ERROR(
- mDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb));
+ kmDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb));
if (rc != ErrorCode::OK) return ResponseCode::SYSTEM_ERROR;
if (error != ErrorCode::OK) {
ALOGE("Keymaster error %d importing key pair", error);
@@ -543,30 +586,23 @@
Blob keyBlob(&blob[0], blob.size(), NULL, 0, TYPE_KEYMASTER_10);
keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
- keyBlob.setFallback(false);
+ keyBlob.setSecurityLevel(securityLevel);
return put(filename, &keyBlob, userId);
}
-bool KeyStore::isHardwareBacked(const android::String16& /*keyType*/) const {
- using ::android::hardware::hidl_string;
- if (mDevice == NULL) {
+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;
}
- bool isSecure = false;
- auto hidlcb = [&] (bool _isSecure, bool, bool, bool, bool, const hidl_string&,
- const hidl_string&) {
- isSecure = _isSecure;
- };
- auto rc = mDevice->getHardwareFeatures(hidlcb);
- if (!rc.isOk()) {
- ALOGE("Communication with keymaster HAL failed while retrieving hardware features (%s)",
- rc.description().c_str());
- return false;
- }
- return isSecure;
+ auto version = getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)->halVersion();
+ if (keyType == kRsaKeyType) return true; // All versions support RSA
+ return keyType == kEcKeyType && version.supportsEc;
}
ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
@@ -574,8 +610,7 @@
auto filepath8 = getBlobFileNameIfExists(keyName, uid, type);
uid_t userId = get_user_id(uid);
- if (filepath8.isOk())
- return get(filepath8.value().string(), keyBlob, type, userId);
+ if (filepath8.isOk()) return get(filepath8.value().string(), keyBlob, type, userId);
return ResponseCode::KEY_NOT_FOUND;
}
@@ -704,7 +739,7 @@
}
void KeyStore::readMetaData() {
- int in = TEMP_FAILURE_RETRY(open(sMetaDataFile, O_RDONLY));
+ int in = TEMP_FAILURE_RETRY(open(kMetaDataFile, O_RDONLY));
if (in < 0) {
return;
}
@@ -729,7 +764,7 @@
sizeof(mMetaData));
}
close(out);
- rename(tmpFileName, sMetaDataFile);
+ rename(tmpFileName, kMetaDataFile);
}
bool KeyStore::upgradeKeystore() {
@@ -742,8 +777,8 @@
userState->initialize();
// Migrate the old .masterkey file to user 0.
- if (access(sOldMasterKey, R_OK) == 0) {
- if (rename(sOldMasterKey, userState->getMasterKeyFileName()) < 0) {
+ if (access(kOldMasterKey, R_OK) == 0) {
+ if (rename(kOldMasterKey, userState->getMasterKeyFileName()) < 0) {
ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
return false;
}
@@ -802,3 +837,17 @@
return upgraded;
}
+
+static void maybeLogKeyIntegrityViolation(const char* filename, const BlobType type) {
+ if (!__android_log_security() || (type != TYPE_KEY_PAIR && type != TYPE_KEYMASTER_10)) return;
+
+ auto uidAlias = filename2UidAlias(filename);
+ uid_t uid = -1;
+ std::string alias;
+
+ if (uidAlias.isOk()) std::tie(uid, alias) = std::move(uidAlias).value();
+
+ log_key_integrity_violation(alias.c_str(), uid);
+}
+
+} // namespace keystore
diff --git a/keystore/keystore.h b/keystore/KeyStore.h
similarity index 75%
rename from keystore/keystore.h
rename to keystore/KeyStore.h
index a0b747f..f0fe9d3 100644
--- a/keystore/keystore.h
+++ b/keystore/KeyStore.h
@@ -17,43 +17,57 @@
#ifndef KEYSTORE_KEYSTORE_H_
#define KEYSTORE_KEYSTORE_H_
-#include "user_state.h"
-
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-
+#include <keymasterV4_0/Keymaster.h>
#include <utils/Vector.h>
-#include "blob.h"
-#include "include/keystore/keymaster_tags.h"
-#include "grant_store.h"
+#include <keystore/keymaster_types.h>
-using ::keystore::NullOr;
+#include "blob.h"
+#include "grant_store.h"
+#include "user_state.h"
+
+namespace keystore {
+
+using ::android::sp;
+using keymaster::support::Keymaster;
+
+class KeymasterDevices : public std::array<sp<Keymaster>, 3> {
+ public:
+ sp<Keymaster>& operator[](SecurityLevel secLevel);
+ sp<Keymaster> operator[](SecurityLevel secLevel) const;
+};
class KeyStore {
- typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
-
public:
- KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
- bool allowNewFallback);
+ KeyStore(const KeymasterDevices& kmDevices,
+ SecurityLevel minimalAllowedSecurityLevelForNewKeys);
~KeyStore();
- km_device_t& getDevice() { return mDevice; }
+ sp<Keymaster> getDevice(SecurityLevel securityLevel) const { return mKmDevices[securityLevel]; }
- NullOr<km_device_t&> getFallbackDevice() {
+ std::pair<sp<Keymaster>, SecurityLevel> getMostSecureDevice() const {
+ SecurityLevel level = SecurityLevel::STRONGBOX;
+ do {
+ if (mKmDevices[level].get()) {
+ return {mKmDevices[level], level};
+ }
+ level = static_cast<SecurityLevel>(static_cast<uint32_t>(level) - 1);
+ } while (level != SecurityLevel::SOFTWARE);
+ return {nullptr, SecurityLevel::SOFTWARE};
+ }
+
+ sp<Keymaster> 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 mFallbackDevice;
+ return mKmDevices[SecurityLevel::SOFTWARE];
} else {
- return {};
+ return nullptr;
}
}
- km_device_t& getDevice(const Blob& blob) {
- // We return a device, based on the nature of the blob to provide backward
- // compatibility with old key blobs generated using the fallback device.
- return blob.isFallback() ? mFallbackDevice : mDevice;
- }
+ sp<Keymaster> getDevice(const Blob& blob) { return mKmDevices[blob.getSecurityLevel()]; }
ResponseCode initialize();
@@ -71,7 +85,7 @@
android::String8 getKeyNameForUidWithDir(const android::String8& keyName, uid_t uid,
const BlobType type);
NullOr<android::String8> getBlobFileNameIfExists(const android::String8& alias, uid_t uid,
- const BlobType type);
+ const BlobType type);
/*
* Delete entries owned by userId. If keepUnencryptedEntries is true
@@ -122,13 +136,12 @@
const UserState* getUserStateByUid(uid_t uid) const;
private:
- static const char* sOldMasterKey;
- static const char* sMetaDataFile;
- static const android::String16 sRSAKeyType;
- Entropy* mEntropy;
+ static const char* kOldMasterKey;
+ static const char* kMetaDataFile;
+ static const android::String16 kRsaKeyType;
+ static const android::String16 kEcKeyType;
- km_device_t mDevice;
- km_device_t mFallbackDevice;
+ KeymasterDevices mKmDevices;
bool mAllowNewFallback;
android::Vector<UserState*> mMasterKeys;
@@ -158,4 +171,6 @@
bool upgradeKeystore();
};
+} // namespace keystore
+
#endif // KEYSTORE_KEYSTORE_H_
diff --git a/keystore/KeymasterArguments.cpp b/keystore/KeymasterArguments.cpp
new file mode 100644
index 0000000..829156c
--- /dev/null
+++ b/keystore/KeymasterArguments.cpp
@@ -0,0 +1,42 @@
+/*
+**
+** 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(const hardware::hidl_vec<keystore::KeyParameter>& other)
+ : data_(other) {}
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
diff --git a/keystore/KeystoreArguments.cpp b/keystore/KeystoreArguments.cpp
new file mode 100644
index 0000000..fe53c29
--- /dev/null
+++ b/keystore/KeystoreArguments.cpp
@@ -0,0 +1,61 @@
+/*
+**
+** 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/KeystoreArguments.h"
+#include "keystore_aidl_hidl_marshalling_utils.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace security {
+
+using ::android::security::KeystoreArg;
+using ::android::security::KeystoreArguments;
+
+const ssize_t MAX_GENERATE_ARGS = 3;
+status_t KeystoreArguments::readFromParcel(const android::Parcel* in) {
+ ssize_t numArgs = in->readInt32();
+ if (numArgs > MAX_GENERATE_ARGS) {
+ return BAD_VALUE;
+ }
+ if (numArgs > 0) {
+ for (size_t i = 0; i < static_cast<size_t>(numArgs); i++) {
+ ssize_t inSize = in->readInt32();
+ if (inSize >= 0 && static_cast<size_t>(inSize) <= in->dataAvail()) {
+ sp<KeystoreArg> arg = new KeystoreArg(in->readInplace(inSize), inSize);
+ args.push_back(arg);
+ } else {
+ args.push_back(NULL);
+ }
+ }
+ }
+ return OK;
+};
+
+status_t KeystoreArguments::writeToParcel(android::Parcel* out) const {
+ out->writeInt32(args.size());
+ for (sp<KeystoreArg> item : args) {
+ size_t keyLength = item->size();
+ out->writeInt32(keyLength);
+ void* buf = out->writeInplace(keyLength);
+ memcpy(buf, item->data(), keyLength);
+ }
+ return OK;
+}
+
+} // namespace security
+} // namespace android
diff --git a/keystore/OperationResult.cpp b/keystore/OperationResult.cpp
new file mode 100644
index 0000000..53c8d62
--- /dev/null
+++ b/keystore/OperationResult.cpp
@@ -0,0 +1,60 @@
+/*
+**
+** 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 keystore::keymaster::ErrorCode;
+using ::android::status_t;
+
+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);
+ out->writeStrongBinder(token);
+ out->writeInt64(handle);
+ out->writeInt32(inputConsumed);
+ keystore::writeKeymasterBlob(data, out);
+ keystore::writeParamSetToParcel(outParams, out);
+ return OK;
+}
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
diff --git a/keystore/auth_token_table.cpp b/keystore/auth_token_table.cpp
index 46b644d..3c51c70 100644
--- a/keystore/auth_token_table.cpp
+++ b/keystore/auth_token_table.cpp
@@ -77,13 +77,12 @@
return time.tv_sec;
}
-void AuthTokenTable::AddAuthenticationToken(const HardwareAuthToken* auth_token) {
- Entry new_entry(auth_token, clock_function_());
- //STOPSHIP: debug only, to be removed
- ALOGD("AddAuthenticationToken: timestamp = %llu (%llu), time_received = %lld",
- static_cast<unsigned long long>(new_entry.timestamp_host_order()),
- static_cast<unsigned long long>(auth_token->timestamp),
- static_cast<long long>(new_entry.time_received()));
+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()));
RemoveEntriesSupersededBy(new_entry);
if (entries_.size() >= max_entries_) {
@@ -95,10 +94,8 @@
}
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;
+ if ((algorithm != Algorithm::RSA && algorithm != Algorithm::EC)) return true;
+ if (purpose == KeyPurpose::SIGN || purpose == KeyPurpose::DECRYPT) return true;
return false;
}
@@ -137,13 +134,13 @@
if (op_handle == 0) return OP_HANDLE_REQUIRED;
auto matching_op = find_if(
- entries_, [&](Entry& e) { return e.token()->challenge == op_handle && !e.completed(); });
+ 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;
- *found = matching_op->token();
+ *found = &matching_op->token();
return OK;
}
@@ -172,7 +169,7 @@
}
newest_match->UpdateLastUse(now);
- *found = newest_match->token();
+ *found = &newest_match->token();
return OK;
}
@@ -202,7 +199,7 @@
}
void AuthTokenTable::MarkCompleted(const uint64_t op_handle) {
- auto found = find_if(entries_, [&](Entry& e) { return e.token()->challenge == op_handle; });
+ auto found = find_if(entries_, [&](Entry& e) { return e.token().challenge == op_handle; });
if (found == entries_.end()) return;
assert(!IsSupersededBySomeEntry(*found));
@@ -211,26 +208,15 @@
if (IsSupersededBySomeEntry(*found)) entries_.erase(found);
}
-AuthTokenTable::Entry::Entry(const HardwareAuthToken* token, time_t current_time)
- : token_(token), time_received_(current_time), last_use_(current_time),
- operation_completed_(token_->challenge == 0) {}
-
-uint64_t AuthTokenTable::Entry::timestamp_host_order() const {
- return ntoh(token_->timestamp);
-}
-
-HardwareAuthenticatorType AuthTokenTable::Entry::authenticator_type() const {
- HardwareAuthenticatorType result = static_cast<HardwareAuthenticatorType>(
- ntoh(static_cast<uint32_t>(token_->authenticatorType)));
- return result;
-}
+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 ((sid == token_->authenticatorId) ||
- (sid == token_->userId && (auth_type & authenticator_type()) != 0))
- return true;
+ for (auto sid : sids) {
+ if (SatisfiesAuth(sid, auth_type)) return true;
+ }
return false;
}
@@ -241,10 +227,9 @@
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));
+ return (token_.userId == entry.token_.userId &&
+ token_.authenticatorType == entry.token_.authenticatorType &&
+ token_.authenticatorId == entry.token_.authenticatorId && is_newer_than(&entry));
}
-} // namespace keymaster
+} // namespace keystore
diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h
index 0056b26..db60003 100644
--- a/keystore/auth_token_table.h
+++ b/keystore/auth_token_table.h
@@ -17,15 +17,14 @@
#include <memory>
#include <vector>
-#include <hardware/hw_auth_token.h>
-#include <keystore/authorization_set.h>
+#include <keystore/keymaster_types.h>
#ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_
#define KEYSTORE_AUTH_TOKEN_TABLE_H_
namespace keystore {
-using android::hardware::keymaster::V3_0::HardwareAuthToken;
+using keymaster::HardwareAuthToken;
namespace test {
class AuthTokenTableTest;
@@ -59,9 +58,9 @@
};
/**
- * Add an authorization token to the table. The table takes ownership of the argument.
+ * Add an authorization token to the table.
*/
- void AddAuthenticationToken(const HardwareAuthToken* token);
+ void AddAuthenticationToken(HardwareAuthToken&& auth_token);
/**
* Find an authorization token that authorizes the operation specified by \p operation_handle on
@@ -97,7 +96,7 @@
class Entry {
public:
- Entry(const HardwareAuthToken* token, time_t current_time);
+ Entry(HardwareAuthToken&& token, time_t current_time);
Entry(Entry&& entry) { *this = std::move(entry); }
void operator=(Entry&& rhs) {
@@ -116,8 +115,8 @@
bool is_newer_than(const Entry* entry) const {
if (!entry) return true;
- uint64_t ts = timestamp_host_order();
- uint64_t other_ts = entry->timestamp_host_order();
+ 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)
@@ -127,14 +126,17 @@
void mark_completed() { operation_completed_ = true; }
- const HardwareAuthToken* token() { return token_.get(); }
+ const HardwareAuthToken& token() const & { return token_; }
time_t time_received() const { return time_received_; }
bool completed() const { return operation_completed_; }
- uint64_t timestamp_host_order() const;
- HardwareAuthenticatorType authenticator_type() const;
private:
- std::unique_ptr<const HardwareAuthToken> token_;
+ 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_;
@@ -156,6 +158,6 @@
time_t (*clock_function_)();
};
-} // namespace keymaster
+} // namespace keystore
#endif // KEYSTORE_AUTH_TOKEN_TABLE_H_
diff --git a/keystore/authorization_set.cpp b/keystore/authorization_set.cpp
index e30b32d..537fe3d 100644
--- a/keystore/authorization_set.cpp
+++ b/keystore/authorization_set.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <keystore/authorization_set.h>
+#include <keystore/keymaster_types.h>
#include <assert.h>
#include <stddef.h>
diff --git a/keystore/binder/android/security/IConfirmationPromptCallback.aidl b/keystore/binder/android/security/IConfirmationPromptCallback.aidl
new file mode 100644
index 0000000..96a1a04
--- /dev/null
+++ b/keystore/binder/android/security/IConfirmationPromptCallback.aidl
@@ -0,0 +1,27 @@
+/**
+ * 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/IKeystoreService.aidl b/keystore/binder/android/security/IKeystoreService.aidl
new file mode 100644
index 0000000..db55062
--- /dev/null
+++ b/keystore/binder/android/security/IKeystoreService.aidl
@@ -0,0 +1,89 @@
+/**
+ * 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;
+
+import android.security.keymaster.ExportResult;
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterCertificateChain;
+import android.security.keymaster.KeymasterBlob;
+import android.security.keymaster.OperationResult;
+import android.security.KeystoreArguments;
+
+/**
+ * This must be kept manually in sync with system/security/keystore until AIDL
+ * can generate both Java and C++ bindings.
+ *
+ * @hide
+ */
+interface IKeystoreService {
+ int getState(int userId);
+ byte[] get(String name, int uid);
+ int insert(String name, in byte[] item, int uid, int flags);
+ int del(String name, int uid);
+ int exist(String name, int uid);
+ String[] list(String namePrefix, int uid);
+ int reset();
+ int onUserPasswordChanged(int userId, String newPassword);
+ int lock(int userId);
+ int unlock(int userId, String userPassword);
+ int isEmpty(int userId);
+ int generate(String name, int uid, int keyType, int keySize, int flags,
+ in KeystoreArguments args);
+ int import_key(String name, in byte[] data, int uid, int flags);
+ byte[] sign(String name, in byte[] data);
+ int verify(String name, in byte[] data, in byte[] signature);
+ byte[] get_pubkey(String name);
+ String grant(String name, int granteeUid);
+ int ungrant(String name, int granteeUid);
+ long getmtime(String name, int uid);
+ int is_hardware_backed(String string);
+ int clear_uid(long uid);
+
+ // Keymaster 0.4 methods
+ int addRngEntropy(in byte[] data, int flags);
+ int generateKey(String alias, in KeymasterArguments arguments, in byte[] entropy, int uid,
+ int flags, out KeyCharacteristics characteristics);
+ int getKeyCharacteristics(String alias, in KeymasterBlob clientId, in KeymasterBlob appData,
+ int uid, out KeyCharacteristics characteristics);
+ int importKey(String alias, in KeymasterArguments arguments, int format,
+ in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics);
+ ExportResult exportKey(String alias, int format, in KeymasterBlob clientId,
+ in KeymasterBlob appData, int uid);
+ OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable,
+ in KeymasterArguments params, in byte[] entropy, int uid);
+ OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input);
+ OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature,
+ in byte[] entropy);
+ int abort(IBinder handle);
+ boolean isOperationAuthorized(IBinder token);
+ int addAuthToken(in byte[] authToken);
+ int onUserAdded(int userId, int parentId);
+ int onUserRemoved(int userId);
+ int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain);
+ int attestDeviceIds(in KeymasterArguments params, out KeymasterCertificateChain chain);
+ int onDeviceOffBody();
+ int importWrappedKey(in String wrappedKeyAlias, in byte[] wrappedKey,
+ in String wrappingKeyAlias, in byte[] maskingKey, in KeymasterArguments arguments,
+ in long rootSid, in long fingerprintSid,
+ out KeyCharacteristics characteristics);
+ 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);
+}
diff --git a/keystore/binder/android/security/KeystoreArguments.aidl b/keystore/binder/android/security/KeystoreArguments.aidl
new file mode 100644
index 0000000..dc8ed50
--- /dev/null
+++ b/keystore/binder/android/security/KeystoreArguments.aidl
@@ -0,0 +1,20 @@
+/**
+ * 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;
+
+/* @hide */
+parcelable KeystoreArguments cpp_header "keystore/KeystoreArguments.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/ExportResult.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/ExportResult.aidl
index 0dcbadd..1748653 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/ExportResult.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <keymaster/softkeymaster.h>
-#include <keystore/keystore.h>
+package android.security.keymaster;
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
- = softkeymaster_module;
+/* @hide */
+parcelable ExportResult cpp_header "keystore/ExportResult.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/KeyCharacteristics.aidl
index 0dcbadd..32e75ad 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <keymaster/softkeymaster.h>
-#include <keystore/keystore.h>
+package android.security.keymaster;
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
- = softkeymaster_module;
+/* @hide */
+parcelable KeyCharacteristics cpp_header "keystore/KeyCharacteristics.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/KeymasterArguments.aidl
similarity index 65%
rename from softkeymaster/module.cpp
rename to keystore/binder/android/security/keymaster/KeymasterArguments.aidl
index 0dcbadd..44d9f09 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/KeymasterArguments.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <keymaster/softkeymaster.h>
-#include <keystore/keystore.h>
+package android.security.keymaster;
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
- = softkeymaster_module;
+/* @hide */
+parcelable KeymasterArguments cpp_header "keystore/KeymasterArguments.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/KeymasterBlob.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/KeymasterBlob.aidl
index 0dcbadd..5c5db9e 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/KeymasterBlob.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <keymaster/softkeymaster.h>
-#include <keystore/keystore.h>
+package android.security.keymaster;
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
- = softkeymaster_module;
+/* @hide */
+parcelable KeymasterBlob cpp_header "keystore/KeymasterBlob.h";
diff --git a/keystore/entropy.h b/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl
similarity index 67%
rename from keystore/entropy.h
rename to keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl
index 0e4d1b2..ddb5cae 100644
--- a/keystore/entropy.h
+++ b/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl
@@ -14,21 +14,7 @@
* limitations under the License.
*/
-#ifndef KEYSTORE_ENTROPY_H_
-#define KEYSTORE_ENTROPY_H_
+package android.security.keymaster;
-#include <stdint.h>
-
-class Entropy {
- public:
- Entropy() : mRandom(-1) {}
- ~Entropy();
-
- bool open();
- bool generate_random_data(uint8_t* data, size_t size) const;
-
- private:
- int mRandom;
-};
-
-#endif // KEYSTORE_ENTROPY_H_
+/* @hide */
+parcelable KeymasterCertificateChain cpp_header "keystore/KeymasterCertificateChain.h";
diff --git a/softkeymaster/module.cpp b/keystore/binder/android/security/keymaster/OperationResult.aidl
similarity index 65%
copy from softkeymaster/module.cpp
copy to keystore/binder/android/security/keymaster/OperationResult.aidl
index 0dcbadd..db689d4 100644
--- a/softkeymaster/module.cpp
+++ b/keystore/binder/android/security/keymaster/OperationResult.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <keymaster/softkeymaster.h>
-#include <keystore/keystore.h>
+package android.security.keymaster;
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
- = softkeymaster_module;
+/* @hide */
+parcelable OperationResult cpp_header "keystore/OperationResult.h";
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 625d057..c3956f0 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -19,12 +19,12 @@
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
+#include <openssl/rand.h>
#include <string.h>
#include <cutils/log.h>
#include "blob.h"
-#include "entropy.h"
#include "keystore_utils.h"
@@ -60,16 +60,31 @@
size_t mSize;
};
-/*
- * Encrypt 'len' data at 'in' with AES-GCM, using 128-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'.
+/**
+ * Returns a EVP_CIPHER appropriate for the given key, based on the key's size.
*/
-ResponseCode AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
- const uint8_t* iv, uint8_t* tag) {
- const EVP_CIPHER* cipher = EVP_aes_128_gcm();
+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);
+
EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
- EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
+ 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]);
@@ -93,15 +108,20 @@
}
/*
- * Decrypt 'len' data at 'in' with AES-GCM, using 128-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').
+ * 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 uint8_t* key,
- const uint8_t* iv, const uint8_t* tag) {
- const EVP_CIPHER* cipher = EVP_aes_128_gcm();
+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);
+
EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
- EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
+ 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));
@@ -114,13 +134,13 @@
out_pos += out_len;
if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
ALOGD("Failed to decrypt blob; ciphertext or tag is likely corrupted");
- return ResponseCode::SYSTEM_ERROR;
+ return ResponseCode::VALUE_CORRUPTED;
}
out_pos += out_len;
if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
ALOGD("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
out_pos - out_tmp.get());
- return ResponseCode::SYSTEM_ERROR;
+ return ResponseCode::VALUE_CORRUPTED;
}
std::copy(out_tmp.get(), out_pos, out);
@@ -205,8 +225,8 @@
}
}
-ResponseCode Blob::writeBlob(const std::string& filename, const uint8_t* aes_key, State state,
- Entropy* entropy) {
+ResponseCode Blob::writeBlob(const std::string& filename, const std::vector<uint8_t>& aes_key,
+ State state) {
ALOGV("writing blob %s", filename.c_str());
const size_t dataLength = mBlob.length;
@@ -219,7 +239,7 @@
}
memset(mBlob.initialization_vector, 0, AES_BLOCK_SIZE);
- if (!entropy->generate_random_data(mBlob.initialization_vector, kGcmIvSizeBytes)) {
+ if (!RAND_bytes(mBlob.initialization_vector, kGcmIvSizeBytes)) {
ALOGW("Could not read random data for: %s", filename.c_str());
return ResponseCode::SYSTEM_ERROR;
}
@@ -255,7 +275,8 @@
return ResponseCode::NO_ERROR;
}
-ResponseCode Blob::readBlob(const std::string& filename, const uint8_t* aes_key, State state) {
+ResponseCode Blob::readBlob(const std::string& filename, const std::vector<uint8_t>& aes_key,
+ State state) {
ALOGV("reading blob %s", filename.c_str());
const int in = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY));
if (in < 0) {
@@ -299,7 +320,7 @@
}
AES_KEY key;
- AES_set_decrypt_key(aes_key, kAesKeySize * 8, &key);
+ AES_set_decrypt_key(aes_key.data(), kAesKeySize * 8, &key);
AES_cbc_encrypt(blob.encrypted, blob.encrypted, encryptedLength, &key, blob.vector,
AES_DECRYPT);
key = {}; // clear key
@@ -327,3 +348,12 @@
return ResponseCode::NO_ERROR;
}
+
+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);
+}
diff --git a/keystore/blob.h b/keystore/blob.h
index 5335037..dc70709 100644
--- a/keystore/blob.h
+++ b/keystore/blob.h
@@ -22,12 +22,15 @@
#include <openssl/aes.h>
#include <openssl/md5.h>
+#include <keystore/keymaster_types.h>
#include <keystore/keystore.h>
+#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;
/* 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
@@ -79,10 +82,9 @@
TYPE_KEY_PAIR = 3,
TYPE_KEYMASTER_10 = 4,
TYPE_KEY_CHARACTERISTICS = 5,
+ TYPE_MASTER_KEY_AES256 = 7,
} BlobType;
-class Entropy;
-
class Blob {
public:
Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
@@ -117,9 +119,13 @@
BlobType getType() const { return BlobType(mBlob.type); }
void setType(BlobType type) { mBlob.type = uint8_t(type); }
- ResponseCode writeBlob(const std::string& filename, const uint8_t* aes_key, State state,
- Entropy* entropy);
- ResponseCode readBlob(const std::string& filename, const uint8_t* aes_key, State state);
+ keystore::SecurityLevel getSecurityLevel() const;
+ void setSecurityLevel(keystore::SecurityLevel);
+
+ ResponseCode writeBlob(const std::string& filename, const std::vector<uint8_t>& aes_key,
+ State state);
+ ResponseCode readBlob(const std::string& filename, const std::vector<uint8_t>& aes_key,
+ State state);
private:
blobv3 mBlob;
diff --git a/keystore/confirmation_manager.cpp b/keystore/confirmation_manager.cpp
new file mode 100644
index 0000000..0dee4aa
--- /dev/null
+++ b/keystore/confirmation_manager.cpp
@@ -0,0 +1,216 @@
+/*
+ * 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();
+
+ finalizeTransaction(ConfirmationResponseCode::Aborted, {}, true);
+
+ *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
+ return Status::ok();
+}
+
+// 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,
+ bool callAbortOnHal) {
+ // Note that confirmationUI->abort() may make the remote HAL process do an IPC call back
+ // into our process resulting in confirmationResultCallback() to be called... this in turn
+ // calls finalizeTransaction(). So we have to be careful a) not holding any locks;
+ // and b) ensure state has been cleared; before doing this...
+
+ mMutex.lock();
+ mRateLimiting.processResult(responseCode);
+ sp<IBinder> listener = mCurrentListener;
+ if (mCurrentListener != nullptr) {
+ mCurrentListener->unlinkToDeath(mDeathRecipient);
+ mCurrentListener = nullptr;
+ }
+ sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
+ if (mCurrentConfirmationUI != nullptr) {
+ mCurrentConfirmationUI->unlinkToDeath(this);
+ mCurrentConfirmationUI = nullptr;
+ }
+ mMutex.unlock();
+
+ // Tell the HAL to shut down the confirmation dialog, if requested.
+ if (confirmationUI != nullptr && callAbortOnHal) {
+ confirmationUI->abort();
+ }
+
+ // 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, false);
+ lock_guard<mutex> lock(mMutex);
+ mLatestConfirmationToken = confirmationToken;
+ return Return<void>();
+}
+
+// Called by keystore main thread.
+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");
+ finalizeTransaction(ConfirmationResponseCode::SystemError, {}, true);
+ } 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, {}, false);
+}
+
+} // namespace keystore
diff --git a/keystore/confirmation_manager.h b/keystore/confirmation_manager.h
new file mode 100644
index 0000000..46b623c
--- /dev/null
+++ b/keystore/confirmation_manager.h
@@ -0,0 +1,104 @@
+/*
+ * 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;
+
+ void finalizeTransaction(ConfirmationResponseCode responseCode,
+ hidl_vec<uint8_t> dataThatWasConfirmed, bool callAbortOnHal);
+
+ // 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
new file mode 100644
index 0000000..12c20fa
--- /dev/null
+++ b/keystore/confirmationui_rate_limiting.h
@@ -0,0 +1,124 @@
+/*
+**
+** 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::time_point;
+using std::chrono::duration;
+
+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;
+ }
+
+ void processResult(ConfirmationResponseCode rc) {
+ 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/entropy.cpp b/keystore/entropy.cpp
deleted file mode 100644
index 1bfe9a1..0000000
--- a/keystore/entropy.cpp
+++ /dev/null
@@ -1,49 +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 "entropy.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <cutils/log.h>
-
-#include "keystore_utils.h"
-
-Entropy::~Entropy() {
- if (mRandom >= 0) {
- close(mRandom);
- }
-}
-
-bool Entropy::open() {
- const char* randomDevice = "/dev/urandom";
- mRandom = TEMP_FAILURE_RETRY(::open(randomDevice, O_RDONLY));
- if (mRandom < 0) {
- ALOGE("open: %s: %s", randomDevice, strerror(errno));
- return false;
- }
- return true;
-}
-
-bool Entropy::generate_random_data(uint8_t* data, size_t size) const {
- return (readFully(mRandom, data, size) == size);
-}
diff --git a/keystore/include/keystore/ExportResult.h b/keystore/include/keystore/ExportResult.h
new file mode 100644
index 0000000..b548942
--- /dev/null
+++ b/keystore/include/keystore/ExportResult.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_EXPORTRESULT_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_EXPORTRESULT_H_
+
+#include <binder/Parcelable.h>
+
+#include "keystore_return_types.h"
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+struct ExportResult : public ::android::Parcelable {
+ ExportResult();
+ ~ExportResult();
+ status_t readFromParcel(const Parcel* in) override;
+ status_t writeToParcel(Parcel* out) const override;
+
+ ::keystore::KeyStoreServiceReturnCode resultCode;
+ hardware::hidl_vec<uint8_t> exportData;
+};
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_EXPORTRESULT_H_
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
deleted file mode 100644
index a045679..0000000
--- a/keystore/include/keystore/IKeystoreService.h
+++ /dev/null
@@ -1,254 +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.
- */
-
-#ifndef KEYSTORE_IKEYSTORESERVICE_H
-#define KEYSTORE_IKEYSTORESERVICE_H
-
-#include "keystore.h"
-#include "keystore_return_types.h"
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <keystore/keymaster_tags.h>
-#include <utils/RefBase.h>
-#include <vector>
-
-namespace android {
-
-class KeystoreArg : public RefBase {
- public:
- KeystoreArg(const void* data, size_t len);
- ~KeystoreArg();
-
- const void* data() const;
- size_t size() const;
-
- private:
- const void* mData;
- size_t mSize;
-};
-
-struct MallocDeleter {
- void operator()(uint8_t* p) { free(p); }
-};
-
-// struct for serializing the results of begin/update/finish
-struct OperationResult : public ::android::Parcelable {
- OperationResult();
- ~OperationResult();
- status_t readFromParcel(const Parcel* in) override;
- status_t writeToParcel(Parcel* out) const override;
-
- ::keystore::KeyStoreServiceReturnCode resultCode;
- sp<IBinder> token;
- uint64_t handle;
- int inputConsumed;
- ::keystore::hidl_vec<uint8_t> data;
- ::keystore::hidl_vec<::keystore::KeyParameter> outParams;
-};
-
-// struct for serializing the results of export
-struct ExportResult : public ::android::Parcelable {
- ExportResult();
- ~ExportResult();
- status_t readFromParcel(const Parcel* in) override;
- status_t writeToParcel(Parcel* out) const override;
-
- ::keystore::KeyStoreServiceReturnCode resultCode;
- ::keystore::hidl_vec<uint8_t> exportData;
-};
-
-/*
- * This must be kept manually in sync with frameworks/base's IKeystoreService.java
- */
-class IKeystoreService : public IInterface {
- public:
- enum {
- GET_STATE = IBinder::FIRST_CALL_TRANSACTION + 0,
- GET = IBinder::FIRST_CALL_TRANSACTION + 1,
- INSERT = IBinder::FIRST_CALL_TRANSACTION + 2,
- DEL = IBinder::FIRST_CALL_TRANSACTION + 3,
- EXIST = IBinder::FIRST_CALL_TRANSACTION + 4,
- LIST = IBinder::FIRST_CALL_TRANSACTION + 5,
- RESET = IBinder::FIRST_CALL_TRANSACTION + 6,
- ON_USER_PASSWORD_CHANGED = IBinder::FIRST_CALL_TRANSACTION + 7,
- LOCK = IBinder::FIRST_CALL_TRANSACTION + 8,
- UNLOCK = IBinder::FIRST_CALL_TRANSACTION + 9,
- IS_EMPTY = IBinder::FIRST_CALL_TRANSACTION + 10,
- GENERATE = IBinder::FIRST_CALL_TRANSACTION + 11,
- IMPORT = IBinder::FIRST_CALL_TRANSACTION + 12,
- SIGN = IBinder::FIRST_CALL_TRANSACTION + 13,
- VERIFY = IBinder::FIRST_CALL_TRANSACTION + 14,
- GET_PUBKEY = IBinder::FIRST_CALL_TRANSACTION + 15,
- GRANT = IBinder::FIRST_CALL_TRANSACTION + 16,
- UNGRANT = IBinder::FIRST_CALL_TRANSACTION + 17,
- GETMTIME = IBinder::FIRST_CALL_TRANSACTION + 18,
- DUPLICATE = IBinder::FIRST_CALL_TRANSACTION + 19,
- IS_HARDWARE_BACKED = IBinder::FIRST_CALL_TRANSACTION + 20,
- CLEAR_UID = IBinder::FIRST_CALL_TRANSACTION + 21,
- ADD_RNG_ENTROPY = IBinder::FIRST_CALL_TRANSACTION + 22,
- GENERATE_KEY = IBinder::FIRST_CALL_TRANSACTION + 23,
- GET_KEY_CHARACTERISTICS = IBinder::FIRST_CALL_TRANSACTION + 24,
- IMPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 25,
- EXPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 26,
- BEGIN = IBinder::FIRST_CALL_TRANSACTION + 27,
- UPDATE = IBinder::FIRST_CALL_TRANSACTION + 28,
- FINISH = IBinder::FIRST_CALL_TRANSACTION + 29,
- ABORT = IBinder::FIRST_CALL_TRANSACTION + 30,
- IS_OPERATION_AUTHORIZED = IBinder::FIRST_CALL_TRANSACTION + 31,
- ADD_AUTH_TOKEN = IBinder::FIRST_CALL_TRANSACTION + 32,
- ON_USER_ADDED = IBinder::FIRST_CALL_TRANSACTION + 33,
- ON_USER_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 34,
- ATTEST_KEY = IBinder::FIRST_CALL_TRANSACTION + 35,
- ATTEST_DEVICE_IDS = IBinder::FIRST_CALL_TRANSACTION + 36,
- ON_DEVICE_OFF_BODY = IBinder::FIRST_CALL_TRANSACTION + 37,
- };
-
- DECLARE_META_INTERFACE(KeystoreService);
-
- virtual ::keystore::KeyStoreServiceReturnCode getState(int32_t userId) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
- ::keystore::hidl_vec<uint8_t>* item) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode insert(const String16& name,
- const ::keystore::hidl_vec<uint8_t>& item,
- int uid, int32_t flags) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode del(const String16& name, int uid) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode exist(const String16& name, int uid) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode list(const String16& prefix, int uid,
- Vector<String16>* matches) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode reset() = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- onUserPasswordChanged(int32_t userId, const String16& newPassword) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode lock(int32_t userId) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode unlock(int32_t userId,
- const String16& password) = 0;
-
- virtual bool isEmpty(int32_t userId) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode generate(const String16& name, int32_t uid,
- int32_t keyType, int32_t keySize,
- int32_t flags,
- Vector<sp<KeystoreArg>>* args) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode import(const String16& name,
- const ::keystore::hidl_vec<uint8_t>& data,
- int uid, int32_t flags) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode sign(const String16& name,
- const ::keystore::hidl_vec<uint8_t>& data,
- ::keystore::hidl_vec<uint8_t>* out) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- verify(const String16& name, const ::keystore::hidl_vec<uint8_t>& data,
- const ::keystore::hidl_vec<uint8_t>& signature) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- get_pubkey(const String16& name, ::keystore::hidl_vec<uint8_t>* pubKey) = 0;
-
- virtual String16 grant(const String16& name, int32_t granteeUid) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode ungrant(const String16& name,
- int32_t granteeUid) = 0;
-
- virtual int64_t getmtime(const String16& name, int32_t uid) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey, int32_t destUid) = 0;
-
- virtual int32_t is_hardware_backed(const String16& keyType) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode clear_uid(int64_t uid) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- addRngEntropy(const ::keystore::hidl_vec<uint8_t>& entropy) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- generateKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
- const ::keystore::hidl_vec<uint8_t>& entropy, int uid, int flags,
- ::keystore::KeyCharacteristics* outCharacteristics) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- getKeyCharacteristics(const String16& name, const ::keystore::hidl_vec<uint8_t>& clientId,
- const ::keystore::hidl_vec<uint8_t>& appData, int32_t uid,
- ::keystore::KeyCharacteristics* outCharacteristics) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- importKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
- ::keystore::KeyFormat format, const ::keystore::hidl_vec<uint8_t>& key, int uid,
- int flags, ::keystore::KeyCharacteristics* outCharacteristics) = 0;
-
- virtual void exportKey(const String16& name, ::keystore::KeyFormat format,
- const ::keystore::hidl_vec<uint8_t>& clientId,
- const ::keystore::hidl_vec<uint8_t>& appData, int uid,
- ExportResult* result) = 0;
-
- virtual void begin(const sp<IBinder>& apptoken, const String16& name,
- ::keystore::KeyPurpose purpose, bool pruneable,
- const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
- const ::keystore::hidl_vec<uint8_t>& entropy, int32_t uid,
- OperationResult* opResult) = 0;
-
- virtual void update(const sp<IBinder>& token,
- const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
- const ::keystore::hidl_vec<uint8_t>& data, OperationResult* opResult) = 0;
-
- virtual void finish(const sp<IBinder>& token,
- const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
- const ::keystore::hidl_vec<uint8_t>& signature,
- const ::keystore::hidl_vec<uint8_t>& entropy,
- OperationResult* opResult) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode abort(const sp<IBinder>& handle) = 0;
-
- virtual bool isOperationAuthorized(const sp<IBinder>& handle) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode addAuthToken(const uint8_t* token,
- size_t length) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode onUserRemoved(int32_t userId) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode
- attestKey(const String16& name, const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
- ::keystore::hidl_vec<::keystore::hidl_vec<uint8_t>>* outChain) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode attestDeviceIds(
- const ::keystore::hidl_vec<::keystore::KeyParameter>& params,
- ::keystore::hidl_vec<::keystore::hidl_vec<uint8_t>>* outChain) = 0;
-
- virtual ::keystore::KeyStoreServiceReturnCode onDeviceOffBody() = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnKeystoreService : public BnInterface<IKeystoreService> {
- public:
- virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0);
-};
-
-} // namespace android
-
-#endif
diff --git a/keystore/include/keystore/KeyAttestationApplicationId.h b/keystore/include/keystore/KeyAttestationApplicationId.h
index a7ce210..c612929 100644
--- a/keystore/include/keystore/KeyAttestationApplicationId.h
+++ b/keystore/include/keystore/KeyAttestationApplicationId.h
@@ -15,12 +15,13 @@
#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
-#include "KeyAttestationPackageInfo.h"
-#include "utils.h"
-#include <binder/Parcelable.h>
#include <memory>
#include <vector>
+#include <binder/Parcelable.h>
+
+#include "KeyAttestationPackageInfo.h"
+
namespace android {
namespace security {
namespace keymaster {
@@ -29,6 +30,8 @@
public:
typedef SharedNullableIterator<const KeyAttestationPackageInfo, std::vector>
ConstKeyAttestationPackageInfoIterator;
+ KeyAttestationApplicationId();
+ KeyAttestationApplicationId(std::unique_ptr<KeyAttestationPackageInfo> package);
status_t writeToParcel(Parcel*) const override;
status_t readFromParcel(const Parcel* parcel) override;
@@ -46,6 +49,6 @@
} // namespace keymaster
} // namespace security
-} // namsepace android
+} // namespace android
#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
diff --git a/keystore/include/keystore/KeyAttestationPackageInfo.h b/keystore/include/keystore/KeyAttestationPackageInfo.h
index b938e83..92d4863 100644
--- a/keystore/include/keystore/KeyAttestationPackageInfo.h
+++ b/keystore/include/keystore/KeyAttestationPackageInfo.h
@@ -15,12 +15,15 @@
#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include <binder/Parcelable.h>
+
#include "Signature.h"
#include "utils.h"
-#include <binder/Parcelable.h>
-#include <memory>
-#include <stdint.h>
-#include <vector>
namespace android {
namespace security {
@@ -30,20 +33,27 @@
public:
typedef SharedNullableIterator<const content::pm::Signature, std::vector>
ConstSignatureIterator;
+ typedef std::vector<std::unique_ptr<content::pm::Signature>>
+ SignaturesVector;
+ typedef std::shared_ptr<SignaturesVector> SharedSignaturesVector;
+
+ KeyAttestationPackageInfo(const String16& packageName, int64_t versionCode,
+ SharedSignaturesVector signatures);
+ KeyAttestationPackageInfo();
status_t writeToParcel(Parcel*) const override;
status_t readFromParcel(const Parcel* parcel) override;
const std::unique_ptr<String16>& package_name() const { return packageName_; }
- int32_t version_code() const { return versionCode_; }
+ int64_t version_code() const { return versionCode_; }
ConstSignatureIterator sigs_begin() const { return ConstSignatureIterator(signatures_); }
ConstSignatureIterator sigs_end() const { return ConstSignatureIterator(); }
private:
std::unique_ptr<String16> packageName_;
- int32_t versionCode_;
- std::shared_ptr<std::vector<std::unique_ptr<content::pm::Signature>>> signatures_;
+ int64_t versionCode_;
+ SharedSignaturesVector signatures_;
};
} // namespace keymaster
diff --git a/keystore/include/keystore/KeyCharacteristics.h b/keystore/include/keystore/KeyCharacteristics.h
new file mode 100644
index 0000000..7fc89c6
--- /dev/null
+++ b/keystore/include/keystore/KeyCharacteristics.h
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYCHARACTERISTICS_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYCHARACTERISTICS_H_
+
+#include <binder/Parcelable.h>
+
+#include "KeymasterArguments.h"
+#include "keymaster_types.h"
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+// Parcelable version of keystore::KeyCharacteristics
+struct KeyCharacteristics : public ::android::Parcelable {
+ KeyCharacteristics(){};
+ explicit KeyCharacteristics(const keystore::KeyCharacteristics& other) {
+ softwareEnforced = KeymasterArguments(other.softwareEnforced);
+ hardwareEnforced = KeymasterArguments(other.hardwareEnforced);
+ }
+ status_t readFromParcel(const Parcel* in) override;
+ status_t writeToParcel(Parcel* out) const override;
+
+ KeymasterArguments softwareEnforced;
+ KeymasterArguments hardwareEnforced;
+};
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYCHARACTERISTICS_H_
diff --git a/keystore/include/keystore/KeymasterArguments.h b/keystore/include/keystore/KeymasterArguments.h
new file mode 100644
index 0000000..99074f8
--- /dev/null
+++ b/keystore/include/keystore/KeymasterArguments.h
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERARGUMENTS_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERARGUMENTS_H_
+
+#include <binder/Parcelable.h>
+
+#include <keystore/keymaster_types.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+// struct for serializing/deserializing a list of KeyParameters
+struct KeymasterArguments : public Parcelable {
+ KeymasterArguments(){};
+ explicit KeymasterArguments(const hardware::hidl_vec<keystore::KeyParameter>& other);
+
+ status_t readFromParcel(const Parcel* in) override;
+ status_t writeToParcel(Parcel* out) const override;
+
+ const inline hardware::hidl_vec<keystore::KeyParameter>& getParameters() const { return data_; }
+
+ private:
+ hardware::hidl_vec<keystore::KeyParameter> data_;
+};
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERARGUMENTS_H_
diff --git a/keystore/include/keystore/KeymasterBlob.h b/keystore/include/keystore/KeymasterBlob.h
new file mode 100644
index 0000000..fc849bd
--- /dev/null
+++ b/keystore/include/keystore/KeymasterBlob.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERBLOB_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERBLOB_H_
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+// Parcelable which wraps hardware::hidl_vec<uint8_t>
+struct KeymasterBlob : public ::android::Parcelable {
+ KeymasterBlob(){};
+ explicit KeymasterBlob(hardware::hidl_vec<uint8_t> data) : data_(data) {}
+ status_t readFromParcel(const Parcel* in) override;
+ status_t writeToParcel(Parcel* out) const override;
+ const hardware::hidl_vec<uint8_t>& getData() const { return data_; }
+
+ private:
+ hardware::hidl_vec<uint8_t> data_;
+};
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERBLOB_H_
diff --git a/keystore/include/keystore/KeymasterCertificateChain.h b/keystore/include/keystore/KeymasterCertificateChain.h
new file mode 100644
index 0000000..132862c
--- /dev/null
+++ b/keystore/include/keystore/KeymasterCertificateChain.h
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERCERTIFICATECHAIN_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERCERTIFICATECHAIN_H_
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+// struct for serializing keymaster_cert_chain_t's
+struct KeymasterCertificateChain : public ::android::Parcelable {
+ KeymasterCertificateChain(){};
+ explicit KeymasterCertificateChain(hardware::hidl_vec<hardware::hidl_vec<uint8_t>> other)
+ : chain(std::move(other)) {}
+
+ status_t readFromParcel(const Parcel* in) override;
+ status_t writeToParcel(Parcel* out) const override;
+
+ private:
+ // The structure is only used as output and doesn't have getter.
+ hardware::hidl_vec<hardware::hidl_vec<uint8_t>> chain;
+};
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYMASTERCERTIFICATECHAIN_H_
diff --git a/keystore/include/keystore/KeystoreArg.h b/keystore/include/keystore/KeystoreArg.h
new file mode 100644
index 0000000..a5e68f2
--- /dev/null
+++ b/keystore/include/keystore/KeystoreArg.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+namespace security {
+
+// Simple pair of generic pointer and length of corresponding data structure.
+class KeystoreArg : public RefBase {
+ public:
+ KeystoreArg(const void* data, size_t len) : mData(data), mSize(len) {}
+ ~KeystoreArg() {}
+
+ const void* data() const { return mData; }
+ size_t size() const { return mSize; }
+
+ private:
+ const void* mData; // provider of the data must handle memory clean-up.
+ size_t mSize;
+};
+
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARG_H
diff --git a/keystore/include/keystore/KeystoreArguments.h b/keystore/include/keystore/KeystoreArguments.h
new file mode 100644
index 0000000..c0a8b0a
--- /dev/null
+++ b/keystore/include/keystore/KeystoreArguments.h
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_
+
+#include <binder/Parcelable.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+#include "KeystoreArg.h"
+#include "keystore_return_types.h"
+
+namespace android {
+namespace security {
+
+// Parcelable KeystoreArguments.java which simply holds byte[][].
+struct KeystoreArguments : public ::android::Parcelable, public RefBase {
+ status_t readFromParcel(const Parcel* in) override;
+ status_t writeToParcel(Parcel* out) const override;
+
+ const Vector<sp<KeystoreArg>>& getArguments() const { return args; }
+
+ private:
+ Vector<sp<KeystoreArg>> args;
+};
+
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYSTOREARGUMENTS_H_
diff --git a/keystore/include/keystore/OperationResult.h b/keystore/include/keystore/OperationResult.h
new file mode 100644
index 0000000..2ceda9a
--- /dev/null
+++ b/keystore/include/keystore/OperationResult.h
@@ -0,0 +1,46 @@
+// 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.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_OPERATIONRESULT_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_OPERATIONRESULT_H_
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+#include "keymaster_types.h"
+#include "keystore_return_types.h"
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+struct OperationResult : public ::android::Parcelable {
+ OperationResult();
+ status_t readFromParcel(const Parcel* in) override;
+ status_t writeToParcel(Parcel* out) const override;
+
+ // Native code may need to use KeyStoreNativeReturnCode
+ ::keystore::KeyStoreServiceReturnCode resultCode;
+ sp<IBinder> token;
+ uint64_t handle;
+ int inputConsumed;
+ ::keystore::hidl_vec<uint8_t> data;
+ ::keystore::hidl_vec<::keystore::KeyParameter> outParams;
+};
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_OPERATIONRESULT_H_
diff --git a/keystore/include/keystore/Signature.h b/keystore/include/keystore/Signature.h
index 59b77bf..3c996bb 100644
--- a/keystore/include/keystore/Signature.h
+++ b/keystore/include/keystore/Signature.h
@@ -15,10 +15,10 @@
#ifndef KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
#define KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
-#include <binder/Parcelable.h>
-#include <stdint.h>
#include <vector>
+#include <binder/Parcelable.h>
+
namespace android {
namespace content {
namespace pm {
diff --git a/keystore/include/keystore/authorization_set.h b/keystore/include/keystore/authorization_set.h
deleted file mode 100644
index 0e57a19..0000000
--- a/keystore/include/keystore/authorization_set.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright 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 SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
-#define SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
-
-#include "keymaster_tags.h"
-#include <vector>
-
-namespace keystore {
-
-class AuthorizationSetBuilder;
-
-/**
- * An ordered collection of KeyParameters. It provides memory ownership and some convenient
- * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters.
- * For serialization, wrap the backing store of this structure in a hidl_vec<KeyParameter>.
- */
-class AuthorizationSet {
- public:
- /**
- * Construct an empty, dynamically-allocated, growable AuthorizationSet.
- */
- AuthorizationSet() {};
-
- // Copy constructor.
- AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
-
- // Move constructor.
- AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {}
-
- // Constructor from hidl_vec<KeyParameter>
- AuthorizationSet(const hidl_vec<KeyParameter>& other) {
- *this = other;
- }
-
- // Copy assignment.
- AuthorizationSet& operator=(const AuthorizationSet& other) {
- data_ = other.data_;
- return *this;
- }
-
- // Move assignment.
- AuthorizationSet& operator=(AuthorizationSet&& other) {
- data_ = std::move(other.data_);
- return *this;
- }
-
- AuthorizationSet& operator=(const hidl_vec<KeyParameter>& other) {
- if (other.size() > 0) {
- data_.resize(other.size());
- for (size_t i = 0; i < data_.size(); ++i) {
- /* This makes a deep copy even of embedded blobs.
- * See assignment operator/copy constructor of hidl_vec.*/
- data_[i] = other[i];
- }
- }
- return *this;
- }
-
- /**
- * Clear existing authorization set data
- */
- void Clear();
-
- ~AuthorizationSet() = default;
-
- /**
- * Returns the size of the set.
- */
- size_t size() const { return data_.size(); }
-
- /**
- * Returns true if the set is empty.
- */
- bool empty() const { return size() == 0; }
-
- /**
- * Returns the data in the set, directly. Be careful with this.
- */
- const KeyParameter* data() const { return data_.data(); }
-
- /**
- * Sorts the set
- */
- void Sort();
-
- /**
- * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
- * AuthorizationSetBuilder).
- */
- void Deduplicate();
-
- /**
- * Adds all elements from \p set that are not already present in this AuthorizationSet. As a
- * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
- */
- void Union(const AuthorizationSet& set);
-
- /**
- * Removes all elements in \p set from this AuthorizationSet.
- */
- void Subtract(const AuthorizationSet& set);
-
- /**
- * Returns the offset of the next entry that matches \p tag, starting from the element after \p
- * begin. If not found, returns -1.
- */
- int find(Tag tag, int begin = -1) const;
-
- /**
- * Removes the entry at the specified index. Returns true if successful, false if the index was
- * out of bounds.
- */
- bool erase(int index);
-
- /**
- * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
- */
- std::vector<KeyParameter>::const_iterator begin() const { return data_.begin(); }
-
- /**
- * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
- */
- std::vector<KeyParameter>::const_iterator end() const { return data_.end(); }
-
- /**
- * Returns the nth element of the set.
- * Like for std::vector::operator[] there is no range check performed. Use of out of range
- * indices is undefined.
- */
- KeyParameter& operator[](int n);
-
- /**
- * Returns the nth element of the set.
- * Like for std::vector::operator[] there is no range check performed. Use of out of range
- * indices is undefined.
- */
- const KeyParameter& operator[](int n) const;
-
- /**
- * Returns true if the set contains at least one instance of \p tag
- */
- bool Contains(Tag tag) const {
- return find(tag) != -1;
- }
-
- template <TagType tag_type, Tag tag, typename ValueT>
- bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
- for (const auto& param: data_) {
- auto entry = authorizationValue(ttag, param);
- if (entry.isOk() && entry.value() == value) return true;
- }
- return false;
- }
- /**
- * Returns the number of \p tag entries.
- */
- size_t GetTagCount(Tag tag) const;
-
- template <typename T>
- inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
- auto entry = GetEntry(tag);
- if (entry.isOk()) return authorizationValue(tag, entry.value());
- return {};
- }
-
- void push_back(const KeyParameter& param) {
- data_.push_back(param);
- }
- void push_back(KeyParameter&& param) {
- data_.push_back(std::move(param));
- }
-
- /**
- * Append the tag and enumerated value to the set.
- * "val" may be exactly one parameter unless a boolean parameter is added.
- * In this case "val" is omitted. This condition is checked at compile time by Authorization()
- */
- template <typename TypedTagT, typename... Value>
- void push_back(TypedTagT tag, Value&&... val) {
- push_back(Authorization(tag, std::forward<Value>(val)...));
- }
-
- template <typename Iterator>
- void append(Iterator begin, Iterator end) {
- while (begin != end) {
- push_back(*begin);
- ++begin;
- }
- }
-
- hidl_vec<KeyParameter> hidl_data() const {
- hidl_vec<KeyParameter> result;
- result.setToExternal(const_cast<KeyParameter*>(data()), size());
- return result;
- }
-
- void Serialize(std::ostream* out) const;
- void Deserialize(std::istream* in);
-
- private:
- NullOr<const KeyParameter&> GetEntry(Tag tag) const;
-
- std::vector<KeyParameter> data_;
-};
-
-class AuthorizationSetBuilder: public AuthorizationSet {
- public:
- template <typename TagType, typename... ValueType>
- AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) {
- push_back(ttag, std::forward<ValueType>(value)...);
- return *this;
- }
-
- template <Tag tag>
- AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data,
- size_t data_length) {
- hidl_vec<uint8_t> new_blob;
- new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
- push_back(ttag, std::move(new_blob));
- return *this;
- }
-
- template <Tag tag>
- AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const char* data,
- size_t data_length) {
- return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length);
- }
-
- AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
- AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
- AuthorizationSetBuilder& AesKey(uint32_t key_size);
- AuthorizationSetBuilder& HmacKey(uint32_t key_size);
-
- AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
- AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
- AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
- AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
-
- AuthorizationSetBuilder& SigningKey();
- AuthorizationSetBuilder& EncryptionKey();
- AuthorizationSetBuilder& NoDigestOrPadding();
- AuthorizationSetBuilder& EcbMode();
-
- AuthorizationSetBuilder& Digest(Digest digest) {
- return Authorization(TAG_DIGEST, digest);
- }
-
- AuthorizationSetBuilder& Padding(PaddingMode padding) {
- return Authorization(TAG_PADDING, padding);
- }
-};
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
- uint64_t public_exponent) {
- Authorization(TAG_ALGORITHM, Algorithm::RSA);
- Authorization(TAG_KEY_SIZE, key_size);
- Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
- return *this;
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
- Authorization(TAG_ALGORITHM, Algorithm::EC);
- Authorization(TAG_KEY_SIZE, key_size);
- return *this;
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
- Authorization(TAG_ALGORITHM, Algorithm::AES);
- return Authorization(TAG_KEY_SIZE, key_size);
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
- Authorization(TAG_ALGORITHM, Algorithm::HMAC);
- Authorization(TAG_KEY_SIZE, key_size);
- return SigningKey();
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
- uint64_t public_exponent) {
- RsaKey(key_size, public_exponent);
- return SigningKey();
-}
-
-inline AuthorizationSetBuilder&
-AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) {
- RsaKey(key_size, public_exponent);
- return EncryptionKey();
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
- EcdsaKey(key_size);
- return SigningKey();
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
- AesKey(key_size);
- return EncryptionKey();
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
- Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
- return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
- Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT);
- return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT);
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
- Authorization(TAG_DIGEST, Digest::NONE);
- return Authorization(TAG_PADDING, PaddingMode::NONE);
-}
-
-inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
- return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
-}
-
-} // namespace keystore
-
-#endif // SYSTEM_SECURITY_KEYSTORE_AUTHORIZATION_SET_H_
diff --git a/keystore/include/keystore/keymaster_tags.h b/keystore/include/keystore/keymaster_tags.h
deleted file mode 100644
index 05a33cd..0000000
--- a/keystore/include/keystore/keymaster_tags.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright 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 SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
-#define SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
-
-/**
- * This header contains various definitions that make working with keymaster tags safer and easier.
- *
- * It makes use of a fair amount of template metaprogramming. The metaprogramming serves the purpose
- * of making it impossible to make certain classes of mistakes when operating on keymaster
- * authorizations. For example, it's an error to create a KeyParameter with tag == Tag::PURPOSE
- * and then to assign Algorithm::RSA to algorithm element of its union. But because the user
- * must choose the union field, there could be a mismatch which the compiler has now way to
- * diagnose.
- *
- * The machinery in this header solves these problems by describing which union field corresponds
- * to which Tag. Central to this mechanism is the template TypedTag. It has zero size and binds a
- * numeric Tag to a type that the compiler understands. By means of the macro DECLARE_TYPED_TAG,
- * we declare types for each of the tags defined in hardware/interfaces/keymaster/2.0/types.hal.
- *
- * The macro DECLARE_TYPED_TAG(name) generates a typename TAG_name_t and a zero sized instance
- * TAG_name. Once these typed tags have been declared we define metafunctions mapping the each tag
- * to its value c++ type and the correct union element of KeyParameter. This is done by means of
- * the macros MAKE_TAG_*VALUE_ACCESSOR, which generates TypedTag2ValueType, a metafunction mapping
- * a typed tag to the corresponding c++ type, and access function, accessTagValue returning a
- * reference to the correct element of KeyParameter.
- * E.g.:
- * given "KeyParameter param;" then "accessTagValue(TAG_PURPOSE, param)"
- * yields a reference to param.f.purpose
- * If used in an assignment the compiler can now check the compatibility of the assigned value.
- *
- * For convenience we also provide the constructor like function Authorization().
- * Authorization takes a typed tag and a value and checks at compile time whether the value given
- * is suitable for the given tag. At runtime it creates a new KeyParameter initialized with the
- * given tag and value and returns it by value.
- *
- * The second convenience function, authorizationValue, allows access to the KeyParameter value in
- * a safe way. It takes a typed tag and a KeyParameter and returns a reference to the value wrapped
- * by NullOr. NullOr has out-of-band information about whether it is save to access the wrapped
- * reference.
- * E.g.:
- * auto param = Authorization(TAG_ALGORITM, Algorithm::RSA);
- * auto value1 = authorizationValue(TAG_PURPOSE, param);
- * auto value2 = authorizationValue(TAG_ALGORITM, param);
- * value1.isOk() yields false, but value2.isOk() yields true, thus value2.value() is save to access.
- */
-
-#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
-#include <hardware/hw_auth_token.h>
-#include <type_traits>
-
-namespace keystore {
-
-using ::android::hardware::keymaster::V3_0::Algorithm;
-using ::android::hardware::keymaster::V3_0::BlockMode;
-using ::android::hardware::keymaster::V3_0::Digest;
-using ::android::hardware::keymaster::V3_0::EcCurve;
-using ::android::hardware::keymaster::V3_0::ErrorCode;
-using ::android::hardware::keymaster::V3_0::HardwareAuthToken;
-using ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
-using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
-using ::android::hardware::keymaster::V3_0::KeyBlobUsageRequirements;
-using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
-using ::android::hardware::keymaster::V3_0::KeyDerivationFunction;
-using ::android::hardware::keymaster::V3_0::KeyFormat;
-using ::android::hardware::keymaster::V3_0::KeyOrigin;
-using ::android::hardware::keymaster::V3_0::KeyParameter;
-using ::android::hardware::keymaster::V3_0::KeyPurpose;
-using ::android::hardware::keymaster::V3_0::PaddingMode;
-using ::android::hardware::keymaster::V3_0::Tag;
-using ::android::hardware::keymaster::V3_0::TagType;
-
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-
-// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have. We
-// need these old values to be able to support old keys that use them.
-static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
-static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
-
-constexpr TagType typeFromTag(Tag tag) {
- return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
-}
-
-/**
- * TypedTag is a templatized version of Tag, which provides compile-time checking of
- * keymaster tag types. Instances are convertible to Tag, so they can be used wherever
- * Tag is expected, and because they encode the tag type it's possible to create
- * function overloads that only operate on tags with a particular type.
- */
-template <TagType tag_type, Tag tag> struct TypedTag {
- inline TypedTag() {
- // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
- // 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile
- // error (no match for template specialization StaticAssert<false>), with no run-time cost.
- static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type");
- }
- operator Tag() const { return tag; }
-};
-
-template <Tag tag> struct Tag2TypedTag { typedef TypedTag<typeFromTag(tag), tag> type; };
-
-template <Tag tag> struct Tag2String;
-
-#define _TAGS_STRINGIFY(x) #x
-#define TAGS_STRINGIFY(x) _TAGS_STRINGIFY(x)
-
-#define DECLARE_TYPED_TAG(name) \
- typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
- extern TAG_##name##_t TAG_##name; \
- template <> struct Tag2String<Tag::name> { \
- static const char* value() { return "Tag::" TAGS_STRINGIFY(name); } \
- }
-
-DECLARE_TYPED_TAG(INVALID);
-DECLARE_TYPED_TAG(KEY_SIZE);
-DECLARE_TYPED_TAG(MAC_LENGTH);
-DECLARE_TYPED_TAG(CALLER_NONCE);
-DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
-DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
-DECLARE_TYPED_TAG(ECIES_SINGLE_HASH_MODE);
-DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
-DECLARE_TYPED_TAG(ACTIVE_DATETIME);
-DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
-DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
-DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
-DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
-DECLARE_TYPED_TAG(ALL_USERS);
-DECLARE_TYPED_TAG(USER_ID);
-DECLARE_TYPED_TAG(USER_SECURE_ID);
-DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
-DECLARE_TYPED_TAG(AUTH_TIMEOUT);
-DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
-DECLARE_TYPED_TAG(ALL_APPLICATIONS);
-DECLARE_TYPED_TAG(APPLICATION_ID);
-DECLARE_TYPED_TAG(APPLICATION_DATA);
-DECLARE_TYPED_TAG(CREATION_DATETIME);
-DECLARE_TYPED_TAG(ROLLBACK_RESISTANT);
-DECLARE_TYPED_TAG(ROOT_OF_TRUST);
-DECLARE_TYPED_TAG(ASSOCIATED_DATA);
-DECLARE_TYPED_TAG(NONCE);
-DECLARE_TYPED_TAG(AUTH_TOKEN);
-DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
-DECLARE_TYPED_TAG(OS_VERSION);
-DECLARE_TYPED_TAG(OS_PATCHLEVEL);
-DECLARE_TYPED_TAG(UNIQUE_ID);
-DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
-DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
-DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
-
-DECLARE_TYPED_TAG(PURPOSE);
-DECLARE_TYPED_TAG(ALGORITHM);
-DECLARE_TYPED_TAG(BLOCK_MODE);
-DECLARE_TYPED_TAG(DIGEST);
-DECLARE_TYPED_TAG(PADDING);
-DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
-DECLARE_TYPED_TAG(ORIGIN);
-DECLARE_TYPED_TAG(USER_AUTH_TYPE);
-DECLARE_TYPED_TAG(KDF);
-DECLARE_TYPED_TAG(EC_CURVE);
-
-template <typename... Elems> struct MetaList {};
-
-using all_tags_t = MetaList<
- TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
- TAG_RSA_PUBLIC_EXPONENT_t, TAG_ECIES_SINGLE_HASH_MODE_t, TAG_INCLUDE_UNIQUE_ID_t,
- TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
- TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_ALL_USERS_t, TAG_USER_ID_t,
- TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
- TAG_ALL_APPLICATIONS_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t,
- TAG_ROLLBACK_RESISTANT_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
- TAG_AUTH_TOKEN_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
- TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t,
- TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
- TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_KDF_t, TAG_EC_CURVE_t>;
-
-/* implementation in keystore_utils.cpp */
-extern const char* stringifyTag(Tag tag);
-
-template <typename TypedTagType> struct TypedTag2ValueType;
-
-#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
- template <Tag tag> struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
- typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
- }; \
- template <Tag tag> \
- inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \
- ->const decltype(param.field_name)& { \
- return param.field_name; \
- } \
- template <Tag tag> \
- inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) \
- ->decltype(param.field_name)& { \
- return param.field_name; \
- }
-
-MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger)
-MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger)
-MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime)
-MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer)
-MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer)
-MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue)
-MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
-MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
-
-#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \
- template <> struct TypedTag2ValueType<decltype(typed_tag)> { \
- typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
- }; \
- inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \
- ->const decltype(param.field_name)& { \
- return param.field_name; \
- } \
- inline auto accessTagValue(decltype(typed_tag), KeyParameter& param) \
- ->decltype(param.field_name)& { \
- return param.field_name; \
- }
-
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_KDF, f.keyDerivationFunction)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType)
-
-template <TagType tag_type, Tag tag, typename ValueT>
-inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
- KeyParameter param;
- param.tag = tag;
- param.f.longInteger = 0;
- accessTagValue(ttag, param) = std::forward<ValueT>(value);
- return param;
-}
-
-// the boolean case
-template <Tag tag> inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
- KeyParameter param;
- param.tag = tag;
- param.f.boolValue = true;
- return param;
-}
-
-template <typename... Pack> struct FirstOrNoneHelper;
-template <typename First> struct FirstOrNoneHelper<First> { typedef First type; };
-template <> struct FirstOrNoneHelper<> {
- struct type {};
-};
-
-template <typename... Pack> using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
-
-template <TagType tag_type, Tag tag, typename... Args>
-inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
- static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
- "TagType::BOOL Authorizations do not take parameters. Presence is truth.");
- static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
- "Authorization other then TagType::BOOL take exactly one parameter.");
- static_assert(
- tag_type == TagType::BOOL ||
- std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
- typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
- "Invalid argument type for given tag.");
-
- return makeKeyParameter(ttag, std::forward<Args>(args)...);
-}
-
-/**
- * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
- * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
- * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
- * wrapped value. In this case the pointer will be NULL though, and the value will be default
- * constructed.
- */
-template <typename ValueT> class NullOr {
- template <typename T> struct reference_initializer {
- static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
- };
- template <typename T> struct pointer_initializer {
- static T init() { return nullptr; }
- };
- template <typename T> struct value_initializer {
- static T init() { return T(); }
- };
- template <typename T>
- using initializer_t =
- std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
- std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
- value_initializer<T>>>;
-
- public:
- NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
- NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
-
- bool isOk() const { return !null_; }
-
- const ValueT& value() const & { return value_; }
- ValueT& value() & { return value_; }
- ValueT&& value() && { return std::move(value_); }
-
- private:
- ValueT value_;
- bool null_;
-};
-
-template <typename T> std::remove_reference_t<T> NullOrOr(T&& v) {
- if (v.isOk()) return v;
- return {};
-}
-
-template <typename Head, typename... Tail>
-std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
- if (head.isOk()) return head;
- return NullOrOr(std::forward<Tail>(tail)...);
-}
-
-template <typename Default, typename Wrapped>
-std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
- static_assert(std::is_convertible<std::remove_reference_t<Default>,
- std::remove_reference_t<Wrapped>>::value,
- "Type of default value must match the type wrapped by NullOr");
- if (optional.isOk()) return optional.value();
- return def;
-}
-
-template <TagType tag_type, Tag tag>
-inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&>
-authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
- if (tag != param.tag) return {};
- return accessTagValue(ttag, param);
-}
-
-} // namespace keymaster
-
-#endif // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
diff --git a/keystore/include/keystore/keymaster_types.h b/keystore/include/keystore/keymaster_types.h
new file mode 100644
index 0000000..f3c6907
--- /dev/null
+++ b/keystore/include/keystore/keymaster_types.h
@@ -0,0 +1,104 @@
+// 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.
+
+#ifndef SECURITY_KEYSTORE_INCLUDE_KEYSTORE_KEYMASTER_TYPES_H_
+#define SECURITY_KEYSTORE_INCLUDE_KEYSTORE_KEYMASTER_TYPES_H_
+
+#include <android/hardware/keymaster/3.0/types.h>
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.0/types.h>
+
+#include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/keymaster_tags.h>
+
+/**
+ * This header lifts the types from the current Keymaster version into the keystore namespace.
+ */
+
+namespace keystore {
+
+// Changing this namespace alias will change the keymaster version.
+namespace keymaster = ::android::hardware::keymaster::V4_0;
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+
+using keymaster::IKeymasterDevice;
+using keymaster::SecurityLevel;
+
+using keymaster::AuthorizationSet;
+using keymaster::AuthorizationSetBuilder;
+
+using keymaster::Algorithm;
+using keymaster::BlockMode;
+using keymaster::Digest;
+using keymaster::EcCurve;
+using keymaster::ErrorCode;
+using keymaster::HardwareAuthenticatorType;
+using keymaster::HardwareAuthToken;
+using keymaster::HmacSharingParameters;
+using keymaster::KeyCharacteristics;
+using keymaster::KeyFormat;
+using keymaster::KeyParameter;
+using keymaster::KeyPurpose;
+using keymaster::OperationHandle;
+using keymaster::PaddingMode;
+using keymaster::SecurityLevel;
+using keymaster::Tag;
+using keymaster::TagType;
+using keymaster::VerificationToken;
+
+using keymaster::TAG_ACTIVE_DATETIME;
+using keymaster::TAG_ALGORITHM;
+using keymaster::TAG_ALLOW_WHILE_ON_BODY;
+using keymaster::TAG_APPLICATION_DATA;
+using keymaster::TAG_APPLICATION_ID;
+using keymaster::TAG_ATTESTATION_APPLICATION_ID;
+using keymaster::TAG_AUTH_TIMEOUT;
+using keymaster::TAG_BLOB_USAGE_REQUIREMENTS;
+using keymaster::TAG_BLOCK_MODE;
+using keymaster::TAG_DIGEST;
+using keymaster::TAG_EC_CURVE;
+using keymaster::TAG_KEY_SIZE;
+using keymaster::TAG_MAC_LENGTH;
+using keymaster::TAG_MAX_USES_PER_BOOT;
+using keymaster::TAG_MIN_MAC_LENGTH;
+using keymaster::TAG_MIN_SECONDS_BETWEEN_OPS;
+using keymaster::TAG_NO_AUTH_REQUIRED;
+using keymaster::TAG_NONCE;
+using keymaster::TAG_ORIGIN;
+using keymaster::TAG_ORIGINATION_EXPIRE_DATETIME;
+using keymaster::TAG_PADDING;
+using keymaster::TAG_PURPOSE;
+using keymaster::TAG_RESET_SINCE_ID_ROTATION;
+using keymaster::TAG_RSA_PUBLIC_EXPONENT;
+using keymaster::TAG_USAGE_EXPIRE_DATETIME;
+using keymaster::TAG_USER_AUTH_TYPE;
+using keymaster::TAG_USER_ID;
+using keymaster::TAG_USER_SECURE_ID;
+
+using keymaster::NullOr;
+
+using Km3HardwareAuthToken = ::android::hardware::keymaster::V3_0::HardwareAuthToken;
+using Km3HardwareAuthenticatorType =
+ ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
+
+// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have. We
+// need these old values to be able to support old keys that use them.
+constexpr int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
+constexpr int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
+
+} // namespace keystore
+
+#endif // SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h
index 7260363..07f645f 100644
--- a/keystore/include/keystore/keystore.h
+++ b/keystore/include/keystore/keystore.h
@@ -26,6 +26,7 @@
STATE_UNINITIALIZED = 3,
};
+// must be in sync with KeyStore.java,
enum class ResponseCode: int32_t {
NO_ERROR = STATE_NO_ERROR, // 1
LOCKED = STATE_LOCKED, // 2
@@ -62,25 +63,7 @@
// encrypted, and it will be stored separately under an unique UID instead. This flag should
// only be available to system uid.
KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3,
+ KEYSTORE_FLAG_STRONGBOX = 1 << 4,
};
-/**
- * Returns the size of the softkey magic header value for measuring
- * and allocating purposes.
- */
-size_t get_softkey_header_size();
-
-/**
- * Adds the magic softkey header to a key blob.
- *
- * Returns NULL if the destination array is too small. Otherwise it
- * returns the offset directly after the magic value.
- */
-uint8_t* add_softkey_header(uint8_t* key_blob, size_t key_blob_length);
-
-/**
- * Returns true if the key blob has a magic softkey header at the beginning.
- */
-bool is_softkey(const uint8_t* key_blob, const size_t key_blob_length);
-
#endif
diff --git a/keystore/include/keystore/keystore_client.h b/keystore/include/keystore/keystore_client.h
index 2ba7fd4..d6a4807 100644
--- a/keystore/include/keystore/keystore_client.h
+++ b/keystore/include/keystore/keystore_client.h
@@ -21,14 +21,12 @@
#include <android-base/macros.h>
-#include "authorization_set.h"
+#include "keymaster_types.h"
#include "keystore.h"
#include "keystore_return_types.h"
namespace keystore {
-
-
// An abstract class providing a convenient interface to keystore services. This
// interface is designed to:
// - hide details of the IPC mechanism (e.g. binder)
@@ -64,7 +62,7 @@
// Note: implementations may generate more than one key but they will always
// have |key_name| as a prefix.
virtual bool encryptWithAuthentication(const std::string& key_name, const std::string& data,
- std::string* encrypted_data) = 0;
+ int32_t flags, std::string* encrypted_data) = 0;
// Decrypts and authenticates |encrypted_data| as output by
// EncryptWithAuthentication using the key(s) identified by |key_name|. On
@@ -87,17 +85,18 @@
// Adds |entropy| to the random number generator. Returns KM_ERROR_OK on
// success and a Keystore ResponseCode or keymaster_error_t on failure.
- virtual KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy) = 0;
+ virtual KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy,
+ int32_t flags) = 0;
// Generates a key according to the given |key_parameters| and stores it with
// the given |key_name|. The [hardware|software]_enforced_characteristics of
// the key are provided on success. Returns KM_ERROR_OK on success. Returns
// KM_ERROR_OK on success and a Keystore ResponseCode or keymaster_error_t on
// failure.
- virtual KeyStoreNativeReturnCode generateKey(const std::string& key_name,
- const keystore::AuthorizationSet& key_parameters,
- keystore::AuthorizationSet* hardware_enforced_characteristics,
- keystore::AuthorizationSet* software_enforced_characteristics) = 0;
+ virtual KeyStoreNativeReturnCode
+ generateKey(const std::string& key_name, const keystore::AuthorizationSet& key_parameters,
+ int32_t flags, keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::AuthorizationSet* software_enforced_characteristics) = 0;
// Provides the [hardware|software]_enforced_characteristics of a key
// identified by |key_name|. Returns KM_ERROR_OK on success and a Keystore
@@ -112,17 +111,17 @@
// [hardware|software]_enforced_characteristics of the key are provided on
// success. Returns KM_ERROR_OK on success and a Keystore ResponseCode or
// keymaster_error_t on failure.
- virtual KeyStoreNativeReturnCode importKey(const std::string& key_name,
- const keystore::AuthorizationSet& key_parameters,
- KeyFormat key_format, const std::string& key_data,
- keystore::AuthorizationSet* hardware_enforced_characteristics,
- keystore::AuthorizationSet* software_enforced_characteristics) = 0;
+ virtual KeyStoreNativeReturnCode
+ importKey(const std::string& key_name, const keystore::AuthorizationSet& key_parameters,
+ KeyFormat key_format, const std::string& key_data,
+ keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::AuthorizationSet* software_enforced_characteristics) = 0;
// Exports the public key identified by |key_name| to |export_data| using
// |export_format|. Returns KM_ERROR_OK on success and a Keystore ResponseCode
// or keymaster_error_t on failure.
virtual KeyStoreNativeReturnCode exportKey(KeyFormat export_format, const std::string& key_name,
- std::string* export_data) = 0;
+ std::string* export_data) = 0;
// Deletes the key identified by |key_name|. Returns KM_ERROR_OK on success
// and a Keystore ResponseCode or keymaster_error_t on failure.
@@ -137,32 +136,30 @@
// |input_parameters|. On success, any |output_parameters| and an operation
// |handle| are populated. Returns KM_ERROR_OK on success and a Keystore
// ResponseCode or keymaster_error_t on failure.
- virtual KeyStoreNativeReturnCode beginOperation(KeyPurpose purpose, const std::string& key_name,
- const keystore::AuthorizationSet& input_parameters,
- keystore::AuthorizationSet* output_parameters,
- uint64_t* handle) = 0;
+ virtual KeyStoreNativeReturnCode
+ beginOperation(KeyPurpose purpose, const std::string& key_name,
+ const keystore::AuthorizationSet& input_parameters,
+ keystore::AuthorizationSet* output_parameters, uint64_t* handle) = 0;
// Continues the operation associated with |handle| using the given
// |input_parameters| and |input_data|. On success, the
// |num_input_bytes_consumed| and any |output_parameters| are populated. Any
// |output_data| will be appended. Returns KM_ERROR_OK on success and a
// Keystore ResponseCode or keymaster_error_t on failure.
- virtual KeyStoreNativeReturnCode updateOperation(uint64_t handle,
- const keystore::AuthorizationSet& input_parameters,
- const std::string& input_data, size_t* num_input_bytes_consumed,
- keystore::AuthorizationSet* output_parameters,
- std::string* output_data) = 0;
+ virtual KeyStoreNativeReturnCode
+ updateOperation(uint64_t handle, const keystore::AuthorizationSet& input_parameters,
+ const std::string& input_data, size_t* num_input_bytes_consumed,
+ keystore::AuthorizationSet* output_parameters, std::string* output_data) = 0;
// Finishes the operation associated with |handle| using the given
// |input_parameters| and, if necessary, a |signature_to_verify|. On success,
// any |output_parameters| are populated and |output_data| is appended.
// Returns KM_ERROR_OK on success and a Keystore ResponseCode or
// keymaster_error_t on failure.
- virtual KeyStoreNativeReturnCode finishOperation(uint64_t handle,
- const keystore::AuthorizationSet& input_parameters,
- const std::string& signature_to_verify,
- keystore::AuthorizationSet* output_parameters,
- std::string* output_data) = 0;
+ virtual KeyStoreNativeReturnCode
+ finishOperation(uint64_t handle, const keystore::AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ keystore::AuthorizationSet* output_parameters, std::string* output_data) = 0;
// Aborts the operation associated with |handle|. Returns KM_ERROR_OK on
// success and a Keystore ResponseCode or keymaster_error_t on failure.
diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h
index eb02275..9edd082 100644
--- a/keystore/include/keystore/keystore_client_impl.h
+++ b/keystore/include/keystore/keystore_client_impl.h
@@ -17,13 +17,13 @@
#include "keystore_client.h"
-#include <string>
#include <map>
+#include <string>
#include <vector>
+#include <android/security/IKeystoreService.h>
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
-#include "IKeystoreService.h"
#include <utils/StrongPointer.h>
namespace keystore {
@@ -35,7 +35,7 @@
// KeystoreClient methods.
bool encryptWithAuthentication(const std::string& key_name, const std::string& data,
- std::string* encrypted_data) override;
+ int32_t flags, std::string* encrypted_data) override;
bool decryptWithAuthentication(const std::string& key_name, const std::string& encrypted_data,
std::string* data) override;
bool oneShotOperation(KeyPurpose purpose, const std::string& key_name,
@@ -43,38 +43,40 @@
const std::string& input_data, const std::string& signature_to_verify,
keystore::AuthorizationSet* output_parameters,
std::string* output_data) override;
- KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy) override;
- KeyStoreNativeReturnCode generateKey(const std::string& key_name,
- const keystore::AuthorizationSet& key_parameters,
- keystore::AuthorizationSet* hardware_enforced_characteristics,
- keystore::AuthorizationSet* software_enforced_characteristics) override;
+ KeyStoreNativeReturnCode addRandomNumberGeneratorEntropy(const std::string& entropy,
+ int32_t flags) override;
+ KeyStoreNativeReturnCode
+ generateKey(const std::string& key_name, const keystore::AuthorizationSet& key_parameters,
+ int32_t flags, keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::AuthorizationSet* software_enforced_characteristics) override;
KeyStoreNativeReturnCode
getKeyCharacteristics(const std::string& key_name,
keystore::AuthorizationSet* hardware_enforced_characteristics,
keystore::AuthorizationSet* software_enforced_characteristics) override;
- KeyStoreNativeReturnCode importKey(const std::string& key_name,
- const keystore::AuthorizationSet& key_parameters,
- KeyFormat key_format, const std::string& key_data,
- keystore::AuthorizationSet* hardware_enforced_characteristics,
- keystore::AuthorizationSet* software_enforced_characteristics) override;
+ KeyStoreNativeReturnCode
+ importKey(const std::string& key_name, const keystore::AuthorizationSet& key_parameters,
+ KeyFormat key_format, const std::string& key_data,
+ keystore::AuthorizationSet* hardware_enforced_characteristics,
+ keystore::AuthorizationSet* software_enforced_characteristics) override;
KeyStoreNativeReturnCode exportKey(KeyFormat export_format, const std::string& key_name,
- std::string* export_data) override;
+ std::string* export_data) override;
KeyStoreNativeReturnCode deleteKey(const std::string& key_name) override;
KeyStoreNativeReturnCode deleteAllKeys() override;
KeyStoreNativeReturnCode beginOperation(KeyPurpose purpose, const std::string& key_name,
- const keystore::AuthorizationSet& input_parameters,
- keystore::AuthorizationSet* output_parameters,
- uint64_t* handle) override;
+ const keystore::AuthorizationSet& input_parameters,
+ keystore::AuthorizationSet* output_parameters,
+ uint64_t* handle) override;
KeyStoreNativeReturnCode updateOperation(uint64_t handle,
- const keystore::AuthorizationSet& input_parameters,
- const std::string& input_data, size_t* num_input_bytes_consumed,
- keystore::AuthorizationSet* output_parameters,
- std::string* output_data) override;
+ const keystore::AuthorizationSet& input_parameters,
+ const std::string& input_data,
+ size_t* num_input_bytes_consumed,
+ keystore::AuthorizationSet* output_parameters,
+ std::string* output_data) override;
KeyStoreNativeReturnCode finishOperation(uint64_t handle,
- const keystore::AuthorizationSet& input_parameters,
- const std::string& signature_to_verify,
- keystore::AuthorizationSet* output_parameters,
- std::string* output_data) override;
+ const keystore::AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ keystore::AuthorizationSet* output_parameters,
+ std::string* output_data) override;
KeyStoreNativeReturnCode abortOperation(uint64_t handle) override;
bool doesKeyExist(const std::string& key_name) override;
bool listKeys(const std::string& prefix, std::vector<std::string>* key_name_list) override;
@@ -85,15 +87,15 @@
// Maps a keystore error code to a code where all success cases use
// KM_ERROR_OK (not keystore's NO_ERROR).
-// int32_t mapKeystoreError(int32_t keystore_error);
+ // int32_t mapKeystoreError(int32_t keystore_error);
// Creates an encryption key suitable for EncryptWithAuthentication or
// verifies attributes if the key already exists. Returns true on success.
- bool createOrVerifyEncryptionKey(const std::string& key_name);
+ bool createOrVerifyEncryptionKey(const std::string& key_name, int32_t flags);
// Creates an authentication key suitable for EncryptWithAuthentication or
// verifies attributes if the key already exists. Returns true on success.
- bool createOrVerifyAuthenticationKey(const std::string& key_name);
+ bool createOrVerifyAuthenticationKey(const std::string& key_name, int32_t flags);
// Verifies attributes of an encryption key suitable for
// EncryptWithAuthentication. Returns true on success and populates |verified|
@@ -107,7 +109,7 @@
android::sp<android::IServiceManager> service_manager_;
android::sp<android::IBinder> keystore_binder_;
- android::sp<android::IKeystoreService> keystore_;
+ android::sp<android::security::IKeystoreService> keystore_;
uint64_t next_virtual_handle_ = 1;
std::map<uint64_t, android::sp<android::IBinder>> active_operations_;
diff --git a/keystore/include/keystore/keystore_client_mock.h b/keystore/include/keystore/keystore_client_mock.h
index 2d1f499..b16367f 100644
--- a/keystore/include/keystore/keystore_client_mock.h
+++ b/keystore/include/keystore/keystore_client_mock.h
@@ -15,8 +15,8 @@
#ifndef KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
#define KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
-#include "gmock/gmock.h"
#include "keystore/keystore_client.h"
+#include "gmock/gmock.h"
using testing::_;
diff --git a/keystore/include/keystore/keystore_get.h b/keystore/include/keystore/keystore_get.h
index 4bddd70..4c3d838 100644
--- a/keystore/include/keystore/keystore_get.h
+++ b/keystore/include/keystore/keystore_get.h
@@ -30,7 +30,7 @@
* length. The third argument is a pointer to an array that will be malloc()
* and the caller is responsible for calling free() on the buffer.
*/
-ssize_t keystore_get(const char *key, size_t length, uint8_t** value);
+ssize_t keystore_get(const char* key, size_t length, uint8_t** value);
#ifdef __cplusplus
}
diff --git a/keystore/include/keystore/keystore_hidl_support.h b/keystore/include/keystore/keystore_hidl_support.h
index 3c64d2a..781b153 100644
--- a/keystore/include/keystore/keystore_hidl_support.h
+++ b/keystore/include/keystore/keystore_hidl_support.h
@@ -18,15 +18,24 @@
#ifndef KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
#define KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
-#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-#include <hidl/Status.h>
-#include <keystore/keymaster_tags.h>
#include <ostream>
#include <sstream>
#include <string>
+#include <android-base/logging.h>
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <hardware/hw_auth_token.h>
+#include <hidl/Status.h>
+#include <keymasterV4_0/keymaster_utils.h>
+
+#include <keystore/keymaster_types.h>
+
namespace keystore {
+using android::hardware::keymaster::V4_0::support::blob2hidlVec;
+using android::hardware::keymaster::V4_0::support::hidlVec2AuthToken;
+using android::hardware::keymaster::V4_0::support::authToken2HidlVec;
+
inline static std::ostream& formatArgs(std::ostream& out) {
return out;
}
@@ -65,46 +74,22 @@
#define KS_HANDLE_HIDL_ERROR(rc) \
::keystore::ksHandleHidlError(rc, __FILE__, ":", __LINE__, ":", __PRETTY_FUNCTION__)
-inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length,
- bool inPlace = true) {
- hidl_vec<uint8_t> result;
- if (inPlace)
- result.setToExternal(const_cast<unsigned char*>(data), length);
- else {
- result.resize(length);
- memcpy(&result[0], data, length);
- }
- return result;
-}
-
-inline static hidl_vec<uint8_t> blob2hidlVec(const std::string& value) {
- hidl_vec<uint8_t> result;
- result.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<std::string::value_type*>(value.data())),
- static_cast<size_t>(value.size()));
- return result;
-}
-
-inline static hidl_vec<uint8_t> blob2hidlVec(const std::vector<uint8_t>& blob) {
- hidl_vec<uint8_t> result;
- result.setToExternal(const_cast<uint8_t*>(blob.data()), static_cast<size_t>(blob.size()));
- return result;
-}
-
template <typename T, typename OutIter>
inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
return std::copy(value_ptr, value_ptr + sizeof(value), dest);
}
-inline static hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
- static_assert(
- std::is_same<decltype(token.hmac), ::android::hardware::hidl_array<uint8_t, 32>>::value,
- "This function assumes token HMAC is 32 bytes, but it might not be.");
+constexpr size_t kHmacSize = 32;
+
+inline static hidl_vec<uint8_t> authToken2HidlVec(const Km3HardwareAuthToken& token) {
+ static_assert(std::is_same<decltype(token.hmac),
+ ::android::hardware::hidl_array<uint8_t, kHmacSize>>::value,
+ "This function assumes token HMAC is 32 bytes, but it might not be.");
static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
- sizeof(token.timestamp) + 32 /* HMAC size */
- == sizeof(hw_auth_token_t),
+ sizeof(token.timestamp) + kHmacSize ==
+ sizeof(hw_auth_token_t),
"HardwareAuthToken content size does not match hw_auth_token_t size");
hidl_vec<uint8_t> result;
@@ -121,6 +106,38 @@
return result;
}
+template <typename T, typename InIter>
+inline static InIter copy_bytes_from_iterator(T* value, InIter src) {
+ uint8_t* value_ptr = reinterpret_cast<uint8_t*>(value);
+ std::copy(src, src + sizeof(T), value_ptr);
+ return src + sizeof(T);
+}
+
+inline static Km3HardwareAuthToken hidlVec2Km3AuthToken(const hidl_vec<uint8_t>& buffer) {
+ Km3HardwareAuthToken token;
+ static_assert(std::is_same<decltype(token.hmac),
+ ::android::hardware::hidl_array<uint8_t, kHmacSize>>::value,
+ "This function assumes token HMAC is 32 bytes, but it might not be.");
+ static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
+ sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+ sizeof(token.timestamp) + kHmacSize ==
+ sizeof(hw_auth_token_t),
+ "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+ if (buffer.size() != sizeof(hw_auth_token_t)) return {};
+
+ auto pos = buffer.begin();
+ ++pos; // skip first byte
+ pos = copy_bytes_from_iterator(&token.challenge, pos);
+ pos = copy_bytes_from_iterator(&token.userId, pos);
+ pos = copy_bytes_from_iterator(&token.authenticatorId, pos);
+ pos = copy_bytes_from_iterator(&token.authenticatorType, pos);
+ pos = copy_bytes_from_iterator(&token.timestamp, pos);
+ pos = std::copy(pos, pos + token.hmac.size(), &token.hmac[0]);
+
+ return token;
+}
+
inline std::string hidlVec2String(const hidl_vec<uint8_t>& value) {
return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
}
diff --git a/keystore/include/keystore/keystore_return_types.h b/keystore/include/keystore/keystore_return_types.h
index 70380c3..fa4a224 100644
--- a/keystore/include/keystore/keystore_return_types.h
+++ b/keystore/include/keystore/keystore_return_types.h
@@ -18,12 +18,12 @@
#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
#define KEYSTORE_INCLUDE_KEYSTORE_KEYSTORE_RETURN_TYPES_H_
+#include "keymaster_types.h"
#include "keystore.h"
-#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
namespace keystore {
-using ::android::hardware::keymaster::V3_0::ErrorCode;
+using keymaster::ErrorCode;
class KeyStoreServiceReturnCode;
class KeyStoreNativeReturnCode;
@@ -46,6 +46,7 @@
KeyStoreServiceReturnCode(const KeyStoreServiceReturnCode& errorCode)
: errorCode_(errorCode.errorCode_) {}
KeyStoreServiceReturnCode(const KeyStoreNativeReturnCode& errorCode);
+ explicit inline KeyStoreServiceReturnCode(const int32_t& errorCode) : errorCode_(errorCode) {}
inline KeyStoreServiceReturnCode& operator=(const ErrorCode& errorCode) {
errorCode_ = int32_t(errorCode);
return *this;
@@ -62,8 +63,9 @@
return errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR) ||
errorCode_ == static_cast<int32_t>(ErrorCode::OK);
}
+
inline operator int32_t() const {
- if (!errorCode_) return static_cast<int32_t>(ResponseCode::NO_ERROR);
+ if (!errorCode_) return static_cast<int32_t>(ResponseCode::NO_ERROR /* 1 */);
return errorCode_;
}
inline bool operator==(const ResponseCode& rhs) const {
@@ -117,6 +119,7 @@
KeyStoreNativeReturnCode(const ResponseCode& errorCode) : errorCode_(int32_t(errorCode)) {}
KeyStoreNativeReturnCode(const KeyStoreNativeReturnCode& errorCode)
: errorCode_(errorCode.errorCode_) {}
+ explicit inline KeyStoreNativeReturnCode(const int32_t& errorCode) : errorCode_(errorCode) {}
KeyStoreNativeReturnCode(const KeyStoreServiceReturnCode& errorcode);
inline KeyStoreNativeReturnCode& operator=(const ErrorCode& errorCode) {
errorCode_ = int32_t(errorCode);
@@ -135,8 +138,8 @@
errorCode_ == static_cast<int32_t>(ErrorCode::OK);
}
inline operator int32_t() const {
- if (errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR)) {
- return static_cast<int32_t>(ErrorCode::OK);
+ if (errorCode_ == static_cast<int32_t>(ResponseCode::NO_ERROR) /* 1 */) {
+ return static_cast<int32_t>(ErrorCode::OK) /* 0 */;
}
return errorCode_;
}
diff --git a/keystore/key_config.proto b/keystore/key_config.proto
new file mode 100644
index 0000000..0b1a398
--- /dev/null
+++ b/keystore/key_config.proto
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package keystore;
+
+option optimize_for = LITE_RUNTIME;
+
+message KeyConfig {
+ // What type of encryption algorithm is this key being generated/imported for
+ // e.g. AES, RSA, etc
+ optional string algorithm = 1;
+
+ // Size of the key being generated/imported
+ optional int32 key_size = 2;
+
+ // Log whether the key was generated, imported, securely imported, or derived.
+ optional string origin = 3;
+
+ // What auth types does this key require? If none, then no auth required.
+ optional string user_auth_type = 4;
+
+ // If user authentication is required, is the requirement time based? If it
+ // is not time based then this field will not be used and the key is per
+ // operation. Per operation keys must be user authenticated on each usage.
+ optional int32 user_auth_key_timeout = 5;
+
+ // Track which padding modes this key supports.
+ repeated string padding = 6;
+
+ // Track which digests this key supports
+ repeated string digest = 7;
+
+ // Check what block mode is being used depending on the mode of encryption
+ repeated string block_mode = 8;
+
+ // Was the key generated/imported successfully?
+ optional bool was_creation_successful = 9;
+
+ // What purposes can this key be used for?
+ repeated string purpose = 10;
+
+ // Which ec curve was selected if elliptic curve cryptography is in use
+ optional string ec_curve = 11;
+
+ // Standalone or is a file system required
+ optional string key_blob_usage_reqs = 12;
+}
diff --git a/keystore/key_proto_handler.cpp b/keystore/key_proto_handler.cpp
new file mode 100644
index 0000000..3bf8c06
--- /dev/null
+++ b/keystore/key_proto_handler.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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_proto_handler.h"
+
+#include <android/os/DropBoxManager.h>
+#include <google/protobuf/message_lite.h>
+#include <keymasterV4_0/Keymaster.h>
+#include <keystore/keymaster_types.h>
+#include <utils/String16.h>
+
+#include "key_config.pb.h"
+
+namespace keystore {
+
+void checkEnforcedCharacteristics(const hidl_vec<KeyParameter>& keyParams, KeyConfig* keyConfig) {
+ for (auto& keyParam : keyParams) {
+ switch (keyParam.tag) {
+ case Tag::PURPOSE:
+ keyConfig->add_purpose(toString(accessTagValue(TAG_PURPOSE, keyParam)));
+ break;
+ case Tag::ALGORITHM:
+ keyConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, keyParam)));
+ break;
+ case Tag::KEY_SIZE:
+ keyConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, keyParam));
+ break;
+ case Tag::BLOCK_MODE:
+ keyConfig->add_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, keyParam)));
+ break;
+ case Tag::PADDING:
+ keyConfig->add_padding(toString(accessTagValue(TAG_PADDING, keyParam)));
+ break;
+ case Tag::DIGEST:
+ keyConfig->add_digest(toString(accessTagValue(TAG_DIGEST, keyParam)));
+ break;
+ case Tag::EC_CURVE:
+ keyConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, keyParam)));
+ break;
+ case Tag::AUTH_TIMEOUT:
+ keyConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, keyParam));
+ break;
+ case Tag::ORIGIN:
+ keyConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, keyParam)));
+ break;
+ case Tag::BLOB_USAGE_REQUIREMENTS:
+ keyConfig->set_key_blob_usage_reqs(
+ toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, keyParam)));
+ break;
+ case Tag::USER_AUTH_TYPE:
+ keyConfig->set_user_auth_type(toString(accessTagValue(TAG_USER_AUTH_TYPE, keyParam)));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
+ bool wasCreationSuccessful) {
+ KeyConfig keyConfig;
+ checkEnforcedCharacteristics(keyParams, &keyConfig);
+ auto dropbox = std::make_unique<android::os::DropBoxManager>();
+ keyConfig.set_was_creation_successful(wasCreationSuccessful);
+
+ size_t size = keyConfig.ByteSize();
+ auto data = std::make_unique<uint8_t[]>(size);
+ keyConfig.SerializeWithCachedSizesToArray(data.get());
+ dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
+}
+
+} // namespace keystore
diff --git a/keystore/key_proto_handler.h b/keystore/key_proto_handler.h
new file mode 100644
index 0000000..a2f6a24
--- /dev/null
+++ b/keystore/key_proto_handler.h
@@ -0,0 +1,29 @@
+/*
+ * 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_KEY_PROTO_HANDLER_H_
+#define KEYSTORE_KEY_PROTO_HANDLER_H_
+
+#include <keystore/keystore_hidl_support.h>
+
+namespace keystore {
+
+void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
+ bool wasCreationSuccessful);
+
+} // namespace keystore
+
+#endif // KEYSTORE_KEY_PROTO_HANDLER_H_
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 39341ef..400c814 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "keystore"
#include "key_store_service.h"
+#include "include/keystore/KeystoreArg.h"
#include <fcntl.h>
#include <sys/stat.h>
@@ -24,30 +25,47 @@
#include <algorithm>
#include <sstream>
+#include <android-base/scopeguard.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>
+#include <log/log_event_list.h>
#include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
#include "defaults.h"
+#include "key_proto_handler.h"
#include "keystore_attestation_id.h"
#include "keystore_keymaster_enforcement.h"
#include "keystore_utils.h"
#include <keystore/keystore_hidl_support.h>
+#include <hardware/hw_auth_token.h>
+
namespace keystore {
using namespace android;
namespace {
+using ::android::binder::Status;
+using android::security::KeystoreArg;
+using android::security::keymaster::ExportResult;
+using android::security::keymaster::KeymasterArguments;
+using android::security::keymaster::KeymasterBlob;
+using android::security::keymaster::KeymasterCertificateChain;
+using android::security::keymaster::OperationResult;
+using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
+
constexpr size_t kMaxOperations = 15;
constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
const char* kTimestampFilePath = "timestamp";
+const int ID_ATTESTATION_REQUEST_GENERIC_INFO = 1 << 0;
+const int ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID = 1 << 1;
struct BIGNUM_Delete {
void operator()(BIGNUM* p) const { BN_free(p); }
@@ -126,58 +144,56 @@
void KeyStoreService::binderDied(const wp<IBinder>& who) {
auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
for (const auto& token : operations) {
- abort(token);
+ int32_t unused_result;
+ abort(token, &unused_result);
}
+ mConfirmationManager->binderDied(who);
}
-KeyStoreServiceReturnCode KeyStoreService::getState(int32_t userId) {
+Status KeyStoreService::getState(int32_t userId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_GET_STATE)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
-
- return ResponseCode(mKeyStore->getState(userId));
+ *aidl_return = mKeyStore->getState(userId);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::get(const String16& name, int32_t uid,
- hidl_vec<uint8_t>* item) {
+Status KeyStoreService::get(const String16& name, int32_t uid, ::std::vector<uint8_t>* item) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(uid);
if (!checkBinderPermission(P_GET, targetUid)) {
- return ResponseCode::PERMISSION_DENIED;
+ // see keystore/keystore.h
+ return Status::fromServiceSpecificError(
+ static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
}
String8 name8(name);
Blob keyBlob;
-
KeyStoreServiceReturnCode rc =
mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_GENERIC);
if (!rc.isOk()) {
- if (item) *item = hidl_vec<uint8_t>();
- return rc;
+ *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));
}
-
- // Do not replace this with "if (item) *item = blob2hidlVec(keyBlob)"!
- // blob2hidlVec creates a hidl_vec<uint8_t> that references, but not owns, the data in keyBlob
- // the subsequent assignment (*item = resultBlob) makes a deep copy, so that *item will own the
- // corresponding resources.
auto resultBlob = blob2hidlVec(keyBlob);
- if (item) {
- *item = resultBlob;
- }
-
- return ResponseCode::NO_ERROR;
+ // 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();
}
-KeyStoreServiceReturnCode KeyStoreService::insert(const String16& name,
- const hidl_vec<uint8_t>& item, int targetUid,
- int32_t flags) {
+Status KeyStoreService::insert(const String16& name, const ::std::vector<uint8_t>& item,
+ int targetUid, int32_t flags, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
targetUid = getEffectiveUid(targetUid);
- auto result =
+ KeyStoreServiceReturnCode result =
checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
if (!result.isOk()) {
- return result;
+ *aidl_return = static_cast<int32_t>(result);
+ return Status::ok();
}
String8 name8(name);
@@ -186,77 +202,98 @@
Blob keyBlob(&item[0], item.size(), NULL, 0, ::TYPE_GENERIC);
keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
- return mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid));
+ *aidl_return =
+ static_cast<int32_t>(mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid)));
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::del(const String16& name, int targetUid) {
+Status KeyStoreService::del(const String16& name, int targetUid, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_DELETE, targetUid)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
String8 name8(name);
ALOGI("del %s %d", name8.string(), targetUid);
auto filename = mKeyStore->getBlobFileNameIfExists(name8, targetUid, ::TYPE_ANY);
- if (!filename.isOk()) return ResponseCode::KEY_NOT_FOUND;
+ if (!filename.isOk()) {
+ *aidl_return = static_cast<int32_t>(ResponseCode::KEY_NOT_FOUND);
+ return Status::ok();
+ }
- ResponseCode result = mKeyStore->del(filename.value().string(), ::TYPE_ANY,
- get_user_id(targetUid));
+ ResponseCode result =
+ mKeyStore->del(filename.value().string(), ::TYPE_ANY, get_user_id(targetUid));
if (result != ResponseCode::NO_ERROR) {
- return result;
+ *aidl_return = static_cast<int32_t>(result);
+ return Status::ok();
}
filename = mKeyStore->getBlobFileNameIfExists(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS);
if (filename.isOk()) {
- return mKeyStore->del(filename.value().string(), ::TYPE_KEY_CHARACTERISTICS,
- get_user_id(targetUid));
+ *aidl_return = static_cast<int32_t>(mKeyStore->del(
+ filename.value().string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid)));
+ return Status::ok();
}
- return ResponseCode::NO_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::exist(const String16& name, int targetUid) {
+Status KeyStoreService::exist(const String16& name, int targetUid, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_EXIST, targetUid)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
auto filename = mKeyStore->getBlobFileNameIfExists(String8(name), targetUid, ::TYPE_ANY);
- return filename.isOk() ? ResponseCode::NO_ERROR : ResponseCode::KEY_NOT_FOUND;
+ *aidl_return = static_cast<int32_t>(filename.isOk() ? ResponseCode::NO_ERROR
+ : ResponseCode::KEY_NOT_FOUND);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::list(const String16& prefix, int targetUid,
- Vector<String16>* matches) {
+Status KeyStoreService::list(const String16& prefix, int targetUid,
+ ::std::vector<::android::String16>* matches) {
KEYSTORE_SERVICE_LOCK;
targetUid = getEffectiveUid(targetUid);
if (!checkBinderPermission(P_LIST, targetUid)) {
- return ResponseCode::PERMISSION_DENIED;
+ return Status::fromServiceSpecificError(
+ static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
}
const String8 prefix8(prefix);
String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid, TYPE_ANY));
-
- if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
- return ResponseCode::SYSTEM_ERROR;
+ android::Vector<android::String16> matches_internal;
+ if (mKeyStore->list(filename, &matches_internal, get_user_id(targetUid)) !=
+ ResponseCode::NO_ERROR) {
+ return Status::fromServiceSpecificError(static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
}
- return ResponseCode::NO_ERROR;
+ matches->clear();
+ for (size_t i = 0; i < matches_internal.size(); ++i) {
+ matches->push_back(matches_internal[i]);
+ }
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::reset() {
+Status KeyStoreService::reset(int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_RESET)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
mKeyStore->resetUser(get_user_id(callingUid), false);
- return ResponseCode::NO_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::onUserPasswordChanged(int32_t userId,
- const String16& password) {
+Status KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password,
+ int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_PASSWORD)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
const String8 password8(password);
@@ -267,32 +304,38 @@
if (password.size() == 0) {
ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
mKeyStore->resetUser(userId, true);
- return ResponseCode::NO_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
} else {
switch (mKeyStore->getState(userId)) {
case ::STATE_UNINITIALIZED: {
// generate master key, encrypt with password, write to file,
// initialize mMasterKey*.
- return mKeyStore->initializeUser(password8, userId);
+ *aidl_return = static_cast<int32_t>(mKeyStore->initializeUser(password8, userId));
+ return Status::ok();
}
case ::STATE_NO_ERROR: {
// rewrite master key with new password.
- return mKeyStore->writeMasterKey(password8, userId);
+ *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);
- return mKeyStore->initializeUser(password8, userId);
+ *aidl_return = static_cast<int32_t>(mKeyStore->initializeUser(password8, userId));
+ return Status::ok();
}
}
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
}
-KeyStoreServiceReturnCode KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
+Status KeyStoreService::onUserAdded(int32_t userId, int32_t parentId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_USER_CHANGED)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
// Sanity check that the new user has an empty keystore.
@@ -306,42 +349,51 @@
// 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.
- return mKeyStore->copyMasterKey(parentId, userId);
+ *aidl_return = static_cast<int32_t>(mKeyStore->copyMasterKey(parentId, userId));
+ return Status::ok();
} else {
- return ResponseCode::NO_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
}
}
-KeyStoreServiceReturnCode KeyStoreService::onUserRemoved(int32_t userId) {
+Status KeyStoreService::onUserRemoved(int32_t userId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_USER_CHANGED)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
mKeyStore->resetUser(userId, false);
- return ResponseCode::NO_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::lock(int32_t userId) {
+Status KeyStoreService::lock(int32_t userId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_LOCK)) {
- return ResponseCode::PERMISSION_DENIED;
+ *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);
- return ResponseCode(state);
+ *aidl_return = static_cast<int32_t>(ResponseCode(state));
+ return Status::ok();
}
+ enforcement_policy.set_device_locked(true, userId);
mKeyStore->lock(userId);
- return ResponseCode::NO_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::unlock(int32_t userId, const String16& pw) {
+Status KeyStoreService::unlock(int32_t userId, const String16& pw, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_UNLOCK)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
State state = mKeyStore->getState(userId);
@@ -357,32 +409,40 @@
ALOGE("unlock called on keystore in unknown state: %d", state);
break;
}
- return ResponseCode(state);
+ *aidl_return = static_cast<int32_t>(ResponseCode(state));
+ return Status::ok();
}
+ enforcement_policy.set_device_locked(false, userId);
const String8 password8(pw);
// read master key, decrypt with password, initialize mMasterKey*.
- return mKeyStore->readMasterKey(password8, userId);
+ *aidl_return = static_cast<int32_t>(mKeyStore->readMasterKey(password8, userId));
+ return Status::ok();
}
-bool KeyStoreService::isEmpty(int32_t userId) {
+Status KeyStoreService::isEmpty(int32_t userId, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_IS_EMPTY)) {
- return false;
+ *aidl_return = static_cast<int32_t>(false);
+ return Status::ok();
}
- return mKeyStore->isEmpty(userId);
+ *aidl_return = static_cast<int32_t>(mKeyStore->isEmpty(userId));
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_t targetUid,
- int32_t keyType, int32_t keySize, int32_t flags,
- Vector<sp<KeystoreArg>>* args) {
+Status KeyStoreService::generate(const String16& name, int32_t targetUid, int32_t keyType,
+ int32_t keySize, int32_t flags,
+ const ::android::security::KeystoreArguments& keystoreArgs,
+ int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
+ const Vector<sp<KeystoreArg>>* args = &(keystoreArgs.getArguments());
targetUid = getEffectiveUid(targetUid);
- auto result =
+ KeyStoreServiceReturnCode result =
checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
if (!result.isOk()) {
- return result;
+ *aidl_return = static_cast<int32_t>(result);
+ return Status::ok();
}
keystore::AuthorizationSet params;
@@ -395,7 +455,8 @@
keySize = EC_DEFAULT_KEY_SIZE;
} else if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
ALOGI("invalid key size %d", keySize);
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
params.push_back(TAG_KEY_SIZE, keySize);
break;
@@ -406,13 +467,15 @@
keySize = RSA_DEFAULT_KEY_SIZE;
} else if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
ALOGI("invalid key size %d", keySize);
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
params.push_back(TAG_KEY_SIZE, keySize);
unsigned long exponent = RSA_DEFAULT_EXPONENT;
if (args->size() > 1) {
ALOGI("invalid number of arguments: %zu", args->size());
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
} else if (args->size() == 1) {
const sp<KeystoreArg>& expArg = args->itemAt(0);
if (expArg != NULL) {
@@ -420,16 +483,19 @@
reinterpret_cast<const unsigned char*>(expArg->data()), expArg->size(), NULL));
if (pubExpBn.get() == NULL) {
ALOGI("Could not convert public exponent to BN");
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
exponent = BN_get_word(pubExpBn.get());
if (exponent == 0xFFFFFFFFL) {
ALOGW("cannot represent public exponent as a long value");
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
} else {
ALOGW("public exponent not read");
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
}
params.push_back(TAG_RSA_PUBLIC_EXPONENT, exponent);
@@ -437,32 +503,37 @@
}
default: {
ALOGW("Unsupported key type %d", keyType);
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
}
- auto rc = generateKey(name, params.hidl_data(), hidl_vec<uint8_t>(), targetUid, flags,
- /*outCharacteristics*/ NULL);
- if (!rc.isOk()) {
- ALOGW("generate failed: %d", int32_t(rc));
+ int32_t aidl_result;
+ android::security::keymaster::KeyCharacteristics unused_characteristics;
+ auto rc = generateKey(name, KeymasterArguments(params.hidl_data()), ::std::vector<uint8_t>(),
+ targetUid, flags, &unused_characteristics, &aidl_result);
+ if (!KeyStoreServiceReturnCode(aidl_result).isOk()) {
+ ALOGW("generate failed: %d", int32_t(aidl_result));
}
- return translateResultToLegacyResult(rc);
+ *aidl_return = aidl_result;
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::import(const String16& name,
- const hidl_vec<uint8_t>& data, int targetUid,
- int32_t flags) {
+Status KeyStoreService::import_key(const String16& name, const ::std::vector<uint8_t>& data,
+ int targetUid, int32_t flags, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
const uint8_t* ptr = &data[0];
Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, data.size()));
if (!pkcs8.get()) {
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
if (!pkey.get()) {
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
int type = EVP_PKEY_type(pkey->type);
AuthorizationSet params;
@@ -476,35 +547,49 @@
break;
default:
ALOGW("Unsupported key type %d", type);
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
- auto rc = importKey(name, params.hidl_data(), KeyFormat::PKCS8, data, targetUid, flags,
- /*outCharacteristics*/ NULL);
+ int import_result;
+ auto rc = importKey(name, KeymasterArguments(params.hidl_data()),
+ static_cast<int32_t>(KeyFormat::PKCS8), data, targetUid, flags,
+ /*outCharacteristics*/ NULL, &import_result);
- if (!rc.isOk()) {
- ALOGW("importKey failed: %d", int32_t(rc));
+ if (!KeyStoreServiceReturnCode(import_result).isOk()) {
+ ALOGW("importKey failed: %d", int32_t(import_result));
}
- return translateResultToLegacyResult(rc);
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::sign(const String16& name, const hidl_vec<uint8_t>& data,
- hidl_vec<uint8_t>* out) {
+Status KeyStoreService::sign(const String16& name, const ::std::vector<uint8_t>& data,
+ ::std::vector<uint8_t>* out) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_SIGN)) {
- return ResponseCode::PERMISSION_DENIED;
+ return Status::fromServiceSpecificError(
+ static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
}
- return doLegacySignVerify(name, data, out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
+ hidl_vec<uint8_t> legacy_out;
+ KeyStoreServiceReturnCode res =
+ doLegacySignVerify(name, data, &legacy_out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
+ if (!res.isOk()) {
+ return Status::fromServiceSpecificError((res));
+ }
+ *out = legacy_out;
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::verify(const String16& name,
- const hidl_vec<uint8_t>& data,
- const hidl_vec<uint8_t>& signature) {
+Status KeyStoreService::verify(const String16& name, const ::std::vector<uint8_t>& data,
+ const ::std::vector<uint8_t>& signature, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!checkBinderPermission(P_VERIFY)) {
- return ResponseCode::PERMISSION_DENIED;
+ return Status::fromServiceSpecificError(
+ static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
}
- return doLegacySignVerify(name, data, nullptr, signature, KeyPurpose::VERIFY);
+ *aidl_return = static_cast<int32_t>(
+ doLegacySignVerify(name, data, nullptr, signature, KeyPurpose::VERIFY));
+ return Status::ok();
}
/*
@@ -518,76 +603,92 @@
* "del_key" since the Java code doesn't really communicate what it's
* intentions are.
*/
-KeyStoreServiceReturnCode KeyStoreService::get_pubkey(const String16& name,
- hidl_vec<uint8_t>* pubKey) {
+Status KeyStoreService::get_pubkey(const String16& name, ::std::vector<uint8_t>* pubKey) {
KEYSTORE_SERVICE_LOCK;
- ExportResult result;
- exportKey(name, KeyFormat::X509, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF, &result);
+ android::security::keymaster::ExportResult result;
+ KeymasterBlob clientId;
+ KeymasterBlob appData;
+ exportKey(name, static_cast<int32_t>(KeyFormat::X509), clientId, appData, UID_SELF, &result);
if (!result.resultCode.isOk()) {
ALOGW("export failed: %d", int32_t(result.resultCode));
- return translateResultToLegacyResult(result.resultCode);
+ return Status::fromServiceSpecificError(static_cast<int32_t>(result.resultCode));
}
if (pubKey) *pubKey = std::move(result.exportData);
- return ResponseCode::NO_ERROR;
+ return Status::ok();
}
-String16 KeyStoreService::grant(const String16& name, int32_t granteeUid) {
+Status KeyStoreService::grant(const String16& name, int32_t granteeUid,
+ ::android::String16* aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t callingUid = IPCThreadState::self()->getCallingUid();
- auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
+ auto result =
+ checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
if (!result.isOk()) {
- return String16();
+ *aidl_return = String16();
+ return Status::ok();
}
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
if (access(filename.string(), R_OK) == -1) {
- return String16();
+ *aidl_return = String16();
+ return Status::ok();
}
- return String16(mKeyStore->addGrant(String8(name).string(), callingUid, granteeUid).c_str());
+ *aidl_return =
+ String16(mKeyStore->addGrant(String8(name).string(), callingUid, granteeUid).c_str());
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
+Status KeyStoreService::ungrant(const String16& name, int32_t granteeUid, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t callingUid = IPCThreadState::self()->getCallingUid();
- auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
+ KeyStoreServiceReturnCode result =
+ checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
if (!result.isOk()) {
- return result;
+ *aidl_return = static_cast<int32_t>(result);
+ return Status::ok();
}
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
if (access(filename.string(), R_OK) == -1) {
- return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
+ *aidl_return = static_cast<int32_t>((errno != ENOENT) ? ResponseCode::SYSTEM_ERROR
+ : ResponseCode::KEY_NOT_FOUND);
+ return Status::ok();
}
- return mKeyStore->removeGrant(name8, callingUid, granteeUid) ? ResponseCode::NO_ERROR
- : ResponseCode::KEY_NOT_FOUND;
+ *aidl_return = static_cast<int32_t>(mKeyStore->removeGrant(name8, callingUid, granteeUid)
+ ? ResponseCode::NO_ERROR
+ : ResponseCode::KEY_NOT_FOUND);
+ return Status::ok();
}
-int64_t KeyStoreService::getmtime(const String16& name, int32_t uid) {
+Status KeyStoreService::getmtime(const String16& name, int32_t uid, int64_t* time) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(uid);
if (!checkBinderPermission(P_GET, targetUid)) {
ALOGW("permission denied for %d: getmtime", targetUid);
- return -1L;
+ *time = -1L;
+ return Status::ok();
}
auto filename = mKeyStore->getBlobFileNameIfExists(String8(name), targetUid, ::TYPE_ANY);
if (!filename.isOk()) {
ALOGW("could not access %s for getmtime", filename.value().string());
- return -1L;
+ *time = -1L;
+ return Status::ok();
}
int fd = TEMP_FAILURE_RETRY(open(filename.value().string(), O_NOFOLLOW, O_RDONLY));
if (fd < 0) {
ALOGW("could not open %s for getmtime", filename.value().string());
- return -1L;
+ *time = -1L;
+ return Status::ok();
}
struct stat s;
@@ -595,85 +696,26 @@
close(fd);
if (ret == -1) {
ALOGW("could not stat %s for getmtime", filename.value().string());
- return -1L;
+ *time = -1L;
+ return Status::ok();
}
- return static_cast<int64_t>(s.st_mtime);
+ *time = static_cast<int64_t>(s.st_mtime);
+ return Status::ok();
}
-// TODO(tuckeris): This is dead code, remove it. Don't bother copying over key characteristics here
-KeyStoreServiceReturnCode KeyStoreService::duplicate(const String16& srcKey, int32_t srcUid,
- const String16& destKey, int32_t destUid) {
+Status KeyStoreService::is_hardware_backed(const String16& keyType, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
- uid_t callingUid = IPCThreadState::self()->getCallingUid();
- pid_t spid = IPCThreadState::self()->getCallingPid();
- if (!has_permission(callingUid, P_DUPLICATE, spid)) {
- ALOGW("permission denied for %d: duplicate", callingUid);
- return ResponseCode::PERMISSION_DENIED;
- }
-
- State state = mKeyStore->getState(get_user_id(callingUid));
- if (!isKeystoreUnlocked(state)) {
- ALOGD("calling duplicate in state: %d", state);
- return ResponseCode(state);
- }
-
- if (srcUid == -1 || static_cast<uid_t>(srcUid) == callingUid) {
- srcUid = callingUid;
- } else if (!is_granted_to(callingUid, srcUid)) {
- ALOGD("migrate not granted from source: %d -> %d", callingUid, srcUid);
- return ResponseCode::PERMISSION_DENIED;
- }
-
- if (destUid == -1) {
- destUid = callingUid;
- }
-
- if (srcUid != destUid) {
- if (static_cast<uid_t>(srcUid) != callingUid) {
- ALOGD("can only duplicate from caller to other or to same uid: "
- "calling=%d, srcUid=%d, destUid=%d",
- callingUid, srcUid, destUid);
- return ResponseCode::PERMISSION_DENIED;
- }
-
- if (!is_granted_to(callingUid, destUid)) {
- ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
- return ResponseCode::PERMISSION_DENIED;
- }
- }
-
- String8 source8(srcKey);
- String8 sourceFile(mKeyStore->getKeyNameForUidWithDir(source8, srcUid, ::TYPE_ANY));
-
- String8 target8(destKey);
- String8 targetFile(mKeyStore->getKeyNameForUidWithDir(target8, destUid, ::TYPE_ANY));
-
- if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
- ALOGD("destination already exists: %s", targetFile.string());
- return ResponseCode::SYSTEM_ERROR;
- }
-
- Blob keyBlob;
- ResponseCode responseCode =
- mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY, get_user_id(srcUid));
- if (responseCode != ResponseCode::NO_ERROR) {
- return responseCode;
- }
-
- return mKeyStore->put(targetFile.string(), &keyBlob, get_user_id(destUid));
+ *aidl_return = static_cast<int32_t>(mKeyStore->isHardwareBacked(keyType) ? 1 : 0);
+ return Status::ok();
}
-int32_t KeyStoreService::is_hardware_backed(const String16& keyType) {
- KEYSTORE_SERVICE_LOCK;
- return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
-}
-
-KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
+Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(targetUid64);
if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
ALOGI("clear_uid %" PRId64, targetUid64);
@@ -682,7 +724,8 @@
String8 prefix = String8::format("%u_", targetUid);
Vector<String16> aliases;
if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
for (uint32_t i = 0; i < aliases.size(); i++) {
@@ -706,67 +749,95 @@
mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
mKeyStore->del(chr_filename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
}
- return ResponseCode::NO_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::addRngEntropy(const hidl_vec<uint8_t>& entropy) {
+Status KeyStoreService::addRngEntropy(const ::std::vector<uint8_t>& entropy, int32_t flags,
+ int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
- const auto& device = mKeyStore->getDevice();
- return KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy));
+ auto device = mKeyStore->getDevice(flagsToSecurityLevel(flags));
+ if (!device) {
+ *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
+ } else {
+ *aidl_return = static_cast<int32_t>(
+ KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy))));
+ }
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
- const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& entropy, int uid,
- int flags,
- KeyCharacteristics* outCharacteristics) {
+Status
+KeyStoreService::generateKey(const String16& name, const KeymasterArguments& params,
+ const ::std::vector<uint8_t>& entropy, int uid, int flags,
+ android::security::keymaster::KeyCharacteristics* outCharacteristics,
+ int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
// TODO(jbires): remove this getCallingUid call upon implementation of b/25646100
uid_t originalUid = IPCThreadState::self()->getCallingUid();
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 rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
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 ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
- if (containsTag(params, Tag::INCLUDE_UNIQUE_ID)) {
+
+ if (containsTag(params.getParameters(), Tag::INCLUDE_UNIQUE_ID)) {
+ // TODO(jbires): remove uid checking upon implementation of b/25646100
if (!checkBinderPermission(P_GEN_UNIQUE_ID) ||
- originalUid != IPCThreadState::self()->getCallingUid()) {
- return ResponseCode::PERMISSION_DENIED;
+ originalUid != IPCThreadState::self()->getCallingUid()) {
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
}
- bool usingFallback = false;
- auto& dev = mKeyStore->getDevice();
- AuthorizationSet keyCharacteristics = params;
+ SecurityLevel securityLevel = flagsToSecurityLevel(flags);
+ auto dev = mKeyStore->getDevice(securityLevel);
+ if (!dev) {
+ *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
+ return Status::ok();
+ }
+ AuthorizationSet keyCharacteristics = params.getParameters();
// TODO: Seed from Linux RNG before this.
- rc = addRngEntropy(entropy);
+ rc = KS_HANDLE_HIDL_ERROR(dev->addRngEntropy(entropy));
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
KeyStoreServiceReturnCode error;
- auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
+ auto hidl_cb = [&](ErrorCode ret, const ::std::vector<uint8_t>& hidlKeyBlob,
const KeyCharacteristics& keyCharacteristics) {
error = ret;
if (!error.isOk()) {
return;
}
- if (outCharacteristics) *outCharacteristics = keyCharacteristics;
+ if (outCharacteristics)
+ *outCharacteristics =
+ ::android::security::keymaster::KeyCharacteristics(keyCharacteristics);
// Write the key
String8 name8(name);
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
- keyBlob.setFallback(usingFallback);
+ keyBlob.setSecurityLevel(securityLevel);
keyBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
- if (isAuthenticationBound(params) && !keyBlob.isCriticalToDeviceEncryption()) {
+ if (isAuthenticationBound(params.getParameters()) &&
+ !keyBlob.isCriticalToDeviceEncryption()) {
keyBlob.setSuperEncrypted(true);
}
keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
@@ -774,24 +845,49 @@
error = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
};
- rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(params, hidl_cb));
+ rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(params.getParameters(), hidl_cb));
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
if (!error.isOk()) {
ALOGE("Failed to generate key -> falling back to software keymaster");
- usingFallback = true;
- auto fallback = mKeyStore->getFallbackDevice();
- if (!fallback.isOk()) {
- return error;
+ uploadKeyCharacteristicsAsProto(params.getParameters(), false /* wasCreationSuccessful */);
+ securityLevel = SecurityLevel::SOFTWARE;
+
+ // No fall back for 3DES
+ for (auto& param : params.getParameters()) {
+ auto algorithm = authorizationValue(TAG_ALGORITHM, param);
+ if (algorithm.isOk() && algorithm.value() == Algorithm::TRIPLE_DES) {
+ *aidl_return = static_cast<int32_t>(ErrorCode::UNSUPPORTED_ALGORITHM);
+ return Status::ok();
+ }
}
- rc = KS_HANDLE_HIDL_ERROR(fallback.value()->generateKey(params, hidl_cb));
+
+ auto fallback = mKeyStore->getFallbackDevice();
+ if (!fallback) {
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
+ }
+ rc = KS_HANDLE_HIDL_ERROR(fallback->generateKey(params.getParameters(), hidl_cb));
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
if (!error.isOk()) {
- return error;
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
}
+ } else {
+ uploadKeyCharacteristicsAsProto(params.getParameters(), true /* wasCreationSuccessful */);
+ }
+
+ if (!containsTag(params.getParameters(), Tag::USER_ID)) {
+ // Most Java processes don't have access to this tag
+ KeyParameter user_id;
+ user_id.tag = Tag::USER_ID;
+ user_id.f.integer = mActiveUserId;
+ keyCharacteristics.push_back(user_id);
}
// Write the characteristics:
@@ -801,24 +897,29 @@
std::stringstream kc_stream;
keyCharacteristics.Serialize(&kc_stream);
if (kc_stream.bad()) {
- return ResponseCode::SYSTEM_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
}
auto kc_buf = kc_stream.str();
Blob charBlob(reinterpret_cast<const uint8_t*>(kc_buf.data()), kc_buf.size(), NULL, 0,
::TYPE_KEY_CHARACTERISTICS);
- charBlob.setFallback(usingFallback);
+ charBlob.setSecurityLevel(securityLevel);
charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
- return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
+ *aidl_return =
+ static_cast<int32_t>(mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid)));
+ return Status::ok();
}
-KeyStoreServiceReturnCode
-KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData, int32_t uid,
- KeyCharacteristics* outCharacteristics) {
+Status KeyStoreService::getKeyCharacteristics(
+ const String16& name, const ::android::security::keymaster::KeymasterBlob& clientId,
+ const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid,
+ ::android::security::keymaster::KeyCharacteristics* outCharacteristics, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
if (!outCharacteristics) {
- return ErrorCode::UNEXPECTED_NULL_POINTER;
+ *aidl_return =
+ static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::UNEXPECTED_NULL_POINTER));
+ return Status::ok();
}
uid_t targetUid = getEffectiveUid(uid);
@@ -826,7 +927,8 @@
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid,
targetUid);
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
Blob keyBlob;
@@ -842,7 +944,8 @@
*/
rc = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
AuthorizationSet keyCharacteristics;
// TODO write one shot stream buffer to avoid copying (twice here)
@@ -851,95 +954,123 @@
std::stringstream charStream(charBuffer);
keyCharacteristics.Deserialize(&charStream);
- outCharacteristics->softwareEnforced = keyCharacteristics.hidl_data();
- return rc;
+ outCharacteristics->softwareEnforced = KeymasterArguments(keyCharacteristics.hidl_data());
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
} else if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
auto hidlKeyBlob = blob2hidlVec(keyBlob);
- auto& dev = mKeyStore->getDevice(keyBlob);
+ auto dev = mKeyStore->getDevice(keyBlob);
KeyStoreServiceReturnCode error;
auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
error = ret;
if (!error.isOk()) {
+ if (error == ErrorCode::INVALID_KEY_BLOB) {
+ log_key_integrity_violation(name8, targetUid);
+ }
return;
}
- *outCharacteristics = keyCharacteristics;
+ *outCharacteristics =
+ ::android::security::keymaster::KeyCharacteristics(keyCharacteristics);
};
- rc = KS_HANDLE_HIDL_ERROR(dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
+ rc = KS_HANDLE_HIDL_ERROR(
+ dev->getKeyCharacteristics(hidlKeyBlob, clientId.getData(), appData.getData(), hidlCb));
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
if (error == ErrorCode::KEY_REQUIRES_UPGRADE) {
AuthorizationSet upgradeParams;
- if (clientId.size()) {
- upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
+ if (clientId.getData().size()) {
+ upgradeParams.push_back(TAG_APPLICATION_ID, clientId.getData());
}
- if (appData.size()) {
- upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
+ if (appData.getData().size()) {
+ upgradeParams.push_back(TAG_APPLICATION_DATA, appData.getData());
}
rc = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
- rc = KS_HANDLE_HIDL_ERROR(
- dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
+ rc = KS_HANDLE_HIDL_ERROR(dev->getKeyCharacteristics(
+ upgradedHidlKeyBlob, clientId.getData(), appData.getData(), hidlCb));
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
// Note that, on success, "error" will have been updated by the hidlCB callback.
// So it is fine to return "error" below.
}
- return error;
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(error));
+ return Status::ok();
}
-KeyStoreServiceReturnCode
-KeyStoreService::importKey(const String16& name, const hidl_vec<KeyParameter>& params,
- KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid, int flags,
- KeyCharacteristics* outCharacteristics) {
+Status
+KeyStoreService::importKey(const String16& name, const KeymasterArguments& params, int32_t format,
+ const ::std::vector<uint8_t>& keyData, int uid, int flags,
+ ::android::security::keymaster::KeyCharacteristics* outCharacteristics,
+ int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
+
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()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
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 ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
- bool usingFallback = false;
- auto& dev = mKeyStore->getDevice();
+ SecurityLevel securityLevel = flagsToSecurityLevel(flags);
+ auto dev = mKeyStore->getDevice(securityLevel);
+ if (!dev) {
+ *aidl_return = static_cast<int32_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
+ return Status::ok();
+ }
String8 name8(name);
KeyStoreServiceReturnCode error;
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
+ auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& keyBlob,
const KeyCharacteristics& keyCharacteristics) {
error = ret;
if (!error.isOk()) {
return;
}
-
- if (outCharacteristics) *outCharacteristics = keyCharacteristics;
+ if (outCharacteristics)
+ *outCharacteristics =
+ ::android::security::keymaster::KeyCharacteristics(keyCharacteristics);
// Write the key:
String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
- ksBlob.setFallback(usingFallback);
+ ksBlob.setSecurityLevel(securityLevel);
ksBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
- if (isAuthenticationBound(params) && !ksBlob.isCriticalToDeviceEncryption()) {
+ if (isAuthenticationBound(params.getParameters()) &&
+ !ksBlob.isCriticalToDeviceEncryption()) {
ksBlob.setSuperEncrypted(true);
}
ksBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
@@ -947,50 +1078,84 @@
error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(uid));
};
- rc = KS_HANDLE_HIDL_ERROR(dev->importKey(params, format, keyData, hidlCb));
+ rc = KS_HANDLE_HIDL_ERROR(
+ dev->importKey(params.getParameters(), KeyFormat(format), keyData, hidlCb));
// possible hidl error
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
// now check error from callback
if (!error.isOk()) {
ALOGE("Failed to import key -> falling back to software keymaster");
- usingFallback = true;
- auto fallback = mKeyStore->getFallbackDevice();
- if (!fallback.isOk()) {
- return error;
+ uploadKeyCharacteristicsAsProto(params.getParameters(), false /* wasCreationSuccessful */);
+ securityLevel = SecurityLevel::SOFTWARE;
+
+ // No fall back for 3DES
+ for (auto& param : params.getParameters()) {
+ auto algorithm = authorizationValue(TAG_ALGORITHM, param);
+ if (algorithm.isOk() && algorithm.value() == Algorithm::TRIPLE_DES) {
+ *aidl_return = static_cast<int32_t>(ErrorCode::UNSUPPORTED_ALGORITHM);
+ return Status::ok();
+ }
}
- rc = KS_HANDLE_HIDL_ERROR(fallback.value()->importKey(params, format, keyData, hidlCb));
+
+ auto fallback = mKeyStore->getFallbackDevice();
+ if (!fallback) {
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
+ }
+ rc = KS_HANDLE_HIDL_ERROR(
+ fallback->importKey(params.getParameters(), KeyFormat(format), keyData, hidlCb));
// possible hidl error
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
// now check error from callback
if (!error.isOk()) {
- return error;
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
}
+ } else {
+ uploadKeyCharacteristicsAsProto(params.getParameters(), true /* wasCreationSuccessful */);
}
// Write the characteristics:
String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));
- AuthorizationSet opParams = params;
+ AuthorizationSet opParams = params.getParameters();
+ if (!containsTag(params.getParameters(), Tag::USER_ID)) {
+ // Most Java processes don't have access to this tag
+ KeyParameter user_id;
+ user_id.tag = Tag::USER_ID;
+ user_id.f.integer = mActiveUserId;
+ opParams.push_back(user_id);
+ }
+
std::stringstream kcStream;
opParams.Serialize(&kcStream);
- if (kcStream.bad()) return ResponseCode::SYSTEM_ERROR;
+ if (kcStream.bad()) {
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
+ }
auto kcBuf = kcStream.str();
Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0,
::TYPE_KEY_CHARACTERISTICS);
- charBlob.setFallback(usingFallback);
+ charBlob.setSecurityLevel(securityLevel);
charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
- return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
+ *aidl_return =
+ static_cast<int32_t>(mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid)));
+
+ return Status::ok();
}
-void KeyStoreService::exportKey(const String16& name, KeyFormat format,
- const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
- int32_t uid, ExportResult* result) {
+Status KeyStoreService::exportKey(const String16& name, int32_t format,
+ const ::android::security::keymaster::KeymasterBlob& clientId,
+ const ::android::security::keymaster::KeymasterBlob& appData,
+ int32_t uid, ExportResult* result) {
KEYSTORE_SERVICE_LOCK;
uid_t targetUid = getEffectiveUid(uid);
@@ -998,7 +1163,7 @@
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid);
result->resultCode = ResponseCode::PERMISSION_DENIED;
- return;
+ return Status::ok();
}
Blob keyBlob;
@@ -1006,21 +1171,24 @@
result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
if (!result->resultCode.isOk()) {
- return;
+ return Status::ok();
}
auto key = blob2hidlVec(keyBlob);
- auto& dev = mKeyStore->getDevice(keyBlob);
+ auto dev = mKeyStore->getDevice(keyBlob);
auto hidlCb = [&](ErrorCode ret, const ::android::hardware::hidl_vec<uint8_t>& keyMaterial) {
result->resultCode = ret;
if (!result->resultCode.isOk()) {
+ if (result->resultCode == ErrorCode::INVALID_KEY_BLOB) {
+ log_key_integrity_violation(name8, targetUid);
+ }
return;
}
result->exportData = keyMaterial;
};
- KeyStoreServiceReturnCode rc =
- KS_HANDLE_HIDL_ERROR(dev->exportKey(format, key, clientId, appData, hidlCb));
+ KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+ dev->exportKey(KeyFormat(format), key, clientId.getData(), appData.getData(), hidlCb));
// Overwrite result->resultCode only on HIDL error. Otherwise we want the result set in the
// callback hidlCb.
if (!rc.isOk()) {
@@ -1029,84 +1197,78 @@
if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
AuthorizationSet upgradeParams;
- if (clientId.size()) {
- upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
+ if (clientId.getData().size()) {
+ upgradeParams.push_back(TAG_APPLICATION_ID, clientId.getData());
}
- if (appData.size()) {
- upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
+ if (appData.getData().size()) {
+ upgradeParams.push_back(TAG_APPLICATION_DATA, appData.getData());
}
result->resultCode = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
if (!result->resultCode.isOk()) {
- return;
+ return Status::ok();
}
auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
- result->resultCode = KS_HANDLE_HIDL_ERROR(
- dev->exportKey(format, upgradedHidlKeyBlob, clientId, appData, hidlCb));
+ result->resultCode = KS_HANDLE_HIDL_ERROR(dev->exportKey(
+ KeyFormat(format), upgradedHidlKeyBlob, clientId.getData(), appData.getData(), hidlCb));
if (!result->resultCode.isOk()) {
- return;
+ return Status::ok();
}
}
+ return Status::ok();
}
-static inline void addAuthTokenToParams(AuthorizationSet* params, const HardwareAuthToken* token) {
- if (token) {
- params->push_back(TAG_AUTH_TOKEN, authToken2HidlVec(*token));
- }
-}
-
-void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
- bool pruneable, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& entropy, int32_t uid,
- OperationResult* result) {
+Status KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, int32_t purpose,
+ bool pruneable, const KeymasterArguments& params,
+ const ::std::vector<uint8_t>& entropy, int32_t uid,
+ OperationResult* result) {
KEYSTORE_SERVICE_LOCK;
+ auto keyPurpose = static_cast<KeyPurpose>(purpose);
+
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);
result->resultCode = ResponseCode::PERMISSION_DENIED;
- return;
+ return Status::ok();
}
if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
result->resultCode = ResponseCode::PERMISSION_DENIED;
- return;
+ return Status::ok();
}
- if (!checkAllowedOperationParams(params)) {
+ if (!checkAllowedOperationParams(params.getParameters())) {
result->resultCode = ErrorCode::INVALID_ARGUMENT;
- return;
+ return Status::ok();
}
+
Blob keyBlob;
String8 name8(name);
result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
if (result->resultCode == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) {
result->resultCode = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
}
- if (!result->resultCode.isOk()) {
- return;
- }
+ if (!result->resultCode.isOk()) return Status::ok();
auto key = blob2hidlVec(keyBlob);
- auto& dev = mKeyStore->getDevice(keyBlob);
- AuthorizationSet opParams = params;
+ auto dev = mKeyStore->getDevice(keyBlob);
+ AuthorizationSet opParams = params.getParameters();
KeyCharacteristics characteristics;
result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
result->resultCode = upgradeKeyBlob(name, targetUid, opParams, &keyBlob);
if (!result->resultCode.isOk()) {
- return;
+ return Status::ok();
}
key = blob2hidlVec(keyBlob);
result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
}
if (!result->resultCode.isOk()) {
- return;
+ return Status::ok();
}
- const HardwareAuthToken* authToken = NULL;
-
// Merge these characteristics with the ones cached when the key was generated or imported
Blob charBlob;
AuthorizationSet persistedCharacteristics;
@@ -1124,28 +1286,30 @@
// Replace the sw_enforced set with those persisted to disk, minus hw_enforced
AuthorizationSet softwareEnforced = characteristics.softwareEnforced;
- AuthorizationSet teeEnforced = characteristics.teeEnforced;
+ AuthorizationSet hardwareEnforced = characteristics.hardwareEnforced;
persistedCharacteristics.Union(softwareEnforced);
- persistedCharacteristics.Subtract(teeEnforced);
+ persistedCharacteristics.Subtract(hardwareEnforced);
characteristics.softwareEnforced = persistedCharacteristics.hidl_data();
- auto authResult = getAuthToken(characteristics, 0, purpose, &authToken,
- /*failOnTokenMissing*/ false);
+ KeyStoreServiceReturnCode authResult;
+ HardwareAuthToken authToken;
+ std::tie(authResult, authToken) =
+ getAuthToken(characteristics, 0 /* no challenge */, keyPurpose,
+ /*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 (!authResult.isOk() && authResult != ResponseCode::OP_AUTH_NEEDED) {
result->resultCode = authResult;
- return;
+ return Status::ok();
}
- addAuthTokenToParams(&opParams, authToken);
-
// Add entropy to the device first.
if (entropy.size()) {
- result->resultCode = addRngEntropy(entropy);
+ result->resultCode = KS_HANDLE_HIDL_ERROR(dev->addRngEntropy(entropy));
if (!result->resultCode.isOk()) {
- return;
+ return Status::ok();
}
}
@@ -1154,18 +1318,19 @@
if (!enforcement_policy.CreateKeyId(key, &keyid)) {
ALOGE("Failed to create a key ID for authorization checking.");
result->resultCode = ErrorCode::UNKNOWN_ERROR;
- return;
+ return Status::ok();
}
// Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths = characteristics.teeEnforced;
- key_auths.append(&characteristics.softwareEnforced[0],
- &characteristics.softwareEnforced[characteristics.softwareEnforced.size()]);
+ AuthorizationSet key_auths = characteristics.hardwareEnforced;
+ key_auths.append(characteristics.softwareEnforced.begin(),
+ characteristics.softwareEnforced.end());
- result->resultCode = enforcement_policy.AuthorizeOperation(
- purpose, keyid, key_auths, opParams, 0 /* op_handle */, true /* is_begin_operation */);
+ result->resultCode =
+ enforcement_policy.AuthorizeOperation(keyPurpose, keyid, key_auths, opParams, authToken,
+ 0 /* op_handle */, true /* is_begin_operation */);
if (!result->resultCode.isOk()) {
- return;
+ return Status::ok();
}
// If there are more than kMaxOperations, abort the oldest operation that was started as
@@ -1181,42 +1346,84 @@
uint64_t operationHandle) {
result->resultCode = ret;
if (!result->resultCode.isOk()) {
+ if (result->resultCode == ErrorCode::INVALID_KEY_BLOB) {
+ log_key_integrity_violation(name8, targetUid);
+ }
return;
}
result->handle = operationHandle;
result->outParams = outParams;
};
- ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
- if (rc != ErrorCode::OK) {
- ALOGW("Got error %d from begin()", rc);
+ KeyStoreServiceReturnCode rc =
+ KS_HANDLE_HIDL_ERROR(dev->begin(keyPurpose, key, opParams.hidl_data(), authToken, hidlCb));
+ if (!rc.isOk()) {
+ LOG(ERROR) << "Got error " << rc << " from begin()";
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
+ return Status::ok();
}
+ rc = result->resultCode;
+
// If there are too many operations abort the oldest operation that was
// started as pruneable and try again.
+ LOG(INFO) << rc << " " << mOperationMap.hasPruneableOperation();
while (rc == ErrorCode::TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
- ALOGW("Ran out of operation handles");
+ LOG(INFO) << "Ran out of operation handles";
if (!pruneOperation()) {
break;
}
- rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
+ rc = KS_HANDLE_HIDL_ERROR(
+ dev->begin(keyPurpose, key, opParams.hidl_data(), authToken, hidlCb));
+ if (!rc.isOk()) {
+ LOG(ERROR) << "Got error " << rc << " from begin()";
+ result->resultCode = ResponseCode::SYSTEM_ERROR;
+ return Status::ok();
+ }
+ rc = result->resultCode;
}
- if (rc != ErrorCode::OK) {
+ if (!rc.isOk()) {
result->resultCode = rc;
- return;
+ return Status::ok();
+ }
+
+ VerificationToken verificationToken;
+ if (authResult.isOk() && authToken.mac.size() &&
+ dev->halVersion().securityLevel == SecurityLevel::STRONGBOX) {
+ // This operation needs an auth token, but the device is a STRONGBOX, so it can't check the
+ // timestamp in the auth token. Get a VerificationToken from the TEE, which will be passed
+ // to update() and begin().
+ rc = KS_HANDLE_HIDL_ERROR(mKeyStore->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)
+ ->verifyAuthorization(result->handle,
+ {} /* parametersToVerify */, authToken,
+ [&](auto error, const auto& token) {
+ result->resultCode = error;
+ verificationToken = token;
+ }));
+
+ if (!rc.isOk()) result->resultCode = rc;
+ if (!result->resultCode.isOk()) {
+ LOG(ERROR) << "Failed to verify authorization " << rc << " from begin()";
+ rc = KS_HANDLE_HIDL_ERROR(dev->abort(result->handle));
+ if (!rc.isOk()) {
+ LOG(ERROR) << "Failed to abort operation " << rc << " from begin()";
+ }
+ return Status::ok();
+ }
}
// 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 = mOperationMap.addOperation(
- result->handle, keyid, purpose, dev, appToken, std::move(characteristics), pruneable);
- assert(characteristics.teeEnforced.size() == 0);
+ sp<IBinder> operationToken =
+ mOperationMap.addOperation(result->handle, keyid, keyPurpose, dev, appToken,
+ std::move(characteristics), params.getParameters(), pruneable);
+ assert(characteristics.hardwareEnforced.size() == 0);
assert(characteristics.softwareEnforced.size() == 0);
result->token = operationToken;
- if (authToken) {
- mOperationMap.setOperationAuthToken(operationToken, authToken);
- }
+ mOperationMap.setOperationAuthToken(operationToken, std::move(authToken));
+ mOperationMap.setOperationVerificationToken(operationToken, std::move(verificationToken));
+
// 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
@@ -1227,240 +1434,265 @@
}
// Other result fields were set in the begin operation's callback.
+ return Status::ok();
}
-void KeyStoreService::update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& data, OperationResult* result) {
- KEYSTORE_SERVICE_LOCK;
- if (!checkAllowedOperationParams(params)) {
- result->resultCode = ErrorCode::INVALID_ARGUMENT;
- return;
- }
- km_device_t dev;
- uint64_t handle;
- KeyPurpose purpose;
- km_id_t keyid;
- const KeyCharacteristics* characteristics;
- if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
- result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
- return;
- }
- AuthorizationSet opParams = params;
- result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
- if (!result->resultCode.isOk()) {
+void KeyStoreService::appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics,
+ std::vector<KeyParameter>* params) {
+ if (!(containsTag(keyCharacteristics.softwareEnforced, Tag::TRUSTED_CONFIRMATION_REQUIRED) ||
+ containsTag(keyCharacteristics.hardwareEnforced, Tag::TRUSTED_CONFIRMATION_REQUIRED))) {
return;
}
- // Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths(characteristics->teeEnforced);
- key_auths.append(&characteristics->softwareEnforced[0],
- &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
- result->resultCode = enforcement_policy.AuthorizeOperation(
- purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
- if (!result->resultCode.isOk()) {
+ hidl_vec<uint8_t> confirmationToken = mConfirmationManager->getLatestConfirmationToken();
+ if (confirmationToken.size() == 0) {
return;
}
+ params->push_back(
+ Authorization(keymaster::TAG_CONFIRMATION_TOKEN, std::move(confirmationToken)));
+ ALOGD("Appending confirmation token\n");
+}
+
+Status KeyStoreService::update(const sp<IBinder>& token, const KeymasterArguments& params,
+ const ::std::vector<uint8_t>& data, OperationResult* result) {
+ KEYSTORE_SERVICE_LOCK;
+ if (!checkAllowedOperationParams(params.getParameters())) {
+ result->resultCode = ErrorCode::INVALID_ARGUMENT;
+ return Status::ok();
+ }
+
+ auto getOpResult = mOperationMap.getOperation(token);
+ if (!getOpResult.isOk()) {
+ result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
+ return Status::ok();
+ }
+ const auto& op = getOpResult.value();
+
+ HardwareAuthToken authToken;
+ std::tie(result->resultCode, authToken) = getOperationAuthTokenIfNeeded(token);
+ if (!result->resultCode.isOk()) return Status::ok();
+
+ // 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());
+
+ result->resultCode = enforcement_policy.AuthorizeOperation(
+ op.purpose, op.keyid, key_auths, params.getParameters(), authToken, op.handle,
+ false /* is_begin_operation */);
+ if (!result->resultCode.isOk()) return Status::ok();
+
+ std::vector<KeyParameter> inParams = params.getParameters();
+
auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
- const hidl_vec<KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
+ const hidl_vec<KeyParameter>& outParams,
+ const ::std::vector<uint8_t>& output) {
result->resultCode = ret;
- if (!result->resultCode.isOk()) {
- return;
+ if (result->resultCode.isOk()) {
+ result->inputConsumed = inputConsumed;
+ result->outParams = outParams;
+ result->data = output;
}
- result->inputConsumed = inputConsumed;
- result->outParams = outParams;
- result->data = output;
};
- KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->update(handle, opParams.hidl_data(),
- data, hidlCb));
+ KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+ op.device->update(op.handle, inParams, data, 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;
+ // removeOperation() will free the memory 'op' used, so the order is important
+ mAuthTokenTable.MarkCompleted(op.handle);
+ mOperationMap.removeOperation(token, /* wasOpSuccessful */ false);
}
+
+ return Status::ok();
}
-void KeyStoreService::finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
- OperationResult* result) {
+Status KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArguments& params,
+ const ::std::vector<uint8_t>& signature,
+ const ::std::vector<uint8_t>& entropy, OperationResult* result) {
KEYSTORE_SERVICE_LOCK;
- if (!checkAllowedOperationParams(params)) {
- result->resultCode = ErrorCode::INVALID_ARGUMENT;
- return;
- }
- km_device_t dev;
- uint64_t handle;
- KeyPurpose purpose;
- km_id_t keyid;
- const KeyCharacteristics* characteristics;
- if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
+ auto getOpResult = mOperationMap.getOperation(token);
+ if (!getOpResult.isOk()) {
result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
- return;
+ return Status::ok();
}
- AuthorizationSet opParams = params;
- result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
- if (!result->resultCode.isOk()) {
- return;
+ const auto& op = std::move(getOpResult.value());
+ if (!checkAllowedOperationParams(params.getParameters())) {
+ result->resultCode = ErrorCode::INVALID_ARGUMENT;
+ return Status::ok();
}
+ HardwareAuthToken authToken;
+ std::tie(result->resultCode, authToken) = getOperationAuthTokenIfNeeded(token);
+ if (!result->resultCode.isOk()) return Status::ok();
+
if (entropy.size()) {
- result->resultCode = addRngEntropy(entropy);
+ result->resultCode = KS_HANDLE_HIDL_ERROR(op.device->addRngEntropy(entropy));
if (!result->resultCode.isOk()) {
- return;
+ return Status::ok();
}
}
// Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths(characteristics->teeEnforced);
- key_auths.append(&characteristics->softwareEnforced[0],
- &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
+ AuthorizationSet key_auths(op.characteristics.hardwareEnforced);
+ key_auths.append(op.characteristics.softwareEnforced.begin(),
+ op.characteristics.softwareEnforced.end());
+
+ std::vector<KeyParameter> inParams = params.getParameters();
+ appendConfirmationTokenIfNeeded(op.characteristics, &inParams);
+
result->resultCode = enforcement_policy.AuthorizeOperation(
- purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
- if (!result->resultCode.isOk()) return;
+ op.purpose, op.keyid, key_auths, params.getParameters(), authToken, op.handle,
+ false /* is_begin_operation */);
+ if (!result->resultCode.isOk()) return Status::ok();
auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
- const hidl_vec<uint8_t>& output) {
+ const ::std::vector<uint8_t>& output) {
result->resultCode = ret;
- if (!result->resultCode.isOk()) {
- return;
+ if (result->resultCode.isOk()) {
+ result->outParams = outParams;
+ result->data = output;
}
- result->outParams = outParams;
- result->data = output;
};
- KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->finish(
- handle, opParams.hidl_data(),
- hidl_vec<uint8_t>() /* TODO(swillden): wire up input to finish() */, signature, hidlCb));
- // Remove the operation regardless of the result
- mOperationMap.removeOperation(token);
- mAuthTokenTable.MarkCompleted(handle);
+ KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
+ op.device->finish(op.handle, inParams,
+ ::std::vector<uint8_t>() /* TODO(swillden): wire up input to finish() */,
+ signature, authToken, op.verificationToken, hidlCb));
+ bool wasOpSuccessful = true;
// 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;
+ wasOpSuccessful = false;
}
+
+ // removeOperation() will free the memory 'op' used, so the order is important
+ mAuthTokenTable.MarkCompleted(op.handle);
+ mOperationMap.removeOperation(token, wasOpSuccessful);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::abort(const sp<IBinder>& token) {
+Status KeyStoreService::abort(const sp<IBinder>& token, int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
- km_device_t dev;
- uint64_t handle;
- KeyPurpose purpose;
- km_id_t keyid;
- if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
- return ErrorCode::INVALID_OPERATION_HANDLE;
+ auto getOpResult = mOperationMap.removeOperation(token, false /* wasOpSuccessful */);
+ if (!getOpResult.isOk()) {
+ *aidl_return = static_cast<int32_t>(ErrorCode::INVALID_OPERATION_HANDLE);
+ return Status::ok();
}
- mOperationMap.removeOperation(token);
+ auto op = std::move(getOpResult.value());
+ mAuthTokenTable.MarkCompleted(op.handle);
- ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->abort(handle));
- mAuthTokenTable.MarkCompleted(handle);
- return rc;
+ ErrorCode error_code = KS_HANDLE_HIDL_ERROR(op.device->abort(op.handle));
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(error_code));
+ return Status::ok();
}
-bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
+Status KeyStoreService::isOperationAuthorized(const sp<IBinder>& token, bool* aidl_return) {
KEYSTORE_SERVICE_LOCK;
- km_device_t dev;
- uint64_t handle;
- const KeyCharacteristics* characteristics;
- KeyPurpose purpose;
- km_id_t keyid;
- if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
- return false;
- }
- const HardwareAuthToken* authToken = NULL;
- mOperationMap.getOperationAuthToken(token, &authToken);
AuthorizationSet ignored;
- auto authResult = addOperationAuthTokenIfNeeded(token, &ignored);
- return authResult.isOk();
+ KeyStoreServiceReturnCode rc;
+ std::tie(rc, std::ignore) = getOperationAuthTokenIfNeeded(token);
+ *aidl_return = rc.isOk();
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
+Status KeyStoreService::addAuthToken(const ::std::vector<uint8_t>& authTokenAsVector,
+ int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
+
// 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());
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
- if (length != sizeof(hw_auth_token_t)) {
- return ErrorCode::INVALID_ARGUMENT;
+ if (authTokenAsVector.size() != sizeof(hw_auth_token_t)) {
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+ return Status::ok();
}
hw_auth_token_t authToken;
- memcpy(reinterpret_cast<void*>(&authToken), token, sizeof(hw_auth_token_t));
+ memcpy(reinterpret_cast<void*>(&authToken), authTokenAsVector.data(), sizeof(hw_auth_token_t));
if (authToken.version != 0) {
- return ErrorCode::INVALID_ARGUMENT;
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+ return Status::ok();
}
- std::unique_ptr<HardwareAuthToken> hidlAuthToken(new HardwareAuthToken);
- hidlAuthToken->challenge = authToken.challenge;
- hidlAuthToken->userId = authToken.user_id;
- hidlAuthToken->authenticatorId = authToken.authenticator_id;
- hidlAuthToken->authenticatorType = authToken.authenticator_type;
- hidlAuthToken->timestamp = authToken.timestamp;
- static_assert(
- std::is_same<decltype(hidlAuthToken->hmac),
- ::android::hardware::hidl_array<uint8_t, sizeof(authToken.hmac)>>::value,
- "This function assumes token HMAC is 32 bytes, but it might not be.");
- std::copy(authToken.hmac, authToken.hmac + sizeof(authToken.hmac), hidlAuthToken->hmac.data());
-
- // The table takes ownership of authToken.
- mAuthTokenTable.AddAuthenticationToken(hidlAuthToken.release());
- return ResponseCode::NO_ERROR;
+ mAuthTokenTable.AddAuthenticationToken(hidlVec2AuthToken(hidl_vec<uint8_t>(authTokenAsVector)));
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
}
-bool isDeviceIdAttestationRequested(const hidl_vec<KeyParameter>& params) {
- for (size_t i = 0; i < params.size(); ++i) {
- switch (params[i].tag) {
+int isDeviceIdAttestationRequested(const KeymasterArguments& params) {
+ const hardware::hidl_vec<KeyParameter> paramsVec = params.getParameters();
+ int result = 0;
+ for (size_t i = 0; i < paramsVec.size(); ++i) {
+ switch (paramsVec[i].tag) {
case Tag::ATTESTATION_ID_BRAND:
case Tag::ATTESTATION_ID_DEVICE:
- case Tag::ATTESTATION_ID_IMEI:
case Tag::ATTESTATION_ID_MANUFACTURER:
- case Tag::ATTESTATION_ID_MEID:
case Tag::ATTESTATION_ID_MODEL:
case Tag::ATTESTATION_ID_PRODUCT:
- case Tag::ATTESTATION_ID_SERIAL:
- return true;
- default:
+ result |= ID_ATTESTATION_REQUEST_GENERIC_INFO;
break;
+ case Tag::ATTESTATION_ID_IMEI:
+ case Tag::ATTESTATION_ID_MEID:
+ case Tag::ATTESTATION_ID_SERIAL:
+ result |= ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID;
+ break;
+ default:
+ continue;
}
}
- return false;
+ return result;
}
-KeyStoreServiceReturnCode KeyStoreService::attestKey(const String16& name,
- const hidl_vec<KeyParameter>& params,
- hidl_vec<hidl_vec<uint8_t>>* outChain) {
+Status KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
+ ::android::security::keymaster::KeymasterCertificateChain* chain,
+ int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
- if (!outChain) {
- return ErrorCode::OUTPUT_PARAMETER_NULL;
- }
-
- if (!checkAllowedOperationParams(params)) {
- return ErrorCode::INVALID_ARGUMENT;
- }
-
- if (isDeviceIdAttestationRequested(params)) {
- // There is a dedicated attestDeviceIds() method for device ID attestation.
- return ErrorCode::INVALID_ARGUMENT;
+ // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
+ if (!checkAllowedOperationParams(params.getParameters())) {
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+ return Status::ok();
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
- AuthorizationSet mutableParams = params;
+ int needsIdAttestation = isDeviceIdAttestationRequested(params);
+ bool needsUniqueIdAttestation = needsIdAttestation & ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID;
+ bool isPrimaryUserSystemUid = (callingUid == AID_SYSTEM);
+ bool isSomeUserSystemUid = (get_app_id(callingUid) == AID_SYSTEM);
+ // Allow system context from any user to request attestation with basic device information,
+ // while only allow system context from user 0 (device owner) to request attestation with
+ // unique device ID.
+ if ((needsIdAttestation && !isSomeUserSystemUid) ||
+ (needsUniqueIdAttestation && !isPrimaryUserSystemUid)) {
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+ return Status::ok();
+ }
+
+ AuthorizationSet mutableParams = params.getParameters();
KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
Blob keyBlob;
String8 name8(name);
rc = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
KeyStoreServiceReturnCode error;
@@ -1469,55 +1701,72 @@
if (!error.isOk()) {
return;
}
- if (outChain) *outChain = certChain;
+ if (chain) {
+ *chain = KeymasterCertificateChain(certChain);
+ }
};
auto hidlKey = blob2hidlVec(keyBlob);
- auto& dev = mKeyStore->getDevice(keyBlob);
+ auto dev = mKeyStore->getDevice(keyBlob);
rc = KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb));
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
- return error;
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::attestDeviceIds(const hidl_vec<KeyParameter>& params,
- hidl_vec<hidl_vec<uint8_t>>* outChain) {
+Status
+KeyStoreService::attestDeviceIds(const KeymasterArguments& params,
+ ::android::security::keymaster::KeymasterCertificateChain* chain,
+ int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
- if (!outChain) {
- return ErrorCode::OUTPUT_PARAMETER_NULL;
- }
+ // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
- if (!checkAllowedOperationParams(params)) {
- return ErrorCode::INVALID_ARGUMENT;
+ if (!checkAllowedOperationParams(params.getParameters())) {
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+ return Status::ok();
}
if (!isDeviceIdAttestationRequested(params)) {
// There is an attestKey() method for attesting keys without device ID attestation.
- return ErrorCode::INVALID_ARGUMENT;
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+ return Status::ok();
}
uid_t callingUid = IPCThreadState::self()->getCallingUid();
sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
if (binder == 0) {
- return ErrorCode::CANNOT_ATTEST_IDS;
+ *aidl_return =
+ static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::CANNOT_ATTEST_IDS));
+ return Status::ok();
}
if (!interface_cast<IPermissionController>(binder)->checkPermission(
String16("android.permission.READ_PRIVILEGED_PHONE_STATE"),
IPCThreadState::self()->getCallingPid(), callingUid)) {
- return ErrorCode::CANNOT_ATTEST_IDS;
+ *aidl_return =
+ static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::CANNOT_ATTEST_IDS));
+ return Status::ok();
}
- AuthorizationSet mutableParams = params;
+ AuthorizationSet mutableParams = params.getParameters();
KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
// Generate temporary key.
- auto& dev = mKeyStore->getDevice();
+ sp<Keymaster> dev = mKeyStore->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
+
+ if (!dev) {
+ *aidl_return = static_cast<int32_t>(ResponseCode::SYSTEM_ERROR);
+ return Status::ok();
+ }
+
KeyStoreServiceReturnCode error;
- hidl_vec<uint8_t> hidlKey;
+ ::std::vector<uint8_t> hidlKey;
AuthorizationSet keyCharacteristics;
keyCharacteristics.push_back(TAG_PURPOSE, KeyPurpose::VERIFY);
@@ -1525,7 +1774,7 @@
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);
- auto generateHidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
+ auto generateHidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& hidlKeyBlob,
const KeyCharacteristics&) {
error = ret;
if (!error.isOk()) {
@@ -1536,10 +1785,12 @@
rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(keyCharacteristics.hidl_data(), generateHidlCb));
if (!rc.isOk()) {
- return rc;
+ *aidl_return = static_cast<int32_t>(rc);
+ return Status::ok();
}
if (!error.isOk()) {
- return error;
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
}
// Attest key and device IDs.
@@ -1548,28 +1799,145 @@
if (!error.isOk()) {
return;
}
- *outChain = certChain;
+ *chain = ::android::security::keymaster::KeymasterCertificateChain(certChain);
};
KeyStoreServiceReturnCode attestationRc =
- KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), attestHidlCb));
+ KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), attestHidlCb));
// Delete temporary key.
KeyStoreServiceReturnCode deletionRc = KS_HANDLE_HIDL_ERROR(dev->deleteKey(hidlKey));
if (!attestationRc.isOk()) {
- return attestationRc;
+ *aidl_return = static_cast<int32_t>(attestationRc);
+ return Status::ok();
}
if (!error.isOk()) {
- return error;
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
}
- return deletionRc;
+ *aidl_return = static_cast<int32_t>(deletionRc);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::onDeviceOffBody() {
+Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) {
KEYSTORE_SERVICE_LOCK;
// TODO(tuckeris): add permission check. This should be callable from ClockworkHome only.
mAuthTokenTable.onDeviceOffBody();
- return ResponseCode::NO_ERROR;
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+ return Status::ok();
+}
+
+#define AIDL_RETURN(rc) \
+ (*_aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(rc)), Status::ok())
+
+Status KeyStoreService::importWrappedKey(
+ 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,
+ ::android::security::keymaster::KeyCharacteristics* outCharacteristics, int32_t* _aidl_return) {
+ KEYSTORE_SERVICE_LOCK;
+
+ uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+ if (!checkBinderPermission(P_INSERT, callingUid)) {
+ return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
+ }
+
+ Blob wrappingKeyBlob;
+ String8 wrappingKeyName8(wrappingKeyAlias);
+ KeyStoreServiceReturnCode rc =
+ mKeyStore->getKeyForName(&wrappingKeyBlob, wrappingKeyName8, callingUid, TYPE_KEYMASTER_10);
+ if (!rc.isOk()) {
+ return AIDL_RETURN(rc);
+ }
+
+ SecurityLevel securityLevel = wrappingKeyBlob.getSecurityLevel();
+ auto dev = mKeyStore->getDevice(securityLevel);
+ if (!dev) {
+ return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
+ }
+
+ auto hidlWrappingKey = blob2hidlVec(wrappingKeyBlob);
+ String8 wrappedKeyAlias8(wrappedKeyAlias);
+
+ KeyStoreServiceReturnCode error;
+
+ auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& keyBlob,
+ const KeyCharacteristics& keyCharacteristics) {
+ error = ret;
+ if (!error.isOk()) {
+ return;
+ }
+ if (outCharacteristics) {
+ *outCharacteristics =
+ ::android::security::keymaster::KeyCharacteristics(keyCharacteristics);
+ }
+
+ // Write the key:
+ String8 filename(
+ mKeyStore->getKeyNameForUidWithDir(wrappedKeyAlias8, callingUid, ::TYPE_KEYMASTER_10));
+
+ Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
+ ksBlob.setSecurityLevel(securityLevel);
+
+ if (containsTag(keyCharacteristics.hardwareEnforced, Tag::USER_SECURE_ID)) {
+ ksBlob.setSuperEncrypted(true);
+ }
+
+ error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(callingUid));
+ };
+
+ rc = KS_HANDLE_HIDL_ERROR(dev->importWrappedKey(wrappedKey, hidlWrappingKey, maskingKey,
+ params.getParameters(), rootSid, fingerprintSid,
+ hidlCb));
+
+ // possible hidl error
+ if (!rc.isOk()) {
+ return AIDL_RETURN(rc);
+ }
+ // now check error from callback
+ if (!error.isOk()) {
+ return AIDL_RETURN(error);
+ }
+
+ // Write the characteristics:
+ String8 cFilename(mKeyStore->getKeyNameForUidWithDir(wrappedKeyAlias8, callingUid,
+ ::TYPE_KEY_CHARACTERISTICS));
+
+ AuthorizationSet opParams = params.getParameters();
+ std::stringstream kcStream;
+ opParams.Serialize(&kcStream);
+ if (kcStream.bad()) {
+ return AIDL_RETURN(ResponseCode::SYSTEM_ERROR);
+ }
+ auto kcBuf = kcStream.str();
+
+ Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0,
+ ::TYPE_KEY_CHARACTERISTICS);
+ charBlob.setSecurityLevel(securityLevel);
+
+ return AIDL_RETURN(mKeyStore->put(cFilename.string(), &charBlob, get_user_id(callingUid)));
+}
+
+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) {
+ KEYSTORE_SERVICE_LOCK;
+ return mConfirmationManager->presentConfirmationPrompt(listener, promptText, extraData, locale,
+ uiOptionsAsFlags, aidl_return);
+}
+
+Status KeyStoreService::cancelConfirmationPrompt(const sp<IBinder>& listener,
+ int32_t* aidl_return) {
+ KEYSTORE_SERVICE_LOCK;
+ return mConfirmationManager->cancelConfirmationPrompt(listener, aidl_return);
+}
+
+Status KeyStoreService::isConfirmationPromptSupported(bool* aidl_return) {
+ KEYSTORE_SERVICE_LOCK;
+ return mConfirmationManager->isConfirmationPromptSupported(aidl_return);
}
/**
@@ -1581,7 +1949,8 @@
size_t op_count_before_abort = mOperationMap.getOperationCount();
// We mostly ignore errors from abort() because all we care about is whether at least
// one operation has been removed.
- int abort_error = abort(oldest);
+ int32_t abort_error;
+ abort(oldest, &abort_error);
if (mOperationMap.getOperationCount() >= op_count_before_abort) {
ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), abort_error);
return false;
@@ -1683,14 +2052,13 @@
}
/**
- * Check that all KeyParameter's provided by the application are
- * allowed. Any parameter that keystore adds itself should be disallowed here.
+ * 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::AUTH_TOKEN:
case Tag::RESET_SINCE_ID_ROTATION:
return false;
default:
@@ -1701,14 +2069,14 @@
}
ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>& key,
- km_device_t* dev,
+ sp<Keymaster>* dev,
const AuthorizationSet& params,
KeyCharacteristics* out) {
- hidl_vec<uint8_t> appId;
- hidl_vec<uint8_t> appData;
+ ::std::vector<uint8_t> clientId;
+ ::std::vector<uint8_t> appData;
for (auto param : params) {
if (param.tag == Tag::APPLICATION_ID) {
- appId = authorizationValue(TAG_APPLICATION_ID, param).value();
+ clientId = authorizationValue(TAG_APPLICATION_ID, param).value();
} else if (param.tag == Tag::APPLICATION_DATA) {
appData = authorizationValue(TAG_APPLICATION_DATA, param).value();
}
@@ -1723,7 +2091,8 @@
if (out) *out = keyCharacteristics;
};
- ErrorCode rc = KS_HANDLE_HIDL_ERROR((*dev)->getKeyCharacteristics(key, appId, appData, hidlCb));
+ ErrorCode rc =
+ KS_HANDLE_HIDL_ERROR((*dev)->getKeyCharacteristics(key, clientId, appData, hidlCb));
if (rc != ErrorCode::OK) {
return rc;
}
@@ -1740,36 +2109,44 @@
* KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
* token for the operation
*/
-KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics,
- uint64_t handle, KeyPurpose purpose,
- const HardwareAuthToken** authToken,
- bool failOnTokenMissing) {
+std::pair<KeyStoreServiceReturnCode, HardwareAuthToken>
+KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle,
+ KeyPurpose purpose, bool failOnTokenMissing) {
- AuthorizationSet allCharacteristics;
- for (size_t i = 0; i < characteristics.softwareEnforced.size(); i++) {
- allCharacteristics.push_back(characteristics.softwareEnforced[i]);
- }
- for (size_t i = 0; i < characteristics.teeEnforced.size(); i++) {
- allCharacteristics.push_back(characteristics.teeEnforced[i]);
- }
- AuthTokenTable::Error err =
- mAuthTokenTable.FindAuthorization(allCharacteristics, purpose, handle, authToken);
+ AuthorizationSet allCharacteristics(characteristics.softwareEnforced);
+ allCharacteristics.append(characteristics.hardwareEnforced.begin(),
+ characteristics.hardwareEnforced.end());
+
+ const HardwareAuthToken* authToken = nullptr;
+ AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
+ allCharacteristics, static_cast<KeyPurpose>(purpose), handle, &authToken);
+
+ KeyStoreServiceReturnCode rc;
+
switch (err) {
case AuthTokenTable::OK:
case AuthTokenTable::AUTH_NOT_REQUIRED:
- return ResponseCode::NO_ERROR;
+ 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
- return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+ ALOGE("getAuthToken failed: %d", err); // STOPSHIP: debug only, to be removed
+ rc = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
+ break;
+
case AuthTokenTable::OP_HANDLE_REQUIRED:
- return failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
- : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
+ rc = failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
+ : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
+ break;
+
default:
ALOGE("Unexpected FindAuthorization return value %d", err);
- return ErrorCode::INVALID_ARGUMENT;
+ rc = ErrorCode::INVALID_ARGUMENT;
}
+
+ return {rc, authToken ? std::move(*authToken) : HardwareAuthToken()};
}
/**
@@ -1783,29 +2160,23 @@
* KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
* operation token.
*/
-KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
- AuthorizationSet* params) {
- const HardwareAuthToken* authToken = nullptr;
- mOperationMap.getOperationAuthToken(token, &authToken);
- if (!authToken) {
- km_device_t dev;
- uint64_t handle;
- const KeyCharacteristics* characteristics = nullptr;
- KeyPurpose purpose;
- km_id_t keyid;
- if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
- return ErrorCode::INVALID_OPERATION_HANDLE;
- }
- auto result = getAuthToken(*characteristics, handle, purpose, &authToken);
- if (!result.isOk()) {
- return result;
- }
- if (authToken) {
- mOperationMap.setOperationAuthToken(token, authToken);
- }
+std::pair<KeyStoreServiceReturnCode, const HardwareAuthToken&>
+KeyStoreService::getOperationAuthTokenIfNeeded(const sp<IBinder>& token) {
+ static HardwareAuthToken emptyToken = {};
+
+ auto getOpResult = mOperationMap.getOperation(token);
+ if (!getOpResult.isOk()) return {ErrorCode::INVALID_OPERATION_HANDLE, emptyToken};
+ const auto& op = getOpResult.value();
+
+ if (!op.hasAuthToken()) {
+ KeyStoreServiceReturnCode rc;
+ HardwareAuthToken found;
+ std::tie(rc, found) = getAuthToken(op.characteristics, op.handle, op.purpose);
+ if (!rc.isOk()) return {rc, emptyToken};
+ mOperationMap.setOperationAuthToken(token, std::move(found));
}
- addAuthTokenToParams(params, authToken);
- return ResponseCode::NO_ERROR;
+
+ return {ResponseCode::NO_ERROR, op.authToken};
}
/**
@@ -1813,21 +2184,19 @@
* preserved and keymaster errors become SYSTEM_ERRORs
*/
KeyStoreServiceReturnCode KeyStoreService::translateResultToLegacyResult(int32_t result) {
- if (result > 0) {
- return static_cast<ResponseCode>(result);
- }
+ if (result > 0) return static_cast<ResponseCode>(result);
return ResponseCode::SYSTEM_ERROR;
}
-static NullOr<const Algorithm&>
-getKeyAlgoritmFromKeyCharacteristics(const KeyCharacteristics& characteristics) {
- for (size_t i = 0; i < characteristics.teeEnforced.size(); ++i) {
- auto algo = authorizationValue(TAG_ALGORITHM, characteristics.teeEnforced[i]);
- if (algo.isOk()) return algo.value();
+static NullOr<const Algorithm&> getKeyAlgoritmFromKeyCharacteristics(
+ const ::android::security::keymaster::KeyCharacteristics& characteristics) {
+ for (const auto& param : characteristics.hardwareEnforced.getParameters()) {
+ auto algo = authorizationValue(TAG_ALGORITHM, param);
+ if (algo.isOk()) return algo;
}
- for (size_t i = 0; i < characteristics.softwareEnforced.size(); ++i) {
- auto algo = authorizationValue(TAG_ALGORITHM, characteristics.softwareEnforced[i]);
- if (algo.isOk()) return algo.value();
+ for (const auto& param : characteristics.softwareEnforced.getParameters()) {
+ auto algo = authorizationValue(TAG_ALGORITHM, param);
+ if (algo.isOk()) return algo;
}
return {};
}
@@ -1838,9 +2207,11 @@
params->push_back(TAG_PADDING, PaddingMode::NONE);
// Look up the algorithm of the key.
- KeyCharacteristics characteristics;
- auto rc = getKeyCharacteristics(name, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF,
- &characteristics);
+ ::android::security::keymaster::KeyCharacteristics characteristics;
+ int32_t result;
+ auto rc = getKeyCharacteristics(name, ::android::security::keymaster::KeymasterBlob(),
+ ::android::security::keymaster::KeymasterBlob(), UID_SELF,
+ &characteristics, &result);
if (!rc.isOk()) {
ALOGE("Failed to get key characteristics");
return;
@@ -1866,8 +2237,8 @@
sp<IBinder> appToken(new BBinder);
sp<IBinder> token;
- begin(appToken, name, purpose, true, inArgs.hidl_data(), hidl_vec<uint8_t>(), UID_SELF,
- &result);
+ begin(appToken, name, static_cast<int32_t>(purpose), true,
+ KeymasterArguments(inArgs.hidl_data()), ::std::vector<uint8_t>(), UID_SELF, &result);
if (!result.resultCode.isOk()) {
if (result.resultCode == ResponseCode::KEY_NOT_FOUND) {
ALOGW("Key not found");
@@ -1883,7 +2254,7 @@
hidl_vec<uint8_t> data_view;
do {
data_view.setToExternal(const_cast<uint8_t*>(&data[consumed]), data.size() - consumed);
- update(token, inArgs.hidl_data(), data_view, &result);
+ update(token, KeymasterArguments(inArgs.hidl_data()), data_view, &result);
if (result.resultCode != ResponseCode::NO_ERROR) {
ALOGW("Error in update: %d", int32_t(result.resultCode));
return translateResultToLegacyResult(result.resultCode);
@@ -1900,7 +2271,8 @@
return ResponseCode::SYSTEM_ERROR;
}
- finish(token, inArgs.hidl_data(), signature, hidl_vec<uint8_t>(), &result);
+ finish(token, KeymasterArguments(inArgs.hidl_data()), signature, ::std::vector<uint8_t>(),
+ &result);
if (result.resultCode != ResponseCode::NO_ERROR) {
ALOGW("Error in finish: %d", int32_t(result.resultCode));
return translateResultToLegacyResult(result.resultCode);
@@ -1923,19 +2295,23 @@
Blob* blob) {
// Read the blob rather than assuming the caller provided the right name/uid/blob triplet.
String8 name8(name);
- ResponseCode responseCode = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
+ KeyStoreServiceReturnCode responseCode =
+ mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
if (responseCode != ResponseCode::NO_ERROR) {
return responseCode;
}
ALOGI("upgradeKeyBlob %s %d", name8.string(), uid);
auto hidlKey = blob2hidlVec(*blob);
- auto& dev = mKeyStore->getDevice(*blob);
+ auto dev = mKeyStore->getDevice(*blob);
KeyStoreServiceReturnCode error;
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
+ auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& upgradedKeyBlob) {
error = ret;
if (!error.isOk()) {
+ if (error == ErrorCode::INVALID_KEY_BLOB) {
+ log_key_integrity_violation(name8, uid);
+ }
return;
}
@@ -1952,7 +2328,7 @@
Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */,
0 /* infoLength */, ::TYPE_KEYMASTER_10);
- newBlob.setFallback(blob->isFallback());
+ newBlob.setSecurityLevel(blob->getSecurityLevel());
newBlob.setEncrypted(blob->isEncrypted());
newBlob.setSuperEncrypted(blob->isSuperEncrypted());
newBlob.setCriticalToDeviceEncryption(blob->isCriticalToDeviceEncryption());
@@ -1976,4 +2352,16 @@
return error;
}
+Status KeyStoreService::onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
+ int32_t* aidl_return) {
+ KEYSTORE_SERVICE_LOCK;
+ enforcement_policy.set_device_locked(isShowing, userId);
+ if (!isShowing) {
+ mActiveUserId = userId;
+ }
+ *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
+
+ return Status::ok();
+}
+
} // namespace keystore
diff --git a/keystore/key_store_service.h b/keystore/key_store_service.h
index 1b2a357..0a1c1dd 100644
--- a/keystore/key_store_service.h
+++ b/keystore/key_store_service.h
@@ -17,59 +17,67 @@
#ifndef KEYSTORE_KEYSTORE_SERVICE_H_
#define KEYSTORE_KEYSTORE_SERVICE_H_
-#include <keystore/IKeystoreService.h>
-
-#include <keystore/authorization_set.h>
+#include <android/security/BnKeystoreService.h>
#include "auth_token_table.h"
-#include "keystore.h"
+#include "confirmation_manager.h"
+
+#include "KeyStore.h"
#include "keystore_keymaster_enforcement.h"
#include "operation.h"
#include "permissions.h"
namespace keystore {
-class KeyStoreService : public android::BnKeystoreService, public android::IBinder::DeathRecipient {
- typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
-
+// 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::BnKeystoreService,
+ android::IBinder::DeathRecipient {
public:
- explicit KeyStoreService(KeyStore* keyStore) : mKeyStore(keyStore), mOperationMap(this) {}
+ explicit KeyStoreService(KeyStore* keyStore)
+ : mKeyStore(keyStore), mOperationMap(this),
+ mConfirmationManager(new ConfirmationManager(this)), mActiveUserId(0) {}
+ virtual ~KeyStoreService() = default;
void binderDied(const android::wp<android::IBinder>& who);
- KeyStoreServiceReturnCode getState(int32_t userId) override;
-
- KeyStoreServiceReturnCode get(const android::String16& name, int32_t uid,
- hidl_vec<uint8_t>* item) override;
- KeyStoreServiceReturnCode insert(const android::String16& name, const hidl_vec<uint8_t>& item,
- int targetUid, int32_t flags) override;
- KeyStoreServiceReturnCode del(const android::String16& name, int targetUid) override;
- KeyStoreServiceReturnCode exist(const android::String16& name, int targetUid) override;
- KeyStoreServiceReturnCode list(const android::String16& prefix, int targetUid,
- android::Vector<android::String16>* matches) override;
-
- KeyStoreServiceReturnCode reset() override;
-
- KeyStoreServiceReturnCode onUserPasswordChanged(int32_t userId,
- const android::String16& password) override;
- KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override;
- KeyStoreServiceReturnCode onUserRemoved(int32_t userId) override;
-
- KeyStoreServiceReturnCode lock(int32_t userId) override;
- KeyStoreServiceReturnCode unlock(int32_t userId, const android::String16& pw) override;
-
- bool isEmpty(int32_t userId) override;
-
- KeyStoreServiceReturnCode
- generate(const android::String16& name, int32_t targetUid, int32_t keyType, int32_t keySize,
- int32_t flags, android::Vector<android::sp<android::KeystoreArg>>* args) override;
- KeyStoreServiceReturnCode import(const android::String16& name, const hidl_vec<uint8_t>& data,
- int targetUid, int32_t flags) override;
- KeyStoreServiceReturnCode sign(const android::String16& name, const hidl_vec<uint8_t>& data,
- hidl_vec<uint8_t>* out) override;
- KeyStoreServiceReturnCode verify(const android::String16& name, const hidl_vec<uint8_t>& data,
- const hidl_vec<uint8_t>& signature) override;
-
+ ::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 reset(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 generate(const ::android::String16& name, int32_t uid,
+ int32_t keyType, int32_t keySize, int32_t flags,
+ const ::android::security::KeystoreArguments& args,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status import_key(const ::android::String16& name,
+ const ::std::vector<uint8_t>& data, int32_t uid,
+ int32_t flags, int32_t* _aidl_return) override;
+ ::android::binder::Status sign(const ::android::String16& name,
+ const ::std::vector<uint8_t>& data,
+ ::std::vector<uint8_t>* _aidl_return) override;
+ ::android::binder::Status verify(const ::android::String16& name,
+ const ::std::vector<uint8_t>& data,
+ const ::std::vector<uint8_t>& signature,
+ int32_t* _aidl_return) override;
/*
* TODO: The abstraction between things stored in hardware and regular blobs
* of data stored on the filesystem should be moved down to keystore itself.
@@ -81,60 +89,96 @@
* "del_key" since the Java code doesn't really communicate what it's
* intentions are.
*/
- KeyStoreServiceReturnCode get_pubkey(const android::String16& name,
- hidl_vec<uint8_t>* pubKey) override;
+ ::android::binder::Status get_pubkey(const ::android::String16& name,
+ ::std::vector<uint8_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 ::std::vector<uint8_t>& data, int32_t flags,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status
+ generateKey(const ::android::String16& alias,
+ const ::android::security::keymaster::KeymasterArguments& arguments,
+ const ::std::vector<uint8_t>& entropy, int32_t uid, int32_t flags,
+ ::android::security::keymaster::KeyCharacteristics* characteristics,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status
+ getKeyCharacteristics(const ::android::String16& alias,
+ const ::android::security::keymaster::KeymasterBlob& clientId,
+ const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid,
+ ::android::security::keymaster::KeyCharacteristics* characteristics,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status
+ importKey(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,
+ ::android::security::keymaster::KeyCharacteristics* characteristics,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status
+ exportKey(const ::android::String16& alias, int32_t format,
+ const ::android::security::keymaster::KeymasterBlob& clientId,
+ const ::android::security::keymaster::KeymasterBlob& appId, int32_t uid,
+ ::android::security::keymaster::ExportResult* _aidl_return) override;
+ ::android::binder::Status
+ begin(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,
+ ::android::security::keymaster::OperationResult* _aidl_return) override;
+ ::android::binder::Status
+ update(const ::android::sp<::android::IBinder>& token,
+ const ::android::security::keymaster::KeymasterArguments& params,
+ const ::std::vector<uint8_t>& input,
+ ::android::security::keymaster::OperationResult* _aidl_return) override;
+ ::android::binder::Status
+ finish(const ::android::sp<::android::IBinder>& token,
+ const ::android::security::keymaster::KeymasterArguments& params,
+ const ::std::vector<uint8_t>& signature, const ::std::vector<uint8_t>& entropy,
+ ::android::security::keymaster::OperationResult* _aidl_return) override;
+ ::android::binder::Status abort(const ::android::sp<::android::IBinder>& handle,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status isOperationAuthorized(const ::android::sp<::android::IBinder>& token,
+ bool* _aidl_return) override;
+ ::android::binder::Status addAuthToken(const ::std::vector<uint8_t>& authToken,
+ int32_t* _aidl_return) 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::String16& alias,
+ const ::android::security::keymaster::KeymasterArguments& params,
+ ::android::security::keymaster::KeymasterCertificateChain* chain,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status
+ attestDeviceIds(const ::android::security::keymaster::KeymasterArguments& params,
+ ::android::security::keymaster::KeymasterCertificateChain* chain,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status onDeviceOffBody(int32_t* _aidl_return) override;
- android::String16 grant(const android::String16& name, int32_t granteeUid) override;
- KeyStoreServiceReturnCode ungrant(const android::String16& name, int32_t granteeUid) override;
+ ::android::binder::Status importWrappedKey(
+ 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, ::android::security::keymaster::KeyCharacteristics* characteristics,
+ int32_t* _aidl_return) override;
- int64_t getmtime(const android::String16& name, int32_t uid) 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;
- KeyStoreServiceReturnCode duplicate(const android::String16& srcKey, int32_t srcUid,
- const android::String16& destKey, int32_t destUid) override;
-
- int32_t is_hardware_backed(const android::String16& keyType) override;
-
- KeyStoreServiceReturnCode clear_uid(int64_t targetUid64) override;
-
- KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override;
- KeyStoreServiceReturnCode generateKey(const android::String16& name,
- const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& entropy, int uid, int flags,
- KeyCharacteristics* outCharacteristics) override;
- KeyStoreServiceReturnCode
- getKeyCharacteristics(const android::String16& name, const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData, int32_t uid,
- KeyCharacteristics* outCharacteristics) override;
- KeyStoreServiceReturnCode importKey(const android::String16& name,
- const hidl_vec<KeyParameter>& params, KeyFormat format,
- const hidl_vec<uint8_t>& keyData, int uid, int flags,
- KeyCharacteristics* outCharacteristics) override;
- void exportKey(const android::String16& name, KeyFormat format,
- const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData, int32_t uid,
- android::ExportResult* result) override;
- void begin(const sp<android::IBinder>& appToken, const android::String16& name,
- KeyPurpose purpose, bool pruneable, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& entropy, int32_t uid,
- android::OperationResult* result) override;
- void update(const sp<android::IBinder>& token, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& data, android::OperationResult* result) override;
- void finish(const sp<android::IBinder>& token, const hidl_vec<KeyParameter>& params,
- const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
- android::OperationResult* result) override;
- KeyStoreServiceReturnCode abort(const sp<android::IBinder>& token) override;
-
- bool isOperationAuthorized(const sp<android::IBinder>& token) override;
-
- KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override;
-
- KeyStoreServiceReturnCode attestKey(const android::String16& name,
- const hidl_vec<KeyParameter>& params,
- hidl_vec<hidl_vec<uint8_t>>* outChain) override;
-
- KeyStoreServiceReturnCode attestDeviceIds(const hidl_vec<KeyParameter>& params,
- hidl_vec<hidl_vec<uint8_t>>* outChain) override;
-
- KeyStoreServiceReturnCode onDeviceOffBody() override;
+ ::android::binder::Status onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
+ int32_t* _aidl_return);
private:
static const int32_t UID_SELF = -1;
@@ -191,37 +235,34 @@
*/
bool checkAllowedOperationParams(const hidl_vec<KeyParameter>& params);
- ErrorCode getOperationCharacteristics(const hidl_vec<uint8_t>& key, km_device_t* dev,
+ ErrorCode getOperationCharacteristics(const hidl_vec<uint8_t>& key, sp<Keymaster>* dev,
const AuthorizationSet& params, KeyCharacteristics* out);
/**
* Get the auth token for this operation from the auth token table.
*
- * Returns ::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
+ * 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
*/
- KeyStoreServiceReturnCode getAuthToken(const KeyCharacteristics& characteristics,
- uint64_t handle, KeyPurpose purpose,
- const HardwareAuthToken** authToken,
- bool failOnTokenMissing = true);
+ std::pair<KeyStoreServiceReturnCode, HardwareAuthToken>
+ getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle, KeyPurpose purpose,
+ bool failOnTokenMissing = true);
/**
- * Add the auth token for the operation to the param list if the operation
- * requires authorization. Uses the cached result in the OperationMap if available
- * otherwise gets the token from the AuthTokenTable and caches the result.
+ * Get the auth token for the operation if the operation requires authorization. Uses the cached
+ * result in the OperationMap if available otherwise gets the token from the AuthTokenTable and
+ * caches the result.
*
- * Returns ::NO_ERROR if the auth token was added or not needed.
- * KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
- * authenticated.
- * KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
- * operation token.
+ * Returns NO_ERROR if the auth token was found or not needed. If not needed, the token will
+ * be empty (which keymaster interprets as no auth token).
+ * KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not authenticated.
+ * KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid operation token.
*/
- KeyStoreServiceReturnCode addOperationAuthTokenIfNeeded(const sp<android::IBinder>& token,
- AuthorizationSet* params);
+ std::pair<KeyStoreServiceReturnCode, const HardwareAuthToken&>
+ getOperationAuthTokenIfNeeded(const sp<android::IBinder>& token);
/**
* Translate a result value to a legacy return value. All keystore errors are
@@ -248,7 +289,13 @@
KeyStoreServiceReturnCode upgradeKeyBlob(const android::String16& name, uid_t targetUid,
const AuthorizationSet& params, Blob* blob);
- ::KeyStore* mKeyStore;
+ /**
+ * Adds a Confirmation Token to the key parameters if needed.
+ */
+ void appendConfirmationTokenIfNeeded(const KeyCharacteristics& keyCharacteristics,
+ std::vector<KeyParameter>* params);
+
+ KeyStore* mKeyStore;
/**
* This mutex locks keystore operations from concurrent execution.
@@ -261,8 +308,10 @@
*/
std::recursive_mutex keystoreServiceMutex_;
OperationMap mOperationMap;
+ android::sp<ConfirmationManager> mConfirmationManager;
keystore::AuthTokenTable mAuthTokenTable;
KeystoreKeymasterEnforcement enforcement_policy;
+ int32_t mActiveUserId;
};
}; // namespace keystore
diff --git a/keystore/keymaster_enforcement.cpp b/keystore/keymaster_enforcement.cpp
index 4cee57d..5a6e591 100644
--- a/keystore/keymaster_enforcement.cpp
+++ b/keystore/keymaster_enforcement.cpp
@@ -29,6 +29,8 @@
#include <hardware/hw_auth_token.h>
#include <list>
+#include <keystore/keystore_hidl_support.h>
+
namespace keystore {
class AccessTimeMap {
@@ -115,6 +117,7 @@
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) {
@@ -125,23 +128,23 @@
case KeyPurpose::DECRYPT:
case KeyPurpose::SIGN:
- case KeyPurpose::DERIVE_KEY:
break;
+
case KeyPurpose::WRAP_KEY:
return ErrorCode::INCOMPATIBLE_PURPOSE;
};
};
if (is_begin_operation)
- return AuthorizeBegin(purpose, keyid, auth_set, operation_params);
+ return AuthorizeBegin(purpose, keyid, auth_set, operation_params, auth_token);
else
- return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+ 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 AuthorizationSet& operation_params,
+ const HardwareAuthToken& auth_token,
uint64_t op_handle) {
int auth_type_index = -1;
for (size_t pos = 0; pos < auth_set.size(); ++pos) {
@@ -174,9 +177,9 @@
if (user_secure_id.isOk()) {
authentication_required = true;
int auth_timeout_index = -1;
- if (AuthTokenMatches(auth_set, operation_params, user_secure_id.value(),
- auth_type_index, auth_timeout_index, op_handle,
- false /* is_begin_operation */))
+ 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;
}
}
@@ -188,7 +191,8 @@
ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
const AuthorizationSet& auth_set,
- const AuthorizationSet& operation_params) {
+ 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;
@@ -219,6 +223,8 @@
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) {
@@ -270,21 +276,28 @@
if (auth_timeout_index != -1) {
auto secure_id = authorizationValue(TAG_USER_SECURE_ID, param);
authentication_required = true;
- if (secure_id.isOk() &&
- AuthTokenMatches(auth_set, operation_params, secure_id.value(), auth_type_index,
- auth_timeout_index, 0 /* op_handle */,
+ 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::AUTH_TOKEN:
case Tag::ROOT_OF_TRUST:
case Tag::APPLICATION_DATA:
case Tag::ATTESTATION_CHALLENGE:
@@ -309,21 +322,18 @@
case Tag::PADDING:
case Tag::NONCE:
case Tag::MIN_MAC_LENGTH:
- case Tag::KDF:
case Tag::EC_CURVE:
/* Tags not used for operations. */
case Tag::BLOB_USAGE_REQUIREMENTS:
- case Tag::EXPORTABLE:
/* Algorithm specific parameters not used for access control. */
case Tag::RSA_PUBLIC_EXPONENT:
- case Tag::ECIES_SINGLE_HASH_MODE:
/* Informational tags. */
case Tag::CREATION_DATETIME:
case Tag::ORIGIN:
- case Tag::ROLLBACK_RESISTANT:
+ case Tag::ROLLBACK_RESISTANCE:
/* Tags handled when KM_TAG_USER_SECURE_ID is handled */
case Tag::NO_AUTH_REQUIRED:
@@ -334,20 +344,21 @@
case Tag::ASSOCIATED_DATA:
/* Tags that are implicitly verified by secure side */
- case Tag::ALL_APPLICATIONS:
case Tag::APPLICATION_ID:
- case Tag::OS_VERSION:
+ case Tag::BOOT_PATCHLEVEL:
case Tag::OS_PATCHLEVEL:
-
- /* Ignored pending removal */
- case Tag::USER_ID:
- case Tag::ALL_USERS:
+ 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:
@@ -355,6 +366,19 @@
}
}
+ 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;
@@ -463,7 +487,7 @@
}
bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set,
- const AuthorizationSet& operation_params,
+ 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,
@@ -471,26 +495,6 @@
assert(auth_type_index < static_cast<int>(auth_set.size()));
assert(auth_timeout_index < static_cast<int>(auth_set.size()));
- auto auth_token_blob = operation_params.GetTagValue(TAG_AUTH_TOKEN);
- if (!auth_token_blob.isOk()) {
- ALOGE("Authentication required, but auth token not provided");
- return false;
- }
-
- if (auth_token_blob.value().size() != sizeof(hw_auth_token_t)) {
- ALOGE("Bug: Auth token is the wrong size (%zu expected, %zu found)",
- sizeof(hw_auth_token_t), auth_token_blob.value().size());
- return false;
- }
-
- hw_auth_token_t auth_token;
- memcpy(&auth_token, &auth_token_blob.value()[0], sizeof(hw_auth_token_t));
- if (auth_token.version != HW_AUTH_TOKEN_VERSION) {
- ALOGE("Bug: Auth token is the version %hhu (or is not an auth token). Expected %d",
- auth_token.version, HW_AUTH_TOKEN_VERSION);
- return false;
- }
-
if (!ValidateTokenSignature(auth_token)) {
ALOGE("Auth token signature invalid");
return false;
@@ -502,9 +506,9 @@
return false;
}
- if (user_secure_id != auth_token.user_id && user_secure_id != auth_token.authenticator_id) {
+ 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.user_id, auth_token.authenticator_id, user_secure_id);
+ auth_token.userId, auth_token.authenticatorId, user_secure_id);
return false;
}
@@ -513,19 +517,18 @@
return false;
}
- assert(auth_set[auth_type_index].tag == KM_TAG_USER_AUTH_TYPE);
+ 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;
- uint32_t token_auth_type = ntoh(auth_token.authenticator_type);
- if ((uint32_t(key_auth_type_mask.value()) & token_auth_type) == 0) {
+ 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(), token_auth_type);
+ 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 == KM_TAG_AUTH_TIMEOUT);
+ 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;
diff --git a/keystore/keymaster_enforcement.h b/keystore/keymaster_enforcement.h
index 4f22f01..6e6c54f 100644
--- a/keystore/keymaster_enforcement.h
+++ b/keystore/keymaster_enforcement.h
@@ -19,7 +19,7 @@
#include <stdio.h>
-#include <keystore/authorization_set.h>
+#include <keystore/keymaster_types.h>
namespace keystore {
@@ -51,7 +51,8 @@
*/
ErrorCode AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
const AuthorizationSet& auth_set,
- const AuthorizationSet& operation_params, uint64_t op_handle,
+ const AuthorizationSet& operation_params,
+ const HardwareAuthToken& auth_token, uint64_t op_handle,
bool is_begin_operation);
/**
@@ -61,16 +62,17 @@
*/
ErrorCode AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
const AuthorizationSet& auth_set,
- const AuthorizationSet& operation_params);
+ 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 AuthorizationSet& operation_params, uint64_t op_handle) {
- return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+ ErrorCode AuthorizeUpdate(const AuthorizationSet& auth_set, const HardwareAuthToken& auth_token,
+ uint64_t op_handle) {
+ return AuthorizeUpdateOrFinish(auth_set, auth_token, op_handle);
}
/**
@@ -78,9 +80,9 @@
* 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 AuthorizationSet& operation_params, uint64_t op_handle) {
- return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
+ ErrorCode AuthorizeFinish(const AuthorizationSet& auth_set, const HardwareAuthToken& auth_token,
+ uint64_t op_handle) {
+ return AuthorizeUpdateOrFinish(auth_set, auth_token, op_handle);
}
/**
@@ -121,7 +123,7 @@
/*
* Returns true if the specified auth_token is older than the specified timeout.
*/
- virtual bool auth_token_timed_out(const hw_auth_token_t& token, uint32_t timeout) const = 0;
+ 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
@@ -138,18 +140,23 @@
* Returns true if the specified auth_token has a valid signature, or if signature validation is
* not available.
*/
- virtual bool ValidateTokenSignature(const hw_auth_token_t& token) const = 0;
+ 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 AuthorizationSet& operation_params, uint64_t op_handle);
+ 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 AuthorizationSet& operation_params, 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;
+ 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_;
diff --git a/keystore/keystore.rc b/keystore/keystore.rc
index 5dac937..132039a 100644
--- a/keystore/keystore.rc
+++ b/keystore/keystore.rc
@@ -1,5 +1,5 @@
service keystore /system/bin/keystore /data/misc/keystore
class main
user keystore
- group keystore drmrpc readproc
+ 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
index 3137ae1..db9b983 100644
--- a/keystore/keystore_aidl_hidl_marshalling_utils.cpp
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.cpp
@@ -15,15 +15,21 @@
** limitations under the License.
*/
-#define LOG_TAG "KeystoreService"
-#include <utils/Log.h>
-
#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/KeystoreArg.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, bool inPlace) {
+
ssize_t length = in.readInt32();
if (length <= 0) {
return {};
@@ -43,44 +49,23 @@
if (!size) return ::android::OK;
- return out->write(&blob[0], size);
+ return out->write(blob.data(), size);
}
-NullOr<hidl_vec<uint8_t>> readBlobAsByteArray(const android::Parcel& in, bool inPlace) {
- // The distinction from readKeymasterBob is that the byte array is not prefixed with a presence
- // value, instead a -1 in the length field indicates NULL.
- ssize_t length = in.readInt32();
- if (length < 0) {
- return {};
- }
+android::status_t writeKeymasterBlob(const ::std::vector<int32_t>& blob, android::Parcel* out) {
- if (length == 0) {
- return hidl_vec<uint8_t>();
- }
-
- const void* buf = in.readInplace(length);
- if (!buf) return hidl_vec<uint8_t>();
-
- return blob2hidlVec(reinterpret_cast<const uint8_t*>(buf), size_t(length), inPlace);
-}
-
-android::status_t writeBlobAsByteArray(const NullOr<const hidl_vec<uint8_t>&>& blob,
- android::Parcel* out) {
- if (!blob.isOk()) {
- return out->writeInt32(-1);
- }
- int32_t size =
- int32_t(std::min<size_t>(blob.value().size(), std::numeric_limits<int32_t>::max()));
+ 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.value()[0], size);
+ 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 {};
}
@@ -105,7 +90,7 @@
break;
case TagType::BIGNUM:
case TagType::BYTES:
- result.blob = readKeymasterBlob(in);
+ result.blob = readKeymasterBlob(in); // byte array
break;
default:
ALOGE("Unsupported KeyParameter tag %d", tag);
@@ -115,6 +100,9 @@
}
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;
@@ -146,7 +134,8 @@
}
hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in) {
- ssize_t length = in.readInt32();
+
+ ssize_t length = in.readInt32(); // -1 for null
size_t ulength = (size_t)length;
if (length < 0) {
ulength = 0;
@@ -171,7 +160,7 @@
auto rc = out->writeInt32(size);
if (rc != ::android::OK) return rc;
for (int32_t i = 0; i < size; ++i) {
- rc = out->writeInt32(1);
+ rc = out->writeInt32(1); // writeTypedObject presence flag.
if (rc != ::android::OK) return rc;
rc = writeKeyParameterToParcel(params[i], out);
if (rc != ::android::OK) return rc;
@@ -179,21 +168,6 @@
return rc;
}
-KeyCharacteristics readKeyCharacteristicsFromParcel(const android::Parcel& in) {
- KeyCharacteristics result;
- result.softwareEnforced = readParamSetFromParcel(in);
- result.teeEnforced = readParamSetFromParcel(in);
- return result;
-}
-
-android::status_t writeKeyCharacteristicsToParcel(const KeyCharacteristics& keyChara,
- android::Parcel* out) {
- auto rc = writeParamSetToParcel(keyChara.softwareEnforced, out);
- if (rc != ::android::OK) return rc;
-
- return writeParamSetToParcel(keyChara.teeEnforced, out);
-}
-
hidl_vec<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel& in) {
hidl_vec<hidl_vec<uint8_t>> result;
@@ -209,7 +183,7 @@
result[i] = readKeymasterBlob(in);
}
return result;
-}
+};
android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>>& certs,
android::Parcel* out) {
@@ -222,4 +196,63 @@
}
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::keymaster::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);
+ 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, true /* in place */);
+ 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
index fcd02ae..13edbd2 100644
--- a/keystore/keystore_aidl_hidl_marshalling_utils.h
+++ b/keystore/keystore_aidl_hidl_marshalling_utils.h
@@ -18,10 +18,12 @@
#ifndef KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_
#define KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_
-#include <binder/Parcel.h>
-#include <keystore/keymaster_tags.h>
#include <utility>
+#include <binder/Parcel.h>
+
+#include <keystore/keymaster_types.h>
+
namespace keystore {
template <typename Fn, typename... Args>
@@ -71,13 +73,7 @@
hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in);
android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params, android::Parcel* out);
-KeyCharacteristics readKeyCharacteristicsFromParcel(const android::Parcel& in);
-android::status_t writeKeyCharacteristicsToParcel(const KeyCharacteristics& keyChara,
- android::Parcel* out);
-
hidl_vec<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel& in);
-android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>>& certs,
- android::Parcel* out);
}
#endif // KEYSTORE_KEYSTORE_AIDL_HIDL_MARSHALLING_UTILS_H_
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index 830482b..3d34ac5 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -34,7 +34,10 @@
#include <keystore/KeyAttestationPackageInfo.h>
#include <keystore/Signature.h>
+#include <private/android_filesystem_config.h> /* for AID_SYSTEM */
+
#include <openssl/asn1t.h>
+#include <openssl/bn.h>
#include <openssl/sha.h>
#include <utils/String8.h>
@@ -43,7 +46,9 @@
namespace {
-static std::vector<uint8_t> signature2SHA256(const content::pm::Signature& sig) {
+constexpr const char* kAttestationSystemPackageName = "AndroidSystem";
+
+std::vector<uint8_t> signature2SHA256(const content::pm::Signature& sig) {
std::vector<uint8_t> digest_buffer(SHA256_DIGEST_LENGTH);
SHA256(sig.data().data(), sig.data().size(), digest_buffer.data());
return digest_buffer;
@@ -95,7 +100,8 @@
ASN1_SET_OF(KM_ATTESTATION_APPLICATION_ID, signature_digests, ASN1_OCTET_STRING),
} ASN1_SEQUENCE_END(KM_ATTESTATION_APPLICATION_ID);
IMPLEMENT_ASN1_FUNCTIONS(KM_ATTESTATION_APPLICATION_ID);
-}
+
+} // namespace
} // namespace android
@@ -143,10 +149,20 @@
return UNKNOWN_ERROR;
}
- if (!ASN1_INTEGER_set(attestation_package_info->version, pinfo.version_code())) {
+ BIGNUM* bn_version = BN_new();
+ if (bn_version == nullptr) {
+ return NO_MEMORY;
+ }
+ if (BN_set_u64(bn_version, static_cast<uint64_t>(pinfo.version_code())) != 1) {
+ BN_free(bn_version);
return UNKNOWN_ERROR;
}
- return NO_ERROR;
+ status_t retval = NO_ERROR;
+ if (BN_to_ASN1_INTEGER(bn_version, attestation_package_info->version) == nullptr) {
+ retval = UNKNOWN_ERROR;
+ }
+ BN_free(bn_version);
+ return retval;
}
StatusOr<std::vector<uint8_t>>
@@ -226,15 +242,23 @@
} // namespace
StatusOr<std::vector<uint8_t>> gather_attestation_application_id(uid_t uid) {
- auto& pm = KeyAttestationApplicationIdProvider::get();
-
- /* Get the attestation application ID from package manager */
KeyAttestationApplicationId key_attestation_id;
- auto status = pm.getKeyAttestationApplicationId(uid, &key_attestation_id);
- if (!status.isOk()) {
- ALOGE("package manager request for key attestation ID failed with: %s",
- status.exceptionMessage().string());
- return FAILED_TRANSACTION;
+
+ if (uid == AID_SYSTEM) {
+ /* Use a fixed ID for system callers */
+ auto pinfo = std::make_unique<KeyAttestationPackageInfo>(
+ String16(kAttestationSystemPackageName), 1 /* version code */,
+ std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
+ key_attestation_id = KeyAttestationApplicationId(std::move(pinfo));
+ } else {
+ /* Get the attestation application ID from package manager */
+ auto& pm = KeyAttestationApplicationIdProvider::get();
+ auto status = pm.getKeyAttestationApplicationId(uid, &key_attestation_id);
+ if (!status.isOk()) {
+ ALOGE("package manager request for key attestation ID failed with: %s %d",
+ status.exceptionMessage().string(), status.exceptionCode());
+ return FAILED_TRANSACTION;
+ }
}
/* DER encode the attestation application ID */
diff --git a/keystore/keystore_cli.cpp b/keystore/keystore_cli.cpp
index 24af024..1e100fc 100644
--- a/keystore/keystore_cli.cpp
+++ b/keystore/keystore_cli.cpp
@@ -18,8 +18,9 @@
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
+#include <vector>
-#include <keystore/IKeystoreService.h>
+#include <android/security/IKeystoreService.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -27,6 +28,7 @@
using namespace android;
using namespace keystore;
+using android::security::IKeystoreService;
static const char* responses[] = {
NULL,
@@ -48,7 +50,8 @@
#define NO_ARG_INT_RETURN(cmd) \
do { \
if (strcmp(argv[1], #cmd) == 0) { \
- int32_t ret = service->cmd(); \
+ int32_t ret = -1; \
+ service->cmd(&ret); \
if (ret < 0) { \
fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
return 1; \
@@ -66,7 +69,8 @@
fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
return 1; \
} \
- int32_t ret = service->cmd(String16(argv[2])); \
+ 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; \
@@ -84,7 +88,8 @@
fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
return 1; \
} \
- int32_t ret = service->cmd(atoi(argv[2])); \
+ 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; \
@@ -107,7 +112,8 @@
uid = atoi(argv[3]); \
fprintf(stderr, "Running as uid %d\n", uid); \
} \
- int32_t ret = service->cmd(String16(argv[2]), 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; \
@@ -125,18 +131,15 @@
fprintf(stderr, "Usage: %s " #cmd " <name> <uid>\n", argv[0]); \
return 1; \
} \
- hidl_vec<uint8_t> data; \
+ std::vector<uint8_t> data; \
int uid = -1; \
if (argc > 3) { \
uid = atoi(argv[3]); \
fprintf(stderr, "Running as uid %d\n", uid); \
} \
- int32_t ret = service->cmd(String16(argv[2]), uid, &data); \
- if (ret < 0) { \
- fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
- return 1; \
- } else if (ret != ::NO_ERROR) { \
- fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
+ ::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); \
@@ -146,7 +149,7 @@
} \
} while (0)
-#define STING_ARG_DATA_STDIN_INT_RETURN(cmd) \
+#define STRING_ARG_DATA_STDIN_INT_RETURN(cmd) \
do { \
if (strcmp(argv[1], #cmd) == 0) { \
if (argc < 3) { \
@@ -156,7 +159,8 @@
uint8_t* data; \
size_t dataSize; \
read_input(&data, &dataSize); \
- int32_t ret = service->cmd(String16(argv[2]), 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; \
@@ -174,13 +178,10 @@
fprintf(stderr, "Usage: %s " #cmd " <name>\n", argv[0]); \
return 1; \
} \
- hidl_vec<uint8_t> data; \
- int32_t ret = service->cmd(String16(argv[2]), &data); \
- if (ret < 0) { \
- fprintf(stderr, "%s: could not connect: %d\n", argv[0], ret); \
- return 1; \
- } else if (ret != ::NO_ERROR) { \
- fprintf(stderr, "%s: " #cmd ": %s (%d)\n", argv[0], responses[ret], ret); \
+ 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); \
@@ -191,16 +192,14 @@
} while (0)
static int list(const sp<IKeystoreService>& service, const String16& name, int uid) {
- Vector<String16> matches;
- int32_t ret = service->list(name, uid, &matches);
- if (ret < 0) {
- fprintf(stderr, "list: could not connect: %d\n", ret);
- return 1;
- } else if (ret != ::NO_ERROR) {
- fprintf(stderr, "list: %s (%d)\n", responses[ret], ret);
+ 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 {
- Vector<String16>::const_iterator it = matches.begin();
+ std::vector<String16>::const_iterator it = matches.begin();
for (; it != matches.end(); ++it) {
printf("%s\n", String8(*it).string());
}
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index 95fc491..6377ec1 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -17,18 +17,34 @@
#include <string>
#include <vector>
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/strings/string_util.h"
-#include "keystore/authorization_set.h"
-#include "keystore/keymaster_tags.h"
-#include "keystore/keystore_client_impl.h"
+#include <base/command_line.h>
+#include <base/files/file_util.h>
+#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/IKeystoreService.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+//#include <keystore/keystore.h>
using base::CommandLine;
-using keystore::AuthorizationSet;
-//using keymaster::AuthorizationSetBuilder;
using keystore::KeystoreClient;
+using android::sp;
+using android::String16;
+using android::security::IKeystoreService;
+using base::CommandLine;
+using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
+
namespace {
using namespace keystore;
@@ -42,8 +58,8 @@
printf("Usage: keystore_client_v2 <command> [options]\n");
printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
" list-brillo-tests\n"
- " add-entropy --input=<entropy>\n"
- " generate --name=<key_name>\n"
+ " add-entropy --input=<entropy> [--seclevel=software|strongbox|tee(default)]\n"
+ " generate --name=<key_name> [--seclevel=software|strongbox|tee(default)]\n"
" get-chars --name=<key_name>\n"
" export --name=<key_name>\n"
" delete --name=<key_name>\n"
@@ -51,18 +67,23 @@
" exists --name=<key_name>\n"
" list [--prefix=<key_name_prefix>]\n"
" sign-verify --name=<key_name>\n"
- " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n");
+ " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n"
+ " [--seclevel=software|strongbox|tee(default)]\n"
+ " confirmation --prompt_text=<PromptText> --extra_data=<hex>\n"
+ " --locale=<locale> [--ui_options=<list_of_ints>]\n"
+ " --cancel_after=<seconds>\n");
exit(1);
}
std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
return std::unique_ptr<KeystoreClient>(
- static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
+ static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
}
void PrintTags(const AuthorizationSet& parameters) {
for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
- printf(" %s\n", stringifyTag(iter->tag));
+ auto tag_str = toString(iter->tag);
+ printf(" %s\n", tag_str.c_str());
}
}
@@ -78,8 +99,9 @@
std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- auto result = keystore->generateKey("tmp", parameters, &hardware_enforced_characteristics,
- &software_enforced_characteristics);
+ auto result =
+ keystore->generateKey("tmp", parameters, 0 /*flags*/, &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
if (!result.isOk()) {
LOG(ERROR) << "Failed to generate key: " << result;
@@ -120,9 +142,7 @@
.Padding(PaddingMode::RSA_PSS)
.Authorization(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(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
}
return parameters;
}
@@ -142,9 +162,7 @@
.Digest(Digest::SHA_2_256)
.Authorization(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(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
}
return parameters;
}
@@ -205,7 +223,8 @@
const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m";
if (test_for_0_3) {
printf("%s: Testing for keymaster v0.3. "
- "This does not meet Brillo requirements.\n", kBoldYellowWarning);
+ "This does not meet Brillo requirements.\n",
+ kBoldYellowWarning);
}
int test_count = 0;
int fail_count = 0;
@@ -259,14 +278,14 @@
}
}
-int AddEntropy(const std::string& input) {
+int AddEntropy(const std::string& input, int32_t flags) {
std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
- int32_t result = keystore->addRandomNumberGeneratorEntropy(input);
+ int32_t result = keystore->addRandomNumberGeneratorEntropy(input, flags);
printf("AddEntropy: %d\n", result);
return result;
}
-int GenerateKey(const std::string& name) {
+int GenerateKey(const std::string& name, int32_t flags) {
std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
AuthorizationSetBuilder params;
params.RsaSigningKey(2048, 65537)
@@ -279,8 +298,8 @@
.Authorization(TAG_NO_AUTH_REQUIRED);
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
- auto result = keystore->generateKey(name, params, &hardware_enforced_characteristics,
- &software_enforced_characteristics);
+ auto result = keystore->generateKey(name, params, flags, &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
printf("GenerateKey: %d\n", int32_t(result));
if (result.isOk()) {
PrintKeyCharacteristics(hardware_enforced_characteristics,
@@ -294,7 +313,7 @@
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
- &software_enforced_characteristics);
+ &software_enforced_characteristics);
printf("GetCharacteristics: %d\n", int32_t(result));
if (result.isOk()) {
PrintKeyCharacteristics(hardware_enforced_characteristics,
@@ -352,8 +371,8 @@
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);
+ auto result =
+ keystore->beginOperation(KeyPurpose::SIGN, name, sign_params, &output_params, &handle);
if (!result.isOk()) {
printf("Sign: BeginOperation failed: %d\n", int32_t(result));
return result;
@@ -377,8 +396,8 @@
// 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->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, &handle);
if (!result.isOk()) {
printf("Verify: BeginOperation failed: %d\n", int32_t(result));
return result;
@@ -404,11 +423,11 @@
}
int Encrypt(const std::string& key_name, const std::string& input_filename,
- const std::string& output_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, &output)) {
+ if (!keystore->encryptWithAuthentication(key_name, input, flags, &output)) {
printf("EncryptWithAuthentication failed.\n");
return 1;
}
@@ -429,6 +448,130 @@
return 0;
}
+uint32_t securityLevelOption2Flags(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 KEYSTORE_FLAG_NONE;
+}
+
+class ConfirmationListener : public android::security::BnConfirmationPromptCallback {
+ public:
+ ConfirmationListener() {}
+
+ virtual ::android::binder::Status
+ onConfirmationPromptCompleted(int32_t result,
+ const ::std::vector<uint8_t>& dataThatWasConfirmed) override {
+ ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(result);
+ printf("Confirmation prompt completed\n"
+ "responseCode = %d\n",
+ responseCode);
+ printf("dataThatWasConfirmed[%zd] = {", dataThatWasConfirmed.size());
+ size_t newLineCountDown = 16;
+ bool hasPrinted = false;
+ for (uint8_t element : dataThatWasConfirmed) {
+ if (hasPrinted) {
+ printf(", ");
+ }
+ if (newLineCountDown == 0) {
+ printf("\n ");
+ newLineCountDown = 32;
+ }
+ printf("0x%02x", element);
+ hasPrinted = true;
+ }
+ printf("}\n");
+ exit(0);
+ }
+};
+
+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 == NULL) {
+ printf("error: could not connect to keystore service.\n");
+ return 1;
+ }
+
+ if (promptText.size() == 0) {
+ printf("The --prompt_text parameter cannot be empty.\n");
+ return 1;
+ }
+
+ std::vector<uint8_t> extraData;
+ if (!base::HexStringToBytes(extraDataHex, &extraData)) {
+ printf("The --extra_data parameter does not appear to be valid hexadecimal.\n");
+ return 1;
+ }
+
+ std::vector<std::string> pieces =
+ base::SplitString(uiOptionsStr, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ int uiOptionsAsFlags = 0;
+ for (auto& p : pieces) {
+ int value;
+ if (!base::StringToInt(p, &value)) {
+ printf("Error parsing %s in --ui_options parameter as a number.\n", p.c_str());
+ return 1;
+ }
+ uiOptionsAsFlags |= (1 << value);
+ }
+
+ double cancelAfterValue = 0.0;
+
+ if (cancelAfter.size() > 0 && !base::StringToDouble(cancelAfter, &cancelAfterValue)) {
+ printf("Error parsing %s in --cancel_after parameter as a double.\n", cancelAfter.c_str());
+ return 1;
+ }
+
+ String16 promptText16(promptText.data(), promptText.size());
+ String16 locale16(locale.data(), locale.size());
+
+ sp<ConfirmationListener> listener = new ConfirmationListener();
+
+ 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);
+ return 1;
+ }
+
+ if (cancelAfterValue > 0.0) {
+ printf("Sleeping %.1f seconds before canceling prompt...\n", cancelAfterValue);
+ base::PlatformThread::Sleep(base::TimeDelta::FromSecondsD(cancelAfterValue));
+ 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::OK) {
+ printf("Canceling confirmation prompt failed with response code %d.\n", responseCode);
+ return 1;
+ }
+ }
+
+ printf("Waiting for prompt to complete - use Ctrl+C to abort...\n");
+ // Use the main thread to process Binder transactions.
+ android::IPCThreadState::self()->joinThreadPool();
+ return 0;
+}
+
} // namespace
int main(int argc, char** argv) {
@@ -444,9 +587,11 @@
} else if (args[0] == "list-brillo-tests") {
return ListTestCases();
} else if (args[0] == "add-entropy") {
- return AddEntropy(command_line->GetSwitchValueASCII("input"));
+ return AddEntropy(command_line->GetSwitchValueASCII("input"),
+ securityLevelOption2Flags(*command_line));
} else if (args[0] == "generate") {
- return GenerateKey(command_line->GetSwitchValueASCII("name"));
+ return GenerateKey(command_line->GetSwitchValueASCII("name"),
+ securityLevelOption2Flags(*command_line));
} else if (args[0] == "get-chars") {
return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
} else if (args[0] == "export") {
@@ -462,13 +607,19 @@
} 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"));
+ return Encrypt(
+ command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"),
+ command_line->GetSwitchValueASCII("out"), securityLevelOption2Flags(*command_line));
} else if (args[0] == "decrypt") {
return Decrypt(command_line->GetSwitchValueASCII("name"),
command_line->GetSwitchValueASCII("in"),
command_line->GetSwitchValueASCII("out"));
+ } else if (args[0] == "confirmation") {
+ return Confirmation(command_line->GetSwitchValueNative("prompt_text"),
+ command_line->GetSwitchValueASCII("extra_data"),
+ command_line->GetSwitchValueASCII("locale"),
+ command_line->GetSwitchValueASCII("ui_options"),
+ command_line->GetSwitchValueASCII("cancel_after"));
} else {
PrintUsageAndExit();
}
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
index f9df134..994e3f2 100644
--- a/keystore/keystore_client_impl.cpp
+++ b/keystore/keystore_client_impl.cpp
@@ -19,25 +19,19 @@
#include <string>
#include <vector>
+#include <android/security/IKeystoreService.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <binder/IServiceManager.h>
-#include <keystore/IKeystoreService.h>
#include <keystore/keystore.h>
#include <log/log.h>
#include <utils/String16.h>
#include <utils/String8.h>
-#include "keystore_client.pb.h"
-#include <keystore/authorization_set.h>
+#include <keystore/keymaster_types.h>
#include <keystore/keystore_hidl_support.h>
-using android::ExportResult;
-using keystore::KeyCharacteristics;
-using android::OperationResult;
-using android::String16;
-using keystore::AuthorizationSet;
-using keystore::AuthorizationSetBuilder;
+#include "keystore_client.pb.h"
namespace {
@@ -49,6 +43,13 @@
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 keystore::AuthorizationSet;
+using keystore::AuthorizationSetBuilder;
+using keystore::KeyCharacteristics;
+using keystore::KeyStoreServiceReturnCode;
} // namespace
namespace keystore {
@@ -56,22 +57,22 @@
KeystoreClientImpl::KeystoreClientImpl() {
service_manager_ = android::defaultServiceManager();
keystore_binder_ = service_manager_->getService(String16("android.security.keystore"));
- keystore_ = android::interface_cast<android::IKeystoreService>(keystore_binder_);
+ keystore_ = android::interface_cast<android::security::IKeystoreService>(keystore_binder_);
}
bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name,
- const std::string& data,
+ 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)) {
+ if (!createOrVerifyEncryptionKey(encryption_key_name, flags)) {
return false;
}
std::string authentication_key_name = key_name + kAuthenticateSuffix;
- if (!createOrVerifyAuthenticationKey(authentication_key_name)) {
+ if (!createOrVerifyAuthenticationKey(authentication_key_name, flags)) {
return false;
}
AuthorizationSetBuilder encrypt_params;
@@ -86,7 +87,7 @@
return false;
}
auto init_vector_blob = output_params.GetTagValue(TAG_NONCE);
- if (!init_vector_blob.isOk()){
+ if (!init_vector_blob.isOk()) {
ALOGE("Encrypt: Missing initialization vector.");
return false;
}
@@ -154,8 +155,7 @@
AuthorizationSet* output_parameters,
std::string* output_data) {
uint64_t handle;
- auto result =
- beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
+ auto result = beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
if (!result.isOk()) {
ALOGE("BeginOperation failed: %d", int32_t(result));
return false;
@@ -178,26 +178,32 @@
return true;
}
-KeyStoreNativeReturnCode KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
- return keystore_->addRngEntropy(blob2hidlVec(entropy));
+KeyStoreNativeReturnCode
+KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy, int32_t flags) {
+ int32_t result;
+ auto binder_result = keystore_->addRngEntropy(blob2hidlVec(entropy), flags, &result);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+ return KeyStoreNativeReturnCode(result);
}
-KeyStoreNativeReturnCode KeystoreClientImpl::generateKey(const std::string& key_name,
- const AuthorizationSet& key_parameters,
- AuthorizationSet* hardware_enforced_characteristics,
- AuthorizationSet* software_enforced_characteristics) {
+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());
- KeyCharacteristics characteristics;
- auto result =
- keystore_->generateKey(key_name16, key_parameters.hidl_data(), hidl_vec<uint8_t>(),
- kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+ ::android::security::keymaster::KeyCharacteristics characteristics;
+ int32_t result;
+ auto binder_result = keystore_->generateKey(
+ key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()),
+ hidl_vec<uint8_t>() /* entropy */, kDefaultUID, flags, &characteristics, &result);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
/* 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.teeEnforced;
- *software_enforced_characteristics = characteristics.softwareEnforced;
- return result;
+ *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
+ *software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
+ return KeyStoreNativeReturnCode(result);
}
KeyStoreNativeReturnCode
@@ -205,66 +211,80 @@
AuthorizationSet* hardware_enforced_characteristics,
AuthorizationSet* software_enforced_characteristics) {
String16 key_name16(key_name.data(), key_name.size());
- KeyCharacteristics characteristics;
- auto result = keystore_->getKeyCharacteristics(key_name16, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
- kDefaultUID, &characteristics);
+ ::android::security::keymaster::KeyCharacteristics characteristics;
+ int32_t result;
+ auto binder_result = keystore_->getKeyCharacteristics(
+ key_name16, android::security::keymaster::KeymasterBlob(),
+ android::security::keymaster::KeymasterBlob(), kDefaultUID, &characteristics, &result);
/* 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.teeEnforced;
- *software_enforced_characteristics = characteristics.softwareEnforced;
- return result;
+ *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
+ *software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
+ return KeyStoreNativeReturnCode(result);
}
-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) {
+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);
- KeyCharacteristics characteristics;
- auto result = keystore_->importKey(key_name16, key_parameters.hidl_data(), key_format,
- hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
-
+ ::android::security::keymaster::KeyCharacteristics characteristics;
+ int32_t result;
+ auto binder_result = keystore_->importKey(
+ key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()),
+ (int)key_format, hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics, &result);
/* 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.teeEnforced;
- *software_enforced_characteristics = characteristics.softwareEnforced;
- return result;
+ *hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
+ *software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
+ return KeyStoreNativeReturnCode(result);
}
KeyStoreNativeReturnCode KeystoreClientImpl::exportKey(KeyFormat export_format,
- const std::string& key_name, std::string* export_data) {
+ const std::string& key_name,
+ std::string* export_data) {
String16 key_name16(key_name.data(), key_name.size());
ExportResult export_result;
- keystore_->exportKey(key_name16, export_format, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
- kDefaultUID, &export_result);
+ auto binder_result = keystore_->exportKey(
+ key_name16, (int)export_format, android::security::keymaster::KeymasterBlob(),
+ android::security::keymaster::KeymasterBlob(), kDefaultUID, &export_result);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
*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());
- return keystore_->del(key_name16, kDefaultUID);
+ 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() {
- return keystore_->clear_uid(kDefaultUID);
+ 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) {
+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());
OperationResult result;
- keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_parameters.hidl_data(),
- hidl_vec<uint8_t>(), kDefaultUID, &result);
+ auto binder_result = keystore_->begin(
+ token, key_name16, (int)purpose, true /*pruneable*/,
+ android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
+ hidl_vec<uint8_t>() /* entropy */, kDefaultUID, &result);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
if (result.resultCode.isOk()) {
*handle = getNextVirtualHandle();
active_operations_[*handle] = result.token;
@@ -275,19 +295,20 @@
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) {
+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;
}
OperationResult result;
auto hidlInputData = blob2hidlVec(input_data);
- keystore_->update(active_operations_[handle], input_parameters.hidl_data(), hidlInputData,
- &result);
+ auto binder_result = keystore_->update(
+ active_operations_[handle],
+ android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
+ hidlInputData, &result);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
if (result.resultCode.isOk()) {
*num_input_bytes_consumed = result.inputConsumed;
@@ -300,19 +321,20 @@
return result.resultCode;
}
-KeyStoreNativeReturnCode KeystoreClientImpl::finishOperation(uint64_t handle,
- const AuthorizationSet& input_parameters,
- const std::string& signature_to_verify,
- AuthorizationSet* output_parameters,
- std::string* output_data) {
+KeyStoreNativeReturnCode
+KeystoreClientImpl::finishOperation(uint64_t handle, const AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ AuthorizationSet* output_parameters, std::string* output_data) {
if (active_operations_.count(handle) == 0) {
return ErrorCode::INVALID_OPERATION_HANDLE;
}
OperationResult result;
auto hidlSignature = blob2hidlVec(signature_to_verify);
- keystore_->finish(active_operations_[handle], input_parameters.hidl_data(),
- hidlSignature,
- hidl_vec<uint8_t>(), &result);
+ auto binder_result = keystore_->finish(
+ active_operations_[handle],
+ android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
+ (std::vector<uint8_t>)hidlSignature, hidl_vec<uint8_t>(), &result);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
if (result.resultCode.isOk()) {
if (result.outParams.size()) {
@@ -329,39 +351,43 @@
if (active_operations_.count(handle) == 0) {
return ErrorCode::INVALID_OPERATION_HANDLE;
}
- auto error_code = keystore_->abort(active_operations_[handle]);
- if (error_code.isOk()) {
+ int32_t result;
+ // Current implementation does not return exceptions in android::binder::Status
+ auto binder_result = keystore_->abort(active_operations_[handle], &result);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+ if (KeyStoreNativeReturnCode(result).isOk()) {
active_operations_.erase(handle);
}
- return error_code;
+ return KeyStoreNativeReturnCode(result);
}
bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) {
String16 key_name16(key_name.data(), key_name.size());
- auto error_code = keystore_->exist(key_name16, kDefaultUID);
- return error_code.isOk();
+ 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) {
String16 prefix16(prefix.data(), prefix.size());
- android::Vector<String16> matches;
- auto error_code = keystore_->list(prefix16, kDefaultUID, &matches);
- if (error_code.isOk()) {
- 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::vector<::android::String16> matches;
+ auto binder_result = keystore_->list(prefix16, kDefaultUID, &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 false;
+ return true;
}
uint64_t KeystoreClientImpl::getNextVirtualHandle() {
return next_virtual_handle_++;
}
-bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name) {
+bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name, int32_t flags) {
bool key_exists = doesKeyExist(key_name);
if (key_exists) {
bool verified = false;
@@ -386,7 +412,7 @@
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
auto result =
- generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
+ generateKey(key_name, key_parameters, flags, &hardware_enforced_characteristics,
&software_enforced_characteristics);
if (!result.isOk()) {
ALOGE("Failed to generate encryption key: %d", int32_t(result));
@@ -399,7 +425,8 @@
return true;
}
-bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name) {
+bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name,
+ int32_t flags) {
bool key_exists = doesKeyExist(key_name);
if (key_exists) {
bool verified = false;
@@ -424,7 +451,7 @@
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
auto result =
- generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
+ generateKey(key_name, key_parameters, flags, &hardware_enforced_characteristics,
&software_enforced_characteristics);
if (!result.isOk()) {
ALOGE("Failed to generate authentication key: %d", int32_t(result));
@@ -442,32 +469,32 @@
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
- &software_enforced_characteristics);
+ &software_enforced_characteristics);
if (!result.isOk()) {
ALOGE("Failed to query encryption key: %d", int32_t(result));
return false;
}
*verified = true;
auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
- software_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));
+ 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));
+ 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));
+ 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;
@@ -483,32 +510,32 @@
AuthorizationSet hardware_enforced_characteristics;
AuthorizationSet software_enforced_characteristics;
auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
- &software_enforced_characteristics);
+ &software_enforced_characteristics);
if (!result.isOk()) {
ALOGE("Failed to query authentication key: %d", int32_t(result));
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){
+ 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));
+ 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));
+ 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));
+ 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;
diff --git a/keystore/keystore_get.cpp b/keystore/keystore_get.cpp
index 8fb7f80..cf67fa4 100644
--- a/keystore/keystore_get.cpp
+++ b/keystore/keystore_get.cpp
@@ -14,24 +14,26 @@
* limitations under the License.
*/
-#include <keystore/IKeystoreService.h>
+#include <android/security/IKeystoreService.h>
#include <binder/IServiceManager.h>
#include <keystore/keystore_get.h>
+#include <vector>
using namespace android;
using namespace keystore;
-ssize_t keystore_get(const char *key, size_t keyLength, uint8_t** value) {
+ssize_t keystore_get(const char* key, size_t keyLength, uint8_t** value) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
- sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+ sp<android::security::IKeystoreService> service =
+ interface_cast<android::security::IKeystoreService>(binder);
if (service == NULL) {
return -1;
}
- hidl_vec<uint8_t> result;
+ ::std::vector<uint8_t> result;
auto ret = service->get(String16(key, keyLength), -1, &result);
if (!ret.isOk()) return -1;
@@ -41,5 +43,4 @@
memcpy(*value, &result[0], result.size());
}
return result.size();
-
}
diff --git a/keystore/keystore_keymaster_enforcement.h b/keystore/keystore_keymaster_enforcement.h
index 0389201..e114ea9 100644
--- a/keystore/keystore_keymaster_enforcement.h
+++ b/keystore/keystore_keymaster_enforcement.h
@@ -73,17 +73,30 @@
return now_date > expiration_date;
}
- bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const {
+ bool auth_token_timed_out(const HardwareAuthToken&, uint32_t) const {
// Assume the token has not timed out, because AuthTokenTable would not have returned it if
// the timeout were past. Secure hardware will also check timeouts if it supports them.
return false;
}
- bool ValidateTokenSignature(const hw_auth_token_t&) const override {
+ bool ValidateTokenSignature(const HardwareAuthToken&) const override {
// Non-secure world cannot validate token signatures because it doesn't have access to the
// signing key. Assume the token is good.
return true;
}
+
+ bool is_device_locked(int32_t userId) const override {
+ // If we haven't had a set call for this user yet, assume the device is locked.
+ if (mIsDeviceLockedForUser.count(userId) == 0) return true;
+ return mIsDeviceLockedForUser.find(userId)->second;
+ }
+
+ void set_device_locked(bool isLocked, int32_t userId) {
+ mIsDeviceLockedForUser[userId] = isLocked;
+ }
+
+ private:
+ std::map<int32_t, bool> mIsDeviceLockedForUser;
};
} // namespace keystore
diff --git a/keystore/keystore_main.cpp b/keystore/keystore_main.cpp
index a739c5e..52e83c8 100644
--- a/keystore/keystore_main.cpp
+++ b/keystore/keystore_main.cpp
@@ -14,25 +14,27 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
#define LOG_TAG "keystore"
+#include <android-base/logging.h>
+#include <android/hidl/manager/1.1/IServiceManager.h>
+#include <android/security/IKeystoreService.h>
+#include <android/system/wifi/keystore/1.0/IKeystore.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
-
-#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
-#include <android/system/wifi/keystore/1.0/IKeystore.h>
+#include <hidl/HidlTransportSupport.h>
+#include <keymasterV4_0/Keymaster3.h>
+#include <keymasterV4_0/Keymaster4.h>
+#include <utils/StrongPointer.h>
#include <wifikeystorehal/keystore.h>
-#include <cutils/log.h>
+#include <keystore/keystore_hidl_support.h>
+#include <keystore/keystore_return_types.h>
-#include "entropy.h"
+#include "KeyStore.h"
#include "key_store_service.h"
-#include "keystore.h"
-#include "permissions.h"
#include "legacy_keymaster_device_wrapper.h"
-#include "include/keystore/keystore_hidl_support.h"
-#include "include/keystore/keystore_return_types.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
@@ -40,68 +42,121 @@
* 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::configureRpcThreadpool;
using ::android::system::wifi::keystore::V1_0::IKeystore;
using ::android::system::wifi::keystore::V1_0::implementation::Keystore;
-using ::android::hardware::configureRpcThreadpool;
+using ::android::hidl::manager::V1_1::IServiceManager;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::keymaster::V4_0::SecurityLevel;
+using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
+using ::android::hardware::keymaster::V4_0::ErrorCode;
-/**
- * TODO implement keystore daemon using binderized keymaster HAL.
- */
+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->listByInterface(
+ 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 = android::hidl::manager::V1_1::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;
- if (argc < 2) {
- ALOGE("A directory must be specified!");
- return 1;
- }
- if (chdir(argv[1]) == -1) {
- ALOGE("chdir: %s: %s", argv[1], strerror(errno));
- return 1;
- }
+ CHECK(argc >= 2) << "A directory must be specified!";
+ CHECK(chdir(argv[1]) != -1) << "chdir: " << argv[1] << ": " << strerror(errno);
- Entropy entropy;
- if (!entropy.open()) {
- return 1;
- }
+ auto kmDevices = initializeKeymasters();
- auto dev = android::hardware::keymaster::V3_0::IKeymasterDevice::getService();
- if (dev.get() == nullptr) {
- return -1;
- }
- auto fallback = android::keystore::makeSoftwareKeymasterDevice();
- if (dev.get() == nullptr) {
- return -1;
- }
+ CHECK(kmDevices[SecurityLevel::SOFTWARE]) << "Missing software Keymaster device";
+ CHECK(kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT])
+ << "Error no viable keymaster device found";
- if (configure_selinux() == -1) {
- return -1;
- }
+ CHECK(configure_selinux() != -1) << "Failed to configure SELinux.";
- bool allowNewFallbackDevice = false;
+ auto halVersion = kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]->halVersion();
- keystore::KeyStoreServiceReturnCode rc;
- rc = KS_HANDLE_HIDL_ERROR(dev->getHardwareFeatures(
- [&] (bool, bool, bool, bool supportsAttestation, bool, const hidl_string&,
- const hidl_string&) {
- // Attestation support indicates the hardware is keymaster 2.0 or higher.
- // For these devices 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.
- allowNewFallbackDevice = !supportsAttestation;
- }));
+ // 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;
- if (!rc.isOk()) {
- return -1;
- }
-
- KeyStore keyStore(&entropy, dev, fallback, allowNewFallbackDevice);
+ keystore::KeyStore keyStore(kmDevices, minimalAllowedSecurityLevelForNewKeys);
keyStore.initialize();
android::sp<android::IServiceManager> sm = android::defaultServiceManager();
android::sp<keystore::KeyStoreService> service = new keystore::KeyStoreService(&keyStore);
android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
- if (ret != android::OK) {
- ALOGE("Couldn't register binder service!");
- return -1;
- }
+ CHECK(ret == android::OK) << "Couldn't register binder service!";
/**
* Register the wifi keystore HAL service to run in passthrough mode.
@@ -111,9 +166,7 @@
configureRpcThreadpool(1, false /* callerWillJoin */);
android::sp<IKeystore> wifiKeystoreHalService = new Keystore();
android::status_t err = wifiKeystoreHalService->registerAsService();
- if (ret != android::OK) {
- ALOGE("Cannot register wifi keystore HAL service: %d", err);
- }
+ CHECK(ret == android::OK) << "Cannot register wifi keystore HAL service: " << err;
/*
* This thread is just going to process Binder transactions.
diff --git a/keystore/keystore_tags_utils.cpp b/keystore/keystore_tags_utils.cpp
deleted file mode 100644
index 278348a..0000000
--- a/keystore/keystore_tags_utils.cpp
+++ /dev/null
@@ -1,46 +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/keymaster_tags.h>
-
-namespace keystore {
-
-template<typename TagList>
-struct TagStringifier;
-
-template<typename ... Tags>
-struct TagStringifier<MetaList<Tags...>> {
- template<TagType tag_type, Tag tag>
- static TypedTag<tag_type, tag> chooseString(TypedTag<tag_type, tag> ttag, Tag runtime_tag,
- const char** result) {
- if (tag == runtime_tag) {
- *result = Tag2String<tag>::value();
- }
- return ttag;
- }
- static const char* stringify(Tag tag) {
- const char* result = "unknown tag";
- [] (Tags&&...) {}(chooseString(Tags(), tag, &result)...);
- return result;
- }
-};
-
-const char* stringifyTag(Tag tag) {
- return TagStringifier<all_tags_t>::stringify(tag);
-}
-
-}
diff --git a/keystore/keystore_utils.cpp b/keystore/keystore_utils.cpp
index b1777d0..e5ae29a 100644
--- a/keystore/keystore_utils.cpp
+++ b/keystore/keystore_utils.cpp
@@ -24,10 +24,14 @@
#include <cutils/log.h>
#include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
-#include <keystore/authorization_set.h>
+#include <log/log_event_list.h>
+
+#include <keystore/keymaster_types.h>
#include <keystore/keystore_client.h>
-#include <keystore/IKeystoreService.h>
+
+#include "blob.h"
size_t readFully(int fd, uint8_t* data, size_t size) {
size_t remaining = size;
@@ -80,7 +84,6 @@
params->push_back(TAG_DIGEST, Digest::SHA_2_256);
params->push_back(TAG_DIGEST, Digest::SHA_2_384);
params->push_back(TAG_DIGEST, Digest::SHA_2_512);
- params->push_back(TAG_ALL_USERS);
params->push_back(TAG_NO_AUTH_REQUIRED);
params->push_back(TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX);
params->push_back(TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX);
@@ -94,3 +97,43 @@
uid_t get_user_id(uid_t uid) {
return uid / AID_USER;
}
+
+void log_key_integrity_violation(const char* name, uid_t uid) {
+ if (!__android_log_security()) return;
+ android_log_event_list(SEC_TAG_KEY_INTEGRITY_VIOLATION)
+ << name << int32_t(uid) << LOG_ID_SECURITY;
+}
+
+namespace keystore {
+
+hidl_vec<uint8_t> blob2hidlVec(const Blob& blob) {
+ hidl_vec<uint8_t> result;
+ result.setToExternal(const_cast<uint8_t*>(blob.getValue()), blob.getLength());
+ return result;
+}
+
+SecurityLevel flagsToSecurityLevel(int32_t flags) {
+ switch (flags & (KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX)) {
+ case KEYSTORE_FLAG_FALLBACK:
+ // treating Strongbox flag as "don't care" if Fallback is set
+ case (KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX):
+ return SecurityLevel::SOFTWARE;
+ case KEYSTORE_FLAG_STRONGBOX:
+ return SecurityLevel::STRONGBOX;
+ default:
+ return SecurityLevel::TRUSTED_ENVIRONMENT;
+ }
+}
+
+uint32_t securityLevelToFlags(SecurityLevel secLevel) {
+ switch (secLevel) {
+ case SecurityLevel::SOFTWARE:
+ return KEYSTORE_FLAG_FALLBACK;
+ case SecurityLevel::STRONGBOX:
+ return KEYSTORE_FLAG_STRONGBOX;
+ default:
+ return 0;
+ }
+}
+
+} // namespace keystore
diff --git a/keystore/keystore_utils.h b/keystore/keystore_utils.h
index f970559..3bc9c01 100644
--- a/keystore/keystore_utils.h
+++ b/keystore/keystore_utils.h
@@ -17,20 +17,15 @@
#ifndef KEYSTORE_KEYSTORE_UTILS_H_
#define KEYSTORE_KEYSTORE_UTILS_H_
-#include <stdint.h>
-
+#include <cstdint>
#include <vector>
#include <openssl/evp.h>
#include <openssl/pem.h>
-#include <hardware/keymaster_defs.h>
-
#include <memory>
-#include <keystore/authorization_set.h>
-
-#include "blob.h"
+#include <keystore/keymaster_types.h>
size_t readFully(int fd, uint8_t* data, size_t size);
size_t writeFully(int fd, uint8_t* data, size_t size);
@@ -59,14 +54,24 @@
};
typedef std::unique_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+class Blob;
+
+// Tags for audit logging. Be careful and don't log sensitive data.
+// Should be in sync with frameworks/base/core/java/android/app/admin/SecurityLogTags.logtags
+constexpr int SEC_TAG_KEY_DESTROYED = 210026;
+constexpr int SEC_TAG_KEY_INTEGRITY_VIOLATION = 210032;
+constexpr int SEC_TAG_AUTH_KEY_GENERATED = 210024;
+constexpr int SEC_TAG_KEY_IMPORTED = 210025;
+
+void log_key_integrity_violation(const char* name, uid_t uid);
+
namespace keystore {
-inline static hidl_vec<uint8_t> blob2hidlVec(const Blob& blob) {
- hidl_vec<uint8_t> result;
- result.setToExternal(const_cast<uint8_t*>(blob.getValue()), blob.getLength());
- return result;
-}
+hidl_vec<uint8_t> blob2hidlVec(const Blob& blob);
-} // namespace keystore
+SecurityLevel flagsToSecurityLevel(int32_t flags);
+uint32_t securityLevelToFlags(SecurityLevel secLevel);
+
+} // namespace keystore
#endif // KEYSTORE_KEYSTORE_UTILS_H_
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index 8c39716..4069060 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -20,47 +20,29 @@
#include <algorithm>
namespace keystore {
-using namespace android;
OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
: mDeathRecipient(deathRecipient) {}
sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
- const OperationMap::km_device_t& dev,
- const sp<IBinder>& appToken,
- KeyCharacteristics&& characteristics, bool pruneable) {
- sp<IBinder> token = new BBinder();
- mMap[token] = Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken);
- if (pruneable) {
- mLru.push_back(token);
- }
- if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) {
- appToken->linkToDeath(mDeathRecipient);
- }
+ 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, 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;
}
-bool OperationMap::getOperation(const sp<IBinder>& token, uint64_t* outHandle, uint64_t* outKeyid,
- KeyPurpose* outPurpose, km_device_t* outDevice,
- const KeyCharacteristics** outCharacteristics) {
- if (!outHandle || !outDevice) {
- return false;
- }
+NullOr<const Operation&> OperationMap::getOperation(const sp<IBinder>& token) {
auto entry = mMap.find(token);
- if (entry == mMap.end()) {
- return false;
- }
- updateLru(token);
+ if (entry == mMap.end()) return {};
- *outHandle = entry->second.handle;
- *outKeyid = entry->second.keyid;
- *outPurpose = entry->second.purpose;
- *outDevice = entry->second.device;
- if (outCharacteristics) {
- *outCharacteristics = &entry->second.characteristics;
- }
- return true;
+ updateLru(token);
+ return entry->second;
}
void OperationMap::updateLru(const sp<IBinder>& token) {
@@ -71,19 +53,18 @@
}
}
-bool OperationMap::removeOperation(const sp<IBinder>& token) {
+NullOr<Operation> OperationMap::removeOperation(const sp<IBinder>& token, bool wasSuccessful) {
auto entry = mMap.find(token);
- if (entry == mMap.end()) {
- return false;
- }
- sp<IBinder> appToken = entry->second.appToken;
+ if (entry == mMap.end()) return {};
+
+ Operation op = std::move(entry->second);
+ uploadOpAsProto(op, wasSuccessful);
mMap.erase(entry);
+
auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
- if (lruEntry != mLru.end()) {
- mLru.erase(lruEntry);
- }
- removeOperationTracking(token, appToken);
- return true;
+ if (lruEntry != mLru.end()) mLru.erase(lruEntry);
+ removeOperationTracking(token, op.appToken);
+ return op;
}
void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken) {
@@ -102,7 +83,7 @@
}
bool OperationMap::hasPruneableOperation() const {
- return mLru.size() != 0;
+ return !mLru.empty();
}
size_t OperationMap::getPruneableOperationCount() const {
@@ -110,49 +91,29 @@
}
sp<IBinder> OperationMap::getOldestPruneableOperation() {
- if (!hasPruneableOperation()) {
- return sp<IBinder>(NULL);
- }
- return mLru[0];
+ if (!hasPruneableOperation()) return sp<IBinder>(nullptr);
+ return mLru.front();
}
-bool OperationMap::getOperationAuthToken(const sp<IBinder>& token,
- const HardwareAuthToken** outToken) {
+void OperationMap::setOperationAuthToken(const sp<IBinder>& token, HardwareAuthToken authToken) {
auto entry = mMap.find(token);
- if (entry == mMap.end()) {
- return false;
- }
- *outToken = entry->second.authToken.get();
- return true;
+ if (entry == mMap.end()) return;
+
+ entry->second.authToken = std::move(authToken);
}
-bool OperationMap::setOperationAuthToken(const sp<IBinder>& token,
- const HardwareAuthToken* authToken) {
+void OperationMap::setOperationVerificationToken(const sp<IBinder>& token,
+ VerificationToken verificationToken) {
auto entry = mMap.find(token);
- if (entry == mMap.end()) {
- return false;
- }
- entry->second.authToken.reset(new HardwareAuthToken);
- *entry->second.authToken = *authToken;
- return true;
+ if (entry == mMap.end()) return;
+
+ entry->second.verificationToken = std::move(verificationToken);
}
std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& appToken) {
auto appEntry = mAppTokenMap.find(appToken);
- if (appEntry != mAppTokenMap.end()) {
- return appEntry->second;
- } else {
- return std::vector<sp<IBinder>>();
- }
+ if (appEntry == mAppTokenMap.end()) return {};
+ return appEntry->second;
}
-OperationMap::Operation::Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_,
- const OperationMap::km_device_t& device_,
- KeyCharacteristics&& characteristics_, sp<IBinder> appToken_)
- : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
- characteristics(characteristics_), appToken(appToken_) {}
-
-OperationMap::Operation::Operation()
- : handle(0), keyid(0), device(nullptr), characteristics(), appToken(nullptr) {}
-
-} // namespace android
+} // namespace keystore
diff --git a/keystore/operation.h b/keystore/operation.h
index e69b43a..4888bfa 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -17,18 +17,25 @@
#ifndef KEYSTORE_OPERATION_H_
#define KEYSTORE_OPERATION_H_
+#include <map>
+#include <vector>
+
#include <binder/Binder.h>
#include <binder/IBinder.h>
-#include <keystore/keymaster_tags.h>
-#include <map>
-#include <utils/LruCache.h>
+#include <keymasterV4_0/Keymaster.h>
#include <utils/StrongPointer.h>
-#include <vector>
+
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_hidl_support.h>
+
+#include "operation_proto_handler.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
@@ -38,51 +45,29 @@
*/
class OperationMap {
- typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
-
public:
explicit OperationMap(IBinder::DeathRecipient* deathRecipient);
- android::sp<android::IBinder> addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
- const km_device_t& dev,
- const android::sp<android::IBinder>& appToken,
- KeyCharacteristics&& characteristics,
- bool pruneable);
- bool getOperation(const android::sp<android::IBinder>& token, uint64_t* outHandle,
- uint64_t* outKeyid, KeyPurpose* outPurpose, km_device_t* outDev,
- const KeyCharacteristics** outCharacteristics);
- bool removeOperation(const android::sp<android::IBinder>& token);
+ 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);
+ NullOr<const Operation&> getOperation(const sp<IBinder>& token);
+ NullOr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful);
bool hasPruneableOperation() const;
size_t getOperationCount() const { return mMap.size(); }
size_t getPruneableOperationCount() const;
- bool getOperationAuthToken(const android::sp<android::IBinder>& token,
- const HardwareAuthToken** outToken);
- bool setOperationAuthToken(const android::sp<android::IBinder>& token,
- const HardwareAuthToken* authToken);
- android::sp<android::IBinder> getOldestPruneableOperation();
- std::vector<android::sp<android::IBinder>>
- getOperationsForToken(const android::sp<android::IBinder>& appToken);
+ void setOperationAuthToken(const sp<IBinder>& token, HardwareAuthToken authToken);
+ void setOperationVerificationToken(const sp<IBinder>& token, VerificationToken authToken);
+ sp<IBinder> getOldestPruneableOperation();
+ std::vector<sp<IBinder>> getOperationsForToken(const sp<IBinder>& appToken);
private:
- void updateLru(const android::sp<android::IBinder>& token);
- void removeOperationTracking(const android::sp<android::IBinder>& token,
- const android::sp<android::IBinder>& appToken);
- struct Operation {
- Operation();
- Operation(uint64_t handle, uint64_t keyid, KeyPurpose purpose, const km_device_t& device,
- KeyCharacteristics&& characteristics, android::sp<android::IBinder> appToken);
- uint64_t handle;
- uint64_t keyid;
- KeyPurpose purpose;
- km_device_t device;
- KeyCharacteristics characteristics;
- android::sp<android::IBinder> appToken;
- std::unique_ptr<HardwareAuthToken> authToken;
- };
- std::map<android::sp<android::IBinder>, Operation> mMap;
- std::vector<android::sp<android::IBinder>> mLru;
- std::map<android::sp<android::IBinder>, std::vector<android::sp<android::IBinder>>>
- mAppTokenMap;
- android::IBinder::DeathRecipient* mDeathRecipient;
+ void updateLru(const sp<IBinder>& token);
+ void removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken);
+ std::map<sp<IBinder>, Operation> mMap;
+ std::vector<sp<IBinder>> mLru;
+ std::map<sp<IBinder>, std::vector<sp<IBinder>>> mAppTokenMap;
+ IBinder::DeathRecipient* mDeathRecipient;
};
} // namespace keystore
diff --git a/keystore/operation_config.proto b/keystore/operation_config.proto
new file mode 100644
index 0000000..37b4cbb
--- /dev/null
+++ b/keystore/operation_config.proto
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package keystore;
+
+option optimize_for = LITE_RUNTIME;
+
+message OperationConfig {
+ // What type of encryption algorithm is the key being used in the op for.
+ optional string algorithm = 1;
+
+ // Size of the key being used in this op
+ optional int32 key_size = 2;
+
+ // Log whether the key in this op was generated, imported,
+ // securely imported, or derived.
+ optional string origin = 3;
+
+ // What auth types does this op require? If none, then no auth required.
+ optional string user_auth_type = 4;
+
+ // If user authentication is required, is the requirement time based? If it
+ // is not time based then this field will not be used and the key is per
+ // operation. Per operation keys must be user authenticated on each usage.
+ optional int32 user_auth_key_timeout = 5;
+
+ // Track which padding mode was used for this operation.
+ optional string padding = 6;
+
+ // Keep track of the digest algorithm being used.
+ optional string digest = 7;
+
+ // Check what block mode is being used depending on the mode of encryption
+ optional string block_mode = 8;
+
+ // Did the operation succeed? If it didn't, this represents bugs or
+ // error cases occurring.
+ optional bool was_op_successful = 9;
+
+ // What purpose is this operation serving? Encrypt, decrypt, sign verify?
+ optional string purpose = 10;
+
+ // Which ec curve was selected if elliptic curve cryptography is in use
+ optional string ec_curve = 11;
+
+ // Standalone or is a file system required
+ optional string key_blob_usage_reqs = 12;
+}
diff --git a/keystore/operation_proto_handler.cpp b/keystore/operation_proto_handler.cpp
new file mode 100644
index 0000000..77e1b73
--- /dev/null
+++ b/keystore/operation_proto_handler.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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 "operation_proto_handler.h"
+
+#include <android/os/DropBoxManager.h>
+#include <google/protobuf/message_lite.h>
+#include <keymasterV4_0/Keymaster.h>
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_hidl_support.h>
+#include <utils/String16.h>
+
+#include "operation_config.pb.h"
+
+namespace keystore {
+
+void determinePurpose(KeyPurpose purpose, OperationConfig* operationConfig) {
+ switch (purpose) {
+ case KeyPurpose::VERIFY:
+ operationConfig->set_purpose("verify");
+ break;
+ case KeyPurpose::ENCRYPT:
+ operationConfig->set_purpose("encrypt");
+ break;
+ case KeyPurpose::SIGN:
+ operationConfig->set_purpose("sign");
+ break;
+ case KeyPurpose::DECRYPT:
+ operationConfig->set_purpose("decrypt");
+ break;
+ case KeyPurpose::WRAP_KEY:
+ operationConfig->set_purpose("wrap");
+ break;
+ default:
+ break;
+ }
+}
+
+void checkKeyCharacteristics(const hidl_vec<KeyParameter>& characteristics,
+ OperationConfig* operationConfig) {
+ for (auto& opParam : characteristics) {
+ switch (opParam.tag) {
+ case Tag::ALGORITHM:
+ operationConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, opParam)));
+ break;
+ case Tag::KEY_SIZE:
+ operationConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, opParam));
+ break;
+ case Tag::EC_CURVE:
+ operationConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, opParam)));
+ break;
+ case Tag::AUTH_TIMEOUT:
+ operationConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, opParam));
+ break;
+ case Tag::ORIGIN:
+ operationConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, opParam)));
+ break;
+ case Tag::BLOB_USAGE_REQUIREMENTS:
+ operationConfig->set_key_blob_usage_reqs(
+ toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, opParam)));
+ break;
+ case Tag::USER_AUTH_TYPE:
+ operationConfig->set_user_auth_type(
+ toString(accessTagValue(TAG_USER_AUTH_TYPE, opParam)));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void checkOpCharacteristics(const hidl_vec<KeyParameter>& characteristics,
+ OperationConfig* operationConfig) {
+ for (auto& opParam : characteristics) {
+ switch (opParam.tag) {
+ case Tag::BLOCK_MODE:
+ operationConfig->set_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, opParam)));
+ break;
+ case Tag::PADDING:
+ operationConfig->set_padding(toString(accessTagValue(TAG_PADDING, opParam)));
+ break;
+ case Tag::DIGEST:
+ operationConfig->set_digest(toString(accessTagValue(TAG_DIGEST, opParam)));
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void uploadOpAsProto(Operation& op, bool wasOpSuccessful) {
+ OperationConfig operationConfig;
+ determinePurpose(op.purpose, &operationConfig);
+ checkKeyCharacteristics(op.characteristics.softwareEnforced, &operationConfig);
+ checkKeyCharacteristics(op.characteristics.hardwareEnforced, &operationConfig);
+ checkOpCharacteristics(op.params, &operationConfig);
+ auto dropbox = std::make_unique<android::os::DropBoxManager>();
+ operationConfig.set_was_op_successful(wasOpSuccessful);
+
+ size_t size = operationConfig.ByteSize();
+ auto data = std::make_unique<uint8_t[]>(size);
+ operationConfig.SerializeWithCachedSizesToArray(data.get());
+ dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
+}
+
+} // namespace keystore
diff --git a/keystore/operation_proto_handler.h b/keystore/operation_proto_handler.h
new file mode 100644
index 0000000..bf461b4
--- /dev/null
+++ b/keystore/operation_proto_handler.h
@@ -0,0 +1,31 @@
+/*
+ * 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_PROTO_HANDLER_H_
+#define KEYSTORE_OPERATION_PROTO_HANDLER_H_
+
+#include "operation_struct.h"
+
+namespace keystore {
+
+using ::android::IBinder;
+using keymaster::support::Keymaster;
+
+void uploadOpAsProto(Operation& op, bool wasOpSuccessful);
+
+} // namespace keystore
+
+#endif // KEYSTORE_OPERATION_PROTO_HANDLER_H_
diff --git a/keystore/operation_struct.h b/keystore/operation_struct.h
new file mode 100644
index 0000000..00f1fe2
--- /dev/null
+++ b/keystore/operation_struct.h
@@ -0,0 +1,59 @@
+/*
+ * 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_0/Keymaster.h>
+#include <utils/StrongPointer.h>
+
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_hidl_support.h>
+
+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_), 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;
+ HardwareAuthToken authToken;
+ VerificationToken verificationToken;
+ const hidl_vec<KeyParameter> params;
+};
+
+} // namespace keystore
+
+#endif
diff --git a/keystore/permissions.cpp b/keystore/permissions.cpp
index 1ba91d9..b297c59 100644
--- a/keystore/permissions.cpp
+++ b/keystore/permissions.cpp
@@ -68,7 +68,14 @@
{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>(
diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp
new file mode 100644
index 0000000..c3f5177
--- /dev/null
+++ b/keystore/tests/Android.bp
@@ -0,0 +1,31 @@
+// Unit test for AuthTokenTable
+
+cc_test {
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-O0",
+ ],
+ srcs: [
+ "auth_token_table_test.cpp",
+ "auth_token_formatting_test.cpp",
+ "confirmationui_rate_limiting_test.cpp",
+ "gtest_main.cpp",
+ ],
+ name: "keystore_unit_tests",
+ tags: ["test"],
+ static_libs: [
+ "android.hardware.confirmationui@1.0",
+ "libbase",
+ "libgtest_main",
+ "libhidlbase",
+ "libkeymaster4support",
+ "libkeystore_test",
+ "liblog",
+ ],
+ shared_libs: ["libkeymaster_messages"],
+ sanitize: {
+ cfi: false,
+ }
+}
diff --git a/keystore/tests/Android.mk b/keystore/tests/Android.mk
deleted file mode 100644
index 8126c94..0000000
--- a/keystore/tests/Android.mk
+++ /dev/null
@@ -1,33 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-# Unit test for AuthTokenTable
-include $(CLEAR_VARS)
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_CFLAGS := -Wall -Wextra -Werror
-LOCAL_SRC_FILES := \
- auth_token_table_test.cpp
-LOCAL_MODULE := keystore_unit_tests
-LOCAL_MODULE_TAGS := test
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libgtest_main libkeystore_test liblog
-LOCAL_SHARED_LIBRARIES := libkeymaster_messages
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_NATIVE_TEST)
diff --git a/keystore/tests/auth_token_formatting_test.cpp b/keystore/tests/auth_token_formatting_test.cpp
new file mode 100644
index 0000000..0ecc4cc
--- /dev/null
+++ b/keystore/tests/auth_token_formatting_test.cpp
@@ -0,0 +1,157 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <endian.h>
+#include <hidl/HidlSupport.h>
+#include <keymaster/logger.h>
+#include <keymasterV4_0/keymaster_utils.h>
+
+#include <keystore/keymaster_types.h>
+#include <keystore/keystore_hidl_support.h>
+
+#include "../auth_token_table.h"
+
+using std::vector;
+
+namespace keystore {
+
+using android::hardware::hidl_array;
+using android::hardware::hidl_vec;
+
+namespace test {
+
+namespace {
+
+class StdoutLogger : public ::keymaster::Logger {
+ public:
+ StdoutLogger() { set_instance(this); }
+
+ int log_msg(LogLevel level, const char* fmt, va_list args) const {
+ int output_len = 0;
+ switch (level) {
+ case DEBUG_LVL:
+ output_len = printf("DEBUG: ");
+ break;
+ case INFO_LVL:
+ output_len = printf("INFO: ");
+ break;
+ case WARNING_LVL:
+ output_len = printf("WARNING: ");
+ break;
+ case ERROR_LVL:
+ output_len = printf("ERROR: ");
+ break;
+ case SEVERE_LVL:
+ output_len = printf("SEVERE: ");
+ break;
+ }
+
+ output_len += vprintf(fmt, args);
+ output_len += printf("\n");
+ return output_len;
+ }
+};
+
+StdoutLogger logger;
+
+} // namespace
+
+constexpr const uint8_t test_token[69] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+ 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44};
+
+constexpr const uint8_t test_hmac_data[] = {
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44};
+
+static const Km3HardwareAuthToken km3_hidl_test_token_little_endian = {
+ UINT64_C(0x0807060504030201), UINT64_C(0x100f0e0d0c0b0a09),
+ UINT64_C(0x1817161514131211), UINT32_C(0x1c1b1a19),
+ UINT64_C(0x24232221201f1e1d), hidl_array<uint8_t, 32>(test_hmac_data)};
+
+static const HardwareAuthToken km4_hidl_test_token = {
+ UINT64_C(0x0807060504030201), UINT64_C(0x100f0e0d0c0b0a09),
+ UINT64_C(0x1817161514131211), static_cast<HardwareAuthenticatorType>(UINT32_C(0x191a1b1c)),
+ UINT64_C(0x1d1e1f2021222324), hidl_vec<uint8_t>(test_hmac_data, test_hmac_data + 32)};
+
+TEST(AuthenticationTokenFormattingTest, hidlVec2Km3AuthToken) {
+ static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+ hidl_vec<uint8_t> hidl_test_token;
+ hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+ ASSERT_EQ(km3_hidl_test_token_little_endian, hidlVec2Km3AuthToken(hidl_test_token));
+}
+
+TEST(AuthenticationTokenFormattingTest, hidlVec2Km4AuthToken) {
+ static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+ hidl_vec<uint8_t> hidl_test_token;
+ hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+ ASSERT_EQ(km4_hidl_test_token, hidlVec2AuthToken(hidl_test_token));
+}
+
+TEST(AuthenticationTokenFormattingTest, km3AuthToken2HidlVec) {
+ static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+ hidl_vec<uint8_t> hidl_test_token;
+ hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+ ASSERT_EQ(hidl_test_token, authToken2HidlVec(km3_hidl_test_token_little_endian));
+}
+
+TEST(AuthenticationTokenFormattingTest, km4AuthToken2HidlVec) {
+ static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+ hidl_vec<uint8_t> hidl_test_token;
+ hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+ ASSERT_EQ(hidl_test_token, authToken2HidlVec(km4_hidl_test_token));
+}
+
+TEST(AuthenticationTokenFormattingTest, backAndForth) {
+ static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+ hidl_vec<uint8_t> hidl_test_token;
+ hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+ ASSERT_EQ(km3_hidl_test_token_little_endian,
+ hidlVec2Km3AuthToken(authToken2HidlVec(km3_hidl_test_token_little_endian)));
+ ASSERT_EQ(km4_hidl_test_token, hidlVec2AuthToken(authToken2HidlVec(km4_hidl_test_token)));
+}
+
+TEST(AuthenticationTokenFormattingTest, forthAndBack) {
+ static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+ hidl_vec<uint8_t> hidl_test_token;
+ hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+ ASSERT_EQ(hidl_test_token, authToken2HidlVec(hidlVec2Km3AuthToken(hidl_test_token)));
+ ASSERT_EQ(hidl_test_token, authToken2HidlVec(hidlVec2Km3AuthToken(hidl_test_token)));
+}
+
+TEST(AuthenticationTokenFormattingTest, roundAndRound) {
+ static_assert(sizeof(hw_auth_token_t) == sizeof(test_token), "test_token has wrong size");
+ hidl_vec<uint8_t> hidl_test_token;
+ hidl_test_token.setToExternal(const_cast<unsigned char*>(test_token), sizeof(test_token));
+ HardwareAuthToken km4_from_hidl = hidlVec2AuthToken(hidl_test_token);
+ hidl_vec<uint8_t> hidl_from_km4 = authToken2HidlVec(km4_from_hidl);
+ Km3HardwareAuthToken km3_from_hidl = hidlVec2Km3AuthToken(hidl_from_km4);
+ hidl_vec<uint8_t> hidl_from_km3 = authToken2HidlVec(km3_from_hidl);
+
+ ASSERT_EQ(hidl_from_km4, hidl_test_token);
+ ASSERT_EQ(hidl_from_km3, hidl_test_token);
+ ASSERT_NE(km4_from_hidl.timestamp, km3_from_hidl.timestamp);
+ ASSERT_NE(static_cast<uint32_t>(km4_from_hidl.authenticatorType),
+ km3_from_hidl.authenticatorType);
+}
+
+} // namespace test
+} // namespace keystore
diff --git a/keystore/tests/auth_token_table_test.cpp b/keystore/tests/auth_token_table_test.cpp
index 1b31cf5..511a78d 100644
--- a/keystore/tests/auth_token_table_test.cpp
+++ b/keystore/tests/auth_token_table_test.cpp
@@ -16,21 +16,17 @@
#include <gtest/gtest.h>
-#include <keymaster/android_keymaster_utils.h>
+#include <endian.h>
#include <keymaster/logger.h>
#include "../auth_token_table.h"
using std::vector;
-inline bool operator==(const hw_auth_token_t& a, const hw_auth_token_t& b) {
- return (memcmp(&a, &b, sizeof(a)) == 0);
-}
-
-namespace keymaster {
+namespace keystore {
namespace test {
-class StdoutLogger : public Logger {
+class StdoutLogger : public ::keymaster::Logger {
public:
StdoutLogger() { set_instance(this); }
@@ -66,26 +62,24 @@
AuthTokenTable table;
}
-static hw_auth_token_t* make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0,
- uint64_t timestamp = 0) {
- hw_auth_token_t* token = new hw_auth_token_t;
- token->user_id = rsid;
- token->authenticator_id = ssid;
- token->authenticator_type = hton(static_cast<uint32_t>(HW_AUTH_PASSWORD));
- token->challenge = challenge;
- token->timestamp = hton(timestamp);
+static HardwareAuthToken make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0,
+ uint64_t timestamp = 0) {
+ HardwareAuthToken token;
+ token.userId = rsid;
+ token.authenticatorId = ssid;
+ token.authenticatorType = HardwareAuthenticatorType::PASSWORD;
+ token.challenge = challenge;
+ token.timestamp = timestamp;
return token;
}
static AuthorizationSet make_set(uint64_t rsid, uint32_t timeout = 10000) {
AuthorizationSetBuilder builder;
- builder.Authorization(TAG_USER_ID, 10)
- .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
+ builder.Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
.Authorization(TAG_USER_SECURE_ID, rsid);
// Use timeout == 0 to indicate tags that require auth per operation.
- if (timeout != 0)
- builder.Authorization(TAG_AUTH_TIMEOUT, timeout);
- return builder.build();
+ if (timeout != 0) builder.Authorization(TAG_AUTH_TIMEOUT, timeout);
+ return builder;
}
// Tests obviously run so fast that a real-time clock with a one-second granularity rarely changes
@@ -102,26 +96,30 @@
table.AddAuthenticationToken(make_token(3, 4));
EXPECT_EQ(2U, table.size());
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
- ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(1U, found->user_id);
- EXPECT_EQ(2U, found->authenticator_id);
+ ASSERT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(1U, found->userId);
+ EXPECT_EQ(2U, found->authenticatorId);
- ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(1U, found->user_id);
- EXPECT_EQ(2U, found->authenticator_id);
+ ASSERT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(1U, found->userId);
+ EXPECT_EQ(2U, found->authenticatorId);
- ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(3U, found->user_id);
- EXPECT_EQ(4U, found->authenticator_id);
+ ASSERT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(3U, found->userId);
+ EXPECT_EQ(4U, found->authenticatorId);
- ASSERT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(4), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(3U, found->user_id);
- EXPECT_EQ(4U, found->authenticator_id);
+ ASSERT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(3U, found->userId);
+ EXPECT_EQ(4U, found->authenticatorId);
ASSERT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(5), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
}
TEST(AuthTokenTableTest, FlushTable) {
@@ -131,13 +129,16 @@
table.AddAuthenticationToken(make_token(2));
table.AddAuthenticationToken(make_token(3));
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
// All three should be in the table.
EXPECT_EQ(3U, table.size());
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
table.Clear();
EXPECT_EQ(0U, table.size());
@@ -150,36 +151,45 @@
table.AddAuthenticationToken(make_token(2));
table.AddAuthenticationToken(make_token(3));
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
// All three should be in the table.
EXPECT_EQ(3U, table.size());
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
table.AddAuthenticationToken(make_token(4));
// Oldest should be gone.
EXPECT_EQ(3U, table.size());
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
// Others should be there, including the new one (4). Search for it first, then the others, so
// 4 becomes the least recently used.
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(4), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
table.AddAuthenticationToken(make_token(5));
// 5 should have replaced 4.
EXPECT_EQ(3U, table.size());
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(4), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(5), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
table.AddAuthenticationToken(make_token(6));
table.AddAuthenticationToken(make_token(7));
@@ -187,12 +197,15 @@
// 2 and 5 should be gone
EXPECT_EQ(3U, table.size());
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(5), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(6), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(7), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(6), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(7), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
table.AddAuthenticationToken(make_token(8));
table.AddAuthenticationToken(make_token(9));
@@ -201,75 +214,76 @@
// Only the three most recent should be there.
EXPECT_EQ(3U, table.size());
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(3), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(4), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(5), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(6), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(6), KeyPurpose::SIGN, 0, &found));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(7), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(8), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(9), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(7), KeyPurpose::SIGN, 0, &found));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(10), KM_PURPOSE_SIGN, 0, &found));
+ table.FindAuthorization(make_set(8), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(9), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(10), KeyPurpose::SIGN, 0, &found));
}
TEST(AuthTokenTableTest, AuthenticationNotRequired) {
AuthTokenTable table;
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
EXPECT_EQ(AuthTokenTable::AUTH_NOT_REQUIRED,
- table.FindAuthorization(
- AuthorizationSetBuilder().Authorization(TAG_NO_AUTH_REQUIRED).build(),
- KM_PURPOSE_SIGN, 0 /* no challenge */, &found));
+ table.FindAuthorization(AuthorizationSetBuilder().Authorization(TAG_NO_AUTH_REQUIRED),
+ KeyPurpose::SIGN, 0 /* no challenge */, &found));
}
TEST(AuthTokenTableTest, OperationHandleNotFound) {
AuthTokenTable table;
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
table.AddAuthenticationToken(make_token(1, 0, 1, 5));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
2 /* non-matching challenge */, &found));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
1 /* matching challenge */, &found));
table.MarkCompleted(1);
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
1 /* used challenge */, &found));
}
TEST(AuthTokenTableTest, OperationHandleRequired) {
AuthTokenTable table;
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
table.AddAuthenticationToken(make_token(1));
EXPECT_EQ(AuthTokenTable::OP_HANDLE_REQUIRED,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
0 /* no op handle */, &found));
}
TEST(AuthTokenTableTest, AuthSidChanged) {
AuthTokenTable table;
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
table.AddAuthenticationToken(make_token(1, 3, /* op handle */ 1));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_WRONG_SID,
- table.FindAuthorization(make_set(2, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(2, 0 /* no timeout */), KeyPurpose::SIGN,
1 /* op handle */, &found));
}
TEST(AuthTokenTableTest, TokenExpired) {
AuthTokenTable table(5, monotonic_clock);
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
auto key_info = make_set(1, 5 /* five second timeout */);
@@ -281,17 +295,17 @@
// keymaster when the found token is passed to it.
table.AddAuthenticationToken(make_token(1, 0));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+ table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+ table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+ table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+ table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+ table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_EXPIRED,
- table.FindAuthorization(key_info, KM_PURPOSE_SIGN, 0 /* no op handle */, &found));
+ table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
}
TEST(AuthTokenTableTest, MarkNonexistentEntryCompleted) {
@@ -302,15 +316,16 @@
TEST(AuthTokenTableTest, SupersededEntries) {
AuthTokenTable table;
- const hw_auth_token_t* found;
+ const HardwareAuthToken* found;
// Add two identical tokens, without challenges. The second should supersede the first, based
// on timestamp (fourth arg to make_token).
table.AddAuthenticationToken(make_token(1, 0, 0, 0));
table.AddAuthenticationToken(make_token(1, 0, 0, 1));
EXPECT_EQ(1U, table.size());
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(1U, ntoh(found->timestamp));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(1U, found->timestamp);
// Add a third token, this with a different RSID. It should not be superseded.
table.AddAuthenticationToken(make_token(2, 0, 0, 2));
@@ -320,10 +335,12 @@
table.AddAuthenticationToken(make_token(1, 0, 0, 3));
table.AddAuthenticationToken(make_token(2, 0, 0, 4));
EXPECT_EQ(2U, table.size());
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(3U, ntoh(found->timestamp));
- EXPECT_EQ(AuthTokenTable::OK, table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0, &found));
- EXPECT_EQ(4U, ntoh(found->timestamp));
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(3U, found->timestamp);
+ EXPECT_EQ(AuthTokenTable::OK,
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
+ EXPECT_EQ(4U, found->timestamp);
// Add another, this one with a challenge value. It should supersede the old one since it is
// newer, and matches other than the challenge.
@@ -338,13 +355,13 @@
// Should be able to find each of them, by specifying their challenge, with a key that is not
// timed (timed keys don't care about challenges).
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1, 0 /* no timeout*/), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout*/), KeyPurpose::SIGN,
1 /* challenge */, &found));
- EXPECT_EQ(5U, ntoh(found->timestamp));
+ EXPECT_EQ(5U, found->timestamp);
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
2 /* challenge */, &found));
- EXPECT_EQ(6U, ntoh(found->timestamp));
+ EXPECT_EQ(6U, found->timestamp);
// Add another, without a challenge, and the same timestamp as the last one. This new one
// actually could be considered already-superseded, but the table doesn't handle that case,
@@ -352,31 +369,31 @@
table.AddAuthenticationToken(make_token(1, 0, 0, 6));
EXPECT_EQ(4U, table.size());
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
- EXPECT_EQ(6U, ntoh(found->timestamp));
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+ EXPECT_EQ(6U, found->timestamp);
// Add another without a challenge but an increased timestamp. This should supersede the
// previous challenge-free entry.
table.AddAuthenticationToken(make_token(1, 0, 0, 7));
EXPECT_EQ(4U, table.size());
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
2 /* challenge */, &found));
- EXPECT_EQ(6U, ntoh(found->timestamp));
+ EXPECT_EQ(6U, found->timestamp);
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
- EXPECT_EQ(7U, ntoh(found->timestamp));
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+ EXPECT_EQ(7U, found->timestamp);
// Mark the entry with challenge 2 as complete. Since there's a newer challenge-free entry, the
// challenge entry will be superseded.
table.MarkCompleted(2);
EXPECT_EQ(3U, table.size());
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
2 /* challenge */, &found));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
- EXPECT_EQ(7U, ntoh(found->timestamp));
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+ EXPECT_EQ(7U, found->timestamp);
// Add another SID 1 entry with a challenge. It supersedes the previous SID 1 entry with
// no challenge (timestamp 7), but not the one with challenge 1 (timestamp 5).
@@ -384,19 +401,19 @@
EXPECT_EQ(3U, table.size());
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
1 /* challenge */, &found));
- EXPECT_EQ(5U, ntoh(found->timestamp));
+ EXPECT_EQ(5U, found->timestamp);
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
3 /* challenge */, &found));
- EXPECT_EQ(8U, ntoh(found->timestamp));
+ EXPECT_EQ(8U, found->timestamp);
// SID 2 entry is still there.
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(2), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
- EXPECT_EQ(4U, ntoh(found->timestamp));
+ table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0 /* challenge */, &found));
+ EXPECT_EQ(4U, found->timestamp);
// Mark the entry with challenge 3 as complete. Since the older challenge 1 entry is
// incomplete, nothing is superseded.
@@ -404,25 +421,25 @@
EXPECT_EQ(3U, table.size());
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
1 /* challenge */, &found));
- EXPECT_EQ(5U, ntoh(found->timestamp));
+ EXPECT_EQ(5U, found->timestamp);
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
- EXPECT_EQ(8U, ntoh(found->timestamp));
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+ EXPECT_EQ(8U, found->timestamp);
// Mark the entry with challenge 1 as complete. Since there's a newer one (with challenge 3,
// completed), the challenge 1 entry is superseded and removed.
table.MarkCompleted(1);
EXPECT_EQ(2U, table.size());
EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
- table.FindAuthorization(make_set(1, 0 /* no timeout */), KM_PURPOSE_SIGN,
+ table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
1 /* challenge */, &found));
EXPECT_EQ(AuthTokenTable::OK,
- table.FindAuthorization(make_set(1), KM_PURPOSE_SIGN, 0 /* challenge */, &found));
- EXPECT_EQ(8U, ntoh(found->timestamp));
+ table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
+ EXPECT_EQ(8U, found->timestamp);
}
-} // namespace keymaster
} // namespace test
+} // namespace keystore
diff --git a/keystore/tests/confirmationui_rate_limiting_test.cpp b/keystore/tests/confirmationui_rate_limiting_test.cpp
new file mode 100644
index 0000000..f56b509
--- /dev/null
+++ b/keystore/tests/confirmationui_rate_limiting_test.cpp
@@ -0,0 +1,274 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "../confirmationui_rate_limiting.h"
+#include <keymaster/logger.h>
+
+using std::vector;
+
+namespace keystore {
+
+namespace test {
+
+namespace {
+
+class StdoutLogger : public ::keymaster::Logger {
+ public:
+ StdoutLogger() { set_instance(this); }
+
+ int log_msg(LogLevel level, const char* fmt, va_list args) const {
+ int output_len = 0;
+ switch (level) {
+ case DEBUG_LVL:
+ output_len = printf("DEBUG: ");
+ break;
+ case INFO_LVL:
+ output_len = printf("INFO: ");
+ break;
+ case WARNING_LVL:
+ output_len = printf("WARNING: ");
+ break;
+ case ERROR_LVL:
+ output_len = printf("ERROR: ");
+ break;
+ case SEVERE_LVL:
+ output_len = printf("SEVERE: ");
+ break;
+ }
+
+ output_len += vprintf(fmt, args);
+ output_len += printf("\n");
+ return output_len;
+ }
+};
+
+StdoutLogger logger;
+
+class FakeClock : public std::chrono::steady_clock {
+ private:
+ static time_point sNow;
+
+ public:
+ static void setNow(time_point newNow) { sNow = newNow; }
+ static time_point now() noexcept { return sNow; }
+};
+
+FakeClock::time_point FakeClock::sNow;
+
+} // namespace
+
+/*
+ * Test that there are no residual slots when various apps receive successful confirmations.
+ */
+TEST(ConfirmationUIRateLimitingTest, noPenaltyTest) {
+ auto now = std::chrono::steady_clock::now();
+ RateLimiting<FakeClock> rateLimiting;
+ FakeClock::setNow(now);
+
+ for (int i = 0; i < 10000; ++i) {
+ ASSERT_TRUE(rateLimiting.tryPrompt(rand()));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ ASSERT_EQ(0U, rateLimiting.usedSlots());
+}
+
+TEST(ConfirmationUIRateLimitingTest, policyTest) {
+ using namespace std::chrono_literals;
+ auto now = std::chrono::steady_clock::now();
+ RateLimiting<FakeClock> rateLimiting;
+ FakeClock::setNow(now);
+
+ // first three tries are free
+ for (int i = 0; i < 3; ++i) {
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+ }
+
+ // throw in a couple of successful confirmations by other apps to make sure there
+ // is not cross talk
+ for (int i = 0; i < 10000; ++i) {
+ uid_t id = rand();
+ if (id == 20) continue;
+ ASSERT_TRUE(rateLimiting.tryPrompt(id));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ // the next three tries get a 30s penalty
+ for (int i = 3; i < 6; ++i) {
+ FakeClock::setNow(FakeClock::now() + 29s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+ }
+
+ // throw in a couple of successful confirmations by other apps to make sure there
+ // is not cross talk
+ for (int i = 0; i < 10000; ++i) {
+ uid_t id = rand();
+ if (id == 20) continue;
+ ASSERT_TRUE(rateLimiting.tryPrompt(id));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ // there after the penalty doubles with each cancellation
+ for (int i = 6; i < 17; ++i) {
+ FakeClock::setNow((FakeClock::now() + 60s * (1ULL << (i - 6))) - 1s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+ }
+
+ // throw in a couple of successful confirmations by other apps to make sure there
+ // is not cross talk
+ for (int i = 0; i < 10000; ++i) {
+ uid_t id = rand();
+ if (id == 20) continue;
+ ASSERT_TRUE(rateLimiting.tryPrompt(id));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ ASSERT_EQ(1U, rateLimiting.usedSlots());
+
+ FakeClock::setNow(FakeClock::now() + 24h - 1s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+
+ // after 24h the counter is forgotten
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+
+ // throw in a couple of successful confirmations by other apps to make sure there
+ // is not cross talk
+ for (int i = 0; i < 10000; ++i) {
+ uid_t id = rand();
+ if (id == 20) continue;
+ ASSERT_TRUE(rateLimiting.tryPrompt(id));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ for (int i = 1; i < 3; ++i) {
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+ }
+
+ // throw in a couple of successful confirmations by other apps to make sure there
+ // is not cross talk
+ for (int i = 0; i < 10000; ++i) {
+ uid_t id = rand();
+ if (id == 20) continue;
+ ASSERT_TRUE(rateLimiting.tryPrompt(id));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ for (int i = 3; i < 6; ++i) {
+ FakeClock::setNow(FakeClock::now() + 29s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+ }
+
+ // throw in a couple of successful confirmations by other apps to make sure there
+ // is not cross talk
+ for (int i = 0; i < 10000; ++i) {
+ uid_t id = rand();
+ if (id == 20) continue;
+ ASSERT_TRUE(rateLimiting.tryPrompt(id));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ for (int i = 6; i < 17; ++i) {
+ FakeClock::setNow((FakeClock::now() + 60s * (1ULL << (i - 6))) - 1s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+ }
+
+ // throw in a couple of successful confirmations by other apps to make sure there
+ // is not cross talk
+ for (int i = 0; i < 10000; ++i) {
+ uid_t id = rand();
+ if (id == 20) continue;
+ ASSERT_TRUE(rateLimiting.tryPrompt(id));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ ASSERT_EQ(1U, rateLimiting.usedSlots());
+}
+
+TEST(ConfirmationUIRateLimitingTest, rewindTest) {
+ using namespace std::chrono_literals;
+ auto now = std::chrono::steady_clock::now();
+ RateLimiting<FakeClock> rateLimiting;
+
+ // first three tries are free
+ for (int i = 0; i < 3; ++i) {
+ FakeClock::setNow(now);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+ }
+
+ for (int i = 3; i < 6; ++i) {
+ FakeClock::setNow(FakeClock::now() + 29s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Canceled);
+ }
+
+ FakeClock::setNow(FakeClock::now() + 59s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::Aborted);
+
+ FakeClock::setNow(FakeClock::now() - 1s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::SystemError);
+
+ // throw in a couple of successful confirmations by other apps to make sure there
+ // is not cross talk
+ for (int i = 0; i < 10000; ++i) {
+ uid_t id = rand();
+ if (id == 20) continue;
+ ASSERT_TRUE(rateLimiting.tryPrompt(id));
+ rateLimiting.processResult(ConfirmationResponseCode::OK);
+ }
+
+ FakeClock::setNow(FakeClock::now() - 1s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+ rateLimiting.processResult(ConfirmationResponseCode::UIError);
+
+ FakeClock::setNow(FakeClock::now() - 1s);
+ ASSERT_FALSE(rateLimiting.tryPrompt(20));
+ FakeClock::setNow(FakeClock::now() + 1s);
+ ASSERT_TRUE(rateLimiting.tryPrompt(20));
+
+ ASSERT_EQ(1U, rateLimiting.usedSlots());
+}
+
+} // namespace test
+} // namespace keystore
diff --git a/keystore/user_state.cpp b/keystore/user_state.cpp
index 5f9cd5f..aab6175 100644
--- a/keystore/user_state.cpp
+++ b/keystore/user_state.cpp
@@ -24,7 +24,9 @@
#include <stdlib.h>
#include <sys/stat.h>
+#include <openssl/digest.h>
#include <openssl/evp.h>
+#include <openssl/rand.h>
#include <cutils/log.h>
@@ -66,7 +68,7 @@
}
void UserState::zeroizeMasterKeysInMemory() {
- memset(mMasterKey, 0, sizeof(mMasterKey));
+ memset(mMasterKey.data(), 0, mMasterKey.size());
memset(mSalt, 0, sizeof(mSalt));
}
@@ -76,11 +78,11 @@
return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
}
-ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
- if (!generateMasterKey(entropy)) {
+ResponseCode UserState::initialize(const android::String8& pw) {
+ if (!generateMasterKey()) {
return ResponseCode::SYSTEM_ERROR;
}
- ResponseCode response = writeMasterKey(pw, entropy);
+ ResponseCode response = writeMasterKey(pw);
if (response != ResponseCode::NO_ERROR) {
return response;
}
@@ -95,7 +97,7 @@
if (src->getState() != STATE_NO_ERROR) {
return ResponseCode::SYSTEM_ERROR;
}
- memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
+ mMasterKey = src->mMasterKey;
setupMasterKeys();
return copyMasterKeyFile(src);
}
@@ -130,14 +132,15 @@
return ResponseCode::NO_ERROR;
}
-ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
- uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
- generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
- Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
- return masterKeyBlob.writeBlob(mMasterKeyFile, passwordKey, STATE_NO_ERROR, entropy);
+ResponseCode UserState::writeMasterKey(const android::String8& pw) {
+ std::vector<uint8_t> passwordKey(MASTER_KEY_SIZE_BYTES);
+ generateKeyFromPassword(passwordKey, pw, mSalt);
+ Blob masterKeyBlob(mMasterKey.data(), mMasterKey.size(), mSalt, sizeof(mSalt),
+ TYPE_MASTER_KEY_AES256);
+ return masterKeyBlob.writeBlob(mMasterKeyFile, passwordKey, STATE_NO_ERROR);
}
-ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
+ResponseCode UserState::readMasterKey(const android::String8& pw) {
int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
if (in < 0) {
return ResponseCode::SYSTEM_ERROR;
@@ -157,23 +160,33 @@
} else {
salt = NULL;
}
- uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
- generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
+
+ size_t masterKeySize = MASTER_KEY_SIZE_BYTES;
+ if (rawBlob.type == TYPE_MASTER_KEY) {
+ masterKeySize = SHA1_DIGEST_SIZE_BYTES;
+ }
+
+ std::vector<uint8_t> passwordKey(masterKeySize);
+ generateKeyFromPassword(passwordKey, pw, salt);
Blob masterKeyBlob(rawBlob);
ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, passwordKey, STATE_NO_ERROR);
if (response == ResponseCode::SYSTEM_ERROR) {
return response;
}
- if (response == ResponseCode::NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
+
+ size_t masterKeyBlobLength = static_cast<size_t>(masterKeyBlob.getLength());
+
+ if (response == ResponseCode::NO_ERROR && masterKeyBlobLength == masterKeySize) {
// If salt was missing, generate one and write a new master key file with the salt.
if (salt == NULL) {
- if (!generateSalt(entropy)) {
+ if (!generateSalt()) {
return ResponseCode::SYSTEM_ERROR;
}
- response = writeMasterKey(pw, entropy);
+ response = writeMasterKey(pw);
}
if (response == ResponseCode::NO_ERROR) {
- memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
+ mMasterKey = std::vector<uint8_t>(masterKeyBlob.getValue(),
+ masterKeyBlob.getValue() + masterKeyBlob.getLength());
setupMasterKeys();
}
return response;
@@ -221,7 +234,7 @@
return true;
}
-void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+void UserState::generateKeyFromPassword(std::vector<uint8_t>& key, const android::String8& pw,
uint8_t* salt) {
size_t saltSize;
if (salt != NULL) {
@@ -233,19 +246,27 @@
saltSize = sizeof("keystore");
}
- PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize,
- 8192, keySize, key);
+ const EVP_MD* digest = EVP_sha256();
+
+ // SHA1 was used prior to increasing the key size
+ if (key.size() == SHA1_DIGEST_SIZE_BYTES) {
+ digest = EVP_sha1();
+ }
+
+ PKCS5_PBKDF2_HMAC(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize, 8192,
+ digest, key.size(), key.data());
}
-bool UserState::generateSalt(Entropy* entropy) {
- return entropy->generate_random_data(mSalt, sizeof(mSalt));
+bool UserState::generateSalt() {
+ return RAND_bytes(mSalt, sizeof(mSalt));
}
-bool UserState::generateMasterKey(Entropy* entropy) {
- if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
+bool UserState::generateMasterKey() {
+ mMasterKey.resize(MASTER_KEY_SIZE_BYTES);
+ if (!RAND_bytes(mMasterKey.data(), mMasterKey.size())) {
return false;
}
- if (!generateSalt(entropy)) {
+ if (!generateSalt()) {
return false;
}
return true;
diff --git a/keystore/user_state.h b/keystore/user_state.h
index c28f7b8..c4f3cd4 100644
--- a/keystore/user_state.h
+++ b/keystore/user_state.h
@@ -24,8 +24,7 @@
#include <utils/String8.h>
#include <keystore/keystore.h>
-
-#include "entropy.h"
+#include <vector>
class UserState {
public:
@@ -47,28 +46,31 @@
void zeroizeMasterKeysInMemory();
bool deleteMasterKey();
- ResponseCode initialize(const android::String8& pw, Entropy* entropy);
+ ResponseCode initialize(const android::String8& pw);
ResponseCode copyMasterKey(UserState* src);
ResponseCode copyMasterKeyFile(UserState* src);
- ResponseCode writeMasterKey(const android::String8& pw, Entropy* entropy);
- ResponseCode readMasterKey(const android::String8& pw, Entropy* entropy);
+ ResponseCode writeMasterKey(const android::String8& pw);
+ ResponseCode readMasterKey(const android::String8& pw);
- auto& getEncryptionKey() const { return mMasterKey; }
+ const std::vector<uint8_t>& getEncryptionKey() const { return mMasterKey; }
bool reset();
private:
- static const int MASTER_KEY_SIZE_BYTES = 16;
+ static const int SHA1_DIGEST_SIZE_BYTES = 16;
+ static const int SHA256_DIGEST_SIZE_BYTES = 32;
+
+ static const int MASTER_KEY_SIZE_BYTES = SHA256_DIGEST_SIZE_BYTES;
static const int MASTER_KEY_SIZE_BITS = MASTER_KEY_SIZE_BYTES * 8;
static const int MAX_RETRY = 4;
static const size_t SALT_SIZE = 16;
- void generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
+ void generateKeyFromPassword(std::vector<uint8_t>& key, const android::String8& pw,
uint8_t* salt);
- bool generateSalt(Entropy* entropy);
- bool generateMasterKey(Entropy* entropy);
+ bool generateSalt();
+ bool generateMasterKey();
void setupMasterKeys();
uid_t mUserId;
@@ -79,7 +81,7 @@
State mState;
int8_t mRetry;
- uint8_t mMasterKey[MASTER_KEY_SIZE_BYTES];
+ std::vector<uint8_t> mMasterKey;
uint8_t mSalt[SALT_SIZE];
};
diff --git a/softkeymaster/Android.mk b/softkeymaster/Android.mk
deleted file mode 100644
index eb32c87..0000000
--- a/softkeymaster/Android.mk
+++ /dev/null
@@ -1,44 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_MODULE := keystore.default
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := module.cpp
-LOCAL_C_INCLUDES := system/security/keystore
-LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
-LOCAL_SHARED_LIBRARIES := libcrypto liblog libkeystore_binder libsoftkeymaster
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-ifeq ($(USE_32_BIT_KEYSTORE), true)
-LOCAL_MULTILIB := 32
-endif
-LOCAL_MODULE := libsoftkeymaster
-LOCAL_SRC_FILES := keymaster_openssl.cpp
-LOCAL_C_INCLUDES := system/security/keystore \
- $(LOCAL_PATH)/include
-LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
-LOCAL_SHARED_LIBRARIES := libcrypto liblog libkeystore_binder
-LOCAL_MODULE_TAGS := optional
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_SHARED_LIBRARY)
diff --git a/softkeymaster/include/keymaster/softkeymaster.h b/softkeymaster/include/keymaster/softkeymaster.h
deleted file mode 100644
index e86ba3d..0000000
--- a/softkeymaster/include/keymaster/softkeymaster.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#include <hardware/keymaster0.h>
-
-#ifndef SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
-#define SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
-
-int openssl_generate_keypair(const keymaster0_device_t* dev, const keymaster_keypair_t key_type,
- const void* key_params, uint8_t** keyBlob, size_t* keyBlobLength);
-
-int openssl_import_keypair(const keymaster0_device_t* dev, const uint8_t* key,
- const size_t key_length, uint8_t** key_blob, size_t* key_blob_length);
-
-int openssl_get_keypair_public(const struct keymaster0_device* dev, const uint8_t* key_blob,
- const size_t key_blob_length, uint8_t** x509_data,
- size_t* x509_data_length);
-
-int openssl_sign_data(const keymaster0_device_t* dev, const void* params, const uint8_t* keyBlob,
- const size_t keyBlobLength, const uint8_t* data, const size_t dataLength,
- uint8_t** signedData, size_t* signedDataLength);
-
-int openssl_verify_data(const keymaster0_device_t* dev, const void* params, const uint8_t* keyBlob,
- const size_t keyBlobLength, const uint8_t* signedData,
- const size_t signedDataLength, const uint8_t* signature,
- const size_t signatureLength);
-
-int openssl_open(const hw_module_t* module, const char* name, hw_device_t** device);
-
-extern struct keystore_module softkeymaster_module;
-
-#endif // SOFTKEYMASTER_INCLUDE_KEYMASTER_SOFTKEYMASTER_H_
diff --git a/softkeymaster/keymaster_openssl.cpp b/softkeymaster/keymaster_openssl.cpp
deleted file mode 100644
index f4d55bd..0000000
--- a/softkeymaster/keymaster_openssl.cpp
+++ /dev/null
@@ -1,785 +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 <errno.h>
-#include <string.h>
-#include <stdint.h>
-
-#include <keystore/keystore.h>
-#include <keymaster/softkeymaster.h>
-
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-#include <openssl/evp.h>
-#include <openssl/bio.h>
-#include <openssl/rsa.h>
-#include <openssl/err.h>
-#include <openssl/x509.h>
-
-#include <memory>
-
-// For debugging
-// #define LOG_NDEBUG 0
-
-#define LOG_TAG "OpenSSLKeyMaster"
-#include <cutils/log.h>
-
-struct BIGNUM_Delete {
- void operator()(BIGNUM* p) const { BN_free(p); }
-};
-typedef std::unique_ptr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
-
-struct EVP_PKEY_Delete {
- void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
-};
-typedef std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
-
-struct PKCS8_PRIV_KEY_INFO_Delete {
- void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
-};
-typedef std::unique_ptr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
-
-struct DSA_Delete {
- void operator()(DSA* p) const { DSA_free(p); }
-};
-typedef std::unique_ptr<DSA, DSA_Delete> Unique_DSA;
-
-struct EC_KEY_Delete {
- void operator()(EC_KEY* p) const { EC_KEY_free(p); }
-};
-typedef std::unique_ptr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
-
-struct EC_GROUP_Delete {
- void operator()(EC_GROUP* p) const { EC_GROUP_free(p); }
-};
-typedef std::unique_ptr<EC_GROUP, EC_GROUP_Delete> Unique_EC_GROUP;
-
-struct RSA_Delete {
- void operator()(RSA* p) const { RSA_free(p); }
-};
-typedef std::unique_ptr<RSA, RSA_Delete> Unique_RSA;
-
-struct Malloc_Free {
- void operator()(void* p) const { free(p); }
-};
-
-typedef std::unique_ptr<keymaster0_device_t> Unique_keymaster_device_t;
-
-/**
- * Many OpenSSL APIs take ownership of an argument on success but
- * don't free the argument on failure. This means we need to tell our
- * scoped pointers when we've transferred ownership, without
- * triggering a warning by not using the result of release().
- */
-template <typename T, typename Delete_T>
-inline void release_because_ownership_transferred(std::unique_ptr<T, Delete_T>& p) {
- T* val __attribute__((unused)) = p.release();
-}
-
-/*
- * Checks this thread's OpenSSL error queue and logs if
- * necessary.
- */
-static void logOpenSSLError(const char* location) {
- int error = ERR_get_error();
-
- if (error != 0) {
- char message[256];
- ERR_error_string_n(error, message, sizeof(message));
- ALOGE("OpenSSL error in %s %d: %s", location, error, message);
- }
-
- ERR_clear_error();
- ERR_remove_thread_state(NULL);
-}
-
-static int wrap_key(EVP_PKEY* pkey, int type, uint8_t** keyBlob, size_t* keyBlobLength) {
- /*
- * Find the length of each size. Public key is not needed anymore
- * but must be kept for alignment purposes.
- */
- int publicLen = 0;
- int privateLen = i2d_PrivateKey(pkey, NULL);
-
- if (privateLen <= 0) {
- ALOGE("private key size was too big");
- return -1;
- }
-
- /* int type + int size + private key data + int size + public key data */
- *keyBlobLength = get_softkey_header_size() + sizeof(type) + sizeof(publicLen) + privateLen +
- sizeof(privateLen) + publicLen;
-
- // derData will be returned to the caller, so allocate it with malloc.
- std::unique_ptr<unsigned char, Malloc_Free> derData(
- static_cast<unsigned char*>(malloc(*keyBlobLength)));
- if (derData.get() == NULL) {
- ALOGE("could not allocate memory for key blob");
- return -1;
- }
- unsigned char* p = derData.get();
-
- /* Write the magic value for software keys. */
- p = add_softkey_header(p, *keyBlobLength);
-
- /* Write key type to allocated buffer */
- for (int i = sizeof(type) - 1; i >= 0; i--) {
- *p++ = (type >> (8 * i)) & 0xFF;
- }
-
- /* Write public key to allocated buffer */
- for (int i = sizeof(publicLen) - 1; i >= 0; i--) {
- *p++ = (publicLen >> (8 * i)) & 0xFF;
- }
-
- /* Write private key to allocated buffer */
- for (int i = sizeof(privateLen) - 1; i >= 0; i--) {
- *p++ = (privateLen >> (8 * i)) & 0xFF;
- }
- if (i2d_PrivateKey(pkey, &p) != privateLen) {
- logOpenSSLError("wrap_key");
- return -1;
- }
-
- *keyBlob = derData.release();
-
- return 0;
-}
-
-static EVP_PKEY* unwrap_key(const uint8_t* keyBlob, const size_t keyBlobLength) {
- long publicLen = 0;
- long privateLen = 0;
- const uint8_t* p = keyBlob;
- const uint8_t* const end = keyBlob + keyBlobLength;
-
- if (keyBlob == NULL) {
- ALOGE("supplied key blob was NULL");
- return NULL;
- }
-
- int type = 0;
- if (keyBlobLength < (get_softkey_header_size() + sizeof(type) + sizeof(publicLen) + 1 +
- sizeof(privateLen) + 1)) {
- ALOGE("key blob appears to be truncated");
- return NULL;
- }
-
- if (!is_softkey(p, keyBlobLength)) {
- ALOGE("cannot read key; it was not made by this keymaster");
- return NULL;
- }
- p += get_softkey_header_size();
-
- for (size_t i = 0; i < sizeof(type); i++) {
- type = (type << 8) | *p++;
- }
-
- for (size_t i = 0; i < sizeof(type); i++) {
- publicLen = (publicLen << 8) | *p++;
- }
- if (p + publicLen > end) {
- ALOGE("public key length encoding error: size=%ld, end=%td", publicLen, end - p);
- return NULL;
- }
-
- p += publicLen;
- if (end - p < 2) {
- ALOGE("private key truncated");
- return NULL;
- }
- for (size_t i = 0; i < sizeof(type); i++) {
- privateLen = (privateLen << 8) | *p++;
- }
- if (p + privateLen > end) {
- ALOGE("private key length encoding error: size=%ld, end=%td", privateLen, end - p);
- return NULL;
- }
-
- Unique_EVP_PKEY pkey(d2i_PrivateKey(type, nullptr, &p, privateLen));
- if (pkey.get() == NULL) {
- logOpenSSLError("unwrap_key");
- return NULL;
- }
-
- return pkey.release();
-}
-
-static int generate_dsa_keypair(EVP_PKEY* pkey, const keymaster_dsa_keygen_params_t* dsa_params) {
- if (dsa_params->key_size < 512) {
- ALOGI("Requested DSA key size is too small (<512)");
- return -1;
- }
-
- Unique_DSA dsa(DSA_new());
-
- if (dsa_params->generator_len == 0 || dsa_params->prime_p_len == 0 ||
- dsa_params->prime_q_len == 0 || dsa_params->generator == NULL ||
- dsa_params->prime_p == NULL || dsa_params->prime_q == NULL) {
- if (DSA_generate_parameters_ex(dsa.get(), dsa_params->key_size, NULL, 0, NULL, NULL,
- NULL) != 1) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
- } else {
- dsa->g = BN_bin2bn(dsa_params->generator, dsa_params->generator_len, NULL);
- if (dsa->g == NULL) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
-
- dsa->p = BN_bin2bn(dsa_params->prime_p, dsa_params->prime_p_len, NULL);
- if (dsa->p == NULL) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
-
- dsa->q = BN_bin2bn(dsa_params->prime_q, dsa_params->prime_q_len, NULL);
- if (dsa->q == NULL) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
- }
-
- if (DSA_generate_key(dsa.get()) != 1) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
-
- if (EVP_PKEY_assign_DSA(pkey, dsa.get()) == 0) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
- release_because_ownership_transferred(dsa);
-
- return 0;
-}
-
-static int generate_ec_keypair(EVP_PKEY* pkey, const keymaster_ec_keygen_params_t* ec_params) {
- Unique_EC_GROUP group;
- switch (ec_params->field_size) {
- case 224:
- group.reset(EC_GROUP_new_by_curve_name(NID_secp224r1));
- break;
- case 256:
- group.reset(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
- break;
- case 384:
- group.reset(EC_GROUP_new_by_curve_name(NID_secp384r1));
- break;
- case 521:
- group.reset(EC_GROUP_new_by_curve_name(NID_secp521r1));
- break;
- default:
- break;
- }
-
- if (group.get() == NULL) {
- logOpenSSLError("generate_ec_keypair");
- return -1;
- }
-
-#if !defined(OPENSSL_IS_BORINGSSL)
- EC_GROUP_set_point_conversion_form(group.get(), POINT_CONVERSION_UNCOMPRESSED);
- EC_GROUP_set_asn1_flag(group.get(), OPENSSL_EC_NAMED_CURVE);
-#endif
-
- /* initialize EC key */
- Unique_EC_KEY eckey(EC_KEY_new());
- if (eckey.get() == NULL) {
- logOpenSSLError("generate_ec_keypair");
- return -1;
- }
-
- if (EC_KEY_set_group(eckey.get(), group.get()) != 1) {
- logOpenSSLError("generate_ec_keypair");
- return -1;
- }
-
- if (EC_KEY_generate_key(eckey.get()) != 1 || EC_KEY_check_key(eckey.get()) < 0) {
- logOpenSSLError("generate_ec_keypair");
- return -1;
- }
-
- if (EVP_PKEY_assign_EC_KEY(pkey, eckey.get()) == 0) {
- logOpenSSLError("generate_ec_keypair");
- return -1;
- }
- release_because_ownership_transferred(eckey);
-
- return 0;
-}
-
-static int generate_rsa_keypair(EVP_PKEY* pkey, const keymaster_rsa_keygen_params_t* rsa_params) {
- Unique_BIGNUM bn(BN_new());
- if (bn.get() == NULL) {
- logOpenSSLError("generate_rsa_keypair");
- return -1;
- }
-
- if (BN_set_word(bn.get(), rsa_params->public_exponent) == 0) {
- logOpenSSLError("generate_rsa_keypair");
- return -1;
- }
-
- /* initialize RSA */
- Unique_RSA rsa(RSA_new());
- if (rsa.get() == NULL) {
- logOpenSSLError("generate_rsa_keypair");
- return -1;
- }
-
- if (!RSA_generate_key_ex(rsa.get(), rsa_params->modulus_size, bn.get(), NULL) ||
- RSA_check_key(rsa.get()) < 0) {
- logOpenSSLError("generate_rsa_keypair");
- return -1;
- }
-
- if (EVP_PKEY_assign_RSA(pkey, rsa.get()) == 0) {
- logOpenSSLError("generate_rsa_keypair");
- return -1;
- }
- release_because_ownership_transferred(rsa);
-
- return 0;
-}
-
-__attribute__((visibility("default"))) int openssl_generate_keypair(
- const keymaster0_device_t*, const keymaster_keypair_t key_type, const void* key_params,
- uint8_t** keyBlob, size_t* keyBlobLength) {
- Unique_EVP_PKEY pkey(EVP_PKEY_new());
- if (pkey.get() == NULL) {
- logOpenSSLError("openssl_generate_keypair");
- return -1;
- }
-
- if (key_params == NULL) {
- ALOGW("key_params == null");
- return -1;
- } else if (key_type == TYPE_DSA) {
- const keymaster_dsa_keygen_params_t* dsa_params =
- (const keymaster_dsa_keygen_params_t*)key_params;
- generate_dsa_keypair(pkey.get(), dsa_params);
- } else if (key_type == TYPE_EC) {
- const keymaster_ec_keygen_params_t* ec_params =
- (const keymaster_ec_keygen_params_t*)key_params;
- generate_ec_keypair(pkey.get(), ec_params);
- } else if (key_type == TYPE_RSA) {
- const keymaster_rsa_keygen_params_t* rsa_params =
- (const keymaster_rsa_keygen_params_t*)key_params;
- generate_rsa_keypair(pkey.get(), rsa_params);
- } else {
- ALOGW("Unsupported key type %d", key_type);
- return -1;
- }
-
- if (wrap_key(pkey.get(), EVP_PKEY_type(pkey->type), keyBlob, keyBlobLength)) {
- return -1;
- }
-
- return 0;
-}
-
-__attribute__((visibility("default"))) int openssl_import_keypair(const keymaster0_device_t*,
- const uint8_t* key,
- const size_t key_length,
- uint8_t** key_blob,
- size_t* key_blob_length) {
- if (key == NULL) {
- ALOGW("input key == NULL");
- return -1;
- } else if (key_blob == NULL || key_blob_length == NULL) {
- ALOGW("output key blob or length == NULL");
- return -1;
- }
-
- Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length));
- if (pkcs8.get() == NULL) {
- logOpenSSLError("openssl_import_keypair");
- return -1;
- }
-
- /* assign to EVP */
- Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
- if (pkey.get() == NULL) {
- logOpenSSLError("openssl_import_keypair");
- return -1;
- }
-
- if (wrap_key(pkey.get(), EVP_PKEY_type(pkey->type), key_blob, key_blob_length)) {
- return -1;
- }
-
- return 0;
-}
-
-__attribute__((visibility("default"))) int openssl_get_keypair_public(const keymaster0_device_t*,
- const uint8_t* key_blob,
- const size_t key_blob_length,
- uint8_t** x509_data,
- size_t* x509_data_length) {
- if (x509_data == NULL || x509_data_length == NULL) {
- ALOGW("output public key buffer == NULL");
- return -1;
- }
-
- Unique_EVP_PKEY pkey(unwrap_key(key_blob, key_blob_length));
- if (pkey.get() == NULL) {
- return -1;
- }
-
- int len = i2d_PUBKEY(pkey.get(), NULL);
- if (len <= 0) {
- logOpenSSLError("openssl_get_keypair_public");
- return -1;
- }
-
- std::unique_ptr<uint8_t, Malloc_Free> key(static_cast<uint8_t*>(malloc(len)));
- if (key.get() == NULL) {
- ALOGE("Could not allocate memory for public key data");
- return -1;
- }
-
- unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get());
- if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
- logOpenSSLError("openssl_get_keypair_public");
- return -1;
- }
-
- ALOGV("Length of x509 data is %d", len);
- *x509_data_length = len;
- *x509_data = key.release();
-
- return 0;
-}
-
-static int sign_dsa(EVP_PKEY* pkey, keymaster_dsa_sign_params_t* sign_params, const uint8_t* data,
- const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
- if (sign_params->digest_type != DIGEST_NONE) {
- ALOGW("Cannot handle digest type %d", sign_params->digest_type);
- return -1;
- }
-
- Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
- if (dsa.get() == NULL) {
- logOpenSSLError("openssl_sign_dsa");
- return -1;
- }
-
- unsigned int dsaSize = DSA_size(dsa.get());
- std::unique_ptr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(dsaSize)));
- if (signedDataPtr.get() == NULL) {
- logOpenSSLError("openssl_sign_dsa");
- return -1;
- }
-
- unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
- if (DSA_sign(0, data, dataLength, tmp, &dsaSize, dsa.get()) <= 0) {
- logOpenSSLError("openssl_sign_dsa");
- return -1;
- }
-
- *signedDataLength = dsaSize;
- *signedData = signedDataPtr.release();
-
- return 0;
-}
-
-static int sign_ec(EVP_PKEY* pkey, keymaster_ec_sign_params_t* sign_params, const uint8_t* data,
- const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
- if (sign_params->digest_type != DIGEST_NONE) {
- ALOGW("Cannot handle digest type %d", sign_params->digest_type);
- return -1;
- }
-
- Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
- if (eckey.get() == NULL) {
- logOpenSSLError("openssl_sign_ec");
- return -1;
- }
-
- unsigned int ecdsaSize = ECDSA_size(eckey.get());
- std::unique_ptr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(ecdsaSize)));
- if (signedDataPtr.get() == NULL) {
- logOpenSSLError("openssl_sign_ec");
- return -1;
- }
-
- unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
- if (ECDSA_sign(0, data, dataLength, tmp, &ecdsaSize, eckey.get()) <= 0) {
- logOpenSSLError("openssl_sign_ec");
- return -1;
- }
-
- *signedDataLength = ecdsaSize;
- *signedData = signedDataPtr.release();
-
- return 0;
-}
-
-static int sign_rsa(EVP_PKEY* pkey, keymaster_rsa_sign_params_t* sign_params, const uint8_t* data,
- const size_t dataLength, uint8_t** signedData, size_t* signedDataLength) {
- if (sign_params->digest_type != DIGEST_NONE) {
- ALOGW("Cannot handle digest type %d", sign_params->digest_type);
- return -1;
- } else if (sign_params->padding_type != PADDING_NONE) {
- ALOGW("Cannot handle padding type %d", sign_params->padding_type);
- return -1;
- }
-
- Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
- if (rsa.get() == NULL) {
- logOpenSSLError("openssl_sign_rsa");
- return -1;
- }
-
- std::unique_ptr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(dataLength)));
- if (signedDataPtr.get() == NULL) {
- logOpenSSLError("openssl_sign_rsa");
- return -1;
- }
-
- unsigned char* tmp = reinterpret_cast<unsigned char*>(signedDataPtr.get());
- if (RSA_private_encrypt(dataLength, data, tmp, rsa.get(), RSA_NO_PADDING) <= 0) {
- logOpenSSLError("openssl_sign_rsa");
- return -1;
- }
-
- *signedDataLength = dataLength;
- *signedData = signedDataPtr.release();
-
- return 0;
-}
-
-__attribute__((visibility("default"))) int openssl_sign_data(
- const keymaster0_device_t*, const void* params, const uint8_t* keyBlob,
- const size_t keyBlobLength, const uint8_t* data, const size_t dataLength, uint8_t** signedData,
- size_t* signedDataLength) {
- if (data == NULL) {
- ALOGW("input data to sign == NULL");
- return -1;
- } else if (signedData == NULL || signedDataLength == NULL) {
- ALOGW("output signature buffer == NULL");
- return -1;
- }
-
- Unique_EVP_PKEY pkey(unwrap_key(keyBlob, keyBlobLength));
- if (pkey.get() == NULL) {
- return -1;
- }
-
- int type = EVP_PKEY_type(pkey->type);
- if (type == EVP_PKEY_DSA) {
- const keymaster_dsa_sign_params_t* sign_params =
- reinterpret_cast<const keymaster_dsa_sign_params_t*>(params);
- return sign_dsa(pkey.get(), const_cast<keymaster_dsa_sign_params_t*>(sign_params), data,
- dataLength, signedData, signedDataLength);
- } else if (type == EVP_PKEY_EC) {
- const keymaster_ec_sign_params_t* sign_params =
- reinterpret_cast<const keymaster_ec_sign_params_t*>(params);
- return sign_ec(pkey.get(), const_cast<keymaster_ec_sign_params_t*>(sign_params), data,
- dataLength, signedData, signedDataLength);
- } else if (type == EVP_PKEY_RSA) {
- const keymaster_rsa_sign_params_t* sign_params =
- reinterpret_cast<const keymaster_rsa_sign_params_t*>(params);
- return sign_rsa(pkey.get(), const_cast<keymaster_rsa_sign_params_t*>(sign_params), data,
- dataLength, signedData, signedDataLength);
- } else {
- ALOGW("Unsupported key type");
- return -1;
- }
-}
-
-static int verify_dsa(EVP_PKEY* pkey, keymaster_dsa_sign_params_t* sign_params,
- const uint8_t* signedData, const size_t signedDataLength,
- const uint8_t* signature, const size_t signatureLength) {
- if (sign_params->digest_type != DIGEST_NONE) {
- ALOGW("Cannot handle digest type %d", sign_params->digest_type);
- return -1;
- }
-
- Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
- if (dsa.get() == NULL) {
- logOpenSSLError("openssl_verify_dsa");
- return -1;
- }
-
- if (DSA_verify(0, signedData, signedDataLength, signature, signatureLength, dsa.get()) <= 0) {
- logOpenSSLError("openssl_verify_dsa");
- return -1;
- }
-
- return 0;
-}
-
-static int verify_ec(EVP_PKEY* pkey, keymaster_ec_sign_params_t* sign_params,
- const uint8_t* signedData, const size_t signedDataLength,
- const uint8_t* signature, const size_t signatureLength) {
- if (sign_params->digest_type != DIGEST_NONE) {
- ALOGW("Cannot handle digest type %d", sign_params->digest_type);
- return -1;
- }
-
- Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
- if (eckey.get() == NULL) {
- logOpenSSLError("openssl_verify_ec");
- return -1;
- }
-
- if (ECDSA_verify(0, signedData, signedDataLength, signature, signatureLength, eckey.get()) <=
- 0) {
- logOpenSSLError("openssl_verify_ec");
- return -1;
- }
-
- return 0;
-}
-
-static int verify_rsa(EVP_PKEY* pkey, keymaster_rsa_sign_params_t* sign_params,
- const uint8_t* signedData, const size_t signedDataLength,
- const uint8_t* signature, const size_t signatureLength) {
- if (sign_params->digest_type != DIGEST_NONE) {
- ALOGW("Cannot handle digest type %d", sign_params->digest_type);
- return -1;
- } else if (sign_params->padding_type != PADDING_NONE) {
- ALOGW("Cannot handle padding type %d", sign_params->padding_type);
- return -1;
- } else if (signatureLength != signedDataLength) {
- ALOGW("signed data length must be signature length");
- return -1;
- }
-
- Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
- if (rsa.get() == NULL) {
- logOpenSSLError("openssl_verify_data");
- return -1;
- }
-
- std::unique_ptr<uint8_t[]> dataPtr(new uint8_t[signedDataLength]);
- if (dataPtr.get() == NULL) {
- logOpenSSLError("openssl_verify_data");
- return -1;
- }
-
- unsigned char* tmp = reinterpret_cast<unsigned char*>(dataPtr.get());
- if (!RSA_public_decrypt(signatureLength, signature, tmp, rsa.get(), RSA_NO_PADDING)) {
- logOpenSSLError("openssl_verify_data");
- return -1;
- }
-
- int result = 0;
- for (size_t i = 0; i < signedDataLength; i++) {
- result |= tmp[i] ^ signedData[i];
- }
-
- return result == 0 ? 0 : -1;
-}
-
-__attribute__((visibility("default"))) int openssl_verify_data(
- const keymaster0_device_t*, const void* params, const uint8_t* keyBlob,
- const size_t keyBlobLength, const uint8_t* signedData, const size_t signedDataLength,
- const uint8_t* signature, const size_t signatureLength) {
- if (signedData == NULL || signature == NULL) {
- ALOGW("data or signature buffers == NULL");
- return -1;
- }
-
- Unique_EVP_PKEY pkey(unwrap_key(keyBlob, keyBlobLength));
- if (pkey.get() == NULL) {
- return -1;
- }
-
- int type = EVP_PKEY_type(pkey->type);
- if (type == EVP_PKEY_DSA) {
- const keymaster_dsa_sign_params_t* sign_params =
- reinterpret_cast<const keymaster_dsa_sign_params_t*>(params);
- return verify_dsa(pkey.get(), const_cast<keymaster_dsa_sign_params_t*>(sign_params),
- signedData, signedDataLength, signature, signatureLength);
- } else if (type == EVP_PKEY_RSA) {
- const keymaster_rsa_sign_params_t* sign_params =
- reinterpret_cast<const keymaster_rsa_sign_params_t*>(params);
- return verify_rsa(pkey.get(), const_cast<keymaster_rsa_sign_params_t*>(sign_params),
- signedData, signedDataLength, signature, signatureLength);
- } else if (type == EVP_PKEY_EC) {
- const keymaster_ec_sign_params_t* sign_params =
- reinterpret_cast<const keymaster_ec_sign_params_t*>(params);
- return verify_ec(pkey.get(), const_cast<keymaster_ec_sign_params_t*>(sign_params),
- signedData, signedDataLength, signature, signatureLength);
- } else {
- ALOGW("Unsupported key type %d", type);
- return -1;
- }
-}
-
-/* Close an opened OpenSSL instance */
-static int openssl_close(hw_device_t* dev) {
- delete dev;
- return 0;
-}
-
-/*
- * Generic device handling
- */
-__attribute__((visibility("default"))) int openssl_open(const hw_module_t* module, const char* name,
- hw_device_t** device) {
- if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
- return -EINVAL;
-
- Unique_keymaster_device_t dev(new keymaster0_device_t);
- if (dev.get() == NULL)
- return -ENOMEM;
-
- dev->common.tag = HARDWARE_DEVICE_TAG;
- dev->common.version = 1;
- dev->common.module = (struct hw_module_t*)module;
- dev->common.close = openssl_close;
-
- dev->flags = KEYMASTER_SOFTWARE_ONLY | KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_DSA |
- KEYMASTER_SUPPORTS_EC;
-
- dev->generate_keypair = openssl_generate_keypair;
- dev->import_keypair = openssl_import_keypair;
- dev->get_keypair_public = openssl_get_keypair_public;
- dev->delete_keypair = NULL;
- dev->delete_all = NULL;
- dev->sign_data = openssl_sign_data;
- dev->verify_data = openssl_verify_data;
-
- ERR_load_crypto_strings();
- ERR_load_BIO_strings();
-
- *device = reinterpret_cast<hw_device_t*>(dev.release());
-
- return 0;
-}
-
-static struct hw_module_methods_t keystore_module_methods = {
- .open = openssl_open,
-};
-
-struct keystore_module softkeymaster_module __attribute__((visibility("default"))) = {
- .common =
- {
- .tag = HARDWARE_MODULE_TAG,
- .module_api_version = KEYMASTER_MODULE_API_VERSION_0_2,
- .hal_api_version = HARDWARE_HAL_API_VERSION,
- .id = KEYSTORE_HARDWARE_MODULE_ID,
- .name = "Keymaster OpenSSL HAL",
- .author = "The Android Open Source Project",
- .methods = &keystore_module_methods,
- .dso = 0,
- .reserved = {},
- },
-};