Loading keymaster/4.0/vts/functional/Android.bp +5 −0 Original line number Diff line number Diff line Loading @@ -30,13 +30,17 @@ cc_test { "keymaster_hidl_hal_test.cpp", ], srcs: [ "BootloaderStateTest.cpp", "HmacKeySharingTest.cpp", "VerificationTokenTest.cpp", "keymaster_hidl_hal_test.cpp", ], static_libs: [ "android.hardware.keymaster@4.0", "libavb_user", "libavb", "libcrypto_static", "libfs_mgr", "libkeymaster4support", "libkeymaster4vtstest", ], Loading Loading @@ -64,6 +68,7 @@ cc_test_library { ], static_libs: [ "android.hardware.keymaster@4.0", "libcrypto_static", "libkeymaster4support", ], } keymaster/4.0/vts/functional/BootloaderStateTest.cpp 0 → 100644 +146 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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. */ #include <memory> #include <optional> #include <string> #include <vector> #include <android-base/properties.h> #include <fstab/fstab.h> #include <libavb/libavb.h> #include <libavb_user/avb_ops_user.h> #include "KeymasterHidlTest.h" namespace android::hardware::keymaster::V4_0::test { using ::std::string; using ::std::vector; // Since this test needs to talk to Keymaster HAL, it can only run as root. Thus, // bootloader can not be locked. class BootloaderStateTest : public KeymasterHidlTest { public: virtual void SetUp() override { KeymasterHidlTest::SetUp(); // Generate a key. auto ec = GenerateKey(AuthorizationSetBuilder() .Authorization(TAG_NO_AUTH_REQUIRED) .EcdsaSigningKey(EcCurve::P_256) .Digest(Digest::SHA_2_256)); ASSERT_EQ(ec, ErrorCode::OK) << "Failed to generate key."; // Generate attestation. hidl_vec<hidl_vec<uint8_t>> cert_chain; ec = AttestKey(AuthorizationSetBuilder() .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge")) .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")), &cert_chain); ASSERT_EQ(ec, ErrorCode::OK) << "Failed to generate attestation."; X509_Ptr cert(parse_cert_blob(cert_chain[0])); ASSERT_TRUE(cert.get()) << "Failed to parse certificate blob."; ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get()); ASSERT_TRUE(attest_rec) << "Failed to get attestation record."; // Parse root of trust. HidlBuf verified_boot_key; keymaster_verified_boot_t verified_boot_state; bool device_locked; HidlBuf verified_boot_hash; auto result = parse_root_of_trust(attest_rec->data, attest_rec->length, &verified_boot_key, &verified_boot_state, &device_locked, &verified_boot_hash); ASSERT_EQ(result, ErrorCode::OK) << "Failed to parse root of trust."; } hidl_vec<uint8_t> attestedVbKey_; keymaster_verified_boot_t attestedVbState_; bool attestedBootloaderState_; hidl_vec<uint8_t> attestedVbmetaDigest_; }; // Check that attested bootloader state is set to 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_, KM_VERIFIED_BOOT_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_KEYMASTER_HIDL_TEST(BootloaderStateTest); } // namespace android::hardware::keymaster::V4_0::test keymaster/4.0/vts/functional/KeymasterHidlTest.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -841,6 +841,30 @@ std::vector<Digest> KeymasterHidlTest::InvalidDigests() { return {}; } X509* parse_cert_blob(const hidl_vec<uint8_t>& blob) { const uint8_t* p = blob.data(); return d2i_X509(nullptr, &p, blob.size()); } ASN1_OCTET_STRING* get_attestation_record(X509* certificate) { ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */)); EXPECT_TRUE(!!oid.get()); if (!oid.get()) return nullptr; int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */); EXPECT_NE(-1, location) << "Attestation extension not found in certificate"; if (location == -1) return nullptr; X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location); EXPECT_TRUE(!!attest_rec_ext) << "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug."; if (!attest_rec_ext) return nullptr; ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext); EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data"; return attest_rec; } } // namespace test } // namespace V4_0 } // namespace keymaster Loading keymaster/4.0/vts/functional/KeymasterHidlTest.h +7 −0 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ #include <hidl/GtestPrinter.h> #include <hidl/ServiceManagement.h> #include <keymasterV4_0/attestation_record.h> #include <keymasterV4_0/authorization_set.h> #include <keymasterV4_0/openssl_utils.h> namespace android { namespace hardware { Loading Loading @@ -241,6 +243,11 @@ class KeymasterHidlTest : public ::testing::TestWithParam<std::string> { testing::ValuesIn(KeymasterHidlTest::build_params()), \ android::hardware::PrintInstanceNameToString) X509* parse_cert_blob(const hidl_vec<uint8_t>& blob); // Extract attestation record from cert. Returned object is still part of cert; don't free it // separately. ASN1_OCTET_STRING* get_attestation_record(X509* certificate); } // namespace test } // namespace V4_0 } // namespace keymaster Loading keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +0 −26 Original line number Diff line number Diff line Loading @@ -263,11 +263,6 @@ struct RSA_Delete { void operator()(RSA* p) { RSA_free(p); } }; X509* parse_cert_blob(const hidl_vec<uint8_t>& blob) { const uint8_t* p = blob.data(); return d2i_X509(nullptr, &p, blob.size()); } bool verify_chain(const hidl_vec<hidl_vec<uint8_t>>& chain, const std::string& msg, const std::string& signature) { { Loading Loading @@ -337,27 +332,6 @@ bool verify_chain(const hidl_vec<hidl_vec<uint8_t>>& chain, const std::string& m return true; } // Extract attestation record from cert. Returned object is still part of cert; don't free it // separately. ASN1_OCTET_STRING* get_attestation_record(X509* certificate) { ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */)); EXPECT_TRUE(!!oid.get()); if (!oid.get()) return nullptr; int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */); EXPECT_NE(-1, location) << "Attestation extension not found in certificate"; if (location == -1) return nullptr; X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location); EXPECT_TRUE(!!attest_rec_ext) << "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug."; if (!attest_rec_ext) return nullptr; ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext); EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data"; return attest_rec; } bool tag_in_list(const KeyParameter& entry) { // Attestations don't contain everything in key authorization lists, so we need to filter // the key lists to produce the lists that we expect to match the attestations. Loading Loading
keymaster/4.0/vts/functional/Android.bp +5 −0 Original line number Diff line number Diff line Loading @@ -30,13 +30,17 @@ cc_test { "keymaster_hidl_hal_test.cpp", ], srcs: [ "BootloaderStateTest.cpp", "HmacKeySharingTest.cpp", "VerificationTokenTest.cpp", "keymaster_hidl_hal_test.cpp", ], static_libs: [ "android.hardware.keymaster@4.0", "libavb_user", "libavb", "libcrypto_static", "libfs_mgr", "libkeymaster4support", "libkeymaster4vtstest", ], Loading Loading @@ -64,6 +68,7 @@ cc_test_library { ], static_libs: [ "android.hardware.keymaster@4.0", "libcrypto_static", "libkeymaster4support", ], }
keymaster/4.0/vts/functional/BootloaderStateTest.cpp 0 → 100644 +146 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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. */ #include <memory> #include <optional> #include <string> #include <vector> #include <android-base/properties.h> #include <fstab/fstab.h> #include <libavb/libavb.h> #include <libavb_user/avb_ops_user.h> #include "KeymasterHidlTest.h" namespace android::hardware::keymaster::V4_0::test { using ::std::string; using ::std::vector; // Since this test needs to talk to Keymaster HAL, it can only run as root. Thus, // bootloader can not be locked. class BootloaderStateTest : public KeymasterHidlTest { public: virtual void SetUp() override { KeymasterHidlTest::SetUp(); // Generate a key. auto ec = GenerateKey(AuthorizationSetBuilder() .Authorization(TAG_NO_AUTH_REQUIRED) .EcdsaSigningKey(EcCurve::P_256) .Digest(Digest::SHA_2_256)); ASSERT_EQ(ec, ErrorCode::OK) << "Failed to generate key."; // Generate attestation. hidl_vec<hidl_vec<uint8_t>> cert_chain; ec = AttestKey(AuthorizationSetBuilder() .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge")) .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")), &cert_chain); ASSERT_EQ(ec, ErrorCode::OK) << "Failed to generate attestation."; X509_Ptr cert(parse_cert_blob(cert_chain[0])); ASSERT_TRUE(cert.get()) << "Failed to parse certificate blob."; ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get()); ASSERT_TRUE(attest_rec) << "Failed to get attestation record."; // Parse root of trust. HidlBuf verified_boot_key; keymaster_verified_boot_t verified_boot_state; bool device_locked; HidlBuf verified_boot_hash; auto result = parse_root_of_trust(attest_rec->data, attest_rec->length, &verified_boot_key, &verified_boot_state, &device_locked, &verified_boot_hash); ASSERT_EQ(result, ErrorCode::OK) << "Failed to parse root of trust."; } hidl_vec<uint8_t> attestedVbKey_; keymaster_verified_boot_t attestedVbState_; bool attestedBootloaderState_; hidl_vec<uint8_t> attestedVbmetaDigest_; }; // Check that attested bootloader state is set to 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_, KM_VERIFIED_BOOT_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_KEYMASTER_HIDL_TEST(BootloaderStateTest); } // namespace android::hardware::keymaster::V4_0::test
keymaster/4.0/vts/functional/KeymasterHidlTest.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -841,6 +841,30 @@ std::vector<Digest> KeymasterHidlTest::InvalidDigests() { return {}; } X509* parse_cert_blob(const hidl_vec<uint8_t>& blob) { const uint8_t* p = blob.data(); return d2i_X509(nullptr, &p, blob.size()); } ASN1_OCTET_STRING* get_attestation_record(X509* certificate) { ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */)); EXPECT_TRUE(!!oid.get()); if (!oid.get()) return nullptr; int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */); EXPECT_NE(-1, location) << "Attestation extension not found in certificate"; if (location == -1) return nullptr; X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location); EXPECT_TRUE(!!attest_rec_ext) << "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug."; if (!attest_rec_ext) return nullptr; ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext); EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data"; return attest_rec; } } // namespace test } // namespace V4_0 } // namespace keymaster Loading
keymaster/4.0/vts/functional/KeymasterHidlTest.h +7 −0 Original line number Diff line number Diff line Loading @@ -22,7 +22,9 @@ #include <hidl/GtestPrinter.h> #include <hidl/ServiceManagement.h> #include <keymasterV4_0/attestation_record.h> #include <keymasterV4_0/authorization_set.h> #include <keymasterV4_0/openssl_utils.h> namespace android { namespace hardware { Loading Loading @@ -241,6 +243,11 @@ class KeymasterHidlTest : public ::testing::TestWithParam<std::string> { testing::ValuesIn(KeymasterHidlTest::build_params()), \ android::hardware::PrintInstanceNameToString) X509* parse_cert_blob(const hidl_vec<uint8_t>& blob); // Extract attestation record from cert. Returned object is still part of cert; don't free it // separately. ASN1_OCTET_STRING* get_attestation_record(X509* certificate); } // namespace test } // namespace V4_0 } // namespace keymaster Loading
keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +0 −26 Original line number Diff line number Diff line Loading @@ -263,11 +263,6 @@ struct RSA_Delete { void operator()(RSA* p) { RSA_free(p); } }; X509* parse_cert_blob(const hidl_vec<uint8_t>& blob) { const uint8_t* p = blob.data(); return d2i_X509(nullptr, &p, blob.size()); } bool verify_chain(const hidl_vec<hidl_vec<uint8_t>>& chain, const std::string& msg, const std::string& signature) { { Loading Loading @@ -337,27 +332,6 @@ bool verify_chain(const hidl_vec<hidl_vec<uint8_t>>& chain, const std::string& m return true; } // Extract attestation record from cert. Returned object is still part of cert; don't free it // separately. ASN1_OCTET_STRING* get_attestation_record(X509* certificate) { ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */)); EXPECT_TRUE(!!oid.get()); if (!oid.get()) return nullptr; int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */); EXPECT_NE(-1, location) << "Attestation extension not found in certificate"; if (location == -1) return nullptr; X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location); EXPECT_TRUE(!!attest_rec_ext) << "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug."; if (!attest_rec_ext) return nullptr; ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext); EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data"; return attest_rec; } bool tag_in_list(const KeyParameter& entry) { // Attestations don't contain everything in key authorization lists, so we need to filter // the key lists to produce the lists that we expect to match the attestations. Loading