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