summaryrefslogtreecommitdiff
path: root/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp')
-rw-r--r--security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp176
1 files changed, 132 insertions, 44 deletions
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 94bc199ca7..766c02dea9 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>
@@ -36,13 +37,41 @@ using std::optional;
os << "(Empty)" << ::std::endl;
else {
os << "\n";
- for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
+ for (auto& entry : set) os << entry << ::std::endl;
}
return os;
}
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,41 @@ void KeyMintAidlTestBase::SetUp() {
}
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();
-
- Status result;
- ByteArray blob;
+ key_blob->clear();
+ key_characteristics->clear();
+ cert_chain_.clear();
- result = keymint_->generateKey(key_desc.vector_data(), &blob, keyChar, &certChain_);
+ KeyCreationResult creationResult;
+ Status result = keymint_->generateKey(key_desc.vector_data(), &creationResult);
- // On result, blob & characteristics should be empty.
if (result.isOk()) {
- if (SecLevel() != SecurityLevel::SOFTWARE) {
- EXPECT_GT(keyChar->hardwareEnforced.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);
+
+ auto algorithm = key_desc.GetTagValue(TAG_ALGORITHM);
+ EXPECT_TRUE(algorithm);
+ if (algorithm &&
+ (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
+ EXPECT_GE(cert_chain_.size(), 1);
+ if (key_desc.Contains(TAG_ATTESTATION_CHALLENGE)) EXPECT_GT(cert_chain_.size(), 1);
+ } else {
+ // For symmetric keys there should be no certificates.
+ EXPECT_EQ(cert_chain_.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;
}
return GetReturnErrorCode(result);
@@ -118,25 +153,37 @@ ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc) {
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_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);
+
+ auto algorithm = key_desc.GetTagValue(TAG_ALGORITHM);
+ EXPECT_TRUE(algorithm);
+ if (algorithm &&
+ (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
+ EXPECT_GE(cert_chain_.size(), 1);
+ if (key_desc.Contains(TAG_ATTESTATION_CHALLENGE)) EXPECT_GT(cert_chain_.size(), 1);
+ } else {
+ // For symmetric keys there should be no certificates.
+ EXPECT_EQ(cert_chain_.size(), 0);
}
- EXPECT_GT(key_characteristics->softwareEnforced.size(), 0);
- *key_blob = blob.data;
}
return GetReturnErrorCode(result);
@@ -151,25 +198,39 @@ ErrorCode KeyMintAidlTestBase::ImportWrappedKey(string wrapped_key, string wrapp
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_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);
+
+ AuthorizationSet allAuths;
+ for (auto& entry : key_characteristics_) {
+ allAuths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ auto algorithm = allAuths.GetTagValue(TAG_ALGORITHM);
+ EXPECT_TRUE(algorithm);
+ if (algorithm &&
+ (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
+ EXPECT_GE(cert_chain_.size(), 1);
+ } else {
+ // For symmetric keys there should be no certificates.
+ EXPECT_EQ(cert_chain_.size(), 0);
}
- EXPECT_GT(key_characteristics_.softwareEnforced.size(), 0);
}
return GetReturnErrorCode(result);
@@ -754,6 +815,33 @@ vector<Digest> KeyMintAidlTestBase::ValidDigests(bool withNone, bool withMD5) {
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;
+}
+
+const vector<KeyParameter>& KeyMintAidlTestBase::HwEnforcedAuthorizations(
+ const vector<KeyCharacteristics>& key_characteristics) {
+ auto found =
+ std::find_if(key_characteristics.begin(), key_characteristics.end(), [](auto& entry) {
+ return entry.securityLevel == SecurityLevel::STRONGBOX ||
+ entry.securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
+ });
+ return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
+}
+
+const vector<KeyParameter>& KeyMintAidlTestBase::SwEnforcedAuthorizations(
+ const vector<KeyCharacteristics>& key_characteristics) {
+ auto found = std::find_if(
+ key_characteristics.begin(), key_characteristics.end(),
+ [](auto& entry) { return entry.securityLevel == SecurityLevel::SOFTWARE; });
+ return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
+}
+
} // namespace test
} // namespace aidl::android::hardware::security::keymint