blob: b2ae313fbcb4e9745e2f31899db9b00b400675b0 [file] [log] [blame]
David Drysdale9f5c0c52022-11-03 15:10:16 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// The tests in this file are intended to be run manually, to allow testing of whether
18// keyblob upgrade works correctly. The manual procedure is roughly:
19//
20// 1) Run the "*Before*" subset of these tests with the `--keyblob_dir <dir>` command-line argument
21// so that keyblobs are saved to a directory on the device:
22//
23// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest*Before*" \
24// --keyblob_dir /data/local/tmp/keymint-blobs
25//
26// All tests should pass, and the `UpgradeKeyBlobs` test should indicate that no keyblob
27// upgrades were needed.
28//
29// 2) Copy the generated keyblobs off the device into a safe place.
30//
31// adb pull /data/local/tmp/keymint-blobs
32//
33// 3) Upgrade the device to a new version.
34//
35// 4) Push the saved keyblobs back onto the upgraded device.
36//
37// adb push keymint-blobs /data/local/tmp/keymint-blobs
38//
39// 5) Run the "*After*" subset of these tests with the `--keyblob_dir <dir>` command-line argument
40// pointing to the directory with the keyblobs:
41//
42// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest*After*" \
43// --keyblob_dir /data/local/tmp/keymint-blobs
44//
45// (Note that this skips the `CreateKeyBlobs` test, which would otherwise replace the saved
46// keyblobs with freshly generated ones.).
47//
48// All tests should pass, and the `UpgradeKeyBlobs` test should have output that matches whether
49// upgrade was expected or not.
50
51#define LOG_TAG "keymint_1_test"
52#include <cutils/log.h>
53
54#include <algorithm>
55#include <fstream>
56#include <iostream>
57
58#include <unistd.h>
59
60#include <openssl/curve25519.h>
61#include <openssl/ec.h>
62#include <openssl/evp.h>
63#include <openssl/mem.h>
64#include <openssl/x509v3.h>
65
66#include "KeyMintAidlTestBase.h"
67
68using aidl::android::hardware::security::keymint::KeyCharacteristics;
69
70namespace aidl::android::hardware::security::keymint::test {
71
72namespace {
73
74std::vector<std::string> keyblob_names_tee = {
75 "aes-key", "aes-key-rr", "des-key", "hmac-key",
76 "rsa-key", "p256-key", "ed25519-key", "x25519-key",
77 "rsa-attest-key", "p256-attest-key", "ed25519-attest-key"};
78
79std::vector<std::string> keyblob_names_sb = {"aes-key", "aes-key-rr", "des-key",
80 "hmac-key", "rsa-key", "p256-key",
81 "rsa-attest-key", "p256-attest-key"};
82
83const std::vector<std::string>& keyblob_names(SecurityLevel sec_level) {
84 if (sec_level == SecurityLevel::STRONGBOX) {
85 return keyblob_names_sb;
86 } else {
87 return keyblob_names_tee;
88 }
89}
90
91bool requires_rr(const std::string& name) {
92 return name.find("-rr") != std::string::npos;
93}
94
95bool is_asymmetric(const std::string& name) {
96 return (name.find("rsa") != std::string::npos || name.find("25519") != std::string::npos ||
97 name.find("p256") != std::string::npos);
98}
99
100std::string keyblob_subdir(const std::string& keyblob_dir, const std::string& full_name,
101 bool create) {
102 if (keyblob_dir.empty()) {
103 return "";
104 }
105
106 // Use a subdirectory for the specific instance, so two different KeyMint instances won't
107 // clash with each other.
108 size_t found = full_name.find_last_of('/');
109 std::string subdir = keyblob_dir + "/" + full_name.substr(found + 1);
110
111 if (create) {
112 mkdir(keyblob_dir.c_str(), 0777);
113 mkdir(subdir.c_str(), 0777);
114 }
115 return subdir;
116}
117
118void save_keyblob(const std::string& subdir, const std::string& name,
119 const vector<uint8_t>& keyblob,
120 const std::vector<KeyCharacteristics>& key_characteristics) {
121 // Write the keyblob out to a file.
122 std::string blobname(subdir + "/" + name + ".keyblob");
123 std::ofstream blobfile(blobname, std::ios::out | std::ios::trunc | std::ios::binary);
124 blobfile.write(reinterpret_cast<const char*>(keyblob.data()), keyblob.size());
125 blobfile.close();
126
127 // Dump the characteristics too.
128 std::string charsname(subdir + "/" + name + ".chars");
129 std::ofstream charsfile(charsname, std::ios::out | std::ios::trunc);
130 charsfile << "{\n";
131 for (const auto& characteristic : key_characteristics) {
132 charsfile << " " << characteristic.toString() << "\n";
133 }
134 charsfile << "}\n";
135 charsfile.close();
136
137 // Also write out a hexdump of the keyblob for convenience.
138 std::string hexname(subdir + "/" + name + ".hex");
139 std::ofstream hexfile(hexname, std::ios::out | std::ios::trunc);
140 hexfile << bin2hex(keyblob) << "\n";
141 hexfile.close();
142}
143
144void save_keyblob_and_cert(const std::string& subdir, const std::string& name,
145 const vector<uint8_t>& keyblob,
146 const std::vector<KeyCharacteristics>& key_characteristics,
147 const std::vector<Certificate>& cert_chain) {
148 save_keyblob(subdir, name, keyblob, key_characteristics);
149
150 if (is_asymmetric(name)) {
151 // Dump the leaf certificate as DER.
152 if (cert_chain.empty()) {
153 FAIL() << "No cert available for " << name;
154 } else {
155 const vector<uint8_t>& certdata = cert_chain[0].encodedCertificate;
156 std::string certname(subdir + "/" + name + ".cert");
157 std::ofstream certfile(certname, std::ios::out | std::ios::trunc | std::ios::binary);
158 certfile.write(reinterpret_cast<const char*>(certdata.data()), certdata.size());
159 certfile.close();
160 }
161 }
162}
163
164void delete_keyblob(const std::string& subdir, const std::string& name) {
165 std::string blobname(subdir + "/" + name + ".keyblob");
166 unlink(blobname.c_str());
167 std::string charsname(subdir + "/" + name + ".chars");
168 unlink(charsname.c_str());
169 std::string hexname(subdir + "/" + name + ".hex");
170 unlink(hexname.c_str());
171 std::string certname(subdir + "/" + name + ".cert");
172 unlink(certname.c_str());
173}
174
175std::vector<uint8_t> load_file(const std::string& subdir, const std::string& name,
176 const std::string& suffix) {
177 std::string blobname(subdir + "/" + name + suffix);
178 std::ifstream blobfile(blobname, std::ios::in | std::ios::binary);
179
180 std::vector<uint8_t> data((std::istreambuf_iterator<char>(blobfile)),
181 std::istreambuf_iterator<char>());
182 return data;
183}
184
185std::vector<uint8_t> load_keyblob(const std::string& subdir, const std::string& name) {
186 return load_file(subdir, name, ".keyblob");
187}
188
189std::vector<uint8_t> load_cert(const std::string& subdir, const std::string& name) {
190 return load_file(subdir, name, ".cert");
191}
192
193} // namespace
194
195class KeyBlobUpgradeTest : public KeyMintAidlTestBase {
196 protected:
197 void UpgradeKeyBlobs(bool expectUpgrade) {
198 std::string subdir = keyblob_subdir(keyblob_dir, GetParam(), /* create? */ false);
199 if (subdir.empty()) {
200 GTEST_SKIP() << "No keyblob directory provided";
201 }
202
203 for (std::string name : keyblob_names(SecLevel())) {
204 for (bool with_hidden : {false, true}) {
205 std::string app_id;
206 std::string app_data;
207 auto builder = AuthorizationSetBuilder();
208 if (with_hidden) {
209 // Build a variant keyblob that requires app_id/app_data
210 app_id = "appid";
211 app_data = "appdata";
212 builder.Authorization(TAG_APPLICATION_ID, "appid")
213 .Authorization(TAG_APPLICATION_DATA, "appdata");
214 name += "-hidden";
215 }
216 SCOPED_TRACE(testing::Message() << name);
217
218 // Load the old format keyblob.
219 std::vector<uint8_t> keyblob = load_keyblob(subdir, name);
220 if (keyblob.empty()) {
221 if (requires_rr(name)) {
222 std::cerr << "Skipping missing keyblob file '" << name
223 << "', assuming rollback resistance unavailable\n";
224 } else {
225 FAIL() << "Missing keyblob file '" << name << "'";
226 }
227 continue;
228 }
229
230 // An upgrade will either produce a new keyblob or no data (if upgrade isn't
231 // needed).
232 std::vector<uint8_t> upgraded_keyblob;
233 Status result =
234 keymint_->upgradeKey(keyblob, builder.vector_data(), &upgraded_keyblob);
235 ASSERT_EQ(ErrorCode::OK, GetReturnErrorCode(result));
236
237 if (upgraded_keyblob.empty()) {
238 std::cerr << "Keyblob '" << name << "' did not require upgrade\n";
239 EXPECT_TRUE(!expectUpgrade) << "Keyblob '" << name << "' unexpectedly upgraded";
240 } else {
241 // Ensure the old format keyblob is deleted (so any secure deletion data is
242 // cleaned up).
243 EXPECT_EQ(ErrorCode::OK, DeleteKey(&keyblob));
244
245 std::vector<uint8_t> app_id_v(app_id.begin(), app_id.end());
246 std::vector<uint8_t> app_data_v(app_data.begin(), app_data.end());
247 std::vector<KeyCharacteristics> key_characteristics;
248 result = keymint_->getKeyCharacteristics(upgraded_keyblob, app_id_v, app_data_v,
249 &key_characteristics);
250 ASSERT_EQ(ErrorCode::OK, GetReturnErrorCode(result))
251 << "Failed getKeyCharacteristics() after upgrade";
252
253 save_keyblob(subdir, name, upgraded_keyblob, key_characteristics);
254 // Cert file is left unchanged.
255 std::cerr << "Keyblob '" << name << "' upgraded\n";
256 EXPECT_TRUE(expectUpgrade)
257 << "Keyblob '" << name << "' unexpectedly left as-is";
258 }
259 }
260 }
261 }
262};
263
264// To save off keyblobs before upgrade, use:
265//
266// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest.CreateKeyBlobs*" \
267// --keyblob_dir /data/local/tmp/keymint-blobs
268//
269// Then copy the contents of the /data/local/tmp/keymint-blobs/ directory somewhere safe:
270//
271// adb pull /data/local/tmp/keymint-blobs/
272TEST_P(KeyBlobUpgradeTest, CreateKeyBlobsBefore) {
273 std::string subdir = keyblob_subdir(keyblob_dir, GetParam(), /* create? */ true);
274
275 std::map<const std::string, AuthorizationSetBuilder> keys_info = {
276 {"aes-key", AuthorizationSetBuilder()
277 .AesEncryptionKey(256)
278 .BlockMode(BlockMode::ECB)
279 .Padding(PaddingMode::PKCS7)
280 .Authorization(TAG_NO_AUTH_REQUIRED)},
281 {"aes-key-rr", AuthorizationSetBuilder()
282 .AesEncryptionKey(256)
283 .BlockMode(BlockMode::ECB)
284 .Padding(PaddingMode::PKCS7)
285 .Authorization(TAG_ROLLBACK_RESISTANCE)
286 .Authorization(TAG_NO_AUTH_REQUIRED)},
287 {"des-key", AuthorizationSetBuilder()
288 .TripleDesEncryptionKey(168)
289 .BlockMode(BlockMode::ECB)
290 .Padding(PaddingMode::PKCS7)
291 .Authorization(TAG_NO_AUTH_REQUIRED)},
292 {"hmac-key", AuthorizationSetBuilder()
293 .HmacKey(128)
subrahmanyamana7a6f702023-01-18 18:13:27 +0000294 .Digest(Digest::SHA_2_256)
David Drysdale9f5c0c52022-11-03 15:10:16 +0000295 .Authorization(TAG_MIN_MAC_LENGTH, 128)
296 .Authorization(TAG_NO_AUTH_REQUIRED)},
297 {"rsa-key", AuthorizationSetBuilder()
298 .RsaEncryptionKey(2048, 65537)
299 .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
300 .Digest(Digest::NONE)
subrahmanyamana7a6f702023-01-18 18:13:27 +0000301 .Digest(Digest::SHA_2_256)
David Drysdale9f5c0c52022-11-03 15:10:16 +0000302 .Padding(PaddingMode::NONE)
303 .Authorization(TAG_NO_AUTH_REQUIRED)
304 .SetDefaultValidity()},
305 {
306 "p256-key",
307 AuthorizationSetBuilder()
308 .EcdsaSigningKey(EcCurve::P_256)
309 .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
310 .Digest(Digest::NONE)
subrahmanyamana7a6f702023-01-18 18:13:27 +0000311 .Digest(Digest::SHA_2_256)
David Drysdale9f5c0c52022-11-03 15:10:16 +0000312 .Authorization(TAG_NO_AUTH_REQUIRED)
313 .SetDefaultValidity(),
314 },
315 {
316 "ed25519-key",
317 AuthorizationSetBuilder()
318 .EcdsaSigningKey(EcCurve::CURVE_25519)
319 .Digest(Digest::NONE)
320 .Authorization(TAG_NO_AUTH_REQUIRED)
321 .SetDefaultValidity(),
322 },
323 {"x25519-key", AuthorizationSetBuilder()
324 .Authorization(TAG_EC_CURVE, EcCurve::CURVE_25519)
325 .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
326 .Authorization(TAG_ALGORITHM, Algorithm::EC)
327 .Authorization(TAG_NO_AUTH_REQUIRED)
328 .SetDefaultValidity()},
329 {"rsa-attest-key", AuthorizationSetBuilder()
330 .RsaKey(2048, 65537)
331 .AttestKey()
332 .Authorization(TAG_NO_AUTH_REQUIRED)
333 .SetDefaultValidity()},
334 {
335 "p256-attest-key",
336 AuthorizationSetBuilder()
337 .EcdsaKey(EcCurve::P_256)
338 .AttestKey()
339 .Authorization(TAG_NO_AUTH_REQUIRED)
340 .SetDefaultValidity(),
341 },
342 {
343 "ed25519-attest-key",
344 AuthorizationSetBuilder()
345 .EcdsaKey(EcCurve::CURVE_25519)
346 .AttestKey()
347 .Authorization(TAG_NO_AUTH_REQUIRED)
348 .SetDefaultValidity(),
349 }};
350
351 for (std::string name : keyblob_names(SecLevel())) {
352 auto entry = keys_info.find(name);
353 ASSERT_NE(entry, keys_info.end()) << "no builder for " << name;
354 auto builder = entry->second;
355 for (bool with_hidden : {false, true}) {
356 if (with_hidden) {
357 // Build a variant keyblob that requires app_id/app_data
358 builder.Authorization(TAG_APPLICATION_ID, "appid")
359 .Authorization(TAG_APPLICATION_DATA, "appdata");
360 name += "-hidden";
361 }
362 SCOPED_TRACE(testing::Message() << name);
363
364 vector<uint8_t> keyblob;
365 vector<KeyCharacteristics> key_characteristics;
366 vector<Certificate> cert_chain;
367 auto result =
368 GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain);
369
370 if (requires_rr(name) && result == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
371 // Rollback resistance support is optional.
372 std::cerr << "Skipping '" << name << "' key as rollback resistance unavailable\n";
373 continue;
374 }
375 ASSERT_EQ(ErrorCode::OK, result) << " failed for " << name;
376
377 if (!subdir.empty()) {
378 save_keyblob_and_cert(subdir, name, keyblob, key_characteristics, cert_chain);
379 }
380 }
381 }
382
383 if (!subdir.empty()) {
384 std::cerr << "Save generated keyblobs with:\n\n adb pull " << keyblob_dir << "\n\n";
385 }
386}
387
388TEST_P(KeyBlobUpgradeTest, UpgradeKeyBlobsBefore) {
389 // Check that attempting to upgrade valid keyblobs does nothing.
390 UpgradeKeyBlobs(/* expectUpgrade= */ false);
391}
392
393// To run this test:
394//
395// - save off some keyblobs before upgrade as per the CreateKeyBlobs test above.
396// - upgrade the device to a version that should trigger keyblob upgrade (e.g. different patchlevel)
397// - put the saved keyblobs back onto the upgraded device:
398//
399// adb push keymint-blobs /data/local/tmp/keymint-blobs
400//
401// - run the test with:
402//
403// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest.UpgradeKeyBlobsAfter*" \
404// --keyblob_dir /data/local/tmp/keymint-blobs
405//
406// - this replaces the keyblob contents in that directory; if needed, save the upgraded keyblobs
407// with:
408// adb pull /data/local/tmp/keymint-blobs/
409TEST_P(KeyBlobUpgradeTest, UpgradeKeyBlobsAfter) {
410 UpgradeKeyBlobs(/* expectUpgrade= */ true);
411}
412
413// To run this test:
414//
415// - save off some keyblobs before upgrade as per the CreateKeyBlobs test above
416// - if needed, upgrade the saved keyblobs as per the UpgradeKeyBlobs test above
417// - run the test with:
418//
419// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest.UseKeyBlobs*" \
420// --keyblob_dir /data/local/tmp/keymint-blobs
421TEST_P(KeyBlobUpgradeTest, UseKeyBlobsBeforeOrAfter) {
422 std::string subdir = keyblob_subdir(keyblob_dir, GetParam(), /* create? */ false);
423 if (subdir.empty()) {
424 GTEST_SKIP() << "No keyblob directory provided with (e.g.) --keyblob_dir "
425 "/data/local/tmp/keymint-blobs";
426 }
427
428 for (std::string name : keyblob_names(SecLevel())) {
429 for (bool with_hidden : {false, true}) {
430 auto builder = AuthorizationSetBuilder();
431 if (with_hidden) {
432 // Build a variant keyblob that requires app_id/app_data
433 builder.Authorization(TAG_APPLICATION_ID, "appid")
434 .Authorization(TAG_APPLICATION_DATA, "appdata");
435 name += "-hidden";
436 }
437 SCOPED_TRACE(testing::Message() << name);
438 std::vector<uint8_t> keyblob = load_keyblob(subdir, name);
439 if (keyblob.empty()) {
440 if (requires_rr(name)) {
441 std::cerr << "Skipping missing keyblob file '" << name
442 << "', assuming rollback resistance unavailable\n";
443 } else {
444 FAIL() << "Missing keyblob file '" << name << "'";
445 }
446 continue;
447 }
448
449 std::vector<uint8_t> cert;
450 if (is_asymmetric(name)) {
451 cert = load_cert(subdir, name);
452 }
453
454 // Perform an algorithm-specific operation with the keyblob.
455 string message = "Hello World!";
456 AuthorizationSet out_params;
457 if (name.find("aes-key") != std::string::npos) {
458 builder.BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
459 string ciphertext = EncryptMessage(keyblob, message, builder, &out_params);
460 string plaintext = DecryptMessage(keyblob, ciphertext, builder);
461 EXPECT_EQ(message, plaintext);
462 } else if (name.find("des-key") != std::string::npos) {
463 builder.BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
464 string ciphertext = EncryptMessage(keyblob, message, builder, &out_params);
465 string plaintext = DecryptMessage(keyblob, ciphertext, builder);
466 EXPECT_EQ(message, plaintext);
467 } else if (name.find("hmac-key") != std::string::npos) {
subrahmanyamana7a6f702023-01-18 18:13:27 +0000468 builder.Digest(Digest::SHA_2_256);
David Drysdale9f5c0c52022-11-03 15:10:16 +0000469 auto sign_builder = builder;
470 sign_builder.Authorization(TAG_MAC_LENGTH, 128);
471 string tag = SignMessage(keyblob, message, sign_builder);
472 VerifyMessage(keyblob, message, tag, builder);
473 } else if (name.find("rsa-key") != std::string::npos) {
474 builder.Digest(Digest::NONE).Padding(PaddingMode::NONE);
475 string signature = SignMessage(keyblob, message, builder);
476 LocalVerifyMessage(cert, message, signature, builder);
477 } else if (name.find("p256-key") != std::string::npos) {
subrahmanyamana7a6f702023-01-18 18:13:27 +0000478 builder.Digest(Digest::SHA_2_256);
David Drysdale9f5c0c52022-11-03 15:10:16 +0000479 string signature = SignMessage(keyblob, message, builder);
480 LocalVerifyMessage(cert, message, signature, builder);
481 } else if (name.find("ed25519-key") != std::string::npos) {
482 builder.Digest(Digest::NONE);
483 string signature = SignMessage(keyblob, message, builder);
484 LocalVerifyMessage(cert, message, signature, builder);
485 } else if (name.find("x25519-key") != std::string::npos) {
486 // Generate EC key on same curve locally (with access to private key material).
487 uint8_t localPrivKeyData[32];
488 uint8_t localPubKeyData[32];
489 X25519_keypair(localPubKeyData, localPrivKeyData);
490 EVP_PKEY_Ptr localPrivKey(EVP_PKEY_new_raw_private_key(
491 EVP_PKEY_X25519, nullptr, localPrivKeyData, sizeof(localPrivKeyData)));
492 // Get encoded form of the public part of the locally generated key.
493 unsigned char* p = nullptr;
494 int localPublicKeySize = i2d_PUBKEY(localPrivKey.get(), &p);
495 ASSERT_GT(localPublicKeySize, 0);
496 vector<uint8_t> localPublicKey(
497 reinterpret_cast<const uint8_t*>(p),
498 reinterpret_cast<const uint8_t*>(p + localPublicKeySize));
499 OPENSSL_free(p);
500
501 // Agree on a key between local and KeyMint.
502 string data;
503 ASSERT_EQ(ErrorCode::OK,
504 Begin(KeyPurpose::AGREE_KEY, keyblob, builder, &out_params));
505 ASSERT_EQ(ErrorCode::OK,
506 Finish(string(localPublicKey.begin(), localPublicKey.end()), &data));
507 vector<uint8_t> keymint_data(data.begin(), data.end());
508
509 // Extract the public key for the KeyMint key from the cert.
510 X509_Ptr kmKeyCert(parse_cert_blob(cert));
511 ASSERT_NE(kmKeyCert, nullptr);
512 EVP_PKEY_Ptr kmPubKey = EVP_PKEY_Ptr(X509_get_pubkey(kmKeyCert.get()));
513 ASSERT_NE(kmPubKey.get(), nullptr);
514
515 size_t kmPubKeySize = 32;
516 uint8_t kmPubKeyData[32];
517 ASSERT_EQ(1,
518 EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
519 ASSERT_EQ(kmPubKeySize, 32);
520
521 // Agree on a key between KeyMint and local.
522 uint8_t sharedKey[32];
523 ASSERT_EQ(1, X25519(sharedKey, localPrivKeyData, kmPubKeyData));
524 vector<uint8_t> local_data(sharedKey, sharedKey + 32);
525
526 // Both ways round should agree.
527 EXPECT_EQ(keymint_data, local_data);
528 } else if (name.find("-attest-key") != std::string::npos) {
529 // Covers rsa-attest-key, p256-attest-key, ed25519-attest-key.
530
531 // Use attestation key to sign RSA signing key
532 AttestationKey attest_key;
533 attest_key.keyBlob = keyblob;
534 attest_key.attestKeyParams = builder.vector_data();
535 attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
536 vector<uint8_t> attested_key_blob;
537 vector<KeyCharacteristics> attested_key_characteristics;
538 vector<Certificate> attested_key_cert_chain;
539 EXPECT_EQ(ErrorCode::OK,
540 GenerateKey(AuthorizationSetBuilder()
541 .RsaSigningKey(2048, 65537)
542 .Authorization(TAG_NO_AUTH_REQUIRED)
543 .AttestationChallenge("challenge")
544 .AttestationApplicationId("app-id")
545 .SetDefaultValidity(),
546 attest_key, &attested_key_blob, &attested_key_characteristics,
547 &attested_key_cert_chain));
548 CheckedDeleteKey(&attested_key_blob);
549 } else {
550 FAIL() << "Unexpected name: " << name;
551 }
552 }
553 }
554}
555
556// This test target deletes any keys from the keyblob subdirectory that have rollback resistance
557// enabled.
558TEST_P(KeyBlobUpgradeTest, DeleteRRKeyBlobsAfter) {
559 std::string subdir = keyblob_subdir(keyblob_dir, GetParam(), /* create? */ false);
560 if (subdir.empty()) {
561 GTEST_SKIP() << "No keyblob directory provided with (e.g.) --keyblob_dir "
562 "/data/local/tmp/keymint-blobs";
563 }
564
565 for (std::string name : keyblob_names(SecLevel())) {
566 for (bool with_hidden : {false, true}) {
567 auto builder = AuthorizationSetBuilder();
568 if (with_hidden) {
569 // Build a variant keyblob that requires app_id/app_data
570 builder.Authorization(TAG_APPLICATION_ID, "appid")
571 .Authorization(TAG_APPLICATION_DATA, "appdata");
572 name += "-hidden";
573 }
574 if (!requires_rr(name)) {
575 std::cerr << "Skipping keyblob file '" << name
576 << "' which does not use rollback resistance\n";
577 continue;
578 }
579 SCOPED_TRACE(testing::Message() << name);
580 std::vector<uint8_t> keyblob = load_keyblob(subdir, name);
581 if (keyblob.empty()) {
582 std::cerr << "Skipping missing keyblob file '" << name
583 << "', assuming rollback resistance unavailable\n";
584 continue;
585 }
586
587 // Delete the key
588 ASSERT_EQ(ErrorCode::OK, DeleteKey(&keyblob));
589
590 // Remove all files relating to the deleted key.
591 std::cerr << "Deleting files for deleted key '" << name << ";";
592 delete_keyblob(subdir, name);
593
594 // Attempting to use the keyblob after deletion should fail.
595 AuthorizationSet out_params;
596 if (name.find("aes-key") != std::string::npos) {
597 builder.BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
598 EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
599 Begin(KeyPurpose::ENCRYPT, keyblob, builder, &out_params));
600 } else {
601 FAIL() << "Unexpected name: " << name;
602 }
603 }
604 }
605}
606
607INSTANTIATE_KEYMINT_AIDL_TEST(KeyBlobUpgradeTest);
608
609} // namespace aidl::android::hardware::security::keymint::test