From e3cdcb2410ba4fb4ad25f4a20072c6fd2485d9b6 Mon Sep 17 00:00:00 2001 From: David Drysdale Date: Tue, 15 Jun 2021 10:11:12 +0100 Subject: [PATCH] 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 --- keymaster/4.0/support/attestation_record.cpp | 111 +++++++++++------ .../functional/keymaster_hidl_hal_test.cpp | 101 +++++++++++++++ keymaster/4.1/support/attestation_record.cpp | 48 ++++++-- .../include/keymasterV4_1/keymaster_tags.h | 8 ++ .../DeviceUniqueAttestationTest.cpp | 115 +++++++++++++++++- .../4.1/vts/functional/Keymaster4_1HidlTest.h | 16 +++ 6 files changed, 350 insertions(+), 49 deletions(-) diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp index bc294bd35b..342b3e2525 100644 --- a/keymaster/4.0/support/attestation_record.cpp +++ b/keymaster/4.0/support/attestation_record.cpp @@ -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, diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index 9e37ed0a44..01c502c586 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -96,6 +96,18 @@ bool contains(hidl_vec& set, TypedTag) { return count > 0; } +// If the given property is available, add it to the tag set under the given tag ID. +template +void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag ttag, + const char* prop) { + char value[PROPERTY_VALUE_MAX]; + int len = property_get(prop, value, /* default = */ ""); + if (len > 0) { + tags->Authorization(ttag, reinterpret_cast(value), + static_cast(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> 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 expected_hw_enforced = key_characteristics_.hardwareEnforced; + expected_hw_enforced.push_back(tag); + + EXPECT_TRUE(verify_attestation_record( + "challenge", "foo", key_characteristics_.softwareEnforced, + hidl_vec(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> cert_chain; + auto result = AttestKey(builder, &cert_chain); + + EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG) + << "result: " << static_cast(result); + } +} + /* * AttestationTest.EcAttestationRequiresAttestationAppId * diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp index 207a7e8264..15230d5def 100644 --- a/keymaster/4.1/support/attestation_record.cpp +++ b/keymaster/4.1/support/attestation_record.cpp @@ -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, diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h index 40eb1426ef..e8db56a85c 100644 --- a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h +++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h @@ -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; diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp index 3d97daf274..4a57f44dd9 100644 --- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp +++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp @@ -27,6 +27,8 @@ #include #include +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& 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> 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> 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(result); + } +} + INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(DeviceUniqueAttestationTest); } // namespace test diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h index f8c1fad233..670ccfbeaf 100644 --- a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h +++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h @@ -18,6 +18,8 @@ #include +#include + #include #include @@ -159,3 +161,17 @@ bool contains(hidl_vec& 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 +void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag 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