diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2023-06-07 17:30:05 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2023-06-07 17:30:05 -0700 |
commit | 4b1a56904ffaeaba1beb00b8449d88625879232e (patch) | |
tree | 4162e52ce313236e90778ff33902a21674bb82c7 /security/keymint/aidl/vts/functional/BootloaderStateTest.cpp | |
parent | e0e0f04e4e2e35544b69d201dc76a66207832535 (diff) | |
parent | 0786ab71425f1021f118b461ede72a4d6727a9f6 (diff) |
Merge 0786ab71425f1021f118b461ede72a4d6727a9f6 on remote branch
Change-Id: I3cdb3f7443c4ee7361dc9a79a15122e8dd1340f8
Diffstat (limited to 'security/keymint/aidl/vts/functional/BootloaderStateTest.cpp')
-rw-r--r-- | security/keymint/aidl/vts/functional/BootloaderStateTest.cpp | 145 |
1 files changed, 109 insertions, 36 deletions
diff --git a/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp b/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp index 723edeef3d..54f187c611 100644 --- a/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp +++ b/security/keymint/aidl/vts/functional/BootloaderStateTest.cpp @@ -21,7 +21,11 @@ #include <string> #include <vector> +#include <android-base/properties.h> #include <android/binder_manager.h> +#include <fstab/fstab.h> +#include <libavb/libavb.h> +#include <libavb_user/avb_ops_user.h> #include <remote_prov/remote_prov_utils.h> #include "KeyMintAidlTestBase.h" @@ -34,49 +38,118 @@ using ::std::vector; // Since this test needs to talk to KeyMint HAL, it can only run as root. Thus, // bootloader can not be locked. -class BootloaderStateTest : public testing::TestWithParam<std::string> { +class BootloaderStateTest : public KeyMintAidlTestBase { public: virtual void SetUp() override { - ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str())); - keyMint_ = IKeyMintDevice::fromBinder(binder); - ASSERT_TRUE(keyMint_) << "Failed to get KM device"; + KeyMintAidlTestBase::SetUp(); + + // Generate a key with attestation. + vector<uint8_t> key_blob; + vector<KeyCharacteristics> key_characteristics; + AuthorizationSet keyDesc = AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(EcCurve::P_256) + .AttestationChallenge("foo") + .AttestationApplicationId("bar") + .Digest(Digest::NONE) + .SetDefaultValidity(); + auto result = GenerateKey(keyDesc, &key_blob, &key_characteristics); + // If factory provisioned attestation key is not supported by Strongbox, + // then create a key with self-signed attestation and use it as the + // attestation key instead. + if (SecLevel() == SecurityLevel::STRONGBOX && + result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) { + result = GenerateKeyWithSelfSignedAttestKey( + AuthorizationSetBuilder() + .EcdsaKey(EcCurve::P_256) + .AttestKey() + .SetDefaultValidity(), /* attest key params */ + keyDesc, &key_blob, &key_characteristics); + } + ASSERT_EQ(ErrorCode::OK, result); + + // Parse attested AVB values. + X509_Ptr cert(parse_cert_blob(cert_chain_[0].encodedCertificate)); + ASSERT_TRUE(cert.get()); + + ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get()); + ASSERT_TRUE(attest_rec); + + auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, &attestedVbKey_, + &attestedVbState_, &attestedBootloaderState_, + &attestedVbmetaDigest_); + ASSERT_EQ(error, ErrorCode::OK); } - std::shared_ptr<IKeyMintDevice> keyMint_; + vector<uint8_t> attestedVbKey_; + VerifiedBoot attestedVbState_; + bool attestedBootloaderState_; + vector<uint8_t> attestedVbmetaDigest_; }; // Check that attested bootloader state is set to unlocked. -TEST_P(BootloaderStateTest, IsUnlocked) { - // Generate a key with attestation. - AuthorizationSet keyDesc = AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(EcCurve::P_256) - .AttestationChallenge("foo") - .AttestationApplicationId("bar") - .Digest(Digest::NONE) - .SetDefaultValidity(); - KeyCreationResult creationResult; - auto kmStatus = keyMint_->generateKey(keyDesc.vector_data(), std::nullopt, &creationResult); - ASSERT_TRUE(kmStatus.isOk()); - - vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain); - - // Parse attested AVB values. - const auto& attestation_cert = key_cert_chain[0].encodedCertificate; - X509_Ptr cert(parse_cert_blob(attestation_cert)); - ASSERT_TRUE(cert.get()); - - ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get()); - ASSERT_TRUE(attest_rec); - - vector<uint8_t> key; - VerifiedBoot attestedVbState; - bool attestedBootloaderState; - vector<uint8_t> attestedVbmetaDigest; - auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, &key, &attestedVbState, - &attestedBootloaderState, &attestedVbmetaDigest); - ASSERT_EQ(error, ErrorCode::OK); - ASSERT_FALSE(attestedBootloaderState) << "This test runs as root. Bootloader must be unlocked."; +TEST_P(BootloaderStateTest, BootloaderIsUnlocked) { + ASSERT_FALSE(attestedBootloaderState_) + << "This test runs as root. Bootloader must be unlocked."; +} + +// Check that verified boot state is set to "unverified", i.e. "orange". +TEST_P(BootloaderStateTest, VbStateIsUnverified) { + // Unlocked bootloader implies that verified boot state must be "unverified". + ASSERT_EQ(attestedVbState_, VerifiedBoot::UNVERIFIED) + << "Verified boot state must be \"UNVERIFIED\" aka \"orange\"."; + + // AVB spec stipulates that bootloader must set "androidboot.verifiedbootstate" parameter + // on the kernel command-line. This parameter is exposed to userspace as + // "ro.boot.verifiedbootstate" property. + auto vbStateProp = ::android::base::GetProperty("ro.boot.verifiedbootstate", ""); + ASSERT_EQ(vbStateProp, "orange") + << "Verified boot state must be \"UNVERIFIED\" aka \"orange\"."; +} + +// Following error codes from avb_slot_data() mean that slot data was loaded +// (even if verification failed). +static inline bool avb_slot_data_loaded(AvbSlotVerifyResult result) { + switch (result) { + case AVB_SLOT_VERIFY_RESULT_OK: + case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: + case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: + case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: + return true; + default: + return false; + } +} + +// Check that attested vbmeta digest is correct. +TEST_P(BootloaderStateTest, VbmetaDigest) { + AvbSlotVerifyData* avbSlotData; + auto suffix = fs_mgr_get_slot_suffix(); + const char* partitions[] = {nullptr}; + auto avbOps = avb_ops_user_new(); + + // For VTS, devices run with vendor_boot-debug.img, which is not release key + // signed. Use AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR to bypass avb + // verification errors. This is OK since we only care about the digest for + // this test case. + auto result = avb_slot_verify(avbOps, partitions, suffix.c_str(), + AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR, + AVB_HASHTREE_ERROR_MODE_EIO, &avbSlotData); + ASSERT_TRUE(avb_slot_data_loaded(result)) << "Failed to load avb slot data"; + + // Unfortunately, bootloader is not required to report the algorithm used + // to calculate the digest. There are only two supported options though, + // SHA256 and SHA512. Attested VBMeta digest must match one of these. + vector<uint8_t> digest256(AVB_SHA256_DIGEST_SIZE); + vector<uint8_t> digest512(AVB_SHA512_DIGEST_SIZE); + + avb_slot_verify_data_calculate_vbmeta_digest(avbSlotData, AVB_DIGEST_TYPE_SHA256, + digest256.data()); + avb_slot_verify_data_calculate_vbmeta_digest(avbSlotData, AVB_DIGEST_TYPE_SHA512, + digest512.data()); + + ASSERT_TRUE((attestedVbmetaDigest_ == digest256) || (attestedVbmetaDigest_ == digest512)) + << "Attested digest does not match computed digest."; } INSTANTIATE_KEYMINT_AIDL_TEST(BootloaderStateTest); |