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