summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format (renamed from keystore/.clang-format)0
-rw-r--r--PREUPLOAD.cfg5
-rw-r--r--keystore-engine/.clang-format10
-rw-r--r--keystore-engine/Android.mk1
-rw-r--r--keystore-engine/keystore_backend_binder.cpp24
-rw-r--r--keystore/Android.bp131
-rw-r--r--keystore/IKeystoreService.cpp1361
-rw-r--r--keystore/KeyAttestationApplicationId.cpp8
-rw-r--r--keystore/KeyAttestationPackageInfo.cpp13
-rw-r--r--keystore/KeyStore.cpp (renamed from keystore/keystore.cpp)166
-rw-r--r--keystore/KeyStore.h (renamed from keystore/keystore.h)64
-rw-r--r--keystore/KeymasterArguments.cpp42
-rw-r--r--keystore/KeystoreArguments.cpp61
-rw-r--r--keystore/OperationResult.cpp60
-rw-r--r--keystore/auth_token_table.cpp59
-rw-r--r--keystore/auth_token_table.h34
-rw-r--r--keystore/authorization_set.cpp2
-rw-r--r--keystore/binder/android/security/IConfirmationPromptCallback.aidl27
-rw-r--r--keystore/binder/android/security/IKeystoreService.aidl89
-rw-r--r--keystore/binder/android/security/KeystoreArguments.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/ExportResult.aidl (renamed from softkeymaster/module.cpp)12
-rw-r--r--keystore/binder/android/security/keymaster/KeyCharacteristics.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/KeymasterArguments.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/KeymasterBlob.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl20
-rw-r--r--keystore/binder/android/security/keymaster/OperationResult.aidl20
-rw-r--r--keystore/blob.cpp13
-rw-r--r--keystore/blob.h4
-rw-r--r--keystore/confirmation_manager.cpp216
-rw-r--r--keystore/confirmation_manager.h104
-rw-r--r--keystore/confirmationui_rate_limiting.h124
-rw-r--r--keystore/include/keystore/ExportResult.h40
-rw-r--r--keystore/include/keystore/IKeystoreService.h254
-rw-r--r--keystore/include/keystore/KeyAttestationApplicationId.h11
-rw-r--r--keystore/include/keystore/KeyAttestationPackageInfo.h24
-rw-r--r--keystore/include/keystore/KeyCharacteristics.h45
-rw-r--r--keystore/include/keystore/KeymasterArguments.h44
-rw-r--r--keystore/include/keystore/KeymasterBlob.h40
-rw-r--r--keystore/include/keystore/KeymasterCertificateChain.h42
-rw-r--r--keystore/include/keystore/KeystoreArg.h42
-rw-r--r--keystore/include/keystore/KeystoreArguments.h42
-rw-r--r--keystore/include/keystore/OperationResult.h46
-rw-r--r--keystore/include/keystore/Signature.h4
-rw-r--r--keystore/include/keystore/authorization_set.h336
-rw-r--r--keystore/include/keystore/keymaster_tags.h351
-rw-r--r--keystore/include/keystore/keymaster_types.h104
-rw-r--r--keystore/include/keystore/keystore.h21
-rw-r--r--keystore/include/keystore/keystore_client.h55
-rw-r--r--keystore/include/keystore/keystore_client_impl.h60
-rw-r--r--keystore/include/keystore/keystore_client_mock.h2
-rw-r--r--keystore/include/keystore/keystore_get.h2
-rw-r--r--keystore/include/keystore/keystore_hidl_support.h87
-rw-r--r--keystore/include/keystore/keystore_return_types.h13
-rw-r--r--keystore/key_config.proto62
-rw-r--r--keystore/key_proto_handler.cpp86
-rw-r--r--keystore/key_proto_handler.h29
-rw-r--r--keystore/key_store_service.cpp1539
-rw-r--r--keystore/key_store_service.h283
-rw-r--r--keystore/keymaster_enforcement.cpp103
-rw-r--r--keystore/keymaster_enforcement.h39
-rw-r--r--keystore/keystore.rc2
-rw-r--r--keystore/keystore_aidl_hidl_marshalling_utils.cpp129
-rw-r--r--keystore/keystore_aidl_hidl_marshalling_utils.h12
-rw-r--r--keystore/keystore_attestation_id.cpp48
-rw-r--r--keystore/keystore_cli.cpp57
-rw-r--r--keystore/keystore_cli_v2.cpp229
-rw-r--r--keystore/keystore_client_impl.cpp235
-rw-r--r--keystore/keystore_get.cpp11
-rw-r--r--keystore/keystore_keymaster_enforcement.h17
-rw-r--r--keystore/keystore_main.cpp169
-rw-r--r--keystore/keystore_tags_utils.cpp46
-rw-r--r--keystore/keystore_utils.cpp49
-rw-r--r--keystore/keystore_utils.h31
-rw-r--r--keystore/operation.cpp111
-rw-r--r--keystore/operation.h69
-rw-r--r--keystore/operation_config.proto63
-rw-r--r--keystore/operation_proto_handler.cpp120
-rw-r--r--keystore/operation_proto_handler.h31
-rw-r--r--keystore/operation_struct.h59
-rw-r--r--keystore/tests/Android.bp20
-rw-r--r--keystore/tests/auth_token_formatting_test.cpp157
-rw-r--r--keystore/tests/auth_token_table_test.cpp253
-rw-r--r--keystore/tests/confirmationui_rate_limiting_test.cpp274
-rw-r--r--softkeymaster/Android.bp40
-rw-r--r--softkeymaster/include/keymaster/softkeymaster.h45
-rw-r--r--softkeymaster/keymaster_openssl.cpp785
86 files changed, 4763 insertions, 4855 deletions
diff --git a/keystore/.clang-format b/.clang-format
index b0dc94c1..b0dc94c1 100644
--- a/keystore/.clang-format
+++ b/.clang-format
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 00000000..c8dbf77f
--- /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-engine/.clang-format b/keystore-engine/.clang-format
new file mode 100644
index 00000000..b0dc94c1
--- /dev/null
+++ b/keystore-engine/.clang-format
@@ -0,0 +1,10 @@
+BasedOnStyle: LLVM
+IndentWidth: 4
+UseTab: Never
+BreakBeforeBraces: Attach
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: true
+IndentCaseLabels: false
+ColumnLimit: 100
+PointerBindsToType: true
+SpacesBeforeTrailingComments: 2
diff --git a/keystore-engine/Android.mk b/keystore-engine/Android.mk
index 89888578..c995dfc1 100644
--- a/keystore-engine/Android.mk
+++ b/keystore-engine/Android.mk
@@ -30,6 +30,7 @@ LOCAL_SHARED_LIBRARIES += \
libcrypto \
libcutils \
libhidlbase \
+ libkeystore_aidl \
libkeystore_binder \
liblog \
libutils
diff --git a/keystore-engine/keystore_backend_binder.cpp b/keystore-engine/keystore_backend_binder.cpp
index 9f02fb56..79b0ec36 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 @@ namespace {
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 @@ int32_t KeystoreBackendBinder::sign(
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 @@ int32_t KeystoreBackendBinder::get_pubkey(
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
index 8addecde..37bc6a83 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -21,39 +21,49 @@ cc_binary {
srcs: [
":IKeyAttestationApplicationIdProvider.aidl",
+ "KeyStore.cpp",
"auth_token_table.cpp",
"blob.cpp",
+ "confirmation_manager.cpp",
"entropy.cpp",
"grant_store.cpp",
+ "key_config.proto",
+ "key_proto_handler.cpp",
"key_store_service.cpp",
"keyblob_utils.cpp",
"keymaster_enforcement.cpp",
- "keystore.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",
- "libcutils",
"libhardware",
"libhidlbase",
"libhidltransport",
"libhwbinder",
+ "libkeymaster4support",
"libkeymaster_messages",
"libkeymaster_portable",
- "libkeymaster_staging",
+ "libkeystore_aidl",
"libkeystore_binder",
+ "libkeystore_parcelables",
"liblog",
+ "libprotobuf-cpp-lite",
"libselinux",
- "libsoftkeymaster",
+ "libservices",
"libsoftkeymasterdevice",
"libutils",
"libwifikeystorehal",
@@ -68,6 +78,8 @@ cc_binary {
enabled: false,
},
},
+
+ required: ["keystore_cli_v2"],
}
cc_binary {
@@ -76,13 +88,15 @@ cc_binary {
srcs: ["keystore_cli.cpp"],
shared_libs: [
- "android.hardware.keymaster@3.0",
+ "android.hardware.keymaster@4.0",
"libbinder",
"libcrypto",
"libcutils",
"libhidlbase",
"libhwbinder",
+ "libkeystore_aidl", // for IKeyStoreService.asInterface()
"libkeystore_binder",
+ "libkeystore_parcelables",
"liblog",
"libutils",
],
@@ -98,39 +112,73 @@ cc_binary {
],
srcs: ["keystore_cli_v2.cpp"],
shared_libs: [
- "android.hardware.keymaster@3.0",
+ "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"],
}
-// Library for keystore clients
cc_library_shared {
- name: "libkeystore_binder",
+ name: "libkeystore_parcelables",
defaults: ["keystore_defaults"],
-
+ export_include_dirs: ["include"],
srcs: [
- "IKeystoreService.cpp",
"KeyAttestationApplicationId.cpp",
"KeyAttestationPackageInfo.cpp",
+ "KeymasterArguments.cpp",
+ "KeystoreArguments.cpp",
+ "OperationResult.cpp",
"Signature.cpp",
- "authorization_set.cpp",
- "keyblob_utils.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",
- "keystore_tags_utils.cpp",
],
shared_libs: [
- "android.hardware.keymaster@3.0",
+ "android.hardware.keymaster@4.0",
"libbinder",
"libhidlbase",
"libhwbinder",
+ "libkeymaster4support",
+ "libkeystore_aidl",
+ "libkeystore_parcelables",
"liblog",
"libprotobuf-cpp-lite",
"libutils",
@@ -140,12 +188,18 @@ cc_library_shared {
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@3.0",
+ "android.hardware.keymaster@4.0",
"libbinder",
"libhidlbase",
"libhwbinder",
+ "libkeystore_aidl",
+ "libkeystore_parcelables",
],
}
@@ -174,22 +228,61 @@ cc_library_static {
name: "libkeystore_test",
defaults: ["keystore_defaults"],
- srcs: ["auth_token_table.cpp"],
+ srcs: [
+ "auth_token_table.cpp",
+ ],
+ cflags: [ "-O0", ],
static_libs: ["libgtest_main"],
shared_libs: [
- "android.hardware.keymaster@3.0",
+ "android.hardware.keymaster@4.0",
"libhidlbase",
"libhwbinder",
- "libkeymaster_messages",
+ "libkeymaster4support",
"libutils",
],
export_shared_lib_headers: [
- "android.hardware.keymaster@3.0",
+ "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/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
deleted file mode 100644
index 09a923df..00000000
--- 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 = nullptr;
- *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(nullptr);
- }
- }
- }
- }
- 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 = nullptr;
- 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 1352124c..4bc939de 100644
--- a/keystore/KeyAttestationApplicationId.cpp
+++ b/keystore/KeyAttestationApplicationId.cpp
@@ -23,6 +23,14 @@ namespace android {
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 a84c2465..75fbb7a1 100644
--- a/keystore/KeyAttestationPackageInfo.cpp
+++ b/keystore/KeyAttestationPackageInfo.cpp
@@ -23,10 +23,17 @@ namespace android {
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::writeToParcel(Parcel* parcel) const {
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
index 582333d7..3a8861e9 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";
+
+const android::String16 KeyStore::kRsaKeyType("RSA");
+const android::String16 KeyStore::kEcKeyType("EC");
-using namespace keystore;
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(Entropy* entropy, const KeymasterDevices& kmDevices,
+ SecurityLevel minimalAllowedSecurityLevelForNewKeys)
+ : mEntropy(entropy), mKmDevices(kmDevices),
+ mAllowNewFallback(minimalAllowedSecurityLevelForNewKeys == SecurityLevel::SOFTWARE) {
memset(&mMetaData, '\0', sizeof(mMetaData));
}
@@ -131,8 +152,8 @@ android::String8 KeyStore::getKeyName(const android::String8& keyName, const Blo
}
}
-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::getKeyNameForUid(
}
}
-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 @@ android::String8 KeyStore::getKeyNameForUidWithDir(
}
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 @@ NullOr<android::String8> KeyStore::getBlobFileNameIfExists(const android::String
// 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 @@ void KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) {
// 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 @@ void KeyStore::lock(uid_t userId) {
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;
}
@@ -351,25 +381,29 @@ ResponseCode KeyStore::del(const char* filename, const BlobType type, uid_t user
// 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 +453,8 @@ static void decode_key(char* out, const char* in, size_t length) {
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 +558,26 @@ ResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char*
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 +587,23 @@ ResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char*
Blob keyBlob(&blob[0], blob.size(), nullptr, 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 == nullptr) {
+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 +611,7 @@ ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyN
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 +740,7 @@ ResponseCode KeyStore::importBlobAsKey(Blob* blob, const char* filename, uid_t u
}
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 +765,7 @@ void KeyStore::writeMetaData() {
sizeof(mMetaData));
}
close(out);
- rename(tmpFileName, sMetaDataFile);
+ rename(tmpFileName, kMetaDataFile);
}
bool KeyStore::upgradeKeystore() {
@@ -742,8 +778,8 @@ bool KeyStore::upgradeKeystore() {
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 +838,17 @@ bool KeyStore::upgradeKeystore() {
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
index a0b747ff..23476d21 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 <keystore/keymaster_types.h>
+
#include "blob.h"
-#include "include/keystore/keymaster_tags.h"
#include "grant_store.h"
+#include "user_state.h"
-using ::keystore::NullOr;
+namespace keystore {
-class KeyStore {
- typedef ::android::sp<::android::hardware::keymaster::V3_0::IKeymasterDevice> km_device_t;
+using ::android::sp;
+using keymaster::support::Keymaster;
+class KeymasterDevices : public std::array<sp<Keymaster>, 3> {
public:
- KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
- bool allowNewFallback);
+ sp<Keymaster>& operator[](SecurityLevel secLevel);
+ sp<Keymaster> operator[](SecurityLevel secLevel) const;
+};
+
+class KeyStore {
+ public:
+ KeyStore(Entropy* entropy, const KeymasterDevices& kmDevices,
+ SecurityLevel minimalAllowedSecurityLevelForNewKeys);
~KeyStore();
- km_device_t& getDevice() { return mDevice; }
+ sp<Keymaster> getDevice(SecurityLevel securityLevel) const { return mKmDevices[securityLevel]; }
+
+ 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};
+ }
- NullOr<km_device_t&> getFallbackDevice() {
+ 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 @@ class KeyStore {
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,13 @@ class KeyStore {
const UserState* getUserStateByUid(uid_t uid) const;
private:
- static const char* sOldMasterKey;
- static const char* sMetaDataFile;
- static const android::String16 sRSAKeyType;
+ static const char* kOldMasterKey;
+ static const char* kMetaDataFile;
+ static const android::String16 kRsaKeyType;
+ static const android::String16 kEcKeyType;
Entropy* mEntropy;
- km_device_t mDevice;
- km_device_t mFallbackDevice;
+ KeymasterDevices mKmDevices;
bool mAllowNewFallback;
android::Vector<UserState*> mMasterKeys;
@@ -158,4 +172,6 @@ class KeyStore {
bool upgradeKeystore();
};
+} // namespace keystore
+
#endif // KEYSTORE_KEYSTORE_H_
diff --git a/keystore/KeymasterArguments.cpp b/keystore/KeymasterArguments.cpp
new file mode 100644
index 00000000..829156cd
--- /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 00000000..6b29e786
--- /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(nullptr);
+ }
+ }
+ }
+ 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 00000000..53c8d626
--- /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 b7cc8454..063da703 100644
--- a/keystore/auth_token_table.cpp
+++ b/keystore/auth_token_table.cpp
@@ -77,13 +77,12 @@ time_t clock_gettime_raw() {
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 @@ void AuthTokenTable::AddAuthenticationToken(const HardwareAuthToken* auth_token)
}
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 @@ AuthTokenTable::FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
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 @@ AuthTokenTable::Error AuthTokenTable::FindTimedAuthorization(const std::vector<u
}
newest_match->UpdateLastUse(now);
- *found = newest_match->token();
+ *found = &newest_match->token();
return OK;
}
@@ -202,7 +199,7 @@ bool AuthTokenTable::IsSupersededBySomeEntry(const Entry& entry) {
}
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 @@ void AuthTokenTable::MarkCompleted(const uint64_t op_handle) {
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 @@ void AuthTokenTable::Entry::UpdateLastUse(time_t time) {
bool AuthTokenTable::Entry::Supersedes(const Entry& entry) const {
if (!entry.completed()) return false;
- return (token_->userId == entry.token_->userId &&
- token_->authenticatorType == entry.token_->authenticatorType &&
- token_->authenticatorId == entry.token_->authenticatorId &&
- timestamp_host_order() > entry.timestamp_host_order());
+ 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 422c7102..db600032 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 @@ class AuthTokenTable {
};
/**
- * 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 AuthTokenTable {
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) {
@@ -114,21 +113,30 @@ class AuthTokenTable {
bool Supersedes(const Entry& entry) const;
bool SatisfiesAuth(const std::vector<uint64_t>& sids, HardwareAuthenticatorType auth_type);
- bool is_newer_than(const Entry* entry) {
+ bool is_newer_than(const Entry* entry) const {
if (!entry) return true;
- return timestamp_host_order() > 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)
+ return (ts > other_ts) ||
+ ((ts == other_ts) && (time_received_ > entry->time_received_));
}
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_;
@@ -150,6 +158,6 @@ class AuthTokenTable {
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 e30b32d9..537fe3d1 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 00000000..96a1a048
--- /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 00000000..db55062e
--- /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 00000000..dc8ed501
--- /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
index 0dcbadd3..17486531 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/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl b/keystore/binder/android/security/keymaster/KeyCharacteristics.aidl
new file mode 100644
index 00000000..32e75ad2
--- /dev/null
+++ b/keystore/binder/android/security/keymaster/KeyCharacteristics.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.keymaster;
+
+/* @hide */
+parcelable KeyCharacteristics cpp_header "keystore/KeyCharacteristics.h";
diff --git a/keystore/binder/android/security/keymaster/KeymasterArguments.aidl b/keystore/binder/android/security/keymaster/KeymasterArguments.aidl
new file mode 100644
index 00000000..44d9f095
--- /dev/null
+++ b/keystore/binder/android/security/keymaster/KeymasterArguments.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.keymaster;
+
+/* @hide */
+parcelable KeymasterArguments cpp_header "keystore/KeymasterArguments.h";
diff --git a/keystore/binder/android/security/keymaster/KeymasterBlob.aidl b/keystore/binder/android/security/keymaster/KeymasterBlob.aidl
new file mode 100644
index 00000000..5c5db9ec
--- /dev/null
+++ b/keystore/binder/android/security/keymaster/KeymasterBlob.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.keymaster;
+
+/* @hide */
+parcelable KeymasterBlob cpp_header "keystore/KeymasterBlob.h";
diff --git a/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl b/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl
new file mode 100644
index 00000000..ddb5cae1
--- /dev/null
+++ b/keystore/binder/android/security/keymaster/KeymasterCertificateChain.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+/* @hide */
+parcelable KeymasterCertificateChain cpp_header "keystore/KeymasterCertificateChain.h";
diff --git a/keystore/binder/android/security/keymaster/OperationResult.aidl b/keystore/binder/android/security/keymaster/OperationResult.aidl
new file mode 100644
index 00000000..db689d46
--- /dev/null
+++ b/keystore/binder/android/security/keymaster/OperationResult.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.keymaster;
+
+/* @hide */
+parcelable OperationResult cpp_header "keystore/OperationResult.h";
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 625d0576..d21c6914 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -114,13 +114,13 @@ ResponseCode AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const
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);
@@ -327,3 +327,12 @@ ResponseCode Blob::readBlob(const std::string& filename, const uint8_t* aes_key,
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 53350379..665e07ac 100644
--- a/keystore/blob.h
+++ b/keystore/blob.h
@@ -22,6 +22,7 @@
#include <openssl/aes.h>
#include <openssl/md5.h>
+#include <keystore/keymaster_types.h>
#include <keystore/keystore.h>
constexpr size_t kValueSize = 32768;
@@ -117,6 +118,9 @@ class Blob {
BlobType getType() const { return BlobType(mBlob.type); }
void setType(BlobType type) { mBlob.type = uint8_t(type); }
+ keystore::SecurityLevel getSecurityLevel() const;
+ void setSecurityLevel(keystore::SecurityLevel);
+
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);
diff --git a/keystore/confirmation_manager.cpp b/keystore/confirmation_manager.cpp
new file mode 100644
index 00000000..0dee4aaa
--- /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 00000000..46b623cb
--- /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 00000000..12c20fae
--- /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/include/keystore/ExportResult.h b/keystore/include/keystore/ExportResult.h
new file mode 100644
index 00000000..b5489427
--- /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 a0456796..00000000
--- 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 a7ce210c..c612929a 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 @@ class KeyAttestationApplicationId : public Parcelable {
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 @@ class KeyAttestationApplicationId : public Parcelable {
} // 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 b938e83c..92d48632 100644
--- a/keystore/include/keystore/KeyAttestationPackageInfo.h
+++ b/keystore/include/keystore/KeyAttestationPackageInfo.h
@@ -15,13 +15,16 @@
#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
-#include "Signature.h"
-#include "utils.h"
-#include <binder/Parcelable.h>
-#include <memory>
#include <stdint.h>
+
+#include <memory>
#include <vector>
+#include <binder/Parcelable.h>
+
+#include "Signature.h"
+#include "utils.h"
+
namespace android {
namespace security {
namespace keymaster {
@@ -30,20 +33,27 @@ class KeyAttestationPackageInfo : public Parcelable {
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 00000000..7fc89c60
--- /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 00000000..99074f8c
--- /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 00000000..fc849bd0
--- /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 00000000..132862c3
--- /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 00000000..a5e68f2b
--- /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 00000000..c0a8b0a2
--- /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 00000000..2ceda9a4
--- /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 59b77bf7..3c996bb9 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 0e57a196..00000000
--- 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 05a33cd9..00000000
--- 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 00000000..f3c69079
--- /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 72603636..07f645fd 100644
--- a/keystore/include/keystore/keystore.h
+++ b/keystore/include/keystore/keystore.h
@@ -26,6 +26,7 @@ enum State {
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 @@ enum KeyStoreFlag : uint8_t {
// 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 2ba7fd49..d6a48076 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 @@ class KeystoreClient {
// 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 @@ class KeystoreClient {
// 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 @@ class KeystoreClient {
// [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 @@ class KeystoreClient {
// |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 eb022755..9edd0824 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 @@ class KeystoreClientImpl : public KeystoreClient {
// 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 @@ class KeystoreClientImpl : public KeystoreClient {
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 @@ class KeystoreClientImpl : public KeystoreClient {
// 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 @@ class KeystoreClientImpl : public KeystoreClient {
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 2d1f4996..b16367fb 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 4bddd707..4c3d8384 100644
--- a/keystore/include/keystore/keystore_get.h
+++ b/keystore/include/keystore/keystore_get.h
@@ -30,7 +30,7 @@ extern "C" {
* 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 3c64d2af..781b153a 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 @@ inline static ErrorCode ksHandleHidlError(const Return<void>& error, Msgs&&... m
#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 @@ inline static hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token
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 70380c39..fa4a224f 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 @@ class KeyStoreServiceReturnCode {
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 @@ class KeyStoreServiceReturnCode {
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 @@ class KeyStoreNativeReturnCode {
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 @@ class KeyStoreNativeReturnCode {
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 00000000..0b1a3980
--- /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 00000000..3bf8c060
--- /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 00000000..a2f6a243
--- /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 38cea69b..dcdaac0c 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); }
@@ -124,55 +142,53 @@ KeyStoreServiceReturnCode updateParamsForAttestation(uid_t callingUid, Authoriza
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) {
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) {
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) {
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);
@@ -181,72 +197,93 @@ KeyStoreServiceReturnCode KeyStoreService::insert(const String16& name,
Blob keyBlob(&item[0], item.size(), nullptr, 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) {
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) {
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) {
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) {
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) {
if (!checkBinderPermission(P_PASSWORD)) {
- return ResponseCode::PERMISSION_DENIED;
+ *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
+ return Status::ok();
}
const String8 password8(password);
@@ -257,31 +294,37 @@ KeyStoreServiceReturnCode KeyStoreService::onUserPasswordChanged(int32_t userId,
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) {
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.
@@ -295,39 +338,48 @@ KeyStoreServiceReturnCode KeyStoreService::onUserAdded(int32_t userId, int32_t p
// 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) {
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) {
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) {
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);
@@ -343,30 +395,38 @@ KeyStoreServiceReturnCode KeyStoreService::unlock(int32_t userId, const String16
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) {
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) {
+ 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;
@@ -379,7 +439,8 @@ KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_
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;
@@ -390,13 +451,15 @@ KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_
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 != nullptr) {
@@ -404,16 +467,19 @@ KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_
reinterpret_cast<const unsigned char*>(expArg->data()), expArg->size(), nullptr));
if (pubExpBn.get() == nullptr) {
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);
@@ -421,31 +487,36 @@ KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_
}
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*/ nullptr);
- 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) {
const uint8_t* ptr = &data[0];
Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(nullptr, &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;
@@ -459,33 +530,47 @@ KeyStoreServiceReturnCode KeyStoreService::import(const String16& name,
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*/ nullptr);
+ int import_result;
+ auto rc = importKey(name, KeymasterArguments(params.hidl_data()),
+ static_cast<int32_t>(KeyFormat::PKCS8), data, targetUid, flags,
+ /*outCharacteristics*/ nullptr, &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) {
if (!checkBinderPermission(P_SIGN)) {
- return ResponseCode::PERMISSION_DENIED;
+ return Status::fromServiceSpecificError(
+ static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
+ }
+ 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));
}
- return doLegacySignVerify(name, data, out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
+ *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) {
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();
}
/*
@@ -499,72 +584,88 @@ KeyStoreServiceReturnCode KeyStoreService::verify(const String16& name,
* "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) {
- ExportResult result;
- exportKey(name, KeyFormat::X509, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF, &result);
+Status KeyStoreService::get_pubkey(const String16& name, ::std::vector<uint8_t>* pubKey) {
+ 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) {
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) {
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) {
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;
@@ -572,82 +673,24 @@ int64_t KeyStoreService::getmtime(const String16& name, int32_t uid) {
close(fd);
if (ret == -1) {
ALOGW("could not stat %s for getmtime", filename.value().string());
- return -1L;
- }
-
- return static_cast<int64_t>(s.st_mtime);
-}
-
-// 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) {
- 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;
+ *time = -1L;
+ return Status::ok();
}
- 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));
+ *time = static_cast<int64_t>(s.st_mtime);
+ return Status::ok();
}
-int32_t KeyStoreService::is_hardware_backed(const String16& keyType) {
- return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
+Status KeyStoreService::is_hardware_backed(const String16& keyType, int32_t* aidl_return) {
+ *aidl_return = static_cast<int32_t>(mKeyStore->isHardwareBacked(keyType) ? 1 : 0);
+ return Status::ok();
}
-KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
+Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* aidl_return) {
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);
@@ -656,7 +699,8 @@ KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
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++) {
@@ -680,61 +724,93 @@ KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
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) {
- const auto& device = mKeyStore->getDevice();
- return KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy));
+Status KeyStoreService::addRngEntropy(const ::std::vector<uint8_t>& entropy, int32_t flags,
+ int32_t* aidl_return) {
+ 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) {
+ // 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 (!checkBinderPermission(P_GEN_UNIQUE_ID)) return ResponseCode::PERMISSION_DENIED;
+ 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()) {
+ *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(), nullptr, 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);
@@ -742,24 +818,49 @@ KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
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;
+ 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();
+ }
+ }
+
auto fallback = mKeyStore->getFallbackDevice();
- if (!fallback.isOk()) {
- return error;
+ if (!fallback) {
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
}
- rc = KS_HANDLE_HIDL_ERROR(fallback.value()->generateKey(params, hidl_cb));
+ 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:
@@ -769,23 +870,28 @@ KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
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(), nullptr, 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) {
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);
@@ -793,7 +899,8 @@ KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint
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;
@@ -809,7 +916,8 @@ KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint
*/
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)
@@ -818,94 +926,122 @@ KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint
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) {
+
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(), nullptr, 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);
@@ -913,57 +1049,91 @@ KeyStoreService::importKey(const String16& name, const hidl_vec<KeyParameter>& p
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;
+ 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();
+ }
+ }
+
auto fallback = mKeyStore->getFallbackDevice();
- if (!fallback.isOk()) {
- return error;
+ if (!fallback) {
+ *aidl_return = static_cast<int32_t>(error);
+ return Status::ok();
}
- rc = KS_HANDLE_HIDL_ERROR(fallback.value()->importKey(params, format, keyData, hidlCb));
+ 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(), nullptr, 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) {
uid_t targetUid = getEffectiveUid(uid);
uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!is_granted_to(callingUid, targetUid)) {
ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid);
result->resultCode = ResponseCode::PERMISSION_DENIED;
- return;
+ return Status::ok();
}
Blob keyBlob;
@@ -971,21 +1141,24 @@ void KeyStoreService::exportKey(const String16& name, KeyFormat format,
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()) {
@@ -994,83 +1167,77 @@ void KeyStoreService::exportKey(const String16& name, KeyFormat format,
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));
- }
-}
+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) {
+ auto keyPurpose = static_cast<KeyPurpose>(purpose);
-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) {
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 = nullptr;
-
// Merge these characteristics with the ones cached when the key was generated or imported
Blob charBlob;
AuthorizationSet persistedCharacteristics;
@@ -1088,28 +1255,30 @@ void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, K
// 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();
}
}
@@ -1118,18 +1287,19 @@ void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, K
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
@@ -1145,13 +1315,17 @@ void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, K
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));
+ ErrorCode rc =
+ KS_HANDLE_HIDL_ERROR(dev->begin(keyPurpose, key, opParams.hidl_data(), authToken, hidlCb));
if (rc != ErrorCode::OK) {
ALOGW("Got error %d from begin()", rc);
}
@@ -1163,24 +1337,44 @@ void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, K
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 != ErrorCode::OK) {
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 != ErrorCode::OK) result->resultCode = rc;
+ if (result->resultCode != ErrorCode::OK) 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
@@ -1191,234 +1385,254 @@ void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, K
}
// 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) {
- if (!checkAllowedOperationParams(params)) {
- result->resultCode = ErrorCode::INVALID_ARGUMENT;
+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;
}
- 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;
+
+ hidl_vec<uint8_t> confirmationToken = mConfirmationManager->getLatestConfirmationToken();
+ if (confirmationToken.size() == 0) {
return;
}
- AuthorizationSet opParams = params;
- result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
- if (!result->resultCode.isOk()) {
- 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) {
+ 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(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());
+
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();
+
+ 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;
- }
+ if (!rc.isOk()) result->resultCode = rc;
+
+ 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) {
- 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)) {
+Status KeyStoreService::finish(const sp<IBinder>& token, const KeymasterArguments& params,
+ const ::std::vector<uint8_t>& signature,
+ const ::std::vector<uint8_t>& entropy, OperationResult* result) {
+ 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) {
- km_device_t dev;
- uint64_t handle;
- KeyPurpose purpose;
- km_id_t keyid;
- if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, nullptr)) {
- return ErrorCode::INVALID_OPERATION_HANDLE;
+Status KeyStoreService::abort(const sp<IBinder>& token, int32_t* aidl_return) {
+ 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) {
- 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 = nullptr;
- mOperationMap.getOperationAuthToken(token, &authToken);
+Status KeyStoreService::isOperationAuthorized(const sp<IBinder>& token, bool* aidl_return) {
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) {
+
// 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;
- }
-
- 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;
+ *aidl_return = static_cast<int32_t>(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
+ return Status::ok();
+ }
+
+ 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:
+ result |= ID_ATTESTATION_REQUEST_GENERIC_INFO;
+ break;
+ case Tag::ATTESTATION_ID_IMEI:
+ case Tag::ATTESTATION_ID_MEID:
case Tag::ATTESTATION_ID_SERIAL:
- return true;
- default:
+ 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) {
- if (!outChain) {
- return ErrorCode::OUTPUT_PARAMETER_NULL;
+Status KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
+ ::android::security::keymaster::KeymasterCertificateChain* chain,
+ int32_t* aidl_return) {
+ // 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();
}
- if (!checkAllowedOperationParams(params)) {
- return ErrorCode::INVALID_ARGUMENT;
- }
+ uid_t callingUid = IPCThreadState::self()->getCallingUid();
- if (isDeviceIdAttestationRequested(params)) {
- // There is a dedicated attestDeviceIds() method for device ID attestation.
- return ErrorCode::INVALID_ARGUMENT;
+ 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();
}
- uid_t callingUid = IPCThreadState::self()->getCallingUid();
-
- 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();
}
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;
@@ -1427,54 +1641,73 @@ KeyStoreServiceReturnCode KeyStoreService::attestKey(const String16& name,
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) {
- if (!outChain) {
- return ErrorCode::OUTPUT_PARAMETER_NULL;
- }
+Status
+KeyStoreService::attestDeviceIds(const KeymasterArguments& params,
+ ::android::security::keymaster::KeymasterCertificateChain* chain,
+ int32_t* aidl_return) {
+ // 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 == nullptr) {
- 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;
+ SecurityLevel securityLevel;
+ std::tie(dev, securityLevel) = mKeyStore->getMostSecureDevice();
+
+ if (securityLevel == SecurityLevel::SOFTWARE) {
+ *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);
@@ -1482,7 +1715,7 @@ KeyStoreServiceReturnCode KeyStoreService::attestDeviceIds(const hidl_vec<KeyPar
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()) {
@@ -1493,10 +1726,12 @@ KeyStoreServiceReturnCode KeyStoreService::attestDeviceIds(const hidl_vec<KeyPar
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.
@@ -1505,27 +1740,140 @@ KeyStoreServiceReturnCode KeyStoreService::attestDeviceIds(const hidl_vec<KeyPar
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) {
// 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) {
+
+ 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(), nullptr, 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(), nullptr, 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) {
+ return mConfirmationManager->presentConfirmationPrompt(listener, promptText, extraData, locale,
+ uiOptionsAsFlags, aidl_return);
+}
+
+Status KeyStoreService::cancelConfirmationPrompt(const sp<IBinder>& listener,
+ int32_t* aidl_return) {
+ return mConfirmationManager->cancelConfirmationPrompt(listener, aidl_return);
+}
+
+Status KeyStoreService::isConfirmationPromptSupported(bool* aidl_return) {
+ return mConfirmationManager->isConfirmationPromptSupported(aidl_return);
}
/**
@@ -1537,7 +1885,8 @@ bool KeyStoreService::pruneOperation() {
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;
@@ -1639,14 +1988,13 @@ bool KeyStoreService::isKeystoreUnlocked(State state) {
}
/**
- * 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:
@@ -1657,14 +2005,14 @@ bool KeyStoreService::checkAllowedOperationParams(const hidl_vec<KeyParameter>&
}
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();
}
@@ -1679,7 +2027,8 @@ ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>&
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;
}
@@ -1696,36 +2045,44 @@ ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>&
* 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(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;
- 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);
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()};
}
/**
@@ -1739,29 +2096,23 @@ KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics
* 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};
}
/**
@@ -1769,21 +2120,19 @@ KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const s
* 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 {};
}
@@ -1794,9 +2143,11 @@ void KeyStoreService::addLegacyBeginParams(const String16& name, AuthorizationSe
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;
@@ -1822,8 +2173,8 @@ KeyStoreServiceReturnCode KeyStoreService::doLegacySignVerify(const String16& na
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");
@@ -1839,7 +2190,7 @@ KeyStoreServiceReturnCode KeyStoreService::doLegacySignVerify(const String16& na
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);
@@ -1856,7 +2207,8 @@ KeyStoreServiceReturnCode KeyStoreService::doLegacySignVerify(const String16& na
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);
@@ -1879,19 +2231,23 @@ KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name,
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;
}
@@ -1908,7 +2264,7 @@ KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name,
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());
@@ -1932,4 +2288,15 @@ KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name,
return error;
}
+Status KeyStoreService::onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
+ int32_t* aidl_return) {
+ 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 4060bd13..00563422 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 @@ class KeyStoreService : public android::BnKeystoreService, public android::IBind
* "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::String16 grant(const android::String16& name, int32_t granteeUid) override;
- KeyStoreServiceReturnCode ungrant(const android::String16& name, int32_t granteeUid) override;
-
- int64_t getmtime(const android::String16& name, int32_t uid) 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 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::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;
+
+ ::android::binder::Status presentConfirmationPrompt(
+ const ::android::sp<::android::IBinder>& listener, const ::android::String16& promptText,
+ const ::std::vector<uint8_t>& extraData, const ::android::String16& locale,
+ int32_t uiOptionsAsFlags, int32_t* _aidl_return) override;
+ ::android::binder::Status
+ cancelConfirmationPrompt(const ::android::sp<::android::IBinder>& listener,
+ int32_t* _aidl_return) override;
+ ::android::binder::Status isConfirmationPromptSupported(bool* _aidl_return) override;
+
+ ::android::binder::Status onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
+ int32_t* _aidl_return);
private:
static const int32_t UID_SELF = -1;
@@ -191,37 +235,34 @@ class KeyStoreService : public android::BnKeystoreService, public android::IBind
*/
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,10 +289,18 @@ class KeyStoreService : public android::BnKeystoreService, public android::IBind
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;
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 4cee57db..5a6e591e 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 @@ KeymasterEnforcement::~KeymasterEnforcement() {
ErrorCode KeymasterEnforcement::AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
const AuthorizationSet& auth_set,
const AuthorizationSet& operation_params,
+ const HardwareAuthToken& auth_token,
uint64_t op_handle, bool is_begin_operation) {
if (is_public_key_algorithm(auth_set)) {
switch (purpose) {
@@ -125,23 +128,23 @@ ErrorCode KeymasterEnforcement::AuthorizeOperation(const KeyPurpose purpose, con
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 @@ ErrorCode KeymasterEnforcement::AuthorizeUpdateOrFinish(const AuthorizationSet&
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::AuthorizeUpdateOrFinish(const AuthorizationSet&
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 @@ ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const k
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 @@ ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const k
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 @@ ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const k
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 @@ ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const k
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 @@ ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const k
}
}
+ 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 @@ template <typename IntType> inline IntType ntoh(const IntType& value) {
}
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 @@ bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set,
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 @@ bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set,
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 @@ bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set,
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 4f22f014..6e6c54f2 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 @@ class KeymasterEnforcement {
*/
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 @@ class KeymasterEnforcement {
*/
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 @@ class KeymasterEnforcement {
* 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 @@ class KeymasterEnforcement {
/*
* 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 @@ class KeymasterEnforcement {
* 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 5dac9377..132039a8 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 3137ae1b..db9b9838 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 @@ android::status_t writeKeymasterBlob(const hidl_vec<uint8_t>& blob, android::Par
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 @@ NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in) {
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 @@ NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in) {
}
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 @@ android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::
}
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 @@ android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params,
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 @@ android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params,
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 @@ hidl_vec<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel
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 @@ android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>
}
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 fcd02ae3..13edbd25 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 @@ android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::
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 830482bb..3d34ac56 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 android {
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_SEQUENCE(KM_ATTESTATION_APPLICATION_ID) = {
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 @@ status_t build_attestation_package_info(const KeyAttestationPackageInfo& pinfo,
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 @@ void unused_functions_silencer() {
} // 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 8b3be313..d5a8afa1 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[] = {
nullptr,
@@ -48,7 +50,8 @@ static const char* responses[] = {
#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 @@ static const char* responses[] = {
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 @@ static const char* responses[] = {
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 @@ static const char* responses[] = {
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 @@ static const char* responses[] = {
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 @@ static const char* responses[] = {
} \
} 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 @@ static const char* responses[] = {
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 @@ static const char* responses[] = {
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 @@ static const char* responses[] = {
} 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 dac01204..157417f8 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 @@ void PrintUsageAndExit() {
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 @@ void PrintUsageAndExit() {
" 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 @@ bool TestKey(const std::string& name, bool required, const AuthorizationSet& par
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 @@ AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
.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 std::move(parameters);
}
@@ -142,9 +162,7 @@ AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) {
.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 std::move(parameters);
}
@@ -205,7 +223,8 @@ int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) {
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 @@ void WriteFile(const std::string& filename, const std::string& content) {
}
}
-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 @@ int GenerateKey(const std::string& name) {
.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 @@ int GetCharacteristics(const std::string& name) {
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 @@ int SignAndVerify(const std::string& name) {
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 @@ int SignAndVerify(const std::string& name) {
// 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 SignAndVerify(const std::string& name) {
}
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 @@ int Decrypt(const std::string& key_name, const std::string& input_filename,
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 == nullptr) {
+ 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 @@ int main(int argc, char** argv) {
} 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 @@ int main(int argc, char** argv) {
} 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 f9df1349..6d998ada 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 kAESKeySize = 256; // bits
constexpr uint32_t kHMACKeySize = 256; // bits
constexpr uint32_t kHMACOutputSize = 256; // bits
+using android::String16;
+using android::security::keymaster::ExportResult;
+using android::security::keymaster::OperationResult;
+using keystore::AuthorizationSet;
+using keystore::AuthorizationSetBuilder;
+using keystore::KeyCharacteristics;
+using keystore::KeyStoreServiceReturnCode;
} // namespace
namespace keystore {
@@ -56,22 +57,22 @@ namespace keystore {
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 @@ bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name,
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 @@ bool KeystoreClientImpl::oneShotOperation(KeyPurpose purpose, const std::string&
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 @@ bool KeystoreClientImpl::oneShotOperation(KeyPurpose purpose, const std::string&
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 @@ KeystoreClientImpl::getKeyCharacteristics(const std::string& key_name,
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 @@ KeyStoreNativeReturnCode KeystoreClientImpl::beginOperation(KeyPurpose purpose,
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 @@ KeyStoreNativeReturnCode KeystoreClientImpl::updateOperation(uint64_t handle,
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 @@ KeyStoreNativeReturnCode KeystoreClientImpl::abortOperation(uint64_t handle) {
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;
}
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 @@ bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name
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 @@ bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name
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 @@ bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_
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 @@ bool KeystoreClientImpl::verifyEncryptionKeyAttributes(const std::string& key_na
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 @@ bool KeystoreClientImpl::verifyAuthenticationKeyAttributes(const std::string& ke
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 4ab65558..fec36c4c 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 == nullptr) {
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 @@ ssize_t keystore_get(const char *key, size_t keyLength, uint8_t** value) {
memcpy(*value, &result[0], result.size());
}
return result.size();
-
}
diff --git a/keystore/keystore_keymaster_enforcement.h b/keystore/keystore_keymaster_enforcement.h
index 0abe0700..e7515a1f 100644
--- a/keystore/keystore_keymaster_enforcement.h
+++ b/keystore/keystore_keymaster_enforcement.h
@@ -73,17 +73,30 @@ class KeystoreKeymasterEnforcement : public KeymasterEnforcement {
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 a739c5e1..82d4e693 100644
--- a/keystore/keystore_main.cpp
+++ b/keystore/keystore_main.cpp
@@ -14,25 +14,28 @@
* 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 "KeyStore.h"
#include "entropy.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 +43,124 @@
* 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;
+
+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;
+}
-/**
- * TODO implement keystore daemon using binderized keymaster HAL.
- */
+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;
- }
+ CHECK(entropy.open()) << "Failed to open entropy source.";
- 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;
- }
+ auto kmDevices = initializeKeymasters();
- if (configure_selinux() == -1) {
- return -1;
- }
+ CHECK(kmDevices[SecurityLevel::SOFTWARE]) << "Missing software Keymaster device";
+ CHECK(kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT])
+ << "Error no viable keymaster device found";
- bool allowNewFallbackDevice = false;
+ CHECK(configure_selinux() != -1) << "Failed to configure SELinux.";
- 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;
- }));
+ auto halVersion = kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]->halVersion();
- if (!rc.isOk()) {
- return -1;
- }
+ // 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;
- KeyStore keyStore(&entropy, dev, fallback, allowNewFallbackDevice);
+ keystore::KeyStore keyStore(&entropy, 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 +170,7 @@ int main(int argc, char* argv[]) {
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 278348af..00000000
--- 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 b1777d0e..e5ae29a9 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 @@ void add_legacy_key_authorizations(int keyType, keystore::AuthorizationSet* para
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_app_id(uid_t uid) {
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 f970559f..3bc9c010 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 @@ struct PKCS8_PRIV_KEY_INFO_Delete {
};
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);
+
+SecurityLevel flagsToSecurityLevel(int32_t flags);
+uint32_t securityLevelToFlags(SecurityLevel secLevel);
-} // namespace keystore
+} // namespace keystore
#endif // KEYSTORE_KEYSTORE_UTILS_H_
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index fdb3c649..40690608 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 @@ void OperationMap::updateLru(const sp<IBinder>& token) {
}
}
-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 @@ void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IB
}
bool OperationMap::hasPruneableOperation() const {
- return mLru.size() != 0;
+ return !mLru.empty();
}
size_t OperationMap::getPruneableOperationCount() const {
@@ -110,49 +91,29 @@ size_t OperationMap::getPruneableOperationCount() const {
}
sp<IBinder> OperationMap::getOldestPruneableOperation() {
- if (!hasPruneableOperation()) {
- return sp<IBinder>(nullptr);
- }
- 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 e69b43af..4888bfac 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 @@ using ::android::sp;
*/
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 00000000..37b4cbba
--- /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 00000000..77e1b73c
--- /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 00000000..bf461b48
--- /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 00000000..00f1fe2b
--- /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/tests/Android.bp b/keystore/tests/Android.bp
index cc896818..73459c17 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -1,20 +1,30 @@
// Unit test for AuthTokenTable
-// TODO: enable after fixing b/68149839
-/*
+
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",
],
- srcs: ["auth_token_table_test.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/auth_token_formatting_test.cpp b/keystore/tests/auth_token_formatting_test.cpp
new file mode 100644
index 00000000..0ecc4cca
--- /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 1b31cf51..29aa71ed 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 @@ TEST(AuthTokenTableTest, Create) {
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 std::move(builder);
}
// Tests obviously run so fast that a real-time clock with a one-second granularity rarely changes
@@ -102,26 +96,30 @@ TEST(AuthTokenTableTest, SimpleAddAndFindTokens) {
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 @@ TEST(AuthTokenTableTest, FlushTable) {
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 @@ TEST(AuthTokenTableTest, TableOverflow) {
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 @@ TEST(AuthTokenTableTest, TableOverflow) {
// 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 @@ TEST(AuthTokenTableTest, TableOverflow) {
// 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 @@ TEST(AuthTokenTableTest, TokenExpired) {
// 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, MarkNonexistentEntryCompleted) {
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 @@ TEST(AuthTokenTableTest, SupersededEntries) {
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 @@ TEST(AuthTokenTableTest, SupersededEntries) {
// 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 @@ TEST(AuthTokenTableTest, SupersededEntries) {
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 @@ TEST(AuthTokenTableTest, SupersededEntries) {
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 @@ TEST(AuthTokenTableTest, SupersededEntries) {
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 00000000..f56b5099
--- /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/softkeymaster/Android.bp b/softkeymaster/Android.bp
deleted file mode 100644
index 3d27ecbc..00000000
--- a/softkeymaster/Android.bp
+++ /dev/null
@@ -1,40 +0,0 @@
-cc_defaults {
- name: "softkeymaster_defaults",
-
- cflags: [
- "-Wall",
- "-Werror",
- "-fvisibility=hidden",
- ],
-}
-
-cc_library_shared {
- name: "keystore.default",
- defaults: ["softkeymaster_defaults"],
-
- relative_install_path: "hw",
- srcs: ["module.cpp"],
- include_dirs: ["system/security/keystore"],
- shared_libs: [
- "libcrypto",
- "libkeystore_binder",
- "liblog",
- "libsoftkeymaster",
- ],
-}
-
-cc_library_shared {
- name: "libsoftkeymaster",
- defaults: ["softkeymaster_defaults"],
-
- srcs: ["keymaster_openssl.cpp"],
- include_dirs: ["system/security/keystore"],
- local_include_dirs: [],
- shared_libs: [
- "libcrypto",
- "libkeystore_binder",
- "liblog",
- ],
-
- export_include_dirs: ["include"],
-}
diff --git a/softkeymaster/include/keymaster/softkeymaster.h b/softkeymaster/include/keymaster/softkeymaster.h
deleted file mode 100644
index e86ba3de..00000000
--- 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 3f5f1f56..00000000
--- 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(nullptr);
-}
-
-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, nullptr);
-
- 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() == nullptr) {
- 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 == nullptr) {
- ALOGE("supplied key blob was NULL");
- return nullptr;
- }
-
- 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 nullptr;
- }
-
- if (!is_softkey(p, keyBlobLength)) {
- ALOGE("cannot read key; it was not made by this keymaster");
- return nullptr;
- }
- 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 nullptr;
- }
-
- p += publicLen;
- if (end - p < 2) {
- ALOGE("private key truncated");
- return nullptr;
- }
- 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 nullptr;
- }
-
- Unique_EVP_PKEY pkey(d2i_PrivateKey(type, nullptr, &p, privateLen));
- if (pkey.get() == nullptr) {
- logOpenSSLError("unwrap_key");
- return nullptr;
- }
-
- 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 == nullptr ||
- dsa_params->prime_p == nullptr || dsa_params->prime_q == nullptr) {
- if (DSA_generate_parameters_ex(dsa.get(), dsa_params->key_size, nullptr, 0, nullptr, nullptr,
- nullptr) != 1) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
- } else {
- dsa->g = BN_bin2bn(dsa_params->generator, dsa_params->generator_len, nullptr);
- if (dsa->g == nullptr) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
-
- dsa->p = BN_bin2bn(dsa_params->prime_p, dsa_params->prime_p_len, nullptr);
- if (dsa->p == nullptr) {
- logOpenSSLError("generate_dsa_keypair");
- return -1;
- }
-
- dsa->q = BN_bin2bn(dsa_params->prime_q, dsa_params->prime_q_len, nullptr);
- if (dsa->q == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- logOpenSSLError("generate_rsa_keypair");
- return -1;
- }
-
- if (!RSA_generate_key_ex(rsa.get(), rsa_params->modulus_size, bn.get(), nullptr) ||
- 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() == nullptr) {
- logOpenSSLError("openssl_generate_keypair");
- return -1;
- }
-
- if (key_params == nullptr) {
- 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 == nullptr) {
- ALOGW("input key == NULL");
- return -1;
- } else if (key_blob == nullptr || key_blob_length == nullptr) {
- ALOGW("output key blob or length == NULL");
- return -1;
- }
-
- Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(nullptr, &key, key_length));
- if (pkcs8.get() == nullptr) {
- logOpenSSLError("openssl_import_keypair");
- return -1;
- }
-
- /* assign to EVP */
- Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
- if (pkey.get() == nullptr) {
- 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 == nullptr || x509_data_length == nullptr) {
- ALOGW("output public key buffer == NULL");
- return -1;
- }
-
- Unique_EVP_PKEY pkey(unwrap_key(key_blob, key_blob_length));
- if (pkey.get() == nullptr) {
- return -1;
- }
-
- int len = i2d_PUBKEY(pkey.get(), nullptr);
- 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() == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- logOpenSSLError("openssl_sign_rsa");
- return -1;
- }
-
- std::unique_ptr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(dataLength)));
- if (signedDataPtr.get() == nullptr) {
- 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 == nullptr) {
- ALOGW("input data to sign == NULL");
- return -1;
- } else if (signedData == nullptr || signedDataLength == nullptr) {
- ALOGW("output signature buffer == NULL");
- return -1;
- }
-
- Unique_EVP_PKEY pkey(unwrap_key(keyBlob, keyBlobLength));
- if (pkey.get() == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- 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() == nullptr) {
- logOpenSSLError("openssl_verify_data");
- return -1;
- }
-
- std::unique_ptr<uint8_t[]> dataPtr(new uint8_t[signedDataLength]);
- if (dataPtr.get() == nullptr) {
- 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 == nullptr || signature == nullptr) {
- ALOGW("data or signature buffers == NULL");
- return -1;
- }
-
- Unique_EVP_PKEY pkey(unwrap_key(keyBlob, keyBlobLength));
- if (pkey.get() == nullptr) {
- 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() == nullptr)
- 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 = nullptr;
- dev->delete_all = nullptr;
- 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 = nullptr,
- .reserved = {},
- },
-};