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