| /* |
| * 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. |
| */ |
| |
| #include <android-base/file.h> |
| #include <android-base/properties.h> |
| #include <android-base/strings.h> |
| #include <fs_mgr.h> |
| #include <fstab/fstab.h> |
| #include <gtest/gtest.h> |
| |
| #include <string> |
| |
| #include "utils.h" |
| |
| static bool isExemptFromAVBTests() { |
| int first_api_level = getFirstApiLevel(); |
| int vendor_api_level = getVendorApiLevel(); |
| GTEST_LOG_(INFO) << "First API level is " << first_api_level; |
| GTEST_LOG_(INFO) << "Vendor API level is " << vendor_api_level; |
| if (first_api_level < __ANDROID_API_S__) { |
| GTEST_LOG_(INFO) << "Exempt from avb test due to old starting API level"; |
| return true; |
| } |
| |
| // This feature name check only applies to devices that first shipped with |
| // SC or later. |
| int min_api_level = (first_api_level < vendor_api_level) ? first_api_level : vendor_api_level; |
| if (min_api_level >= __ANDROID_API_S__ && |
| !deviceSupportsFeature("android.hardware.security.model.compatible")) { |
| GTEST_LOG_(INFO) << "Skipping test: FEATURE_SECURITY_MODEL_COMPATIBLE missing."; |
| return true; |
| } |
| return false; |
| } |
| |
| static std::set<std::string> getVerityMountPoints() { |
| std::set<std::string> verity_partitions; |
| |
| android::fs_mgr::Fstab mounted_fstab; |
| if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) { |
| ADD_FAILURE() << "Failed to read the mounted fstab"; |
| return verity_partitions; |
| } |
| |
| // Build a list of mount points that are either mounted or known to have |
| // importance. |
| std::set<std::string> mount_points = {"/", "/system"}; |
| for (const auto& entry : mounted_fstab) { |
| mount_points.insert(entry.mount_point); |
| } |
| android::fs_mgr::Fstab fstab; |
| if (!ReadDefaultFstab(&fstab)) { |
| ADD_FAILURE() << "Failed to read default fstab"; |
| return verity_partitions; |
| } |
| |
| for (const auto& entry : fstab) { |
| if (!entry.fs_mgr_flags.avb) { |
| continue; |
| } |
| |
| if (mount_points.find(entry.mount_point) == mount_points.end()) { |
| GTEST_LOG_(INFO) << entry.mount_point << " isn't mounted, skipping"; |
| continue; |
| } |
| |
| if (mount_points.find(entry.mount_point) == mount_points.end()) { |
| GTEST_LOG_(INFO) << entry.mount_point << " isn't mounted, skipping"; |
| continue; |
| } |
| |
| if (android::base::EqualsIgnoreCase(entry.fs_type, "emmc")) { |
| GTEST_LOG_(INFO) << entry.mount_point << " has emmc fs_type, skipping"; |
| continue; |
| } |
| |
| GTEST_LOG_(INFO) << "partition enabled verity " << entry.mount_point; |
| verity_partitions.insert(android::base::Basename(entry.mount_point)); |
| } |
| return verity_partitions; |
| } |
| |
| // As required by CDD, verified boot MUST use verification algorithms as strong |
| // as current recommendations from NIST for hashing algorithms (SHA-256). |
| // @CddTest = 9.10/C-1-5 |
| TEST(VerifiedBootTest, avbHashtreeNotUsingSha1) { |
| GTEST_SKIP() << "Skipping due to broken test. See b/264937051"; |
| if (isExemptFromAVBTests()) { |
| GTEST_SKIP(); |
| } |
| |
| auto verity_mount_points = getVerityMountPoints(); |
| for (const auto& mount_point : verity_mount_points) { |
| // The verity sysprop use "system" as the partition name in the system as |
| // root case. |
| std::string partition = mount_point == "/" ? "system" : mount_point; |
| std::string alg_prop_name = "partition." + partition + ".verified.hash_alg"; |
| std::string hash_alg = android::base::GetProperty(alg_prop_name, ""); |
| ASSERT_FALSE(hash_alg.empty()); |
| ASSERT_FALSE(android::base::StartsWithIgnoreCase(hash_alg, "sha1")); |
| } |
| } |
| |
| // Ensure that protected partitions are being verified every time they are read |
| // from, rather than once per boot. |
| // @CddTest = 9.10/C-1-7 |
| TEST(VerifiedBootTest, avbNotUsingCheckAtMostOnce) { |
| if (isExemptFromAVBTests()) { |
| GTEST_SKIP(); |
| } |
| if (getFirstApiLevel() < __ANDROID_API_U__) { |
| GTEST_SKIP() << "Skipping test: Exempt due to old API level"; |
| } |
| |
| // Any device with sufficient RAM or a 64-bit CPU is not allowed to use |
| // check_at_most_once. |
| // |
| // Sufficiently performance limited devices are allowed to use it out of necessity. |
| if (android::base::GetBoolProperty("ro.config.low_ram", false) && |
| android::base::GetProperty("ro.product.cpu.abilist64", "").empty()) |
| GTEST_SKIP() |
| << "Skipping test: Device is performance constrained (low ram or 32-bit)"; |
| |
| auto verity_mount_points = getVerityMountPoints(); |
| for (const auto& mount_point : verity_mount_points) { |
| // The verity sysprop use "system" as the partition name in the system as |
| // root case. |
| std::string partition = mount_point == "/" ? "system" : mount_point; |
| std::string prop_name = "partition." + partition + ".verified.check_at_most_once"; |
| ASSERT_FALSE(android::base::GetBoolProperty(prop_name, false)); |
| } |
| } |