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 
19 #include <android-base/unique_fd.h>
20 #include <base/files/file_util.h>
21 #include <base/rand_util.h>
22 #include <base/strings/string_util.h>
23 #include <libavb/libavb.h>
24 
25 #include "avb_util.h"
26 #include "fs_avb_test_util.h"
27 
28 // Target classes or functions to test:
29 using android::fs_mgr::AvbPartitionToDevicePatition;
30 using android::fs_mgr::DeriveAvbPartitionName;
31 using android::fs_mgr::FstabEntry;
32 using android::fs_mgr::GetAvbFooter;
33 using android::fs_mgr::GetAvbPropertyDescriptor;
34 using android::fs_mgr::GetChainPartitionInfo;
35 using android::fs_mgr::GetTotalSize;
36 using android::fs_mgr::LoadAndVerifyVbmetaByPartition;
37 using android::fs_mgr::LoadAndVerifyVbmetaByPath;
38 using android::fs_mgr::ValidatePublicKeyBlob;
39 using android::fs_mgr::VBMetaData;
40 using android::fs_mgr::VBMetaVerifyResult;
41 using android::fs_mgr::VerifyVBMetaData;
42 using android::fs_mgr::VerifyVBMetaSignature;
43 
44 namespace fs_avb_host_test {
45 
46 class AvbUtilTest : public BaseFsAvbTest {
47   public:
AvbUtilTest()48     AvbUtilTest(){};
49 
50   protected:
~AvbUtilTest()51     ~AvbUtilTest(){};
52     // Helper function for VerifyVBMetaSignature test. Modifies vbmeta.data()
53     // in a number of places at |offset| of size |length| and checks that
54     // VerifyVBMetaSignature() returns |expected_result|.
55     bool TestVBMetaModification(VBMetaVerifyResult expected_result, const VBMetaData& vbmeta,
56                                 size_t offset, size_t length);
57     // Modifies a random bit for a file, in the range of [offset, offset + length - 1].
58     void ModifyFile(const base::FilePath& file_path, size_t offset, ssize_t length);
59 
60     // Loads the content of avb_image_path and comparies it with the content of vbmeta.
61     bool CompareVBMeta(const base::FilePath& avb_image_path, const VBMetaData& expected_vbmeta);
62 
63     // Sets the flas in vbmeta header, the image_path could be a vbmeta.img or a system.img.
64     void SetVBMetaFlags(const base::FilePath& image_path, uint32_t flags);
65 };
66 
SetVBMetaFlags(const base::FilePath & image_path,uint32_t flags)67 void AvbUtilTest::SetVBMetaFlags(const base::FilePath& image_path, uint32_t flags) {
68     if (!base::PathExists(image_path)) return;
69 
70     std::string image_file_name = image_path.RemoveExtension().BaseName().value();
71     bool is_vbmeta_partition =
72         base::StartsWith(image_file_name, "vbmeta", base::CompareCase::INSENSITIVE_ASCII);
73 
74     android::base::unique_fd fd(open(image_path.value().c_str(), O_RDWR | O_CLOEXEC));
75     EXPECT_TRUE(fd > 0);
76 
77     uint64_t vbmeta_offset = 0;  // for vbmeta.img
78     if (!is_vbmeta_partition) {
79         std::unique_ptr<AvbFooter> footer = GetAvbFooter(fd);
80         EXPECT_NE(nullptr, footer);
81         vbmeta_offset = footer->vbmeta_offset;
82     }
83 
84     auto flags_offset = vbmeta_offset + offsetof(AvbVBMetaImageHeader, flags);
85     uint32_t flags_data = htobe32(flags);
86     EXPECT_EQ(flags_offset, lseek64(fd, flags_offset, SEEK_SET));
87     EXPECT_EQ(sizeof flags_data, write(fd, &flags_data, sizeof flags_data));
88 }
89 
TEST_F(AvbUtilTest,AvbPartitionToDevicePatition)90 TEST_F(AvbUtilTest, AvbPartitionToDevicePatition) {
91     EXPECT_EQ("system", AvbPartitionToDevicePatition("system", "", ""));
92     EXPECT_EQ("system", AvbPartitionToDevicePatition("system", "", "_b"));
93 
94     EXPECT_EQ("system_a", AvbPartitionToDevicePatition("system", "_a", ""));
95     EXPECT_EQ("system_a", AvbPartitionToDevicePatition("system", "_a", "_b"));
96 
97     EXPECT_EQ("system_b", AvbPartitionToDevicePatition("system_other", "", "_b"));
98     EXPECT_EQ("system_b", AvbPartitionToDevicePatition("system_other", "_a", "_b"));
99 }
100 
TEST_F(AvbUtilTest,DeriveAvbPartitionName)101 TEST_F(AvbUtilTest, DeriveAvbPartitionName) {
102     // The fstab_entry to test.
103     FstabEntry fstab_entry = {
104             .blk_device = "/dev/block/dm-1",  // a dm-linear device (logical)
105             .logical_partition_name = "system",
106             .mount_point = "/system",
107             .fs_type = "ext4",
108     };
109 
110     // Logical partitions.
111     // non-A/B
112     fstab_entry.fs_mgr_flags.logical = true;
113     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_dont_care"));
114     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
115     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "", ""));
116     // Active slot.
117     fstab_entry.fs_mgr_flags.slot_select = true;
118     fstab_entry.logical_partition_name = "system_a";
119     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_dont_care"));
120     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
121     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", ""));
122     EXPECT_EQ("system_a", DeriveAvbPartitionName(fstab_entry, "_wont_erase_a", "_dont_care"));
123     // The other slot.
124     fstab_entry.fs_mgr_flags.slot_select = false;
125     fstab_entry.fs_mgr_flags.slot_select_other = true;
126     fstab_entry.logical_partition_name = "system_b";
127     EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_b"));
128     EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
129     EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "", "_b"));
130     EXPECT_EQ("system_b_other", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_wont_erase_b"));
131 
132     // Non-logical partitions.
133     // non-A/B.
134     fstab_entry.fs_mgr_flags.logical = false;
135     fstab_entry.fs_mgr_flags.slot_select = false;
136     fstab_entry.fs_mgr_flags.slot_select_other = false;
137     fstab_entry.blk_device = "/dev/block/by-name/system";
138     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_dont_care"));
139     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
140     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "", ""));
141     // Active slot _a.
142     fstab_entry.fs_mgr_flags.slot_select = true;
143     fstab_entry.blk_device = "/dev/block/by-name/system_a";
144     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_dont_care"));
145     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
146     EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", ""));
147     EXPECT_EQ("system_a", DeriveAvbPartitionName(fstab_entry, "_wont_erase_a", "_dont_care"));
148     // Inactive slot _b.
149     fstab_entry.fs_mgr_flags.slot_select = false;
150     fstab_entry.fs_mgr_flags.slot_select_other = true;
151     fstab_entry.blk_device = "/dev/block/by-name/system_b";
152     EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "dont_care", "_b"));
153     EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
154     EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "", "_b"));
155     EXPECT_EQ("system_b_other", DeriveAvbPartitionName(fstab_entry, "dont_care", "_wont_erase_b"));
156 }
157 
TEST_F(AvbUtilTest,GetFdTotalSize)158 TEST_F(AvbUtilTest, GetFdTotalSize) {
159     // Generates a raw test.img via BaseFsAvbTest.
160     const size_t image_size = 5 * 1024 * 1024;
161     base::FilePath image_path = GenerateImage("test.img", image_size);
162 
163     // Checks file size is as expected via base::GetFileSize().
164     int64_t file_size;
165     ASSERT_TRUE(base::GetFileSize(image_path, &file_size));
166     EXPECT_EQ(image_size, file_size);
167 
168     // Checks file size is expected via libfs_avb internal utils.
169     auto fd = OpenUniqueReadFd(image_path);
170     EXPECT_EQ(image_size, GetTotalSize(fd));
171 }
172 
TEST_F(AvbUtilTest,GetFdTotalSizeWithOffset)173 TEST_F(AvbUtilTest, GetFdTotalSizeWithOffset) {
174     // Generates a raw test.img via BaseFsAvbTest.
175     const size_t image_size = 10 * 1024 * 1024;
176     base::FilePath image_path = GenerateImage("test.img", image_size);
177 
178     // Checks file size is expected even with a non-zero offset at the beginning.
179     auto fd = OpenUniqueReadFd(image_path);
180     off_t initial_offset = 2019;
181     EXPECT_EQ(initial_offset, lseek(fd, initial_offset, SEEK_SET));
182     EXPECT_EQ(image_size, GetTotalSize(fd));            // checks that total size is still returned.
183     EXPECT_EQ(initial_offset, lseek(fd, 0, SEEK_CUR));  // checks original offset is restored.
184 }
185 
TEST_F(AvbUtilTest,GetAvbFooter)186 TEST_F(AvbUtilTest, GetAvbFooter) {
187     // Generates a raw system.img
188     const size_t image_size = 10 * 1024 * 1024;
189     const size_t partition_size = 15 * 1024 * 1024;
190     base::FilePath system_path = GenerateImage("system.img", image_size);
191     EXPECT_NE(0U, system_path.value().size());
192 
193     // Checks image size is as expected.
194     int64_t file_size;
195     ASSERT_TRUE(base::GetFileSize(system_path, &file_size));
196     EXPECT_EQ(image_size, file_size);
197 
198     // Appends AVB Hashtree Footer.
199     AddAvbFooter(system_path, "hashtree", "system", partition_size, "SHA512_RSA8192", 20,
200                  data_dir_.Append("testkey_rsa8192.pem"), "d00df00d",
201                  "--internal_release_string \"unit test\"");
202 
203     // Checks partition size is as expected, after adding footer.
204     ASSERT_TRUE(base::GetFileSize(system_path, &file_size));
205     EXPECT_EQ(partition_size, file_size);
206 
207     // Checks avb footer and avb vbmeta.
208     EXPECT_EQ(
209             "Footer version:           1.0\n"
210             "Image size:               15728640 bytes\n"
211             "Original image size:      10485760 bytes\n"
212             "VBMeta offset:            10661888\n"
213             "VBMeta size:              3648 bytes\n"
214             "--\n"
215             "Minimum libavb version:   1.0\n"
216             "Header Block:             256 bytes\n"
217             "Authentication Block:     1088 bytes\n"
218             "Auxiliary Block:          2304 bytes\n"
219             "Algorithm:                SHA512_RSA8192\n"
220             "Rollback Index:           20\n"
221             "Flags:                    0\n"
222             "Release String:           'unit test'\n"
223             "Descriptors:\n"
224             "    Hashtree descriptor:\n"
225             "      Version of dm-verity:  1\n"
226             "      Image Size:            10485760 bytes\n"
227             "      Tree Offset:           10485760\n"
228             "      Tree Size:             86016 bytes\n"
229             "      Data Block Size:       4096 bytes\n"
230             "      Hash Block Size:       4096 bytes\n"
231             "      FEC num roots:         2\n"
232             "      FEC offset:            10571776\n"
233             "      FEC size:              90112 bytes\n"
234             "      Hash Algorithm:        sha1\n"
235             "      Partition Name:        system\n"
236             "      Salt:                  d00df00d\n"
237             "      Root Digest:           a3d5dd307341393d85de356c384ff543ec1ed81b\n"
238             "      Flags:                 0\n",
239             InfoImage(system_path));
240 
241     // Checks each field from GetAvbFooter(fd).
242     auto fd = OpenUniqueReadFd(system_path);
243     auto footer = GetAvbFooter(fd);
244     EXPECT_NE(nullptr, footer);
245     EXPECT_EQ(10485760, footer->original_image_size);
246     EXPECT_EQ(10661888, footer->vbmeta_offset);
247     EXPECT_EQ(3648, footer->vbmeta_size);
248 }
249 
TEST_F(AvbUtilTest,GetAvbFooterErrorVerification)250 TEST_F(AvbUtilTest, GetAvbFooterErrorVerification) {
251     // Generates a raw system.img
252     const size_t image_size = 5 * 1024 * 1024;
253     base::FilePath system_path = GenerateImage("system.img", image_size);
254 
255     // Checks each field from GetAvbFooter(fd).
256     auto fd = OpenUniqueReadFd(system_path);
257     auto footer = GetAvbFooter(fd);
258     EXPECT_EQ(nullptr, footer);
259 }
260 
TEST_F(AvbUtilTest,GetAvbFooterInsufficientSize)261 TEST_F(AvbUtilTest, GetAvbFooterInsufficientSize) {
262     // Generates a raw system.img
263     const size_t image_size = AVB_FOOTER_SIZE - 10;
264     base::FilePath system_path = GenerateImage("system.img", image_size);
265 
266     // Checks each field from GetAvbFooter(fd).
267     auto fd = OpenUniqueReadFd(system_path);
268     auto footer = GetAvbFooter(fd);
269     EXPECT_EQ(nullptr, footer);
270 }
271 
TEST_F(AvbUtilTest,GetAvbPropertyDescriptor_Basic)272 TEST_F(AvbUtilTest, GetAvbPropertyDescriptor_Basic) {
273     // Makes a vbmeta.img with some properties.
274     GenerateVBMetaImage("vbmeta.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
275                         {}, /* include_descriptor_image_paths */
276                         {}, /* chain_partitions */
277                         "--prop foo:android "
278                         "--prop bar:treble "
279                         "--internal_release_string \"unit test\" ");
280     auto vbmeta = LoadVBMetaData("vbmeta.img");
281 
282     // Puts the vbmeta into a vector, for GetAvbPropertyDescriptor to use.
283     std::vector<VBMetaData> vbmeta_images;
284     vbmeta_images.emplace_back(std::move(vbmeta));
285 
286     EXPECT_EQ("android", GetAvbPropertyDescriptor("foo", vbmeta_images));
287     EXPECT_EQ("treble", GetAvbPropertyDescriptor("bar", vbmeta_images));
288     EXPECT_EQ("", GetAvbPropertyDescriptor("non-existent", vbmeta_images));
289 }
290 
TEST_F(AvbUtilTest,GetAvbPropertyDescriptor_SecurityPatchLevel)291 TEST_F(AvbUtilTest, GetAvbPropertyDescriptor_SecurityPatchLevel) {
292     // Generates a raw boot.img
293     const size_t boot_image_size = 5 * 1024 * 1024;
294     const size_t boot_partition_size = 10 * 1024 * 1024;
295     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
296     // Adds AVB Hash Footer.
297     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
298                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
299                  "--internal_release_string \"unit test\"");
300 
301     // Generates a raw system.img, use a smaller size to speed-up unit test.
302     const size_t system_image_size = 10 * 1024 * 1024;
303     const size_t system_partition_size = 15 * 1024 * 1024;
304     base::FilePath system_path = GenerateImage("system.img", system_image_size);
305     // Adds AVB Hashtree Footer.
306     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
307                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
308                  "--prop com.android.build.system.security_patch:2019-04-05 "
309                  "--internal_release_string \"unit test\"");
310 
311     // Generates chain partition descriptors.
312     base::FilePath rsa4096_public_key =
313             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
314 
315     // Makes a vbmeta.img including the 'system' chained descriptor.
316     GenerateVBMetaImage("vbmeta.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
317                         {boot_path},                         /* include_descriptor_image_paths */
318                         {{"system", 3, rsa4096_public_key}}, /* chain_partitions */
319                         "--internal_release_string \"unit test\"");
320 
321     auto vbmeta = LoadVBMetaData("vbmeta.img");
322     auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system-vbmeta.img");
323 
324     // Puts the vbmeta into a vector, for GetAvbPropertyDescriptor to use.
325     std::vector<VBMetaData> vbmeta_images;
326     vbmeta_images.emplace_back(std::move(vbmeta));
327     vbmeta_images.emplace_back(std::move(system_vbmeta));
328 
329     EXPECT_EQ("2019-04-05",
330               GetAvbPropertyDescriptor("com.android.build.system.security_patch", vbmeta_images));
331 }
332 
TEST_F(AvbUtilTest,GetVBMetaHeader)333 TEST_F(AvbUtilTest, GetVBMetaHeader) {
334     // Generates a raw boot.img
335     const size_t image_size = 5 * 1024 * 1024;
336     const size_t partition_size = 10 * 1024 * 1024;
337     base::FilePath boot_path = GenerateImage("boot.img", image_size);
338     // Appends AVB Hash Footer.
339     AddAvbFooter(boot_path, "hash", "boot", partition_size, "SHA256_RSA4096", 10,
340                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
341                  "--internal_release_string \"unit test\"");
342     // Extracts boot vbmeta from boot.img into boot-vbmeta.img.
343     base::FilePath boot_vbmeta = ExtractVBMetaImage(boot_path, "boot-vbmeta.img");
344     EXPECT_EQ(
345             "Minimum libavb version:   1.0\n"
346             "Header Block:             256 bytes\n"
347             "Authentication Block:     576 bytes\n"
348             "Auxiliary Block:          1216 bytes\n"
349             "Algorithm:                SHA256_RSA4096\n"
350             "Rollback Index:           10\n"
351             "Flags:                    0\n"
352             "Release String:           'unit test'\n"
353             "Descriptors:\n"
354             "    Hash descriptor:\n"
355             "      Image Size:            5242880 bytes\n"
356             "      Hash Algorithm:        sha256\n"
357             "      Partition Name:        boot\n"
358             "      Salt:                  d00df00d\n"
359             "      Digest:                "
360             "222dd01e98284a1fcd7781f85d1392e43a530511a64eff96db197db90ebc4df1\n"
361             "      Flags:                 0\n",
362             InfoImage("boot-vbmeta.img"));
363 
364     // Creates a VBMetaData with the content from boot-vbmeta.img.
365     std::string content;
366     EXPECT_TRUE(base::ReadFileToString(boot_vbmeta, &content));
367     VBMetaData vbmeta((uint8_t*)content.data(), content.size(), "boot-vbmeta");
368     EXPECT_EQ(content.size(), vbmeta.size());
369 
370     // Checks each field returned from GetVBMetaHeader().
371     auto vbmeta_header = vbmeta.GetVBMetaHeader(false /* update_vbmeta_size */);
372     EXPECT_NE(nullptr, vbmeta_header);
373     EXPECT_EQ(576, vbmeta_header->authentication_data_block_size);
374     EXPECT_EQ(1216, vbmeta_header->auxiliary_data_block_size);
375     EXPECT_EQ(AVB_ALGORITHM_TYPE_SHA256_RSA4096, vbmeta_header->algorithm_type);
376     EXPECT_EQ(0, vbmeta_header->hash_offset);
377     EXPECT_EQ(32, vbmeta_header->hash_size);
378     EXPECT_EQ(32, vbmeta_header->signature_offset);
379     EXPECT_EQ(512, vbmeta_header->signature_size);
380     EXPECT_EQ(176, vbmeta_header->public_key_offset);
381     EXPECT_EQ(1032, vbmeta_header->public_key_size);
382     EXPECT_EQ(0, vbmeta_header->descriptors_offset);
383     EXPECT_EQ(176, vbmeta_header->descriptors_size);
384     EXPECT_EQ(10, vbmeta_header->rollback_index);
385     EXPECT_EQ(0, vbmeta_header->flags);
386     EXPECT_EQ("unit test", std::string((const char*)vbmeta_header->release_string));
387 
388     // Appends some garbage to the end of the vbmeta buffer, checks it still can work.
389     std::string padding(2020, 'A');  // Generate a padding with length 2020.
390     std::string content_padding = content + padding;
391     VBMetaData vbmeta_padding((const uint8_t*)content_padding.data(), content_padding.size(),
392                               "boot");
393     EXPECT_EQ(content_padding.size(), vbmeta_padding.size());
394 
395     // Checks each field still can be parsed properly, even with garbage padding.
396     vbmeta_header = vbmeta_padding.GetVBMetaHeader(false /* update_vbmeta_size */);
397     EXPECT_NE(nullptr, vbmeta_header);
398     EXPECT_EQ(576, vbmeta_header->authentication_data_block_size);
399     EXPECT_EQ(1216, vbmeta_header->auxiliary_data_block_size);
400     EXPECT_EQ(AVB_ALGORITHM_TYPE_SHA256_RSA4096, vbmeta_header->algorithm_type);
401     EXPECT_EQ(0, vbmeta_header->hash_offset);
402     EXPECT_EQ(32, vbmeta_header->hash_size);
403     EXPECT_EQ(32, vbmeta_header->signature_offset);
404     EXPECT_EQ(512, vbmeta_header->signature_size);
405     EXPECT_EQ(176, vbmeta_header->public_key_offset);
406     EXPECT_EQ(1032, vbmeta_header->public_key_size);
407     EXPECT_EQ(0, vbmeta_header->descriptors_offset);
408     EXPECT_EQ(176, vbmeta_header->descriptors_size);
409     EXPECT_EQ(10, vbmeta_header->rollback_index);
410     EXPECT_EQ(0, vbmeta_header->flags);
411     EXPECT_EQ("unit test", std::string((const char*)vbmeta_header->release_string));
412 
413     // Checks vbmeta size is updated to the actual size without padding.
414     vbmeta_header = vbmeta_padding.GetVBMetaHeader(true /* update_vbmeta_size */);
415     EXPECT_EQ(content_padding.size() - padding.size(), vbmeta_padding.size());
416 }
417 
TEST_F(AvbUtilTest,ValidatePublicKeyBlob)418 TEST_F(AvbUtilTest, ValidatePublicKeyBlob) {
419     // Generates a raw key.bin
420     const size_t key_size = 2048;
421     base::FilePath key_path = GenerateImage("key.bin", key_size);
422 
423     uint8_t key_data[key_size];
424     EXPECT_EQ(key_size, base::ReadFile(key_path, (char*)key_data, key_size));
425 
426     std::string expected_key_blob;
427     EXPECT_TRUE(base::ReadFileToString(key_path, &expected_key_blob));
428     EXPECT_TRUE(ValidatePublicKeyBlob(key_data, key_size, expected_key_blob));
429 
430     key_data[10] ^= 0x80;  // toggles a bit and expects a failure
431     EXPECT_FALSE(ValidatePublicKeyBlob(key_data, key_size, expected_key_blob));
432     key_data[10] ^= 0x80;  // toggles the bit again, should pass
433     EXPECT_TRUE(ValidatePublicKeyBlob(key_data, key_size, expected_key_blob));
434 }
435 
TEST_F(AvbUtilTest,VerifyEmptyPublicKeyBlob)436 TEST_F(AvbUtilTest, VerifyEmptyPublicKeyBlob) {
437     // Generates a raw key.bin
438     const size_t key_size = 2048;
439     base::FilePath key_path = GenerateImage("key.bin", key_size);
440 
441     uint8_t key_data[key_size];
442     EXPECT_EQ(key_size, base::ReadFile(key_path, (char*)key_data, key_size));
443 
444     std::string expected_key_blob = "";  // empty means no expectation, thus return true.
445     EXPECT_TRUE(ValidatePublicKeyBlob(key_data, key_size, expected_key_blob));
446 }
447 
TEST_F(AvbUtilTest,ValidatePublicKeyBlob_MultipleAllowedKeys)448 TEST_F(AvbUtilTest, ValidatePublicKeyBlob_MultipleAllowedKeys) {
449     base::FilePath rsa2048_public_key =
450             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
451     base::FilePath rsa4096_public_key =
452             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
453     base::FilePath rsa8192_public_key =
454             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa8192.pem"));
455 
456     std::vector<std::string> allowed_key_paths;
457     allowed_key_paths.push_back(rsa2048_public_key.value());
458     allowed_key_paths.push_back(rsa4096_public_key.value());
459 
460     std::string expected_key_blob_2048;
461     EXPECT_TRUE(base::ReadFileToString(rsa2048_public_key, &expected_key_blob_2048));
462     std::string expected_key_blob_4096;
463     EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
464     std::string expected_key_blob_8192;
465     EXPECT_TRUE(base::ReadFileToString(rsa8192_public_key, &expected_key_blob_8192));
466 
467     EXPECT_TRUE(ValidatePublicKeyBlob(expected_key_blob_2048, allowed_key_paths));
468     EXPECT_TRUE(ValidatePublicKeyBlob(expected_key_blob_4096, allowed_key_paths));
469 
470     EXPECT_FALSE(ValidatePublicKeyBlob(expected_key_blob_8192, allowed_key_paths));
471     EXPECT_FALSE(ValidatePublicKeyBlob("invalid_content", allowed_key_paths));
472     EXPECT_FALSE(ValidatePublicKeyBlob("", allowed_key_paths));
473 
474     allowed_key_paths.push_back(rsa8192_public_key.value());
475     EXPECT_TRUE(ValidatePublicKeyBlob(expected_key_blob_8192, allowed_key_paths));
476 }
477 
TEST_F(AvbUtilTest,VerifyVBMetaSignature)478 TEST_F(AvbUtilTest, VerifyVBMetaSignature) {
479     const size_t image_size = 10 * 1024 * 1024;
480     const size_t partition_size = 15 * 1024 * 1024;
481     auto signing_key = data_dir_.Append("testkey_rsa4096.pem");
482     auto vbmeta = GenerateImageAndExtractVBMetaData("system", image_size, partition_size,
483                                                     "hashtree", signing_key, "SHA256_RSA4096",
484                                                     10 /* rollback_index */);
485 
486     auto expected_public_key_blob = ExtractPublicKeyAvbBlob(signing_key);
487     EXPECT_EQ(VBMetaVerifyResult::kSuccess,
488               VerifyVBMetaSignature(vbmeta, expected_public_key_blob,
489                                     nullptr /* out_public_key_data */));
490 
491     // Converts the expected key into an 'unexpected' key.
492     expected_public_key_blob[10] ^= 0x80;
493     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
494               VerifyVBMetaSignature(vbmeta, expected_public_key_blob,
495                                     nullptr /* out_public_key_data */));
496 }
497 
TEST_F(AvbUtilTest,VerifyVBMetaSignatureOutputPublicKeyData)498 TEST_F(AvbUtilTest, VerifyVBMetaSignatureOutputPublicKeyData) {
499     const size_t image_size = 10 * 1024 * 1024;
500     const size_t partition_size = 15 * 1024 * 1024;
501     auto signing_key = data_dir_.Append("testkey_rsa4096.pem");
502     auto vbmeta = GenerateImageAndExtractVBMetaData("system", image_size, partition_size,
503                                                     "hashtree", signing_key, "SHA256_RSA4096",
504                                                     10 /* rollback_index */);
505     std::string out_public_key_data;
506     auto expected_public_key_blob = ExtractPublicKeyAvbBlob(signing_key);
507     EXPECT_EQ(VBMetaVerifyResult::kSuccess,
508               VerifyVBMetaSignature(vbmeta, expected_public_key_blob, &out_public_key_data));
509     EXPECT_EQ(out_public_key_data, expected_public_key_blob);
510 
511     // Converts the expected key into an 'unexpected' key.
512     expected_public_key_blob[10] ^= 0x80;
513     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
514               VerifyVBMetaSignature(vbmeta, expected_public_key_blob, &out_public_key_data));
515     EXPECT_NE(out_public_key_data, expected_public_key_blob);
516 }
517 
TestVBMetaModification(VBMetaVerifyResult expected_result,const VBMetaData & vbmeta,size_t offset,size_t length)518 bool AvbUtilTest::TestVBMetaModification(VBMetaVerifyResult expected_result,
519                                          const VBMetaData& vbmeta, size_t offset, size_t length) {
520     uint8_t* d = reinterpret_cast<uint8_t*>(vbmeta.data());
521     const int kNumCheckIntervals = 8;
522 
523     // Tests |kNumCheckIntervals| modifications in the start, middle, and
524     // end of the given sub-array at offset with size.
525     for (int n = 0; n <= kNumCheckIntervals; n++) {
526         size_t o = std::min(length * n / kNumCheckIntervals, length - 1) + offset;
527         d[o] ^= 0x80;
528         VBMetaVerifyResult result = VerifyVBMetaSignature(vbmeta, "" /* expected_public_key_blob */,
529                                                           nullptr /* out_public_key_data */);
530         d[o] ^= 0x80;
531         if (result != expected_result) {
532             return false;
533         }
534     }
535 
536     return true;
537 }
538 
TEST_F(AvbUtilTest,VerifyVBMetaSignatureWithModification)539 TEST_F(AvbUtilTest, VerifyVBMetaSignatureWithModification) {
540     const size_t image_size = 10 * 1024 * 1024;
541     const size_t partition_size = 15 * 1024 * 1024;
542     auto signing_key = data_dir_.Append("testkey_rsa4096.pem");
543     auto vbmeta = GenerateImageAndExtractVBMetaData("system", image_size, partition_size,
544                                                     "hashtree", signing_key, "SHA256_RSA4096",
545                                                     10 /* rollback_index */);
546 
547     auto header = vbmeta.GetVBMetaHeader(true /* update_vbmeta_size */);
548     size_t header_block_offset = 0;
549     size_t authentication_block_offset = header_block_offset + sizeof(AvbVBMetaImageHeader);
550     size_t auxiliary_block_offset =
551             authentication_block_offset + header->authentication_data_block_size;
552 
553     // Should detect modifications in the auxiliary data block.
554     EXPECT_TRUE(TestVBMetaModification(VBMetaVerifyResult::kErrorVerification, vbmeta,
555                                        auxiliary_block_offset, header->auxiliary_data_block_size));
556 
557     // Sholud detect modifications in the hash part of authentication data block.
558     EXPECT_TRUE(TestVBMetaModification(VBMetaVerifyResult::kErrorVerification, vbmeta,
559                                        authentication_block_offset + header->hash_offset,
560                                        header->hash_size));
561 
562     // Sholud detect modifications in the signature part of authentication data block.
563     EXPECT_TRUE(TestVBMetaModification(VBMetaVerifyResult::kErrorVerification, vbmeta,
564                                        authentication_block_offset + header->signature_offset,
565                                        header->signature_size));
566 }
567 
TEST_F(AvbUtilTest,VerifyVBMetaSignatureNotSigned)568 TEST_F(AvbUtilTest, VerifyVBMetaSignatureNotSigned) {
569     const size_t image_size = 10 * 1024 * 1024;
570     const size_t partition_size = 15 * 1024 * 1024;
571     auto vbmeta = GenerateImageAndExtractVBMetaData(
572             "system", image_size, partition_size, "hashtree", {} /* avb_signing_key */,
573             "" /* avb_algorithm */, 10 /* rollback_index */);
574 
575     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
576               VerifyVBMetaSignature(vbmeta, "" /* expected_public_key_blob */,
577                                     nullptr /* out_public_key_data */));
578 }
579 
TEST_F(AvbUtilTest,VerifyVBMetaSignatureInvalidVBMeta)580 TEST_F(AvbUtilTest, VerifyVBMetaSignatureInvalidVBMeta) {
581     const size_t buffer_size = 5 * 1024 * 1024;
582     std::vector<uint8_t> vbmeta_buffer(buffer_size);
583     for (size_t n = 0; n < buffer_size; n++) {
584         vbmeta_buffer[n] = uint8_t(n);
585     }
586 
587     VBMetaData invalid_vbmeta((const uint8_t*)vbmeta_buffer.data(), vbmeta_buffer.size(),
588                               "invalid_vbmeta");
589     EXPECT_EQ(VBMetaVerifyResult::kError,
590               VerifyVBMetaSignature(invalid_vbmeta, "" /* expected_public_key_blob */,
591                                     nullptr /* out_public_Key_data */));
592 }
593 
CompareVBMeta(const base::FilePath & avb_image_path,const VBMetaData & expected_vbmeta)594 bool AvbUtilTest::CompareVBMeta(const base::FilePath& avb_image_path,
595                                 const VBMetaData& expected_vbmeta) {
596     if (!base::PathExists(avb_image_path)) return false;
597 
598     std::string image_file_name = avb_image_path.RemoveExtension().BaseName().value();
599 
600     base::FilePath extracted_vbmeta_path;
601     if (base::StartsWith(image_file_name, "vbmeta", base::CompareCase::INSENSITIVE_ASCII)) {
602         extracted_vbmeta_path = avb_image_path;  // no need to extract if it's a vbmeta image.
603     } else {
604         extracted_vbmeta_path = ExtractVBMetaImage(avb_image_path, image_file_name + "-vbmeta.img");
605     }
606 
607     // Gets file size of the vbmeta image.
608     int64_t extracted_vbmeta_size;
609     EXPECT_TRUE(base::GetFileSize(extracted_vbmeta_path, &extracted_vbmeta_size));
610 
611     // Reads the vbmeta into a vector.
612     std::vector<uint8_t> extracted_vbmeta_content(extracted_vbmeta_size);
613     EXPECT_TRUE(base::ReadFile(extracted_vbmeta_path,
614                                reinterpret_cast<char*>(extracted_vbmeta_content.data()),
615                                extracted_vbmeta_size));
616 
617     // Compares extracted_vbmeta_content with the expected_vbmeta.
618     EXPECT_EQ(expected_vbmeta.size(), extracted_vbmeta_size);
619     return memcmp(reinterpret_cast<void*>(extracted_vbmeta_content.data()),
620                   reinterpret_cast<void*>(expected_vbmeta.data()), extracted_vbmeta_size) == 0;
621 }
622 
TEST_F(AvbUtilTest,VerifyVBMetaDataWithoutFooter)623 TEST_F(AvbUtilTest, VerifyVBMetaDataWithoutFooter) {
624     // Generates chain partition descriptors.
625     base::FilePath rsa2048_public_key =
626             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
627     base::FilePath rsa4096_public_key =
628             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
629 
630     // Makes a vbmeta image includeing 'boot' and 'system' chained descriptors.
631     auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
632                                            data_dir_.Append("testkey_rsa8192.pem"),
633                                            {}, /* include_descriptor_image_paths */
634                                            {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
635                                             {"system", 2, rsa4096_public_key}},
636                                            "--internal_release_string \"unit test\"");
637     EXPECT_EQ(
638             "Minimum libavb version:   1.0\n"
639             "Header Block:             256 bytes\n"
640             "Authentication Block:     1088 bytes\n"
641             "Auxiliary Block:          3840 bytes\n"
642             "Algorithm:                SHA256_RSA8192\n"
643             "Rollback Index:           0\n"
644             "Flags:                    0\n"
645             "Release String:           'unit test'\n"
646             "Descriptors:\n"
647             "    Chain Partition descriptor:\n"
648             "      Partition Name:          boot\n"
649             "      Rollback Index Location: 1\n"
650             "      Public key (sha1):       cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
651             "    Chain Partition descriptor:\n"
652             "      Partition Name:          system\n"
653             "      Rollback Index Location: 2\n"
654             "      Public key (sha1):       2597c218aae470a130f61162feaae70afd97f011\n",
655             InfoImage("vbmeta.img"));
656 
657     android::base::unique_fd fd(open(vbmeta_path.value().c_str(), O_RDONLY | O_CLOEXEC));
658     ASSERT_TRUE(fd > 0);
659 
660     VBMetaVerifyResult verify_result;
661     std::string out_public_key_data;
662     std::unique_ptr<VBMetaData> vbmeta = VerifyVBMetaData(
663             fd, "vbmeta", "" /*expected_public_key_blob */, &out_public_key_data, &verify_result);
664     EXPECT_TRUE(vbmeta != nullptr);
665     EXPECT_EQ(VBMetaVerifyResult::kSuccess, verify_result);
666 
667     auto rsa8192_public_key_blob = ExtractPublicKeyAvbBlob(data_dir_.Append("testkey_rsa8192.pem"));
668     EXPECT_EQ(rsa8192_public_key_blob, out_public_key_data);
669 
670     // Checkes the returned vbmeta content is the same as that extracted via avbtool.
671     vbmeta->GetVBMetaHeader(true /* update_vbmeta_size */);
672     EXPECT_TRUE(CompareVBMeta(vbmeta_path, *vbmeta));
673 }
674 
TEST_F(AvbUtilTest,VerifyVBMetaDataWithFooter)675 TEST_F(AvbUtilTest, VerifyVBMetaDataWithFooter) {
676     const size_t image_size = 10 * 1024 * 1024;
677     const size_t partition_size = 15 * 1024 * 1024;
678     base::FilePath system_path = GenerateImage("system.img", image_size);
679 
680     // Appends AVB Hashtree Footer.
681     AddAvbFooter(system_path, "hashtree", "system", partition_size, "SHA512_RSA8192", 20,
682                  data_dir_.Append("testkey_rsa8192.pem"), "d00df00d",
683                  "--internal_release_string \"unit test\"");
684 
685     android::base::unique_fd fd(open(system_path.value().c_str(), O_RDONLY | O_CLOEXEC));
686     ASSERT_TRUE(fd > 0);
687 
688     VBMetaVerifyResult verify_result;
689     std::string out_public_key_data;
690     std::unique_ptr<VBMetaData> vbmeta = VerifyVBMetaData(
691             fd, "system", "" /*expected_public_key_blob */, &out_public_key_data, &verify_result);
692     EXPECT_TRUE(vbmeta != nullptr);
693     EXPECT_EQ(VBMetaVerifyResult::kSuccess, verify_result);
694 
695     auto rsa8192_public_key_blob = ExtractPublicKeyAvbBlob(data_dir_.Append("testkey_rsa8192.pem"));
696     EXPECT_EQ(rsa8192_public_key_blob, out_public_key_data);
697 
698     // Checkes the returned vbmeta content is the same as that extracted via avbtool.
699     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
700 }
701 
702 // Modifies a random bit for a file, in the range of [offset, offset + length - 1].
703 // Length < 0 means only resets previous modification without introducing new modification.
ModifyFile(const base::FilePath & file_path,size_t offset,ssize_t length)704 void AvbUtilTest::ModifyFile(const base::FilePath& file_path, size_t offset, ssize_t length) {
705     static int last_modified_location = -1;
706     static std::string last_file_path;
707 
708     int64_t file_size;
709     ASSERT_TRUE(base::GetFileSize(file_path, &file_size));
710 
711     std::vector<uint8_t> file_content(file_size);
712     ASSERT_TRUE(base::ReadFile(file_path, reinterpret_cast<char*>(file_content.data()), file_size));
713 
714     // Resets previous modification for consecutive calls on the same file.
715     if (last_file_path == file_path.value()) {
716         file_content[last_modified_location] ^= 0x80;
717     }
718 
719     // Introduces a new modification.
720     if (length > 0) {
721         int modify_location = base::RandInt(offset, offset + length - 1);
722         file_content[modify_location] ^= 0x80;
723         last_file_path = file_path.value();
724         last_modified_location = modify_location;
725     }
726 
727     ASSERT_EQ(file_size, static_cast<const size_t>(base::WriteFile(
728                                  file_path, reinterpret_cast<const char*>(file_content.data()),
729                                  file_content.size())));
730 }
731 
TEST_F(AvbUtilTest,VerifyVBMetaDataError)732 TEST_F(AvbUtilTest, VerifyVBMetaDataError) {
733     const size_t image_size = 10 * 1024 * 1024;
734     const size_t partition_size = 15 * 1024 * 1024;
735     base::FilePath system_path = GenerateImage("system.img", image_size);
736 
737     // Appends AVB Hashtree Footer.
738     AddAvbFooter(system_path, "hashtree", "system", partition_size, "SHA512_RSA8192", 20,
739                  data_dir_.Append("testkey_rsa8192.pem"), "d00df00d",
740                  "--internal_release_string \"unit test\"");
741 
742     android::base::unique_fd fd(open(system_path.value().c_str(), O_RDONLY | O_CLOEXEC));
743     ASSERT_TRUE(fd > 0);
744 
745     std::unique_ptr<AvbFooter> footer = GetAvbFooter(fd);
746     EXPECT_TRUE(footer != nullptr);
747 
748     VBMetaVerifyResult verify_result;
749     std::string out_public_key_data;
750     std::unique_ptr<VBMetaData> vbmeta = VerifyVBMetaData(
751             fd, "system", "" /*expected_public_key_blob */, &out_public_key_data, &verify_result);
752     EXPECT_NE(nullptr, vbmeta);
753     EXPECT_EQ(VBMetaVerifyResult::kSuccess, verify_result);
754 
755     auto rsa8192_public_key_blob = ExtractPublicKeyAvbBlob(data_dir_.Append("testkey_rsa8192.pem"));
756     EXPECT_EQ(rsa8192_public_key_blob, out_public_key_data);
757 
758     // Modifies hash and signature, checks there is verification error.
759     auto header = vbmeta->GetVBMetaHeader(true /* update_vbmeta_size */);
760     size_t header_block_offset = 0;
761     size_t authentication_block_offset = header_block_offset + sizeof(AvbVBMetaImageHeader);
762 
763     // Modifies the hash.
764     ModifyFile(system_path,
765                footer->vbmeta_offset + authentication_block_offset + header->hash_offset,
766                header->hash_size);
767     android::base::unique_fd hash_modified_fd(
768             open(system_path.value().c_str(), O_RDONLY | O_CLOEXEC));
769     ASSERT_TRUE(hash_modified_fd > 0);
770     // Should return ErrorVerification.
771     vbmeta = VerifyVBMetaData(hash_modified_fd, "system", "" /*expected_public_key_blob */,
772                               nullptr /* out_public_key_data */, &verify_result);
773     EXPECT_NE(nullptr, vbmeta);
774     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
775     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
776 
777     // Modifies the auxiliary data block.
778     size_t auxiliary_block_offset =
779             authentication_block_offset + header->authentication_data_block_size;
780     ModifyFile(system_path, footer->vbmeta_offset + auxiliary_block_offset,
781                header->auxiliary_data_block_size);
782     android::base::unique_fd aux_modified_fd(
783             open(system_path.value().c_str(), O_RDONLY | O_CLOEXEC));
784     ASSERT_TRUE(aux_modified_fd > 0);
785     // Should return ErrorVerification.
786     vbmeta = VerifyVBMetaData(aux_modified_fd, "system", "" /*expected_public_key_blob */,
787                               nullptr /* out_public_key_data */, &verify_result);
788     EXPECT_NE(nullptr, vbmeta);
789     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
790     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
791 
792     // Resets previous modification by setting offset to -1, and checks the verification can pass.
793     ModifyFile(system_path, 0 /* offset */, -1 /* length */);
794     android::base::unique_fd ok_fd(open(system_path.value().c_str(), O_RDONLY | O_CLOEXEC));
795     ASSERT_TRUE(ok_fd > 0);
796     // Should return ResultOK..
797     vbmeta = VerifyVBMetaData(ok_fd, "system", "" /*expected_public_key_blob */,
798                               nullptr /* out_public_key_data */, &verify_result);
799     EXPECT_NE(nullptr, vbmeta);
800     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
801     EXPECT_EQ(VBMetaVerifyResult::kSuccess, verify_result);
802 }
803 
TEST_F(AvbUtilTest,GetChainPartitionInfo)804 TEST_F(AvbUtilTest, GetChainPartitionInfo) {
805     // Generates a raw boot.img
806     const size_t boot_image_size = 5 * 1024 * 1024;
807     const size_t boot_partition_size = 10 * 1024 * 1024;
808     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
809     // Adds AVB Hash Footer.
810     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
811                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
812                  "--internal_release_string \"unit test\"");
813 
814     // Generates a raw system.img, use a smaller size to speed-up unit test.
815     const size_t system_image_size = 10 * 1024 * 1024;
816     const size_t system_partition_size = 15 * 1024 * 1024;
817     base::FilePath system_path = GenerateImage("system.img", system_image_size);
818     // Adds AVB Hashtree Footer.
819     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
820                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
821                  "--internal_release_string \"unit test\"");
822 
823     // Generates chain partition descriptors.
824     base::FilePath rsa2048_public_key =
825             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
826     base::FilePath rsa4096_public_key =
827             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
828     // Makes a vbmeta_system.img including the 'system' chained descriptor.
829     GenerateVBMetaImage("vbmeta_system.img", "SHA256_RSA4096", 0,
830                         data_dir_.Append("testkey_rsa4096.pem"),
831                         {},                                  /* include_descriptor_image_paths */
832                         {{"system", 3, rsa4096_public_key}}, /* chain_partitions */
833                         "--internal_release_string \"unit test\"");
834 
835     // Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
836     GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0, data_dir_.Append("testkey_rsa8192.pem"),
837                         {},                               /* include_descriptor_image_paths */
838                         {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
839                          {"vbmeta_system", 2, rsa4096_public_key}},
840                         "--internal_release_string \"unit test\"");
841 
842     // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
843     EXPECT_EQ("6f4bf815a651aa35ec7102a88b7906b91aef284bc5e20d0bf527c7d460da3266",
844               CalcVBMetaDigest("vbmeta.img", "sha256"));
845     // Loads the key blobs for comparison.
846     std::string expected_key_blob_2048;
847     EXPECT_TRUE(base::ReadFileToString(rsa2048_public_key, &expected_key_blob_2048));
848     std::string expected_key_blob_4096;
849     EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
850 
851     // Checks chain descriptors in vbmeta.img
852     EXPECT_EQ(
853             "Minimum libavb version:   1.0\n"
854             "Header Block:             256 bytes\n"
855             "Authentication Block:     1088 bytes\n"
856             "Auxiliary Block:          3840 bytes\n"
857             "Algorithm:                SHA256_RSA8192\n"
858             "Rollback Index:           0\n"
859             "Flags:                    0\n"
860             "Release String:           'unit test'\n"
861             "Descriptors:\n"
862             "    Chain Partition descriptor:\n"
863             "      Partition Name:          boot\n"
864             "      Rollback Index Location: 1\n"
865             "      Public key (sha1):       cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
866             "    Chain Partition descriptor:\n"
867             "      Partition Name:          vbmeta_system\n"
868             "      Rollback Index Location: 2\n"
869             "      Public key (sha1):       2597c218aae470a130f61162feaae70afd97f011\n",
870             InfoImage("vbmeta.img"));
871 
872     bool fatal_error = false;
873     auto chained_descriptors = GetChainPartitionInfo(LoadVBMetaData("vbmeta.img"), &fatal_error);
874     EXPECT_EQ(2, chained_descriptors.size());  // contains 'boot' and 'vbmeta_system'.
875     EXPECT_EQ(false, fatal_error);
876 
877     EXPECT_EQ("boot", chained_descriptors[0].partition_name);
878     EXPECT_EQ(expected_key_blob_2048, chained_descriptors[0].public_key_blob);
879 
880     EXPECT_EQ("vbmeta_system", chained_descriptors[1].partition_name);
881     EXPECT_EQ(expected_key_blob_4096, chained_descriptors[1].public_key_blob);
882 
883     // Checks chain descriptors in vbmeta_system.img
884     EXPECT_EQ(
885             "Minimum libavb version:   1.0\n"
886             "Header Block:             256 bytes\n"
887             "Authentication Block:     576 bytes\n"
888             "Auxiliary Block:          2176 bytes\n"
889             "Algorithm:                SHA256_RSA4096\n"
890             "Rollback Index:           0\n"
891             "Flags:                    0\n"
892             "Release String:           'unit test'\n"
893             "Descriptors:\n"
894             "    Chain Partition descriptor:\n"
895             "      Partition Name:          system\n"
896             "      Rollback Index Location: 3\n"
897             "      Public key (sha1):       2597c218aae470a130f61162feaae70afd97f011\n",
898             InfoImage("vbmeta_system.img"));
899 
900     chained_descriptors = GetChainPartitionInfo(LoadVBMetaData("vbmeta_system.img"), &fatal_error);
901     EXPECT_EQ(1, chained_descriptors.size());  // contains 'system' only.
902     EXPECT_EQ(false, fatal_error);
903     EXPECT_EQ("system", chained_descriptors[0].partition_name);
904     EXPECT_EQ(expected_key_blob_4096, chained_descriptors[0].public_key_blob);
905 }
906 
TEST_F(AvbUtilTest,GetChainPartitionInfoNone)907 TEST_F(AvbUtilTest, GetChainPartitionInfoNone) {
908     // Generates a raw boot.img
909     const size_t boot_image_size = 5 * 1024 * 1024;
910     const size_t boot_partition_size = 10 * 1024 * 1024;
911     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
912     // Adds AVB Hash Footer.
913     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA4096", 10,
914                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
915                  "--internal_release_string \"unit test\"");
916 
917     // Generates a raw system.img, use a smaller size to speed-up unit test.
918     const size_t system_image_size = 10 * 1024 * 1024;
919     const size_t system_partition_size = 15 * 1024 * 1024;
920     base::FilePath system_path = GenerateImage("system.img", system_image_size);
921     // Adds AVB Hashtree Footer.
922     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA8192", 20,
923                  data_dir_.Append("testkey_rsa8192.pem"), "d00df00d",
924                  "--internal_release_string \"unit test\"");
925 
926     // Makes a vbmeta.img including both 'boot' and 'system' descriptors.
927     GenerateVBMetaImage("vbmeta.img", "SHA256_RSA2048", 0, data_dir_.Append("testkey_rsa2048.pem"),
928                         {boot_path, system_path}, /* include_descriptor_image_paths */
929                         {},                       /* chain_partitions */
930                         "--internal_release_string \"unit test\"");
931     EXPECT_EQ("a069cbfc30c816cddf3b53f1ad53b7ca5d61a3d93845eb596bbb1b40caa1c62f",
932               CalcVBMetaDigest("vbmeta.img", "sha256"));
933 
934     EXPECT_EQ(
935             "Minimum libavb version:   1.0\n"
936             "Header Block:             256 bytes\n"
937             "Authentication Block:     320 bytes\n"
938             "Auxiliary Block:          960 bytes\n"
939             "Algorithm:                SHA256_RSA2048\n"
940             "Rollback Index:           0\n"
941             "Flags:                    0\n"
942             "Release String:           'unit test'\n"
943             "Descriptors:\n"
944             "    Hash descriptor:\n"
945             "      Image Size:            5242880 bytes\n"
946             "      Hash Algorithm:        sha256\n"
947             "      Partition Name:        boot\n"
948             "      Salt:                  d00df00d\n"
949             "      Digest:                "
950             "222dd01e98284a1fcd7781f85d1392e43a530511a64eff96db197db90ebc4df1\n"
951             "      Flags:                 0\n"
952             "    Hashtree descriptor:\n"
953             "      Version of dm-verity:  1\n"
954             "      Image Size:            10485760 bytes\n"
955             "      Tree Offset:           10485760\n"
956             "      Tree Size:             86016 bytes\n"
957             "      Data Block Size:       4096 bytes\n"
958             "      Hash Block Size:       4096 bytes\n"
959             "      FEC num roots:         2\n"
960             "      FEC offset:            10571776\n"
961             "      FEC size:              90112 bytes\n"
962             "      Hash Algorithm:        sha1\n"
963             "      Partition Name:        system\n"
964             "      Salt:                  d00df00d\n"
965             "      Root Digest:           a3d5dd307341393d85de356c384ff543ec1ed81b\n"
966             "      Flags:                 0\n",
967             InfoImage("vbmeta.img"));
968 
969     // Checks none of chain descriptors is found.
970     bool fatal_error = false;
971     auto chained_descriptors = GetChainPartitionInfo(LoadVBMetaData("vbmeta.img"), &fatal_error);
972     EXPECT_EQ(0, chained_descriptors.size());  // There is no chain descriptors.
973     EXPECT_EQ(false, fatal_error);
974 }
975 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPath)976 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPath) {
977     // Generates a raw system_other.img, use a smaller size to speed-up unit test.
978     const size_t system_image_size = 10 * 1024 * 1024;
979     const size_t system_partition_size = 15 * 1024 * 1024;
980     base::FilePath system_path = GenerateImage("system_other.img", system_image_size);
981 
982     // Adds AVB Hashtree Footer.
983     AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
984                  20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
985                  "--internal_release_string \"unit test\"");
986 
987     std::string expected_key_blob_4096 =
988             ExtractPublicKeyAvbBlob(data_dir_.Append("testkey_rsa4096.pem"));
989 
990     bool verification_disabled;
991     VBMetaVerifyResult verify_result;
992     std::string out_public_key_data;
993     std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
994             system_path.value(), "system_other", expected_key_blob_4096,
995             false /* allow_verification_error */, false /* rollback_protection */,
996             false /* is_chained_vbmeta */, &out_public_key_data, &verification_disabled,
997             &verify_result);
998 
999     EXPECT_NE(nullptr, vbmeta);
1000     EXPECT_EQ(VBMetaVerifyResult::kSuccess, verify_result);
1001     EXPECT_EQ(false, verification_disabled);
1002     EXPECT_EQ(expected_key_blob_4096, out_public_key_data);
1003 
1004     EXPECT_EQ(2112UL, vbmeta->size());
1005     EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
1006     EXPECT_EQ("system_other", vbmeta->partition());
1007     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
1008 }
1009 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPathErrorVerification)1010 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathErrorVerification) {
1011     // Generates a raw system_other.img, use a smaller size to speed-up unit test.
1012     const size_t system_image_size = 10 * 1024 * 1024;
1013     const size_t system_partition_size = 15 * 1024 * 1024;
1014     base::FilePath system_path = GenerateImage("system_other.img", system_image_size);
1015 
1016     // Adds AVB Hashtree Footer.
1017     AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
1018                  20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
1019                  "--internal_release_string \"unit test\"");
1020 
1021     std::string expected_key_blob_4096 =
1022             ExtractPublicKeyAvbBlob(data_dir_.Append("testkey_rsa4096.pem"));
1023 
1024     // Modifies the auxiliary data of system_other.img
1025     auto fd = OpenUniqueReadFd(system_path);
1026     auto system_footer = GetAvbFooter(fd);
1027     auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system_other-vbmeta.img");
1028     auto system_header = system_vbmeta.GetVBMetaHeader(true /* update_vbmeta_size */);
1029     size_t header_block_offset = 0;
1030     size_t authentication_block_offset = header_block_offset + sizeof(AvbVBMetaImageHeader);
1031     size_t auxiliary_block_offset =
1032         authentication_block_offset + system_header->authentication_data_block_size;
1033 
1034     // Modifies the hash.
1035     ModifyFile(
1036         system_path,
1037         (system_footer->vbmeta_offset + authentication_block_offset + system_header->hash_offset),
1038         system_header->hash_size);
1039 
1040     VBMetaVerifyResult verify_result;
1041     // Not allow verification error.
1042     std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
1043             system_path.value(), "system_other", expected_key_blob_4096,
1044             false /* allow_verification_error */, false /* rollback_protection */,
1045             false /* is_chained_vbmeta */, nullptr /* out_public_key_data */,
1046             nullptr /* verification_disabled */, &verify_result);
1047     EXPECT_EQ(nullptr, vbmeta);
1048 
1049     // Allow verification error.
1050     vbmeta = LoadAndVerifyVbmetaByPath(
1051             system_path.value(), "system_other", expected_key_blob_4096,
1052             true /* allow_verification_error */, false /* rollback_protection */,
1053             false /* is_chained_vbmeta */, nullptr /* out_public_key_data */,
1054             nullptr /* verification_disabled */, &verify_result);
1055     EXPECT_NE(nullptr, vbmeta);
1056     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
1057 
1058     EXPECT_EQ(2112UL, vbmeta->size());
1059     EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
1060     EXPECT_EQ("system_other", vbmeta->partition());
1061     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
1062 
1063     // Modifies the auxiliary data block.
1064     ModifyFile(system_path, system_footer->vbmeta_offset + auxiliary_block_offset,
1065                system_header->auxiliary_data_block_size);
1066 
1067     // Not allow verification error.
1068     vbmeta = LoadAndVerifyVbmetaByPath(
1069             system_path.value(), "system_other", expected_key_blob_4096,
1070             false /* allow_verification_error */, false /* rollback_protection */,
1071             false /* is_chained_vbmeta */, nullptr /* out_public_key_data */,
1072             nullptr /* verification_disabled */, &verify_result);
1073     EXPECT_EQ(nullptr, vbmeta);
1074 
1075     // Allow verification error.
1076     vbmeta = LoadAndVerifyVbmetaByPath(
1077             system_path.value(), "system_other", expected_key_blob_4096,
1078             true /* allow_verification_error */, false /* rollback_protection */,
1079             false /* is_chained_vbmeta */, nullptr /* out_public_key_data */,
1080             nullptr /* verification_disabled */, &verify_result);
1081     EXPECT_NE(nullptr, vbmeta);
1082     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
1083 }
1084 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPathUnexpectedPublicKey)1085 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathUnexpectedPublicKey) {
1086     // Generates a raw system_other.img, use a smaller size to speed-up unit test.
1087     const size_t system_image_size = 10 * 1024 * 1024;
1088     const size_t system_partition_size = 15 * 1024 * 1024;
1089     base::FilePath system_path = GenerateImage("system_other.img", system_image_size);
1090 
1091     // Adds AVB Hashtree Footer.
1092     AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
1093                  20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
1094                  "--internal_release_string \"unit test\"");
1095 
1096     std::string unexpected_key_blob_2048 =
1097             ExtractPublicKeyAvbBlob(data_dir_.Append("testkey_rsa2048.pem"));
1098     std::string expected_key_blob_4096 =
1099             ExtractPublicKeyAvbBlob(data_dir_.Append("testkey_rsa4096.pem"));
1100 
1101     // Uses the correct expected public key.
1102     VBMetaVerifyResult verify_result;
1103     std::string out_public_key_data;
1104     std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
1105             system_path.value(), "system_other", expected_key_blob_4096,
1106             false /* allow_verification_error */, false /* rollback_protection */,
1107             false /* is_chained_vbmeta */, &out_public_key_data,
1108             nullptr /* verification_disabled */, &verify_result);
1109     EXPECT_NE(nullptr, vbmeta);
1110     EXPECT_EQ(verify_result, VBMetaVerifyResult::kSuccess);
1111     EXPECT_EQ(expected_key_blob_4096, out_public_key_data);
1112     EXPECT_EQ(2112UL, vbmeta->size());
1113     EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
1114     EXPECT_EQ("system_other", vbmeta->partition());
1115     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
1116 
1117     // Uses the wrong expected public key with allow_verification_error set to false.
1118     vbmeta = LoadAndVerifyVbmetaByPath(
1119             system_path.value(), "system_other", unexpected_key_blob_2048,
1120             false /* allow_verification_error */, false /* rollback_protection */,
1121             false /* is_chained_vbmeta */, &out_public_key_data,
1122             nullptr /* verification_disabled */, &verify_result);
1123     EXPECT_EQ(nullptr, vbmeta);
1124     // Checks out_public_key_data is still loaded properly, if the error is due
1125     // to an unexpected public key instead of vbmeta image verification error.
1126     EXPECT_EQ(expected_key_blob_4096, out_public_key_data);
1127 
1128     // Uses the wrong expected public key with allow_verification_error set to true.
1129     vbmeta = LoadAndVerifyVbmetaByPath(
1130             system_path.value(), "system_other", unexpected_key_blob_2048,
1131             true /* allow_verification_error */, false /* rollback_protection */,
1132             false /* is_chained_vbmeta */, &out_public_key_data,
1133             nullptr /* verification_disabled */, &verify_result);
1134     EXPECT_NE(nullptr, vbmeta);
1135     EXPECT_EQ(expected_key_blob_4096, out_public_key_data);
1136     EXPECT_EQ(verify_result, VBMetaVerifyResult::kErrorVerification);
1137     EXPECT_EQ(2112UL, vbmeta->size());
1138     EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
1139     EXPECT_EQ("system_other", vbmeta->partition());
1140     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
1141 }
1142 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPathVerificationDisabled)1143 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathVerificationDisabled) {
1144     // Generates a raw system_other.img, use a smaller size to speed-up unit test.
1145     const size_t system_image_size = 10 * 1024 * 1024;
1146     const size_t system_partition_size = 15 * 1024 * 1024;
1147     base::FilePath system_path = GenerateImage("system_other.img", system_image_size);
1148 
1149     // Adds AVB Hashtree Footer.
1150     AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
1151                  20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
1152                  "--internal_release_string \"unit test\"");
1153 
1154     base::FilePath rsa4096_public_key =
1155         ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
1156 
1157     std::string expected_key_blob_4096;
1158     EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
1159 
1160     // Sets disabled flag and expect the returned verification_disabled is true.
1161     SetVBMetaFlags(system_path, AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
1162     bool verification_disabled;
1163     VBMetaVerifyResult verify_result;
1164     std::string out_public_key_data;
1165     std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
1166             system_path.value(), "system_other", expected_key_blob_4096,
1167             true /* allow_verification_error */, false /* rollback_protection */,
1168             false /* is_chained_vbmeta */, nullptr /* out_public_key_data */,
1169             &verification_disabled, &verify_result);
1170 
1171     EXPECT_NE(nullptr, vbmeta);
1172     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
1173     EXPECT_EQ(true, verification_disabled);  // should be true.
1174 
1175     EXPECT_EQ(2112UL, vbmeta->size());
1176     EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
1177     EXPECT_EQ("system_other", vbmeta->partition());
1178     EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
1179 
1180     // Since the vbmeta flags is modified, vbmeta will be nullptr
1181     // if verification error isn't allowed.
1182     vbmeta = LoadAndVerifyVbmetaByPath(
1183             system_path.value(), "system_other", expected_key_blob_4096,
1184             false /* allow_verification_error */, false /* rollback_protection */,
1185             false /* is_chained_vbmeta */, nullptr /* out_public_key_data */,
1186             &verification_disabled, &verify_result);
1187     EXPECT_EQ(nullptr, vbmeta);
1188 }
1189 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPartition)1190 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartition) {
1191     // Generates a raw boot.img
1192     const size_t boot_image_size = 5 * 1024 * 1024;
1193     const size_t boot_partition_size = 10 * 1024 * 1024;
1194     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
1195 
1196     // Adds AVB Hash Footer.
1197     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
1198                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
1199                  "--internal_release_string \"unit test\"");
1200 
1201     // Generates a raw system.img, use a smaller size to speed-up unit test.
1202     const size_t system_image_size = 10 * 1024 * 1024;
1203     const size_t system_partition_size = 15 * 1024 * 1024;
1204     base::FilePath system_path = GenerateImage("system.img", system_image_size);
1205     // Adds AVB Hashtree Footer.
1206     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
1207                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
1208                  "--internal_release_string \"unit test\"");
1209 
1210     // Generates chain partition descriptors.
1211     base::FilePath rsa2048_public_key =
1212             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
1213     base::FilePath rsa4096_public_key =
1214             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
1215     // Makes a vbmeta_system.img including the 'system' chained descriptor.
1216     auto vbmeta_system_path = GenerateVBMetaImage(
1217             "vbmeta_system.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
1218             {},                                  /* include_descriptor_image_paths */
1219             {{"system", 3, rsa4096_public_key}}, /* chain_partitions */
1220             "--internal_release_string \"unit test\"");
1221 
1222     // Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
1223     auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
1224                                            data_dir_.Append("testkey_rsa8192.pem"),
1225                                            {}, /* include_descriptor_image_paths */
1226                                            {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
1227                                             {"vbmeta_system", 2, rsa4096_public_key}},
1228                                            "--internal_release_string \"unit test\"");
1229 
1230     // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
1231     EXPECT_EQ("6f4bf815a651aa35ec7102a88b7906b91aef284bc5e20d0bf527c7d460da3266",
1232               CalcVBMetaDigest("vbmeta.img", "sha256"));
1233 
1234     // Starts to test LoadAndVerifyVbmetaByPartition.
1235     std::vector<VBMetaData> vbmeta_images;
1236     auto vbmeta_image_path = [this](const std::string& partition_name) {
1237         return test_dir_.Append(partition_name + ".img").value();
1238     };
1239 
1240     EXPECT_EQ(VBMetaVerifyResult::kSuccess,
1241               LoadAndVerifyVbmetaByPartition(
1242                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1243                   "" /* expected_public_key_blob*/, false /* allow_verification_error */,
1244                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1245                   false /* is_chained_vbmeta*/, &vbmeta_images));
1246 
1247     EXPECT_EQ(4UL, vbmeta_images.size());  // vbmeta, boot, vbmeta_system and system
1248     // Binary comparison for each vbmeta image.
1249     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1250     EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
1251     EXPECT_TRUE(CompareVBMeta(vbmeta_system_path, vbmeta_images[2]));
1252     EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[3]));
1253 
1254     // Skip loading chained vbmeta images.
1255     vbmeta_images.clear();
1256     EXPECT_EQ(VBMetaVerifyResult::kSuccess,
1257               LoadAndVerifyVbmetaByPartition(
1258                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1259                   "" /* expected_public_key_blob*/, false /* allow_verification_error */,
1260                   false /* load_chained_vbmeta */, true /* rollback_protection */,
1261                   vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
1262     // Only vbmeta is loaded.
1263     EXPECT_EQ(1UL, vbmeta_images.size());
1264     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1265 }
1266 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPartitionWithSuffixes)1267 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionWithSuffixes) {
1268     // Tests the following chained partitions.
1269     // vbmeta_a.img
1270     // |--> boot_b.img (boot_other)
1271     // |--> vbmeta_system_b.img (vbmeta_system_other)
1272     //      |--> system_a.img
1273 
1274     // Generates a raw boot_b.img
1275     const size_t boot_image_size = 5 * 1024 * 1024;
1276     const size_t boot_partition_size = 10 * 1024 * 1024;
1277     base::FilePath boot_path = GenerateImage("boot_b.img", boot_image_size);
1278 
1279     // Adds AVB Hash Footer.
1280     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
1281                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
1282                  "--internal_release_string \"unit test\"");
1283 
1284     // Generates a raw system_a.img, use a smaller size to speed-up unit test.
1285     const size_t system_image_size = 10 * 1024 * 1024;
1286     const size_t system_partition_size = 15 * 1024 * 1024;
1287     base::FilePath system_path = GenerateImage("system_a.img", system_image_size);
1288     // Adds AVB Hashtree Footer.
1289     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
1290                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
1291                  "--internal_release_string \"unit test\"");
1292 
1293     // Generates chain partition descriptors.
1294     base::FilePath rsa2048_public_key =
1295             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
1296     base::FilePath rsa4096_public_key =
1297             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
1298     // Makes a vbmeta_system_b.img including the 'system' chained descriptor.
1299     auto vbmeta_system_path = GenerateVBMetaImage(
1300             "vbmeta_system_b.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
1301             {},                                  /* include_descriptor_image_paths */
1302             {{"system", 3, rsa4096_public_key}}, /* chain_partitions */
1303             "--internal_release_string \"unit test\"");
1304 
1305     // Makes a vbmeta_a.img includeing 'boot_other' and 'vbmeta_system_other' chained descriptors.
1306     auto vbmeta_path = GenerateVBMetaImage(
1307             "vbmeta_a.img", "SHA256_RSA8192", 0, data_dir_.Append("testkey_rsa8192.pem"),
1308             {},                                     /* include_descriptor_image_paths */
1309             {{"boot_other", 1, rsa2048_public_key}, /* chain_partitions */
1310              {"vbmeta_system_other", 2, rsa4096_public_key}},
1311             "--internal_release_string \"unit test\"");
1312 
1313     // Starts to test LoadAndVerifyVbmetaByPartition with ab_suffix and ab_other_suffix.
1314     auto vbmeta_image_path = [this](const std::string& partition_name) {
1315         return test_dir_.Append(partition_name + ".img").value();
1316     };
1317 
1318     std::vector<VBMetaData> vbmeta_images;
1319     EXPECT_EQ(VBMetaVerifyResult::kSuccess,
1320               LoadAndVerifyVbmetaByPartition(
1321                   "vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
1322                   "" /* expected_public_key_blob*/, false /* allow_verification_error */,
1323                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1324                   false /* is_chained_vbmeta*/, &vbmeta_images));
1325 
1326     EXPECT_EQ(4UL, vbmeta_images.size());  // vbmeta, boot_other, vbmeta_system_other and system
1327     // Binary comparison for each vbmeta image.
1328     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1329     EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
1330     EXPECT_TRUE(CompareVBMeta(vbmeta_system_path, vbmeta_images[2]));
1331     EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[3]));
1332 
1333     // Skips loading chained vbmeta images.
1334     vbmeta_images.clear();
1335     EXPECT_EQ(VBMetaVerifyResult::kSuccess,
1336               LoadAndVerifyVbmetaByPartition(
1337                   "vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
1338                   "" /* expected_public_key_blob*/, false /* allow_verification_error */,
1339                   false /* load_chained_vbmeta */, true /* rollback_protection */,
1340                   vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
1341     // Only vbmeta is loaded.
1342     EXPECT_EQ(1UL, vbmeta_images.size());
1343     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1344 
1345     // Using an invalid suffix for 'other' slot, checks it returns error.
1346     EXPECT_EQ(VBMetaVerifyResult::kError,
1347               LoadAndVerifyVbmetaByPartition(
1348                   "vbmeta" /* partition_name */, "_a" /* ab_suffix */,
1349                   "_invalid_suffix" /* other_suffix */, "" /* expected_public_key_blob*/,
1350                   false /* allow_verification_error */, true /* load_chained_vbmeta */,
1351                   true /* rollback_protection */, vbmeta_image_path, false /* is_chained_vbmeta*/,
1352                   &vbmeta_images));
1353 }
1354 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPartitionErrorVerification)1355 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionErrorVerification) {
1356     // Generates a raw boot.img
1357     const size_t boot_image_size = 5 * 1024 * 1024;
1358     const size_t boot_partition_size = 10 * 1024 * 1024;
1359     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
1360 
1361     // Adds AVB Hash Footer.
1362     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
1363                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
1364                  "--internal_release_string \"unit test\"");
1365 
1366     // Generates a raw system.img, use a smaller size to speed-up unit test.
1367     const size_t system_image_size = 10 * 1024 * 1024;
1368     const size_t system_partition_size = 15 * 1024 * 1024;
1369     base::FilePath system_path = GenerateImage("system.img", system_image_size);
1370     // Adds AVB Hashtree Footer.
1371     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
1372                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
1373                  "--internal_release_string \"unit test\"");
1374 
1375     // Generates chain partition descriptors.
1376     base::FilePath rsa2048_public_key =
1377             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
1378     base::FilePath rsa4096_public_key =
1379             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
1380 
1381     // Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
1382     auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
1383                                            data_dir_.Append("testkey_rsa8192.pem"),
1384                                            {}, /* include_descriptor_image_paths */
1385                                            {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
1386                                             {"system", 2, rsa4096_public_key}},
1387                                            "--internal_release_string \"unit test\"");
1388 
1389     // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
1390     EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
1391               CalcVBMetaDigest("vbmeta.img", "sha256"));
1392 
1393     auto vbmeta = LoadVBMetaData("vbmeta.img");
1394 
1395     // Modifies hash, checks there is error if allow_verification_error is false.
1396     auto header = vbmeta.GetVBMetaHeader(true /* update_vbmeta_size */);
1397     size_t header_block_offset = 0;
1398     size_t authentication_block_offset = header_block_offset + sizeof(AvbVBMetaImageHeader);
1399 
1400     // Modifies the hash.
1401     ModifyFile(vbmeta_path, authentication_block_offset + header->hash_offset, header->hash_size);
1402 
1403     // Starts to test LoadAndVerifyVbmetaByPartition.
1404     std::vector<VBMetaData> vbmeta_images;
1405     auto vbmeta_image_path = [this](const std::string& partition_name) {
1406         return test_dir_.Append(partition_name + ".img").value();
1407     };
1408     EXPECT_EQ(VBMetaVerifyResult::kError,
1409               LoadAndVerifyVbmetaByPartition(
1410                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1411                   "" /* expected_public_key_blob*/, false /* allow_verification_error */,
1412                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1413                   false /* is_chained_vbmeta*/, &vbmeta_images));
1414     // Stops to load vbmeta because the top-level vbmeta has verification error.
1415     EXPECT_EQ(0UL, vbmeta_images.size());
1416 
1417     // Tries again with verification error allowed.
1418     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
1419               LoadAndVerifyVbmetaByPartition(
1420                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "", /* other_suffix */
1421                   "" /* expected_public_key_blob*/, true /* allow_verification_error */,
1422                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1423                   false /* is_chained_vbmeta*/, &vbmeta_images));
1424 
1425     EXPECT_EQ(3UL, vbmeta_images.size());  // vbmeta, boot, and system
1426     // Binary comparison for each vbmeta image.
1427     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1428     EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
1429     EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[2]));
1430 
1431     // Resets the modification of the hash.
1432     ModifyFile(vbmeta_path, 0 /* offset */, -1 /* length */);
1433 
1434     // Modifies the auxiliary data of system.img
1435     auto fd = OpenUniqueReadFd(system_path);
1436     auto system_footer = GetAvbFooter(fd);
1437     auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system-vbmeta.img");
1438     auto system_header = system_vbmeta.GetVBMetaHeader(true /* update_vbmeta_size */);
1439     size_t auxiliary_block_offset =
1440             authentication_block_offset + system_header->authentication_data_block_size;
1441 
1442     // Modifies the auxiliary data block.
1443     ModifyFile(system_path, system_footer->vbmeta_offset + auxiliary_block_offset,
1444                system_header->auxiliary_data_block_size);
1445     vbmeta_images.clear();
1446     EXPECT_EQ(VBMetaVerifyResult::kError,
1447               LoadAndVerifyVbmetaByPartition(
1448                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1449                   "" /* expected_public_key_blob*/, false /* allow_verification_error */,
1450                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1451                   false /* is_chained_vbmeta*/, &vbmeta_images));
1452     // 'vbmeta', 'boot' but no 'system', because of verification error.
1453     EXPECT_EQ(2UL, vbmeta_images.size());
1454     // Binary comparison for the loaded 'vbmeta' and 'boot'.
1455     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1456     EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
1457 
1458     // Resets the modification of the auxiliary data.
1459     ModifyFile(system_path, 0 /* offset */, -1 /* length */);
1460 
1461     // Sets the vbmeta header flags on a chained partition, which introduces an error.
1462     ModifyFile(system_path, system_footer->vbmeta_offset + offsetof(AvbVBMetaImageHeader, flags),
1463                sizeof(uint32_t));
1464     EXPECT_EQ(VBMetaVerifyResult::kError,
1465               LoadAndVerifyVbmetaByPartition(
1466                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1467                   "" /* expected_public_key_blob*/, true /* allow_verification_error */,
1468                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1469                   false /* is_chained_vbmeta*/, &vbmeta_images));
1470 }
1471 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPartitionVerificationDisabled)1472 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionVerificationDisabled) {
1473     // Generates a raw boot.img
1474     const size_t boot_image_size = 5 * 1024 * 1024;
1475     const size_t boot_partition_size = 10 * 1024 * 1024;
1476     base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
1477 
1478     // Adds AVB Hash Footer.
1479     AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
1480                  data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
1481                  "--internal_release_string \"unit test\"");
1482 
1483     // Generates a raw system.img, use a smaller size to speed-up unit test.
1484     const size_t system_image_size = 10 * 1024 * 1024;
1485     const size_t system_partition_size = 15 * 1024 * 1024;
1486     base::FilePath system_path = GenerateImage("system.img", system_image_size);
1487     // Adds AVB Hashtree Footer.
1488     AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
1489                  data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
1490                  "--internal_release_string \"unit test\"");
1491 
1492     // Generates chain partition descriptors.
1493     base::FilePath rsa2048_public_key =
1494         ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
1495     base::FilePath rsa4096_public_key =
1496         ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
1497     // Makes a vbmeta_system.img including the 'system' chained descriptor.
1498     auto vbmeta_system_path = GenerateVBMetaImage(
1499         "vbmeta_system.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
1500         {},                                  /* include_descriptor_image_paths */
1501         {{"system", 3, rsa4096_public_key}}, /* chain_partitions */
1502         "--internal_release_string \"unit test\"");
1503 
1504     // Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
1505     auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
1506                                            data_dir_.Append("testkey_rsa8192.pem"),
1507                                            {}, /* include_descriptor_image_paths */
1508                                            {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
1509                                             {"vbmeta_system", 2, rsa4096_public_key}},
1510                                            "--internal_release_string \"unit test\"");
1511 
1512     // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
1513     EXPECT_EQ("6f4bf815a651aa35ec7102a88b7906b91aef284bc5e20d0bf527c7d460da3266",
1514               CalcVBMetaDigest("vbmeta.img", "sha256"));
1515 
1516     // Starts to test LoadAndVerifyVbmetaByPartition.
1517     std::vector<VBMetaData> vbmeta_images;
1518     auto vbmeta_image_path = [this](const std::string& partition_name) {
1519         return test_dir_.Append(partition_name + ".img").value();
1520     };
1521 
1522     EXPECT_EQ(VBMetaVerifyResult::kSuccess,
1523               LoadAndVerifyVbmetaByPartition(
1524                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1525                   "" /* expected_public_key_blob*/, false /* allow_verification_error */,
1526                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1527                   false /* is_chained_vbmeta*/, &vbmeta_images));
1528 
1529     EXPECT_EQ(4UL, vbmeta_images.size());  // vbmeta, boot, vbmeta_system and system
1530     // Binary comparison for each vbmeta image.
1531     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1532     EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
1533     EXPECT_TRUE(CompareVBMeta(vbmeta_system_path, vbmeta_images[2]));
1534     EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[3]));
1535 
1536     // Sets VERIFICATION_DISABLED to the top-level vbmeta.img
1537     SetVBMetaFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
1538     vbmeta_images.clear();
1539     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
1540               LoadAndVerifyVbmetaByPartition(
1541                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1542                   "" /* expected_public_key_blob*/, true /* allow_verification_error */,
1543                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1544                   false /* is_chained_vbmeta*/, &vbmeta_images));
1545     EXPECT_EQ(1UL, vbmeta_images.size());  // Only vbmeta is loaded
1546     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1547 
1548     // HASHTREE_DISABLED still loads the chained vbmeta.
1549     SetVBMetaFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
1550     vbmeta_images.clear();
1551     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
1552               LoadAndVerifyVbmetaByPartition(
1553                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1554                   "" /* expected_public_key_blob*/, true /* allow_verification_error */,
1555                   true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
1556                   false /* is_chained_vbmeta*/, &vbmeta_images));
1557     EXPECT_EQ(4UL, vbmeta_images.size());  // vbmeta, boot, vbmeta_system and system
1558     // Binary comparison for each vbmeta image.
1559     EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
1560     EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
1561     EXPECT_TRUE(CompareVBMeta(vbmeta_system_path, vbmeta_images[2]));
1562     EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[3]));
1563 }
1564 
TEST_F(AvbUtilTest,LoadAndVerifyVbmetaByPartitionUnexpectedPublicKey)1565 TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionUnexpectedPublicKey) {
1566     // Generates chain partition descriptors.
1567     base::FilePath rsa2048_public_key =
1568             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
1569     base::FilePath rsa4096_public_key =
1570             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
1571     base::FilePath rsa8192_public_key =
1572             ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa8192.pem"));
1573 
1574     // Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
1575     auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
1576                                            data_dir_.Append("testkey_rsa8192.pem"),
1577                                            {}, /* include_descriptor_image_paths */
1578                                            {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
1579                                             {"system", 2, rsa4096_public_key}},
1580                                            "--internal_release_string \"unit test\"");
1581     std::string expected_key_blob_4096;
1582     EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
1583     std::string expected_key_blob_8192;
1584     EXPECT_TRUE(base::ReadFileToString(rsa8192_public_key, &expected_key_blob_8192));
1585 
1586     auto vbmeta_image_path = [this](const std::string& partition_name) {
1587         return test_dir_.Append(partition_name + ".img").value();
1588     };
1589     std::vector<VBMetaData> vbmeta_images;
1590     // Uses the correct expected public key.
1591     EXPECT_EQ(VBMetaVerifyResult::kSuccess,
1592               LoadAndVerifyVbmetaByPartition(
1593                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1594                   expected_key_blob_8192, true /* allow_verification_error */,
1595                   false /* load_chained_vbmeta */, true /* rollback_protection */,
1596                   vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
1597 
1598     // Uses the wrong expected public key with allow_verification_error set to true.
1599     vbmeta_images.clear();
1600     EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
1601               LoadAndVerifyVbmetaByPartition(
1602                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1603                   expected_key_blob_4096, true /* allow_verification_error */,
1604                   false /* load_chained_vbmeta */, true /* rollback_protection */,
1605                   vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
1606 
1607     // Uses the wrong expected public key with allow_verification_error set to false.
1608     vbmeta_images.clear();
1609     EXPECT_EQ(VBMetaVerifyResult::kError,
1610               LoadAndVerifyVbmetaByPartition(
1611                   "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
1612                   expected_key_blob_4096, false /* allow_verification_error */,
1613                   false /* load_chained_vbmeta */, true /* rollback_protection */,
1614                   vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
1615 }
1616 
1617 }  // namespace fs_avb_host_test
1618