1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <endian.h>
18 #include <stdlib.h>
19 
20 #include <android-base/file.h>
21 #include <base/files/file_util.h>
22 #include <base/strings/string_util.h>
23 #include <fs_avb/fs_avb.h>
24 #include <libavb/libavb.h>
25 
26 #include "fs_avb_test_util.h"
27 
28 // Target classes or functions to test:
29 using android::fs_mgr::AvbHandle;
30 using android::fs_mgr::AvbHandleStatus;
31 using android::fs_mgr::HashAlgorithm;
32 
33 namespace fs_avb_host_test {
34 
35 class PublicFsAvbTest : public BaseFsAvbTest {
36   public:
PublicFsAvbTest()37     PublicFsAvbTest(){};
38 
39   protected:
~PublicFsAvbTest()40     ~PublicFsAvbTest(){};
41     // Modifies |flags| field in the vbmeta header in an Avb image.
42     // e.g., AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED.
43     void ModifyVBMetaHeaderFlags(const base::FilePath& vbmeta_image_path, uint32_t flags);
44 };
45 
ModifyVBMetaHeaderFlags(const base::FilePath & vbmeta_image_path,uint32_t flags)46 void PublicFsAvbTest::ModifyVBMetaHeaderFlags(const base::FilePath& vbmeta_image_path,
47                                               uint32_t flags) {
48     if (!base::PathExists(vbmeta_image_path)) return;
49 
50     // Only support modifying the flags in vbmeta*.img.
51     std::string image_file_name = vbmeta_image_path.RemoveExtension().BaseName().value();
52     ASSERT_TRUE(base::StartsWith(image_file_name, "vbmeta", base::CompareCase::INSENSITIVE_ASCII));
53 
54     android::base::unique_fd fd(open(vbmeta_image_path.value().c_str(), O_RDWR | O_CLOEXEC));
55     EXPECT_TRUE(fd > 0);
56 
57     auto flags_offset = offsetof(AvbVBMetaImageHeader, flags);
58     uint32_t flags_data = htobe32(flags);
59     EXPECT_EQ(flags_offset, lseek64(fd, flags_offset, SEEK_SET));
60     EXPECT_EQ(sizeof flags_data, write(fd, &flags_data, sizeof flags_data));
61 }
62 
TEST_F(PublicFsAvbTest,LoadAndVerifyVbmeta)63 TEST_F(PublicFsAvbTest, LoadAndVerifyVbmeta) {
64     // Generates a raw boot.img
65     const size_t boot_image_size = 5 * 1024 * 1024;
66     const size_t boot_partition_size = 10 * 1024 * 1024;
67     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
68 
69     // Adds AVB Hash Footer.
70     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
71                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
72                  "--internal_release_string \"unit test\"");
73 
74     // Generates a raw system.img, use a smaller size to speed-up unit test.
75     const size_t system_image_size = 10 * 1024 * 1024;
76     const size_t system_partition_size = 15 * 1024 * 1024;
77     base::FilePath system_path = GenerateImage("system.img", system_image_size);
78     // Adds AVB Hashtree Footer.
79     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
80                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
81                  "--internal_release_string \"unit test\"");
82 
83     // Generates chain partition descriptors.
84     base::FilePath rsa2048_public_key =
85             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
86     base::FilePath rsa4096_public_key =
87             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
88 
89     // Makes a vbmeta image includeing 'boot' and 'system' chained descriptors.
90     auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
91                                            data_dir_.Append("testkey_rsa8192.pem"),
92                                            {}, /* include_descriptor_image_paths */
93                                            {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
94                                             {"system", 2, rsa4096_public_key}},
95                                            "--internal_release_string \"unit test\"");
96 
97     // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
98     EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
99               CalcVBMetaDigest("vbmeta.img", "sha256"));
100 
101     // Invokes the public API from fs_avb.h.
102     auto vbmeta_image_path = [this](const std::string& partition_name) {
103         return test_dir_.Append(partition_name + ".img").value();
104     };
105     auto avb_handle = AvbHandle::LoadAndVerifyVbmeta(
106             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
107             "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
108             false /* allow_verification_error */, true /* load_chained_vbmeta */,
109             true /* rollback_protection */, vbmeta_image_path);
110     EXPECT_NE(nullptr, avb_handle);
111     EXPECT_EQ(AvbHandleStatus::kSuccess, avb_handle->status());
112 
113     // Checks the summary info for all vbmeta images.
114     // Checks the digest matches the value calculated by CalcVBMetaDigest().
115     EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
116               avb_handle->vbmeta_info().digest);
117     EXPECT_EQ(8576UL, avb_handle->vbmeta_info().total_size);
118     EXPECT_EQ(HashAlgorithm::kSHA256, avb_handle->vbmeta_info().hash_algorithm);
119 
120     // Skip loading chained vbmeta.
121     avb_handle = AvbHandle::LoadAndVerifyVbmeta(
122             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
123             "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
124             false /* allow_verification_error */, false /* load_chained_vbmeta */,
125             true /* rollback_protection */, vbmeta_image_path);
126     EXPECT_NE(nullptr, avb_handle);
127     EXPECT_EQ(AvbHandleStatus::kSuccess, avb_handle->status());
128     EXPECT_EQ("5c31197992b3c72a854ec7dc0eb9609ffebcffab7917ffd381a99ecee328f09c",
129               avb_handle->vbmeta_info().digest);
130     EXPECT_EQ(5184UL, avb_handle->vbmeta_info().total_size);
131     EXPECT_EQ(HashAlgorithm::kSHA256, avb_handle->vbmeta_info().hash_algorithm);
132 }
133 
TEST_F(PublicFsAvbTest,LoadAndVerifyVbmetaWithModifications)134 TEST_F(PublicFsAvbTest, LoadAndVerifyVbmetaWithModifications) {
135     // Generates a raw boot.img
136     const size_t boot_image_size = 5 * 1024 * 1024;
137     const size_t boot_partition_size = 10 * 1024 * 1024;
138     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
139 
140     // Adds AVB Hash Footer.
141     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
142                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
143                  "--internal_release_string \"unit test\"");
144 
145     // Generates a raw system.img, use a smaller size to speed-up unit test.
146     const size_t system_image_size = 10 * 1024 * 1024;
147     const size_t system_partition_size = 15 * 1024 * 1024;
148     base::FilePath system_path = GenerateImage("system.img", system_image_size);
149     // Adds AVB Hashtree Footer.
150     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
151                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
152                  "--internal_release_string \"unit test\"");
153 
154     // Generates chain partition descriptors.
155     base::FilePath rsa2048_public_key =
156             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
157     base::FilePath rsa4096_public_key =
158             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
159 
160     // Makes a vbmeta image includeing 'boot' and 'system' chained descriptors.
161     auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
162                                            data_dir_.Append("testkey_rsa8192.pem"),
163                                            {}, /* include_descriptor_image_paths */
164                                            {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
165                                             {"system", 2, rsa4096_public_key}},
166                                            "--internal_release_string \"unit test\"");
167 
168     // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
169     EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
170               CalcVBMetaDigest("vbmeta.img", "sha256"));
171 
172     // Sets AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED in the vbmeta.img.
173     ModifyVBMetaHeaderFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
174 
175     auto vbmeta_image_path = [this](const std::string& partition_name) {
176         return test_dir_.Append(partition_name + ".img").value();
177     };
178     auto avb_handle = AvbHandle::LoadAndVerifyVbmeta(
179             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
180             "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
181             false /* allow_verification_error */, true /* load_chained_vbmeta */,
182             true /* rollback_protection */, vbmeta_image_path);
183     // Returns a null handler because allow_verification is not True.
184     EXPECT_EQ(nullptr, avb_handle);
185 
186     // Try again with allow_verification_error set to true.
187     avb_handle = AvbHandle::LoadAndVerifyVbmeta(
188             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
189             "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
190             true /* allow_verification_error */, true /* load_chained_vbmeta */,
191             true /* rollback_protection */, vbmeta_image_path);
192     EXPECT_NE(nullptr, avb_handle);
193     EXPECT_EQ(AvbHandleStatus::kHashtreeDisabled, avb_handle->status());
194 
195     // Checks the summary info for all vbmeta images.
196     // Checks the digest matches the value calculated by CalcVBMetaDigest().
197     EXPECT_EQ("ae8f7ad95cbb7ce4f0feeeedc2a0a39824af5cd29dad4d028597cab4b8c2e83c",
198               CalcVBMetaDigest("vbmeta.img", "sha256"));
199     EXPECT_EQ("ae8f7ad95cbb7ce4f0feeeedc2a0a39824af5cd29dad4d028597cab4b8c2e83c",
200               avb_handle->vbmeta_info().digest);
201     EXPECT_EQ(8576UL, avb_handle->vbmeta_info().total_size);
202     EXPECT_EQ(HashAlgorithm::kSHA256, avb_handle->vbmeta_info().hash_algorithm);
203 
204     // Sets AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED in the vbmeta.img.
205     ModifyVBMetaHeaderFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
206     // Loads the vbmeta with allow_verification_error set to true.
207     avb_handle = AvbHandle::LoadAndVerifyVbmeta(
208             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
209             "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
210             true /* allow_verification_error */, true /* load_chained_vbmeta */,
211             true /* rollback_protection */, vbmeta_image_path);
212     EXPECT_NE(nullptr, avb_handle);
213     EXPECT_EQ(AvbHandleStatus::kVerificationDisabled, avb_handle->status());
214     // Only the top-level vbmeta.img is loaded, when VERIFICATION_DISABLED is set.
215     // However, CalcVBMetaDigest() reads all vbmeta structs to calculate the digest,
216     // including vbmeta.img, boot.img and syste.img. So we don't compare the digest here.
217     EXPECT_EQ(5184UL, avb_handle->vbmeta_info().total_size);
218 
219     // Sets a unknown flag in the vbmeta.imgm and expects to get
220     // AvbHandleStatus::kVerificationError.
221     ModifyVBMetaHeaderFlags(vbmeta_path, 0x10000000);
222     // Loads the vbmeta with allow_verification_error set to true.
223     avb_handle = AvbHandle::LoadAndVerifyVbmeta(
224             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
225             "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
226             true /* allow_verification_error */, true /* load_chained_vbmeta */,
227             true /* rollback_protection */, vbmeta_image_path);
228     EXPECT_NE(nullptr, avb_handle);
229     EXPECT_EQ(AvbHandleStatus::kVerificationError, avb_handle->status());
230     // Checks the digest matches the value calculated by CalcVBMetaDigest().
231     EXPECT_EQ("8fb99c4f54500053c3582df5eaf04e9a533137398879188aad9968ec19a664f1",
232               CalcVBMetaDigest("vbmeta.img", "sha256"));
233     EXPECT_EQ("8fb99c4f54500053c3582df5eaf04e9a533137398879188aad9968ec19a664f1",
234               avb_handle->vbmeta_info().digest);
235     EXPECT_EQ(8576UL, avb_handle->vbmeta_info().total_size);
236     EXPECT_EQ(HashAlgorithm::kSHA256, avb_handle->vbmeta_info().hash_algorithm);
237 }
238 
TEST_F(PublicFsAvbTest,LoadAndVerifyVbmetaWithPublicKeys)239 TEST_F(PublicFsAvbTest, LoadAndVerifyVbmetaWithPublicKeys) {
240     // Generates a raw boot.img
241     const size_t boot_image_size = 5 * 1024 * 1024;
242     const size_t boot_partition_size = 10 * 1024 * 1024;
243     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
244 
245     // Adds AVB Hash Footer.
246     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
247                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
248                  "--internal_release_string \"unit test\"");
249 
250     // Generates a raw system.img, use a smaller size to speed-up unit test.
251     const size_t system_image_size = 10 * 1024 * 1024;
252     const size_t system_partition_size = 15 * 1024 * 1024;
253     base::FilePath system_path = GenerateImage("system.img", system_image_size);
254     // Adds AVB Hashtree Footer.
255     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
256                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
257                  "--internal_release_string \"unit test\"");
258 
259     // Generates chain partition descriptors.
260     base::FilePath rsa2048_public_key =
261             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
262     base::FilePath rsa4096_public_key =
263             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
264     base::FilePath rsa8192_public_key =
265             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa8192.pem"));
266 
267     // Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
268     auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
269                                            data_dir_.Append("testkey_rsa8192.pem"),
270                                            {}, /* include_descriptor_image_paths */
271                                            {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
272                                             {"system", 2, rsa4096_public_key}},
273                                            "--internal_release_string \"unit test\"");
274 
275     auto vbmeta_image_path = [this](const std::string& partition_name) {
276         return test_dir_.Append(partition_name + ".img").value();
277     };
278     std::vector<VBMetaData> vbmeta_images;
279     // Uses the correct expected public key.
280     auto avb_handle = AvbHandle::LoadAndVerifyVbmeta(
281             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
282             rsa8192_public_key.value(), HashAlgorithm::kSHA256, true /* allow_verification_error */,
283             true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path);
284     EXPECT_NE(nullptr, avb_handle);
285     EXPECT_EQ(AvbHandleStatus::kSuccess, avb_handle->status());
286 
287     // Uses a non-existed public key.
288     avb_handle = AvbHandle::LoadAndVerifyVbmeta(
289             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
290             "/path/to/non-existed/key", HashAlgorithm::kSHA256, true /* allow_verification_error */,
291             true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path);
292     EXPECT_EQ(nullptr, avb_handle);
293 
294     // Uses an incorrect public key, with allow_verification_error false.
295     avb_handle = AvbHandle::LoadAndVerifyVbmeta(
296             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
297             rsa4096_public_key.value(), HashAlgorithm::kSHA256,
298             false /* allow_verification_error */, true /* load_chained_vbmeta */,
299             true /* rollback_protection */, vbmeta_image_path);
300     EXPECT_EQ(nullptr, avb_handle);
301 
302     // Uses an incorrect public key, with allow_verification_error true.
303     avb_handle = AvbHandle::LoadAndVerifyVbmeta(
304             "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
305             rsa4096_public_key.value(), HashAlgorithm::kSHA256, true /* allow_verification_error */,
306             true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path);
307     EXPECT_NE(nullptr, avb_handle);
308     EXPECT_EQ(AvbHandleStatus::kVerificationError, avb_handle->status());
309 }
310 
311 }  // namespace fs_avb_host_test
312