blob: 1cfb4f692bddfba26e261249eb9a15c2286f989c [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>
Janis Danisevskis2437fde2021-03-08 11:30:11 -080018#include <iomanip>
19#include <iostream>
Darren Krahn69a3dbc2015-09-22 16:21:04 -070020#include <memory>
21#include <string>
22#include <vector>
23
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070024#include <base/command_line.h>
25#include <base/files/file_util.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050026#include <base/strings/string_number_conversions.h>
27#include <base/strings/string_split.h>
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070028#include <base/strings/string_util.h>
Darren Krahn69a3dbc2015-09-22 16:21:04 -070029
Janis Danisevskis2437fde2021-03-08 11:30:11 -080030#include <aidl/android/security/apc/BnConfirmationCallback.h>
31#include <aidl/android/security/apc/IProtectedConfirmation.h>
32#include <aidl/android/system/keystore2/IKeystoreService.h>
33#include <aidl/android/system/keystore2/ResponseCode.h>
34#include <android/binder_manager.h>
35#include <android/binder_process.h>
36#include <keymint_support/authorization_set.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050037
Janis Danisevskis2437fde2021-03-08 11:30:11 -080038#include <openssl/evp.h>
39#include <openssl/mem.h>
40#include <openssl/x509.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050041
Janis Danisevskis2437fde2021-03-08 11:30:11 -080042#include "keystore_client.pb.h"
43
44namespace apc = ::aidl::android::security::apc;
45namespace keymint = ::aidl::android::hardware::security::keymint;
46namespace ks2 = ::aidl::android::system::keystore2;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050047
Darren Krahn69a3dbc2015-09-22 16:21:04 -070048using base::CommandLine;
Janis Danisevskis2437fde2021-03-08 11:30:11 -080049using keystore::EncryptedData;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050050
Darren Krahn69a3dbc2015-09-22 16:21:04 -070051namespace {
52
Darren Krahna9474ab2015-11-03 14:38:53 -080053struct TestCase {
54 std::string name;
55 bool required_for_brillo_pts;
Janis Danisevskis2437fde2021-03-08 11:30:11 -080056 keymint::AuthorizationSet parameters;
Darren Krahna9474ab2015-11-03 14:38:53 -080057};
58
Janis Danisevskis2cb4f092021-05-17 13:25:07 -070059constexpr const char keystore2_service_name[] = "android.system.keystore2.IKeystoreService/default";
Janis Danisevskis2437fde2021-03-08 11:30:11 -080060
61int unwrapError(const ndk::ScopedAStatus& status) {
62 if (status.isOk()) return 0;
63 if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) {
64 return status.getServiceSpecificError();
65 } else {
66 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
67 }
68}
69
70ks2::KeyDescriptor keyDescriptor(const std::string& alias) {
71 return {
72 .domain = ks2::Domain::APP,
73 .nspace = -1, // ignored - should be -1.
74 .alias = alias,
75 .blob = {},
76 };
77}
78
Darren Krahn69a3dbc2015-09-22 16:21:04 -070079void PrintUsageAndExit() {
80 printf("Usage: keystore_client_v2 <command> [options]\n");
Darren Krahn82f4f5b2016-03-03 16:21:07 -080081 printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
Darren Krahna9474ab2015-11-03 14:38:53 -080082 " list-brillo-tests\n"
Janis Danisevskisc1460142017-12-18 16:48:46 -080083 " add-entropy --input=<entropy> [--seclevel=software|strongbox|tee(default)]\n"
84 " generate --name=<key_name> [--seclevel=software|strongbox|tee(default)]\n"
Darren Krahn69a3dbc2015-09-22 16:21:04 -070085 " get-chars --name=<key_name>\n"
86 " export --name=<key_name>\n"
87 " delete --name=<key_name>\n"
88 " delete-all\n"
89 " exists --name=<key_name>\n"
90 " list [--prefix=<key_name_prefix>]\n"
Rob Barneseb7f79b2018-11-08 15:44:10 -070091 " list-apps-with-keys\n"
Darren Krahn251cb282015-09-28 08:51:18 -070092 " sign-verify --name=<key_name>\n"
Janis Danisevskisc1460142017-12-18 16:48:46 -080093 " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n"
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050094 " [--seclevel=software|strongbox|tee(default)]\n"
95 " confirmation --prompt_text=<PromptText> --extra_data=<hex>\n"
96 " --locale=<locale> [--ui_options=<list_of_ints>]\n"
97 " --cancel_after=<seconds>\n");
Darren Krahn69a3dbc2015-09-22 16:21:04 -070098 exit(1);
99}
100
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800101std::shared_ptr<ks2::IKeystoreService> CreateKeystoreInstance() {
102 ::ndk::SpAIBinder keystoreBinder(AServiceManager_checkService(keystore2_service_name));
103 auto result = ks2::IKeystoreService::fromBinder(keystoreBinder);
104 if (result) return result;
105 std::cerr << "Unable to connect to Keystore.";
106 exit(-1);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700107}
108
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800109std::shared_ptr<ks2::IKeystoreSecurityLevel>
110GetSecurityLevelInterface(std::shared_ptr<ks2::IKeystoreService> keystore,
111 keymint::SecurityLevel securitylevel) {
112 std::shared_ptr<ks2::IKeystoreSecurityLevel> sec_level;
113 auto rc = keystore->getSecurityLevel(securitylevel, &sec_level);
114 if (rc.isOk()) return sec_level;
115 std::cerr << "Unable to get security level interface from Keystore: " << rc.getDescription();
116 exit(-1);
117}
118
119bool isHardwareEnforced(const ks2::Authorization& a) {
120 return !(a.securityLevel == keymint::SecurityLevel::SOFTWARE ||
121 a.securityLevel == keymint::SecurityLevel::KEYSTORE);
122}
123
124void PrintTags(const std::vector<ks2::Authorization>& characteristics, bool printHardwareEnforced) {
125 for (const auto& a : characteristics) {
126 if (isHardwareEnforced(a) == printHardwareEnforced) {
127 std::cout << toString(a.keyParameter.tag) << "\n";
128 }
Darren Krahna9474ab2015-11-03 14:38:53 -0800129 }
130}
131
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800132void PrintKeyCharacteristics(const std::vector<ks2::Authorization>& characteristics) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800133 printf("Hardware:\n");
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800134 PrintTags(characteristics, true /* printHardwareEnforced */);
Darren Krahna9474ab2015-11-03 14:38:53 -0800135 printf("Software:\n");
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800136 PrintTags(characteristics, false /* printHardwareEnforced */);
Darren Krahna9474ab2015-11-03 14:38:53 -0800137}
138
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800139const char kEncryptSuffix[] = "_ENC";
140const char kAuthenticateSuffix[] = "_AUTH";
141constexpr uint32_t kAESKeySize = 256; // bits
142constexpr uint32_t kHMACKeySize = 256; // bits
143constexpr uint32_t kHMACOutputSize = 256; // bits
144
145bool verifyEncryptionKeyAttributes(const std::vector<ks2::Authorization> authorizations) {
146 bool verified = true;
147 verified =
148 verified &&
149 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
150 return a.keyParameter.tag == keymint::Tag::ALGORITHM &&
151 a.keyParameter.value ==
152 keymint::KeyParameterValue::make<keymint::KeyParameterValue::algorithm>(
153 keymint::Algorithm::AES);
154 });
155
156 verified =
157 verified &&
158 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
159 return a.keyParameter.tag == keymint::Tag::KEY_SIZE &&
160 a.keyParameter.value ==
161 keymint::KeyParameterValue::make<keymint::KeyParameterValue::integer>(
162 kAESKeySize);
163 });
164
165 verified =
166 verified &&
167 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
168 return a.keyParameter.tag == keymint::Tag::BLOCK_MODE &&
169 a.keyParameter.value ==
170 keymint::KeyParameterValue::make<keymint::KeyParameterValue::blockMode>(
171 keymint::BlockMode::CBC);
172 });
173
174 verified =
175 verified &&
176 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
177 return a.keyParameter.tag == keymint::Tag::PADDING &&
178 a.keyParameter.value ==
179 keymint::KeyParameterValue::make<keymint::KeyParameterValue::paddingMode>(
180 keymint::PaddingMode::PKCS7);
181 });
182
183 return verified;
184}
185
186bool verifyAuthenticationKeyAttributes(const std::vector<ks2::Authorization> authorizations) {
187 bool verified = true;
188 verified =
189 verified &&
190 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
191 return a.keyParameter.tag == keymint::Tag::ALGORITHM &&
192 a.keyParameter.value ==
193 keymint::KeyParameterValue::make<keymint::KeyParameterValue::algorithm>(
194 keymint::Algorithm::HMAC);
195 });
196
197 verified =
198 verified &&
199 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
200 return a.keyParameter.tag == keymint::Tag::KEY_SIZE &&
201 a.keyParameter.value ==
202 keymint::KeyParameterValue::make<keymint::KeyParameterValue::integer>(
203 kHMACKeySize);
204 });
205
206 verified =
207 verified &&
208 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
209 return a.keyParameter.tag == keymint::Tag::MIN_MAC_LENGTH &&
210 a.keyParameter.value ==
211 keymint::KeyParameterValue::make<keymint::KeyParameterValue::integer>(
212 kHMACOutputSize);
213 });
214
215 verified =
216 verified &&
217 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
218 return a.keyParameter.tag == keymint::Tag::DIGEST &&
219 a.keyParameter.value ==
220 keymint::KeyParameterValue::make<keymint::KeyParameterValue::digest>(
221 keymint::Digest::SHA_2_256);
222 });
223 return verified;
224}
225
226std::variant<int, ks2::KeyEntryResponse>
227loadOrCreateAndVerifyEncryptionKey(const std::string& name, keymint::SecurityLevel securityLevel,
228 bool create) {
229 auto keystore = CreateKeystoreInstance();
230
231 ks2::KeyEntryResponse keyEntryResponse;
232
233 bool foundKey = true;
234 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
235 if (!rc.isOk()) {
236 auto error = unwrapError(rc);
237 if (ks2::ResponseCode(error) == ks2::ResponseCode::KEY_NOT_FOUND && create) {
238 foundKey = false;
239 } else {
240 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
241 return error;
242 }
243 }
244
245 if (!foundKey) {
246 auto sec_level = GetSecurityLevelInterface(keystore, securityLevel);
247 auto params = keymint::AuthorizationSetBuilder()
248 .AesEncryptionKey(kAESKeySize)
249 .Padding(keymint::PaddingMode::PKCS7)
250 .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC)
251 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
252
253 ks2::KeyMetadata keyMetadata;
254
255 rc = sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */,
256 params.vector_data(), 0 /* flags */, {} /* entropy */,
257 &keyMetadata);
258 if (!rc.isOk()) {
259 std::cerr << "Failed to generate key: " << rc.getDescription() << std::endl;
260 return unwrapError(rc);
261 }
262
263 rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
264 if (!rc.isOk()) {
265 std::cerr << "Failed to get key entry (second try): " << rc.getDescription()
266 << std::endl;
267 return unwrapError(rc);
268 }
269 }
270
271 if (!verifyEncryptionKeyAttributes(keyEntryResponse.metadata.authorizations)) {
272 std::cerr << "Key has wrong set of parameters." << std::endl;
273 return static_cast<int>(ks2::ResponseCode::INVALID_ARGUMENT);
274 }
275
276 return keyEntryResponse;
277}
278
279std::variant<int, ks2::KeyEntryResponse>
280loadOrCreateAndVerifyAuthenticationKey(const std::string& name,
281 keymint::SecurityLevel securityLevel, bool create) {
282 auto keystore = CreateKeystoreInstance();
283
284 ks2::KeyEntryResponse keyEntryResponse;
285
286 bool foundKey = true;
287 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
288 if (!rc.isOk()) {
289 auto error = unwrapError(rc);
290 if (ks2::ResponseCode(error) == ks2::ResponseCode::KEY_NOT_FOUND && create) {
291 foundKey = false;
292 } else {
293 std::cerr << "Failed to get HMAC key entry: " << rc.getDescription() << std::endl;
294 return error;
295 }
296 }
297
298 if (!foundKey) {
299 auto sec_level = GetSecurityLevelInterface(keystore, securityLevel);
300 auto params = keymint::AuthorizationSetBuilder()
301 .HmacKey(kHMACKeySize)
302 .Digest(keymint::Digest::SHA_2_256)
303 .Authorization(keymint::TAG_MIN_MAC_LENGTH, kHMACOutputSize)
304 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
305
306 ks2::KeyMetadata keyMetadata;
307
308 rc = sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */,
309 params.vector_data(), 0 /* flags */, {} /* entropy */,
310 &keyMetadata);
311 if (!rc.isOk()) {
312 std::cerr << "Failed to generate HMAC key: " << rc.getDescription() << std::endl;
313 return unwrapError(rc);
314 }
315
316 rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
317 if (!rc.isOk()) {
318 std::cerr << "Failed to get HMAC key entry (second try): " << rc.getDescription()
319 << std::endl;
320 return unwrapError(rc);
321 }
322 }
323
324 if (!verifyAuthenticationKeyAttributes(keyEntryResponse.metadata.authorizations)) {
325 std::cerr << "Key has wrong set of parameters." << std::endl;
326 return static_cast<int>(ks2::ResponseCode::INVALID_ARGUMENT);
327 }
328
329 return keyEntryResponse;
330}
331
332std::variant<int, std::vector<uint8_t>>
333encryptWithAuthentication(const std::string& name, const std::vector<uint8_t>& data,
334 keymint::SecurityLevel securityLevel) {
335 // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random
336 // IV. The authentication algorithm is HMAC-SHA256 and is computed over the
337 // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM
338 // because hardware support for GCM is not mandatory for all Brillo devices.
339 std::string encryption_key_name = name + kEncryptSuffix;
340 auto encryption_key_result =
341 loadOrCreateAndVerifyEncryptionKey(encryption_key_name, securityLevel, true /* create */);
342 if (auto error = std::get_if<int>(&encryption_key_result)) {
343 return *error;
344 }
345 auto encryption_key = std::get<ks2::KeyEntryResponse>(encryption_key_result);
346
347 std::string authentication_key_name = name + kAuthenticateSuffix;
348 auto authentication_key_result = loadOrCreateAndVerifyAuthenticationKey(
349 authentication_key_name, securityLevel, true /* create */);
350 if (auto error = std::get_if<int>(&authentication_key_result)) {
351 return *error;
352 }
353 auto authentication_key = std::get<ks2::KeyEntryResponse>(authentication_key_result);
354
355 ks2::CreateOperationResponse encOperationResponse;
356 auto encrypt_params = keymint::AuthorizationSetBuilder()
357 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::ENCRYPT)
358 .Padding(keymint::PaddingMode::PKCS7)
359 .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC);
360
361 auto rc = encryption_key.iSecurityLevel->createOperation(
362 encryption_key.metadata.key, encrypt_params.vector_data(), false /* forced */,
363 &encOperationResponse);
364 if (!rc.isOk()) {
365 std::cerr << "Failed to begin encryption operation: " << rc.getDescription() << std::endl;
366 return unwrapError(rc);
367 }
368
369 std::optional<std::vector<uint8_t>> optCiphertext;
370
371 rc = encOperationResponse.iOperation->finish(data, {}, &optCiphertext);
372 if (!rc.isOk()) {
373 std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl;
374 return unwrapError(rc);
375 }
376
377 std::vector<uint8_t> initVector;
378 if (auto params = encOperationResponse.parameters) {
379 for (auto& p : params->keyParameter) {
380 if (auto iv = keymint::authorizationValue(keymint::TAG_NONCE, p)) {
381 initVector = std::move(iv->get());
382 break;
383 }
384 }
385 if (initVector.empty()) {
386 std::cerr << "Encryption operation did not return an IV." << std::endl;
387 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
388 }
389 }
390
391 if (!optCiphertext) {
392 std::cerr << "Encryption succeeded but no ciphertext returned." << std::endl;
393 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
394 }
395
396 auto ciphertext = std::move(*optCiphertext);
397 auto toBeSigned = initVector;
398 toBeSigned.insert(toBeSigned.end(), ciphertext.begin(), ciphertext.end());
399
400 ks2::CreateOperationResponse signOperationResponse;
401 auto sign_params = keymint::AuthorizationSetBuilder()
402 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::SIGN)
403 .Digest(keymint::Digest::SHA_2_256)
404 .Authorization(keymint::TAG_MAC_LENGTH, kHMACOutputSize);
405
406 rc = authentication_key.iSecurityLevel->createOperation(
407 authentication_key.metadata.key, sign_params.vector_data(), false /* forced */,
408 &signOperationResponse);
409 if (!rc.isOk()) {
410 std::cerr << "Failed to begin signing operation: " << rc.getDescription() << std::endl;
411 return unwrapError(rc);
412 }
413
414 std::optional<std::vector<uint8_t>> optMac;
415
416 rc = signOperationResponse.iOperation->finish(toBeSigned, {}, &optMac);
417 if (!rc.isOk()) {
418 std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl;
419 return unwrapError(rc);
420 }
421
422 if (!optMac) {
423 std::cerr << "Signing succeeded but no MAC returned." << std::endl;
424 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
425 }
426
427 auto mac = std::move(*optMac);
428
429 EncryptedData protobuf;
430 protobuf.set_init_vector(initVector.data(), initVector.size());
431 protobuf.set_authentication_data(mac.data(), mac.size());
432 protobuf.set_encrypted_data(ciphertext.data(), ciphertext.size());
433 std::string resultString;
434 if (!protobuf.SerializeToString(&resultString)) {
435 std::cerr << "Encrypt: Failed to serialize EncryptedData protobuf.";
436 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
437 }
438
439 std::vector<uint8_t> result(reinterpret_cast<const uint8_t*>(resultString.data()),
440 reinterpret_cast<const uint8_t*>(resultString.data()) +
441 resultString.size());
442 return result;
443}
444
445std::variant<int, std::vector<uint8_t>>
446decryptWithAuthentication(const std::string& name, const std::vector<uint8_t>& data) {
447
448 // Decode encrypted data
449 EncryptedData protobuf;
450 if (!protobuf.ParseFromArray(data.data(), data.size())) {
451 std::cerr << "Decrypt: Failed to parse EncryptedData protobuf." << std::endl;
452 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
453 }
454
455 // Load encryption and authentication keys.
456 std::string encryption_key_name = name + kEncryptSuffix;
457 auto encryption_key_result = loadOrCreateAndVerifyEncryptionKey(
458 encryption_key_name, keymint::SecurityLevel::KEYSTORE /* ignored */, false /* create */);
459 if (auto error = std::get_if<int>(&encryption_key_result)) {
460 return *error;
461 }
462 auto encryption_key = std::get<ks2::KeyEntryResponse>(encryption_key_result);
463
464 std::string authentication_key_name = name + kAuthenticateSuffix;
465 auto authentication_key_result = loadOrCreateAndVerifyAuthenticationKey(
466 authentication_key_name, keymint::SecurityLevel::KEYSTORE /* ignored */,
467 false /* create */);
468 if (auto error = std::get_if<int>(&authentication_key_result)) {
469 return *error;
470 }
471 auto authentication_key = std::get<ks2::KeyEntryResponse>(authentication_key_result);
472
473 // Begin authentication operation
474 ks2::CreateOperationResponse signOperationResponse;
475 auto sign_params = keymint::AuthorizationSetBuilder()
476 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::VERIFY)
477 .Digest(keymint::Digest::SHA_2_256)
478 .Authorization(keymint::TAG_MAC_LENGTH, kHMACOutputSize);
479
480 auto rc = authentication_key.iSecurityLevel->createOperation(
481 authentication_key.metadata.key, sign_params.vector_data(), false /* forced */,
482 &signOperationResponse);
483 if (!rc.isOk()) {
484 std::cerr << "Failed to begin verify operation: " << rc.getDescription() << std::endl;
485 return unwrapError(rc);
486 }
487
488 const uint8_t* p = reinterpret_cast<const uint8_t*>(protobuf.init_vector().data());
489 std::vector<uint8_t> toBeVerified(p, p + protobuf.init_vector().size());
490
491 p = reinterpret_cast<const uint8_t*>(protobuf.encrypted_data().data());
492 toBeVerified.insert(toBeVerified.end(), p, p + protobuf.encrypted_data().size());
493
494 p = reinterpret_cast<const uint8_t*>(protobuf.authentication_data().data());
495 std::vector<uint8_t> signature(p, p + protobuf.authentication_data().size());
496
497 std::optional<std::vector<uint8_t>> optOut;
498 rc = signOperationResponse.iOperation->finish(toBeVerified, signature, &optOut);
499 if (!rc.isOk()) {
500 std::cerr << "Decrypt: HMAC verification failed: " << rc.getDescription() << std::endl;
501 return unwrapError(rc);
502 }
503
504 // Begin decryption operation
505 ks2::CreateOperationResponse encOperationResponse;
506 auto encrypt_params = keymint::AuthorizationSetBuilder()
507 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::DECRYPT)
508 .Authorization(keymint::TAG_NONCE, protobuf.init_vector().data(),
509 protobuf.init_vector().size())
510 .Padding(keymint::PaddingMode::PKCS7)
511 .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC);
512
513 rc = encryption_key.iSecurityLevel->createOperation(encryption_key.metadata.key,
514 encrypt_params.vector_data(),
515 false /* forced */, &encOperationResponse);
516 if (!rc.isOk()) {
517 std::cerr << "Failed to begin encryption operation: " << rc.getDescription() << std::endl;
518 return unwrapError(rc);
519 }
520
521 std::optional<std::vector<uint8_t>> optPlaintext;
522
523 p = reinterpret_cast<const uint8_t*>(protobuf.encrypted_data().data());
524 std::vector<uint8_t> cyphertext(p, p + protobuf.encrypted_data().size());
525
526 rc = encOperationResponse.iOperation->finish(cyphertext, {}, &optPlaintext);
527 if (!rc.isOk()) {
528 std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl;
529 return unwrapError(rc);
530 }
531
532 if (!optPlaintext) {
533 std::cerr << "Decryption succeeded but no plaintext returned." << std::endl;
534 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
535 }
536
537 return *optPlaintext;
538}
539
540bool TestKey(const std::string& name, bool required,
541 const std::vector<keymint::KeyParameter>& parameters) {
542 auto keystore = CreateKeystoreInstance();
543 auto sec_level =
544 GetSecurityLevelInterface(keystore, keymint::SecurityLevel::TRUSTED_ENVIRONMENT);
545
546 ks2::KeyDescriptor keyDescriptor = {
547 .domain = ks2::Domain::APP,
548 .nspace = -1,
549 .alias = "tmp",
550 .blob = {},
551 };
552
553 ks2::KeyMetadata keyMetadata;
554
555 auto rc = sec_level->generateKey(keyDescriptor, {} /* attestationKey */, parameters,
556 0 /* flags */, {} /* entropy */, &keyMetadata);
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800557 const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800558 if (!rc.isOk()) {
559 LOG(ERROR) << "Failed to generate key: " << rc.getDescription();
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800560 printf("[%s] %s\n", kBoldRedAbort, name.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -0800561 return false;
562 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800563
564 rc = keystore->deleteKey(keyDescriptor);
565 if (!rc.isOk()) {
566 LOG(ERROR) << "Failed to delete key: " << rc.getDescription();
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800567 printf("[%s] %s\n", kBoldRedAbort, name.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -0800568 return false;
569 }
570 printf("===============================================================\n");
571 printf("%s Key Characteristics:\n", name.c_str());
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800572 PrintKeyCharacteristics(keyMetadata.authorizations);
573 bool hardware_backed = std::any_of(keyMetadata.authorizations.begin(),
574 keyMetadata.authorizations.end(), isHardwareEnforced);
575 if (std::any_of(keyMetadata.authorizations.begin(), keyMetadata.authorizations.end(),
576 [&](const auto& a) {
577 return !isHardwareEnforced(a) &&
578 (a.keyParameter.tag == keymint::Tag::ALGORITHM ||
579 a.keyParameter.tag == keymint::Tag::KEY_SIZE ||
580 a.keyParameter.tag == keymint::Tag::RSA_PUBLIC_EXPONENT);
581 })) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800582 VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
583 hardware_backed = false;
584 }
585 const char kBoldRedFail[] = "\033[1;31mFAIL\033[0m";
586 const char kBoldGreenPass[] = "\033[1;32mPASS\033[0m";
587 const char kBoldYellowWarn[] = "\033[1;33mWARN\033[0m";
588 printf("[%s] %s\n",
589 hardware_backed ? kBoldGreenPass : (required ? kBoldRedFail : kBoldYellowWarn),
590 name.c_str());
591
592 return (hardware_backed || !required);
593}
594
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800595keymint::AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
596 keymint::AuthorizationSetBuilder parameters;
Darren Krahna9474ab2015-11-03 14:38:53 -0800597 parameters.RsaSigningKey(key_size, 65537)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800598 .Digest(keymint::Digest::SHA_2_256)
599 .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN)
600 .Padding(keymint::PaddingMode::RSA_PSS)
601 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800602 if (!sha256_only) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800603 parameters.Digest(keymint::Digest::SHA_2_224)
604 .Digest(keymint::Digest::SHA_2_384)
605 .Digest(keymint::Digest::SHA_2_512);
Darren Krahna9474ab2015-11-03 14:38:53 -0800606 }
Yi Kong53b02f72018-07-26 17:13:50 -0700607 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800608}
609
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800610keymint::AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) {
611 keymint::AuthorizationSetBuilder parameters;
Darren Krahna9474ab2015-11-03 14:38:53 -0800612 parameters.RsaEncryptionKey(key_size, 65537)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800613 .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_ENCRYPT)
614 .Padding(keymint::PaddingMode::RSA_OAEP)
615 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Yi Kong53b02f72018-07-26 17:13:50 -0700616 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800617}
618
David Drysdaleff0f5922021-10-14 15:13:16 +0100619keymint::AuthorizationSet GetECDSAParameters(keymint::EcCurve curve, bool sha256_only) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800620 keymint::AuthorizationSetBuilder parameters;
David Drysdaleff0f5922021-10-14 15:13:16 +0100621 parameters.EcdsaSigningKey(curve)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800622 .Digest(keymint::Digest::SHA_2_256)
623 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800624 if (!sha256_only) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800625 parameters.Digest(keymint::Digest::SHA_2_224)
626 .Digest(keymint::Digest::SHA_2_384)
627 .Digest(keymint::Digest::SHA_2_512);
Darren Krahna9474ab2015-11-03 14:38:53 -0800628 }
Yi Kong53b02f72018-07-26 17:13:50 -0700629 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800630}
631
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800632keymint::AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
633 keymint::AuthorizationSetBuilder parameters;
634 parameters.AesEncryptionKey(key_size).Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800635 if (with_gcm_mode) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800636 parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::GCM)
637 .Authorization(keymint::TAG_MIN_MAC_LENGTH, 128);
Darren Krahna9474ab2015-11-03 14:38:53 -0800638 } else {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800639 parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::ECB);
640 parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC);
641 parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CTR);
642 parameters.Padding(keymint::PaddingMode::NONE);
Darren Krahna9474ab2015-11-03 14:38:53 -0800643 }
Yi Kong53b02f72018-07-26 17:13:50 -0700644 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800645}
646
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800647keymint::AuthorizationSet GetHMACParameters(uint32_t key_size, keymint::Digest digest) {
648 keymint::AuthorizationSetBuilder parameters;
Darren Krahna9474ab2015-11-03 14:38:53 -0800649 parameters.HmacKey(key_size)
650 .Digest(digest)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800651 .Authorization(keymint::TAG_MIN_MAC_LENGTH, 224)
652 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Yi Kong53b02f72018-07-26 17:13:50 -0700653 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800654}
655
656std::vector<TestCase> GetTestCases() {
657 TestCase test_cases[] = {
658 {"RSA-2048 Sign", true, GetRSASignParameters(2048, true)},
659 {"RSA-2048 Sign (more digests)", false, GetRSASignParameters(2048, false)},
660 {"RSA-3072 Sign", false, GetRSASignParameters(3072, false)},
661 {"RSA-4096 Sign", false, GetRSASignParameters(4096, false)},
662 {"RSA-2048 Encrypt", true, GetRSAEncryptParameters(2048)},
663 {"RSA-3072 Encrypt", false, GetRSAEncryptParameters(3072)},
664 {"RSA-4096 Encrypt", false, GetRSAEncryptParameters(4096)},
David Drysdaleff0f5922021-10-14 15:13:16 +0100665 {"ECDSA-P256 Sign", true, GetECDSAParameters(keymint::EcCurve::P_256, true)},
666 {"ECDSA-P256 Sign (more digests)", false,
667 GetECDSAParameters(keymint::EcCurve::P_256, false)},
668 {"ECDSA-P224 Sign", false, GetECDSAParameters(keymint::EcCurve::P_224, false)},
669 {"ECDSA-P384 Sign", false, GetECDSAParameters(keymint::EcCurve::P_384, false)},
670 {"ECDSA-P521 Sign", false, GetECDSAParameters(keymint::EcCurve::P_521, false)},
Darren Krahna9474ab2015-11-03 14:38:53 -0800671 {"AES-128", true, GetAESParameters(128, false)},
672 {"AES-256", true, GetAESParameters(256, false)},
673 {"AES-128-GCM", false, GetAESParameters(128, true)},
674 {"AES-256-GCM", false, GetAESParameters(256, true)},
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800675 {"HMAC-SHA256-16", true, GetHMACParameters(16, keymint::Digest::SHA_2_256)},
676 {"HMAC-SHA256-32", true, GetHMACParameters(32, keymint::Digest::SHA_2_256)},
677 {"HMAC-SHA256-64", false, GetHMACParameters(64, keymint::Digest::SHA_2_256)},
678 {"HMAC-SHA224-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_224)},
679 {"HMAC-SHA384-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_384)},
680 {"HMAC-SHA512-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_512)},
Darren Krahna9474ab2015-11-03 14:38:53 -0800681 };
682 return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
683}
684
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800685int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) {
686 const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m";
687 if (test_for_0_3) {
688 printf("%s: Testing for keymaster v0.3. "
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700689 "This does not meet Brillo requirements.\n",
690 kBoldYellowWarning);
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800691 }
Darren Krahna9474ab2015-11-03 14:38:53 -0800692 int test_count = 0;
693 int fail_count = 0;
694 std::vector<TestCase> test_cases = GetTestCases();
695 for (const auto& test_case : test_cases) {
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800696 if (!prefix.empty() &&
697 !base::StartsWith(test_case.name, prefix, base::CompareCase::SENSITIVE)) {
698 continue;
699 }
700 if (test_for_0_3 &&
701 (base::StartsWith(test_case.name, "AES", base::CompareCase::SENSITIVE) ||
702 base::StartsWith(test_case.name, "HMAC", base::CompareCase::SENSITIVE))) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800703 continue;
704 }
705 ++test_count;
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800706 if (!TestKey(test_case.name, test_case.required_for_brillo_pts,
707 test_case.parameters.vector_data())) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800708 VLOG(1) << "Test failed: " << test_case.name;
709 ++fail_count;
710 }
711 }
712 return fail_count;
713}
714
715int ListTestCases() {
716 const char kBoldGreenRequired[] = "\033[1;32mREQUIRED\033[0m";
717 const char kBoldYellowRecommended[] = "\033[1;33mRECOMMENDED\033[0m";
718 std::vector<TestCase> test_cases = GetTestCases();
719 for (const auto& test_case : test_cases) {
720 printf("%s : %s\n", test_case.name.c_str(),
721 test_case.required_for_brillo_pts ? kBoldGreenRequired : kBoldYellowRecommended);
722 }
723 return 0;
724}
725
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800726std::vector<uint8_t> ReadFile(const std::string& filename) {
Darren Krahn251cb282015-09-28 08:51:18 -0700727 std::string content;
728 base::FilePath path(filename);
729 if (!base::ReadFileToString(path, &content)) {
730 printf("Failed to read file: %s\n", filename.c_str());
731 exit(1);
732 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800733 std::vector<uint8_t> buffer(reinterpret_cast<const uint8_t*>(content.data()),
734 reinterpret_cast<const uint8_t*>(content.data()) + content.size());
735 return buffer;
Darren Krahn251cb282015-09-28 08:51:18 -0700736}
737
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800738void WriteFile(const std::string& filename, const std::vector<uint8_t>& content) {
Darren Krahn251cb282015-09-28 08:51:18 -0700739 base::FilePath path(filename);
740 int size = content.size();
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800741 if (base::WriteFile(path, reinterpret_cast<const char*>(content.data()), size) != size) {
Darren Krahn251cb282015-09-28 08:51:18 -0700742 printf("Failed to write file: %s\n", filename.c_str());
743 exit(1);
744 }
745}
746
Rob Barneseb7f79b2018-11-08 15:44:10 -0700747// Note: auth_bound keys created with this tool will not be usable.
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800748int GenerateKey(const std::string& name, keymint::SecurityLevel securityLevel, bool auth_bound) {
749 auto keystore = CreateKeystoreInstance();
750 auto sec_level = GetSecurityLevelInterface(keystore, securityLevel);
751 keymint::AuthorizationSetBuilder params;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700752 params.RsaSigningKey(2048, 65537)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800753 .Digest(keymint::Digest::SHA_2_224)
754 .Digest(keymint::Digest::SHA_2_256)
755 .Digest(keymint::Digest::SHA_2_384)
756 .Digest(keymint::Digest::SHA_2_512)
757 .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN)
758 .Padding(keymint::PaddingMode::RSA_PSS);
Rob Barneseb7f79b2018-11-08 15:44:10 -0700759 if (auth_bound) {
760 // Gatekeeper normally generates the secure user id.
761 // Using zero allows the key to be created, but it will not be usuable.
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800762 params.Authorization(keymint::TAG_USER_SECURE_ID, 0);
Rob Barneseb7f79b2018-11-08 15:44:10 -0700763 } else {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800764 params.Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Rob Barneseb7f79b2018-11-08 15:44:10 -0700765 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800766
767 ks2::KeyMetadata keyMetadata;
768
769 auto rc =
770 sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */, params.vector_data(),
771 0 /* flags */, {} /* entropy */, &keyMetadata);
772
Janis Danisevskis2cb4f092021-05-17 13:25:07 -0700773 if (!rc.isOk()) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800774 std::cerr << "GenerateKey failed: " << rc.getDescription() << std::endl;
775 return unwrapError(rc);
Darren Krahna9474ab2015-11-03 14:38:53 -0800776 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800777 std::cout << "GenerateKey: success" << std::endl;
778 PrintKeyCharacteristics(keyMetadata.authorizations);
779 return 0;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700780}
781
782int GetCharacteristics(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800783 auto keystore = CreateKeystoreInstance();
784
785 ks2::KeyEntryResponse keyEntryResponse;
786
787 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
788 if (!rc.isOk()) {
789 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
790 return unwrapError(rc);
Darren Krahna9474ab2015-11-03 14:38:53 -0800791 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800792
793 std::cout << "GetCharacteristics: success" << std::endl;
794 PrintKeyCharacteristics(keyEntryResponse.metadata.authorizations);
795 return 0;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700796}
797
798int ExportKey(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800799 auto keystore = CreateKeystoreInstance();
800
801 ks2::KeyEntryResponse keyEntryResponse;
802
803 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
804 if (!rc.isOk()) {
805 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
806 return unwrapError(rc);
807 }
808
809 if (auto cert = keyEntryResponse.metadata.certificate) {
810 std::cout << "ExportKey: Got certificate of length (" << cert->size() << ")" << std::endl;
811 } else {
812 std::cout << "ExportKey: Key entry does not have a public component.\n";
813 std::cout << "Possibly a symmetric key?" << std::endl;
814 }
815 return 0;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700816}
817
818int DeleteKey(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800819 auto keystore = CreateKeystoreInstance();
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700820
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800821 auto rc = keystore->deleteKey(keyDescriptor(name));
822 if (!rc.isOk()) {
823 std::cerr << "Failed to delete key: " << rc.getDescription();
824 return unwrapError(rc);
825 }
826 std::cout << "Successfully deleted key." << std::endl;
827 return 0;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700828}
829
830int DoesKeyExist(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800831 auto keystore = CreateKeystoreInstance();
832 ks2::KeyEntryResponse keyEntryResponse;
833
834 bool keyExists = true;
835 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
836 if (!rc.isOk()) {
837 auto responseCode = unwrapError(rc);
838 if (ks2::ResponseCode(responseCode) == ks2::ResponseCode::KEY_NOT_FOUND) {
839 keyExists = false;
840 } else {
841 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
842 return unwrapError(rc);
843 }
844 }
845 std::cout << "DoesKeyExists: " << (keyExists ? "yes" : "no") << std::endl;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700846 return 0;
847}
848
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800849int List() {
850 auto keystore = CreateKeystoreInstance();
851 std::vector<ks2::KeyDescriptor> key_list;
852 auto rc = keystore->listEntries(ks2::Domain::APP, -1 /* nspace ignored */, &key_list);
853 if (!rc.isOk()) {
854 std::cerr << "ListKeys failed: " << rc.getDescription() << std::endl;
855 return unwrapError(rc);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700856 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800857 std::cout << "Keys:\n";
858 for (const auto& key : key_list) {
859 std::cout << " "
860 << (key.alias ? *key.alias : "Whoopsi - no alias, this should not happen.")
861 << std::endl;
Rob Barneseb7f79b2018-11-08 15:44:10 -0700862 }
863 return 0;
864}
865
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700866int SignAndVerify(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800867 auto keystore = CreateKeystoreInstance();
868 auto sign_params = keymint::AuthorizationSetBuilder()
869 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::SIGN)
870 .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN)
871 .Digest(keymint::Digest::SHA_2_256);
872
873 keymint::AuthorizationSet output_params;
874
875 ks2::KeyEntryResponse keyEntryResponse;
876
877 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
878 if (!rc.isOk()) {
879 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
880 return unwrapError(rc);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700881 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800882
883 ks2::CreateOperationResponse operationResponse;
884
885 rc = keyEntryResponse.iSecurityLevel->createOperation(keyEntryResponse.metadata.key,
886 sign_params.vector_data(),
887 false /* forced */, &operationResponse);
888 if (!rc.isOk()) {
889 std::cerr << "Failed to create operation: " << rc.getDescription() << std::endl;
890 return unwrapError(rc);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700891 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800892
893 const std::vector<uint8_t> data_to_sign{0x64, 0x61, 0x74, 0x61, 0x5f, 0x74,
894 0x6f, 0x5f, 0x73, 0x69, 0x67, 0x6e};
895 std::optional<std::vector<uint8_t>> output_data;
896 rc = operationResponse.iOperation->finish(data_to_sign, {}, &output_data);
897 if (!rc.isOk()) {
898 std::cerr << "Failed to finalize operation: " << rc.getDescription() << std::endl;
899 return unwrapError(rc);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700900 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800901
902 if (!output_data) {
903 std::cerr << "Odd signing succeeded but no signature was returned." << std::endl;
904 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700905 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800906 auto signature = std::move(*output_data);
907
908 std::cout << "Sign: " << signature.size() << " bytes." << std::endl;
909
910 if (auto cert = keyEntryResponse.metadata.certificate) {
911 const uint8_t* p = cert->data();
912 bssl::UniquePtr<X509> decoded_cert(d2i_X509(nullptr, &p, (long)cert->size()));
913 bssl::UniquePtr<EVP_PKEY> decoded_pkey(X509_get_pubkey(decoded_cert.get()));
914 bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_new());
915 if (!ctx) {
916 std::cerr << "Failed to created EVP_MD context. << std::endl";
917 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
918 }
919
920 if (!EVP_DigestVerifyInit(ctx.get(), nullptr, EVP_sha256(), nullptr, decoded_pkey.get()) ||
921 !EVP_DigestVerifyUpdate(ctx.get(), data_to_sign.data(), data_to_sign.size()) ||
922 EVP_DigestVerifyFinal(ctx.get(), signature.data(), signature.size()) != 1) {
923 std::cerr << "Failed to verify signature." << std::endl;
924 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
925 }
926 } else {
927 std::cerr << "No public key to check signature against." << std::endl;
928 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
929 }
930
931 std::cout << "Verify: OK" << std::endl;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700932 return 0;
933}
934
Darren Krahn251cb282015-09-28 08:51:18 -0700935int Encrypt(const std::string& key_name, const std::string& input_filename,
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800936 const std::string& output_filename, keymint::SecurityLevel securityLevel) {
937 auto input = ReadFile(input_filename);
938 auto result = encryptWithAuthentication(key_name, input, securityLevel);
939 if (auto error = std::get_if<int>(&result)) {
940 std::cerr << "EncryptWithAuthentication failed." << std::endl;
941 return *error;
Darren Krahn251cb282015-09-28 08:51:18 -0700942 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800943 WriteFile(output_filename, std::get<std::vector<uint8_t>>(result));
Darren Krahn251cb282015-09-28 08:51:18 -0700944 return 0;
945}
946
947int Decrypt(const std::string& key_name, const std::string& input_filename,
948 const std::string& output_filename) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800949 auto input = ReadFile(input_filename);
950 auto result = decryptWithAuthentication(key_name, input);
951 if (auto error = std::get_if<int>(&result)) {
952 std::cerr << "DecryptWithAuthentication failed." << std::endl;
953 return *error;
Darren Krahn251cb282015-09-28 08:51:18 -0700954 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800955 WriteFile(output_filename, std::get<std::vector<uint8_t>>(result));
Darren Krahn251cb282015-09-28 08:51:18 -0700956 return 0;
957}
958
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800959keymint::SecurityLevel securityLevelOption2SecurlityLevel(const CommandLine& cmd) {
Janis Danisevskisc1460142017-12-18 16:48:46 -0800960 if (cmd.HasSwitch("seclevel")) {
961 auto str = cmd.GetSwitchValueASCII("seclevel");
962 if (str == "strongbox") {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800963 return keymint::SecurityLevel::STRONGBOX;
964 } else if (str == "tee") {
965 return keymint::SecurityLevel::TRUSTED_ENVIRONMENT;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800966 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800967 std::cerr << "Unknown Security level: " << str << std::endl;
968 std::cerr << "Supported security levels: \"strongbox\" or \"tee\" (default)" << std::endl;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800969 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800970 return keymint::SecurityLevel::TRUSTED_ENVIRONMENT;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800971}
972
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800973class ConfirmationListener
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800974 : public apc::BnConfirmationCallback,
975 public std::promise<std::tuple<apc::ResponseCode, std::optional<std::vector<uint8_t>>>> {
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500976 public:
977 ConfirmationListener() {}
978
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800979 virtual ::ndk::ScopedAStatus
980 onCompleted(::aidl::android::security::apc::ResponseCode result,
981 const std::optional<std::vector<uint8_t>>& dataConfirmed) override {
982 this->set_value({result, dataConfirmed});
983 return ::ndk::ScopedAStatus::ok();
984 };
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500985};
986
987int Confirmation(const std::string& promptText, const std::string& extraDataHex,
988 const std::string& locale, const std::string& uiOptionsStr,
989 const std::string& cancelAfter) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800990 ::ndk::SpAIBinder apcBinder(AServiceManager_getService("android.security.apc"));
991 auto apcService = apc::IProtectedConfirmation::fromBinder(apcBinder);
992 if (!apcService) {
993 std::cerr << "Error: could not connect to apc service." << std::endl;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500994 return 1;
995 }
996
997 if (promptText.size() == 0) {
Janis Danisevskis1a8d5802018-03-14 13:38:07 -0700998 printf("The --prompt_text parameter cannot be empty.\n");
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500999 return 1;
1000 }
1001
1002 std::vector<uint8_t> extraData;
1003 if (!base::HexStringToBytes(extraDataHex, &extraData)) {
1004 printf("The --extra_data parameter does not appear to be valid hexadecimal.\n");
1005 return 1;
1006 }
1007
1008 std::vector<std::string> pieces =
1009 base::SplitString(uiOptionsStr, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
1010 int uiOptionsAsFlags = 0;
1011 for (auto& p : pieces) {
1012 int value;
1013 if (!base::StringToInt(p, &value)) {
1014 printf("Error parsing %s in --ui_options parameter as a number.\n", p.c_str());
1015 return 1;
1016 }
1017 uiOptionsAsFlags |= (1 << value);
1018 }
1019
1020 double cancelAfterValue = 0.0;
1021
1022 if (cancelAfter.size() > 0 && !base::StringToDouble(cancelAfter, &cancelAfterValue)) {
1023 printf("Error parsing %s in --cancel_after parameter as a double.\n", cancelAfter.c_str());
1024 return 1;
1025 }
1026
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001027 auto listener = std::make_shared<ConfirmationListener>();
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001028
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001029 auto future = listener->get_future();
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001030 auto rc = apcService->presentPrompt(listener, promptText, extraData, locale, uiOptionsAsFlags);
1031
1032 if (!rc.isOk()) {
1033 std::cerr << "Presenting confirmation prompt failed: " << rc.getDescription() << std::endl;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001034 return 1;
1035 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001036
1037 std::cerr << "Waiting for prompt to complete - use Ctrl+C to abort..." << std::endl;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001038
1039 if (cancelAfterValue > 0.0) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001040 std::cerr << "Sleeping " << cancelAfterValue << " seconds before canceling prompt..."
1041 << std::endl;
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001042 auto fstatus =
1043 future.wait_for(std::chrono::milliseconds(uint64_t(cancelAfterValue * 1000)));
1044 if (fstatus == std::future_status::timeout) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001045 rc = apcService->cancelPrompt(listener);
1046 if (!rc.isOk()) {
1047 std::cerr << "Canceling confirmation prompt failed: " << rc.getDescription()
1048 << std::endl;
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001049 return 1;
1050 }
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001051 }
1052 }
1053
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001054 future.wait();
1055
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001056 auto [responseCode, dataThatWasConfirmed] = future.get();
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001057
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001058 std::cerr << "Confirmation prompt completed\n"
1059 << "responseCode = " << toString(responseCode);
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001060 size_t newLineCountDown = 16;
1061 bool hasPrinted = false;
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001062 if (dataThatWasConfirmed) {
1063 std::cerr << "dataThatWasConfirmed[" << dataThatWasConfirmed->size() << "] = {";
1064 for (uint8_t element : *dataThatWasConfirmed) {
1065 if (hasPrinted) {
1066 std::cerr << ", ";
1067 }
1068 if (newLineCountDown == 0) {
1069 std::cerr << "\n ";
1070 newLineCountDown = 32;
1071 }
1072 std::cerr << "0x" << std::hex << std::setw(2) << std::setfill('0') << (unsigned)element;
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001073
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001074 hasPrinted = true;
1075 }
1076 }
1077 std::cerr << std::endl;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001078 return 0;
1079}
1080
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001081} // namespace
1082
1083int main(int argc, char** argv) {
1084 CommandLine::Init(argc, argv);
1085 CommandLine* command_line = CommandLine::ForCurrentProcess();
1086 CommandLine::StringVector args = command_line->GetArgs();
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001087
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001088 ABinderProcess_startThreadPool();
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001089
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001090 if (args.empty()) {
1091 PrintUsageAndExit();
1092 }
Darren Krahna9474ab2015-11-03 14:38:53 -08001093 if (args[0] == "brillo-platform-test") {
Darren Krahn82f4f5b2016-03-03 16:21:07 -08001094 return BrilloPlatformTest(command_line->GetSwitchValueASCII("prefix"),
1095 command_line->HasSwitch("test_for_0_3"));
Darren Krahna9474ab2015-11-03 14:38:53 -08001096 } else if (args[0] == "list-brillo-tests") {
1097 return ListTestCases();
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001098 } else if (args[0] == "generate") {
Janis Danisevskisc1460142017-12-18 16:48:46 -08001099 return GenerateKey(command_line->GetSwitchValueASCII("name"),
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001100 securityLevelOption2SecurlityLevel(*command_line),
Rob Barneseb7f79b2018-11-08 15:44:10 -07001101 command_line->HasSwitch("auth_bound"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001102 } else if (args[0] == "get-chars") {
1103 return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
1104 } else if (args[0] == "export") {
1105 return ExportKey(command_line->GetSwitchValueASCII("name"));
1106 } else if (args[0] == "delete") {
1107 return DeleteKey(command_line->GetSwitchValueASCII("name"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001108 } else if (args[0] == "exists") {
1109 return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
1110 } else if (args[0] == "list") {
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001111 return List();
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001112 } else if (args[0] == "sign-verify") {
1113 return SignAndVerify(command_line->GetSwitchValueASCII("name"));
Darren Krahn251cb282015-09-28 08:51:18 -07001114 } else if (args[0] == "encrypt") {
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001115 return Encrypt(command_line->GetSwitchValueASCII("name"),
1116 command_line->GetSwitchValueASCII("in"),
1117 command_line->GetSwitchValueASCII("out"),
1118 securityLevelOption2SecurlityLevel(*command_line));
Darren Krahn251cb282015-09-28 08:51:18 -07001119 } else if (args[0] == "decrypt") {
1120 return Decrypt(command_line->GetSwitchValueASCII("name"),
1121 command_line->GetSwitchValueASCII("in"),
1122 command_line->GetSwitchValueASCII("out"));
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001123 } else if (args[0] == "confirmation") {
Janis Danisevskis1a8d5802018-03-14 13:38:07 -07001124 return Confirmation(command_line->GetSwitchValueNative("prompt_text"),
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001125 command_line->GetSwitchValueASCII("extra_data"),
1126 command_line->GetSwitchValueASCII("locale"),
1127 command_line->GetSwitchValueASCII("ui_options"),
1128 command_line->GetSwitchValueASCII("cancel_after"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001129 } else {
1130 PrintUsageAndExit();
1131 }
1132 return 0;
1133}