blob: d01c67d4a847cfc66ef1be01600ca846648a722c [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>
Jooyung Han7ffd2fd2021-11-19 15:11:39 +090022#include <variant>
Darren Krahn69a3dbc2015-09-22 16:21:04 -070023#include <vector>
24
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070025#include <base/command_line.h>
26#include <base/files/file_util.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050027#include <base/strings/string_number_conversions.h>
28#include <base/strings/string_split.h>
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070029#include <base/strings/string_util.h>
Darren Krahn69a3dbc2015-09-22 16:21:04 -070030
Janis Danisevskis2437fde2021-03-08 11:30:11 -080031#include <aidl/android/security/apc/BnConfirmationCallback.h>
32#include <aidl/android/security/apc/IProtectedConfirmation.h>
33#include <aidl/android/system/keystore2/IKeystoreService.h>
34#include <aidl/android/system/keystore2/ResponseCode.h>
35#include <android/binder_manager.h>
36#include <android/binder_process.h>
37#include <keymint_support/authorization_set.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050038
Janis Danisevskis2437fde2021-03-08 11:30:11 -080039#include <openssl/evp.h>
40#include <openssl/mem.h>
41#include <openssl/x509.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050042
Janis Danisevskis2437fde2021-03-08 11:30:11 -080043#include "keystore_client.pb.h"
44
45namespace apc = ::aidl::android::security::apc;
46namespace keymint = ::aidl::android::hardware::security::keymint;
47namespace ks2 = ::aidl::android::system::keystore2;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050048
Darren Krahn69a3dbc2015-09-22 16:21:04 -070049using base::CommandLine;
Janis Danisevskis2437fde2021-03-08 11:30:11 -080050using keystore::EncryptedData;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050051
Darren Krahn69a3dbc2015-09-22 16:21:04 -070052namespace {
53
Darren Krahna9474ab2015-11-03 14:38:53 -080054struct TestCase {
55 std::string name;
56 bool required_for_brillo_pts;
Janis Danisevskis2437fde2021-03-08 11:30:11 -080057 keymint::AuthorizationSet parameters;
Darren Krahna9474ab2015-11-03 14:38:53 -080058};
59
Janis Danisevskis2cb4f092021-05-17 13:25:07 -070060constexpr const char keystore2_service_name[] = "android.system.keystore2.IKeystoreService/default";
Janis Danisevskis2437fde2021-03-08 11:30:11 -080061
62int unwrapError(const ndk::ScopedAStatus& status) {
63 if (status.isOk()) return 0;
64 if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) {
65 return status.getServiceSpecificError();
66 } else {
67 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
68 }
69}
70
71ks2::KeyDescriptor keyDescriptor(const std::string& alias) {
72 return {
73 .domain = ks2::Domain::APP,
74 .nspace = -1, // ignored - should be -1.
75 .alias = alias,
76 .blob = {},
77 };
78}
79
Darren Krahn69a3dbc2015-09-22 16:21:04 -070080void PrintUsageAndExit() {
81 printf("Usage: keystore_client_v2 <command> [options]\n");
Darren Krahn82f4f5b2016-03-03 16:21:07 -080082 printf("Commands: brillo-platform-test [--prefix=<test_name_prefix>] [--test_for_0_3]\n"
Darren Krahna9474ab2015-11-03 14:38:53 -080083 " list-brillo-tests\n"
Janis Danisevskisc1460142017-12-18 16:48:46 -080084 " add-entropy --input=<entropy> [--seclevel=software|strongbox|tee(default)]\n"
85 " generate --name=<key_name> [--seclevel=software|strongbox|tee(default)]\n"
Darren Krahn69a3dbc2015-09-22 16:21:04 -070086 " get-chars --name=<key_name>\n"
87 " export --name=<key_name>\n"
88 " delete --name=<key_name>\n"
89 " delete-all\n"
90 " exists --name=<key_name>\n"
91 " list [--prefix=<key_name_prefix>]\n"
Rob Barneseb7f79b2018-11-08 15:44:10 -070092 " list-apps-with-keys\n"
Darren Krahn251cb282015-09-28 08:51:18 -070093 " sign-verify --name=<key_name>\n"
Janis Danisevskisc1460142017-12-18 16:48:46 -080094 " [en|de]crypt --name=<key_name> --in=<file> --out=<file>\n"
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050095 " [--seclevel=software|strongbox|tee(default)]\n"
96 " confirmation --prompt_text=<PromptText> --extra_data=<hex>\n"
97 " --locale=<locale> [--ui_options=<list_of_ints>]\n"
98 " --cancel_after=<seconds>\n");
Darren Krahn69a3dbc2015-09-22 16:21:04 -070099 exit(1);
100}
101
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800102std::shared_ptr<ks2::IKeystoreService> CreateKeystoreInstance() {
103 ::ndk::SpAIBinder keystoreBinder(AServiceManager_checkService(keystore2_service_name));
104 auto result = ks2::IKeystoreService::fromBinder(keystoreBinder);
105 if (result) return result;
106 std::cerr << "Unable to connect to Keystore.";
107 exit(-1);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700108}
109
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800110std::shared_ptr<ks2::IKeystoreSecurityLevel>
111GetSecurityLevelInterface(std::shared_ptr<ks2::IKeystoreService> keystore,
112 keymint::SecurityLevel securitylevel) {
113 std::shared_ptr<ks2::IKeystoreSecurityLevel> sec_level;
114 auto rc = keystore->getSecurityLevel(securitylevel, &sec_level);
115 if (rc.isOk()) return sec_level;
116 std::cerr << "Unable to get security level interface from Keystore: " << rc.getDescription();
117 exit(-1);
118}
119
120bool isHardwareEnforced(const ks2::Authorization& a) {
121 return !(a.securityLevel == keymint::SecurityLevel::SOFTWARE ||
122 a.securityLevel == keymint::SecurityLevel::KEYSTORE);
123}
124
125void PrintTags(const std::vector<ks2::Authorization>& characteristics, bool printHardwareEnforced) {
126 for (const auto& a : characteristics) {
127 if (isHardwareEnforced(a) == printHardwareEnforced) {
128 std::cout << toString(a.keyParameter.tag) << "\n";
129 }
Darren Krahna9474ab2015-11-03 14:38:53 -0800130 }
131}
132
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800133void PrintKeyCharacteristics(const std::vector<ks2::Authorization>& characteristics) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800134 printf("Hardware:\n");
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800135 PrintTags(characteristics, true /* printHardwareEnforced */);
Darren Krahna9474ab2015-11-03 14:38:53 -0800136 printf("Software:\n");
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800137 PrintTags(characteristics, false /* printHardwareEnforced */);
Darren Krahna9474ab2015-11-03 14:38:53 -0800138}
139
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800140const char kEncryptSuffix[] = "_ENC";
141const char kAuthenticateSuffix[] = "_AUTH";
142constexpr uint32_t kAESKeySize = 256; // bits
143constexpr uint32_t kHMACKeySize = 256; // bits
144constexpr uint32_t kHMACOutputSize = 256; // bits
145
146bool verifyEncryptionKeyAttributes(const std::vector<ks2::Authorization> authorizations) {
147 bool verified = true;
148 verified =
149 verified &&
150 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
151 return a.keyParameter.tag == keymint::Tag::ALGORITHM &&
152 a.keyParameter.value ==
153 keymint::KeyParameterValue::make<keymint::KeyParameterValue::algorithm>(
154 keymint::Algorithm::AES);
155 });
156
157 verified =
158 verified &&
159 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
160 return a.keyParameter.tag == keymint::Tag::KEY_SIZE &&
161 a.keyParameter.value ==
162 keymint::KeyParameterValue::make<keymint::KeyParameterValue::integer>(
163 kAESKeySize);
164 });
165
166 verified =
167 verified &&
168 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
169 return a.keyParameter.tag == keymint::Tag::BLOCK_MODE &&
170 a.keyParameter.value ==
171 keymint::KeyParameterValue::make<keymint::KeyParameterValue::blockMode>(
172 keymint::BlockMode::CBC);
173 });
174
175 verified =
176 verified &&
177 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
178 return a.keyParameter.tag == keymint::Tag::PADDING &&
179 a.keyParameter.value ==
180 keymint::KeyParameterValue::make<keymint::KeyParameterValue::paddingMode>(
181 keymint::PaddingMode::PKCS7);
182 });
183
184 return verified;
185}
186
187bool verifyAuthenticationKeyAttributes(const std::vector<ks2::Authorization> authorizations) {
188 bool verified = true;
189 verified =
190 verified &&
191 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
192 return a.keyParameter.tag == keymint::Tag::ALGORITHM &&
193 a.keyParameter.value ==
194 keymint::KeyParameterValue::make<keymint::KeyParameterValue::algorithm>(
195 keymint::Algorithm::HMAC);
196 });
197
198 verified =
199 verified &&
200 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
201 return a.keyParameter.tag == keymint::Tag::KEY_SIZE &&
202 a.keyParameter.value ==
203 keymint::KeyParameterValue::make<keymint::KeyParameterValue::integer>(
204 kHMACKeySize);
205 });
206
207 verified =
208 verified &&
209 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
210 return a.keyParameter.tag == keymint::Tag::MIN_MAC_LENGTH &&
211 a.keyParameter.value ==
212 keymint::KeyParameterValue::make<keymint::KeyParameterValue::integer>(
213 kHMACOutputSize);
214 });
215
216 verified =
217 verified &&
218 std::any_of(authorizations.begin(), authorizations.end(), [&](const ks2::Authorization& a) {
219 return a.keyParameter.tag == keymint::Tag::DIGEST &&
220 a.keyParameter.value ==
221 keymint::KeyParameterValue::make<keymint::KeyParameterValue::digest>(
222 keymint::Digest::SHA_2_256);
223 });
224 return verified;
225}
226
227std::variant<int, ks2::KeyEntryResponse>
228loadOrCreateAndVerifyEncryptionKey(const std::string& name, keymint::SecurityLevel securityLevel,
229 bool create) {
230 auto keystore = CreateKeystoreInstance();
231
232 ks2::KeyEntryResponse keyEntryResponse;
233
234 bool foundKey = true;
235 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
236 if (!rc.isOk()) {
237 auto error = unwrapError(rc);
238 if (ks2::ResponseCode(error) == ks2::ResponseCode::KEY_NOT_FOUND && create) {
239 foundKey = false;
240 } else {
241 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
242 return error;
243 }
244 }
245
246 if (!foundKey) {
247 auto sec_level = GetSecurityLevelInterface(keystore, securityLevel);
248 auto params = keymint::AuthorizationSetBuilder()
249 .AesEncryptionKey(kAESKeySize)
250 .Padding(keymint::PaddingMode::PKCS7)
251 .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC)
252 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
253
254 ks2::KeyMetadata keyMetadata;
255
256 rc = sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */,
257 params.vector_data(), 0 /* flags */, {} /* entropy */,
258 &keyMetadata);
259 if (!rc.isOk()) {
260 std::cerr << "Failed to generate key: " << rc.getDescription() << std::endl;
261 return unwrapError(rc);
262 }
263
264 rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
265 if (!rc.isOk()) {
266 std::cerr << "Failed to get key entry (second try): " << rc.getDescription()
267 << std::endl;
268 return unwrapError(rc);
269 }
270 }
271
272 if (!verifyEncryptionKeyAttributes(keyEntryResponse.metadata.authorizations)) {
273 std::cerr << "Key has wrong set of parameters." << std::endl;
274 return static_cast<int>(ks2::ResponseCode::INVALID_ARGUMENT);
275 }
276
277 return keyEntryResponse;
278}
279
280std::variant<int, ks2::KeyEntryResponse>
281loadOrCreateAndVerifyAuthenticationKey(const std::string& name,
282 keymint::SecurityLevel securityLevel, bool create) {
283 auto keystore = CreateKeystoreInstance();
284
285 ks2::KeyEntryResponse keyEntryResponse;
286
287 bool foundKey = true;
288 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
289 if (!rc.isOk()) {
290 auto error = unwrapError(rc);
291 if (ks2::ResponseCode(error) == ks2::ResponseCode::KEY_NOT_FOUND && create) {
292 foundKey = false;
293 } else {
294 std::cerr << "Failed to get HMAC key entry: " << rc.getDescription() << std::endl;
295 return error;
296 }
297 }
298
299 if (!foundKey) {
300 auto sec_level = GetSecurityLevelInterface(keystore, securityLevel);
301 auto params = keymint::AuthorizationSetBuilder()
302 .HmacKey(kHMACKeySize)
303 .Digest(keymint::Digest::SHA_2_256)
304 .Authorization(keymint::TAG_MIN_MAC_LENGTH, kHMACOutputSize)
305 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
306
307 ks2::KeyMetadata keyMetadata;
308
309 rc = sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */,
310 params.vector_data(), 0 /* flags */, {} /* entropy */,
311 &keyMetadata);
312 if (!rc.isOk()) {
313 std::cerr << "Failed to generate HMAC key: " << rc.getDescription() << std::endl;
314 return unwrapError(rc);
315 }
316
317 rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
318 if (!rc.isOk()) {
319 std::cerr << "Failed to get HMAC key entry (second try): " << rc.getDescription()
320 << std::endl;
321 return unwrapError(rc);
322 }
323 }
324
325 if (!verifyAuthenticationKeyAttributes(keyEntryResponse.metadata.authorizations)) {
326 std::cerr << "Key has wrong set of parameters." << std::endl;
327 return static_cast<int>(ks2::ResponseCode::INVALID_ARGUMENT);
328 }
329
330 return keyEntryResponse;
331}
332
333std::variant<int, std::vector<uint8_t>>
334encryptWithAuthentication(const std::string& name, const std::vector<uint8_t>& data,
335 keymint::SecurityLevel securityLevel) {
336 // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random
337 // IV. The authentication algorithm is HMAC-SHA256 and is computed over the
338 // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM
339 // because hardware support for GCM is not mandatory for all Brillo devices.
340 std::string encryption_key_name = name + kEncryptSuffix;
341 auto encryption_key_result =
342 loadOrCreateAndVerifyEncryptionKey(encryption_key_name, securityLevel, true /* create */);
343 if (auto error = std::get_if<int>(&encryption_key_result)) {
344 return *error;
345 }
346 auto encryption_key = std::get<ks2::KeyEntryResponse>(encryption_key_result);
347
348 std::string authentication_key_name = name + kAuthenticateSuffix;
349 auto authentication_key_result = loadOrCreateAndVerifyAuthenticationKey(
350 authentication_key_name, securityLevel, true /* create */);
351 if (auto error = std::get_if<int>(&authentication_key_result)) {
352 return *error;
353 }
354 auto authentication_key = std::get<ks2::KeyEntryResponse>(authentication_key_result);
355
356 ks2::CreateOperationResponse encOperationResponse;
357 auto encrypt_params = keymint::AuthorizationSetBuilder()
358 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::ENCRYPT)
359 .Padding(keymint::PaddingMode::PKCS7)
360 .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC);
361
362 auto rc = encryption_key.iSecurityLevel->createOperation(
363 encryption_key.metadata.key, encrypt_params.vector_data(), false /* forced */,
364 &encOperationResponse);
365 if (!rc.isOk()) {
366 std::cerr << "Failed to begin encryption operation: " << rc.getDescription() << std::endl;
367 return unwrapError(rc);
368 }
369
370 std::optional<std::vector<uint8_t>> optCiphertext;
371
372 rc = encOperationResponse.iOperation->finish(data, {}, &optCiphertext);
373 if (!rc.isOk()) {
374 std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl;
375 return unwrapError(rc);
376 }
377
378 std::vector<uint8_t> initVector;
379 if (auto params = encOperationResponse.parameters) {
380 for (auto& p : params->keyParameter) {
381 if (auto iv = keymint::authorizationValue(keymint::TAG_NONCE, p)) {
382 initVector = std::move(iv->get());
383 break;
384 }
385 }
386 if (initVector.empty()) {
387 std::cerr << "Encryption operation did not return an IV." << std::endl;
388 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
389 }
390 }
391
392 if (!optCiphertext) {
393 std::cerr << "Encryption succeeded but no ciphertext returned." << std::endl;
394 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
395 }
396
397 auto ciphertext = std::move(*optCiphertext);
398 auto toBeSigned = initVector;
399 toBeSigned.insert(toBeSigned.end(), ciphertext.begin(), ciphertext.end());
400
401 ks2::CreateOperationResponse signOperationResponse;
402 auto sign_params = keymint::AuthorizationSetBuilder()
403 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::SIGN)
404 .Digest(keymint::Digest::SHA_2_256)
405 .Authorization(keymint::TAG_MAC_LENGTH, kHMACOutputSize);
406
407 rc = authentication_key.iSecurityLevel->createOperation(
408 authentication_key.metadata.key, sign_params.vector_data(), false /* forced */,
409 &signOperationResponse);
410 if (!rc.isOk()) {
411 std::cerr << "Failed to begin signing operation: " << rc.getDescription() << std::endl;
412 return unwrapError(rc);
413 }
414
415 std::optional<std::vector<uint8_t>> optMac;
416
417 rc = signOperationResponse.iOperation->finish(toBeSigned, {}, &optMac);
418 if (!rc.isOk()) {
419 std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl;
420 return unwrapError(rc);
421 }
422
423 if (!optMac) {
424 std::cerr << "Signing succeeded but no MAC returned." << std::endl;
425 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
426 }
427
428 auto mac = std::move(*optMac);
429
430 EncryptedData protobuf;
431 protobuf.set_init_vector(initVector.data(), initVector.size());
432 protobuf.set_authentication_data(mac.data(), mac.size());
433 protobuf.set_encrypted_data(ciphertext.data(), ciphertext.size());
434 std::string resultString;
435 if (!protobuf.SerializeToString(&resultString)) {
436 std::cerr << "Encrypt: Failed to serialize EncryptedData protobuf.";
437 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
438 }
439
440 std::vector<uint8_t> result(reinterpret_cast<const uint8_t*>(resultString.data()),
441 reinterpret_cast<const uint8_t*>(resultString.data()) +
442 resultString.size());
443 return result;
444}
445
446std::variant<int, std::vector<uint8_t>>
447decryptWithAuthentication(const std::string& name, const std::vector<uint8_t>& data) {
448
449 // Decode encrypted data
450 EncryptedData protobuf;
451 if (!protobuf.ParseFromArray(data.data(), data.size())) {
452 std::cerr << "Decrypt: Failed to parse EncryptedData protobuf." << std::endl;
453 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
454 }
455
456 // Load encryption and authentication keys.
457 std::string encryption_key_name = name + kEncryptSuffix;
458 auto encryption_key_result = loadOrCreateAndVerifyEncryptionKey(
459 encryption_key_name, keymint::SecurityLevel::KEYSTORE /* ignored */, false /* create */);
460 if (auto error = std::get_if<int>(&encryption_key_result)) {
461 return *error;
462 }
463 auto encryption_key = std::get<ks2::KeyEntryResponse>(encryption_key_result);
464
465 std::string authentication_key_name = name + kAuthenticateSuffix;
466 auto authentication_key_result = loadOrCreateAndVerifyAuthenticationKey(
467 authentication_key_name, keymint::SecurityLevel::KEYSTORE /* ignored */,
468 false /* create */);
469 if (auto error = std::get_if<int>(&authentication_key_result)) {
470 return *error;
471 }
472 auto authentication_key = std::get<ks2::KeyEntryResponse>(authentication_key_result);
473
474 // Begin authentication operation
475 ks2::CreateOperationResponse signOperationResponse;
476 auto sign_params = keymint::AuthorizationSetBuilder()
477 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::VERIFY)
478 .Digest(keymint::Digest::SHA_2_256)
479 .Authorization(keymint::TAG_MAC_LENGTH, kHMACOutputSize);
480
481 auto rc = authentication_key.iSecurityLevel->createOperation(
482 authentication_key.metadata.key, sign_params.vector_data(), false /* forced */,
483 &signOperationResponse);
484 if (!rc.isOk()) {
485 std::cerr << "Failed to begin verify operation: " << rc.getDescription() << std::endl;
486 return unwrapError(rc);
487 }
488
489 const uint8_t* p = reinterpret_cast<const uint8_t*>(protobuf.init_vector().data());
490 std::vector<uint8_t> toBeVerified(p, p + protobuf.init_vector().size());
491
492 p = reinterpret_cast<const uint8_t*>(protobuf.encrypted_data().data());
493 toBeVerified.insert(toBeVerified.end(), p, p + protobuf.encrypted_data().size());
494
495 p = reinterpret_cast<const uint8_t*>(protobuf.authentication_data().data());
496 std::vector<uint8_t> signature(p, p + protobuf.authentication_data().size());
497
498 std::optional<std::vector<uint8_t>> optOut;
499 rc = signOperationResponse.iOperation->finish(toBeVerified, signature, &optOut);
500 if (!rc.isOk()) {
501 std::cerr << "Decrypt: HMAC verification failed: " << rc.getDescription() << std::endl;
502 return unwrapError(rc);
503 }
504
505 // Begin decryption operation
506 ks2::CreateOperationResponse encOperationResponse;
507 auto encrypt_params = keymint::AuthorizationSetBuilder()
508 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::DECRYPT)
509 .Authorization(keymint::TAG_NONCE, protobuf.init_vector().data(),
510 protobuf.init_vector().size())
511 .Padding(keymint::PaddingMode::PKCS7)
512 .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC);
513
514 rc = encryption_key.iSecurityLevel->createOperation(encryption_key.metadata.key,
515 encrypt_params.vector_data(),
516 false /* forced */, &encOperationResponse);
517 if (!rc.isOk()) {
518 std::cerr << "Failed to begin encryption operation: " << rc.getDescription() << std::endl;
519 return unwrapError(rc);
520 }
521
522 std::optional<std::vector<uint8_t>> optPlaintext;
523
524 p = reinterpret_cast<const uint8_t*>(protobuf.encrypted_data().data());
525 std::vector<uint8_t> cyphertext(p, p + protobuf.encrypted_data().size());
526
527 rc = encOperationResponse.iOperation->finish(cyphertext, {}, &optPlaintext);
528 if (!rc.isOk()) {
529 std::cerr << "Failed to finish encryption operation: " << rc.getDescription() << std::endl;
530 return unwrapError(rc);
531 }
532
533 if (!optPlaintext) {
534 std::cerr << "Decryption succeeded but no plaintext returned." << std::endl;
535 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
536 }
537
538 return *optPlaintext;
539}
540
541bool TestKey(const std::string& name, bool required,
542 const std::vector<keymint::KeyParameter>& parameters) {
543 auto keystore = CreateKeystoreInstance();
544 auto sec_level =
545 GetSecurityLevelInterface(keystore, keymint::SecurityLevel::TRUSTED_ENVIRONMENT);
546
547 ks2::KeyDescriptor keyDescriptor = {
548 .domain = ks2::Domain::APP,
549 .nspace = -1,
550 .alias = "tmp",
551 .blob = {},
552 };
553
554 ks2::KeyMetadata keyMetadata;
555
556 auto rc = sec_level->generateKey(keyDescriptor, {} /* attestationKey */, parameters,
557 0 /* flags */, {} /* entropy */, &keyMetadata);
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800558 const char kBoldRedAbort[] = "\033[1;31mABORT\033[0m";
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800559 if (!rc.isOk()) {
560 LOG(ERROR) << "Failed to generate key: " << rc.getDescription();
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800561 printf("[%s] %s\n", kBoldRedAbort, name.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -0800562 return false;
563 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800564
565 rc = keystore->deleteKey(keyDescriptor);
566 if (!rc.isOk()) {
567 LOG(ERROR) << "Failed to delete key: " << rc.getDescription();
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800568 printf("[%s] %s\n", kBoldRedAbort, name.c_str());
Darren Krahna9474ab2015-11-03 14:38:53 -0800569 return false;
570 }
571 printf("===============================================================\n");
572 printf("%s Key Characteristics:\n", name.c_str());
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800573 PrintKeyCharacteristics(keyMetadata.authorizations);
574 bool hardware_backed = std::any_of(keyMetadata.authorizations.begin(),
575 keyMetadata.authorizations.end(), isHardwareEnforced);
576 if (std::any_of(keyMetadata.authorizations.begin(), keyMetadata.authorizations.end(),
577 [&](const auto& a) {
578 return !isHardwareEnforced(a) &&
579 (a.keyParameter.tag == keymint::Tag::ALGORITHM ||
580 a.keyParameter.tag == keymint::Tag::KEY_SIZE ||
581 a.keyParameter.tag == keymint::Tag::RSA_PUBLIC_EXPONENT);
582 })) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800583 VLOG(1) << "Hardware-backed key but required characteristics enforced in software.";
584 hardware_backed = false;
585 }
586 const char kBoldRedFail[] = "\033[1;31mFAIL\033[0m";
587 const char kBoldGreenPass[] = "\033[1;32mPASS\033[0m";
588 const char kBoldYellowWarn[] = "\033[1;33mWARN\033[0m";
589 printf("[%s] %s\n",
590 hardware_backed ? kBoldGreenPass : (required ? kBoldRedFail : kBoldYellowWarn),
591 name.c_str());
592
593 return (hardware_backed || !required);
594}
595
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800596keymint::AuthorizationSet GetRSASignParameters(uint32_t key_size, bool sha256_only) {
597 keymint::AuthorizationSetBuilder parameters;
Darren Krahna9474ab2015-11-03 14:38:53 -0800598 parameters.RsaSigningKey(key_size, 65537)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800599 .Digest(keymint::Digest::SHA_2_256)
600 .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN)
601 .Padding(keymint::PaddingMode::RSA_PSS)
602 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800603 if (!sha256_only) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800604 parameters.Digest(keymint::Digest::SHA_2_224)
605 .Digest(keymint::Digest::SHA_2_384)
606 .Digest(keymint::Digest::SHA_2_512);
Darren Krahna9474ab2015-11-03 14:38:53 -0800607 }
Yi Kong53b02f72018-07-26 17:13:50 -0700608 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800609}
610
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800611keymint::AuthorizationSet GetRSAEncryptParameters(uint32_t key_size) {
612 keymint::AuthorizationSetBuilder parameters;
Darren Krahna9474ab2015-11-03 14:38:53 -0800613 parameters.RsaEncryptionKey(key_size, 65537)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800614 .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_ENCRYPT)
615 .Padding(keymint::PaddingMode::RSA_OAEP)
616 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Yi Kong53b02f72018-07-26 17:13:50 -0700617 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800618}
619
David Drysdaleff0f5922021-10-14 15:13:16 +0100620keymint::AuthorizationSet GetECDSAParameters(keymint::EcCurve curve, bool sha256_only) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800621 keymint::AuthorizationSetBuilder parameters;
David Drysdaleff0f5922021-10-14 15:13:16 +0100622 parameters.EcdsaSigningKey(curve)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800623 .Digest(keymint::Digest::SHA_2_256)
624 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800625 if (!sha256_only) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800626 parameters.Digest(keymint::Digest::SHA_2_224)
627 .Digest(keymint::Digest::SHA_2_384)
628 .Digest(keymint::Digest::SHA_2_512);
Darren Krahna9474ab2015-11-03 14:38:53 -0800629 }
Yi Kong53b02f72018-07-26 17:13:50 -0700630 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800631}
632
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800633keymint::AuthorizationSet GetAESParameters(uint32_t key_size, bool with_gcm_mode) {
634 keymint::AuthorizationSetBuilder parameters;
635 parameters.AesEncryptionKey(key_size).Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Darren Krahna9474ab2015-11-03 14:38:53 -0800636 if (with_gcm_mode) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800637 parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::GCM)
638 .Authorization(keymint::TAG_MIN_MAC_LENGTH, 128);
Darren Krahna9474ab2015-11-03 14:38:53 -0800639 } else {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800640 parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::ECB);
641 parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC);
642 parameters.Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CTR);
643 parameters.Padding(keymint::PaddingMode::NONE);
Darren Krahna9474ab2015-11-03 14:38:53 -0800644 }
Yi Kong53b02f72018-07-26 17:13:50 -0700645 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800646}
647
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800648keymint::AuthorizationSet GetHMACParameters(uint32_t key_size, keymint::Digest digest) {
649 keymint::AuthorizationSetBuilder parameters;
Darren Krahna9474ab2015-11-03 14:38:53 -0800650 parameters.HmacKey(key_size)
651 .Digest(digest)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800652 .Authorization(keymint::TAG_MIN_MAC_LENGTH, 224)
653 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Yi Kong53b02f72018-07-26 17:13:50 -0700654 return std::move(parameters);
Darren Krahna9474ab2015-11-03 14:38:53 -0800655}
656
657std::vector<TestCase> GetTestCases() {
658 TestCase test_cases[] = {
659 {"RSA-2048 Sign", true, GetRSASignParameters(2048, true)},
660 {"RSA-2048 Sign (more digests)", false, GetRSASignParameters(2048, false)},
661 {"RSA-3072 Sign", false, GetRSASignParameters(3072, false)},
662 {"RSA-4096 Sign", false, GetRSASignParameters(4096, false)},
663 {"RSA-2048 Encrypt", true, GetRSAEncryptParameters(2048)},
664 {"RSA-3072 Encrypt", false, GetRSAEncryptParameters(3072)},
665 {"RSA-4096 Encrypt", false, GetRSAEncryptParameters(4096)},
David Drysdaleff0f5922021-10-14 15:13:16 +0100666 {"ECDSA-P256 Sign", true, GetECDSAParameters(keymint::EcCurve::P_256, true)},
667 {"ECDSA-P256 Sign (more digests)", false,
668 GetECDSAParameters(keymint::EcCurve::P_256, false)},
669 {"ECDSA-P224 Sign", false, GetECDSAParameters(keymint::EcCurve::P_224, false)},
670 {"ECDSA-P384 Sign", false, GetECDSAParameters(keymint::EcCurve::P_384, false)},
671 {"ECDSA-P521 Sign", false, GetECDSAParameters(keymint::EcCurve::P_521, false)},
Darren Krahna9474ab2015-11-03 14:38:53 -0800672 {"AES-128", true, GetAESParameters(128, false)},
673 {"AES-256", true, GetAESParameters(256, false)},
674 {"AES-128-GCM", false, GetAESParameters(128, true)},
675 {"AES-256-GCM", false, GetAESParameters(256, true)},
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800676 {"HMAC-SHA256-16", true, GetHMACParameters(16, keymint::Digest::SHA_2_256)},
677 {"HMAC-SHA256-32", true, GetHMACParameters(32, keymint::Digest::SHA_2_256)},
678 {"HMAC-SHA256-64", false, GetHMACParameters(64, keymint::Digest::SHA_2_256)},
679 {"HMAC-SHA224-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_224)},
680 {"HMAC-SHA384-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_384)},
681 {"HMAC-SHA512-32", false, GetHMACParameters(32, keymint::Digest::SHA_2_512)},
Darren Krahna9474ab2015-11-03 14:38:53 -0800682 };
683 return std::vector<TestCase>(&test_cases[0], &test_cases[arraysize(test_cases)]);
684}
685
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800686int BrilloPlatformTest(const std::string& prefix, bool test_for_0_3) {
687 const char kBoldYellowWarning[] = "\033[1;33mWARNING\033[0m";
688 if (test_for_0_3) {
689 printf("%s: Testing for keymaster v0.3. "
Shawn Willdenbb22a6c2017-12-06 19:35:28 -0700690 "This does not meet Brillo requirements.\n",
691 kBoldYellowWarning);
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800692 }
Darren Krahna9474ab2015-11-03 14:38:53 -0800693 int test_count = 0;
694 int fail_count = 0;
695 std::vector<TestCase> test_cases = GetTestCases();
696 for (const auto& test_case : test_cases) {
Darren Krahn82f4f5b2016-03-03 16:21:07 -0800697 if (!prefix.empty() &&
698 !base::StartsWith(test_case.name, prefix, base::CompareCase::SENSITIVE)) {
699 continue;
700 }
701 if (test_for_0_3 &&
702 (base::StartsWith(test_case.name, "AES", base::CompareCase::SENSITIVE) ||
703 base::StartsWith(test_case.name, "HMAC", base::CompareCase::SENSITIVE))) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800704 continue;
705 }
706 ++test_count;
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800707 if (!TestKey(test_case.name, test_case.required_for_brillo_pts,
708 test_case.parameters.vector_data())) {
Darren Krahna9474ab2015-11-03 14:38:53 -0800709 VLOG(1) << "Test failed: " << test_case.name;
710 ++fail_count;
711 }
712 }
713 return fail_count;
714}
715
716int ListTestCases() {
717 const char kBoldGreenRequired[] = "\033[1;32mREQUIRED\033[0m";
718 const char kBoldYellowRecommended[] = "\033[1;33mRECOMMENDED\033[0m";
719 std::vector<TestCase> test_cases = GetTestCases();
720 for (const auto& test_case : test_cases) {
721 printf("%s : %s\n", test_case.name.c_str(),
722 test_case.required_for_brillo_pts ? kBoldGreenRequired : kBoldYellowRecommended);
723 }
724 return 0;
725}
726
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800727std::vector<uint8_t> ReadFile(const std::string& filename) {
Darren Krahn251cb282015-09-28 08:51:18 -0700728 std::string content;
729 base::FilePath path(filename);
730 if (!base::ReadFileToString(path, &content)) {
731 printf("Failed to read file: %s\n", filename.c_str());
732 exit(1);
733 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800734 std::vector<uint8_t> buffer(reinterpret_cast<const uint8_t*>(content.data()),
735 reinterpret_cast<const uint8_t*>(content.data()) + content.size());
736 return buffer;
Darren Krahn251cb282015-09-28 08:51:18 -0700737}
738
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800739void WriteFile(const std::string& filename, const std::vector<uint8_t>& content) {
Darren Krahn251cb282015-09-28 08:51:18 -0700740 base::FilePath path(filename);
741 int size = content.size();
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800742 if (base::WriteFile(path, reinterpret_cast<const char*>(content.data()), size) != size) {
Darren Krahn251cb282015-09-28 08:51:18 -0700743 printf("Failed to write file: %s\n", filename.c_str());
744 exit(1);
745 }
746}
747
Rob Barneseb7f79b2018-11-08 15:44:10 -0700748// Note: auth_bound keys created with this tool will not be usable.
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800749int GenerateKey(const std::string& name, keymint::SecurityLevel securityLevel, bool auth_bound) {
750 auto keystore = CreateKeystoreInstance();
751 auto sec_level = GetSecurityLevelInterface(keystore, securityLevel);
752 keymint::AuthorizationSetBuilder params;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700753 params.RsaSigningKey(2048, 65537)
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800754 .Digest(keymint::Digest::SHA_2_224)
755 .Digest(keymint::Digest::SHA_2_256)
756 .Digest(keymint::Digest::SHA_2_384)
757 .Digest(keymint::Digest::SHA_2_512)
758 .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN)
759 .Padding(keymint::PaddingMode::RSA_PSS);
Rob Barneseb7f79b2018-11-08 15:44:10 -0700760 if (auth_bound) {
761 // Gatekeeper normally generates the secure user id.
762 // Using zero allows the key to be created, but it will not be usuable.
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800763 params.Authorization(keymint::TAG_USER_SECURE_ID, 0);
Rob Barneseb7f79b2018-11-08 15:44:10 -0700764 } else {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800765 params.Authorization(keymint::TAG_NO_AUTH_REQUIRED);
Rob Barneseb7f79b2018-11-08 15:44:10 -0700766 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800767
768 ks2::KeyMetadata keyMetadata;
769
770 auto rc =
771 sec_level->generateKey(keyDescriptor(name), {} /* attestationKey */, params.vector_data(),
772 0 /* flags */, {} /* entropy */, &keyMetadata);
773
Janis Danisevskis2cb4f092021-05-17 13:25:07 -0700774 if (!rc.isOk()) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800775 std::cerr << "GenerateKey failed: " << rc.getDescription() << std::endl;
776 return unwrapError(rc);
Darren Krahna9474ab2015-11-03 14:38:53 -0800777 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800778 std::cout << "GenerateKey: success" << std::endl;
779 PrintKeyCharacteristics(keyMetadata.authorizations);
780 return 0;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700781}
782
783int GetCharacteristics(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800784 auto keystore = CreateKeystoreInstance();
785
786 ks2::KeyEntryResponse keyEntryResponse;
787
788 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
789 if (!rc.isOk()) {
790 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
791 return unwrapError(rc);
Darren Krahna9474ab2015-11-03 14:38:53 -0800792 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800793
794 std::cout << "GetCharacteristics: success" << std::endl;
795 PrintKeyCharacteristics(keyEntryResponse.metadata.authorizations);
796 return 0;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700797}
798
799int ExportKey(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800800 auto keystore = CreateKeystoreInstance();
801
802 ks2::KeyEntryResponse keyEntryResponse;
803
804 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
805 if (!rc.isOk()) {
806 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
807 return unwrapError(rc);
808 }
809
810 if (auto cert = keyEntryResponse.metadata.certificate) {
811 std::cout << "ExportKey: Got certificate of length (" << cert->size() << ")" << std::endl;
812 } else {
813 std::cout << "ExportKey: Key entry does not have a public component.\n";
814 std::cout << "Possibly a symmetric key?" << std::endl;
815 }
816 return 0;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700817}
818
819int DeleteKey(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800820 auto keystore = CreateKeystoreInstance();
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700821
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800822 auto rc = keystore->deleteKey(keyDescriptor(name));
823 if (!rc.isOk()) {
824 std::cerr << "Failed to delete key: " << rc.getDescription();
825 return unwrapError(rc);
826 }
827 std::cout << "Successfully deleted key." << std::endl;
828 return 0;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700829}
830
831int DoesKeyExist(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800832 auto keystore = CreateKeystoreInstance();
833 ks2::KeyEntryResponse keyEntryResponse;
834
835 bool keyExists = true;
836 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
837 if (!rc.isOk()) {
838 auto responseCode = unwrapError(rc);
839 if (ks2::ResponseCode(responseCode) == ks2::ResponseCode::KEY_NOT_FOUND) {
840 keyExists = false;
841 } else {
842 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
843 return unwrapError(rc);
844 }
845 }
846 std::cout << "DoesKeyExists: " << (keyExists ? "yes" : "no") << std::endl;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700847 return 0;
848}
849
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800850int List() {
851 auto keystore = CreateKeystoreInstance();
852 std::vector<ks2::KeyDescriptor> key_list;
853 auto rc = keystore->listEntries(ks2::Domain::APP, -1 /* nspace ignored */, &key_list);
854 if (!rc.isOk()) {
855 std::cerr << "ListKeys failed: " << rc.getDescription() << std::endl;
856 return unwrapError(rc);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700857 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800858 std::cout << "Keys:\n";
859 for (const auto& key : key_list) {
860 std::cout << " "
861 << (key.alias ? *key.alias : "Whoopsi - no alias, this should not happen.")
862 << std::endl;
Rob Barneseb7f79b2018-11-08 15:44:10 -0700863 }
864 return 0;
865}
866
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700867int SignAndVerify(const std::string& name) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800868 auto keystore = CreateKeystoreInstance();
869 auto sign_params = keymint::AuthorizationSetBuilder()
870 .Authorization(keymint::TAG_PURPOSE, keymint::KeyPurpose::SIGN)
871 .Padding(keymint::PaddingMode::RSA_PKCS1_1_5_SIGN)
872 .Digest(keymint::Digest::SHA_2_256);
873
874 keymint::AuthorizationSet output_params;
875
876 ks2::KeyEntryResponse keyEntryResponse;
877
878 auto rc = keystore->getKeyEntry(keyDescriptor(name), &keyEntryResponse);
879 if (!rc.isOk()) {
880 std::cerr << "Failed to get key entry: " << rc.getDescription() << std::endl;
881 return unwrapError(rc);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700882 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800883
884 ks2::CreateOperationResponse operationResponse;
885
886 rc = keyEntryResponse.iSecurityLevel->createOperation(keyEntryResponse.metadata.key,
887 sign_params.vector_data(),
888 false /* forced */, &operationResponse);
889 if (!rc.isOk()) {
890 std::cerr << "Failed to create operation: " << rc.getDescription() << std::endl;
891 return unwrapError(rc);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700892 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800893
894 const std::vector<uint8_t> data_to_sign{0x64, 0x61, 0x74, 0x61, 0x5f, 0x74,
895 0x6f, 0x5f, 0x73, 0x69, 0x67, 0x6e};
896 std::optional<std::vector<uint8_t>> output_data;
897 rc = operationResponse.iOperation->finish(data_to_sign, {}, &output_data);
898 if (!rc.isOk()) {
899 std::cerr << "Failed to finalize operation: " << rc.getDescription() << std::endl;
900 return unwrapError(rc);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700901 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800902
903 if (!output_data) {
904 std::cerr << "Odd signing succeeded but no signature was returned." << std::endl;
905 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700906 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800907 auto signature = std::move(*output_data);
908
909 std::cout << "Sign: " << signature.size() << " bytes." << std::endl;
910
911 if (auto cert = keyEntryResponse.metadata.certificate) {
912 const uint8_t* p = cert->data();
913 bssl::UniquePtr<X509> decoded_cert(d2i_X509(nullptr, &p, (long)cert->size()));
914 bssl::UniquePtr<EVP_PKEY> decoded_pkey(X509_get_pubkey(decoded_cert.get()));
915 bssl::UniquePtr<EVP_MD_CTX> ctx(EVP_MD_CTX_new());
916 if (!ctx) {
917 std::cerr << "Failed to created EVP_MD context. << std::endl";
918 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
919 }
920
921 if (!EVP_DigestVerifyInit(ctx.get(), nullptr, EVP_sha256(), nullptr, decoded_pkey.get()) ||
922 !EVP_DigestVerifyUpdate(ctx.get(), data_to_sign.data(), data_to_sign.size()) ||
923 EVP_DigestVerifyFinal(ctx.get(), signature.data(), signature.size()) != 1) {
924 std::cerr << "Failed to verify signature." << std::endl;
925 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
926 }
927 } else {
928 std::cerr << "No public key to check signature against." << std::endl;
929 return static_cast<int>(ks2::ResponseCode::SYSTEM_ERROR);
930 }
931
932 std::cout << "Verify: OK" << std::endl;
Darren Krahn69a3dbc2015-09-22 16:21:04 -0700933 return 0;
934}
935
Darren Krahn251cb282015-09-28 08:51:18 -0700936int Encrypt(const std::string& key_name, const std::string& input_filename,
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800937 const std::string& output_filename, keymint::SecurityLevel securityLevel) {
938 auto input = ReadFile(input_filename);
939 auto result = encryptWithAuthentication(key_name, input, securityLevel);
940 if (auto error = std::get_if<int>(&result)) {
941 std::cerr << "EncryptWithAuthentication failed." << std::endl;
942 return *error;
Darren Krahn251cb282015-09-28 08:51:18 -0700943 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800944 WriteFile(output_filename, std::get<std::vector<uint8_t>>(result));
Darren Krahn251cb282015-09-28 08:51:18 -0700945 return 0;
946}
947
948int Decrypt(const std::string& key_name, const std::string& input_filename,
949 const std::string& output_filename) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800950 auto input = ReadFile(input_filename);
951 auto result = decryptWithAuthentication(key_name, input);
952 if (auto error = std::get_if<int>(&result)) {
953 std::cerr << "DecryptWithAuthentication failed." << std::endl;
954 return *error;
Darren Krahn251cb282015-09-28 08:51:18 -0700955 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800956 WriteFile(output_filename, std::get<std::vector<uint8_t>>(result));
Darren Krahn251cb282015-09-28 08:51:18 -0700957 return 0;
958}
959
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800960keymint::SecurityLevel securityLevelOption2SecurlityLevel(const CommandLine& cmd) {
Janis Danisevskisc1460142017-12-18 16:48:46 -0800961 if (cmd.HasSwitch("seclevel")) {
962 auto str = cmd.GetSwitchValueASCII("seclevel");
963 if (str == "strongbox") {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800964 return keymint::SecurityLevel::STRONGBOX;
965 } else if (str == "tee") {
966 return keymint::SecurityLevel::TRUSTED_ENVIRONMENT;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800967 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800968 std::cerr << "Unknown Security level: " << str << std::endl;
969 std::cerr << "Supported security levels: \"strongbox\" or \"tee\" (default)" << std::endl;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800970 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800971 return keymint::SecurityLevel::TRUSTED_ENVIRONMENT;
Janis Danisevskisc1460142017-12-18 16:48:46 -0800972}
973
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -0800974class ConfirmationListener
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800975 : public apc::BnConfirmationCallback,
976 public std::promise<std::tuple<apc::ResponseCode, std::optional<std::vector<uint8_t>>>> {
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500977 public:
978 ConfirmationListener() {}
979
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800980 virtual ::ndk::ScopedAStatus
981 onCompleted(::aidl::android::security::apc::ResponseCode result,
982 const std::optional<std::vector<uint8_t>>& dataConfirmed) override {
983 this->set_value({result, dataConfirmed});
984 return ::ndk::ScopedAStatus::ok();
985 };
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500986};
987
988int Confirmation(const std::string& promptText, const std::string& extraDataHex,
989 const std::string& locale, const std::string& uiOptionsStr,
990 const std::string& cancelAfter) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -0800991 ::ndk::SpAIBinder apcBinder(AServiceManager_getService("android.security.apc"));
992 auto apcService = apc::IProtectedConfirmation::fromBinder(apcBinder);
993 if (!apcService) {
994 std::cerr << "Error: could not connect to apc service." << std::endl;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500995 return 1;
996 }
997
998 if (promptText.size() == 0) {
Janis Danisevskis1a8d5802018-03-14 13:38:07 -0700999 printf("The --prompt_text parameter cannot be empty.\n");
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001000 return 1;
1001 }
1002
1003 std::vector<uint8_t> extraData;
1004 if (!base::HexStringToBytes(extraDataHex, &extraData)) {
1005 printf("The --extra_data parameter does not appear to be valid hexadecimal.\n");
1006 return 1;
1007 }
1008
1009 std::vector<std::string> pieces =
1010 base::SplitString(uiOptionsStr, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
1011 int uiOptionsAsFlags = 0;
1012 for (auto& p : pieces) {
1013 int value;
1014 if (!base::StringToInt(p, &value)) {
1015 printf("Error parsing %s in --ui_options parameter as a number.\n", p.c_str());
1016 return 1;
1017 }
1018 uiOptionsAsFlags |= (1 << value);
1019 }
1020
1021 double cancelAfterValue = 0.0;
1022
1023 if (cancelAfter.size() > 0 && !base::StringToDouble(cancelAfter, &cancelAfterValue)) {
1024 printf("Error parsing %s in --cancel_after parameter as a double.\n", cancelAfter.c_str());
1025 return 1;
1026 }
1027
Frederick Mayle9afe8822022-03-23 17:00:27 +00001028 auto listener = ndk::SharedRefBase::make<ConfirmationListener>();
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001029
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001030 auto future = listener->get_future();
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001031 auto rc = apcService->presentPrompt(listener, promptText, extraData, locale, uiOptionsAsFlags);
1032
1033 if (!rc.isOk()) {
1034 std::cerr << "Presenting confirmation prompt failed: " << rc.getDescription() << std::endl;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001035 return 1;
1036 }
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001037
1038 std::cerr << "Waiting for prompt to complete - use Ctrl+C to abort..." << std::endl;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001039
1040 if (cancelAfterValue > 0.0) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001041 std::cerr << "Sleeping " << cancelAfterValue << " seconds before canceling prompt..."
1042 << std::endl;
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001043 auto fstatus =
1044 future.wait_for(std::chrono::milliseconds(uint64_t(cancelAfterValue * 1000)));
1045 if (fstatus == std::future_status::timeout) {
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001046 rc = apcService->cancelPrompt(listener);
1047 if (!rc.isOk()) {
1048 std::cerr << "Canceling confirmation prompt failed: " << rc.getDescription()
1049 << std::endl;
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001050 return 1;
1051 }
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001052 }
1053 }
1054
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001055 future.wait();
1056
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001057 auto [responseCode, dataThatWasConfirmed] = future.get();
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001058
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001059 std::cerr << "Confirmation prompt completed\n"
1060 << "responseCode = " << toString(responseCode);
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001061 size_t newLineCountDown = 16;
1062 bool hasPrinted = false;
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001063 if (dataThatWasConfirmed) {
1064 std::cerr << "dataThatWasConfirmed[" << dataThatWasConfirmed->size() << "] = {";
1065 for (uint8_t element : *dataThatWasConfirmed) {
1066 if (hasPrinted) {
1067 std::cerr << ", ";
1068 }
1069 if (newLineCountDown == 0) {
1070 std::cerr << "\n ";
1071 newLineCountDown = 32;
1072 }
1073 std::cerr << "0x" << std::hex << std::setw(2) << std::setfill('0') << (unsigned)element;
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001074
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001075 hasPrinted = true;
1076 }
1077 }
1078 std::cerr << std::endl;
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001079 return 0;
1080}
1081
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001082} // namespace
1083
1084int main(int argc, char** argv) {
1085 CommandLine::Init(argc, argv);
1086 CommandLine* command_line = CommandLine::ForCurrentProcess();
1087 CommandLine::StringVector args = command_line->GetArgs();
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001088
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001089 ABinderProcess_startThreadPool();
Janis Danisevskis4aec5bc2018-11-14 20:36:55 -08001090
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001091 if (args.empty()) {
1092 PrintUsageAndExit();
1093 }
Darren Krahna9474ab2015-11-03 14:38:53 -08001094 if (args[0] == "brillo-platform-test") {
Darren Krahn82f4f5b2016-03-03 16:21:07 -08001095 return BrilloPlatformTest(command_line->GetSwitchValueASCII("prefix"),
1096 command_line->HasSwitch("test_for_0_3"));
Darren Krahna9474ab2015-11-03 14:38:53 -08001097 } else if (args[0] == "list-brillo-tests") {
1098 return ListTestCases();
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001099 } else if (args[0] == "generate") {
Janis Danisevskisc1460142017-12-18 16:48:46 -08001100 return GenerateKey(command_line->GetSwitchValueASCII("name"),
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001101 securityLevelOption2SecurlityLevel(*command_line),
Rob Barneseb7f79b2018-11-08 15:44:10 -07001102 command_line->HasSwitch("auth_bound"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001103 } else if (args[0] == "get-chars") {
1104 return GetCharacteristics(command_line->GetSwitchValueASCII("name"));
1105 } else if (args[0] == "export") {
1106 return ExportKey(command_line->GetSwitchValueASCII("name"));
1107 } else if (args[0] == "delete") {
1108 return DeleteKey(command_line->GetSwitchValueASCII("name"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001109 } else if (args[0] == "exists") {
1110 return DoesKeyExist(command_line->GetSwitchValueASCII("name"));
1111 } else if (args[0] == "list") {
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001112 return List();
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001113 } else if (args[0] == "sign-verify") {
1114 return SignAndVerify(command_line->GetSwitchValueASCII("name"));
Darren Krahn251cb282015-09-28 08:51:18 -07001115 } else if (args[0] == "encrypt") {
Janis Danisevskis2437fde2021-03-08 11:30:11 -08001116 return Encrypt(command_line->GetSwitchValueASCII("name"),
1117 command_line->GetSwitchValueASCII("in"),
1118 command_line->GetSwitchValueASCII("out"),
1119 securityLevelOption2SecurlityLevel(*command_line));
Darren Krahn251cb282015-09-28 08:51:18 -07001120 } else if (args[0] == "decrypt") {
1121 return Decrypt(command_line->GetSwitchValueASCII("name"),
1122 command_line->GetSwitchValueASCII("in"),
1123 command_line->GetSwitchValueASCII("out"));
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001124 } else if (args[0] == "confirmation") {
Janis Danisevskis1a8d5802018-03-14 13:38:07 -07001125 return Confirmation(command_line->GetSwitchValueNative("prompt_text"),
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001126 command_line->GetSwitchValueASCII("extra_data"),
1127 command_line->GetSwitchValueASCII("locale"),
1128 command_line->GetSwitchValueASCII("ui_options"),
1129 command_line->GetSwitchValueASCII("cancel_after"));
Darren Krahn69a3dbc2015-09-22 16:21:04 -07001130 } else {
1131 PrintUsageAndExit();
1132 }
1133 return 0;
1134}