Change KeyCharacteristics

Support key characteristics with three security levels, do not store
unenforced authorizations with keys or bind them to keys.

Bug: 163606833
Test: atest VtsAidlKeyMintTargetTest
Change-Id: Idbc523f16d8ef66ec38e0d503ad579a93c49e7b4
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 94bc199..93a216f 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -17,6 +17,7 @@
 #include "KeyMintAidlTestBase.h"
 
 #include <chrono>
+#include <unordered_set>
 #include <vector>
 
 #include <android-base/logging.h>
@@ -43,6 +44,34 @@
 
 namespace test {
 
+namespace {
+
+// Predicate for testing basic characteristics validity in generation or import.
+bool KeyCharacteristicsBasicallyValid(SecurityLevel secLevel,
+                                      const vector<KeyCharacteristics>& key_characteristics) {
+    if (key_characteristics.empty()) return false;
+
+    std::unordered_set<SecurityLevel> levels_seen;
+    for (auto& entry : key_characteristics) {
+        if (entry.authorizations.empty()) return false;
+
+        if (levels_seen.find(entry.securityLevel) != levels_seen.end()) return false;
+        levels_seen.insert(entry.securityLevel);
+
+        // Generally, we should only have one entry, at the same security level as the KM
+        // instance.  There is an exception: StrongBox KM can have some authorizations that are
+        // enforced by the TEE.
+        bool isExpectedSecurityLevel = secLevel == entry.securityLevel ||
+                                       (secLevel == SecurityLevel::STRONGBOX &&
+                                        entry.securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT);
+
+        if (!isExpectedSecurityLevel) return false;
+    }
+    return true;
+}
+
+}  // namespace
+
 ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(const Status& result) {
     if (result.isOk()) return ErrorCode::OK;
 
@@ -78,35 +107,30 @@
 }
 
 ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc,
-                                           vector<uint8_t>* keyBlob, KeyCharacteristics* keyChar) {
-    EXPECT_NE(keyBlob, nullptr) << "Key blob pointer must not be null.  Test bug";
-    EXPECT_NE(keyChar, nullptr)
+                                           vector<uint8_t>* key_blob,
+                                           vector<KeyCharacteristics>* key_characteristics) {
+    EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null.  Test bug";
+    EXPECT_NE(key_characteristics, nullptr)
             << "Previous characteristics not deleted before generating key.  Test bug.";
 
     // Aidl does not clear these output parameters if the function returns
     // error.  This is different from hal where output parameter is always
     // cleared due to hal returning void.  So now we need to do our own clearing
     // of the output variables prior to calling keyMint aidl libraries.
-    keyBlob->clear();
-    keyChar->softwareEnforced.clear();
-    keyChar->hardwareEnforced.clear();
-    certChain_.clear();
+    key_blob->clear();
+    key_characteristics->clear();
+    cert_chain_.clear();
 
-    Status result;
-    ByteArray blob;
+    KeyCreationResult creationResult;
+    Status result = keymint_->generateKey(key_desc.vector_data(), &creationResult);
 
-    result = keymint_->generateKey(key_desc.vector_data(), &blob, keyChar, &certChain_);
-
-    // On result, blob & characteristics should be empty.
     if (result.isOk()) {
-        if (SecLevel() != SecurityLevel::SOFTWARE) {
-            EXPECT_GT(keyChar->hardwareEnforced.size(), 0);
-        }
-        EXPECT_GT(keyChar->softwareEnforced.size(), 0);
-        // TODO(seleneh) in a later version where we return @nullable
-        // single Certificate, check non-null single certificate is always
-        // non-empty.
-        *keyBlob = blob.data;
+        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics);
+        EXPECT_GT(creationResult.keyBlob.size(), 0);
+        *key_blob = std::move(creationResult.keyBlob);
+        *key_characteristics = std::move(creationResult.keyCharacteristics);
+        cert_chain_ = std::move(creationResult.certificateChain);
     }
 
     return GetReturnErrorCode(result);
@@ -118,25 +142,26 @@
 
 ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
                                          const string& key_material, vector<uint8_t>* key_blob,
-                                         KeyCharacteristics* key_characteristics) {
+                                         vector<KeyCharacteristics>* key_characteristics) {
     Status result;
 
-    certChain_.clear();
-    key_characteristics->softwareEnforced.clear();
-    key_characteristics->hardwareEnforced.clear();
+    cert_chain_.clear();
+    key_characteristics->clear();
     key_blob->clear();
 
-    ByteArray blob;
+    KeyCreationResult creationResult;
     result = keymint_->importKey(key_desc.vector_data(), format,
-                                 vector<uint8_t>(key_material.begin(), key_material.end()), &blob,
-                                 key_characteristics, &certChain_);
+                                 vector<uint8_t>(key_material.begin(), key_material.end()),
+                                 &creationResult);
 
     if (result.isOk()) {
-        if (SecLevel() != SecurityLevel::SOFTWARE) {
-            EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
-        }
-        EXPECT_GT(key_characteristics->softwareEnforced.size(), 0);
-        *key_blob = blob.data;
+        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics);
+        EXPECT_GT(creationResult.keyBlob.size(), 0);
+
+        *key_blob = std::move(creationResult.keyBlob);
+        *key_characteristics = std::move(creationResult.keyCharacteristics);
+        cert_chain_ = std::move(creationResult.certificateChain);
     }
 
     return GetReturnErrorCode(result);
@@ -151,25 +176,25 @@
                                                 const AuthorizationSet& wrapping_key_desc,
                                                 string masking_key,
                                                 const AuthorizationSet& unwrapping_params) {
-    Status result;
     EXPECT_EQ(ErrorCode::OK, ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key));
 
-    ByteArray outBlob;
-    key_characteristics_.softwareEnforced.clear();
-    key_characteristics_.hardwareEnforced.clear();
+    key_characteristics_.clear();
 
-    result = keymint_->importWrappedKey(vector<uint8_t>(wrapped_key.begin(), wrapped_key.end()),
-                                        key_blob_,
-                                        vector<uint8_t>(masking_key.begin(), masking_key.end()),
-                                        unwrapping_params.vector_data(), 0 /* passwordSid */,
-                                        0 /* biometricSid */, &outBlob, &key_characteristics_);
+    KeyCreationResult creationResult;
+    Status result = keymint_->importWrappedKey(
+            vector<uint8_t>(wrapped_key.begin(), wrapped_key.end()), key_blob_,
+            vector<uint8_t>(masking_key.begin(), masking_key.end()),
+            unwrapping_params.vector_data(), 0 /* passwordSid */, 0 /* biometricSid */,
+            &creationResult);
 
     if (result.isOk()) {
-        key_blob_ = outBlob.data;
-        if (SecLevel() != SecurityLevel::SOFTWARE) {
-            EXPECT_GT(key_characteristics_.hardwareEnforced.size(), 0);
-        }
-        EXPECT_GT(key_characteristics_.softwareEnforced.size(), 0);
+        EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
+                     creationResult.keyCharacteristics);
+        EXPECT_GT(creationResult.keyBlob.size(), 0);
+
+        key_blob_ = std::move(creationResult.keyBlob);
+        key_characteristics_ = std::move(creationResult.keyCharacteristics);
+        cert_chain_ = std::move(creationResult.certificateChain);
     }
 
     return GetReturnErrorCode(result);
@@ -754,6 +779,15 @@
     return {};
 }
 
+static const vector<KeyParameter> kEmptyAuthList{};
+
+const vector<KeyParameter>& KeyMintAidlTestBase::SecLevelAuthorizations(
+        const vector<KeyCharacteristics>& key_characteristics) {
+    auto found = std::find_if(key_characteristics.begin(), key_characteristics.end(),
+                              [this](auto& entry) { return entry.securityLevel == SecLevel(); });
+    return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
+}
+
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint