summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Krahn <dkrahn@google.com>2015-09-22 16:21:04 -0700
committerGaurav Shah <gauravsh@google.com>2015-11-02 09:12:39 -0800
commit69a3dbc2bbbe0b304eb91376ff7f79c8bde995a1 (patch)
treec46a81a11bd45bfc4018811f2b310e7776d667be
parent91e439b0e86d42032d8b53200f0f9557d3e7ef17 (diff)
downloadsecurity-69a3dbc2bbbe0b304eb91376ff7f79c8bde995a1.tar.gz
Create a KeystoreClient class.
KeystoreClient is designed to give native brillo services convenient access to keystore services. This CL also includes a command line tool that uses the KeystoreClient interface. This was used for testing but can also be enhanced to be generally useful. BUG: 23528174 TEST=manual tests using keystore_cli_v2 Change-Id: I6266d98cfc7c4936f803a8133020c032bc519a5b
-rw-r--r--keystore/Android.mk29
-rw-r--r--keystore/include/keystore/keystore_client.h153
-rw-r--r--keystore/include/keystore/keystore_client_impl.h92
-rw-r--r--keystore/include/keystore/keystore_client_mock.h77
-rw-r--r--keystore/keystore_cli_v2.cpp217
-rw-r--r--keystore/keystore_client_impl.cpp251
6 files changed, 816 insertions, 3 deletions
diff --git a/keystore/Android.mk b/keystore/Android.mk
index 3babd1d3..6c25b892 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -38,7 +38,6 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_MODULE := keystore
LOCAL_MODULE_TAGS := optional
LOCAL_INIT_RC := keystore.rc
-LOCAL_C_INCLUES := system/keymaster/
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_EXECUTABLE)
@@ -54,14 +53,38 @@ LOCAL_MODULE_TAGS := debug
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_EXECUTABLE)
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_CFLAGS := -Wall -Wextra -Werror
+LOCAL_SRC_FILES := keystore_cli_v2.cpp
+LOCAL_SHARED_LIBRARIES := \
+ libchrome \
+ libkeymaster_messages \
+ libkeystore_binder
+LOCAL_MODULE := keystore_cli_v2
+LOCAL_MODULE_TAGS := debug
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_EXECUTABLE)
+
# Library for keystore clients
include $(CLEAR_VARS)
ifeq ($(USE_32_BIT_KEYSTORE), true)
LOCAL_MULTILIB := 32
endif
LOCAL_CFLAGS := -Wall -Wextra -Werror
-LOCAL_SRC_FILES := IKeystoreService.cpp keystore_get.cpp keyblob_utils.cpp
-LOCAL_SHARED_LIBRARIES := libbinder libutils liblog libsoftkeymasterdevice
+LOCAL_SRC_FILES := \
+ IKeystoreService.cpp \
+ keyblob_utils.cpp \
+ keystore_client_impl.cpp \
+ keystore_get.cpp
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libkeymaster_messages \
+ liblog \
+ libsoftkeymasterdevice \
+ libutils
LOCAL_MODULE := libkeystore_binder
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
diff --git a/keystore/include/keystore/keystore_client.h b/keystore/include/keystore/keystore_client.h
new file mode 100644
index 00000000..f87e9af0
--- /dev/null
+++ b/keystore/include/keystore/keystore_client.h
@@ -0,0 +1,153 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_KEYSTORE_CLIENT_H_
+#define KEYSTORE_KEYSTORE_CLIENT_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "hardware/keymaster_defs.h"
+#include "keymaster/authorization_set.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)
+// - use std data types
+// - encourage the use of keymaster::AuthorizationSet[Builder]
+// - be convenient for native services integrating with keystore
+// - be safely mocked for unit testing (e.g. pure virtual methods)
+//
+// Example usage:
+// KeystoreClient* keystore = new KeyStoreClientImpl();
+// keystore->AddRandomNumberGeneratorEntropy("unpredictable");
+//
+// Notes on error codes:
+// Keystore binder methods return a variety of values including ResponseCode
+// values defined in keystore.h, keymaster_error_t values defined in
+// keymaster_defs.h, or just 0 or -1 (both of which conflict with
+// keymaster_error_t). The methods in this class converge on a single success
+// indicator for convenience. KM_ERROR_OK was chosen over ::NO_ERROR for two
+// reasons:
+// 1) KM_ERROR_OK is 0, which is a common convention for success, is the gmock
+// default, and allows error checks like 'if (error) {...'.
+// 2) Although both pollute the global namespace, KM_ERROR_OK has a prefix per
+// C convention and hopefully clients can use this interface without
+// needing to include 'keystore.h' directly.
+class KeystoreClient {
+ public:
+ KeystoreClient() = default;
+ virtual ~KeystoreClient() = default;
+
+ // Adds |entropy| to the random number generator. Returns KM_ERROR_OK on
+ // success and a Keystore ResponseCode or keymaster_error_t on failure.
+ virtual int32_t addRandomNumberGeneratorEntropy(const std::string& entropy) = 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 int32_t generateKey(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::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
+ // ResponseCode or keymaster_error_t on failure.
+ virtual int32_t
+ getKeyCharacteristics(const std::string& key_name,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) = 0;
+
+ // Imports |key_data| in the given |key_format|, applies 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 and a Keystore ResponseCode or
+ // keymaster_error_t on failure.
+ virtual int32_t importKey(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster_key_format_t key_format, const std::string& key_data,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::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 int32_t exportKey(keymaster_key_format_t export_format, const std::string& key_name,
+ 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.
+ virtual int32_t deleteKey(const std::string& key_name) = 0;
+
+ // Deletes all keys owned by the caller. Returns KM_ERROR_OK on success and a
+ // Keystore ResponseCode or keymaster_error_t on failure.
+ virtual int32_t deleteAllKeys() = 0;
+
+ // Begins a cryptographic operation (e.g. encrypt, sign) identified by
+ // |purpose| using the key identified by |key_name| and the given
+ // |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 int32_t beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ keymaster::AuthorizationSet* output_parameters,
+ keymaster_operation_handle_t* handle) = 0;
+
+ // Continues the operation associated with |handle| using the given
+ // |input_parameters| and |input_data|. On success, the
+ // |num_input_bytes_consumed|, any |output_parameters|, and any |output_data|
+ // is populated. Returns KM_ERROR_OK on success and a Keystore ResponseCode or
+ // keymaster_error_t on failure.
+ virtual int32_t updateOperation(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data, size_t* num_input_bytes_consumed,
+ keymaster::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| and final |output_data| are populated. Returns
+ // KM_ERROR_OK on success and a Keystore ResponseCode or keymaster_error_t on
+ // failure.
+ virtual int32_t finishOperation(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ keymaster::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.
+ virtual int32_t abortOperation(keymaster_operation_handle_t handle) = 0;
+
+ // Returns true if a key identified by |key_name| exists in the caller's
+ // key store. Returns false if an error occurs.
+ virtual bool doesKeyExist(const std::string& key_name) = 0;
+
+ // Provides a |key_name_list| containing all existing key names in the
+ // caller's key store starting with |prefix|. Returns true on success.
+ virtual bool listKeys(const std::string& prefix, std::vector<std::string>* key_name_list) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KeystoreClient);
+};
+
+} // namespace keystore
+
+#endif // KEYSTORE_KEYSTORE_CLIENT_H_
diff --git a/keystore/include/keystore/keystore_client_impl.h b/keystore/include/keystore/keystore_client_impl.h
new file mode 100644
index 00000000..7ed8443b
--- /dev/null
+++ b/keystore/include/keystore/keystore_client_impl.h
@@ -0,0 +1,92 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
+#define KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
+
+#include "keystore/keystore_client.h"
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include "binder/IBinder.h"
+#include "binder/IServiceManager.h"
+#include "keystore/IKeystoreService.h"
+#include "utils/StrongPointer.h"
+
+namespace keystore {
+
+class KeystoreClientImpl : public KeystoreClient {
+ public:
+ KeystoreClientImpl();
+ ~KeystoreClientImpl() override = default;
+
+ // KeystoreClient methods.
+ int32_t addRandomNumberGeneratorEntropy(const std::string& entropy) override;
+ int32_t generateKey(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) override;
+ int32_t
+ getKeyCharacteristics(const std::string& key_name,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) override;
+ int32_t importKey(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster_key_format_t key_format, const std::string& key_data,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics) override;
+ int32_t exportKey(keymaster_key_format_t export_format, const std::string& key_name,
+ std::string* export_data) override;
+ int32_t deleteKey(const std::string& key_name) override;
+ int32_t deleteAllKeys() override;
+ int32_t beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ keymaster::AuthorizationSet* output_parameters,
+ keymaster_operation_handle_t* handle) override;
+ int32_t updateOperation(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data, size_t* num_input_bytes_consumed,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) override;
+ int32_t finishOperation(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters,
+ std::string* output_data) override;
+ int32_t abortOperation(keymaster_operation_handle_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;
+
+ private:
+ android::sp<android::IServiceManager> service_manager_;
+ android::sp<android::IBinder> keystore_binder_;
+ android::sp<android::IKeystoreService> keystore_;
+ keymaster_operation_handle_t next_virtual_handle_ = 1;
+ std::map<keymaster_operation_handle_t, android::sp<android::IBinder>> active_operations_;
+
+ // Returns an available virtual operation handle.
+ keymaster_operation_handle_t getNextVirtualHandle();
+
+ // 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);
+
+ DISALLOW_COPY_AND_ASSIGN(KeystoreClientImpl);
+};
+
+} // namespace keystore
+
+#endif // KEYSTORE_KEYSTORE_CLIENT_IMPL_H_
diff --git a/keystore/include/keystore/keystore_client_mock.h b/keystore/include/keystore/keystore_client_mock.h
new file mode 100644
index 00000000..2bda8444
--- /dev/null
+++ b/keystore/include/keystore/keystore_client_mock.h
@@ -0,0 +1,77 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
+#define KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
+
+#include "gmock/gmock.h"
+#include "keystore/keystore_client.h"
+
+using testing::_;
+
+namespace keystore {
+
+// A mock implementation of KeystoreClient. By default all methods do nothing
+// and return KM_ERROR_OK (or false).
+class KeystoreClientMock : public KeystoreClient {
+ public:
+ KeystoreClientMock() = default;
+ ~KeystoreClientMock() = default;
+
+ MOCK_METHOD1(addRandomNumberGeneratorEntropy, int32_t(const std::string& entropy));
+ MOCK_METHOD4(generateKey,
+ int32_t(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics));
+ MOCK_METHOD3(getKeyCharacteristics,
+ int32_t(const std::string& key_name,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics));
+ MOCK_METHOD6(importKey,
+ int32_t(const std::string& key_name,
+ const keymaster::AuthorizationSet& key_parameters,
+ keymaster_key_format_t key_format, const std::string& key_data,
+ keymaster::AuthorizationSet* hardware_enforced_characteristics,
+ keymaster::AuthorizationSet* software_enforced_characteristics));
+ MOCK_METHOD3(exportKey, int32_t(keymaster_key_format_t export_format,
+ const std::string& key_name, std::string* export_data));
+ MOCK_METHOD1(deleteKey, int32_t(const std::string& key_name));
+ MOCK_METHOD0(deleteAllKeys, int32_t());
+ MOCK_METHOD5(beginOperation, int32_t(keymaster_purpose_t purpose, const std::string& key_name,
+ const keymaster::AuthorizationSet& input_parameters,
+ keymaster::AuthorizationSet* output_parameters,
+ keymaster_operation_handle_t* handle));
+ MOCK_METHOD6(updateOperation,
+ int32_t(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& input_data, size_t* num_input_bytes_consumed,
+ keymaster::AuthorizationSet* output_parameters, std::string* output_data));
+ MOCK_METHOD5(finishOperation,
+ int32_t(keymaster_operation_handle_t handle,
+ const keymaster::AuthorizationSet& input_parameters,
+ const std::string& signature_to_verify,
+ keymaster::AuthorizationSet* output_parameters, std::string* output_data));
+ MOCK_METHOD1(abortOperation, int32_t(keymaster_operation_handle_t handle));
+ MOCK_METHOD1(doesKeyExist, bool(const std::string& key_name));
+ MOCK_METHOD2(listKeys,
+ bool(const std::string& prefix, std::vector<std::string>* key_name_list));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KeystoreClientMock);
+};
+
+} // namespace keystore
+
+#endif // KEYSTORE_KEYSTORE_CLIENT_MOCK_H_
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
new file mode 100644
index 00000000..288d600e
--- /dev/null
+++ b/keystore/keystore_cli_v2.cpp
@@ -0,0 +1,217 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cstdio>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "keymaster/authorization_set.h"
+#include "keystore/keystore_client_impl.h"
+
+using base::CommandLine;
+using keymaster::AuthorizationSet;
+using keymaster::AuthorizationSetBuilder;
+using keystore::KeystoreClient;
+
+namespace {
+
+void PrintUsageAndExit() {
+ printf("Usage: keystore_client_v2 <command> [options]\n");
+ printf("Commands: add-entropy --input=<entropy>\n"
+ " generate --name=<key_name>\n"
+ " get-chars --name=<key_name>\n"
+ " export --name=<key_name>\n"
+ " delete --name=<key_name>\n"
+ " delete-all\n"
+ " exists --name=<key_name>\n"
+ " list [--prefix=<key_name_prefix>]\n"
+ " sign-verify --name=<key_name>\n");
+ exit(1);
+}
+
+std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
+ return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
+}
+
+int AddEntropy(const std::string& input) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ int32_t result = keystore->addRandomNumberGeneratorEntropy(input);
+ printf("AddEntropy: %d\n", result);
+ return result;
+}
+
+int GenerateKey(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ AuthorizationSetBuilder params;
+ params.RsaSigningKey(2048, 65537)
+ .Digest(KM_DIGEST_SHA_2_224)
+ .Digest(KM_DIGEST_SHA_2_256)
+ .Digest(KM_DIGEST_SHA_2_384)
+ .Digest(KM_DIGEST_SHA_2_512)
+ .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)
+ .Padding(KM_PAD_RSA_PSS)
+ .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ int32_t result = keystore->generateKey(name, params.build(), &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+ printf("GenerateKey: %d (%zu, %zu)\n", result, hardware_enforced_characteristics.size(),
+ software_enforced_characteristics.size());
+ return result;
+}
+
+int GetCharacteristics(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ AuthorizationSet hardware_enforced_characteristics;
+ AuthorizationSet software_enforced_characteristics;
+ int32_t result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
+ &software_enforced_characteristics);
+ printf("GetCharacteristics: %d (%zu, %zu)\n", result, hardware_enforced_characteristics.size(),
+ software_enforced_characteristics.size());
+ return result;
+}
+
+int ExportKey(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ std::string data;
+ int32_t result = keystore->exportKey(KM_KEY_FORMAT_X509, name, &data);
+ printf("ExportKey: %d (%zu)\n", result, data.size());
+ return result;
+}
+
+int DeleteKey(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ int32_t result = keystore->deleteKey(name);
+ printf("DeleteKey: %d\n", result);
+ return result;
+}
+
+int DeleteAllKeys() {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ int32_t result = keystore->deleteAllKeys();
+ printf("DeleteAllKeys: %d\n", result);
+ return result;
+}
+
+int DoesKeyExist(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no");
+ return 0;
+}
+
+int List(const std::string& prefix) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ std::vector<std::string> key_list;
+ if (!keystore->listKeys(prefix, &key_list)) {
+ printf("ListKeys failed.\n");
+ return 1;
+ }
+ printf("Keys:\n");
+ for (const auto& key_name : key_list) {
+ printf(" %s\n", key_name.c_str());
+ }
+ return 0;
+}
+
+int SignAndVerify(const std::string& name) {
+ std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
+ AuthorizationSetBuilder sign_params;
+ sign_params.Padding(KM_PAD_RSA_PKCS1_1_5_SIGN);
+ sign_params.Digest(KM_DIGEST_SHA_2_256);
+ AuthorizationSet output_params;
+ keymaster_operation_handle_t handle;
+ int32_t result = keystore->beginOperation(KM_PURPOSE_SIGN, name, sign_params.build(),
+ &output_params, &handle);
+ if (result != KM_ERROR_OK) {
+ printf("Sign: BeginOperation failed: %d\n", result);
+ return result;
+ }
+ AuthorizationSet empty_params;
+ size_t num_input_bytes_consumed;
+ std::string output_data;
+ result = keystore->updateOperation(handle, empty_params, "data_to_sign",
+ &num_input_bytes_consumed, &output_params, &output_data);
+ if (result != KM_ERROR_OK) {
+ printf("Sign: UpdateOperation failed: %d\n", result);
+ return result;
+ }
+ result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
+ &output_params, &output_data);
+ if (result != KM_ERROR_OK) {
+ printf("Sign: FinishOperation failed: %d\n", result);
+ return result;
+ }
+ printf("Sign: %zu bytes.\n", output_data.size());
+ // We have a signature, now verify it.
+ std::string signature_to_verify = output_data;
+ result = keystore->beginOperation(KM_PURPOSE_VERIFY, name, sign_params.build(), &output_params,
+ &handle);
+ if (result != KM_ERROR_OK) {
+ printf("Verify: BeginOperation failed: %d\n", result);
+ return result;
+ }
+ result = keystore->updateOperation(handle, empty_params, "data_to_sign",
+ &num_input_bytes_consumed, &output_params, &output_data);
+ if (result != KM_ERROR_OK) {
+ printf("Verify: UpdateOperation failed: %d\n", result);
+ return result;
+ }
+ result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
+ &output_data);
+ if (result == KM_ERROR_VERIFICATION_FAILED) {
+ printf("Verify: Failed to verify signature.\n");
+ return result;
+ }
+ if (result != KM_ERROR_OK) {
+ printf("Verify: FinishOperation failed: %d\n", result);
+ return result;
+ }
+ printf("Verify: OK\n");
+ return 0;
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ CommandLine::Init(argc, argv);
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ CommandLine::StringVector args = command_line->GetArgs();
+ if (args.empty()) {
+ PrintUsageAndExit();
+ }
+ if (args[0] == "add-entropy") {
+ return AddEntropy(command_line->GetSwitchValueASCII("input"));
+ } else if (args[0] == "generate") {
+ return GenerateKey(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "get-chars") {
+ return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "export") {
+ return ExportKey(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "delete") {
+ return DeleteKey(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "delete-all") {
+ return DeleteAllKeys();
+ } else if (args[0] == "exists") {
+ return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
+ } else if (args[0] == "list") {
+ return List(command_line->GetSwitchValueASCII("prefix"));
+ } else if (args[0] == "sign-verify") {
+ return SignAndVerify(command_line->GetSwitchValueASCII("name"));
+ } else {
+ PrintUsageAndExit();
+ }
+ return 0;
+}
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
new file mode 100644
index 00000000..deaa6153
--- /dev/null
+++ b/keystore/keystore_client_impl.cpp
@@ -0,0 +1,251 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "keystore/keystore_client_impl.h"
+
+#include <string>
+#include <vector>
+
+#include "binder/IBinder.h"
+#include "binder/IInterface.h"
+#include "binder/IServiceManager.h"
+#include "keystore/IKeystoreService.h"
+#include "keystore/keystore.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
+
+using android::ExportResult;
+using android::KeyCharacteristics;
+using android::KeymasterArguments;
+using android::OperationResult;
+using android::String16;
+using keymaster::AuthorizationSet;
+
+namespace {
+
+// Use the UID of the current process.
+const int kDefaultUID = -1;
+
+const uint8_t* StringAsByteArray(const std::string& s) {
+ return reinterpret_cast<const uint8_t*>(s.data());
+}
+
+std::string ByteArrayAsString(const uint8_t* data, size_t data_size) {
+ return std::string(reinterpret_cast<const char*>(data), data_size);
+}
+
+} // namespace
+
+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_);
+}
+
+int32_t KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
+ return mapKeystoreError(keystore_->addRngEntropy(StringAsByteArray(entropy), entropy.size()));
+}
+
+int32_t KeystoreClientImpl::generateKey(const std::string& key_name,
+ const AuthorizationSet& key_parameters,
+ AuthorizationSet* hardware_enforced_characteristics,
+ AuthorizationSet* software_enforced_characteristics) {
+ String16 key_name16(key_name.data(), key_name.size());
+ KeymasterArguments key_arguments;
+ key_arguments.params.assign(key_parameters.begin(), key_parameters.end());
+ KeyCharacteristics characteristics;
+ int32_t result =
+ keystore_->generateKey(key_name16, key_arguments, NULL /*entropy*/, 0 /*entropyLength*/,
+ kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+ hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+ software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+ return mapKeystoreError(result);
+}
+
+int32_t
+KeystoreClientImpl::getKeyCharacteristics(const std::string& key_name,
+ AuthorizationSet* hardware_enforced_characteristics,
+ AuthorizationSet* software_enforced_characteristics) {
+ String16 key_name16(key_name.data(), key_name.size());
+ keymaster_blob_t client_id_blob = {nullptr, 0};
+ keymaster_blob_t app_data_blob = {nullptr, 0};
+ KeyCharacteristics characteristics;
+ int32_t result = keystore_->getKeyCharacteristics(key_name16, &client_id_blob, &app_data_blob,
+ &characteristics);
+ hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+ software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+ return mapKeystoreError(result);
+}
+
+int32_t KeystoreClientImpl::importKey(const std::string& key_name,
+ const AuthorizationSet& key_parameters,
+ keymaster_key_format_t key_format,
+ const std::string& key_data,
+ AuthorizationSet* hardware_enforced_characteristics,
+ AuthorizationSet* software_enforced_characteristics) {
+ String16 key_name16(key_name.data(), key_name.size());
+ KeymasterArguments key_arguments;
+ key_arguments.params.assign(key_parameters.begin(), key_parameters.end());
+ KeyCharacteristics characteristics;
+ int32_t result =
+ keystore_->importKey(key_name16, key_arguments, key_format, StringAsByteArray(key_data),
+ key_data.size(), kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
+ hardware_enforced_characteristics->Reinitialize(characteristics.characteristics.hw_enforced);
+ software_enforced_characteristics->Reinitialize(characteristics.characteristics.sw_enforced);
+ return mapKeystoreError(result);
+}
+
+int32_t KeystoreClientImpl::exportKey(keymaster_key_format_t export_format,
+ const std::string& key_name, std::string* export_data) {
+ String16 key_name16(key_name.data(), key_name.size());
+ keymaster_blob_t client_id_blob = {nullptr, 0};
+ keymaster_blob_t app_data_blob = {nullptr, 0};
+ ExportResult export_result;
+ keystore_->exportKey(key_name16, export_format, &client_id_blob, &app_data_blob,
+ &export_result);
+ *export_data = ByteArrayAsString(export_result.exportData.get(), export_result.dataLength);
+ return mapKeystoreError(export_result.resultCode);
+}
+
+int32_t KeystoreClientImpl::deleteKey(const std::string& key_name) {
+ String16 key_name16(key_name.data(), key_name.size());
+ return mapKeystoreError(keystore_->del(key_name16, kDefaultUID));
+}
+
+int32_t KeystoreClientImpl::deleteAllKeys() {
+ return mapKeystoreError(keystore_->clear_uid(kDefaultUID));
+}
+
+int32_t KeystoreClientImpl::beginOperation(keymaster_purpose_t purpose, const std::string& key_name,
+ const AuthorizationSet& input_parameters,
+ AuthorizationSet* output_parameters,
+ keymaster_operation_handle_t* handle) {
+ android::sp<android::IBinder> token(new android::BBinder);
+ String16 key_name16(key_name.data(), key_name.size());
+ KeymasterArguments input_arguments;
+ input_arguments.params.assign(input_parameters.begin(), input_parameters.end());
+ OperationResult result;
+ keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_arguments,
+ NULL /*entropy*/, 0 /*entropyLength*/, &result);
+ int32_t error_code = mapKeystoreError(result.resultCode);
+ if (error_code == KM_ERROR_OK) {
+ *handle = getNextVirtualHandle();
+ active_operations_[*handle] = result.token;
+ if (!result.outParams.params.empty()) {
+ output_parameters->Reinitialize(&*result.outParams.params.begin(),
+ result.outParams.params.size());
+ }
+ }
+ return error_code;
+}
+
+int32_t KeystoreClientImpl::updateOperation(keymaster_operation_handle_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 KM_ERROR_INVALID_OPERATION_HANDLE;
+ }
+ KeymasterArguments input_arguments;
+ input_arguments.params.assign(input_parameters.begin(), input_parameters.end());
+ OperationResult result;
+ keystore_->update(active_operations_[handle], input_arguments, StringAsByteArray(input_data),
+ input_data.size(), &result);
+ int32_t error_code = mapKeystoreError(result.resultCode);
+ if (error_code == KM_ERROR_OK) {
+ *num_input_bytes_consumed = result.inputConsumed;
+ if (!result.outParams.params.empty()) {
+ output_parameters->Reinitialize(&*result.outParams.params.begin(),
+ result.outParams.params.size());
+ }
+ *output_data = ByteArrayAsString(result.data.get(), result.dataLength);
+ }
+ return error_code;
+}
+
+int32_t KeystoreClientImpl::finishOperation(keymaster_operation_handle_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 KM_ERROR_INVALID_OPERATION_HANDLE;
+ }
+ KeymasterArguments input_arguments;
+ input_arguments.params.assign(input_parameters.begin(), input_parameters.end());
+ OperationResult result;
+ keystore_->finish(active_operations_[handle], input_arguments,
+ StringAsByteArray(signature_to_verify), signature_to_verify.size(),
+ NULL /*entropy*/, 0 /*entropyLength*/, &result);
+ int32_t error_code = mapKeystoreError(result.resultCode);
+ if (error_code == KM_ERROR_OK) {
+ if (!result.outParams.params.empty()) {
+ output_parameters->Reinitialize(&*result.outParams.params.begin(),
+ result.outParams.params.size());
+ }
+ *output_data = ByteArrayAsString(result.data.get(), result.dataLength);
+ active_operations_.erase(handle);
+ }
+ return error_code;
+}
+
+int32_t KeystoreClientImpl::abortOperation(keymaster_operation_handle_t handle) {
+ if (active_operations_.count(handle) == 0) {
+ return KM_ERROR_INVALID_OPERATION_HANDLE;
+ }
+ int32_t error_code = mapKeystoreError(keystore_->abort(active_operations_[handle]));
+ if (error_code == KM_ERROR_OK) {
+ active_operations_.erase(handle);
+ }
+ return error_code;
+}
+
+bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) {
+ String16 key_name16(key_name.data(), key_name.size());
+ int32_t error_code = mapKeystoreError(keystore_->exist(key_name16, kDefaultUID));
+ return (error_code == KM_ERROR_OK);
+}
+
+bool KeystoreClientImpl::listKeys(const std::string& prefix,
+ std::vector<std::string>* key_name_list) {
+ String16 prefix16(prefix.data(), prefix.size());
+ android::Vector<String16> matches;
+ int32_t error_code = mapKeystoreError(keystore_->list(prefix16, kDefaultUID, &matches));
+ if (error_code == KM_ERROR_OK) {
+ 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;
+ }
+ return false;
+}
+
+keymaster_operation_handle_t KeystoreClientImpl::getNextVirtualHandle() {
+ return next_virtual_handle_++;
+}
+
+int32_t KeystoreClientImpl::mapKeystoreError(int32_t keystore_error) {
+ // See notes in keystore_client.h for rationale.
+ if (keystore_error == ::NO_ERROR) {
+ return KM_ERROR_OK;
+ }
+ return keystore_error;
+}
+
+} // namespace keystore