Merge "Add more vts tests related to limited use key. 1. Fix test case for usage count limit tag = 1 case, when hardware cannot enforce it, the tag should by enforced by keystore. 2. Add test case for usage count limit tag > 1. 3. Add test case to verify the usage count limit tag appears correctly in the attestation certificate for asymmetic key."
This commit is contained in:
commit
49ad4f04d8
5 changed files with 220 additions and 56 deletions
|
@ -27,7 +27,7 @@ import android.hardware.security.keymint.TagType;
|
|||
* data are stored in KeyParameter.
|
||||
*/
|
||||
@VintfStability
|
||||
@Backing(type = "int")
|
||||
@Backing(type="int")
|
||||
enum Tag {
|
||||
/**
|
||||
* Tag::INVALID should never be set. It means you hit an error.
|
||||
|
@ -82,7 +82,6 @@ enum Tag {
|
|||
*/
|
||||
BLOCK_MODE = (2 << 28) /* TagType:ENUM_REP */ | 4,
|
||||
|
||||
|
||||
/**
|
||||
* Tag::DIGEST specifies the digest algorithms that may be used with the key to perform signing
|
||||
* and verification operations. This tag is relevant to RSA, ECDSA and HMAC keys. Possible
|
||||
|
@ -187,21 +186,21 @@ enum Tag {
|
|||
*/
|
||||
INCLUDE_UNIQUE_ID = (7 << 28) /* TagType:BOOL */ | 202,
|
||||
|
||||
/**
|
||||
* Tag::RSA_OAEP_MGF_DIGEST specifies the MGF1 digest algorithms that may be used with
|
||||
* RSA encryption/decryption with OAEP padding. If the key characteristics supports OAEP
|
||||
* and this tag is absent then SHA1 digest is selected by default for MGF1.
|
||||
*
|
||||
* This tag is repeatable for key generation/import. If this tag is present in the key
|
||||
* characteristics with one or more values from @4.0::Digest, then for RSA cipher
|
||||
* operations with OAEP Padding, the caller must specify a digest in the additionalParams
|
||||
* argument of begin operation. If this tag is missing or the specified digest is not in
|
||||
* the digests associated with the key then begin operation must fail with
|
||||
* ErrorCode::INCOMPATIBLE_MGF_DIGEST.
|
||||
*
|
||||
* Must be hardware-enforced.
|
||||
*/
|
||||
RSA_OAEP_MGF_DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 203,
|
||||
/**
|
||||
* Tag::RSA_OAEP_MGF_DIGEST specifies the MGF1 digest algorithms that may be used with
|
||||
* RSA encryption/decryption with OAEP padding. If the key characteristics supports OAEP
|
||||
* and this tag is absent then SHA1 digest is selected by default for MGF1.
|
||||
*
|
||||
* This tag is repeatable for key generation/import. If this tag is present in the key
|
||||
* characteristics with one or more values from @4.0::Digest, then for RSA cipher
|
||||
* operations with OAEP Padding, the caller must specify a digest in the additionalParams
|
||||
* argument of begin operation. If this tag is missing or the specified digest is not in
|
||||
* the digests associated with the key then begin operation must fail with
|
||||
* ErrorCode::INCOMPATIBLE_MGF_DIGEST.
|
||||
*
|
||||
* Must be hardware-enforced.
|
||||
*/
|
||||
RSA_OAEP_MGF_DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 203,
|
||||
|
||||
/**
|
||||
* TODO(seleneh) this tag needs to be deleted from all codes.
|
||||
|
@ -346,14 +345,14 @@ enum Tag {
|
|||
* 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.
|
||||
* characteristics with SecurityLevel::KEYSTORE 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.
|
||||
* characteristics with the SecurityLevel::KEYSTORE.
|
||||
*
|
||||
* 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
|
||||
|
@ -497,7 +496,8 @@ enum Tag {
|
|||
*/
|
||||
TRUSTED_USER_PRESENCE_REQUIRED = (7 << 28) /* TagType:BOOL */ | 507,
|
||||
|
||||
/** Tag::TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and
|
||||
/**
|
||||
* Tag::TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and
|
||||
* specifies that this key must not be usable unless the user provides confirmation of the data
|
||||
* to be signed. Confirmation is proven to keyMint via an approval token. See
|
||||
* CONFIRMATION_TOKEN, as well as the ConfirmatinUI HAL.
|
||||
|
|
|
@ -55,6 +55,9 @@ bool KeyCharacteristicsBasicallyValid(SecurityLevel secLevel,
|
|||
for (auto& entry : key_characteristics) {
|
||||
if (entry.authorizations.empty()) return false;
|
||||
|
||||
// Just ignore the SecurityLevel::KEYSTORE as the KM won't do any enforcement on this.
|
||||
if (entry.securityLevel == SecurityLevel::KEYSTORE) continue;
|
||||
|
||||
if (levels_seen.find(entry.securityLevel) != levels_seen.end()) return false;
|
||||
levels_seen.insert(entry.securityLevel);
|
||||
|
||||
|
@ -824,22 +827,36 @@ const vector<KeyParameter>& KeyMintAidlTestBase::SecLevelAuthorizations(
|
|||
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;
|
||||
});
|
||||
const vector<KeyParameter>& KeyMintAidlTestBase::SecLevelAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics, SecurityLevel securityLevel) {
|
||||
auto found = std::find_if(
|
||||
key_characteristics.begin(), key_characteristics.end(),
|
||||
[securityLevel](auto& entry) { return entry.securityLevel == securityLevel; });
|
||||
return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
|
||||
}
|
||||
|
||||
const vector<KeyParameter>& KeyMintAidlTestBase::SwEnforcedAuthorizations(
|
||||
AuthorizationSet KeyMintAidlTestBase::HwEnforcedAuthorizations(
|
||||
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;
|
||||
AuthorizationSet authList;
|
||||
for (auto& entry : key_characteristics) {
|
||||
if (entry.securityLevel == SecurityLevel::STRONGBOX ||
|
||||
entry.securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT) {
|
||||
authList.push_back(AuthorizationSet(entry.authorizations));
|
||||
}
|
||||
}
|
||||
return authList;
|
||||
}
|
||||
|
||||
AuthorizationSet KeyMintAidlTestBase::SwEnforcedAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics) {
|
||||
AuthorizationSet authList;
|
||||
for (auto& entry : key_characteristics) {
|
||||
if (entry.securityLevel == SecurityLevel::SOFTWARE ||
|
||||
entry.securityLevel == SecurityLevel::KEYSTORE) {
|
||||
authList.push_back(AuthorizationSet(entry.authorizations));
|
||||
}
|
||||
}
|
||||
return authList;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
|
|
@ -175,9 +175,12 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
|
|||
inline const vector<KeyParameter>& SecLevelAuthorizations() {
|
||||
return SecLevelAuthorizations(key_characteristics_);
|
||||
}
|
||||
const vector<KeyParameter>& HwEnforcedAuthorizations(
|
||||
const vector<KeyParameter>& SecLevelAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics, SecurityLevel securityLevel);
|
||||
|
||||
AuthorizationSet HwEnforcedAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics);
|
||||
const vector<KeyParameter>& SwEnforcedAuthorizations(
|
||||
AuthorizationSet SwEnforcedAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics);
|
||||
|
||||
private:
|
||||
|
|
|
@ -645,6 +645,61 @@ TEST_P(NewKeyGenerationTest, LimitedUsageRsa) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NewKeyGenerationTest.LimitedUsageRsaWithAttestation
|
||||
*
|
||||
* Verifies that KeyMint can generate all required RSA key sizes with limited usage, and that the
|
||||
* resulting keys have correct characteristics and attestation.
|
||||
*/
|
||||
TEST_P(NewKeyGenerationTest, LimitedUsageRsaWithAttestation) {
|
||||
for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
|
||||
auto challenge = "hello";
|
||||
auto app_id = "foo";
|
||||
|
||||
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)
|
||||
.AttestationChallenge(challenge)
|
||||
.AttestationApplicationId(app_id)
|
||||
.Authorization(TAG_NO_AUTH_REQUIRED)
|
||||
.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";
|
||||
|
||||
// Check the usage count limit tag also appears in the attestation.
|
||||
EXPECT_TRUE(verify_chain(cert_chain_));
|
||||
ASSERT_GT(cert_chain_.size(), 0);
|
||||
|
||||
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
|
||||
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
|
||||
EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
|
||||
sw_enforced, hw_enforced, SecLevel(),
|
||||
cert_chain_[0].encodedCertificate));
|
||||
|
||||
CheckedDeleteKey(&key_blob);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NewKeyGenerationTest.NoInvalidRsaSizes
|
||||
*
|
||||
|
@ -4297,11 +4352,11 @@ INSTANTIATE_KEYMINT_AIDL_TEST(MaxOperationsTest);
|
|||
typedef KeyMintAidlTestBase UsageCountLimitTest;
|
||||
|
||||
/*
|
||||
* UsageCountLimitTest.TestLimitAes
|
||||
* UsageCountLimitTest.TestSingleUseAes
|
||||
*
|
||||
* Verifies that the usage count limit tag works correctly with AES keys.
|
||||
* Verifies that the usage count limit tag = 1 works correctly with AES keys.
|
||||
*/
|
||||
TEST_P(UsageCountLimitTest, TestLimitAes) {
|
||||
TEST_P(UsageCountLimitTest, TestSingleUseAes) {
|
||||
if (SecLevel() == SecurityLevel::STRONGBOX) return;
|
||||
|
||||
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
|
||||
|
@ -4322,31 +4377,75 @@ TEST_P(UsageCountLimitTest, TestLimitAes) {
|
|||
string message = "1234567890123456";
|
||||
auto params = AuthorizationSetBuilder().EcbMode().Padding(PaddingMode::NONE);
|
||||
|
||||
AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
|
||||
AuthorizationSet keystore_auths =
|
||||
SecLevelAuthorizations(key_characteristics_, SecurityLevel::KEYSTORE);
|
||||
|
||||
// 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.
|
||||
// Usage count limit tag is enforced by keystore, keymint does nothing.
|
||||
EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U));
|
||||
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* UsageCountLimitTest.TestLimitRsa
|
||||
* UsageCountLimitTest.TestLimitedUseAes
|
||||
*
|
||||
* Verifies that the usage count limit tag works correctly with RSA keys.
|
||||
* Verifies that the usage count limit tag > 1 works correctly with AES keys.
|
||||
*/
|
||||
TEST_P(UsageCountLimitTest, TestLimitRsa) {
|
||||
TEST_P(UsageCountLimitTest, TestLimitedUseAes) {
|
||||
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, 3)));
|
||||
|
||||
// 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, 3U))
|
||||
<< "key usage count limit " << 3U << " missing";
|
||||
|
||||
string message = "1234567890123456";
|
||||
auto params = AuthorizationSetBuilder().EcbMode().Padding(PaddingMode::NONE);
|
||||
|
||||
AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
|
||||
AuthorizationSet keystore_auths =
|
||||
SecLevelAuthorizations(key_characteristics_, SecurityLevel::KEYSTORE);
|
||||
|
||||
EncryptMessage(message, params);
|
||||
EncryptMessage(message, params);
|
||||
EncryptMessage(message, params);
|
||||
|
||||
if (hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U)) {
|
||||
// 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 keystore, keymint does nothing.
|
||||
EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U));
|
||||
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* UsageCountLimitTest.TestSingleUseRsa
|
||||
*
|
||||
* Verifies that the usage count limit tag = 1 works correctly with RSA keys.
|
||||
*/
|
||||
TEST_P(UsageCountLimitTest, TestSingleUseRsa) {
|
||||
if (SecLevel() == SecurityLevel::STRONGBOX) return;
|
||||
|
||||
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
|
||||
|
@ -4366,22 +4465,64 @@ TEST_P(UsageCountLimitTest, TestLimitRsa) {
|
|||
string message = "1234567890123456";
|
||||
auto params = AuthorizationSetBuilder().NoDigestOrPadding();
|
||||
|
||||
AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
|
||||
AuthorizationSet keystore_auths =
|
||||
SecLevelAuthorizations(key_characteristics_, SecurityLevel::KEYSTORE);
|
||||
|
||||
// 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.
|
||||
// Usage count limit tag is enforced by keystore, keymint does nothing.
|
||||
EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U));
|
||||
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* UsageCountLimitTest.TestLimitUseRsa
|
||||
*
|
||||
* Verifies that the usage count limit tag > 1 works correctly with RSA keys.
|
||||
*/
|
||||
TEST_P(UsageCountLimitTest, TestLimitUseRsa) {
|
||||
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, 3)));
|
||||
|
||||
// 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, 3U))
|
||||
<< "key usage count limit " << 3U << " missing";
|
||||
|
||||
string message = "1234567890123456";
|
||||
auto params = AuthorizationSetBuilder().NoDigestOrPadding();
|
||||
|
||||
AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
|
||||
AuthorizationSet keystore_auths =
|
||||
SecLevelAuthorizations(key_characteristics_, SecurityLevel::KEYSTORE);
|
||||
|
||||
SignMessage(message, params);
|
||||
SignMessage(message, params);
|
||||
SignMessage(message, params);
|
||||
|
||||
if (hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U)) {
|
||||
// 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 keystore, keymint does nothing.
|
||||
EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U));
|
||||
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ typedef struct km_auth_list {
|
|||
ASN1_NULL* device_unique_attestation;
|
||||
ASN1_NULL* storage_key;
|
||||
ASN1_NULL* identity_credential;
|
||||
ASN1_INTEGER* usage_count_limit;
|
||||
} KM_AUTH_LIST;
|
||||
|
||||
ASN1_SEQUENCE(KM_AUTH_LIST) = {
|
||||
|
@ -143,7 +144,8 @@ ASN1_SEQUENCE(KM_AUTH_LIST) = {
|
|||
ASN1_EXP_OPT(KM_AUTH_LIST, storage_key, ASN1_NULL, TAG_STORAGE_KEY.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential, ASN1_NULL,
|
||||
TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
|
||||
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, usage_count_limit, ASN1_INTEGER,
|
||||
TAG_USAGE_COUNT_LIMIT.maskedTag()),
|
||||
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
|
||||
|
||||
|
@ -285,6 +287,7 @@ static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet*
|
|||
copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
|
||||
copyAuthTag(record->storage_key, TAG_STORAGE_KEY, auth_list);
|
||||
copyAuthTag(record->identity_credential, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
|
||||
copyAuthTag(record->usage_count_limit, TAG_USAGE_COUNT_LIMIT, auth_list);
|
||||
|
||||
return ErrorCode::OK;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue