diff options
author | Darren Krahn <dkrahn@google.com> | 2015-09-22 16:21:04 -0700 |
---|---|---|
committer | Gaurav Shah <gauravsh@google.com> | 2015-11-02 09:12:39 -0800 |
commit | 69a3dbc2bbbe0b304eb91376ff7f79c8bde995a1 (patch) | |
tree | c46a81a11bd45bfc4018811f2b310e7776d667be | |
parent | 91e439b0e86d42032d8b53200f0f9557d3e7ef17 (diff) | |
download | security-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.mk | 29 | ||||
-rw-r--r-- | keystore/include/keystore/keystore_client.h | 153 | ||||
-rw-r--r-- | keystore/include/keystore/keystore_client_impl.h | 92 | ||||
-rw-r--r-- | keystore/include/keystore/keystore_client_mock.h | 77 | ||||
-rw-r--r-- | keystore/keystore_cli_v2.cpp | 217 | ||||
-rw-r--r-- | keystore/keystore_client_impl.cpp | 251 |
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 |