Commit 69a3dbc2 authored by Darren Krahn's avatar Darren Krahn Committed by Gaurav Shah
Browse files

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
parent 91e439b0
......@@ -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
......
// 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_
// 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_
// 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_
// 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;
}
// 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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment