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
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
new file mode 100644
index 0000000..288d600
--- /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;
+}