blob: 4f4040d3cd21ff90982ed7d7b6dd8f22260e4702 [file] [log] [blame]
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001// Copyright 2015 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <cstdio>
16#include <memory>
17#include <string>
18#include <vector>
19
20#include "base/command_line.h"
Darren Krahn251cb282015-09-28 08:51:18 -070021#include "base/files/file_util.h"
Darren Krahn69a3dbc2015-09-22 16:21:04 -070022#include "keymaster/authorization_set.h"
23#include "keystore/keystore_client_impl.h"
24
25using base::CommandLine;
26using keymaster::AuthorizationSet;
27using keymaster::AuthorizationSetBuilder;
28using keystore::KeystoreClient;
29
30namespace {
31
32void PrintUsageAndExit() {
33 printf("Usage: keystore_client_v2 <command> [options]\n");
34 printf("Commands: add-entropy --input=<entropy>\n"
35 " generate --name=<key_name>\n"
36 " get-chars --name=<key_name>\n"
37 " export --name=<key_name>\n"
38 " delete --name=<key_name>\n"
39 " delete-all\n"
40 " exists --name=<key_name>\n"
41 " list [--prefix=<key_name_prefix>]\n"
Darren Krahn251cb282015-09-28 08:51:18 -070042 " sign-verify --name=<key_name>\n"
43 " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n");
Darren Krahn69a3dbc2015-09-22 16:21:04 -070044 exit(1);
45}
46
47std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
48 return std::unique_ptr<KeystoreClient>(new keystore::KeystoreClientImpl);
49}
50
Darren Krahn251cb282015-09-28 08:51:18 -070051std::string ReadFile(const std::string& filename) {
52 std::string content;
53 base::FilePath path(filename);
54 if (!base::ReadFileToString(path, &content)) {
55 printf("Failed to read file: %s\n", filename.c_str());
56 exit(1);
57 }
58 return content;
59}
60
61void WriteFile(const std::string& filename, const std::string& content) {
62 base::FilePath path(filename);
63 int size = content.size();
64 if (base::WriteFile(path, content.data(), size) != size) {
65 printf("Failed to write file: %s\n", filename.c_str());
66 exit(1);
67 }
68}
69
Darren Krahn69a3dbc2015-09-22 16:21:04 -070070int AddEntropy(const std::string& input) {
71 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
72 int32_t result = keystore->addRandomNumberGeneratorEntropy(input);
73 printf("AddEntropy: %d\n", result);
74 return result;
75}
76
77int GenerateKey(const std::string& name) {
78 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
79 AuthorizationSetBuilder params;
80 params.RsaSigningKey(2048, 65537)
81 .Digest(KM_DIGEST_SHA_2_224)
82 .Digest(KM_DIGEST_SHA_2_256)
83 .Digest(KM_DIGEST_SHA_2_384)
84 .Digest(KM_DIGEST_SHA_2_512)
85 .Padding(KM_PAD_RSA_PKCS1_1_5_SIGN)
86 .Padding(KM_PAD_RSA_PSS)
87 .Authorization(keymaster::TAG_NO_AUTH_REQUIRED);
88 AuthorizationSet hardware_enforced_characteristics;
89 AuthorizationSet software_enforced_characteristics;
90 int32_t result = keystore->generateKey(name, params.build(), &hardware_enforced_characteristics,
91 &software_enforced_characteristics);
92 printf("GenerateKey: %d (%zu, %zu)\n", result, hardware_enforced_characteristics.size(),
93 software_enforced_characteristics.size());
94 return result;
95}
96
97int GetCharacteristics(const std::string& name) {
98 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
99 AuthorizationSet hardware_enforced_characteristics;
100 AuthorizationSet software_enforced_characteristics;
101 int32_t result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
102 &software_enforced_characteristics);
103 printf("GetCharacteristics: %d (%zu, %zu)\n", result, hardware_enforced_characteristics.size(),
104 software_enforced_characteristics.size());
105 return result;
106}
107
108int ExportKey(const std::string& name) {
109 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
110 std::string data;
111 int32_t result = keystore->exportKey(KM_KEY_FORMAT_X509, name, &data);
112 printf("ExportKey: %d (%zu)\n", result, data.size());
113 return result;
114}
115
116int DeleteKey(const std::string& name) {
117 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
118 int32_t result = keystore->deleteKey(name);
119 printf("DeleteKey: %d\n", result);
120 return result;
121}
122
123int DeleteAllKeys() {
124 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
125 int32_t result = keystore->deleteAllKeys();
126 printf("DeleteAllKeys: %d\n", result);
127 return result;
128}
129
130int DoesKeyExist(const std::string& name) {
131 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
132 printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no");
133 return 0;
134}
135
136int List(const std::string& prefix) {
137 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
138 std::vector<std::string> key_list;
139 if (!keystore->listKeys(prefix, &key_list)) {
140 printf("ListKeys failed.\n");
141 return 1;
142 }
143 printf("Keys:\n");
144 for (const auto& key_name : key_list) {
145 printf(" %s\n", key_name.c_str());
146 }
147 return 0;
148}
149
150int SignAndVerify(const std::string& name) {
151 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
152 AuthorizationSetBuilder sign_params;
153 sign_params.Padding(KM_PAD_RSA_PKCS1_1_5_SIGN);
154 sign_params.Digest(KM_DIGEST_SHA_2_256);
155 AuthorizationSet output_params;
156 keymaster_operation_handle_t handle;
157 int32_t result = keystore->beginOperation(KM_PURPOSE_SIGN, name, sign_params.build(),
158 &output_params, &handle);
159 if (result != KM_ERROR_OK) {
160 printf("Sign: BeginOperation failed: %d\n", result);
161 return result;
162 }
163 AuthorizationSet empty_params;
164 size_t num_input_bytes_consumed;
165 std::string output_data;
166 result = keystore->updateOperation(handle, empty_params, "data_to_sign",
167 &num_input_bytes_consumed, &output_params, &output_data);
168 if (result != KM_ERROR_OK) {
169 printf("Sign: UpdateOperation failed: %d\n", result);
170 return result;
171 }
172 result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
173 &output_params, &output_data);
174 if (result != KM_ERROR_OK) {
175 printf("Sign: FinishOperation failed: %d\n", result);
176 return result;
177 }
178 printf("Sign: %zu bytes.\n", output_data.size());
179 // We have a signature, now verify it.
180 std::string signature_to_verify = output_data;
Darren Krahn251cb282015-09-28 08:51:18 -0700181 output_data.clear();
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700182 result = keystore->beginOperation(KM_PURPOSE_VERIFY, name, sign_params.build(), &output_params,
183 &handle);
184 if (result != KM_ERROR_OK) {
185 printf("Verify: BeginOperation failed: %d\n", result);
186 return result;
187 }
188 result = keystore->updateOperation(handle, empty_params, "data_to_sign",
189 &num_input_bytes_consumed, &output_params, &output_data);
190 if (result != KM_ERROR_OK) {
191 printf("Verify: UpdateOperation failed: %d\n", result);
192 return result;
193 }
194 result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
195 &output_data);
196 if (result == KM_ERROR_VERIFICATION_FAILED) {
197 printf("Verify: Failed to verify signature.\n");
198 return result;
199 }
200 if (result != KM_ERROR_OK) {
201 printf("Verify: FinishOperation failed: %d\n", result);
202 return result;
203 }
204 printf("Verify: OK\n");
205 return 0;
206}
207
Darren Krahn251cb282015-09-28 08:51:18 -0700208int Encrypt(const std::string& key_name, const std::string& input_filename,
209 const std::string& output_filename) {
210 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
211 std::string input = ReadFile(input_filename);
212 std::string output;
213 if (!keystore->encryptWithAuthentication(key_name, input, &output)) {
214 printf("EncryptWithAuthentication failed.\n");
215 return 1;
216 }
217 WriteFile(output_filename, output);
218 return 0;
219}
220
221int Decrypt(const std::string& key_name, const std::string& input_filename,
222 const std::string& output_filename) {
223 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
224 std::string input = ReadFile(input_filename);
225 std::string output;
226 if (!keystore->decryptWithAuthentication(key_name, input, &output)) {
227 printf("DecryptWithAuthentication failed.\n");
228 return 1;
229 }
230 WriteFile(output_filename, output);
231 return 0;
232}
233
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700234} // namespace
235
236int main(int argc, char** argv) {
237 CommandLine::Init(argc, argv);
238 CommandLine* command_line = CommandLine::ForCurrentProcess();
239 CommandLine::StringVector args = command_line->GetArgs();
240 if (args.empty()) {
241 PrintUsageAndExit();
242 }
243 if (args[0] == "add-entropy") {
244 return AddEntropy(command_line->GetSwitchValueASCII("input"));
245 } else if (args[0] == "generate") {
246 return GenerateKey(command_line->GetSwitchValueASCII("name"));
247 } else if (args[0] == "get-chars") {
248 return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
249 } else if (args[0] == "export") {
250 return ExportKey(command_line->GetSwitchValueASCII("name"));
251 } else if (args[0] == "delete") {
252 return DeleteKey(command_line->GetSwitchValueASCII("name"));
253 } else if (args[0] == "delete-all") {
254 return DeleteAllKeys();
255 } else if (args[0] == "exists") {
256 return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
257 } else if (args[0] == "list") {
258 return List(command_line->GetSwitchValueASCII("prefix"));
259 } else if (args[0] == "sign-verify") {
260 return SignAndVerify(command_line->GetSwitchValueASCII("name"));
Darren Krahn251cb282015-09-28 08:51:18 -0700261 } else if (args[0] == "encrypt") {
262 return Encrypt(command_line->GetSwitchValueASCII("name"),
263 command_line->GetSwitchValueASCII("in"),
264 command_line->GetSwitchValueASCII("out"));
265 } else if (args[0] == "decrypt") {
266 return Decrypt(command_line->GetSwitchValueASCII("name"),
267 command_line->GetSwitchValueASCII("in"),
268 command_line->GetSwitchValueASCII("out"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700269 } else {
270 PrintUsageAndExit();
271 }
272 return 0;
273}