Adding a test using second IMEI as attestation ids. am: 5283f81f64 am: e146a75eb5 am: 6db972db0e

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2378091

Change-Id: I3061f88ad88beb4eaea33ecac4f6b8894900949f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Rajesh Nyamagoud
2023-02-21 19:32:09 +00:00
committed by Automerger Merge Worker
4 changed files with 193 additions and 0 deletions

View File

@@ -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

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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;
}