KeyMaster VTS: improve attestation tests

Check that the various ATTESTATION_ID_* tags are included if they
have the correct value, and that keygen fails if they have an invalid
value.

Also fix the support libraries to add the missing fields to the ASN.1
schema and fix the existing ordering.

Bug: 190757200
Test: VtsHalKeymasterV4_1TargetTest, VtsHalKeymasterV4_0TargetTest
Merged-In: I11d28d71676d44ebdc79b25b2eb70947022bb1cf
Ignore-AOSP-First: to be cross-merged manually
Change-Id: I5e19880bbc9e2e667f1204bdc2247ae53a3dada7
This commit is contained in:
David Drysdale 2021-06-15 10:11:12 +01:00
parent a676c3b4ef
commit e3cdcb2410
6 changed files with 350 additions and 49 deletions

View file

@ -71,6 +71,7 @@ typedef struct km_auth_list {
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
ASN1_NULL* rollback_resistance;
ASN1_INTEGER* active_date_time;
ASN1_INTEGER* origination_expire_date_time;
ASN1_INTEGER* usage_expire_date_time;
@ -78,56 +79,84 @@ typedef struct km_auth_list {
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
ASN1_NULL* trusted_user_presence_required;
ASN1_NULL* trusted_confirmation_required;
ASN1_NULL* unlocked_device_required;
ASN1_NULL* all_applications;
ASN1_OCTET_STRING* application_id;
ASN1_INTEGER* creation_date_time;
ASN1_INTEGER* origin;
ASN1_NULL* rollback_resistance;
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
ASN1_OCTET_STRING* attestation_application_id;
ASN1_NULL* trusted_user_presence_required;
ASN1_NULL* trusted_confirmation_required;
ASN1_NULL* unlocked_device_required;
ASN1_OCTET_STRING* attestation_id_brand;
ASN1_OCTET_STRING* attestation_id_device;
ASN1_OCTET_STRING* attestation_id_product;
ASN1_OCTET_STRING* attestation_id_serial;
ASN1_OCTET_STRING* attestation_id_imei;
ASN1_OCTET_STRING* attestation_id_meid;
ASN1_OCTET_STRING* attestation_id_manufacturer;
ASN1_OCTET_STRING* attestation_id_model;
ASN1_INTEGER* vendor_patchlevel;
ASN1_INTEGER* boot_patchlevel;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL, TAG_ROLLBACK_RESISTANCE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL, TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER, TAG_CREATION_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER, TAG_VENDOR_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
TAG_ROLLBACK_RESISTANCE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
TAG_CREATION_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_BRAND.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_DEVICE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_SERIAL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_IMEI.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_MEID.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_MODEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
TAG_VENDOR_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
@ -259,6 +288,14 @@ static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet*
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,

View file

@ -96,6 +96,18 @@ bool contains(hidl_vec<KeyParameter>& set, TypedTag<tag_type, tag>) {
return count > 0;
}
// If the given property is available, add it to the tag set under the given tag ID.
template <Tag tag>
void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
const char* prop) {
char value[PROPERTY_VALUE_MAX];
int len = property_get(prop, value, /* default = */ "");
if (len > 0) {
tags->Authorization(ttag, reinterpret_cast<const uint8_t*>(value),
static_cast<size_t>(len));
}
}
constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
@ -4408,6 +4420,95 @@ TEST_P(AttestationTest, EcAttestation) {
SecLevel(), cert_chain[0]));
}
/*
* AttestationTest.EcAttestationID
*
* Verifies that attesting to EC keys with correct attestation ID fields works and generates the
* expected output.
*/
TEST_P(AttestationTest, EcAttestationID) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)));
// Collection of valid attestation ID tags.
auto attestation_id_tags = AuthorizationSetBuilder();
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
"ro.product.manufacturer");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
for (const KeyParameter& tag : attestation_id_tags) {
AuthorizationSetBuilder builder =
AuthorizationSetBuilder()
.Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
.Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo"));
// Include one of the (valid) attestation ID tags.
builder.push_back(tag);
hidl_vec<hidl_vec<uint8_t>> cert_chain;
auto result = AttestKey(builder, &cert_chain);
if (result == ErrorCode::CANNOT_ATTEST_IDS) {
continue;
}
ASSERT_EQ(ErrorCode::OK, result);
EXPECT_GE(cert_chain.size(), 2U);
std::vector<KeyParameter> expected_hw_enforced = key_characteristics_.hardwareEnforced;
expected_hw_enforced.push_back(tag);
EXPECT_TRUE(verify_attestation_record(
"challenge", "foo", key_characteristics_.softwareEnforced,
hidl_vec<KeyParameter>(expected_hw_enforced), SecLevel(), cert_chain[0]));
}
}
/*
* AttestationTest.EcAttestationMismatchID
*
* Verifies that attesting to EC keys with incorrect attestation ID fields fails.
*/
TEST_P(AttestationTest, EcAttestationMismatchID) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)));
// Collection of invalid attestation ID tags.
std::string invalid = "completely-invalid";
auto invalid_tags =
AuthorizationSetBuilder()
.Authorization(V4_0::TAG_ATTESTATION_ID_BRAND, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_DEVICE, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_PRODUCT, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_SERIAL, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_IMEI, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_MEID, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_MANUFACTURER, invalid.data(),
invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_MODEL, invalid.data(), invalid.size());
for (const KeyParameter& invalid_tag : invalid_tags) {
AuthorizationSetBuilder builder =
AuthorizationSetBuilder()
.Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
.Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo"));
// Include one of the invalid attestation ID tags.
builder.push_back(invalid_tag);
hidl_vec<hidl_vec<uint8_t>> cert_chain;
auto result = AttestKey(builder, &cert_chain);
EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
<< "result: " << static_cast<int32_t>(result);
}
}
/*
* AttestationTest.EcAttestationRequiresAttestationAppId
*

View file

@ -79,6 +79,8 @@ typedef struct km_auth_list {
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
ASN1_NULL* rollback_resistance;
ASN1_NULL* early_boot_only;
ASN1_INTEGER* active_date_time;
ASN1_INTEGER* origination_expire_date_time;
ASN1_INTEGER* usage_expire_date_time;
@ -86,21 +88,27 @@ typedef struct km_auth_list {
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
ASN1_NULL* trusted_user_presence_required;
ASN1_NULL* trusted_confirmation_required;
ASN1_NULL* unlocked_device_required;
ASN1_NULL* all_applications;
ASN1_OCTET_STRING* application_id;
ASN1_INTEGER* creation_date_time;
ASN1_INTEGER* origin;
ASN1_NULL* rollback_resistance;
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
ASN1_OCTET_STRING* attestation_application_id;
ASN1_NULL* trusted_user_presence_required;
ASN1_NULL* trusted_confirmation_required;
ASN1_NULL* unlocked_device_required;
ASN1_OCTET_STRING* attestation_id_brand;
ASN1_OCTET_STRING* attestation_id_device;
ASN1_OCTET_STRING* attestation_id_product;
ASN1_OCTET_STRING* attestation_id_serial;
ASN1_OCTET_STRING* attestation_id_imei;
ASN1_OCTET_STRING* attestation_id_meid;
ASN1_OCTET_STRING* attestation_id_manufacturer;
ASN1_OCTET_STRING* attestation_id_model;
ASN1_INTEGER* vendor_patchlevel;
ASN1_INTEGER* boot_patchlevel;
ASN1_NULL* early_boot_only;
ASN1_NULL* device_unique_attestation;
ASN1_NULL* identity_credential_key;
} KM_AUTH_LIST;
@ -116,6 +124,7 @@ ASN1_SEQUENCE(KM_AUTH_LIST) = {
TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
TAG_ROLLBACK_RESISTANCE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
@ -138,12 +147,27 @@ ASN1_SEQUENCE(KM_AUTH_LIST) = {
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_BRAND.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_DEVICE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_SERIAL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_IMEI.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_MEID.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
TAG_ATTESTATION_ID_MODEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
TAG_VENDOR_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL,
@ -279,6 +303,14 @@ static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet*
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,

View file

@ -53,6 +53,14 @@ using V4_0::TAG_APPLICATION_ID;
using V4_0::TAG_ASSOCIATED_DATA;
using V4_0::TAG_ATTESTATION_APPLICATION_ID;
using V4_0::TAG_ATTESTATION_CHALLENGE;
using V4_0::TAG_ATTESTATION_ID_BRAND;
using V4_0::TAG_ATTESTATION_ID_DEVICE;
using V4_0::TAG_ATTESTATION_ID_IMEI;
using V4_0::TAG_ATTESTATION_ID_MANUFACTURER;
using V4_0::TAG_ATTESTATION_ID_MEID;
using V4_0::TAG_ATTESTATION_ID_MODEL;
using V4_0::TAG_ATTESTATION_ID_PRODUCT;
using V4_0::TAG_ATTESTATION_ID_SERIAL;
using V4_0::TAG_AUTH_TIMEOUT;
using V4_0::TAG_BLOB_USAGE_REQUIREMENTS;
using V4_0::TAG_BLOCK_MODE;

View file

@ -27,6 +27,8 @@
#include <keymasterV4_1/attestation_record.h>
#include <keymasterV4_1/authorization_set.h>
using android::hardware::keymaster::V4_0::test::add_tag_from_prop;
// Not to dump the attestation by default. Can enable by specify the parameter
// "--dump_attestations" on lunching VTS
static bool dumpAttestations = false;
@ -173,10 +175,15 @@ void check_attestation_record(AttestationRecord attestation, const HidlBuf& chal
attestation.software_enforced.Sort();
attestation.hardware_enforced.Sort();
EXPECT_EQ(filter_tags(expected_sw_enforced), filter_tags(attestation.software_enforced))
<< DIFFERENCE(expected_sw_enforced, attestation.software_enforced);
EXPECT_EQ(filter_tags(expected_hw_enforced), filter_tags(attestation.hardware_enforced))
<< DIFFERENCE(expected_hw_enforced, attestation.hardware_enforced);
expected_sw_enforced = filter_tags(expected_sw_enforced);
expected_hw_enforced = filter_tags(expected_hw_enforced);
AuthorizationSet attestation_sw_enforced = filter_tags(attestation.software_enforced);
AuthorizationSet attestation_hw_enforced = filter_tags(attestation.hardware_enforced);
EXPECT_EQ(expected_sw_enforced, attestation_sw_enforced)
<< DIFFERENCE(expected_sw_enforced, attestation_sw_enforced);
EXPECT_EQ(expected_hw_enforced, attestation_hw_enforced)
<< DIFFERENCE(expected_hw_enforced, attestation_hw_enforced);
}
X509_Ptr parse_cert_blob(const std::vector<uint8_t>& blob) {
@ -342,6 +349,106 @@ TEST_P(DeviceUniqueAttestationTest, Ecdsa) {
SecLevel());
}
TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
if (SecLevel() != SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID))));
// Collection of valid attestation ID tags.
auto attestation_id_tags = AuthorizationSetBuilder();
add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_SERIAL, "ro.serial");
add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_MANUFACTURER,
"ro.product.manufacturer");
add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_MODEL, "ro.product.model");
for (const KeyParameter& tag : attestation_id_tags) {
hidl_vec<hidl_vec<uint8_t>> cert_chain;
HidlBuf challenge("challenge");
HidlBuf app_id("foo");
AuthorizationSetBuilder builder =
AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
.Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id);
builder.push_back(tag);
ErrorCode result = convert(AttestKey(builder, &cert_chain));
// It is optional for Strong box to support DeviceUniqueAttestation.
if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
ASSERT_EQ(ErrorCode::OK, result);
EXPECT_EQ(2U, cert_chain.size());
if (dumpAttestations) {
for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
}
auto [err, attestation] = parse_attestation_record(cert_chain[0]);
ASSERT_EQ(ErrorCode::OK, err);
AuthorizationSetBuilder hw_enforced =
AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
.Authorization(TAG_OS_VERSION, os_version())
.Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
hw_enforced.push_back(tag);
check_attestation_record(
attestation, challenge,
/* sw_enforced */
AuthorizationSetBuilder().Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
hw_enforced, SecLevel());
}
}
TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
if (SecLevel() != SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID))));
// Collection of invalid attestation ID tags.
std::string invalid = "completely-invalid";
auto attestation_id_tags =
AuthorizationSetBuilder()
.Authorization(V4_0::TAG_ATTESTATION_ID_BRAND, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_DEVICE, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_PRODUCT, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_SERIAL, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_IMEI, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_MEID, invalid.data(), invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_MANUFACTURER, invalid.data(),
invalid.size())
.Authorization(V4_0::TAG_ATTESTATION_ID_MODEL, invalid.data(), invalid.size());
for (const KeyParameter& invalid_tag : attestation_id_tags) {
hidl_vec<hidl_vec<uint8_t>> cert_chain;
HidlBuf challenge("challenge");
HidlBuf app_id("foo");
AuthorizationSetBuilder builder =
AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
.Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id);
builder.push_back(invalid_tag);
ErrorCode result = convert(AttestKey(builder, &cert_chain));
EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
<< "result: " << static_cast<int32_t>(result);
}
}
INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(DeviceUniqueAttestationTest);
} // namespace test

View file

@ -18,6 +18,8 @@
#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
#include <android-base/properties.h>
#include <KeymasterHidlTest.h>
#include <keymasterV4_1/authorization_set.h>
@ -159,3 +161,17 @@ bool contains(hidl_vec<KeyParameter>& set, TypedTag typedTag) {
android::hardware::PrintInstanceNameToString)
} // namespace android::hardware::keymaster::V4_1::test
namespace android::hardware::keymaster::V4_0::test {
// If the given property is available, add it to the tag set under the given tag ID.
template <Tag tag>
void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
const char* prop) {
std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
if (!prop_value.empty()) {
tags->Authorization(ttag, prop_value.data(), prop_value.size());
}
}
} // namespace android::hardware::keymaster::V4_0::test