diff options
author | David Drysdale <drysdale@google.com> | 2021-06-14 14:46:02 +0100 |
---|---|---|
committer | David Drysdale <drysdale@google.com> | 2021-06-17 16:43:37 +0100 |
commit | a676c3b4eff557889cfb8e2b20f2275a459d5646 (patch) | |
tree | 76cb82f7152a08d00dbfe0d9f3186125d5518e7a /security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp | |
parent | 98949afb705dc8e9c9f1a2498cc99d22da579660 (diff) |
KeyMint 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 update attestation tags to include vendor/boot patchlevel if
they're available. (They always should be, but fixing that is a
separate task.)
Bug: 190757200
Test: VtsAidlKeyMintTargetTest
Merged-In: Ibaed7364c6d08c0982e2a9fb6cb864ae42cf39fe
Change-Id: Ibaed7364c6d08c0982e2a9fb6cb864ae42cf39fe
Diffstat (limited to 'security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp')
-rw-r--r-- | security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp | 186 |
1 files changed, 159 insertions, 27 deletions
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp index 732d9ebadd..a3ed3ad4a0 100644 --- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp +++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp @@ -29,7 +29,7 @@ class DeviceUniqueAttestationTest : public KeyMintAidlTestBase { protected: void CheckUniqueAttestationResults(const vector<uint8_t>& key_blob, const vector<KeyCharacteristics>& key_characteristics, - const AuthorizationSet& hw_enforced, int key_size) { + const AuthorizationSet& hw_enforced) { ASSERT_GT(cert_chain_.size(), 0); if (KeyMintAidlTestBase::dump_Attestations) { @@ -40,8 +40,6 @@ class DeviceUniqueAttestationTest : public KeyMintAidlTestBase { AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics); - EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size)) << "Key size missing"; - // The device-unique attestation chain should contain exactly two certificates: // * The leaf with the attestation extension. // * A self-signed root, signed using the device-unique key. @@ -136,17 +134,32 @@ TEST_P(DeviceUniqueAttestationTest, RsaDeviceUniqueAttestation) { ASSERT_EQ(ErrorCode::OK, result); - AuthorizationSet hw_enforced = AuthorizationSetBuilder() - .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION) - .Authorization(TAG_NO_AUTH_REQUIRED) - .RsaSigningKey(2048, 65537) - .Digest(Digest::SHA_2_256) - .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN) - .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED) - .Authorization(TAG_OS_VERSION, os_version()) - .Authorization(TAG_OS_PATCHLEVEL, os_patch_level()); - - CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size); + AuthorizationSetBuilder hw_enforced = + AuthorizationSetBuilder() + .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION) + .Authorization(TAG_NO_AUTH_REQUIRED) + .RsaSigningKey(2048, 65537) + .Digest(Digest::SHA_2_256) + .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN) + .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED) + .Authorization(TAG_OS_VERSION, os_version()) + .Authorization(TAG_OS_PATCHLEVEL, os_patch_level()); + + // Any patchlevels attached to the key should also be present in the attestation extension. + AuthorizationSet auths; + for (const auto& entry : key_characteristics) { + auths.push_back(AuthorizationSet(entry.authorizations)); + } + auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL); + if (vendor_pl) { + hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl); + } + auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL); + if (boot_pl) { + hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl); + } + + CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced); } /* @@ -160,11 +173,10 @@ TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestation) { vector<uint8_t> key_blob; vector<KeyCharacteristics> key_characteristics; - int key_size = 256; auto result = GenerateKey(AuthorizationSetBuilder() .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(256) + .EcdsaSigningKey(EcCurve::P_256) .Digest(Digest::SHA_2_256) .Authorization(TAG_INCLUDE_UNIQUE_ID) .AttestationChallenge("challenge") @@ -176,17 +188,137 @@ TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestation) { if (result == ErrorCode::CANNOT_ATTEST_IDS) return; ASSERT_EQ(ErrorCode::OK, result); - AuthorizationSet hw_enforced = AuthorizationSetBuilder() - .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION) - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(EcCurve::P_256) - .Digest(Digest::SHA_2_256) - .Authorization(TAG_EC_CURVE, EcCurve::P_256) - .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED) - .Authorization(TAG_OS_VERSION, os_version()) - .Authorization(TAG_OS_PATCHLEVEL, os_patch_level()); - - CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size); + AuthorizationSetBuilder hw_enforced = + AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(EcCurve::P_256) + .Digest(Digest::SHA_2_256) + .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION) + .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED) + .Authorization(TAG_OS_VERSION, os_version()) + .Authorization(TAG_OS_PATCHLEVEL, os_patch_level()); + // Any patchlevels attached to the key should also be present in the attestation extension. + AuthorizationSet auths; + for (const auto& entry : key_characteristics) { + auths.push_back(AuthorizationSet(entry.authorizations)); + } + auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL); + if (vendor_pl) { + hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl); + } + auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL); + if (boot_pl) { + hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl); + } + + CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced); +} + +/* + * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestationID + * + * Verifies that device unique attestation can include IDs that do match the + * local device. + */ +TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) { + if (SecLevel() != SecurityLevel::STRONGBOX) return; + + // 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"); + vector<uint8_t> key_blob; + vector<KeyCharacteristics> key_characteristics; + + for (const KeyParameter& tag : attestation_id_tags) { + SCOPED_TRACE(testing::Message() << "+tag-" << tag); + AuthorizationSetBuilder builder = AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(EcCurve::P_256) + .Digest(Digest::SHA_2_256) + .Authorization(TAG_INCLUDE_UNIQUE_ID) + .AttestationChallenge("challenge") + .AttestationApplicationId("foo") + .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION); + builder.push_back(tag); + auto result = GenerateKey(builder, &key_blob, &key_characteristics); + + // It is optional for Strong box to support DeviceUniqueAttestation. + if (result == ErrorCode::CANNOT_ATTEST_IDS) return; + ASSERT_EQ(ErrorCode::OK, result); + + AuthorizationSetBuilder hw_enforced = + AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(EcCurve::P_256) + .Digest(Digest::SHA_2_256) + .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION) + .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED) + .Authorization(TAG_OS_VERSION, os_version()) + .Authorization(TAG_OS_PATCHLEVEL, os_patch_level()); + // Expect the specified tag to be present in the attestation extension. + hw_enforced.push_back(tag); + // Any patchlevels attached to the key should also be present in the attestation extension. + AuthorizationSet auths; + for (const auto& entry : key_characteristics) { + auths.push_back(AuthorizationSet(entry.authorizations)); + } + auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL); + if (vendor_pl) { + hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl); + } + auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL); + if (boot_pl) { + hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl); + } + CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced); + } +} + +/* + * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestationMismatchID + * + * Verifies that device unique attestation rejects attempts to attest to IDs that + * don't match the local device. + */ +TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) { + if (SecLevel() != SecurityLevel::STRONGBOX) return; + + // Collection of invalid attestation ID tags. + auto attestation_id_tags = + AuthorizationSetBuilder() + .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand") + .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device") + .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product") + .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial") + .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei") + .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid") + .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer") + .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model"); + vector<uint8_t> key_blob; + vector<KeyCharacteristics> key_characteristics; + + for (const KeyParameter& invalid_tag : attestation_id_tags) { + SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag); + AuthorizationSetBuilder builder = AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(EcCurve::P_256) + .Digest(Digest::SHA_2_256) + .Authorization(TAG_INCLUDE_UNIQUE_ID) + .AttestationChallenge("challenge") + .AttestationApplicationId("foo") + .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION); + // Add the tag that doesn't match the local device's real ID. + builder.push_back(invalid_tag); + auto result = GenerateKey(builder, &key_blob, &key_characteristics); + + ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG); + } } INSTANTIATE_KEYMINT_AIDL_TEST(DeviceUniqueAttestationTest); |