Merge "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)."

This commit is contained in:
Treehugger Robot 2021-01-26 23:05:51 +00:00 committed by Gerrit Code Review
commit 0d59cbdb1d
4 changed files with 250 additions and 11 deletions

View file

@ -42,6 +42,7 @@ enum Tag {
USAGE_EXPIRE_DATETIME = 1610613138,
MIN_SECONDS_BETWEEN_OPS = 805306771,
MAX_USES_PER_BOOT = 805306772,
USAGE_COUNT_LIMIT = 805306773,
USER_ID = 805306869,
USER_SECURE_ID = -1610612234,
NO_AUTH_REQUIRED = 1879048695,

View file

@ -332,6 +332,35 @@ enum Tag {
*/
MAX_USES_PER_BOOT = (3 << 28) /* TagType:UINT */ | 404,
/**
* Tag::USAGE_COUNT_LIMIT specifies the number of times that a key may be used. This can be
* used to limit the use of a key.
*
* The value is a 32-bit integer representing the current number of attempts left.
*
* When initializing a limited use key, the value of this tag represents the maximum usage
* limit for that key. After the key usage is exhausted, the key blob should be invalidated by
* finish() call. Any subsequent attempts to use the key must result in a failure with
* ErrorCode::INVALID_KEY_BLOB returned by IKeyMintDevice.
*
* At this point, if the caller specifies count > 1, it is not expected that any TEE will be
* able to enforce this feature in the hardware due to limited resources of secure
* storage. In this case, the tag with the value of maximum usage must be added to the key
* characteristics with SecurityLevel::SOFTWARE by the IKeyMintDevice.
*
* On the other hand, if the caller specifies count = 1, some TEEs may have the ability
* to enforce this feature in the hardware with its secure storage. If the IKeyMintDevice
* implementation can enforce this feature, the tag with value = 1 must be added to the key
* characteristics with the SecurityLevel of the IKeyMintDevice. If the IKeyMintDevice can't
* enforce this feature even when the count = 1, the tag must be added to the key
* characteristics with the SecurityLevel::SOFTWARE.
*
* When the key is attested, this tag with the same value must also be added to the attestation
* record. This tag must have the same SecurityLevel as the tag that is added to the key
* characteristics.
*/
USAGE_COUNT_LIMIT = (3 << 28) | 405, /* TagType:UINT */
/**
* Tag::USER_ID specifies the ID of the Android user that is permitted to use the key.
*

View file

@ -562,7 +562,7 @@ TEST_P(NewKeyGenerationTest, Rsa) {
}
/*
* NewKeyGenerationTest.Rsa
* NewKeyGenerationTest.RsaWithAttestation
*
* Verifies that keymint can generate all required RSA key sizes, and that the resulting keys
* have correct characteristics.
@ -606,6 +606,45 @@ TEST_P(NewKeyGenerationTest, RsaWithAttestation) {
}
}
/*
* 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
*
@ -665,6 +704,43 @@ TEST_P(NewKeyGenerationTest, Ecdsa) {
}
}
/*
* 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
*
@ -779,6 +855,44 @@ TEST_P(NewKeyGenerationTest, Hmac) {
}
}
/*
* 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
*
@ -4153,7 +4267,7 @@ TEST_P(MaxOperationsTest, TestLimitAes) {
}
/*
* MaxOperationsTest.TestLimitAes
* MaxOperationsTest.TestLimitRsa
*
* Verifies that the max uses per boot tag works correctly with RSA keys.
*/
@ -4180,6 +4294,100 @@ TEST_P(MaxOperationsTest, TestLimitRsa) {
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;
/*

View file

@ -119,6 +119,7 @@ DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED);
DECLARE_TYPED_TAG(TRUSTED_USER_PRESENCE_REQUIRED);
DECLARE_TYPED_TAG(UNIQUE_ID);
DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED);
DECLARE_TYPED_TAG(USAGE_COUNT_LIMIT);
DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
DECLARE_TYPED_TAG(USER_AUTH_TYPE);
DECLARE_TYPED_TAG(USER_ID);
@ -135,15 +136,15 @@ using all_tags_t = MetaList<
TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t, TAG_USER_SECURE_ID_t,
TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t,
TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_HARDWARE_TYPE_t,
TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t,
TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t, TAG_ATTESTATION_ID_DEVICE_t,
TAG_ATTESTATION_ID_PRODUCT_t, TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
TAG_ATTESTATION_ID_SERIAL_t, TAG_ATTESTATION_ID_IMEI_t, TAG_ATTESTATION_ID_MEID_t,
TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USAGE_COUNT_LIMIT_t,
TAG_USER_ID_t, TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t,
TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t,
TAG_HARDWARE_TYPE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t,
TAG_ATTESTATION_ID_DEVICE_t, TAG_ATTESTATION_ID_PRODUCT_t,
TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
TAG_DIGEST_t, TAG_PADDING_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t,
TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_CONFIRMATION_REQUIRED_t,