Adding a test using second IMEI as attestation ids.
1. Using second IMEI as attestation id without using first IMEI. Test should generate a key using second IMEI as attestation id without using first IMEI as attestation id. Test should validate second IMEI in attesation record. 2. Using first IMEI as well as second IMEI as attestation ids. Test should generate a key using first IMEI and second IMEI as attestation ids. Test should validate first IMEI and second IMEI in attestation record. Test: atest -c VtsAidlKeyMintTargetTest Bug: 263197083, 264979486 Change-Id: I61c3f32e15a8d478a838d14e7db9917a33682267
This commit is contained in:
parent
72394c7c55
commit
5283f81f64
5 changed files with 194 additions and 0 deletions
|
@ -1014,6 +1014,14 @@ TEST_P(AttestKeyTest, EcdsaAttestationMismatchID) {
|
|||
.Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
|
||||
.Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
|
||||
.Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
|
||||
|
||||
// TODO(b/262255219): Remove this condition when StrongBox supports 2nd IMEI attestation.
|
||||
if (SecLevel() != SecurityLevel::STRONGBOX) {
|
||||
if (isSecondImeiIdAttestationRequired()) {
|
||||
attestation_id_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI,
|
||||
"invalid-second-imei");
|
||||
}
|
||||
}
|
||||
vector<uint8_t> key_blob;
|
||||
vector<KeyCharacteristics> key_characteristics;
|
||||
|
||||
|
@ -1042,6 +1050,178 @@ TEST_P(AttestKeyTest, EcdsaAttestationMismatchID) {
|
|||
CheckedDeleteKey(&attest_key.keyBlob);
|
||||
}
|
||||
|
||||
TEST_P(AttestKeyTest, SecondIMEIAttestationIDSuccess) {
|
||||
if (is_gsi_image()) {
|
||||
// GSI sets up a standard set of device identifiers that may not match
|
||||
// the device identifiers held by the device.
|
||||
GTEST_SKIP() << "Test not applicable under GSI";
|
||||
}
|
||||
|
||||
// TODO(b/262255219): Remove this condition when StrongBox supports 2nd IMEI attestation.
|
||||
if (SecLevel() == SecurityLevel::STRONGBOX) {
|
||||
GTEST_SKIP() << "Test not applicable for SecurityLevel::STRONGBOX";
|
||||
}
|
||||
|
||||
// Skip the test if there is no second IMEI exists.
|
||||
string second_imei = get_imei(1);
|
||||
if (second_imei.empty() || second_imei.compare("null") == 0) {
|
||||
GTEST_SKIP() << "Test not applicable as there is no second IMEI";
|
||||
}
|
||||
|
||||
if (!isSecondImeiIdAttestationRequired()) {
|
||||
GTEST_SKIP() << "Test not applicable for KeyMint-Version < 3 or first-api-level < 34";
|
||||
}
|
||||
|
||||
// Create attestation key.
|
||||
AttestationKey attest_key;
|
||||
vector<KeyCharacteristics> attest_key_characteristics;
|
||||
vector<Certificate> attest_key_cert_chain;
|
||||
ASSERT_EQ(ErrorCode::OK,
|
||||
GenerateAttestKey(AuthorizationSetBuilder()
|
||||
.EcdsaKey(EcCurve::P_256)
|
||||
.AttestKey()
|
||||
.SetDefaultValidity(),
|
||||
{} /* attestation signing key */, &attest_key.keyBlob,
|
||||
&attest_key_characteristics, &attest_key_cert_chain));
|
||||
attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
|
||||
EXPECT_EQ(attest_key_cert_chain.size(), 1);
|
||||
EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
|
||||
|
||||
// Use attestation key to sign an ECDSA key, but include an attestation ID field.
|
||||
AuthorizationSetBuilder builder = AuthorizationSetBuilder()
|
||||
.EcdsaSigningKey(EcCurve::P_256)
|
||||
.Authorization(TAG_NO_AUTH_REQUIRED)
|
||||
.AttestationChallenge("challenge")
|
||||
.AttestationApplicationId("foo")
|
||||
.SetDefaultValidity();
|
||||
// b/264979486 - second imei doesn't depend on first imei.
|
||||
// Add second IMEI as attestation id without adding first IMEI as
|
||||
// attestation id.
|
||||
builder.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, second_imei.data(), second_imei.size());
|
||||
|
||||
vector<uint8_t> attested_key_blob;
|
||||
vector<KeyCharacteristics> attested_key_characteristics;
|
||||
vector<Certificate> attested_key_cert_chain;
|
||||
auto result = GenerateKey(builder, attest_key, &attested_key_blob,
|
||||
&attested_key_characteristics, &attested_key_cert_chain);
|
||||
|
||||
if (result == ErrorCode::CANNOT_ATTEST_IDS && !isDeviceIdAttestationRequired()) {
|
||||
GTEST_SKIP()
|
||||
<< "Test not applicable as device does not support SECOND-IMEI ID attestation.";
|
||||
}
|
||||
|
||||
ASSERT_EQ(result, ErrorCode::OK);
|
||||
|
||||
device_id_attestation_vsr_check(result);
|
||||
|
||||
CheckedDeleteKey(&attested_key_blob);
|
||||
|
||||
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
|
||||
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
|
||||
|
||||
// The attested key characteristics will not contain APPLICATION_ID_* fields (their
|
||||
// spec definitions all have "Must never appear in KeyCharacteristics"), but the
|
||||
// attestation extension should contain them, so make sure the extra tag is added.
|
||||
vector<uint8_t> imei_blob(second_imei.data(), second_imei.data() + second_imei.size());
|
||||
KeyParameter imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, imei_blob);
|
||||
hw_enforced.push_back(imei_tag);
|
||||
|
||||
EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
|
||||
hw_enforced, SecLevel(),
|
||||
attested_key_cert_chain[0].encodedCertificate));
|
||||
|
||||
CheckedDeleteKey(&attest_key.keyBlob);
|
||||
}
|
||||
|
||||
TEST_P(AttestKeyTest, MultipleIMEIAttestationIDSuccess) {
|
||||
if (is_gsi_image()) {
|
||||
// GSI sets up a standard set of device identifiers that may not match
|
||||
// the device identifiers held by the device.
|
||||
GTEST_SKIP() << "Test not applicable under GSI";
|
||||
}
|
||||
|
||||
// TODO(b/262255219): Remove this condition when StrongBox supports 2nd IMEI attestation.
|
||||
if (SecLevel() == SecurityLevel::STRONGBOX) {
|
||||
GTEST_SKIP() << "Test not applicable for SecurityLevel::STRONGBOX";
|
||||
}
|
||||
|
||||
// Skip the test if there is no first IMEI exists.
|
||||
string imei = get_imei(0);
|
||||
if (imei.empty() || imei.compare("null") == 0) {
|
||||
GTEST_SKIP() << "Test not applicable as there is no first IMEI";
|
||||
}
|
||||
|
||||
// Skip the test if there is no second IMEI exists.
|
||||
string second_imei = get_imei(1);
|
||||
if (second_imei.empty() || second_imei.compare("null") == 0) {
|
||||
GTEST_SKIP() << "Test not applicable as there is no second IMEI";
|
||||
}
|
||||
|
||||
if (!isSecondImeiIdAttestationRequired()) {
|
||||
GTEST_SKIP() << "Test not applicable for KeyMint-Version < 3 or first-api-level < 34";
|
||||
}
|
||||
|
||||
// Create attestation key.
|
||||
AttestationKey attest_key;
|
||||
vector<KeyCharacteristics> attest_key_characteristics;
|
||||
vector<Certificate> attest_key_cert_chain;
|
||||
ASSERT_EQ(ErrorCode::OK,
|
||||
GenerateAttestKey(AuthorizationSetBuilder()
|
||||
.EcdsaKey(EcCurve::P_256)
|
||||
.AttestKey()
|
||||
.SetDefaultValidity(),
|
||||
{} /* attestation signing key */, &attest_key.keyBlob,
|
||||
&attest_key_characteristics, &attest_key_cert_chain));
|
||||
attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
|
||||
EXPECT_EQ(attest_key_cert_chain.size(), 1);
|
||||
EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
|
||||
|
||||
// Use attestation key to sign an ECDSA key, but include both IMEI attestation ID fields.
|
||||
AuthorizationSetBuilder builder = AuthorizationSetBuilder()
|
||||
.EcdsaSigningKey(EcCurve::P_256)
|
||||
.Authorization(TAG_NO_AUTH_REQUIRED)
|
||||
.AttestationChallenge("challenge")
|
||||
.AttestationApplicationId("foo")
|
||||
.SetDefaultValidity();
|
||||
builder.Authorization(TAG_ATTESTATION_ID_IMEI, imei.data(), imei.size());
|
||||
builder.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, second_imei.data(), second_imei.size());
|
||||
|
||||
vector<uint8_t> attested_key_blob;
|
||||
vector<KeyCharacteristics> attested_key_characteristics;
|
||||
vector<Certificate> attested_key_cert_chain;
|
||||
auto result = GenerateKey(builder, attest_key, &attested_key_blob,
|
||||
&attested_key_characteristics, &attested_key_cert_chain);
|
||||
|
||||
if (result == ErrorCode::CANNOT_ATTEST_IDS && !isDeviceIdAttestationRequired()) {
|
||||
GTEST_SKIP() << "Test not applicable as device does not support IMEI ID attestation.";
|
||||
}
|
||||
|
||||
ASSERT_EQ(result, ErrorCode::OK);
|
||||
|
||||
device_id_attestation_vsr_check(result);
|
||||
|
||||
CheckedDeleteKey(&attested_key_blob);
|
||||
|
||||
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
|
||||
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
|
||||
|
||||
// The attested key characteristics will not contain APPLICATION_ID_* fields (their
|
||||
// spec definitions all have "Must never appear in KeyCharacteristics"), but the
|
||||
// attestation extension should contain them, so make sure the extra tag is added.
|
||||
vector<uint8_t> imei_blob(imei.data(), imei.data() + imei.size());
|
||||
KeyParameter imei_tag = Authorization(TAG_ATTESTATION_ID_IMEI, imei_blob);
|
||||
hw_enforced.push_back(imei_tag);
|
||||
vector<uint8_t> sec_imei_blob(second_imei.data(), second_imei.data() + second_imei.size());
|
||||
KeyParameter sec_imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, sec_imei_blob);
|
||||
hw_enforced.push_back(sec_imei_tag);
|
||||
|
||||
EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
|
||||
hw_enforced, SecLevel(),
|
||||
attested_key_cert_chain[0].encodedCertificate));
|
||||
|
||||
CheckedDeleteKey(&attest_key.keyBlob);
|
||||
}
|
||||
|
||||
INSTANTIATE_KEYMINT_AIDL_TEST(AttestKeyTest);
|
||||
|
||||
} // namespace aidl::android::hardware::security::keymint::test
|
||||
|
|
|
@ -217,6 +217,14 @@ bool KeyMintAidlTestBase::isDeviceIdAttestationRequired() {
|
|||
return AidlVersion() >= 2 || property_get_int32("ro.vendor.api_level", 0) >= 33;
|
||||
}
|
||||
|
||||
/**
|
||||
* An API to determine second IMEI ID attestation is required or not,
|
||||
* which is supported for KeyMint version 3 or first_api_level greater than 33.
|
||||
*/
|
||||
bool KeyMintAidlTestBase::isSecondImeiIdAttestationRequired() {
|
||||
return AidlVersion() >= 3 && property_get_int32("ro.vendor.api_level", 0) > 33;
|
||||
}
|
||||
|
||||
bool KeyMintAidlTestBase::Curve25519Supported() {
|
||||
// Strongbox never supports curve 25519.
|
||||
if (SecLevel() == SecurityLevel::STRONGBOX) {
|
||||
|
|
|
@ -85,6 +85,7 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
|
|||
uint32_t boot_patch_level(const vector<KeyCharacteristics>& key_characteristics);
|
||||
uint32_t boot_patch_level();
|
||||
bool isDeviceIdAttestationRequired();
|
||||
bool isSecondImeiIdAttestationRequired();
|
||||
|
||||
bool Curve25519Supported();
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ typedef struct km_auth_list {
|
|||
ASN1_INTEGER* boot_patchlevel;
|
||||
ASN1_NULL* device_unique_attestation;
|
||||
ASN1_NULL* identity_credential;
|
||||
ASN1_OCTET_STRING* attestation_id_second_imei;
|
||||
} KM_AUTH_LIST;
|
||||
|
||||
ASN1_SEQUENCE(KM_AUTH_LIST) = {
|
||||
|
@ -170,6 +171,8 @@ ASN1_SEQUENCE(KM_AUTH_LIST) = {
|
|||
TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential, ASN1_NULL,
|
||||
TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
|
||||
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_second_imei, ASN1_OCTET_STRING,
|
||||
TAG_ATTESTATION_ID_SECOND_IMEI.maskedTag()),
|
||||
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
|
||||
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
|
||||
|
||||
|
@ -323,6 +326,7 @@ static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet*
|
|||
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
|
||||
copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
|
||||
copyAuthTag(record->identity_credential, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
|
||||
copyAuthTag(record->attestation_id_second_imei, TAG_ATTESTATION_ID_SECOND_IMEI, auth_list);
|
||||
|
||||
return ErrorCode::OK;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
|
|||
DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
|
||||
DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
|
||||
DECLARE_TYPED_TAG(ATTESTATION_ID_IMEI);
|
||||
DECLARE_TYPED_TAG(ATTESTATION_ID_SECOND_IMEI);
|
||||
DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
|
||||
DECLARE_TYPED_TAG(ATTESTATION_ID_MEID);
|
||||
DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
|
||||
|
|
Loading…
Reference in a new issue