blob: e1fb2d9c67e215eb7eb727f10870dd10532c2fb6 [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
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070020#include <base/command_line.h>
21#include <base/files/file_util.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050022#include <base/strings/string_number_conversions.h>
23#include <base/strings/string_split.h>
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070024#include <base/strings/string_util.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050025#include <base/strings/utf_string_conversions.h>
26#include <base/threading/platform_thread.h>
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070027#include <keystore/keymaster_types.h>
28#include <keystore/keystore_client_impl.h>
Darren Krahn69a3dbc2015-09-22 16:21:04 -070029
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050030#include <android/hardware/confirmationui/1.0/types.h>
31#include <android/security/BnConfirmationPromptCallback.h>
Rob Barnesbb6cabd2018-10-04 17:10:37 -060032#include <android/security/keystore/IKeystoreService.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050033
34#include <binder/IPCThreadState.h>
35#include <binder/IServiceManager.h>
36
37//#include <keystore/keystore.h>
38
Darren Krahn69a3dbc2015-09-22 16:21:04 -070039using base::CommandLine;
Darren Krahn69a3dbc2015-09-22 16:21:04 -070040using keystore::KeystoreClient;
41
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050042using android::sp;
43using android::String16;
Rob Barnesbb6cabd2018-10-04 17:10:37 -060044using android::security::keystore::IKeystoreService;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050045using base::CommandLine;
46using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
47
Darren Krahn69a3dbc2015-09-22 16:21:04 -070048namespace {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010049using namespace keystore;
Darren Krahn69a3dbc2015-09-22 16:21:04 -070050
Darren Krahna9474ab2015-11-03 14:38:53 -080051struct TestCase {
52 std::string name;
53 bool required_for_brillo_pts;
54 AuthorizationSet parameters;
55};
56
Darren Krahn69a3dbc2015-09-22 16:21:04 -070057void PrintUsageAndExit() {
58 printf("Usage: keystore_client_v2 <command> [options]\n");
Darren Krahn82f4f5b2016-03-03 16:21:07 -080059 printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
Darren Krahna9474ab2015-11-03 14:38:53 -080060 " list-brillo-tests\n"
Janis Danisevskisc1460142017-12-18 16:48:46 -080061 " add-entropy --input=<entropy> [--seclevel=software|strongbox|tee(default)]\n"
62 " generate --name=<key_name> [--seclevel=software|strongbox|tee(default)]\n"
Darren Krahn69a3dbc2015-09-22 16:21:04 -070063 " get-chars --name=<key_name>\n"
64 " export --name=<key_name>\n"
65 " delete --name=<key_name>\n"
66 " delete-all\n"
67 " exists --name=<key_name>\n"
68 " list [--prefix=<key_name_prefix>]\n"
Rob Barneseb7f79b2018-11-08 15:44:10 -070069 " list-apps-with-keys\n"
Darren Krahn251cb282015-09-28 08:51:18 -070070 " sign-verify --name=<key_name>\n"
Janis Danisevskisc1460142017-12-18 16:48:46 -080071 " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n"
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050072 " [--seclevel=software|strongbox|tee(default)]\n"
73 " confirmation --prompt_text=<PromptText> --extra_data=<hex>\n"
74 " --locale=<locale> [--ui_options=<list_of_ints>]\n"
75 " --cancel_after=<seconds>\n");
Darren Krahn69a3dbc2015-09-22 16:21:04 -070076 exit(1);
77}
78
79std::unique_ptr<KeystoreClient> CreateKeystoreInstance() {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010080 return std::unique_ptr<KeystoreClient>(
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070081 static_cast<KeystoreClient*>(new keystore::KeystoreClientImpl));
Darren Krahn69a3dbc2015-09-22 16:21:04 -070082}
83
Darren Krahna9474ab2015-11-03 14:38:53 -080084void PrintTags(const AuthorizationSet& parameters) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010085 for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070086 auto tag_str = toString(iter->tag);
87 printf(" %s\n", tag_str.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -080088 }
89}
90
91void PrintKeyCharacteristics(const AuthorizationSet& hardware_enforced_characteristics,
92 const AuthorizationSet& software_enforced_characteristics) {
93 printf("Hardware:\n");
94 PrintTags(hardware_enforced_characteristics);
95 printf("Software:\n");
96 PrintTags(software_enforced_characteristics);
97}
98
99bool TestKey(const std::string& name, bool required, const AuthorizationSet& parameters) {
100 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
101 AuthorizationSet hardware_enforced_characteristics;
102 AuthorizationSet software_enforced_characteristics;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800103 auto result =
104 keystore->generateKey("tmp", parameters, 0 /*flags*/, &hardware_enforced_characteristics,
105 &software_enforced_characteristics);
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800106 const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100107 if (!result.isOk()) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800108 LOG(ERROR) << "Failed to generate key: " << result;
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800109 printf("[%s] %s\n", kBoldRedAbort, name.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -0800110 return false;
111 }
112 result = keystore->deleteKey("tmp");
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100113 if (!result.isOk()) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800114 LOG(ERROR) << "Failed to delete key: " << result;
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800115 printf("[%s] %s\n", kBoldRedAbort, name.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -0800116 return false;
117 }
118 printf("===============================================================\n");
119 printf("%s Key Characteristics:\n", name.c_str());
120 PrintKeyCharacteristics(hardware_enforced_characteristics, software_enforced_characteristics);
121 bool hardware_backed = (hardware_enforced_characteristics.size() > 0);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100122 if (software_enforced_characteristics.GetTagCount(TAG_ALGORITHM) > 0 ||
123 software_enforced_characteristics.GetTagCount(TAG_KEY_SIZE) > 0 ||
124 software_enforced_characteristics.GetTagCount(TAG_RSA_PUBLIC_EXPONENT) > 0) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800125 VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
126 hardware_backed = false;
127 }
128 const char kBoldRedFail[] = "\033[1;31mFAIL\033[0m";
129 const char kBoldGreenPass[] = "\033[1;32mPASS\033[0m";
130 const char kBoldYellowWarn[] = "\033[1;33mWARN\033[0m";
131 printf("[%s] %s\n",
132 hardware_backed ? kBoldGreenPass : (required ? kBoldRedFail : kBoldYellowWarn),
133 name.c_str());
134
135 return (hardware_backed || !required);
136}
137
138AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
139 AuthorizationSetBuilder parameters;
140 parameters.RsaSigningKey(key_size, 65537)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100141 .Digest(Digest::SHA_2_256)
142 .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
143 .Padding(PaddingMode::RSA_PSS)
144 .Authorization(TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800145 if (!sha256_only) {
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700146 parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
Darren Krahna9474ab2015-11-03 14:38:53 -0800147 }
Yi Kong53b02f72018-07-26 17:13:50 -0700148 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800149}
150
151AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) {
152 AuthorizationSetBuilder parameters;
153 parameters.RsaEncryptionKey(key_size, 65537)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100154 .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)
155 .Padding(PaddingMode::RSA_OAEP)
156 .Authorization(TAG_NO_AUTH_REQUIRED);
Yi Kong53b02f72018-07-26 17:13:50 -0700157 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800158}
159
160AuthorizationSet GetECDSAParameters(uint32_t key_size, bool sha256_only) {
161 AuthorizationSetBuilder parameters;
162 parameters.EcdsaSigningKey(key_size)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100163 .Digest(Digest::SHA_2_256)
164 .Authorization(TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800165 if (!sha256_only) {
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700166 parameters.Digest(Digest::SHA_2_224).Digest(Digest::SHA_2_384).Digest(Digest::SHA_2_512);
Darren Krahna9474ab2015-11-03 14:38:53 -0800167 }
Yi Kong53b02f72018-07-26 17:13:50 -0700168 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800169}
170
171AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
172 AuthorizationSetBuilder parameters;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100173 parameters.AesEncryptionKey(key_size).Authorization(TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800174 if (with_gcm_mode) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100175 parameters.Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
176 .Authorization(TAG_MIN_MAC_LENGTH, 128);
Darren Krahna9474ab2015-11-03 14:38:53 -0800177 } else {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100178 parameters.Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
179 parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
180 parameters.Authorization(TAG_BLOCK_MODE, BlockMode::CTR);
181 parameters.Padding(PaddingMode::NONE);
Darren Krahna9474ab2015-11-03 14:38:53 -0800182 }
Yi Kong53b02f72018-07-26 17:13:50 -0700183 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800184}
185
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100186AuthorizationSet GetHMACParameters(uint32_t key_size, Digest digest) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800187 AuthorizationSetBuilder parameters;
188 parameters.HmacKey(key_size)
189 .Digest(digest)
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100190 .Authorization(TAG_MIN_MAC_LENGTH, 224)
191 .Authorization(TAG_NO_AUTH_REQUIRED);
Yi Kong53b02f72018-07-26 17:13:50 -0700192 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800193}
194
195std::vector<TestCase> GetTestCases() {
196 TestCase test_cases[] = {
197 {"RSA-2048 Sign", true, GetRSASignParameters(2048, true)},
198 {"RSA-2048 Sign (more digests)", false, GetRSASignParameters(2048, false)},
199 {"RSA-3072 Sign", false, GetRSASignParameters(3072, false)},
200 {"RSA-4096 Sign", false, GetRSASignParameters(4096, false)},
201 {"RSA-2048 Encrypt", true, GetRSAEncryptParameters(2048)},
202 {"RSA-3072 Encrypt", false, GetRSAEncryptParameters(3072)},
203 {"RSA-4096 Encrypt", false, GetRSAEncryptParameters(4096)},
204 {"ECDSA-P256 Sign", true, GetECDSAParameters(256, true)},
205 {"ECDSA-P256 Sign (more digests)", false, GetECDSAParameters(256, false)},
206 {"ECDSA-P224 Sign", false, GetECDSAParameters(224, false)},
207 {"ECDSA-P384 Sign", false, GetECDSAParameters(384, false)},
208 {"ECDSA-P521 Sign", false, GetECDSAParameters(521, false)},
209 {"AES-128", true, GetAESParameters(128, false)},
210 {"AES-256", true, GetAESParameters(256, false)},
211 {"AES-128-GCM", false, GetAESParameters(128, true)},
212 {"AES-256-GCM", false, GetAESParameters(256, true)},
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100213 {"HMAC-SHA256-16", true, GetHMACParameters(16, Digest::SHA_2_256)},
214 {"HMAC-SHA256-32", true, GetHMACParameters(32, Digest::SHA_2_256)},
215 {"HMAC-SHA256-64", false, GetHMACParameters(64, Digest::SHA_2_256)},
216 {"HMAC-SHA224-32", false, GetHMACParameters(32, Digest::SHA_2_224)},
217 {"HMAC-SHA384-32", false, GetHMACParameters(32, Digest::SHA_2_384)},
218 {"HMAC-SHA512-32", false, GetHMACParameters(32, Digest::SHA_2_512)},
Darren Krahna9474ab2015-11-03 14:38:53 -0800219 };
220 return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
221}
222
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800223int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) {
224 const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m";
225 if (test_for_0_3) {
226 printf("%s: Testing for keymaster v0.3. "
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700227 "This does not meet Brillo requirements.\n",
228 kBoldYellowWarning);
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800229 }
Darren Krahna9474ab2015-11-03 14:38:53 -0800230 int test_count = 0;
231 int fail_count = 0;
232 std::vector<TestCase> test_cases = GetTestCases();
233 for (const auto& test_case : test_cases) {
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800234 if (!prefix.empty() &&
235 !base::StartsWith(test_case.name, prefix, base::CompareCase::SENSITIVE)) {
236 continue;
237 }
238 if (test_for_0_3 &&
239 (base::StartsWith(test_case.name, "AES", base::CompareCase::SENSITIVE) ||
240 base::StartsWith(test_case.name, "HMAC", base::CompareCase::SENSITIVE))) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800241 continue;
242 }
243 ++test_count;
244 if (!TestKey(test_case.name, test_case.required_for_brillo_pts, test_case.parameters)) {
245 VLOG(1) << "Test failed: " << test_case.name;
246 ++fail_count;
247 }
248 }
249 return fail_count;
250}
251
252int ListTestCases() {
253 const char kBoldGreenRequired[] = "\033[1;32mREQUIRED\033[0m";
254 const char kBoldYellowRecommended[] = "\033[1;33mRECOMMENDED\033[0m";
255 std::vector<TestCase> test_cases = GetTestCases();
256 for (const auto& test_case : test_cases) {
257 printf("%s : %s\n", test_case.name.c_str(),
258 test_case.required_for_brillo_pts ? kBoldGreenRequired : kBoldYellowRecommended);
259 }
260 return 0;
261}
262
Darren Krahn251cb282015-09-28 08:51:18 -0700263std::string ReadFile(const std::string& filename) {
264 std::string content;
265 base::FilePath path(filename);
266 if (!base::ReadFileToString(path, &content)) {
267 printf("Failed to read file: %s\n", filename.c_str());
268 exit(1);
269 }
270 return content;
271}
272
273void WriteFile(const std::string& filename, const std::string& content) {
274 base::FilePath path(filename);
275 int size = content.size();
276 if (base::WriteFile(path, content.data(), size) != size) {
277 printf("Failed to write file: %s\n", filename.c_str());
278 exit(1);
279 }
280}
281
Janis Danisevskisc1460142017-12-18 16:48:46 -0800282int AddEntropy(const std::string& input, int32_t flags) {
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700283 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
Janis Danisevskisc1460142017-12-18 16:48:46 -0800284 int32_t result = keystore->addRandomNumberGeneratorEntropy(input, flags);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700285 printf("AddEntropy: %d\n", result);
286 return result;
287}
288
Rob Barneseb7f79b2018-11-08 15:44:10 -0700289// Note: auth_bound keys created with this tool will not be usable.
290int GenerateKey(const std::string& name, int32_t flags, bool auth_bound) {
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)
Rob Barneseb7f79b2018-11-08 15:44:10 -0700299 .Padding(PaddingMode::RSA_PSS);
300 if (auth_bound) {
301 // Gatekeeper normally generates the secure user id.
302 // Using zero allows the key to be created, but it will not be usuable.
303 params.Authorization(TAG_USER_SECURE_ID, 0);
304 } else {
305 params.Authorization(TAG_NO_AUTH_REQUIRED);
306 }
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700307 AuthorizationSet hardware_enforced_characteristics;
308 AuthorizationSet software_enforced_characteristics;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800309 auto result = keystore->generateKey(name, params, flags, &hardware_enforced_characteristics,
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700310 &software_enforced_characteristics);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100311 printf("GenerateKey: %d\n", int32_t(result));
312 if (result.isOk()) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800313 PrintKeyCharacteristics(hardware_enforced_characteristics,
314 software_enforced_characteristics);
315 }
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700316 return result;
317}
318
319int GetCharacteristics(const std::string& name) {
320 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
321 AuthorizationSet hardware_enforced_characteristics;
322 AuthorizationSet software_enforced_characteristics;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100323 auto result = keystore->getKeyCharacteristics(name, &hardware_enforced_characteristics,
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700324 &software_enforced_characteristics);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100325 printf("GetCharacteristics: %d\n", int32_t(result));
326 if (result.isOk()) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800327 PrintKeyCharacteristics(hardware_enforced_characteristics,
328 software_enforced_characteristics);
329 }
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700330 return result;
331}
332
333int ExportKey(const std::string& name) {
334 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
335 std::string data;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100336 int32_t result = keystore->exportKey(KeyFormat::X509, name, &data);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700337 printf("ExportKey: %d (%zu)\n", result, data.size());
338 return result;
339}
340
341int DeleteKey(const std::string& name) {
342 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
343 int32_t result = keystore->deleteKey(name);
344 printf("DeleteKey: %d\n", result);
345 return result;
346}
347
348int DeleteAllKeys() {
349 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
350 int32_t result = keystore->deleteAllKeys();
351 printf("DeleteAllKeys: %d\n", result);
352 return result;
353}
354
355int DoesKeyExist(const std::string& name) {
356 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
357 printf("DoesKeyExist: %s\n", keystore->doesKeyExist(name) ? "yes" : "no");
358 return 0;
359}
360
361int List(const std::string& prefix) {
362 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
363 std::vector<std::string> key_list;
364 if (!keystore->listKeys(prefix, &key_list)) {
365 printf("ListKeys failed.\n");
366 return 1;
367 }
368 printf("Keys:\n");
369 for (const auto& key_name : key_list) {
370 printf(" %s\n", key_name.c_str());
371 }
372 return 0;
373}
374
Rob Barneseb7f79b2018-11-08 15:44:10 -0700375int ListAppsWithKeys() {
376
377 sp<android::IServiceManager> sm = android::defaultServiceManager();
378 sp<android::IBinder> binder = sm->getService(String16("android.security.keystore"));
379 sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(binder);
380 if (service == nullptr) {
381 fprintf(stderr, "Error connecting to keystore service.\n");
382 return 1;
383 }
384 int32_t aidl_return;
385 ::std::vector<int32_t> uids(100);
386 android::binder::Status status = service->listUidsOfAuthBoundKeys(&uids, &aidl_return);
387 if (!status.isOk()) {
388 fprintf(stderr, "Requesting uids of auth bound keys failed with error %s.\n",
389 status.toString8().c_str());
390 return 1;
391 }
392 if (!KeyStoreNativeReturnCode(aidl_return).isOk()) {
393 fprintf(stderr, "Requesting uids of auth bound keys failed with code %d.\n", aidl_return);
394 return 1;
395 }
396 printf("Apps with auth bound keys:\n");
397 for (auto i = uids.begin(); i != uids.end(); ++i) {
398 if (*i == 0) break;
399 printf("%d\n", *i);
400 }
401 return 0;
402}
403
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700404int SignAndVerify(const std::string& name) {
405 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
406 AuthorizationSetBuilder sign_params;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100407 sign_params.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN);
408 sign_params.Digest(Digest::SHA_2_256);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700409 AuthorizationSet output_params;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100410 uint64_t handle;
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700411 auto result =
412 keystore->beginOperation(KeyPurpose::SIGN, name, sign_params, &output_params, &handle);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100413 if (!result.isOk()) {
414 printf("Sign: BeginOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700415 return result;
416 }
417 AuthorizationSet empty_params;
418 size_t num_input_bytes_consumed;
419 std::string output_data;
420 result = keystore->updateOperation(handle, empty_params, "data_to_sign",
421 &num_input_bytes_consumed, &output_params, &output_data);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100422 if (!result.isOk()) {
423 printf("Sign: UpdateOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700424 return result;
425 }
426 result = keystore->finishOperation(handle, empty_params, std::string() /*signature_to_verify*/,
427 &output_params, &output_data);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100428 if (!result.isOk()) {
429 printf("Sign: FinishOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700430 return result;
431 }
432 printf("Sign: %zu bytes.\n", output_data.size());
433 // We have a signature, now verify it.
434 std::string signature_to_verify = output_data;
Darren Krahn251cb282015-09-28 08:51:18 -0700435 output_data.clear();
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700436 result =
437 keystore->beginOperation(KeyPurpose::VERIFY, name, sign_params, &output_params, &handle);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100438 if (!result.isOk()) {
439 printf("Verify: BeginOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700440 return result;
441 }
442 result = keystore->updateOperation(handle, empty_params, "data_to_sign",
443 &num_input_bytes_consumed, &output_params, &output_data);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100444 if (!result.isOk()) {
445 printf("Verify: UpdateOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700446 return result;
447 }
448 result = keystore->finishOperation(handle, empty_params, signature_to_verify, &output_params,
449 &output_data);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100450 if (result == ErrorCode::VERIFICATION_FAILED) {
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700451 printf("Verify: Failed to verify signature.\n");
452 return result;
453 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100454 if (!result.isOk()) {
455 printf("Verify: FinishOperation failed: %d\n", int32_t(result));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700456 return result;
457 }
458 printf("Verify: OK\n");
459 return 0;
460}
461
Darren Krahn251cb282015-09-28 08:51:18 -0700462int Encrypt(const std::string& key_name, const std::string& input_filename,
Janis Danisevskisc1460142017-12-18 16:48:46 -0800463 const std::string& output_filename, int32_t flags) {
Darren Krahn251cb282015-09-28 08:51:18 -0700464 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
465 std::string input = ReadFile(input_filename);
466 std::string output;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800467 if (!keystore->encryptWithAuthentication(key_name, input, flags, &output)) {
Darren Krahn251cb282015-09-28 08:51:18 -0700468 printf("EncryptWithAuthentication failed.\n");
469 return 1;
470 }
471 WriteFile(output_filename, output);
472 return 0;
473}
474
475int Decrypt(const std::string& key_name, const std::string& input_filename,
476 const std::string& output_filename) {
477 std::unique_ptr<KeystoreClient> keystore = CreateKeystoreInstance();
478 std::string input = ReadFile(input_filename);
479 std::string output;
480 if (!keystore->decryptWithAuthentication(key_name, input, &output)) {
481 printf("DecryptWithAuthentication failed.\n");
482 return 1;
483 }
484 WriteFile(output_filename, output);
485 return 0;
486}
487
Janis Danisevskisc1460142017-12-18 16:48:46 -0800488uint32_t securityLevelOption2Flags(const CommandLine& cmd) {
489 if (cmd.HasSwitch("seclevel")) {
490 auto str = cmd.GetSwitchValueASCII("seclevel");
491 if (str == "strongbox") {
492 return KEYSTORE_FLAG_STRONGBOX;
493 } else if (str == "software") {
494 return KEYSTORE_FLAG_FALLBACK;
495 }
496 }
497 return KEYSTORE_FLAG_NONE;
498}
499
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500500class ConfirmationListener : public android::security::BnConfirmationPromptCallback {
501 public:
502 ConfirmationListener() {}
503
504 virtual ::android::binder::Status
505 onConfirmationPromptCompleted(int32_t result,
506 const ::std::vector<uint8_t>& dataThatWasConfirmed) override {
507 ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(result);
508 printf("Confirmation prompt completed\n"
509 "responseCode = %d\n",
510 responseCode);
511 printf("dataThatWasConfirmed[%zd] = {", dataThatWasConfirmed.size());
512 size_t newLineCountDown = 16;
513 bool hasPrinted = false;
514 for (uint8_t element : dataThatWasConfirmed) {
515 if (hasPrinted) {
516 printf(", ");
517 }
518 if (newLineCountDown == 0) {
519 printf("\n ");
520 newLineCountDown = 32;
521 }
522 printf("0x%02x", element);
523 hasPrinted = true;
524 }
525 printf("}\n");
526 exit(0);
527 }
528};
529
530int Confirmation(const std::string& promptText, const std::string& extraDataHex,
531 const std::string& locale, const std::string& uiOptionsStr,
532 const std::string& cancelAfter) {
533 sp<android::IServiceManager> sm = android::defaultServiceManager();
534 sp<android::IBinder> binder = sm->getService(String16("android.security.keystore"));
535 sp<IKeystoreService> service = android::interface_cast<IKeystoreService>(binder);
Yi Konge353f252018-07-30 01:38:39 -0700536 if (service == nullptr) {
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500537 printf("error: could not connect to keystore service.\n");
538 return 1;
539 }
540
541 if (promptText.size() == 0) {
Janis Danisevskis1a8d5802018-03-14 13:38:07 -0700542 printf("The --prompt_text parameter cannot be empty.\n");
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500543 return 1;
544 }
545
546 std::vector<uint8_t> extraData;
547 if (!base::HexStringToBytes(extraDataHex, &extraData)) {
548 printf("The --extra_data parameter does not appear to be valid hexadecimal.\n");
549 return 1;
550 }
551
552 std::vector<std::string> pieces =
553 base::SplitString(uiOptionsStr, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
554 int uiOptionsAsFlags = 0;
555 for (auto& p : pieces) {
556 int value;
557 if (!base::StringToInt(p, &value)) {
558 printf("Error parsing %s in --ui_options parameter as a number.\n", p.c_str());
559 return 1;
560 }
561 uiOptionsAsFlags |= (1 << value);
562 }
563
564 double cancelAfterValue = 0.0;
565
566 if (cancelAfter.size() > 0 && !base::StringToDouble(cancelAfter, &cancelAfterValue)) {
567 printf("Error parsing %s in --cancel_after parameter as a double.\n", cancelAfter.c_str());
568 return 1;
569 }
570
571 String16 promptText16(promptText.data(), promptText.size());
572 String16 locale16(locale.data(), locale.size());
573
574 sp<ConfirmationListener> listener = new ConfirmationListener();
575
576 int32_t aidl_return;
577 android::binder::Status status = service->presentConfirmationPrompt(
578 listener, promptText16, extraData, locale16, uiOptionsAsFlags, &aidl_return);
579 if (!status.isOk()) {
580 printf("Presenting confirmation prompt failed with binder status '%s'.\n",
581 status.toString8().c_str());
582 return 1;
583 }
584 ConfirmationResponseCode responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
585 if (responseCode != ConfirmationResponseCode::OK) {
586 printf("Presenting confirmation prompt failed with response code %d.\n", responseCode);
587 return 1;
588 }
589
590 if (cancelAfterValue > 0.0) {
591 printf("Sleeping %.1f seconds before canceling prompt...\n", cancelAfterValue);
592 base::PlatformThread::Sleep(base::TimeDelta::FromSecondsD(cancelAfterValue));
593 status = service->cancelConfirmationPrompt(listener, &aidl_return);
594 if (!status.isOk()) {
595 printf("Canceling confirmation prompt failed with binder status '%s'.\n",
596 status.toString8().c_str());
597 return 1;
598 }
599 responseCode = static_cast<ConfirmationResponseCode>(aidl_return);
600 if (responseCode != ConfirmationResponseCode::OK) {
601 printf("Canceling confirmation prompt failed with response code %d.\n", responseCode);
602 return 1;
603 }
604 }
605
606 printf("Waiting for prompt to complete - use Ctrl+C to abort...\n");
607 // Use the main thread to process Binder transactions.
608 android::IPCThreadState::self()->joinThreadPool();
609 return 0;
610}
611
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700612} // namespace
613
614int main(int argc, char** argv) {
615 CommandLine::Init(argc, argv);
616 CommandLine* command_line = CommandLine::ForCurrentProcess();
617 CommandLine::StringVector args = command_line->GetArgs();
618 if (args.empty()) {
619 PrintUsageAndExit();
620 }
Darren Krahna9474ab2015-11-03 14:38:53 -0800621 if (args[0] == "brillo-platform-test") {
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800622 return BrilloPlatformTest(command_line->GetSwitchValueASCII("prefix"),
623 command_line->HasSwitch("test_for_0_3"));
Darren Krahna9474ab2015-11-03 14:38:53 -0800624 } else if (args[0] == "list-brillo-tests") {
625 return ListTestCases();
626 } else if (args[0] == "add-entropy") {
Janis Danisevskisc1460142017-12-18 16:48:46 -0800627 return AddEntropy(command_line->GetSwitchValueASCII("input"),
628 securityLevelOption2Flags(*command_line));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700629 } else if (args[0] == "generate") {
Janis Danisevskisc1460142017-12-18 16:48:46 -0800630 return GenerateKey(command_line->GetSwitchValueASCII("name"),
Rob Barneseb7f79b2018-11-08 15:44:10 -0700631 securityLevelOption2Flags(*command_line),
632 command_line->HasSwitch("auth_bound"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700633 } else if (args[0] == "get-chars") {
634 return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
635 } else if (args[0] == "export") {
636 return ExportKey(command_line->GetSwitchValueASCII("name"));
637 } else if (args[0] == "delete") {
638 return DeleteKey(command_line->GetSwitchValueASCII("name"));
639 } else if (args[0] == "delete-all") {
640 return DeleteAllKeys();
641 } else if (args[0] == "exists") {
642 return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
643 } else if (args[0] == "list") {
644 return List(command_line->GetSwitchValueASCII("prefix"));
Rob Barneseb7f79b2018-11-08 15:44:10 -0700645 } else if (args[0] == "list-apps-with-keys") {
646 return ListAppsWithKeys();
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700647 } else if (args[0] == "sign-verify") {
648 return SignAndVerify(command_line->GetSwitchValueASCII("name"));
Darren Krahn251cb282015-09-28 08:51:18 -0700649 } else if (args[0] == "encrypt") {
Janis Danisevskisc1460142017-12-18 16:48:46 -0800650 return Encrypt(
651 command_line->GetSwitchValueASCII("name"), command_line->GetSwitchValueASCII("in"),
652 command_line->GetSwitchValueASCII("out"), securityLevelOption2Flags(*command_line));
Darren Krahn251cb282015-09-28 08:51:18 -0700653 } else if (args[0] == "decrypt") {
654 return Decrypt(command_line->GetSwitchValueASCII("name"),
655 command_line->GetSwitchValueASCII("in"),
656 command_line->GetSwitchValueASCII("out"));
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500657 } else if (args[0] == "confirmation") {
Janis Danisevskis1a8d5802018-03-14 13:38:07 -0700658 return Confirmation(command_line->GetSwitchValueNative("prompt_text"),
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500659 command_line->GetSwitchValueASCII("extra_data"),
660 command_line->GetSwitchValueASCII("locale"),
661 command_line->GetSwitchValueASCII("ui_options"),
662 command_line->GetSwitchValueASCII("cancel_after"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700663 } else {
664 PrintUsageAndExit();
665 }
666 return 0;
667}