blob: 1c943189bfe725b8a0e886d39fb8a7f868ece5b1 [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
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -080015#include <chrono>
Darren Krahn69a3dbc2015-09-22 16:21:04 -070016#include <cstdio>
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -080017#include <future>
Darren Krahn69a3dbc2015-09-22 16:21:04 -070018#include <memory>
19#include <string>
20#include <vector>
21
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070022#include <base/command_line.h>
23#include <base/files/file_util.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050024#include <base/strings/string_number_conversions.h>
25#include <base/strings/string_split.h>
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070026#include <base/strings/string_util.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050027#include <base/strings/utf_string_conversions.h>
28#include <base/threading/platform_thread.h>
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070029#include <keystore/keymaster_types.h>
30#include <keystore/keystore_client_impl.h>
Darren Krahn69a3dbc2015-09-22 16:21:04 -070031
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050032#include <android/hardware/confirmationui/1.0/types.h>
33#include <android/security/BnConfirmationPromptCallback.h>
Rob Barnesbb6cabd2018-10-04 17:10:37 -060034#include <android/security/keystore/IKeystoreService.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050035
36#include <binder/IPCThreadState.h>
37#include <binder/IServiceManager.h>
38
39//#include <keystore/keystore.h>
40
Darren Krahn69a3dbc2015-09-22 16:21:04 -070041using base::CommandLine;
Darren Krahn69a3dbc2015-09-22 16:21:04 -070042using keystore::KeystoreClient;
43
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050044using android::sp;
45using android::String16;
Rob Barnesbb6cabd2018-10-04 17:10:37 -060046using android::security::keystore::IKeystoreService;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050047using base::CommandLine;
48using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
49
Darren Krahn69a3dbc2015-09-22 16:21:04 -070050namespace {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010051using namespace keystore;
Darren Krahn69a3dbc2015-09-22 16:21:04 -070052
Darren Krahna9474ab2015-11-03 14:38:53 -080053struct TestCase {
54 std::string name;
55 bool required_for_brillo_pts;
56 AuthorizationSet parameters;
57};
58
Darren Krahn69a3dbc2015-09-22 16:21:04 -070059void PrintUsageAndExit() {
60 printf("Usage: keystore_client_v2 <command> [options]\n");
Darren Krahn82f4f5b2016-03-03 16:21:07 -080061 printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
Darren Krahna9474ab2015-11-03 14:38:53 -080062 " list-brillo-tests\n"
Janis Danisevskisc1460142017-12-18 16:48:46 -080063 " add-entropy --input=<entropy> [--seclevel=software|strongbox|tee(default)]\n"
64 " generate --name=<key_name> [--seclevel=software|strongbox|tee(default)]\n"
Darren Krahn69a3dbc2015-09-22 16:21:04 -070065 " get-chars --name=<key_name>\n"
66 " export --name=<key_name>\n"
67 " delete --name=<key_name>\n"
68 " delete-all\n"
69 " exists --name=<key_name>\n"
70 " list [--prefix=<key_name_prefix>]\n"
Darren Krahn251cb282015-09-28 08:51:18 -070071 " sign-verify --name=<key_name>\n"
Janis Danisevskisc1460142017-12-18 16:48:46 -080072 " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n"
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050073 " [--seclevel=software|strongbox|tee(default)]\n"
74 " confirmation --prompt_text=<PromptText> --extra_data=<hex>\n"
75 " --locale=<locale> [--ui_options=<list_of_ints>]\n"
76 " --cancel_after=<seconds>\n");
Darren Krahn69a3dbc2015-09-22 16:21:04 -070077 exit(1);
78}
79
80std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010081 return std::unique_ptr<KeystoreClient>(
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070082 static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
Darren Krahn69a3dbc2015-09-22 16:21:04 -070083}
84
Darren Krahna9474ab2015-11-03 14:38:53 -080085void PrintTags(const AuthorizationSet& parameters) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010086 for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070087 auto tag_str = toString(iter->tag);
88 printf(" %s\n", tag_str.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -080089 }
90}
91
92void PrintKeyCharacteristics(const AuthorizationSet& hardware_enforced_characteristics,
93 const AuthorizationSet& software_enforced_characteristics) {
94 printf("Hardware:\n");
95 PrintTags(hardware_enforced_characteristics);
96 printf("Software:\n");
97 PrintTags(software_enforced_characteristics);
98}
99
100bool TestKey(const std::string& name, bool required, const AuthorizationSet& parameters) {
101 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
102 AuthorizationSet hardware_enforced_characteristics;
103 AuthorizationSet software_enforced_characteristics;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800104 auto result =
105 keystore->generateKey("tmp", parameters, 0 /*flags*/, &hardware_enforced_characteristics,
106 &software_enforced_characteristics);
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800107 const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100108 if (!result.isOk()) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800109 LOG(ERROR) << "Failed to generate key: " << result;
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800110 printf("[%s] %s\n", kBoldRedAbort, name.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -0800111 return false;
112 }
113 result = keystore->deleteKey("tmp");
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100114 if (!result.isOk()) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800115 LOG(ERROR) << "Failed to delete key: " << result;
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800116 printf("[%s] %s\n", kBoldRedAbort, name.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -0800117 return false;
118 }
119 printf("===============================================================\n");
120 printf("%s Key Characteristics:\n", name.c_str());
121 PrintKeyCharacteristics(hardware_enforced_characteristics, software_enforced_characteristics);
122 bool hardware_backed = (hardware_enforced_characteristics.size() > 0);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100123 if (software_enforced_characteristics.GetTagCount(TAG_ALGORITHM) > 0 ||
124 software_enforced_characteristics.GetTagCount(TAG_KEY_SIZE) > 0 ||
125 software_enforced_characteristics.GetTagCount(TAG_RSA_PUBLIC_EXPONENT) > 0) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800126 VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
127 hardware_backed = false;
128 }
129 const char kBoldRedFail[] = "\033[1;31mFAIL\033[0m";
130 const char kBoldGreenPass[] = "\033[1;32mPASS\033[0m";
131 const char kBoldYellowWarn[] = "\033[1;33mWARN\033[0m";
132 printf("[%s] %s\n",
133 hardware_backed ? kBoldGreenPass : (required ? kBoldRedFail : kBoldYellowWarn),
134 name.c_str());
135
136 return (hardware_backed || !required);
137}
138
139AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
140 AuthorizationSetBuilder parameters;
141 parameters.RsaSigningKey(key_size, 65537)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100142 .Digest(Digest::SHA_2_256)
143 .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
144 .Padding(PaddingMode::RSA_PSS)
145 .Authorization(TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800146 if (!sha256_only) {
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700147 parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
Darren Krahna9474ab2015-11-03 14:38:53 -0800148 }
Yi Kong53b02f72018-07-26 17:13:50 -0700149 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800150}
151
152AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) {
153 AuthorizationSetBuilder parameters;
154 parameters.RsaEncryptionKey(key_size, 65537)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100155 .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)
156 .Padding(PaddingMode::RSA_OAEP)
157 .Authorization(TAG_NO_AUTH_REQUIRED);
Yi Kong53b02f72018-07-26 17:13:50 -0700158 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800159}
160
161AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) {
162 AuthorizationSetBuilder parameters;
163 parameters.EcdsaSigningKey(key_size)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100164 .Digest(Digest::SHA_2_256)
165 .Authorization(TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800166 if (!sha256_only) {
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700167 parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
Darren Krahna9474ab2015-11-03 14:38:53 -0800168 }
Yi Kong53b02f72018-07-26 17:13:50 -0700169 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800170}
171
172AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
173 AuthorizationSetBuilder parameters;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100174 parameters.AesEncryptionKey(key_size).Authorization(TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800175 if (with_gcm_mode) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100176 parameters.Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
177 .Authorization(TAG_MIN_MAC_LENGTH, 128);
Darren Krahna9474ab2015-11-03 14:38:53 -0800178 } else {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100179 parameters.Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
180 parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
181 parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CTR);
182 parameters.Padding(PaddingMode::NONE);
Darren Krahna9474ab2015-11-03 14:38:53 -0800183 }
Yi Kong53b02f72018-07-26 17:13:50 -0700184 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800185}
186
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100187AuthorizationSet GetHMACParameters(uint32_t key_size, Digest digest) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800188 AuthorizationSetBuilder parameters;
189 parameters.HmacKey(key_size)
190 .Digest(digest)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100191 .Authorization(TAG_MIN_MAC_LENGTH, 224)
192 .Authorization(TAG_NO_AUTH_REQUIRED);
Yi Kong53b02f72018-07-26 17:13:50 -0700193 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800194}
195
196std::vector<TestCase> GetTestCases() {
197 TestCase test_cases[] = {
198 {"RSA-2048 Sign", true, GetRSASignParameters(2048, true)},
199 {"RSA-2048 Sign (more digests)", false, GetRSASignParameters(2048, false)},
200 {"RSA-3072 Sign", false, GetRSASignParameters(3072, false)},
201 {"RSA-4096 Sign", false, GetRSASignParameters(4096, false)},
202 {"RSA-2048 Encrypt", true, GetRSAEncryptParameters(2048)},
203 {"RSA-3072 Encrypt", false, GetRSAEncryptParameters(3072)},
204 {"RSA-4096 Encrypt", false, GetRSAEncryptParameters(4096)},
205 {"ECDSA-P256 Sign", true, GetECDSAParameters(256, true)},
206 {"ECDSA-P256 Sign (more digests)", false, GetECDSAParameters(256, false)},
207 {"ECDSA-P224 Sign", false, GetECDSAParameters(224, false)},
208 {"ECDSA-P384 Sign", false, GetECDSAParameters(384, false)},
209 {"ECDSA-P521 Sign", false, GetECDSAParameters(521, false)},
210 {"AES-128", true, GetAESParameters(128, false)},
211 {"AES-256", true, GetAESParameters(256, false)},
212 {"AES-128-GCM", false, GetAESParameters(128, true)},
213 {"AES-256-GCM", false, GetAESParameters(256, true)},
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100214 {"HMAC-SHA256-16", true, GetHMACParameters(16, Digest::SHA_2_256)},
215 {"HMAC-SHA256-32", true, GetHMACParameters(32, Digest::SHA_2_256)},
216 {"HMAC-SHA256-64", false, GetHMACParameters(64, Digest::SHA_2_256)},
217 {"HMAC-SHA224-32", false, GetHMACParameters(32, Digest::SHA_2_224)},
218 {"HMAC-SHA384-32", false, GetHMACParameters(32, Digest::SHA_2_384)},
219 {"HMAC-SHA512-32", false, GetHMACParameters(32, Digest::SHA_2_512)},
Darren Krahna9474ab2015-11-03 14:38:53 -0800220 };
221 return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
222}
223
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800224int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) {
225 const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m";
226 if (test_for_0_3) {
227 printf("%s: Testing for keymaster v0.3. "
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700228 "This does not meet Brillo requirements.\n",
229 kBoldYellowWarning);
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800230 }
Darren Krahna9474ab2015-11-03 14:38:53 -0800231 int test_count = 0;
232 int fail_count = 0;
233 std::vector<TestCase> test_cases = GetTestCases();
234 for (const auto& test_case : test_cases) {
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800235 if (!prefix.empty() &&
236 !base::StartsWith(test_case.name, prefix, base::CompareCase::SENSITIVE)) {
237 continue;
238 }
239 if (test_for_0_3 &&
240 (base::StartsWith(test_case.name, "AES", base::CompareCase::SENSITIVE) ||
241 base::StartsWith(test_case.name, "HMAC", base::CompareCase::SENSITIVE))) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800242 continue;
243 }
244 ++test_count;
245 if (!TestKey(test_case.name, test_case.required_for_brillo_pts, test_case.parameters)) {
246 VLOG(1) << "Test failed: " << test_case.name;
247 ++fail_count;
248 }
249 }
250 return fail_count;
251}
252
253int ListTestCases() {
254 const char kBoldGreenRequired[] = "\033[1;32mREQUIRED\033[0m";
255 const char kBoldYellowRecommended[] = "\033[1;33mRECOMMENDED\033[0m";
256 std::vector<TestCase> test_cases = GetTestCases();
257 for (const auto& test_case : test_cases) {
258 printf("%s : %s\n", test_case.name.c_str(),
259 test_case.required_for_brillo_pts ? kBoldGreenRequired : kBoldYellowRecommended);
260 }
261 return 0;
262}
263
Darren Krahn251cb282015-09-28 08:51:18 -0700264std::string ReadFile(const std::string& filename) {
265 std::string content;
266 base::FilePath path(filename);
267 if (!base::ReadFileToString(path, &content)) {
268 printf("Failed to read file: %s\n", filename.c_str());
269 exit(1);
270 }
271 return content;
272}
273
274void WriteFile(const std::string& filename, const std::string& content) {
275 base::FilePath path(filename);
276 int size = content.size();
277 if (base::WriteFile(path, content.data(), size) != size) {
278 printf("Failed to write file: %s\n", filename.c_str());
279 exit(1);
280 }
281}
282
Janis Danisevskisc1460142017-12-18 16:48:46 -0800283int AddEntropy(const std::string& input, int32_t flags) {
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700284 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
Janis Danisevskisc1460142017-12-18 16:48:46 -0800285 int32_t result = keystore->addRandomNumberGeneratorEntropy(input, flags);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700286 printf("AddEntropy: %d\n", result);
287 return result;
288}
289
Janis Danisevskisc1460142017-12-18 16:48:46 -0800290int GenerateKey(const std::string& name, int32_t flags) {
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700291 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
292 AuthorizationSetBuilder params;
293 params.RsaSigningKey(2048, 65537)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100294 .Digest(Digest::SHA_2_224)
295 .Digest(Digest::SHA_2_256)
296 .Digest(Digest::SHA_2_384)
297 .Digest(Digest::SHA_2_512)
298 .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
299 .Padding(PaddingMode::RSA_PSS)
300 .Authorization(TAG_NO_AUTH_REQUIRED);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700301 AuthorizationSet hardware_enforced_characteristics;
302 AuthorizationSet software_enforced_characteristics;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800303 auto result = keystore->generateKey(name, params, flags, &hardware_enforced_characteristics,
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700304 &software_enforced_characteristics);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100305 printf("GenerateKey: %d\n", int32_t(result));
306 if (result.isOk()) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800307 PrintKeyCharacteristics(hardware_enforced_characteristics,
308 software_enforced_characteristics);
309 }
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700310 return result;
311}
312
313int GetCharacteristics(const std::string& name) {
314 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
315 AuthorizationSet hardware_enforced_characteristics;
316 AuthorizationSet software_enforced_characteristics;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100317 auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700318 &software_enforced_characteristics);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100319 printf("GetCharacteristics: %d\n", int32_t(result));
320 if (result.isOk()) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800321 PrintKeyCharacteristics(hardware_enforced_characteristics,
322 software_enforced_characteristics);
323 }
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700324 return result;
325}
326
327int ExportKey(const std::string& name) {
328 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
329 std::string data;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100330 int32_t result = keystore->exportKey(KeyFormat::X509, name, &data);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700331 printf("ExportKey: %d (%zu)\n", result, data.size());
332 return result;
333}
334
335int DeleteKey(const std::string& name) {
336 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
337 int32_t result = keystore->deleteKey(name);
338 printf("DeleteKey: %d\n", result);
339 return result;
340}
341
342int DeleteAllKeys() {
343 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
344 int32_t result = keystore->deleteAllKeys();
345 printf("DeleteAllKeys: %d\n", result);
346 return result;
347}
348
349int DoesKeyExist(const std::string& name) {
350 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
351 printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no");
352 return 0;
353}
354
355int List(const std::string& prefix) {
356 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
357 std::vector<std::string> key_list;
358 if (!keystore->listKeys(prefix, &key_list)) {
359 printf("ListKeys failed.\n");
360 return 1;
361 }
362 printf("Keys:\n");
363 for (const auto& key_name : key_list) {
364 printf(" %s\n", key_name.c_str());
365 }
366 return 0;
367}
368
369int SignAndVerify(const std::string& name) {
370 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
371 AuthorizationSetBuilder sign_params;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100372 sign_params.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN);
373 sign_params.Digest(Digest::SHA_2_256);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700374 AuthorizationSet output_params;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100375 uint64_t handle;
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700376 auto result =
377 keystore->beginOperation(KeyPurpose::SIGN, name, sign_params, &output_params, &handle);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100378 if (!result.isOk()) {
379 printf("Sign: BeginOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700380 return result;
381 }
382 AuthorizationSet empty_params;
383 size_t num_input_bytes_consumed;
384 std::string output_data;
385 result = keystore->updateOperation(handle, empty_params, "data_to_sign",
386 &num_input_bytes_consumed, &output_params, &output_data);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100387 if (!result.isOk()) {
388 printf("Sign: UpdateOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700389 return result;
390 }
391 result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
392 &output_params, &output_data);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100393 if (!result.isOk()) {
394 printf("Sign: FinishOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700395 return result;
396 }
397 printf("Sign: %zu bytes.\n", output_data.size());
398 // We have a signature, now verify it.
399 std::string signature_to_verify = output_data;
Darren Krahn251cb282015-09-28 08:51:18 -0700400 output_data.clear();
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700401 result =
402 keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, &handle);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100403 if (!result.isOk()) {
404 printf("Verify: BeginOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700405 return result;
406 }
407 result = keystore->updateOperation(handle, empty_params, "data_to_sign",
408 &num_input_bytes_consumed, &output_params, &output_data);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100409 if (!result.isOk()) {
410 printf("Verify: UpdateOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700411 return result;
412 }
413 result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
414 &output_data);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100415 if (result == ErrorCode::VERIFICATION_FAILED) {
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700416 printf("Verify: Failed to verify signature.\n");
417 return result;
418 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100419 if (!result.isOk()) {
420 printf("Verify: FinishOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700421 return result;
422 }
423 printf("Verify: OK\n");
424 return 0;
425}
426
Darren Krahn251cb282015-09-28 08:51:18 -0700427int Encrypt(const std::string& key_name, const std::string& input_filename,
Janis Danisevskisc1460142017-12-18 16:48:46 -0800428 const std::string& output_filename, int32_t flags) {
Darren Krahn251cb282015-09-28 08:51:18 -0700429 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
430 std::string input = ReadFile(input_filename);
431 std::string output;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800432 if (!keystore->encryptWithAuthentication(key_name, input, flags, &output)) {
Darren Krahn251cb282015-09-28 08:51:18 -0700433 printf("EncryptWithAuthentication failed.\n");
434 return 1;
435 }
436 WriteFile(output_filename, output);
437 return 0;
438}
439
440int Decrypt(const std::string& key_name, const std::string& input_filename,
441 const std::string& output_filename) {
442 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
443 std::string input = ReadFile(input_filename);
444 std::string output;
445 if (!keystore->decryptWithAuthentication(key_name, input, &output)) {
446 printf("DecryptWithAuthentication failed.\n");
447 return 1;
448 }
449 WriteFile(output_filename, output);
450 return 0;
451}
452
Janis Danisevskisc1460142017-12-18 16:48:46 -0800453uint32_t securityLevelOption2Flags(const CommandLine& cmd) {
454 if (cmd.HasSwitch("seclevel")) {
455 auto str = cmd.GetSwitchValueASCII("seclevel");
456 if (str == "strongbox") {
457 return KEYSTORE_FLAG_STRONGBOX;
458 } else if (str == "software") {
459 return KEYSTORE_FLAG_FALLBACK;
460 }
461 }
462 return KEYSTORE_FLAG_NONE;
463}
464
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800465class ConfirmationListener
466 : public android::security::BnConfirmationPromptCallback,
467 public std::promise<std::tuple<ConfirmationResponseCode, std::vector<uint8_t>>> {
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500468 public:
469 ConfirmationListener() {}
470
471 virtual ::android::binder::Status
472 onConfirmationPromptCompleted(int32_t result,
473 const ::std::vector<uint8_t>& dataThatWasConfirmed) override {
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800474 this->set_value({static_cast<ConfirmationResponseCode>(result), dataThatWasConfirmed});
475 return ::android::binder::Status::ok();
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500476 }
477};
478
479int Confirmation(const std::string& promptText, const std::string& extraDataHex,
480 const std::string& locale, const std::string& uiOptionsStr,
481 const std::string& cancelAfter) {
482 sp<android::IServiceManager> sm = android::defaultServiceManager();
483 sp<android::IBinder> binder = sm->getService(String16("android.security.keystore"));
484 sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(binder);
Yi Konge353f252018-07-30 01:38:39 -0700485 if (service == nullptr) {
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500486 printf("error: could not connect to keystore service.\n");
487 return 1;
488 }
489
490 if (promptText.size() == 0) {
Janis Danisevskis1a8d5802018-03-14 13:38:07 -0700491 printf("The --prompt_text parameter cannot be empty.\n");
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500492 return 1;
493 }
494
495 std::vector<uint8_t> extraData;
496 if (!base::HexStringToBytes(extraDataHex, &extraData)) {
497 printf("The --extra_data parameter does not appear to be valid hexadecimal.\n");
498 return 1;
499 }
500
501 std::vector<std::string> pieces =
502 base::SplitString(uiOptionsStr, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
503 int uiOptionsAsFlags = 0;
504 for (auto& p : pieces) {
505 int value;
506 if (!base::StringToInt(p, &value)) {
507 printf("Error parsing %s in --ui_options parameter as a number.\n", p.c_str());
508 return 1;
509 }
510 uiOptionsAsFlags |= (1 << value);
511 }
512
513 double cancelAfterValue = 0.0;
514
515 if (cancelAfter.size() > 0 && !base::StringToDouble(cancelAfter, &cancelAfterValue)) {
516 printf("Error parsing %s in --cancel_after parameter as a double.\n", cancelAfter.c_str());
517 return 1;
518 }
519
520 String16 promptText16(promptText.data(), promptText.size());
521 String16 locale16(locale.data(), locale.size());
522
523 sp<ConfirmationListener> listener = new ConfirmationListener();
524
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800525 auto future = listener->get_future();
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500526 int32_t aidl_return;
527 android::binder::Status status = service->presentConfirmationPrompt(
528 listener, promptText16, extraData, locale16, uiOptionsAsFlags, &aidl_return);
529 if (!status.isOk()) {
530 printf("Presenting confirmation prompt failed with binder status '%s'.\n",
531 status.toString8().c_str());
532 return 1;
533 }
534 ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
535 if (responseCode != ConfirmationResponseCode::OK) {
536 printf("Presenting confirmation prompt failed with response code %d.\n", responseCode);
537 return 1;
538 }
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800539 printf("Waiting for prompt to complete - use Ctrl+C to abort...\n");
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500540
541 if (cancelAfterValue > 0.0) {
542 printf("Sleeping %.1f seconds before canceling prompt...\n", cancelAfterValue);
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800543 auto fstatus =
544 future.wait_for(std::chrono::milliseconds(uint64_t(cancelAfterValue * 1000)));
545 if (fstatus == std::future_status::timeout) {
546 status = service->cancelConfirmationPrompt(listener, &aidl_return);
547 if (!status.isOk()) {
548 printf("Canceling confirmation prompt failed with binder status '%s'.\n",
549 status.toString8().c_str());
550 return 1;
551 }
552 responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
553 if (responseCode == ConfirmationResponseCode::Ignored) {
554 // The confirmation was completed by the user so take the response
555 } else if (responseCode != ConfirmationResponseCode::OK) {
556 printf("Canceling confirmation prompt failed with response code %d.\n",
557 responseCode);
558 return 1;
559 }
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500560 }
561 }
562
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800563 future.wait();
564
565 auto [rc, dataThatWasConfirmed] = future.get();
566
567 printf("Confirmation prompt completed\n"
568 "responseCode = %d\n",
569 rc);
570 printf("dataThatWasConfirmed[%zd] = {", dataThatWasConfirmed.size());
571 size_t newLineCountDown = 16;
572 bool hasPrinted = false;
573 for (uint8_t element : dataThatWasConfirmed) {
574 if (hasPrinted) {
575 printf(", ");
576 }
577 if (newLineCountDown == 0) {
578 printf("\n ");
579 newLineCountDown = 32;
580 }
581 printf("0x%02x", element);
582 hasPrinted = true;
583 }
584 printf("}\n");
585
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500586 return 0;
587}
588
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700589} // namespace
590
591int main(int argc, char** argv) {
592 CommandLine::Init(argc, argv);
593 CommandLine* command_line = CommandLine::ForCurrentProcess();
594 CommandLine::StringVector args = command_line->GetArgs();
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800595
596 std::thread thread_pool([] { android::IPCThreadState::self()->joinThreadPool(false); });
597 thread_pool.detach();
598
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700599 if (args.empty()) {
600 PrintUsageAndExit();
601 }
Darren Krahna9474ab2015-11-03 14:38:53 -0800602 if (args[0] == "brillo-platform-test") {
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800603 return BrilloPlatformTest(command_line->GetSwitchValueASCII("prefix"),
604 command_line->HasSwitch("test_for_0_3"));
Darren Krahna9474ab2015-11-03 14:38:53 -0800605 } else if (args[0] == "list-brillo-tests") {
606 return ListTestCases();
607 } else if (args[0] == "add-entropy") {
Janis Danisevskisc1460142017-12-18 16:48:46 -0800608 return AddEntropy(command_line->GetSwitchValueASCII("input"),
609 securityLevelOption2Flags(*command_line));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700610 } else if (args[0] == "generate") {
Janis Danisevskisc1460142017-12-18 16:48:46 -0800611 return GenerateKey(command_line->GetSwitchValueASCII("name"),
612 securityLevelOption2Flags(*command_line));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700613 } else if (args[0] == "get-chars") {
614 return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
615 } else if (args[0] == "export") {
616 return ExportKey(command_line->GetSwitchValueASCII("name"));
617 } else if (args[0] == "delete") {
618 return DeleteKey(command_line->GetSwitchValueASCII("name"));
619 } else if (args[0] == "delete-all") {
620 return DeleteAllKeys();
621 } else if (args[0] == "exists") {
622 return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
623 } else if (args[0] == "list") {
624 return List(command_line->GetSwitchValueASCII("prefix"));
625 } else if (args[0] == "sign-verify") {
626 return SignAndVerify(command_line->GetSwitchValueASCII("name"));
Darren Krahn251cb282015-09-28 08:51:18 -0700627 } else if (args[0] == "encrypt") {
Janis Danisevskisc1460142017-12-18 16:48:46 -0800628 return Encrypt(
629 command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"),
630 command_line->GetSwitchValueASCII("out"), securityLevelOption2Flags(*command_line));
Darren Krahn251cb282015-09-28 08:51:18 -0700631 } else if (args[0] == "decrypt") {
632 return Decrypt(command_line->GetSwitchValueASCII("name"),
633 command_line->GetSwitchValueASCII("in"),
634 command_line->GetSwitchValueASCII("out"));
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500635 } else if (args[0] == "confirmation") {
Janis Danisevskis1a8d5802018-03-14 13:38:07 -0700636 return Confirmation(command_line->GetSwitchValueNative("prompt_text"),
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500637 command_line->GetSwitchValueASCII("extra_data"),
638 command_line->GetSwitchValueASCII("locale"),
639 command_line->GetSwitchValueASCII("ui_options"),
640 command_line->GetSwitchValueASCII("cancel_after"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700641 } else {
642 PrintUsageAndExit();
643 }
644 return 0;
645}