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:
parent
a676c3b4ef
commit
e3cdcb2410
6 changed files with 350 additions and 49 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue