Add limited use keys related tag into KeyMint aidl.
And add vts test to verify the tag appears in the key characteristics.
also if the tag is enforced in the hardware, afer the usage of the key
is exhausted, the key blob should be invalidated from the secure storage
(such as RPMB partition).
Bug: b/174140443
Test: atest VtsHalKeyMintV1_0TargetTest
Change-Id: Ic65b855c5a8692ab8d1281dd46562ad0844ab1b0
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index e7c94f3..8d1da81 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -560,7 +560,7 @@
}
/*
- * NewKeyGenerationTest.Rsa
+ * NewKeyGenerationTest.RsaWithAttestation
*
* Verifies that keymint can generate all required RSA key sizes, and that the resulting keys
* have correct characteristics.
@@ -605,6 +605,45 @@
}
/*
+ * NewKeyGenerationTest.LimitedUsageRsa
+ *
+ * Verifies that KeyMint can generate all required RSA key sizes with limited usage, and that the
+ * resulting keys have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, LimitedUsageRsa) {
+ for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.NoInvalidRsaSizes
*
* Verifies that keymint cannot generate any RSA key sizes that are designated as invalid.
@@ -664,6 +703,43 @@
}
/*
+ * NewKeyGenerationTest.LimitedUsageEcdsa
+ *
+ * Verifies that KeyMint can generate all required EC key sizes with limited usage, and that the
+ * resulting keys have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, LimitedUsageEcdsa) {
+ for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(key_size)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.EcdsaDefaultSize
*
* Verifies that failing to specify a key size for EC key generation returns
@@ -778,6 +854,44 @@
}
/*
+ * NewKeyGenerationTest.LimitedUsageHmac
+ *
+ * Verifies that KeyMint supports all required digests with limited usage Hmac, and that the
+ * resulting keys have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, LimitedUsageHmac) {
+ for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ constexpr size_t key_size = 128;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(key_size)
+ .Digest(digest)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.HmacCheckKeySizes
*
* Verifies that keymint supports all key sizes, and rejects all invalid key sizes.
@@ -4151,7 +4265,7 @@
}
/*
- * MaxOperationsTest.TestLimitAes
+ * MaxOperationsTest.TestLimitRsa
*
* Verifies that the max uses per boot tag works correctly with RSA keys.
*/
@@ -4178,6 +4292,100 @@
INSTANTIATE_KEYMINT_AIDL_TEST(MaxOperationsTest);
+typedef KeyMintAidlTestBase UsageCountLimitTest;
+
+/*
+ * UsageCountLimitTest.TestLimitAes
+ *
+ * Verifies that the usage count limit tag works correctly with AES keys.
+ */
+TEST_P(UsageCountLimitTest, TestLimitAes) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .EcbMode()
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1)));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics_) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ string message = "1234567890123456";
+ auto params = AuthorizationSetBuilder().EcbMode().Padding(PaddingMode::NONE);
+
+ // First usage of AES key should work.
+ EncryptMessage(message, params);
+
+ AuthorizationSet hardware_auths;
+ for (auto& entry : key_characteristics_) {
+ if (entry.securityLevel != SecurityLevel::SOFTWARE) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ }
+ if (hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U)) {
+ // Usage count limit tag is enforced by hardware. After using the key, the key blob
+ // must be invalidated from secure storage (such as RPMB partition).
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::ENCRYPT, params));
+ } else {
+ // Usage count limit tag is enforced by software, keymint does nothing.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+ }
+}
+
+/*
+ * UsageCountLimitTest.TestLimitRsa
+ *
+ * Verifies that the usage count limit tag works correctly with RSA keys.
+ */
+TEST_P(UsageCountLimitTest, TestLimitRsa) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(1024, 65537)
+ .NoDigestOrPadding()
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1)));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics_) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ string message = "1234567890123456";
+ auto params = AuthorizationSetBuilder().NoDigestOrPadding();
+
+ // First usage of RSA key should work.
+ SignMessage(message, params);
+
+ AuthorizationSet hardware_auths;
+ for (auto& entry : key_characteristics_) {
+ if (entry.securityLevel != SecurityLevel::SOFTWARE) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ }
+
+ if (hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U)) {
+ // Usage count limit tag is enforced by hardware. After using the key, the key blob
+ // must be invalidated from secure storage (such as RPMB partition).
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::SIGN, params));
+ } else {
+ // Usage count limit tag is enforced by software, keymint does nothing.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
+ }
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(UsageCountLimitTest);
+
typedef KeyMintAidlTestBase AddEntropyTest;
/*