mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
For the time being, allow the version number in the attestation record to be 100 even if the AIDL version is 2, so that implementations don't have to update both versions simultaneously. Bug: 194358913 Test: TreeHugger, VtsAidlKeyMintTargetTest Change-Id: I9aae69327a62014e286ce30ca2a4d91c4c280714
353 lines
16 KiB
C++
353 lines
16 KiB
C++
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "keymint_1_attest_key_test"
|
|
|
|
#include <cutils/log.h>
|
|
#include <cutils/properties.h>
|
|
#include <keymint_support/key_param_output.h>
|
|
#include <keymint_support/openssl_utils.h>
|
|
|
|
#include "KeyMintAidlTestBase.h"
|
|
|
|
namespace aidl::android::hardware::security::keymint::test {
|
|
|
|
class DeviceUniqueAttestationTest : public KeyMintAidlTestBase {
|
|
protected:
|
|
void CheckUniqueAttestationResults(const vector<uint8_t>& key_blob,
|
|
const vector<KeyCharacteristics>& key_characteristics,
|
|
const AuthorizationSet& hw_enforced) {
|
|
ASSERT_GT(cert_chain_.size(), 0);
|
|
|
|
if (KeyMintAidlTestBase::dump_Attestations) {
|
|
std::cout << bin2hex(cert_chain_[0].encodedCertificate) << std::endl;
|
|
}
|
|
|
|
ASSERT_GT(key_blob.size(), 0U);
|
|
|
|
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
|
|
|
|
// The device-unique attestation chain should contain exactly three certificates:
|
|
// * The leaf with the attestation extension.
|
|
// * An intermediate, signing the leaf using the device-unique key.
|
|
// * A self-signed root, signed using some authority's key, certifying
|
|
// the device-unique key.
|
|
const size_t chain_length = cert_chain_.size();
|
|
ASSERT_TRUE(chain_length == 2 || chain_length == 3);
|
|
// TODO(b/191361618): Once StrongBox implementations use a correctly-issued
|
|
// certificate chain, do not skip issuers matching.
|
|
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_, /* strict_issuer_check= */ false));
|
|
|
|
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
|
|
EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
|
|
hw_enforced, SecLevel(),
|
|
cert_chain_[0].encodedCertificate));
|
|
}
|
|
};
|
|
|
|
/*
|
|
* DeviceUniqueAttestationTest.RsaNonStrongBoxUnimplemented
|
|
*
|
|
* Verifies that non strongbox implementations do not implement Rsa device unique
|
|
* attestation.
|
|
*/
|
|
TEST_P(DeviceUniqueAttestationTest, RsaNonStrongBoxUnimplemented) {
|
|
if (SecLevel() == SecurityLevel::STRONGBOX) {
|
|
GTEST_SKIP() << "Test not applicable to StrongBox device";
|
|
}
|
|
|
|
vector<uint8_t> key_blob;
|
|
vector<KeyCharacteristics> key_characteristics;
|
|
|
|
// Check RSA implementation
|
|
auto result = GenerateKey(AuthorizationSetBuilder()
|
|
.Authorization(TAG_NO_AUTH_REQUIRED)
|
|
.RsaSigningKey(2048, 65537)
|
|
.Digest(Digest::SHA_2_256)
|
|
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
|
|
.Authorization(TAG_INCLUDE_UNIQUE_ID)
|
|
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
|
|
.AttestationChallenge("challenge")
|
|
.AttestationApplicationId("foo")
|
|
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
|
|
&key_blob, &key_characteristics);
|
|
|
|
ASSERT_TRUE(result == ErrorCode::INVALID_ARGUMENT || result == ErrorCode::UNSUPPORTED_TAG);
|
|
}
|
|
|
|
/*
|
|
* DeviceUniqueAttestationTest.EcdsaNonStrongBoxUnimplemented
|
|
*
|
|
* Verifies that non strongbox implementations do not implement Ecdsa device unique
|
|
* attestation.
|
|
*/
|
|
TEST_P(DeviceUniqueAttestationTest, EcdsaNonStrongBoxUnimplemented) {
|
|
if (SecLevel() == SecurityLevel::STRONGBOX) {
|
|
GTEST_SKIP() << "Test not applicable to StrongBox device";
|
|
}
|
|
|
|
vector<uint8_t> key_blob;
|
|
vector<KeyCharacteristics> key_characteristics;
|
|
|
|
// Check Ecdsa implementation
|
|
auto result = GenerateKey(AuthorizationSetBuilder()
|
|
.Authorization(TAG_NO_AUTH_REQUIRED)
|
|
.EcdsaSigningKey(EcCurve::P_256)
|
|
.Digest(Digest::SHA_2_256)
|
|
.Authorization(TAG_INCLUDE_UNIQUE_ID)
|
|
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
|
|
.AttestationChallenge("challenge")
|
|
.AttestationApplicationId("foo")
|
|
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
|
|
&key_blob, &key_characteristics);
|
|
|
|
ASSERT_TRUE(result == ErrorCode::INVALID_ARGUMENT || result == ErrorCode::UNSUPPORTED_TAG);
|
|
}
|
|
|
|
/*
|
|
* DeviceUniqueAttestationTest.RsaDeviceUniqueAttestation
|
|
*
|
|
* Verifies that strongbox implementations of Rsa implements device unique
|
|
* attestation correctly, if implemented.
|
|
*/
|
|
TEST_P(DeviceUniqueAttestationTest, RsaDeviceUniqueAttestation) {
|
|
if (SecLevel() != SecurityLevel::STRONGBOX) {
|
|
GTEST_SKIP() << "Test not applicable to non-StrongBox device";
|
|
}
|
|
|
|
vector<uint8_t> key_blob;
|
|
vector<KeyCharacteristics> key_characteristics;
|
|
int key_size = 2048;
|
|
|
|
auto result = GenerateKey(AuthorizationSetBuilder()
|
|
.Authorization(TAG_NO_AUTH_REQUIRED)
|
|
.RsaSigningKey(key_size, 65537)
|
|
.Digest(Digest::SHA_2_256)
|
|
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
|
|
.Authorization(TAG_INCLUDE_UNIQUE_ID)
|
|
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
|
|
.AttestationChallenge("challenge")
|
|
.AttestationApplicationId("foo")
|
|
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
|
|
&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_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);
|
|
}
|
|
|
|
/*
|
|
* DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestation
|
|
*
|
|
* Verifies that strongbox implementations of Rsa implements device unique
|
|
* attestation correctly, if implemented.
|
|
*/
|
|
TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestation) {
|
|
if (SecLevel() != SecurityLevel::STRONGBOX) {
|
|
GTEST_SKIP() << "Test not applicable to non-StrongBox device";
|
|
}
|
|
|
|
vector<uint8_t> key_blob;
|
|
vector<KeyCharacteristics> key_characteristics;
|
|
|
|
auto result = GenerateKey(AuthorizationSetBuilder()
|
|
.Authorization(TAG_NO_AUTH_REQUIRED)
|
|
.EcdsaSigningKey(EcCurve::P_256)
|
|
.Digest(Digest::SHA_2_256)
|
|
.Authorization(TAG_INCLUDE_UNIQUE_ID)
|
|
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
|
|
.AttestationChallenge("challenge")
|
|
.AttestationApplicationId("foo")
|
|
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
|
|
&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());
|
|
// 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) {
|
|
GTEST_SKIP() << "Test not applicable to non-StrongBox device";
|
|
}
|
|
|
|
// 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)
|
|
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
|
|
.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) {
|
|
GTEST_SKIP() << "Test not applicable to non-StrongBox device";
|
|
}
|
|
|
|
// 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)
|
|
.Authorization(TAG_CREATION_DATETIME, 1619621648000)
|
|
.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);
|
|
|
|
} // namespace aidl::android::hardware::security::keymint::test
|