• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #include <iostream>
26 
27 #include <endian.h>
28 #include <inttypes.h>
29 #include <string.h>
30 
31 #include <base/files/file_util.h>
32 #include <base/strings/string_split.h>
33 #include <base/strings/string_util.h>
34 #include <base/strings/stringprintf.h>
35 
36 #include <libavb/avb_sha.h>
37 #include <libavb/libavb.h>
38 
39 #include "avb_unittest_util.h"
40 #include "fake_avb_ops.h"
41 
42 namespace avb {
43 
44 class AvbToolTest : public BaseAvbToolTest {
45  public:
AvbToolTest()46   AvbToolTest() {}
47 
SetUp()48   virtual void SetUp() override {
49     BaseAvbToolTest::SetUp();
50     ops_.set_partition_dir(testdir_);
51     ops_.set_stored_rollback_indexes({{0, 0}, {1, 0}, {2, 0}, {3, 0}});
52     ops_.set_stored_is_device_unlocked(false);
53   }
54 
55   void AddHashFooterTest(bool sparse_image);
56   void CreateRootfsWithHashtreeFooter(bool sparse_image,
57                                       const std::string& hash_algorithm,
58                                       const std::string& root_digest,
59                                       base::FilePath* rootfs_path);
60   void AddHashtreeFooterTest(bool sparse_image);
61   void AddHashtreeFooterFECTest(bool sparse_image);
62 
63   void GenerateImageWithHashAndHashtreeSetup();
64 
65   FakeAvbOps ops_;
66 };
67 
68 // This test ensure that the version is increased in both
69 // avb_boot_image.h and the avb tool.
TEST_F(AvbToolTest,AvbVersionInSync)70 TEST_F(AvbToolTest, AvbVersionInSync) {
71   base::FilePath path = testdir_.Append("version.txt");
72   EXPECT_COMMAND(0, "./avbtool.py version > %s", path.value().c_str());
73   std::string printed_version;
74   ASSERT_TRUE(base::ReadFileToString(path, &printed_version));
75   base::TrimWhitespaceASCII(printed_version, base::TRIM_ALL, &printed_version);
76   // See comments in libavb/avb_version.c and avbtool's get_release_string()
77   // about being in sync.
78   EXPECT_EQ(printed_version,
79             std::string("avbtool ") + std::string(avb_version_string()));
80 }
81 
TEST_F(AvbToolTest,DefaultReleaseString)82 TEST_F(AvbToolTest, DefaultReleaseString) {
83   GenerateVBMetaImage("vbmeta.img",
84                       "SHA256_RSA2048",
85                       0,
86                       base::FilePath("test/data/testkey_rsa2048.pem"));
87 
88   // Default release string is "avbtool " + avb_version_string().
89   AvbVBMetaImageHeader h;
90   avb_vbmeta_image_header_to_host_byte_order(
91       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
92   EXPECT_EQ(std::string("avbtool ") + std::string(avb_version_string()),
93             std::string((const char*)h.release_string));
94 }
95 
TEST_F(AvbToolTest,ReleaseStringAppend)96 TEST_F(AvbToolTest, ReleaseStringAppend) {
97   GenerateVBMetaImage("vbmeta.img",
98                       "SHA256_RSA2048",
99                       0,
100                       base::FilePath("test/data/testkey_rsa2048.pem"),
101                       "--append_to_release_string \"Woot XYZ\"");
102 
103   // Note that avbtool inserts the space by itself.
104   std::string expected_str =
105       std::string("avbtool ") + std::string(avb_version_string()) + " Woot XYZ";
106 
107   AvbVBMetaImageHeader h;
108   avb_vbmeta_image_header_to_host_byte_order(
109       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
110   EXPECT_EQ(expected_str, std::string((const char*)h.release_string));
111 }
112 
TEST_F(AvbToolTest,ReleaseStringAppendTruncated)113 TEST_F(AvbToolTest, ReleaseStringAppendTruncated) {
114   // Append enough text that truncation is sure to happen.
115   std::string append_str = "0123456789abcdef0123456789abcdef0123456789abcdef";
116   std::string expected_str = std::string("avbtool ") +
117                              std::string(avb_version_string()) + " " +
118                              append_str;
119   EXPECT_GT(expected_str.size(), (size_t)(AVB_RELEASE_STRING_SIZE - 1));
120   expected_str.resize(AVB_RELEASE_STRING_SIZE - 1);
121 
122   GenerateVBMetaImage(
123       "vbmeta.img",
124       "SHA256_RSA2048",
125       0,
126       base::FilePath("test/data/testkey_rsa2048.pem"),
127       std::string("--append_to_release_string \"") + append_str + "\"");
128 
129   // This checks that it ends with a NUL byte.
130   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
131             avb_vbmeta_image_verify(
132                 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr));
133 
134   // For good measure we also check here.
135   AvbVBMetaImageHeader h;
136   avb_vbmeta_image_header_to_host_byte_order(
137       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
138   EXPECT_EQ(expected_str, std::string((const char*)h.release_string));
139 }
140 
TEST_F(AvbToolTest,ExtractPublicKey)141 TEST_F(AvbToolTest, ExtractPublicKey) {
142   GenerateVBMetaImage("vbmeta.img",
143                       "SHA256_RSA2048",
144                       0,
145                       base::FilePath("test/data/testkey_rsa2048.pem"),
146                       "--internal_release_string \"\"");
147 
148   std::string key_data =
149       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem"));
150 
151   AvbVBMetaImageHeader h;
152   avb_vbmeta_image_header_to_host_byte_order(
153       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
154   uint8_t* d = reinterpret_cast<uint8_t*>(vbmeta_image_.data());
155   size_t auxiliary_data_block_offset =
156       sizeof(AvbVBMetaImageHeader) + h.authentication_data_block_size;
157   EXPECT_GT(h.auxiliary_data_block_size, key_data.size());
158   EXPECT_EQ(0,
159             memcmp(key_data.data(),
160                    d + auxiliary_data_block_offset + h.public_key_offset,
161                    key_data.size()));
162 }
163 
TEST_F(AvbToolTest,CheckDescriptors)164 TEST_F(AvbToolTest, CheckDescriptors) {
165   GenerateVBMetaImage("vbmeta.img",
166                       "SHA256_RSA2048",
167                       0,
168                       base::FilePath("test/data/testkey_rsa2048.pem"),
169                       "--prop foo:brillo "
170                       "--prop bar:chromeos "
171                       "--prop prisoner:24601 "
172                       "--prop hexnumber:0xcafe "
173                       "--prop hexnumber_capital:0xCAFE "
174                       "--prop large_hexnumber:0xfedcba9876543210 "
175                       "--prop larger_than_uint64:0xfedcba98765432101 "
176                       "--prop almost_a_number:423x "
177                       "--prop_from_file blob:test/data/small_blob.bin "
178                       "--internal_release_string \"\"");
179 
180   AvbVBMetaImageHeader h;
181   avb_vbmeta_image_header_to_host_byte_order(
182       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
183 
184   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
185             avb_vbmeta_image_verify(
186                 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr));
187 
188   const char* s;
189   size_t len;
190   uint64_t val;
191 
192   // Basic.
193   s = avb_property_lookup(
194       vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &len);
195   EXPECT_EQ(0, strcmp(s, "brillo"));
196   EXPECT_EQ(6U, len);
197   s = avb_property_lookup(
198       vbmeta_image_.data(), vbmeta_image_.size(), "bar", 0, &len);
199   EXPECT_EQ(0, strcmp(s, "chromeos"));
200   EXPECT_EQ(8U, len);
201   s = avb_property_lookup(
202       vbmeta_image_.data(), vbmeta_image_.size(), "non-existant", 0, &len);
203   EXPECT_EQ(0U, len);
204   EXPECT_EQ(NULL, s);
205 
206   // Numbers.
207   EXPECT_NE(
208       0,
209       avb_property_lookup_uint64(
210           vbmeta_image_.data(), vbmeta_image_.size(), "prisoner", 0, &val));
211   EXPECT_EQ(24601U, val);
212 
213   EXPECT_NE(
214       0,
215       avb_property_lookup_uint64(
216           vbmeta_image_.data(), vbmeta_image_.size(), "hexnumber", 0, &val));
217   EXPECT_EQ(0xcafeU, val);
218 
219   EXPECT_NE(0,
220             avb_property_lookup_uint64(vbmeta_image_.data(),
221                                        vbmeta_image_.size(),
222                                        "hexnumber_capital",
223                                        0,
224                                        &val));
225   EXPECT_EQ(0xcafeU, val);
226 
227   EXPECT_NE(0,
228             avb_property_lookup_uint64(vbmeta_image_.data(),
229                                        vbmeta_image_.size(),
230                                        "large_hexnumber",
231                                        0,
232                                        &val));
233   EXPECT_EQ(0xfedcba9876543210U, val);
234 
235   // We could catch overflows and return an error ... but we currently don't.
236   EXPECT_NE(0,
237             avb_property_lookup_uint64(vbmeta_image_.data(),
238                                        vbmeta_image_.size(),
239                                        "larger_than_uint64",
240                                        0,
241                                        &val));
242   EXPECT_EQ(0xedcba98765432101U, val);
243 
244   // Number-parsing failures.
245   EXPECT_EQ(0,
246             avb_property_lookup_uint64(
247                 vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &val));
248 
249   EXPECT_EQ(0,
250             avb_property_lookup_uint64(vbmeta_image_.data(),
251                                        vbmeta_image_.size(),
252                                        "almost_a_number",
253                                        0,
254                                        &val));
255 
256   // Blobs.
257   //
258   // test/data/small_blob.bin is 21 byte file full of NUL-bytes except
259   // for the string "brillo ftw!" at index 2 and '\n' at the last
260   // byte.
261   s = avb_property_lookup(
262       vbmeta_image_.data(), vbmeta_image_.size(), "blob", 0, &len);
263   EXPECT_EQ(21U, len);
264   EXPECT_EQ(0, memcmp(s, "\0\0", 2));
265   EXPECT_EQ(0, memcmp(s + 2, "brillo ftw!", 11));
266   EXPECT_EQ(0, memcmp(s + 13, "\0\0\0\0\0\0\0", 7));
267   EXPECT_EQ('\n', s[20]);
268 }
269 
TEST_F(AvbToolTest,Padding)270 TEST_F(AvbToolTest, Padding) {
271   GenerateVBMetaImage("vbmeta.img",
272                       "SHA256_RSA2048",
273                       0,
274                       base::FilePath("test/data/testkey_rsa2048.pem"),
275                       "--internal_release_string \"\"");
276 
277   GenerateVBMetaImage("vbmeta_padded.img",
278                       "SHA256_RSA2048",
279                       0,
280                       base::FilePath("test/data/testkey_rsa2048.pem"),
281                       "--internal_release_string \"\" --padding_size 4096");
282 
283   base::FilePath vbmeta_path = testdir_.Append("vbmeta.img");
284   base::FilePath vbmeta_padded_path = testdir_.Append("vbmeta_padded.img");
285   int64_t vbmeta_size, vbmeta_padded_size;
286   ASSERT_TRUE(base::GetFileSize(vbmeta_path, &vbmeta_size));
287   ASSERT_TRUE(base::GetFileSize(vbmeta_padded_path, &vbmeta_padded_size));
288 
289   EXPECT_NE(vbmeta_size, vbmeta_padded_size);
290 
291   // The padded size should be a multiple of 4096.
292   EXPECT_EQ(vbmeta_padded_size % 4096, 0);
293 
294   // When rounded up the unpadded size should equal the padded size.
295   int64_t vbmeta_size_rounded_up = ((vbmeta_size + 4095) / 4096) * 4096;
296   EXPECT_EQ(vbmeta_size_rounded_up, vbmeta_padded_size);
297 }
298 
TEST_F(AvbToolTest,CheckRollbackIndex)299 TEST_F(AvbToolTest, CheckRollbackIndex) {
300   uint64_t rollback_index = 42;
301   GenerateVBMetaImage("vbmeta.img",
302                       "SHA256_RSA2048",
303                       rollback_index,
304                       base::FilePath("test/data/testkey_rsa2048.pem"),
305                       "--internal_release_string \"\"");
306 
307   AvbVBMetaImageHeader h;
308   avb_vbmeta_image_header_to_host_byte_order(
309       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
310 
311   EXPECT_EQ(rollback_index, h.rollback_index);
312 }
313 
TEST_F(AvbToolTest,CheckRollbackIndexLocationOmitted)314 TEST_F(AvbToolTest, CheckRollbackIndexLocationOmitted) {
315   uint32_t expected_rollback_index_location = 0;
316 
317   GenerateVBMetaImage("vbmeta.img",
318                       "SHA256_RSA2048",
319                       0,
320                       base::FilePath("test/data/testkey_rsa2048.pem"),
321                       "--internal_release_string \"\"");
322 
323   AvbVBMetaImageHeader h;
324   avb_vbmeta_image_header_to_host_byte_order(
325       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
326 
327   EXPECT_EQ(expected_rollback_index_location, h.rollback_index_location);
328   EXPECT_EQ(1u, h.required_libavb_version_major);
329   EXPECT_EQ(0u, h.required_libavb_version_minor);
330 }
331 
TEST_F(AvbToolTest,CheckRollbackIndexLocation)332 TEST_F(AvbToolTest, CheckRollbackIndexLocation) {
333   uint32_t rollback_index_location = 42;
334   GenerateVBMetaImage("vbmeta.img",
335                       "SHA256_RSA2048",
336                       0,
337                       base::FilePath("test/data/testkey_rsa2048.pem"),
338                       base::StringPrintf("--rollback_index_location %d",
339                                          rollback_index_location));
340 
341   AvbVBMetaImageHeader h;
342   avb_vbmeta_image_header_to_host_byte_order(
343       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
344 
345   EXPECT_EQ(rollback_index_location, h.rollback_index_location);
346   EXPECT_EQ(1u, h.required_libavb_version_major);
347   EXPECT_EQ(2u, h.required_libavb_version_minor);
348 }
349 
TEST_F(AvbToolTest,CheckPubkeyReturned)350 TEST_F(AvbToolTest, CheckPubkeyReturned) {
351   GenerateVBMetaImage("vbmeta.img",
352                       "SHA256_RSA2048",
353                       0,
354                       base::FilePath("test/data/testkey_rsa2048.pem"),
355                       "--internal_release_string \"\"");
356 
357   const uint8_t* pubkey = NULL;
358   size_t pubkey_length = 0;
359 
360   EXPECT_EQ(
361       AVB_VBMETA_VERIFY_RESULT_OK,
362       avb_vbmeta_image_verify(
363           vbmeta_image_.data(), vbmeta_image_.size(), &pubkey, &pubkey_length));
364 
365   AvbVBMetaImageHeader h;
366   avb_vbmeta_image_header_to_host_byte_order(
367       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
368 
369   EXPECT_EQ(pubkey_length, h.public_key_size);
370 
371   const uint8_t* expected_pubkey =
372       vbmeta_image_.data() + sizeof(AvbVBMetaImageHeader) +
373       h.authentication_data_block_size + h.public_key_offset;
374   EXPECT_EQ(pubkey, expected_pubkey);
375 }
376 
TEST_F(AvbToolTest,Info)377 TEST_F(AvbToolTest, Info) {
378   GenerateVBMetaImage("vbmeta.img",
379                       "SHA256_RSA2048",
380                       0,
381                       base::FilePath("test/data/testkey_rsa2048.pem"),
382                       "--prop foo:brillo "
383                       "--prop bar:chromeos "
384                       "--prop prisoner:24601 "
385                       "--prop hexnumber:0xcafe "
386                       "--prop hexnumber_capital:0xCAFE "
387                       "--prop large_hexnumber:0xfedcba9876543210 "
388                       "--prop larger_than_uint64:0xfedcba98765432101 "
389                       "--prop almost_a_number:423x "
390                       "--prop_from_file blob:test/data/small_blob.bin "
391                       "--prop_from_file large_blob:test/data/large_blob.bin "
392                       "--internal_release_string \"\"");
393 
394   ASSERT_EQ(
395       "Minimum libavb version:   1.0\n"
396       "Header Block:             256 bytes\n"
397       "Authentication Block:     320 bytes\n"
398       "Auxiliary Block:          3200 bytes\n"
399       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
400       "Algorithm:                SHA256_RSA2048\n"
401       "Rollback Index:           0\n"
402       "Flags:                    0\n"
403       "Rollback Index Location:  0\n"
404       "Release String:           ''\n"
405       "Descriptors:\n"
406       "    Prop: foo -> 'brillo'\n"
407       "    Prop: bar -> 'chromeos'\n"
408       "    Prop: prisoner -> '24601'\n"
409       "    Prop: hexnumber -> '0xcafe'\n"
410       "    Prop: hexnumber_capital -> '0xCAFE'\n"
411       "    Prop: large_hexnumber -> '0xfedcba9876543210'\n"
412       "    Prop: larger_than_uint64 -> '0xfedcba98765432101'\n"
413       "    Prop: almost_a_number -> '423x'\n"
414       "    Prop: blob -> '\\x00\\x00brillo "
415       "ftw!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n'\n"
416       "    Prop: large_blob -> (2048 bytes)\n",
417       InfoImage(vbmeta_image_path_));
418 }
419 
collect_descriptors(const AvbDescriptor * descriptor,void * user_data)420 static bool collect_descriptors(const AvbDescriptor* descriptor,
421                                 void* user_data) {
422   std::vector<const AvbDescriptor*>* descriptors =
423       reinterpret_cast<std::vector<const AvbDescriptor*>*>(user_data);
424   descriptors->push_back(descriptor);
425   return true;  // Keep iterating.
426 }
427 
AddHashFooterGetExpectedVBMetaInfo(const bool sparse_image,const uint64_t partition_size)428 static std::string AddHashFooterGetExpectedVBMetaInfo(
429     const bool sparse_image, const uint64_t partition_size) {
430   return base::StringPrintf(
431       "Footer version:           1.0\n"
432       "Image size:               %" PRIu64
433       " bytes\n"
434       "Original image size:      1052672 bytes\n"
435       "VBMeta offset:            1052672\n"
436       "VBMeta size:              1280 bytes\n"
437       "--\n"
438       "Minimum libavb version:   1.0%s\n"
439       "Header Block:             256 bytes\n"
440       "Authentication Block:     320 bytes\n"
441       "Auxiliary Block:          704 bytes\n"
442       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
443       "Algorithm:                SHA256_RSA2048\n"
444       "Rollback Index:           0\n"
445       "Flags:                    0\n"
446       "Rollback Index Location:  0\n"
447       "Release String:           ''\n"
448       "Descriptors:\n"
449       "    Hash descriptor:\n"
450       "      Image Size:            1052672 bytes\n"
451       "      Hash Algorithm:        sha256\n"
452       "      Partition Name:        foobar\n"
453       "      Salt:                  d00df00d\n"
454       "      Digest:                "
455       "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
456       "5e4ed357fbcf58d88d9\n"
457       "      Flags:                 0\n",
458       partition_size,
459       sparse_image ? " (Sparse)" : "");
460 }
461 
AddHashFooterTest(bool sparse_image)462 void AvbToolTest::AddHashFooterTest(bool sparse_image) {
463   const size_t rootfs_size = 1028 * 1024;
464   const size_t partition_size = 1536 * 1024;
465   const size_t resized_partition_size = 1280 * 1024;
466 
467   // Generate a 1028 KiB file with known content. Some content have
468   // been arranged to ensure FILL_DATA segments in the sparse file.
469   std::vector<uint8_t> rootfs;
470   rootfs.resize(rootfs_size);
471   for (size_t n = 0; n < rootfs_size; n++) {
472     if ((n >= 5 * 1000 && n < 105 * 1000) ||
473         (n >= 205 * 1000 && n < 305 * 1000) ||
474         (n >= 505 * 1000 && n < 605 * 1000)) {
475       rootfs[n] = uint8_t(n) & 0x03;
476     } else {
477       rootfs[n] = uint8_t(n);
478     }
479   }
480   base::FilePath external_vbmeta_path = testdir_.Append("external_vbmeta.bin");
481   base::FilePath extracted_vbmeta_path =
482       testdir_.Append("extracted_vbmeta.bin");
483   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
484   EXPECT_EQ(rootfs_size,
485             static_cast<const size_t>(
486                 base::WriteFile(rootfs_path,
487                                 reinterpret_cast<const char*>(rootfs.data()),
488                                 rootfs.size())));
489 
490   if (sparse_image) {
491     EXPECT_COMMAND(0,
492                    "mv %s %s.unsparse",
493                    rootfs_path.value().c_str(),
494                    rootfs_path.value().c_str());
495     EXPECT_COMMAND(0,
496                    "img2simg %s.unsparse %s",
497                    rootfs_path.value().c_str(),
498                    rootfs_path.value().c_str());
499     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
500   }
501 
502   /* Do this twice to check that 'add_hash_footer' is idempotent. */
503   for (int n = 0; n < 2; n++) {
504     EXPECT_COMMAND(0,
505                    "./avbtool.py add_hash_footer --salt d00df00d "
506                    "--hash_algorithm sha256 --image %s "
507                    "--partition_size %d --partition_name foobar "
508                    "--algorithm SHA256_RSA2048 "
509                    "--key test/data/testkey_rsa2048.pem "
510                    "--output_vbmeta %s "
511                    "--internal_release_string \"\"",
512                    rootfs_path.value().c_str(),
513                    (int)partition_size,
514                    external_vbmeta_path.value().c_str());
515 
516     ASSERT_EQ(AddHashFooterGetExpectedVBMetaInfo(sparse_image, partition_size),
517               InfoImage(rootfs_path));
518 
519     ASSERT_EQ(
520         "Minimum libavb version:   1.0\n"
521         "Header Block:             256 bytes\n"
522         "Authentication Block:     320 bytes\n"
523         "Auxiliary Block:          704 bytes\n"
524         "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
525         "Algorithm:                SHA256_RSA2048\n"
526         "Rollback Index:           0\n"
527         "Flags:                    0\n"
528         "Rollback Index Location:  0\n"
529         "Release String:           ''\n"
530         "Descriptors:\n"
531         "    Hash descriptor:\n"
532         "      Image Size:            1052672 bytes\n"
533         "      Hash Algorithm:        sha256\n"
534         "      Partition Name:        foobar\n"
535         "      Salt:                  d00df00d\n"
536         "      Digest:                "
537         "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
538         "5e4ed357fbcf58d88d9\n"
539         "      Flags:                 0\n",
540         InfoImage(external_vbmeta_path));
541 
542     // Check that the extracted vbmeta matches the externally generally one.
543     EXPECT_COMMAND(0,
544                    "./avbtool.py extract_vbmeta_image --image %s "
545                    "--output %s",
546                    rootfs_path.value().c_str(),
547                    extracted_vbmeta_path.value().c_str());
548     EXPECT_COMMAND(0,
549                    "diff %s %s",
550                    external_vbmeta_path.value().c_str(),
551                    extracted_vbmeta_path.value().c_str());
552   }
553 
554   // Resize the image and check that the only thing that has changed
555   // is where the footer is. First check that resizing to a smaller
556   // size than the original rootfs fails. Then resize to something
557   // larger than the original rootfs but smaller than the current
558   // partition size.
559   EXPECT_COMMAND(1,
560                  "./avbtool.py resize_image --image %s "
561                  "--partition_size %d",
562                  rootfs_path.value().c_str(),
563                  (int)(rootfs_size - 16 * 1024));
564   EXPECT_COMMAND(0,
565                  "./avbtool.py resize_image --image %s "
566                  "--partition_size %d",
567                  rootfs_path.value().c_str(),
568                  (int)resized_partition_size);
569   ASSERT_EQ(
570       AddHashFooterGetExpectedVBMetaInfo(sparse_image, resized_partition_size),
571       InfoImage(rootfs_path));
572 
573   if (sparse_image) {
574     EXPECT_COMMAND(0,
575                    "mv %s %s.sparse",
576                    rootfs_path.value().c_str(),
577                    rootfs_path.value().c_str());
578     EXPECT_COMMAND(0,
579                    "simg2img %s.sparse %s",
580                    rootfs_path.value().c_str(),
581                    rootfs_path.value().c_str());
582     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
583   }
584 
585   // Manually calculate the hash to check that it agrees with avbtool.
586   AvbSHA256Ctx hasher_ctx;
587   const uint8_t hasher_salt[4] = {0xd0, 0x0d, 0xf0, 0x0d};
588   avb_sha256_init(&hasher_ctx);
589   avb_sha256_update(&hasher_ctx, hasher_salt, 4);
590   avb_sha256_update(&hasher_ctx, rootfs.data(), rootfs_size);
591   uint8_t* hasher_digest = avb_sha256_final(&hasher_ctx);
592   EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
593             mem_to_hexstring(hasher_digest, AVB_SHA256_DIGEST_SIZE));
594 
595   // Now check that we can find the VBMeta block again from the footer.
596   std::string part_data;
597   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
598 
599   // Check footer contains correct data.
600   AvbFooter f;
601   EXPECT_NE(0,
602             avb_footer_validate_and_byteswap(
603                 reinterpret_cast<const AvbFooter*>(
604                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
605                 &f));
606   EXPECT_EQ(
607       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
608       AVB_FOOTER_MAGIC);
609   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
610   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
611   EXPECT_EQ(1052672UL, f.original_image_size);
612   EXPECT_EQ(1052672UL, f.vbmeta_offset);
613   EXPECT_EQ(1280UL, f.vbmeta_size);
614 
615   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
616   const uint8_t* vbmeta_data =
617       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
618   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
619             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
620 
621   // Collect all descriptors.
622   std::vector<const AvbDescriptor*> descriptors;
623   avb_descriptor_foreach(
624       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
625 
626   // We should only have a single descriptor and it should be a
627   // hash descriptor.
628   EXPECT_EQ(1UL, descriptors.size());
629   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, avb_be64toh(descriptors[0]->tag));
630   AvbHashDescriptor d;
631   EXPECT_NE(
632       0,
633       avb_hash_descriptor_validate_and_byteswap(
634           reinterpret_cast<const AvbHashDescriptor*>(descriptors[0]), &d));
635   EXPECT_EQ(1052672UL, d.image_size);
636   EXPECT_EQ(6UL, d.partition_name_len);
637   EXPECT_EQ(4UL, d.salt_len);
638   EXPECT_EQ(32UL, d.digest_len);
639   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
640                             sizeof(AvbHashDescriptor);
641   uint64_t o = 0;
642   EXPECT_EQ("foobar",
643             std::string(reinterpret_cast<const char*>(desc_end + o),
644                         d.partition_name_len));
645   o += d.partition_name_len;
646   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
647   o += d.salt_len;
648   EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
649             mem_to_hexstring(desc_end + o, d.digest_len));
650 
651   // Check that the footer is correctly erased.
652   EXPECT_COMMAND(
653       0, "./avbtool.py erase_footer --image %s", rootfs_path.value().c_str());
654   int64_t erased_footer_file_size;
655   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
656   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size);
657 
658   // Check that --do_not_append_vbmeta_image works as intended.
659   EXPECT_COMMAND(0,
660                  "./avbtool.py add_hash_footer --salt d00df00d "
661                  "--hash_algorithm sha256 --image %s "
662                  "--partition_size %d --partition_name foobar "
663                  "--algorithm SHA256_RSA2048 "
664                  "--key test/data/testkey_rsa2048.pem "
665                  "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
666                  "--internal_release_string \"\"",
667                  rootfs_path.value().c_str(),
668                  (int)partition_size,
669                  external_vbmeta_path.value().c_str());
670   int64_t file_size;
671   ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
672   EXPECT_EQ(static_cast<size_t>(file_size), rootfs_size);
673   EXPECT_COMMAND(0,
674                  "diff %s %s_2nd_run",
675                  external_vbmeta_path.value().c_str(),
676                  external_vbmeta_path.value().c_str());
677 }
678 
TEST_F(AvbToolTest,AddHashFooter)679 TEST_F(AvbToolTest, AddHashFooter) {
680   AddHashFooterTest(false);
681 }
682 
TEST_F(AvbToolTest,AddHashFooterSparse)683 TEST_F(AvbToolTest, AddHashFooterSparse) {
684   AddHashFooterTest(true);
685 }
686 
RemoveLinesStartingWith(const std::string & str,const std::string & prefix)687 static std::string RemoveLinesStartingWith(const std::string& str,
688                                            const std::string& prefix) {
689   std::vector<std::string> lines;
690   std::string ret;
691 
692   lines = base::SplitString(
693       str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
694   for (const std::string& line : lines) {
695     if (!base::StartsWith(line, prefix, base::CompareCase::SENSITIVE)) {
696       ret += line;
697       ret += '\n';
698     }
699   }
700   return ret;
701 }
702 
703 // NOTE: make_ext4fs was removed and there is no replacement for how we use
704 // it... so this is currently disabled..
TEST_F(AvbToolTest,DISABLED_AddHashFooterSparseWithHoleAtTheEnd)705 TEST_F(AvbToolTest, DISABLED_AddHashFooterSparseWithHoleAtTheEnd) {
706   const size_t partition_size = 10 * 1024 * 1024;
707   const size_t metadata_size = 128 * 1024;
708 
709   // It's not enough to run img2simg on a file with a lot of zeroes at
710   // the end since that will turn up as "Fill with value (for value =
711   // 0x00000000)" and not "Don't care". Instead, use make_ext4fs for
712   // this since it will put a big hole (e.g. "Don't care" chunk) at
713   // the end.
714   base::FilePath partition_path = testdir_.Append("partition.bin");
715   EXPECT_COMMAND(0,
716                  "make_ext4fs -s -L test -l %zd %s",
717                  partition_size - metadata_size,
718                  partition_path.value().c_str());
719 
720   EXPECT_COMMAND(0,
721                  "./avbtool.py add_hash_footer --salt d00df00d "
722                  "--hash_algorithm sha256 --image %s "
723                  "--partition_size %d --partition_name foobar "
724                  "--algorithm SHA256_RSA2048 "
725                  "--key test/data/testkey_rsa2048.pem "
726                  "--internal_release_string \"\"",
727                  partition_path.value().c_str(),
728                  (int)partition_size);
729 
730   // Since we may be using an arbritary version of make_ext4fs
731   // (because of different branches) the contents of the resulting
732   // disk image may slightly change. It's enough to just remove the
733   // "Digest:" line from the output to work around this.
734   std::string info =
735       RemoveLinesStartingWith(InfoImage(partition_path), "      Digest:");
736   ASSERT_EQ(
737       "Footer version:           1.0\n"
738       "Image size:               10485760 bytes\n"
739       "Original image size:      10354688 bytes\n"
740       "VBMeta offset:            10354688\n"
741       "VBMeta size:              1280 bytes\n"
742       "--\n"
743       "Minimum libavb version:   1.0 (Sparse)\n"
744       "Header Block:             256 bytes\n"
745       "Authentication Block:     320 bytes\n"
746       "Auxiliary Block:          704 bytes\n"
747       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
748       "Algorithm:                SHA256_RSA2048\n"
749       "Rollback Index:           0\n"
750       "Flags:                    0\n"
751       "Rollback Index Location:  0\n"
752       "Release String:           ''\n"
753       "Descriptors:\n"
754       "    Hash descriptor:\n"
755       "      Image Size:            10354688 bytes\n"
756       "      Hash Algorithm:        sha256\n"
757       "      Partition Name:        foobar\n"
758       "      Salt:                  d00df00d\n"
759       "      Flags:                 0\n",
760       info);
761 
762   EXPECT_COMMAND(0,
763                  "mv %s %s.sparse",
764                  partition_path.value().c_str(),
765                  partition_path.value().c_str());
766   EXPECT_COMMAND(0,
767                  "simg2img %s.sparse %s",
768                  partition_path.value().c_str(),
769                  partition_path.value().c_str());
770   EXPECT_COMMAND(0, "rm -f %s.sparse", partition_path.value().c_str());
771 }
772 
TEST_F(AvbToolTest,AddHashFooterCalcMaxImageSize)773 TEST_F(AvbToolTest, AddHashFooterCalcMaxImageSize) {
774   const size_t partition_size = 10 * 1024 * 1024;
775   base::FilePath output_path = testdir_.Append("max_size.txt");
776 
777   EXPECT_COMMAND(0,
778                  "./avbtool.py add_hash_footer "
779                  "--partition_size %zd "
780                  "--calc_max_image_size > %s",
781                  partition_size,
782                  output_path.value().c_str());
783   std::string max_image_size_data;
784   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
785   EXPECT_EQ("10416128\n", max_image_size_data);
786   size_t max_image_size = atoll(max_image_size_data.c_str());
787 
788   // Metadata takes up 68 KiB.
789   EXPECT_EQ(68 * 1024ULL, partition_size - max_image_size);
790 
791   // Check that we can add a hash footer for an image this size for
792   // such a partition size.
793   base::FilePath boot_path = GenerateImage("boot", max_image_size);
794   EXPECT_COMMAND(0,
795                  "./avbtool.py add_hash_footer"
796                  " --image %s"
797                  " --partition_name boot"
798                  " --partition_size %zd"
799                  " --salt deadbeef"
800                  " --algorithm SHA512_RSA4096 "
801                  " --key test/data/testkey_rsa4096.pem"
802                  " --internal_release_string \"\"",
803                  boot_path.value().c_str(),
804                  partition_size);
805 }
806 
TEST_F(AvbToolTest,AddHashFooterWithPersistentDigest)807 TEST_F(AvbToolTest, AddHashFooterWithPersistentDigest) {
808   size_t partition_size = 1024 * 1024;
809   base::FilePath path = GenerateImage("digest_location", 1024);
810   EXPECT_COMMAND(0,
811                  "./avbtool.py add_hash_footer "
812                  "--hash_algorithm sha256 --image %s "
813                  "--partition_size %d --partition_name foobar "
814                  "--algorithm SHA256_RSA2048 "
815                  "--key test/data/testkey_rsa2048.pem "
816                  "--internal_release_string \"\" "
817                  "--use_persistent_digest",
818                  path.value().c_str(),
819                  (int)partition_size);
820   // There are two important bits specific to these flags:
821   //   Minimum libavb version = 1.1
822   //   Hash descriptor -> Digest = (empty)
823   ASSERT_EQ(
824       "Footer version:           1.0\n"
825       "Image size:               1048576 bytes\n"
826       "Original image size:      1024 bytes\n"
827       "VBMeta offset:            4096\n"
828       "VBMeta size:              1280 bytes\n"
829       "--\n"
830       "Minimum libavb version:   1.1\n"
831       "Header Block:             256 bytes\n"
832       "Authentication Block:     320 bytes\n"
833       "Auxiliary Block:          704 bytes\n"
834       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
835       "Algorithm:                SHA256_RSA2048\n"
836       "Rollback Index:           0\n"
837       "Flags:                    0\n"
838       "Rollback Index Location:  0\n"
839       "Release String:           ''\n"
840       "Descriptors:\n"
841       "    Hash descriptor:\n"
842       "      Image Size:            1024 bytes\n"
843       "      Hash Algorithm:        sha256\n"
844       "      Partition Name:        foobar\n"
845       "      Salt:                  \n"
846       "      Digest:                \n"
847       "      Flags:                 0\n",
848       InfoImage(path));
849 }
850 
TEST_F(AvbToolTest,AddHashFooterWithNoAB)851 TEST_F(AvbToolTest, AddHashFooterWithNoAB) {
852   size_t partition_size = 1024 * 1024;
853   base::FilePath path = GenerateImage("digest_location", 1024);
854   EXPECT_COMMAND(0,
855                  "./avbtool.py add_hash_footer --salt d00df00d "
856                  "--hash_algorithm sha256 --image %s "
857                  "--partition_size %d --partition_name foobar "
858                  "--algorithm SHA256_RSA2048 "
859                  "--key test/data/testkey_rsa2048.pem "
860                  "--internal_release_string \"\" "
861                  "--do_not_use_ab",
862                  path.value().c_str(),
863                  (int)partition_size);
864   // There are two important bits specific to these flags:
865   //   Minimum libavb version = 1.1
866   //   Hash descriptor -> Flags = 1
867   ASSERT_EQ(
868       "Footer version:           1.0\n"
869       "Image size:               1048576 bytes\n"
870       "Original image size:      1024 bytes\n"
871       "VBMeta offset:            4096\n"
872       "VBMeta size:              1280 bytes\n"
873       "--\n"
874       "Minimum libavb version:   1.1\n"
875       "Header Block:             256 bytes\n"
876       "Authentication Block:     320 bytes\n"
877       "Auxiliary Block:          704 bytes\n"
878       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
879       "Algorithm:                SHA256_RSA2048\n"
880       "Rollback Index:           0\n"
881       "Flags:                    0\n"
882       "Rollback Index Location:  0\n"
883       "Release String:           ''\n"
884       "Descriptors:\n"
885       "    Hash descriptor:\n"
886       "      Image Size:            1024 bytes\n"
887       "      Hash Algorithm:        sha256\n"
888       "      Partition Name:        foobar\n"
889       "      Salt:                  d00df00d\n"
890       "      Digest:                "
891       "91386fea3e251ad0c2cb6859e4f4772f37fdb69f17d46636ddc9e7fbfd3bf3d0\n"
892       "      Flags:                 1\n",
893       InfoImage(path));
894 }
895 
TEST_F(AvbToolTest,AddHashFooterWithPersistentDigestAndNoAB)896 TEST_F(AvbToolTest, AddHashFooterWithPersistentDigestAndNoAB) {
897   size_t partition_size = 1024 * 1024;
898   base::FilePath path = GenerateImage("digest_location", 1024);
899   EXPECT_COMMAND(0,
900                  "./avbtool.py add_hash_footer "
901                  "--hash_algorithm sha256 --image %s "
902                  "--partition_size %d --partition_name foobar "
903                  "--algorithm SHA256_RSA2048 "
904                  "--key test/data/testkey_rsa2048.pem "
905                  "--internal_release_string \"\" "
906                  "--use_persistent_digest --do_not_use_ab",
907                  path.value().c_str(),
908                  (int)partition_size);
909   // There are three important bits specific to these flags:
910   //   Minimum libavb version = 1.1
911   //   Hash descriptor -> Digest = (empty)
912   //   Hash descriptor -> Flags = 1
913   ASSERT_EQ(
914       "Footer version:           1.0\n"
915       "Image size:               1048576 bytes\n"
916       "Original image size:      1024 bytes\n"
917       "VBMeta offset:            4096\n"
918       "VBMeta size:              1280 bytes\n"
919       "--\n"
920       "Minimum libavb version:   1.1\n"
921       "Header Block:             256 bytes\n"
922       "Authentication Block:     320 bytes\n"
923       "Auxiliary Block:          704 bytes\n"
924       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
925       "Algorithm:                SHA256_RSA2048\n"
926       "Rollback Index:           0\n"
927       "Flags:                    0\n"
928       "Rollback Index Location:  0\n"
929       "Release String:           ''\n"
930       "Descriptors:\n"
931       "    Hash descriptor:\n"
932       "      Image Size:            1024 bytes\n"
933       "      Hash Algorithm:        sha256\n"
934       "      Partition Name:        foobar\n"
935       "      Salt:                  \n"
936       "      Digest:                \n"
937       "      Flags:                 1\n",
938       InfoImage(path));
939 }
940 
CreateRootfsWithHashtreeFooter(bool sparse_image,const std::string & hash_algorithm,const std::string & root_digest,base::FilePath * output_rootfs_path)941 void AvbToolTest::CreateRootfsWithHashtreeFooter(
942     bool sparse_image,
943     const std::string& hash_algorithm,
944     const std::string& root_digest,
945     base::FilePath* output_rootfs_path) {
946   const size_t rootfs_size = 1028 * 1024;
947   const size_t partition_size = 1536 * 1024;
948 
949   // Generate a 1028 KiB file with known content.
950   std::vector<uint8_t> rootfs;
951   rootfs.resize(rootfs_size);
952   for (size_t n = 0; n < rootfs_size; n++)
953     rootfs[n] = uint8_t(n);
954   base::FilePath external_vbmeta_path = testdir_.Append("external_vbmeta.bin");
955   base::FilePath extracted_vbmeta_path =
956       testdir_.Append("extracted_vbmeta.bin");
957   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
958   EXPECT_EQ(rootfs_size,
959             static_cast<const size_t>(
960                 base::WriteFile(rootfs_path,
961                                 reinterpret_cast<const char*>(rootfs.data()),
962                                 rootfs.size())));
963 
964   if (sparse_image) {
965     EXPECT_COMMAND(0,
966                    "mv %s %s.unsparse",
967                    rootfs_path.value().c_str(),
968                    rootfs_path.value().c_str());
969     EXPECT_COMMAND(0,
970                    "img2simg %s.unsparse %s",
971                    rootfs_path.value().c_str(),
972                    rootfs_path.value().c_str());
973     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
974   }
975 
976   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
977   for (int n = 0; n < 2; n++) {
978     EXPECT_COMMAND(0,
979                    "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
980                    "--hash_algorithm %s "
981                    "--partition_size %d --partition_name foobar "
982                    "--algorithm SHA256_RSA2048 "
983                    "--key test/data/testkey_rsa2048.pem "
984                    "--output_vbmeta_image %s "
985                    "--internal_release_string \"\" "
986                    "--do_not_generate_fec",
987                    rootfs_path.value().c_str(),
988                    hash_algorithm.c_str(),
989                    (int)partition_size,
990                    external_vbmeta_path.value().c_str());
991 
992     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
993                                  "Image size:               1572864 bytes\n"
994                                  "Original image size:      1052672 bytes\n"
995                                  "VBMeta offset:            1069056\n"
996                                  "VBMeta size:              1344 bytes\n"
997                                  "--\n"
998                                  "Minimum libavb version:   1.0%s\n"
999                                  "Header Block:             256 bytes\n"
1000                                  "Authentication Block:     320 bytes\n"
1001                                  "Auxiliary Block:          768 bytes\n"
1002                                  "Public key (sha1):        "
1003                                  "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1004                                  "Algorithm:                SHA256_RSA2048\n"
1005                                  "Rollback Index:           0\n"
1006                                  "Flags:                    0\n"
1007                                  "Rollback Index Location:  0\n"
1008                                  "Release String:           ''\n"
1009                                  "Descriptors:\n"
1010                                  "    Hashtree descriptor:\n"
1011                                  "      Version of dm-verity:  1\n"
1012                                  "      Image Size:            1052672 bytes\n"
1013                                  "      Tree Offset:           1052672\n"
1014                                  "      Tree Size:             16384 bytes\n"
1015                                  "      Data Block Size:       4096 bytes\n"
1016                                  "      Hash Block Size:       4096 bytes\n"
1017                                  "      FEC num roots:         0\n"
1018                                  "      FEC offset:            0\n"
1019                                  "      FEC size:              0 bytes\n"
1020                                  "      Hash Algorithm:        %s\n"
1021                                  "      Partition Name:        foobar\n"
1022                                  "      Salt:                  d00df00d\n"
1023                                  "      Root Digest:           "
1024                                  "%s\n"
1025                                  "      Flags:                 0\n",
1026                                  sparse_image ? " (Sparse)" : "",
1027                                  hash_algorithm.c_str(),
1028                                  root_digest.c_str()),
1029               InfoImage(rootfs_path));
1030 
1031     ASSERT_EQ(base::StringPrintf("Minimum libavb version:   1.0\n"
1032                                  "Header Block:             256 bytes\n"
1033                                  "Authentication Block:     320 bytes\n"
1034                                  "Auxiliary Block:          768 bytes\n"
1035                                  "Public key (sha1):        "
1036                                  "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1037                                  "Algorithm:                SHA256_RSA2048\n"
1038                                  "Rollback Index:           0\n"
1039                                  "Flags:                    0\n"
1040                                  "Rollback Index Location:  0\n"
1041                                  "Release String:           ''\n"
1042                                  "Descriptors:\n"
1043                                  "    Hashtree descriptor:\n"
1044                                  "      Version of dm-verity:  1\n"
1045                                  "      Image Size:            1052672 bytes\n"
1046                                  "      Tree Offset:           1052672\n"
1047                                  "      Tree Size:             16384 bytes\n"
1048                                  "      Data Block Size:       4096 bytes\n"
1049                                  "      Hash Block Size:       4096 bytes\n"
1050                                  "      FEC num roots:         0\n"
1051                                  "      FEC offset:            0\n"
1052                                  "      FEC size:              0 bytes\n"
1053                                  "      Hash Algorithm:        %s\n"
1054                                  "      Partition Name:        foobar\n"
1055                                  "      Salt:                  d00df00d\n"
1056                                  "      Root Digest:           "
1057                                  "%s\n"
1058                                  "      Flags:                 0\n",
1059                                  hash_algorithm.c_str(),
1060                                  root_digest.c_str()),
1061               InfoImage(external_vbmeta_path));
1062 
1063     // Check that the extracted vbmeta matches the externally generally one.
1064     EXPECT_COMMAND(0,
1065                    "./avbtool.py extract_vbmeta_image --image %s "
1066                    "--output %s",
1067                    rootfs_path.value().c_str(),
1068                    extracted_vbmeta_path.value().c_str());
1069     EXPECT_COMMAND(0,
1070                    "diff %s %s",
1071                    external_vbmeta_path.value().c_str(),
1072                    extracted_vbmeta_path.value().c_str());
1073   }
1074 
1075   *output_rootfs_path = rootfs_path;
1076 }
1077 
AddHashtreeFooterTest(bool sparse_image)1078 void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
1079   base::FilePath rootfs_path;
1080   CreateRootfsWithHashtreeFooter(sparse_image,
1081                                  "sha1",
1082                                  "e811611467dcd6e8dc4324e45f706c2bdd51db67",
1083                                  &rootfs_path);
1084 
1085   /* Zero the hashtree on a copy of the image. */
1086   EXPECT_COMMAND(0,
1087                  "cp %s %s.zht",
1088                  rootfs_path.value().c_str(),
1089                  rootfs_path.value().c_str());
1090   EXPECT_COMMAND(0,
1091                  "./avbtool.py zero_hashtree --image %s.zht ",
1092                  rootfs_path.value().c_str());
1093 
1094   if (sparse_image) {
1095     EXPECT_COMMAND(0,
1096                    "mv %s %s.sparse",
1097                    rootfs_path.value().c_str(),
1098                    rootfs_path.value().c_str());
1099     EXPECT_COMMAND(0,
1100                    "simg2img %s.sparse %s",
1101                    rootfs_path.value().c_str(),
1102                    rootfs_path.value().c_str());
1103     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
1104 
1105     EXPECT_COMMAND(0,
1106                    "mv %s.zht %s.zht.sparse",
1107                    rootfs_path.value().c_str(),
1108                    rootfs_path.value().c_str());
1109     EXPECT_COMMAND(0,
1110                    "simg2img %s.zht.sparse %s.zht",
1111                    rootfs_path.value().c_str(),
1112                    rootfs_path.value().c_str());
1113     EXPECT_COMMAND(0, "rm -f %s.zht.sparse", rootfs_path.value().c_str());
1114   }
1115 
1116   // To check that we generate the correct hashtree we can use
1117   // veritysetup(1) - another codebase for working with dm-verity
1118   // hashtrees - to verify it.
1119   //
1120   // If we don't want to impose the requirement of having the
1121   // veritysetup(1) command available on builders we can comment this
1122   // out.
1123   EXPECT_COMMAND(0,
1124                  "veritysetup --no-superblock --format=1 --hash=sha1 "
1125                  "--data-block-size=4096 --hash-block-size=4096 "
1126                  "--salt=d00df00d "
1127                  "--data-blocks=257 "
1128                  "--hash-offset=1052672 "
1129                  "verify "
1130                  "%s %s "
1131                  "e811611467dcd6e8dc4324e45f706c2bdd51db67",
1132                  rootfs_path.value().c_str(),
1133                  rootfs_path.value().c_str());
1134 
1135   // Now check that we can find the VBMeta block again from the footer.
1136   std::string part_data;
1137   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1138 
1139   // Also read the zeroed hash-tree version.
1140   std::string zht_part_data;
1141   ASSERT_TRUE(base::ReadFileToString(
1142       base::FilePath(rootfs_path.value() + ".zht"), &zht_part_data));
1143 
1144   // Check footer contains correct data.
1145   AvbFooter f;
1146   EXPECT_NE(0,
1147             avb_footer_validate_and_byteswap(
1148                 reinterpret_cast<const AvbFooter*>(
1149                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1150                 &f));
1151   EXPECT_EQ(
1152       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1153       AVB_FOOTER_MAGIC);
1154   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1155   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1156   EXPECT_EQ(1052672UL, f.original_image_size);
1157   EXPECT_EQ(1069056UL, f.vbmeta_offset);
1158   EXPECT_EQ(1344UL, f.vbmeta_size);
1159 
1160   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1161   const uint8_t* vbmeta_data =
1162       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1163   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1164             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1165 
1166   // Collect all descriptors.
1167   std::vector<const AvbDescriptor*> descriptors;
1168   avb_descriptor_foreach(
1169       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1170 
1171   // We should only have a single descriptor and it should be a
1172   // hashtree descriptor.
1173   EXPECT_EQ(1UL, descriptors.size());
1174   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1175   AvbHashtreeDescriptor d;
1176   EXPECT_NE(
1177       0,
1178       avb_hashtree_descriptor_validate_and_byteswap(
1179           reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1180   EXPECT_EQ(1UL, d.dm_verity_version);
1181   EXPECT_EQ(1052672UL, d.image_size);
1182   EXPECT_EQ(1052672UL, d.tree_offset);
1183   EXPECT_EQ(16384UL, d.tree_size);
1184   EXPECT_EQ(4096UL, d.data_block_size);
1185   EXPECT_EQ(4096UL, d.hash_block_size);
1186   EXPECT_EQ(6UL, d.partition_name_len);
1187   EXPECT_EQ(4UL, d.salt_len);
1188   EXPECT_EQ(20UL, d.root_digest_len);
1189   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1190                             sizeof(AvbHashtreeDescriptor);
1191   uint64_t o = 0;
1192   EXPECT_EQ("foobar",
1193             std::string(reinterpret_cast<const char*>(desc_end + o),
1194                         d.partition_name_len));
1195   o += d.partition_name_len;
1196   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1197   o += d.salt_len;
1198   EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1199             mem_to_hexstring(desc_end + o, d.root_digest_len));
1200 
1201   // Check that the zeroed hashtree version differ only by the hashtree + fec
1202   // being zeroed out.
1203   EXPECT_EQ(part_data.size(), zht_part_data.size());
1204   size_t zht_ht_begin = d.tree_offset;
1205   size_t zht_ht_end = zht_ht_begin + d.tree_size;
1206   size_t zht_fec_begin = zht_ht_end;
1207   size_t zht_fec_end = zht_fec_begin + d.fec_size;
1208   EXPECT_EQ(0, memcmp(part_data.data(), zht_part_data.data(), zht_ht_begin));
1209   EXPECT_NE(0,
1210             memcmp(part_data.data() + zht_ht_begin,
1211                    zht_part_data.data() + zht_ht_begin,
1212                    zht_fec_end - zht_ht_begin));
1213   EXPECT_EQ(0,
1214             memcmp(part_data.data() + zht_fec_end,
1215                    zht_part_data.data() + zht_fec_end,
1216                    zht_part_data.size() - zht_fec_end));
1217   EXPECT_EQ(0, strncmp(zht_part_data.data() + zht_ht_begin, "ZeRoHaSH", 8));
1218   for (size_t n = zht_ht_begin + 8; n < zht_ht_end; n++) {
1219     EXPECT_EQ(0, zht_part_data.data()[n]);
1220   }
1221   if (d.fec_size > 0) {
1222     EXPECT_EQ(0, strncmp(zht_part_data.data() + zht_fec_begin, "ZeRoHaSH", 8));
1223     for (size_t n = zht_fec_begin + 8; n < zht_fec_end; n++) {
1224       EXPECT_EQ(0, zht_part_data.data()[n]);
1225     }
1226   }
1227 
1228   // Check that we correctly generate dm-verity kernel cmdline
1229   // snippets, if requested.
1230   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1231   EXPECT_COMMAND(0,
1232                  "./avbtool.py make_vbmeta_image "
1233                  "--output %s "
1234                  "--setup_rootfs_from_kernel %s "
1235                  "--algorithm SHA256_RSA2048 "
1236                  "--key test/data/testkey_rsa2048.pem "
1237                  "--internal_release_string \"\"",
1238                  vbmeta_dmv_path.value().c_str(),
1239                  rootfs_path.value().c_str());
1240 
1241   ASSERT_EQ(
1242       "Minimum libavb version:   1.0\n"
1243       "Header Block:             256 bytes\n"
1244       "Authentication Block:     320 bytes\n"
1245       "Auxiliary Block:          896 bytes\n"
1246       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1247       "Algorithm:                SHA256_RSA2048\n"
1248       "Rollback Index:           0\n"
1249       "Flags:                    0\n"
1250       "Rollback Index Location:  0\n"
1251       "Release String:           ''\n"
1252       "Descriptors:\n"
1253       "    Kernel Cmdline descriptor:\n"
1254       "      Flags:                 1\n"
1255       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1256       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1257       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1258       "d00df00d 2 $(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
1259       "    Kernel Cmdline descriptor:\n"
1260       "      Flags:                 2\n"
1261       "      Kernel Cmdline:        "
1262       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1263       InfoImage(vbmeta_dmv_path));
1264 
1265   // Check that the footer is correctly erased and the hashtree
1266   // remains - see above for why the constant 1069056 is used.
1267   EXPECT_COMMAND(0,
1268                  "./avbtool.py erase_footer --image %s --keep_hashtree",
1269                  rootfs_path.value().c_str());
1270   int64_t erased_footer_file_size;
1271   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1272   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1069056UL);
1273 
1274   const size_t rootfs_size = 1028 * 1024;
1275   const size_t partition_size = 1536 * 1024;
1276   base::FilePath external_vbmeta_path = testdir_.Append("external_vbmeta.bin");
1277   // Check that --do_not_append_vbmeta_image works as intended.
1278   //
1279   // For this we need to reset the size of the image to the original
1280   // size because it's not possible to identify the existing hashtree.
1281   EXPECT_COMMAND(
1282       0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str());
1283   EXPECT_COMMAND(0,
1284                  "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
1285                  "--partition_size %d --partition_name foobar "
1286                  "--algorithm SHA256_RSA2048 "
1287                  "--key test/data/testkey_rsa2048.pem "
1288                  "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
1289                  "--internal_release_string \"\" "
1290                  "--do_not_generate_fec",
1291                  rootfs_path.value().c_str(),
1292                  (int)partition_size,
1293                  external_vbmeta_path.value().c_str());
1294   int64_t file_size;
1295   ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
1296   EXPECT_EQ(static_cast<size_t>(file_size), 1069056UL);
1297   EXPECT_COMMAND(0,
1298                  "diff %s %s_2nd_run",
1299                  external_vbmeta_path.value().c_str(),
1300                  external_vbmeta_path.value().c_str());
1301 }
1302 
TEST_F(AvbToolTest,AddHashtreeFooter)1303 TEST_F(AvbToolTest, AddHashtreeFooter) {
1304   AddHashtreeFooterTest(false);
1305 }
1306 
TEST_F(AvbToolTest,AddHashtreeFooterSparse)1307 TEST_F(AvbToolTest, AddHashtreeFooterSparse) {
1308   AddHashtreeFooterTest(true);
1309 }
1310 
TEST_F(AvbToolTest,AddHashtreeFooterSparseWithBlake2b256)1311 TEST_F(AvbToolTest, AddHashtreeFooterSparseWithBlake2b256) {
1312   base::FilePath rootfs_path;
1313   CreateRootfsWithHashtreeFooter(
1314       true,
1315       "blake2b-256",
1316       "9ed423dda921619181bf1889746fe2dd28ae1e673be8d802b4713122e3209513",
1317       &rootfs_path);
1318 }
1319 
AddHashtreeFooterFECTest(bool sparse_image)1320 void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
1321   const size_t rootfs_size = 1028 * 1024;
1322   const size_t partition_size = 1536 * 1024;
1323 
1324   // Generate a 1028 KiB file with known content.
1325   std::vector<uint8_t> rootfs;
1326   rootfs.resize(rootfs_size);
1327   for (size_t n = 0; n < rootfs_size; n++)
1328     rootfs[n] = uint8_t(n);
1329   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
1330   EXPECT_EQ(rootfs_size,
1331             static_cast<const size_t>(
1332                 base::WriteFile(rootfs_path,
1333                                 reinterpret_cast<const char*>(rootfs.data()),
1334                                 rootfs.size())));
1335 
1336   if (sparse_image) {
1337     EXPECT_COMMAND(0,
1338                    "mv %s %s.unsparse",
1339                    rootfs_path.value().c_str(),
1340                    rootfs_path.value().c_str());
1341     EXPECT_COMMAND(0,
1342                    "img2simg %s.unsparse %s",
1343                    rootfs_path.value().c_str(),
1344                    rootfs_path.value().c_str());
1345     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
1346   }
1347 
1348   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
1349   for (int n = 0; n < 2; n++) {
1350     EXPECT_COMMAND(0,
1351                    "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
1352                    "--partition_size %d --partition_name foobar "
1353                    "--algorithm SHA256_RSA2048 "
1354                    "--key test/data/testkey_rsa2048.pem "
1355                    "--internal_release_string \"\"",
1356                    rootfs_path.value().c_str(),
1357                    (int)partition_size);
1358 
1359     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
1360                                  "Image size:               1572864 bytes\n"
1361                                  "Original image size:      1052672 bytes\n"
1362                                  "VBMeta offset:            1085440\n"
1363                                  "VBMeta size:              1344 bytes\n"
1364                                  "--\n"
1365                                  "Minimum libavb version:   1.0%s\n"
1366                                  "Header Block:             256 bytes\n"
1367                                  "Authentication Block:     320 bytes\n"
1368                                  "Auxiliary Block:          768 bytes\n"
1369                                  "Public key (sha1):        "
1370                                  "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1371                                  "Algorithm:                SHA256_RSA2048\n"
1372                                  "Rollback Index:           0\n"
1373                                  "Flags:                    0\n"
1374                                  "Rollback Index Location:  0\n"
1375                                  "Release String:           ''\n"
1376                                  "Descriptors:\n"
1377                                  "    Hashtree descriptor:\n"
1378                                  "      Version of dm-verity:  1\n"
1379                                  "      Image Size:            1052672 bytes\n"
1380                                  "      Tree Offset:           1052672\n"
1381                                  "      Tree Size:             16384 bytes\n"
1382                                  "      Data Block Size:       4096 bytes\n"
1383                                  "      Hash Block Size:       4096 bytes\n"
1384                                  "      FEC num roots:         2\n"
1385                                  "      FEC offset:            1069056\n"
1386                                  "      FEC size:              16384 bytes\n"
1387                                  "      Hash Algorithm:        sha1\n"
1388                                  "      Partition Name:        foobar\n"
1389                                  "      Salt:                  d00df00d\n"
1390                                  "      Root Digest:           "
1391                                  "e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
1392                                  "      Flags:                 0\n",
1393                                  sparse_image ? " (Sparse)" : ""),
1394               InfoImage(rootfs_path));
1395   }
1396 
1397   /* Zero the hashtree and FEC on a copy of the image. */
1398   EXPECT_COMMAND(0,
1399                  "cp %s %s.zht",
1400                  rootfs_path.value().c_str(),
1401                  rootfs_path.value().c_str());
1402   EXPECT_COMMAND(0,
1403                  "./avbtool.py zero_hashtree --image %s.zht ",
1404                  rootfs_path.value().c_str());
1405 
1406   if (sparse_image) {
1407     EXPECT_COMMAND(0,
1408                    "mv %s %s.sparse",
1409                    rootfs_path.value().c_str(),
1410                    rootfs_path.value().c_str());
1411     EXPECT_COMMAND(0,
1412                    "simg2img %s.sparse %s",
1413                    rootfs_path.value().c_str(),
1414                    rootfs_path.value().c_str());
1415     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
1416 
1417     EXPECT_COMMAND(0,
1418                    "mv %s.zht %s.zht.sparse",
1419                    rootfs_path.value().c_str(),
1420                    rootfs_path.value().c_str());
1421     EXPECT_COMMAND(0,
1422                    "simg2img %s.zht.sparse %s.zht",
1423                    rootfs_path.value().c_str(),
1424                    rootfs_path.value().c_str());
1425     EXPECT_COMMAND(0, "rm -f %s.zht.sparse", rootfs_path.value().c_str());
1426   }
1427 
1428   /* TODO: would be nice to verify that the FEC data is correct. */
1429 
1430   // Now check that we can find the VBMeta block again from the footer.
1431   std::string part_data;
1432   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1433 
1434   // Also read the zeroed hash-tree version.
1435   std::string zht_part_data;
1436   ASSERT_TRUE(base::ReadFileToString(
1437       base::FilePath(rootfs_path.value() + ".zht"), &zht_part_data));
1438 
1439   // Check footer contains correct data.
1440   AvbFooter f;
1441   EXPECT_NE(0,
1442             avb_footer_validate_and_byteswap(
1443                 reinterpret_cast<const AvbFooter*>(
1444                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1445                 &f));
1446   EXPECT_EQ(
1447       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1448       AVB_FOOTER_MAGIC);
1449   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1450   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1451   EXPECT_EQ(1052672UL, f.original_image_size);
1452   EXPECT_EQ(1085440UL, f.vbmeta_offset);
1453   EXPECT_EQ(1344UL, f.vbmeta_size);
1454 
1455   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1456   const uint8_t* vbmeta_data =
1457       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1458   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1459             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1460 
1461   // Collect all descriptors.
1462   std::vector<const AvbDescriptor*> descriptors;
1463   avb_descriptor_foreach(
1464       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1465 
1466   // We should only have a single descriptor and it should be a
1467   // hashtree descriptor.
1468   EXPECT_EQ(1UL, descriptors.size());
1469   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1470   AvbHashtreeDescriptor d;
1471   EXPECT_NE(
1472       0,
1473       avb_hashtree_descriptor_validate_and_byteswap(
1474           reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1475   EXPECT_EQ(1UL, d.dm_verity_version);
1476   EXPECT_EQ(1052672UL, d.image_size);
1477   EXPECT_EQ(1052672UL, d.tree_offset);
1478   EXPECT_EQ(16384UL, d.tree_size);
1479   EXPECT_EQ(4096UL, d.data_block_size);
1480   EXPECT_EQ(2UL, d.fec_num_roots);
1481   EXPECT_EQ(1069056UL, d.fec_offset);
1482   EXPECT_EQ(16384UL, d.fec_size);
1483   EXPECT_EQ(6UL, d.partition_name_len);
1484   EXPECT_EQ(4UL, d.salt_len);
1485   EXPECT_EQ(20UL, d.root_digest_len);
1486   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1487                             sizeof(AvbHashtreeDescriptor);
1488   uint64_t o = 0;
1489   EXPECT_EQ("foobar",
1490             std::string(reinterpret_cast<const char*>(desc_end + o),
1491                         d.partition_name_len));
1492   o += d.partition_name_len;
1493   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1494   o += d.salt_len;
1495   EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1496             mem_to_hexstring(desc_end + o, d.root_digest_len));
1497 
1498   // Check that the zeroed hashtree version differ only by the hashtree + fec
1499   // being zeroed out.
1500   EXPECT_EQ(part_data.size(), zht_part_data.size());
1501   size_t zht_ht_begin = d.tree_offset;
1502   size_t zht_ht_end = zht_ht_begin + d.tree_size;
1503   size_t zht_fec_begin = zht_ht_end;
1504   size_t zht_fec_end = zht_fec_begin + d.fec_size;
1505   EXPECT_EQ(0, memcmp(part_data.data(), zht_part_data.data(), zht_ht_begin));
1506   EXPECT_NE(0,
1507             memcmp(part_data.data() + zht_ht_begin,
1508                    zht_part_data.data() + zht_ht_begin,
1509                    zht_fec_end - zht_ht_begin));
1510   EXPECT_EQ(0,
1511             memcmp(part_data.data() + zht_fec_end,
1512                    zht_part_data.data() + zht_fec_end,
1513                    zht_part_data.size() - zht_fec_end));
1514   EXPECT_EQ(0, strncmp(zht_part_data.data() + zht_ht_begin, "ZeRoHaSH", 8));
1515   for (size_t n = zht_ht_begin + 8; n < zht_ht_end; n++) {
1516     EXPECT_EQ(0, zht_part_data.data()[n]);
1517   }
1518   if (d.fec_size > 0) {
1519     EXPECT_EQ(0, strncmp(zht_part_data.data() + zht_fec_begin, "ZeRoHaSH", 8));
1520     for (size_t n = zht_fec_begin + 8; n < zht_fec_end; n++) {
1521       EXPECT_EQ(0, zht_part_data.data()[n]);
1522     }
1523   }
1524 
1525   // Check that we correctly generate dm-verity kernel cmdline
1526   // snippets, if requested.
1527   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1528   EXPECT_COMMAND(0,
1529                  "./avbtool.py make_vbmeta_image "
1530                  "--output %s "
1531                  "--setup_rootfs_from_kernel %s "
1532                  "--algorithm SHA256_RSA2048 "
1533                  "--key test/data/testkey_rsa2048.pem "
1534                  "--internal_release_string \"\"",
1535                  vbmeta_dmv_path.value().c_str(),
1536                  rootfs_path.value().c_str());
1537 
1538   ASSERT_EQ(
1539       "Minimum libavb version:   1.0\n"
1540       "Header Block:             256 bytes\n"
1541       "Authentication Block:     320 bytes\n"
1542       "Auxiliary Block:          960 bytes\n"
1543       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1544       "Algorithm:                SHA256_RSA2048\n"
1545       "Rollback Index:           0\n"
1546       "Flags:                    0\n"
1547       "Rollback Index Location:  0\n"
1548       "Release String:           ''\n"
1549       "Descriptors:\n"
1550       "    Kernel Cmdline descriptor:\n"
1551       "      Flags:                 1\n"
1552       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1553       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1554       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1555       "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
1556       "use_fec_from_device "
1557       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 261 "
1558       "fec_start 261\" root=/dev/dm-0'\n"
1559       "    Kernel Cmdline descriptor:\n"
1560       "      Flags:                 2\n"
1561       "      Kernel Cmdline:        "
1562       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1563       InfoImage(vbmeta_dmv_path));
1564 
1565   // Check that the footer is correctly erased and the hashtree and
1566   // FEC data remains. The constant 1085440 is used because it's where
1567   // the FEC data ends (it's at offset 1069056 and size 16384).
1568   EXPECT_COMMAND(0,
1569                  "./avbtool.py erase_footer --image %s --keep_hashtree",
1570                  rootfs_path.value().c_str());
1571   int64_t erased_footer_file_size;
1572   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1573   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1085440UL);
1574 }
1575 
TEST_F(AvbToolTest,AddHashtreeFooterFEC)1576 TEST_F(AvbToolTest, AddHashtreeFooterFEC) {
1577   AddHashtreeFooterFECTest(false);
1578 }
1579 
TEST_F(AvbToolTest,AddHashtreeFooterFECSparse)1580 TEST_F(AvbToolTest, AddHashtreeFooterFECSparse) {
1581   AddHashtreeFooterFECTest(true);
1582 }
1583 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSize)1584 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSize) {
1585   const size_t partition_size = 10 * 1024 * 1024;
1586   base::FilePath output_path = testdir_.Append("max_size.txt");
1587 
1588   EXPECT_COMMAND(0,
1589                  "./avbtool.py add_hashtree_footer "
1590                  "--partition_size %zd --calc_max_image_size "
1591                  "--do_not_generate_fec > %s",
1592                  partition_size,
1593                  output_path.value().c_str());
1594   std::string max_image_size_data;
1595   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1596   EXPECT_EQ("10330112\n", max_image_size_data);
1597   size_t max_image_size = atoll(max_image_size_data.c_str());
1598 
1599   // Hashtree and metadata takes up 152 KiB - compare to below with
1600   // FEC which is 244 KiB.
1601   EXPECT_EQ(152 * 1024ULL, partition_size - max_image_size);
1602 
1603   // Check that we can add a hashtree with an image this size for such
1604   // a partition size.
1605   base::FilePath system_path = GenerateImage("system", max_image_size);
1606   EXPECT_COMMAND(0,
1607                  "./avbtool.py add_hashtree_footer"
1608                  " --image %s"
1609                  " --partition_name system"
1610                  " --partition_size %zd"
1611                  " --salt deadbeef"
1612                  " --algorithm SHA512_RSA4096 "
1613                  " --key test/data/testkey_rsa4096.pem"
1614                  " --internal_release_string \"\" "
1615                  "--do_not_generate_fec",
1616                  system_path.value().c_str(),
1617                  partition_size);
1618 }
1619 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSizeWithFEC)1620 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) {
1621   const size_t partition_size = 10 * 1024 * 1024;
1622   base::FilePath output_path = testdir_.Append("max_size.txt");
1623 
1624   EXPECT_COMMAND(0,
1625                  "./avbtool.py add_hashtree_footer "
1626                  "--partition_size %zd --calc_max_image_size > %s",
1627                  partition_size,
1628                  output_path.value().c_str());
1629   std::string max_image_size_data;
1630   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1631   EXPECT_EQ("10235904\n", max_image_size_data);
1632   size_t max_image_size = atoll(max_image_size_data.c_str());
1633 
1634   // Hashtree, FEC codes, and metadata takes up 244 KiB - compare to
1635   // above wihtout FEC which is 152 KiB.
1636   EXPECT_EQ(244 * 1024ULL, partition_size - max_image_size);
1637 
1638   // Check that we can add a hashtree with an image this size for such
1639   // a partition size.
1640   base::FilePath system_path = GenerateImage("system", max_image_size);
1641   EXPECT_COMMAND(0,
1642                  "./avbtool.py add_hashtree_footer"
1643                  " --image %s"
1644                  " --partition_name system"
1645                  " --partition_size %zd"
1646                  " --salt deadbeef"
1647                  " --algorithm SHA512_RSA4096 "
1648                  " --key test/data/testkey_rsa4096.pem"
1649                  " --internal_release_string \"\"",
1650                  system_path.value().c_str(),
1651                  partition_size);
1652 }
1653 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSizeWithNoHashtree)1654 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithNoHashtree) {
1655   const size_t partition_size = 10 * 1024 * 1024;
1656   base::FilePath output_path = testdir_.Append("max_size.txt");
1657 
1658   EXPECT_COMMAND(0,
1659                  "./avbtool.py add_hashtree_footer "
1660                  "--no_hashtree "
1661                  "--partition_size %zd --calc_max_image_size > %s",
1662                  partition_size,
1663                  output_path.value().c_str());
1664   std::string max_image_size_data;
1665   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1666   EXPECT_EQ("10416128\n", max_image_size_data);
1667   size_t max_image_size = atoll(max_image_size_data.c_str());
1668 
1669   // vbmeta(64) + footer(4) takes up 68 KiB
1670   EXPECT_EQ(68 * 1024ULL, partition_size - max_image_size);
1671 
1672   // Check that we can add a hashtree with an image this size for such
1673   // a partition size.
1674   base::FilePath system_path = GenerateImage("system", max_image_size);
1675   EXPECT_COMMAND(0,
1676                  "./avbtool.py add_hashtree_footer"
1677                  " --image %s"
1678                  " --no_hashtree"
1679                  " --partition_name system"
1680                  " --partition_size %zd"
1681                  " --salt deadbeef"
1682                  " --algorithm SHA512_RSA4096 "
1683                  " --key test/data/testkey_rsa4096.pem"
1684                  " --internal_release_string \"\"",
1685                  system_path.value().c_str(),
1686                  partition_size);
1687   // with --no_hashtree, Tree/FEC sizes are 0 bytes
1688   ASSERT_EQ(
1689       "Footer version:           1.0\n"
1690       "Image size:               10485760 bytes\n"
1691       "Original image size:      10416128 bytes\n"
1692       "VBMeta offset:            10416128\n"
1693       "VBMeta size:              2112 bytes\n"
1694       "--\n"
1695       "Minimum libavb version:   1.0\n"
1696       "Header Block:             256 bytes\n"
1697       "Authentication Block:     576 bytes\n"
1698       "Auxiliary Block:          1280 bytes\n"
1699       "Public key (sha1):        2597c218aae470a130f61162feaae70afd97f011\n"
1700       "Algorithm:                SHA512_RSA4096\n"
1701       "Rollback Index:           0\n"
1702       "Flags:                    0\n"
1703       "Rollback Index Location:  0\n"
1704       "Release String:           ''\n"
1705       "Descriptors:\n"
1706       "    Hashtree descriptor:\n"
1707       "      Version of dm-verity:  1\n"
1708       "      Image Size:            10416128 bytes\n"
1709       "      Tree Offset:           10416128\n"
1710       "      Tree Size:             0 bytes\n"
1711       "      Data Block Size:       4096 bytes\n"
1712       "      Hash Block Size:       4096 bytes\n"
1713       "      FEC num roots:         2\n"
1714       "      FEC offset:            10416128\n"
1715       "      FEC size:              0 bytes\n"
1716       "      Hash Algorithm:        sha1\n"
1717       "      Partition Name:        system\n"
1718       "      Salt:                  deadbeef\n"
1719       "      Root Digest:           4215bd42bcc99636f42956ce3d2c7884d6a8093b\n"
1720       "      Flags:                 0\n",
1721       InfoImage(system_path));
1722 }
1723 
TEST_F(AvbToolTest,AddHashtreeFooterWithPersistentDigest)1724 TEST_F(AvbToolTest, AddHashtreeFooterWithPersistentDigest) {
1725   size_t partition_size = 10 * 1024 * 1024;
1726   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1727   EXPECT_COMMAND(0,
1728                  "./avbtool.py add_hashtree_footer "
1729                  "--hash_algorithm sha256 --image %s "
1730                  "--partition_size %d --partition_name foobar "
1731                  "--algorithm SHA256_RSA2048 "
1732                  "--key test/data/testkey_rsa2048.pem "
1733                  "--internal_release_string \"\" "
1734                  "--use_persistent_digest",
1735                  path.value().c_str(),
1736                  (int)partition_size);
1737   // There are two important bits here specific to --use_persistent_digest:
1738   //   Minimum libavb version = 1.1
1739   //   Hashtree descriptor -> Root Digest = (empty)
1740   ASSERT_EQ(
1741       "Footer version:           1.0\n"
1742       "Image size:               10485760 bytes\n"
1743       "Original image size:      5242880 bytes\n"
1744       "VBMeta offset:            5337088\n"
1745       "VBMeta size:              1344 bytes\n"
1746       "--\n"
1747       "Minimum libavb version:   1.1\n"
1748       "Header Block:             256 bytes\n"
1749       "Authentication Block:     320 bytes\n"
1750       "Auxiliary Block:          768 bytes\n"
1751       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1752       "Algorithm:                SHA256_RSA2048\n"
1753       "Rollback Index:           0\n"
1754       "Flags:                    0\n"
1755       "Rollback Index Location:  0\n"
1756       "Release String:           ''\n"
1757       "Descriptors:\n"
1758       "    Hashtree descriptor:\n"
1759       "      Version of dm-verity:  1\n"
1760       "      Image Size:            5242880 bytes\n"
1761       "      Tree Offset:           5242880\n"
1762       "      Tree Size:             45056 bytes\n"
1763       "      Data Block Size:       4096 bytes\n"
1764       "      Hash Block Size:       4096 bytes\n"
1765       "      FEC num roots:         2\n"
1766       "      FEC offset:            5287936\n"
1767       "      FEC size:              49152 bytes\n"
1768       "      Hash Algorithm:        sha256\n"
1769       "      Partition Name:        foobar\n"
1770       "      Salt:                  \n"
1771       "      Root Digest:           \n"
1772       "      Flags:                 0\n",
1773       InfoImage(path));
1774 }
1775 
TEST_F(AvbToolTest,AddHashtreeFooterWithNoAB)1776 TEST_F(AvbToolTest, AddHashtreeFooterWithNoAB) {
1777   size_t partition_size = 10 * 1024 * 1024;
1778   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1779   EXPECT_COMMAND(0,
1780                  "./avbtool.py add_hashtree_footer --salt d00df00d "
1781                  "--hash_algorithm sha256 --image %s "
1782                  "--partition_size %d --partition_name foobar "
1783                  "--algorithm SHA256_RSA2048 "
1784                  "--key test/data/testkey_rsa2048.pem "
1785                  "--internal_release_string \"\" "
1786                  "--do_not_use_ab",
1787                  path.value().c_str(),
1788                  (int)partition_size);
1789   // There are two important bits here we're expecting with --do_not_use_ab:
1790   //   Minimum libavb version = 1.1
1791   //   Hashtree descriptor -> Flags = 1
1792   ASSERT_EQ(
1793       "Footer version:           1.0\n"
1794       "Image size:               10485760 bytes\n"
1795       "Original image size:      5242880 bytes\n"
1796       "VBMeta offset:            5337088\n"
1797       "VBMeta size:              1344 bytes\n"
1798       "--\n"
1799       "Minimum libavb version:   1.1\n"
1800       "Header Block:             256 bytes\n"
1801       "Authentication Block:     320 bytes\n"
1802       "Auxiliary Block:          768 bytes\n"
1803       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1804       "Algorithm:                SHA256_RSA2048\n"
1805       "Rollback Index:           0\n"
1806       "Flags:                    0\n"
1807       "Rollback Index Location:  0\n"
1808       "Release String:           ''\n"
1809       "Descriptors:\n"
1810       "    Hashtree descriptor:\n"
1811       "      Version of dm-verity:  1\n"
1812       "      Image Size:            5242880 bytes\n"
1813       "      Tree Offset:           5242880\n"
1814       "      Tree Size:             45056 bytes\n"
1815       "      Data Block Size:       4096 bytes\n"
1816       "      Hash Block Size:       4096 bytes\n"
1817       "      FEC num roots:         2\n"
1818       "      FEC offset:            5287936\n"
1819       "      FEC size:              49152 bytes\n"
1820       "      Hash Algorithm:        sha256\n"
1821       "      Partition Name:        foobar\n"
1822       "      Salt:                  d00df00d\n"
1823       "      Root Digest:           "
1824       "d0e31526f5a3f8e3f59acf726bd31ae7861ee78f9baa9195356bf479c6f9119d\n"
1825       "      Flags:                 1\n",
1826       InfoImage(path));
1827 }
1828 
TEST_F(AvbToolTest,AddHashtreeFooterWithPersistentDigestAndNoAB)1829 TEST_F(AvbToolTest, AddHashtreeFooterWithPersistentDigestAndNoAB) {
1830   size_t partition_size = 10 * 1024 * 1024;
1831   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1832   EXPECT_COMMAND(0,
1833                  "./avbtool.py add_hashtree_footer "
1834                  "--hash_algorithm sha256 --image %s "
1835                  "--partition_size %d --partition_name foobar "
1836                  "--algorithm SHA256_RSA2048 "
1837                  "--key test/data/testkey_rsa2048.pem "
1838                  "--internal_release_string \"\" "
1839                  "--use_persistent_digest --do_not_use_ab",
1840                  path.value().c_str(),
1841                  (int)partition_size);
1842   // There are three important bits specific to these flags:
1843   //   Minimum libavb version = 1.1
1844   //   Hashtree descriptor -> Root Digest = (empty)
1845   //   Hashtree descriptor -> Flags = 1
1846   ASSERT_EQ(
1847       "Footer version:           1.0\n"
1848       "Image size:               10485760 bytes\n"
1849       "Original image size:      5242880 bytes\n"
1850       "VBMeta offset:            5337088\n"
1851       "VBMeta size:              1344 bytes\n"
1852       "--\n"
1853       "Minimum libavb version:   1.1\n"
1854       "Header Block:             256 bytes\n"
1855       "Authentication Block:     320 bytes\n"
1856       "Auxiliary Block:          768 bytes\n"
1857       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1858       "Algorithm:                SHA256_RSA2048\n"
1859       "Rollback Index:           0\n"
1860       "Flags:                    0\n"
1861       "Rollback Index Location:  0\n"
1862       "Release String:           ''\n"
1863       "Descriptors:\n"
1864       "    Hashtree descriptor:\n"
1865       "      Version of dm-verity:  1\n"
1866       "      Image Size:            5242880 bytes\n"
1867       "      Tree Offset:           5242880\n"
1868       "      Tree Size:             45056 bytes\n"
1869       "      Data Block Size:       4096 bytes\n"
1870       "      Hash Block Size:       4096 bytes\n"
1871       "      FEC num roots:         2\n"
1872       "      FEC offset:            5287936\n"
1873       "      FEC size:              49152 bytes\n"
1874       "      Hash Algorithm:        sha256\n"
1875       "      Partition Name:        foobar\n"
1876       "      Salt:                  \n"
1877       "      Root Digest:           \n"
1878       "      Flags:                 1\n",
1879       InfoImage(path));
1880 }
1881 
TEST_F(AvbToolTest,AddHashtreeFooterNoSizeOrName)1882 TEST_F(AvbToolTest, AddHashtreeFooterNoSizeOrName) {
1883   // Size must be a multiple of block size (4096 bytes)
1884   size_t file_size = 72 * 1024;
1885   base::FilePath path = GenerateImage("data.bin", file_size);
1886 
1887   // Note how there is no --partition_size or --partition_name here.
1888   EXPECT_COMMAND(0,
1889                  "./avbtool.py add_hashtree_footer --salt d00df00d "
1890                  "--image %s "
1891                  "--algorithm SHA256_RSA2048 "
1892                  "--key test/data/testkey_rsa2048.pem "
1893                  "--internal_release_string \"\" ",
1894                  path.value().c_str());
1895 
1896   ASSERT_EQ(
1897       "Footer version:           1.0\n"
1898       "Image size:               94208 bytes\n"
1899       "Original image size:      73728 bytes\n"
1900       "VBMeta offset:            86016\n"
1901       "VBMeta size:              1344 bytes\n"
1902       "--\n"
1903       "Minimum libavb version:   1.0\n"
1904       "Header Block:             256 bytes\n"
1905       "Authentication Block:     320 bytes\n"
1906       "Auxiliary Block:          768 bytes\n"
1907       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1908       "Algorithm:                SHA256_RSA2048\n"
1909       "Rollback Index:           0\n"
1910       "Flags:                    0\n"
1911       "Rollback Index Location:  0\n"
1912       "Release String:           ''\n"
1913       "Descriptors:\n"
1914       "    Hashtree descriptor:\n"
1915       "      Version of dm-verity:  1\n"
1916       "      Image Size:            73728 bytes\n"
1917       "      Tree Offset:           73728\n"
1918       "      Tree Size:             4096 bytes\n"
1919       "      Data Block Size:       4096 bytes\n"
1920       "      Hash Block Size:       4096 bytes\n"
1921       "      FEC num roots:         2\n"
1922       "      FEC offset:            77824\n"
1923       "      FEC size:              8192 bytes\n"
1924       "      Hash Algorithm:        sha1\n"
1925       "      Partition Name:        \n"
1926       "      Salt:                  d00df00d\n"
1927       "      Root Digest:           2f73fb340e982794643e1121d82d5195677c2b31\n"
1928       "      Flags:                 0\n",
1929       InfoImage(path));
1930 
1931   // Check that at least avbtool can verify the image and hashtree.
1932   EXPECT_COMMAND(0,
1933                  "./avbtool.py verify_image "
1934                  "--image %s ",
1935                  path.value().c_str());
1936 }
1937 
TEST_F(AvbToolTest,AddHashtreeFooterSingleBlock)1938 TEST_F(AvbToolTest, AddHashtreeFooterSingleBlock) {
1939   // Tests a special case that the file size is just one block.
1940   size_t file_size = 4096;
1941   base::FilePath path = GenerateImage("data.bin", file_size);
1942 
1943   // Note how there is no --partition_size or --partition_name here.
1944   EXPECT_COMMAND(0,
1945                  "./avbtool.py add_hashtree_footer --salt d00df00d "
1946                  "--image %s "
1947                  "--algorithm SHA256_RSA2048 "
1948                  "--key test/data/testkey_rsa2048.pem "
1949                  "--internal_release_string \"\" ",
1950                  path.value().c_str());
1951 
1952   ASSERT_EQ(
1953       "Footer version:           1.0\n"
1954       "Image size:               20480 bytes\n"
1955       "Original image size:      4096 bytes\n"
1956       "VBMeta offset:            12288\n"
1957       "VBMeta size:              1344 bytes\n"
1958       "--\n"
1959       "Minimum libavb version:   1.0\n"
1960       "Header Block:             256 bytes\n"
1961       "Authentication Block:     320 bytes\n"
1962       "Auxiliary Block:          768 bytes\n"
1963       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
1964       "Algorithm:                SHA256_RSA2048\n"
1965       "Rollback Index:           0\n"
1966       "Flags:                    0\n"
1967       "Rollback Index Location:  0\n"
1968       "Release String:           ''\n"
1969       "Descriptors:\n"
1970       "    Hashtree descriptor:\n"
1971       "      Version of dm-verity:  1\n"
1972       "      Image Size:            4096 bytes\n"
1973       "      Tree Offset:           4096\n"
1974       "      Tree Size:             0 bytes\n"
1975       "      Data Block Size:       4096 bytes\n"
1976       "      Hash Block Size:       4096 bytes\n"
1977       "      FEC num roots:         2\n"
1978       "      FEC offset:            4096\n"
1979       "      FEC size:              8192 bytes\n"
1980       "      Hash Algorithm:        sha1\n"
1981       "      Partition Name:        \n"
1982       "      Salt:                  d00df00d\n"
1983       "      Root Digest:           4bd1e1f0aa1c2c793bb9f3e52de6ae7393889e61\n"
1984       "      Flags:                 0\n",
1985       InfoImage(path));
1986 
1987   // Check that at least avbtool can verify the image and hashtree.
1988   EXPECT_COMMAND(0,
1989                  "./avbtool.py verify_image "
1990                  "--image %s ",
1991                  path.value().c_str());
1992 }
1993 
TEST_F(AvbToolTest,AddHashtreeFooterNoSizeWrongSize)1994 TEST_F(AvbToolTest, AddHashtreeFooterNoSizeWrongSize) {
1995   // Size must be a multiple of block size (4096 bytes) and this one isn't...
1996   size_t file_size = 70 * 1024;
1997   base::FilePath path = GenerateImage("data.bin", file_size);
1998 
1999   // ... so we expect this command to fail.
2000   EXPECT_COMMAND(1,
2001                  "./avbtool.py add_hashtree_footer --salt d00df00d "
2002                  "--image %s "
2003                  "--algorithm SHA256_RSA2048 "
2004                  "--key test/data/testkey_rsa2048.pem "
2005                  "--internal_release_string \"\" ",
2006                  path.value().c_str());
2007 }
2008 
TEST_F(AvbToolTest,AddHashtreeFooterRoundImageSize)2009 TEST_F(AvbToolTest, AddHashtreeFooterRoundImageSize) {
2010   // Image size needs not to be a multiple of block size (4096 bytes) if
2011   // --partition_size is specified. avbtool will round the image size being
2012   // a multiple of block size, prior to add an AVB footer.
2013   size_t image_size = 70 * 1024;
2014   base::FilePath path = GenerateImage("data.bin", image_size);
2015 
2016   size_t partition_size = 10 * 1024 * 1024;
2017   // Note that there is --partition_size here.
2018   EXPECT_COMMAND(0,
2019                  "./avbtool.py add_hashtree_footer --salt d00df00d "
2020                  "--image %s "
2021                  "--algorithm SHA256_RSA2048 "
2022                  "--key test/data/testkey_rsa2048.pem "
2023                  "--partition_size %d --partition_name foobar "
2024                  "--internal_release_string \"\" ",
2025                  path.value().c_str(),
2026                  (int)partition_size);
2027 }
2028 
TEST_F(AvbToolTest,AddHashtreeFooterNoWrongPartitionSize)2029 TEST_F(AvbToolTest, AddHashtreeFooterNoWrongPartitionSize) {
2030   // Partition size must be a multiple of block size (4096 bytes) and this
2031   // one isn't...
2032   size_t partition_size = 10 * 1024 * 1024 + 1024;
2033 
2034   // Image size doesn't matter in this case.
2035   size_t image_size = 70 * 1024;
2036   base::FilePath path = GenerateImage("data.bin", image_size);
2037 
2038   // ... so we expect this command to fail.
2039   EXPECT_COMMAND(1,
2040                  "./avbtool.py add_hashtree_footer --salt d00df00d "
2041                  "--image %s "
2042                  "--algorithm SHA256_RSA2048 "
2043                  "--key test/data/testkey_rsa2048.pem "
2044                  "--partition_size %d --partition_name foobar "
2045                  "--internal_release_string \"\" ",
2046                  path.value().c_str(),
2047                  (int)partition_size);
2048 }
2049 
TEST_F(AvbToolTest,AddHashtreeFooterWithCheckAtMostOnce)2050 TEST_F(AvbToolTest, AddHashtreeFooterWithCheckAtMostOnce) {
2051   size_t partition_size = 10 * 1024 * 1024;
2052   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
2053   EXPECT_COMMAND(0,
2054                  "./avbtool.py add_hashtree_footer --salt d00df00d "
2055                  "--hash_algorithm sha256 --image %s "
2056                  "--partition_size %d --partition_name foobar "
2057                  "--algorithm SHA256_RSA2048 "
2058                  "--key test/data/testkey_rsa2048.pem "
2059                  "--internal_release_string \"\" "
2060                  "--check_at_most_once",
2061                  path.value().c_str(),
2062                  (int)partition_size);
2063   // There are two important bits here we're expecting with --check_at_most_once:
2064   //   Minimum libavb version = 1.1
2065   //   Hashtree descriptor -> Flags = 2
2066   ASSERT_EQ(
2067       "Footer version:           1.0\n"
2068       "Image size:               10485760 bytes\n"
2069       "Original image size:      5242880 bytes\n"
2070       "VBMeta offset:            5337088\n"
2071       "VBMeta size:              1344 bytes\n"
2072       "--\n"
2073       "Minimum libavb version:   1.1\n"
2074       "Header Block:             256 bytes\n"
2075       "Authentication Block:     320 bytes\n"
2076       "Auxiliary Block:          768 bytes\n"
2077       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2078       "Algorithm:                SHA256_RSA2048\n"
2079       "Rollback Index:           0\n"
2080       "Flags:                    0\n"
2081       "Rollback Index Location:  0\n"
2082       "Release String:           ''\n"
2083       "Descriptors:\n"
2084       "    Hashtree descriptor:\n"
2085       "      Version of dm-verity:  1\n"
2086       "      Image Size:            5242880 bytes\n"
2087       "      Tree Offset:           5242880\n"
2088       "      Tree Size:             45056 bytes\n"
2089       "      Data Block Size:       4096 bytes\n"
2090       "      Hash Block Size:       4096 bytes\n"
2091       "      FEC num roots:         2\n"
2092       "      FEC offset:            5287936\n"
2093       "      FEC size:              49152 bytes\n"
2094       "      Hash Algorithm:        sha256\n"
2095       "      Partition Name:        foobar\n"
2096       "      Salt:                  d00df00d\n"
2097       "      Root Digest:           "
2098       "d0e31526f5a3f8e3f59acf726bd31ae7861ee78f9baa9195356bf479c6f9119d\n"
2099       "      Flags:                 2\n",
2100       InfoImage(path));
2101 }
2102 
TEST_F(AvbToolTest,KernelCmdlineDescriptor)2103 TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
2104   base::FilePath vbmeta_path =
2105       testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
2106 
2107   EXPECT_COMMAND(0,
2108                  "./avbtool.py make_vbmeta_image "
2109                  "--output %s "
2110                  "--kernel_cmdline 'foo bar baz' "
2111                  "--kernel_cmdline 'second cmdline' "
2112                  "--algorithm SHA256_RSA2048 "
2113                  "--key test/data/testkey_rsa2048.pem "
2114                  "--internal_release_string \"\"",
2115                  vbmeta_path.value().c_str());
2116 
2117   ASSERT_EQ(
2118       "Minimum libavb version:   1.0\n"
2119       "Header Block:             256 bytes\n"
2120       "Authentication Block:     320 bytes\n"
2121       "Auxiliary Block:          640 bytes\n"
2122       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2123       "Algorithm:                SHA256_RSA2048\n"
2124       "Rollback Index:           0\n"
2125       "Flags:                    0\n"
2126       "Rollback Index Location:  0\n"
2127       "Release String:           ''\n"
2128       "Descriptors:\n"
2129       "    Kernel Cmdline descriptor:\n"
2130       "      Flags:                 0\n"
2131       "      Kernel Cmdline:        'foo bar baz'\n"
2132       "    Kernel Cmdline descriptor:\n"
2133       "      Flags:                 0\n"
2134       "      Kernel Cmdline:        'second cmdline'\n",
2135       InfoImage(vbmeta_path));
2136 
2137   // Now check the VBMeta image.
2138   std::string image_data;
2139   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
2140 
2141   const uint8_t* vbmeta_data =
2142       reinterpret_cast<const uint8_t*>(image_data.data());
2143   const size_t vbmeta_size = image_data.length();
2144   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
2145             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
2146 
2147   // Collect all descriptors.
2148   std::vector<const AvbDescriptor*> descriptors;
2149   avb_descriptor_foreach(
2150       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
2151 
2152   // We should have two descriptors - check them.
2153   EXPECT_EQ(2UL, descriptors.size());
2154   AvbKernelCmdlineDescriptor d;
2155   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
2156             avb_be64toh(descriptors[0]->tag));
2157   EXPECT_NE(
2158       0,
2159       avb_kernel_cmdline_descriptor_validate_and_byteswap(
2160           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]),
2161           &d));
2162   EXPECT_EQ("foo bar baz",
2163             std::string(reinterpret_cast<const char*>(descriptors[0]) +
2164                             sizeof(AvbKernelCmdlineDescriptor),
2165                         d.kernel_cmdline_length));
2166   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
2167             avb_be64toh(descriptors[1]->tag));
2168   EXPECT_NE(
2169       0,
2170       avb_kernel_cmdline_descriptor_validate_and_byteswap(
2171           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]),
2172           &d));
2173   EXPECT_EQ("second cmdline",
2174             std::string(reinterpret_cast<const char*>(descriptors[1]) +
2175                             sizeof(AvbKernelCmdlineDescriptor),
2176                         d.kernel_cmdline_length));
2177 }
2178 
TEST_F(AvbToolTest,CalculateKernelCmdline)2179 TEST_F(AvbToolTest, CalculateKernelCmdline) {
2180   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2181   EXPECT_COMMAND(0,
2182                  "./avbtool.py make_vbmeta_image "
2183                  "--output %s "
2184                  "--kernel_cmdline 'foo bar baz' "
2185                  "--kernel_cmdline 'second cmdline' "
2186                  "--algorithm SHA256_RSA2048 "
2187                  "--key test/data/testkey_rsa2048.pem "
2188                  "--internal_release_string \"\"",
2189                  vbmeta_path.value().c_str());
2190 
2191   base::FilePath out_path = testdir_.Append("out.txt");
2192   std::string out;
2193   EXPECT_COMMAND(0,
2194                  "./avbtool.py calculate_kernel_cmdline --image %s > %s",
2195                  vbmeta_path.value().c_str(),
2196                  out_path.value().c_str());
2197   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2198   EXPECT_EQ(out, "foo bar baz second cmdline");
2199 }
2200 
TEST_F(AvbToolTest,CalculateKernelCmdlineChainedAndWithFlags)2201 TEST_F(AvbToolTest, CalculateKernelCmdlineChainedAndWithFlags) {
2202   const size_t rootfs_size = 1028 * 1024;
2203   const size_t partition_size = 1536 * 1024;
2204 
2205   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2206 
2207   // Generate a 1028 KiB file with known content, add a hashtree, and cmdline
2208   // descriptors for setting up this hashtree. Notably this will create *two*
2209   // cmdline descriptors so we can test calculate_kernel_cmdline's
2210   // --hashtree_disabled option.
2211   std::vector<uint8_t> rootfs;
2212   rootfs.resize(rootfs_size);
2213   for (size_t n = 0; n < rootfs_size; n++)
2214     rootfs[n] = uint8_t(n);
2215   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
2216   EXPECT_EQ(rootfs_size,
2217             static_cast<const size_t>(
2218                 base::WriteFile(rootfs_path,
2219                                 reinterpret_cast<const char*>(rootfs.data()),
2220                                 rootfs.size())));
2221 
2222   EXPECT_COMMAND(
2223       0,
2224       "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
2225       " --output %s",
2226       pk_path.value().c_str());
2227 
2228   EXPECT_COMMAND(0,
2229                  "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
2230                  "--partition_size %d --partition_name rootfs "
2231                  "--algorithm SHA256_RSA2048 "
2232                  "--key test/data/testkey_rsa2048.pem "
2233                  "--internal_release_string \"\" "
2234                  "--setup_as_rootfs_from_kernel",
2235                  rootfs_path.value().c_str(),
2236                  (int)partition_size);
2237   EXPECT_EQ(
2238       "Footer version:           1.0\n"
2239       "Image size:               1572864 bytes\n"
2240       "Original image size:      1052672 bytes\n"
2241       "VBMeta offset:            1085440\n"
2242       "VBMeta size:              1792 bytes\n"
2243       "--\n"
2244       "Minimum libavb version:   1.0\n"
2245       "Header Block:             256 bytes\n"
2246       "Authentication Block:     320 bytes\n"
2247       "Auxiliary Block:          1216 bytes\n"
2248       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2249       "Algorithm:                SHA256_RSA2048\n"
2250       "Rollback Index:           0\n"
2251       "Flags:                    0\n"
2252       "Rollback Index Location:  0\n"
2253       "Release String:           ''\n"
2254       "Descriptors:\n"
2255       "    Hashtree descriptor:\n"
2256       "      Version of dm-verity:  1\n"
2257       "      Image Size:            1052672 bytes\n"
2258       "      Tree Offset:           1052672\n"
2259       "      Tree Size:             16384 bytes\n"
2260       "      Data Block Size:       4096 bytes\n"
2261       "      Hash Block Size:       4096 bytes\n"
2262       "      FEC num roots:         2\n"
2263       "      FEC offset:            1069056\n"
2264       "      FEC size:              16384 bytes\n"
2265       "      Hash Algorithm:        sha1\n"
2266       "      Partition Name:        rootfs\n"
2267       "      Salt:                  d00df00d\n"
2268       "      Root Digest:           e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
2269       "      Flags:                 0\n"
2270       "    Kernel Cmdline descriptor:\n"
2271       "      Flags:                 1\n"
2272       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
2273       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
2274       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
2275       "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
2276       "use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 "
2277       "fec_blocks 261 fec_start 261\" root=/dev/dm-0'\n"
2278       "    Kernel Cmdline descriptor:\n"
2279       "      Flags:                 2\n"
2280       "      Kernel Cmdline:        "
2281       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
2282       InfoImage(rootfs_path));
2283 
2284   // Chain to the rootfs.img and include two cmdline descriptors.
2285   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2286   EXPECT_COMMAND(0,
2287                  "./avbtool.py make_vbmeta_image "
2288                  "--output %s "
2289                  "--kernel_cmdline 'foo bar baz' "
2290                  "--kernel_cmdline 'second cmdline' "
2291                  "--chain_partition rootfs:1:%s "
2292                  "--algorithm SHA256_RSA2048 "
2293                  "--key test/data/testkey_rsa2048.pem "
2294                  "--internal_release_string \"\"",
2295                  vbmeta_path.value().c_str(),
2296                  pk_path.value().c_str());
2297   EXPECT_EQ(
2298       "Minimum libavb version:   1.0\n"
2299       "Header Block:             256 bytes\n"
2300       "Authentication Block:     320 bytes\n"
2301       "Auxiliary Block:          1280 bytes\n"
2302       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2303       "Algorithm:                SHA256_RSA2048\n"
2304       "Rollback Index:           0\n"
2305       "Flags:                    0\n"
2306       "Rollback Index Location:  0\n"
2307       "Release String:           ''\n"
2308       "Descriptors:\n"
2309       "    Chain Partition descriptor:\n"
2310       "      Partition Name:          rootfs\n"
2311       "      Rollback Index Location: 1\n"
2312       "      Public key (sha1):       "
2313       "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2314       "    Kernel Cmdline descriptor:\n"
2315       "      Flags:                 0\n"
2316       "      Kernel Cmdline:        'foo bar baz'\n"
2317       "    Kernel Cmdline descriptor:\n"
2318       "      Flags:                 0\n"
2319       "      Kernel Cmdline:        'second cmdline'\n",
2320       InfoImage(vbmeta_path));
2321 
2322   base::FilePath out_path = testdir_.Append("out.txt");
2323   std::string out;
2324 
2325   // First check the kernel cmdline without --hashtree_disabled - compare with
2326   // above info_image output.
2327   EXPECT_COMMAND(0,
2328                  "./avbtool.py calculate_kernel_cmdline --image %s > %s",
2329                  vbmeta_path.value().c_str(),
2330                  out_path.value().c_str());
2331   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2332   EXPECT_EQ(
2333       "dm=\"1 vroot none ro 1,0 2056 verity 1 "
2334       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
2335       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
2336       "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
2337       "use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 "
2338       "fec_blocks 261 fec_start 261\" root=/dev/dm-0 foo bar baz second "
2339       "cmdline",
2340       out);
2341 
2342   // Then check the kernel cmdline with --hashtree_disabled - compare with above
2343   // info_image output.
2344   EXPECT_COMMAND(
2345       0,
2346       "./avbtool.py calculate_kernel_cmdline --image %s --hashtree_disabled > %s",
2347       vbmeta_path.value().c_str(),
2348       out_path.value().c_str());
2349   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2350   EXPECT_EQ(
2351       "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID) foo bar baz second cmdline",
2352       out);
2353 }
2354 
TEST_F(AvbToolTest,AddHashFooterSmallImageWithExternalVbmeta)2355 TEST_F(AvbToolTest, AddHashFooterSmallImageWithExternalVbmeta) {
2356   const size_t image_size = 37;
2357   const size_t partition_size = 20 * 4096;
2358 
2359   std::vector<uint8_t> image(image_size, 0);
2360   for (size_t n = 0; n < image_size; n++) {
2361     image[n] = uint8_t(n);
2362   }
2363 
2364   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
2365   base::FilePath image_path = testdir_.Append("kernel.bin");
2366   EXPECT_EQ(image_size,
2367             static_cast<const size_t>(
2368                 base::WriteFile(image_path,
2369                                 reinterpret_cast<const char*>(image.data()),
2370                                 image.size())));
2371   EXPECT_COMMAND(0,
2372                  "./avbtool.py add_hash_footer --salt d00df00d "
2373                  "--hash_algorithm sha256 --image %s "
2374                  "--partition_size %zu --partition_name kernel "
2375                  "--algorithm SHA256_RSA2048 "
2376                  "--key test/data/testkey_rsa2048.pem "
2377                  "--output_vbmeta %s "
2378                  "--do_not_append_vbmeta_image "
2379                  "--internal_release_string \"\"",
2380                  image_path.value().c_str(),
2381                  partition_size,
2382                  ext_vbmeta_path.value().c_str());
2383 
2384   // It is not this unit test's job to check the vbmeta content.
2385 
2386   int64_t file_size;
2387   ASSERT_TRUE(base::GetFileSize(image_path, &file_size));
2388   EXPECT_EQ(static_cast<size_t>(file_size), image_size);
2389 }
2390 
TEST_F(AvbToolTest,IncludeDescriptor)2391 TEST_F(AvbToolTest, IncludeDescriptor) {
2392   base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin");
2393   base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin");
2394   base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
2395 
2396   EXPECT_COMMAND(0,
2397                  "./avbtool.py make_vbmeta_image "
2398                  "--output %s "
2399                  "--kernel_cmdline 'something' "
2400                  "--prop name:value "
2401                  "--internal_release_string \"\"",
2402                  vbmeta1_path.value().c_str());
2403 
2404   EXPECT_COMMAND(0,
2405                  "./avbtool.py make_vbmeta_image "
2406                  "--output %s "
2407                  "--prop name2:value2 "
2408                  "--prop name3:value3 "
2409                  "--internal_release_string \"\"",
2410                  vbmeta2_path.value().c_str());
2411 
2412   EXPECT_COMMAND(0,
2413                  "./avbtool.py make_vbmeta_image "
2414                  "--output %s "
2415                  "--prop name4:value4 "
2416                  "--include_descriptors_from_image %s "
2417                  "--include_descriptors_from_image %s "
2418                  "--internal_release_string \"\"",
2419                  vbmeta3_path.value().c_str(),
2420                  vbmeta1_path.value().c_str(),
2421                  vbmeta2_path.value().c_str());
2422 
2423   ASSERT_EQ(
2424       "Minimum libavb version:   1.0\n"
2425       "Header Block:             256 bytes\n"
2426       "Authentication Block:     0 bytes\n"
2427       "Auxiliary Block:          256 bytes\n"
2428       "Algorithm:                NONE\n"
2429       "Rollback Index:           0\n"
2430       "Flags:                    0\n"
2431       "Rollback Index Location:  0\n"
2432       "Release String:           ''\n"
2433       "Descriptors:\n"
2434       "    Prop: name4 -> 'value4'\n"
2435       "    Prop: name -> 'value'\n"
2436       "    Kernel Cmdline descriptor:\n"
2437       "      Flags:                 0\n"
2438       "      Kernel Cmdline:        'something'\n"
2439       "    Prop: name2 -> 'value2'\n"
2440       "    Prop: name3 -> 'value3'\n",
2441       InfoImage(vbmeta3_path));
2442 }
2443 
TEST_F(AvbToolTest,ChainedPartition)2444 TEST_F(AvbToolTest, ChainedPartition) {
2445   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
2446 
2447   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2448 
2449   EXPECT_COMMAND(
2450       0,
2451       "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
2452       " --output %s",
2453       pk_path.value().c_str());
2454 
2455   EXPECT_COMMAND(
2456       0,
2457       "./avbtool.py make_vbmeta_image "
2458       "--output %s "
2459       "--chain_partition system:1:%s "
2460       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2461       "--internal_release_string \"\"",
2462       vbmeta_path.value().c_str(),
2463       pk_path.value().c_str());
2464 
2465   ASSERT_EQ(
2466       "Minimum libavb version:   1.0\n"
2467       "Header Block:             256 bytes\n"
2468       "Authentication Block:     320 bytes\n"
2469       "Auxiliary Block:          1152 bytes\n"
2470       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2471       "Algorithm:                SHA256_RSA2048\n"
2472       "Rollback Index:           0\n"
2473       "Flags:                    0\n"
2474       "Rollback Index Location:  0\n"
2475       "Release String:           ''\n"
2476       "Descriptors:\n"
2477       "    Chain Partition descriptor:\n"
2478       "      Partition Name:          system\n"
2479       "      Rollback Index Location: 1\n"
2480       "      Public key (sha1):       "
2481       "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n",
2482       InfoImage(vbmeta_path));
2483 
2484   // Now check the VBMeta image.
2485   std::string image_data;
2486   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
2487 
2488   const uint8_t* vbmeta_data =
2489       reinterpret_cast<const uint8_t*>(image_data.data());
2490   const size_t vbmeta_size = image_data.length();
2491   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
2492             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
2493 
2494   // Collect all descriptors.
2495   std::vector<const AvbDescriptor*> descriptors;
2496   avb_descriptor_foreach(
2497       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
2498 
2499   // We should have one descriptor - check it.
2500   EXPECT_EQ(1UL, descriptors.size());
2501 
2502   std::string pk_data;
2503   ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data));
2504 
2505   AvbChainPartitionDescriptor d;
2506   EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
2507             avb_be64toh(descriptors[0]->tag));
2508   EXPECT_NE(
2509       0,
2510       avb_chain_partition_descriptor_validate_and_byteswap(
2511           reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]),
2512           &d));
2513   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
2514                             sizeof(AvbChainPartitionDescriptor);
2515   uint64_t o = 0;
2516   EXPECT_EQ("system",
2517             std::string(reinterpret_cast<const char*>(desc_end + o),
2518                         d.partition_name_len));
2519   o += d.partition_name_len;
2520   EXPECT_EQ(pk_data,
2521             std::string(reinterpret_cast<const char*>(descriptors[0]) +
2522                             sizeof(AvbChainPartitionDescriptor) + o,
2523                         d.public_key_len));
2524 }
2525 
TEST_F(AvbToolTest,ChainedPartitionNoLocationCollision)2526 TEST_F(AvbToolTest, ChainedPartitionNoLocationCollision) {
2527   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
2528 
2529   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2530 
2531   EXPECT_COMMAND(
2532       0,
2533       "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
2534       " --output %s",
2535       pk_path.value().c_str());
2536 
2537   // Check that avbtool bails if the same Rollback Index Location is
2538   // used for multiple chained partitions.
2539   EXPECT_COMMAND(
2540       1,
2541       "./avbtool.py make_vbmeta_image "
2542       "--output %s "
2543       "--chain_partition system:1:%s "
2544       "--chain_partition other:1:%s "
2545       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2546       "--internal_release_string \"\"",
2547       vbmeta_path.value().c_str(),
2548       pk_path.value().c_str(),
2549       pk_path.value().c_str());
2550 }
2551 
TEST_F(AvbToolTest,AppendVBMetaImage)2552 TEST_F(AvbToolTest, AppendVBMetaImage) {
2553   size_t boot_size = 5 * 1024 * 1024;
2554   size_t boot_partition_size = 32 * 1024 * 1024;
2555   base::FilePath boot_path = GenerateImage("boot", boot_size);
2556 
2557   GenerateVBMetaImage("vbmeta.img",
2558                       "SHA256_RSA2048",
2559                       0,
2560                       base::FilePath("test/data/testkey_rsa2048.pem"),
2561                       std::string("--append_to_release_string \"\" "
2562                                   "--kernel_cmdline foo"));
2563 
2564   EXPECT_COMMAND(0,
2565                  "./avbtool.py append_vbmeta_image "
2566                  "--image %s "
2567                  "--partition_size %d "
2568                  "--vbmeta_image %s ",
2569                  boot_path.value().c_str(),
2570                  (int)boot_partition_size,
2571                  vbmeta_image_path_.value().c_str());
2572 
2573   std::string vbmeta_contents = InfoImage(vbmeta_image_path_);
2574   std::string boot_contents = InfoImage(boot_path);
2575 
2576   // Check that boot.img has the same vbmeta blob as from vbmeta.img -
2577   // we do this by inspecting 'avbtool info_image' output combined
2578   // with the known footer location given boot.img has 5 MiB known
2579   // content and the partition size is 32 MiB.
2580   ASSERT_EQ(
2581       "Minimum libavb version:   1.0\n"
2582       "Header Block:             256 bytes\n"
2583       "Authentication Block:     320 bytes\n"
2584       "Auxiliary Block:          576 bytes\n"
2585       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2586       "Algorithm:                SHA256_RSA2048\n"
2587       "Rollback Index:           0\n"
2588       "Flags:                    0\n"
2589       "Rollback Index Location:  0\n"
2590       "Release String:           'avbtool 1.2.0 '\n"
2591       "Descriptors:\n"
2592       "    Kernel Cmdline descriptor:\n"
2593       "      Flags:                 0\n"
2594       "      Kernel Cmdline:        'foo'\n",
2595       vbmeta_contents);
2596   std::string known_footer =
2597       "Footer version:           1.0\n"
2598       "Image size:               33554432 bytes\n"
2599       "Original image size:      5242880 bytes\n"
2600       "VBMeta offset:            5242880\n"
2601       "VBMeta size:              1152 bytes\n"
2602       "--\n";
2603   ASSERT_EQ(known_footer + vbmeta_contents, boot_contents);
2604 
2605   // Also verify that the blobs are the same, bit for bit.
2606   base::File f =
2607       base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
2608   std::vector<uint8_t> loaded_vbmeta;
2609   loaded_vbmeta.resize(1152);
2610   EXPECT_EQ(
2611       f.Read(
2612           5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152),
2613       1152);
2614   EXPECT_EQ(vbmeta_image_, loaded_vbmeta);
2615 }
2616 
TEST_F(AvbToolTest,SigningHelperBasic)2617 TEST_F(AvbToolTest, SigningHelperBasic) {
2618   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2619   base::FilePath signing_helper_test_path =
2620       testdir_.Append("signing_helper_test");
2621   EXPECT_COMMAND(
2622       0,
2623       "SIGNING_HELPER_TEST=\"%s\" ./avbtool.py make_vbmeta_image "
2624       "--output %s "
2625       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2626       "--signing_helper test/avbtool_signing_helper_test.py "
2627       "--internal_release_string \"\"",
2628       signing_helper_test_path.value().c_str(),
2629       vbmeta_path.value().c_str());
2630 
2631   // Now check the value in test file.
2632   std::string value;
2633   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
2634   EXPECT_EQ("DONE", value);
2635 }
2636 
TEST_F(AvbToolTest,SigningHelperWithFilesBasic)2637 TEST_F(AvbToolTest, SigningHelperWithFilesBasic) {
2638   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2639   base::FilePath signing_helper_test_path =
2640       testdir_.Append("signing_helper_test");
2641   EXPECT_COMMAND(
2642       0,
2643       "SIGNING_HELPER_TEST=\"%s\" ./avbtool.py make_vbmeta_image "
2644       "--output %s "
2645       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2646       "--signing_helper_with_files "
2647       "test/avbtool_signing_helper_with_files_test.py "
2648       "--internal_release_string \"\"",
2649       signing_helper_test_path.value().c_str(),
2650       vbmeta_path.value().c_str());
2651 
2652   // Now check the value in test file.
2653   std::string value;
2654   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
2655   EXPECT_EQ("DONE", value);
2656 }
2657 
TEST_F(AvbToolTest,SigningHelperReturnError)2658 TEST_F(AvbToolTest, SigningHelperReturnError) {
2659   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2660   EXPECT_COMMAND(
2661       1,
2662       "./avbtool.py make_vbmeta_image "
2663       "--output %s "
2664       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2665       "--signing_helper test/avbtool_signing_helper_test.py "
2666       "--internal_release_string \"\"",
2667       vbmeta_path.value().c_str());
2668 }
2669 
TEST_F(AvbToolTest,SigningHelperWithFilesReturnError)2670 TEST_F(AvbToolTest, SigningHelperWithFilesReturnError) {
2671   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2672   EXPECT_COMMAND(
2673       1,
2674       "./avbtool.py make_vbmeta_image "
2675       "--output %s "
2676       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2677       "--signing_helper_with_files "
2678       "test/avbtool_signing_helper_with_files_test.py "
2679       "--internal_release_string \"\"",
2680       vbmeta_path.value().c_str());
2681 }
2682 
TEST_F(AvbToolTest,VerifyImageNoSignature)2683 TEST_F(AvbToolTest, VerifyImageNoSignature) {
2684   GenerateVBMetaImage("vbmeta.img",
2685                       "",  // NONE
2686                       0,
2687                       base::FilePath());
2688 
2689   EXPECT_COMMAND(0,
2690                  "./avbtool.py verify_image "
2691                  "--image %s ",
2692                  vbmeta_image_path_.value().c_str());
2693 }
2694 
TEST_F(AvbToolTest,VerifyImageValidSignature)2695 TEST_F(AvbToolTest, VerifyImageValidSignature) {
2696   GenerateVBMetaImage("vbmeta.img",
2697                       "SHA256_RSA2048",
2698                       0,
2699                       base::FilePath("test/data/testkey_rsa2048.pem"));
2700 
2701   EXPECT_COMMAND(0,
2702                  "./avbtool.py verify_image "
2703                  "--image %s ",
2704                  vbmeta_image_path_.value().c_str());
2705 }
2706 
TEST_F(AvbToolTest,VerifyImageCorruptedVBMeta)2707 TEST_F(AvbToolTest, VerifyImageCorruptedVBMeta) {
2708   GenerateVBMetaImage("vbmeta.img",
2709                       "SHA256_RSA2048",
2710                       0,
2711                       base::FilePath("test/data/testkey_rsa2048.pem"));
2712 
2713   // Corrupt four bytes of data in the end of the image. Since the aux
2714   // data is at the end and this data is signed, this will change the
2715   // value of the computed hash.
2716   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2717   EXPECT_EQ(AVB_IO_RESULT_OK,
2718             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2719                                                "vbmeta",
2720                                                -4,  // offset from end
2721                                                sizeof corrupt_data,
2722                                                corrupt_data));
2723 
2724   EXPECT_COMMAND(1,
2725                  "./avbtool.py verify_image "
2726                  "--image %s ",
2727                  vbmeta_image_path_.value().c_str());
2728 }
2729 
TEST_F(AvbToolTest,VerifyImageOtherKeyMatching)2730 TEST_F(AvbToolTest, VerifyImageOtherKeyMatching) {
2731   GenerateVBMetaImage("vbmeta.img",
2732                       "SHA256_RSA2048",
2733                       0,
2734                       base::FilePath("test/data/testkey_rsa2048.pem"));
2735 
2736   EXPECT_COMMAND(0,
2737                  "./avbtool.py verify_image "
2738                  "--image %s --key test/data/testkey_rsa2048.pem",
2739                  vbmeta_image_path_.value().c_str());
2740 }
2741 
TEST_F(AvbToolTest,VerifyImageOtherKeyNotMatching)2742 TEST_F(AvbToolTest, VerifyImageOtherKeyNotMatching) {
2743   GenerateVBMetaImage("vbmeta.img",
2744                       "SHA256_RSA2048",
2745                       0,
2746                       base::FilePath("test/data/testkey_rsa2048.pem"));
2747 
2748   EXPECT_COMMAND(1,
2749                  "./avbtool.py verify_image "
2750                  "--image %s --key test/data/testkey_rsa4096.pem",
2751                  vbmeta_image_path_.value().c_str());
2752 }
2753 
TEST_F(AvbToolTest,VerifyImageBrokenSignature)2754 TEST_F(AvbToolTest, VerifyImageBrokenSignature) {
2755   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2756   base::FilePath signing_helper_test_path =
2757       testdir_.Append("signing_helper_test");
2758 
2759   // Intentionally make the signer generate a wrong signature.
2760   EXPECT_COMMAND(
2761       0,
2762       "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool.py make_vbmeta_image "
2763       "--output %s "
2764       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2765       "--signing_helper test/avbtool_signing_helper_test.py "
2766       "--internal_release_string \"\"",
2767       vbmeta_path.value().c_str());
2768 
2769   EXPECT_COMMAND(1,
2770                  "./avbtool.py verify_image "
2771                  "--image %s ",
2772                  vbmeta_path.value().c_str());
2773 }
2774 
2775 // Helper to generate boot.img, unsparse system.img, and vbmeta.img.
GenerateImageWithHashAndHashtreeSetup()2776 void AvbToolTest::GenerateImageWithHashAndHashtreeSetup() {
2777   const size_t boot_partition_size = 16 * 1024 * 1024;
2778   const size_t boot_image_size = 5 * 1024 * 1024;
2779   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
2780   EXPECT_COMMAND(0,
2781                  "./avbtool.py add_hash_footer"
2782                  " --image %s"
2783                  " --rollback_index 0"
2784                  " --partition_name boot"
2785                  " --partition_size %zd"
2786                  " --salt deadbeef"
2787                  " --internal_release_string \"\"",
2788                  boot_path.value().c_str(),
2789                  boot_partition_size);
2790 
2791   const size_t system_partition_size = 10 * 1024 * 1024;
2792   const size_t system_image_size = 8 * 1024 * 1024;
2793   base::FilePath system_path = GenerateImage("system.img", system_image_size);
2794   EXPECT_COMMAND(0,
2795                  "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
2796                  "--partition_size %zd --partition_name system "
2797                  "--internal_release_string \"\" ",
2798                  system_path.value().c_str(),
2799                  system_partition_size);
2800 
2801   GenerateVBMetaImage("vbmeta.img",
2802                       "SHA256_RSA2048",
2803                       0,
2804                       base::FilePath("test/data/testkey_rsa2048.pem"),
2805                       base::StringPrintf("--include_descriptors_from_image %s "
2806                                          "--include_descriptors_from_image %s",
2807                                          boot_path.value().c_str(),
2808                                          system_path.value().c_str()));
2809 }
2810 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtree)2811 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) {
2812   GenerateImageWithHashAndHashtreeSetup();
2813 
2814   // Do two checks - one for system.img not sparse, and one where it
2815   // is sparse.
2816   for (int n = 0; n < 2; n++) {
2817     EXPECT_COMMAND(0,
2818                    "./avbtool.py verify_image "
2819                    "--image %s ",
2820                    vbmeta_image_path_.value().c_str());
2821     if (n == 0) {
2822       EXPECT_COMMAND(0,
2823                      "img2simg %s %s.sparse",
2824                      testdir_.Append("system.img").value().c_str(),
2825                      testdir_.Append("system.img").value().c_str());
2826       EXPECT_COMMAND(0,
2827                      "mv %s.sparse %s",
2828                      testdir_.Append("system.img").value().c_str(),
2829                      testdir_.Append("system.img").value().c_str());
2830     }
2831   }
2832 }
2833 
TEST_F(AvbToolTest,VerifyImageWithHashAndZeroedHashtree)2834 TEST_F(AvbToolTest, VerifyImageWithHashAndZeroedHashtree) {
2835   const size_t system_partition_size = 10 * 1024 * 1024;
2836   const size_t system_image_size = 8 * 1024 * 1024;
2837   base::FilePath system_path = GenerateImage("system.img", system_image_size);
2838   EXPECT_COMMAND(0,
2839                  "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
2840                  "--partition_size %zd --partition_name system "
2841                  "--internal_release_string \"\" ",
2842                  system_path.value().c_str(),
2843                  system_partition_size);
2844 
2845   GenerateVBMetaImage("vbmeta.img",
2846                       "SHA256_RSA2048",
2847                       0,
2848                       base::FilePath("test/data/testkey_rsa2048.pem"),
2849                       base::StringPrintf("--include_descriptors_from_image %s ",
2850                                          system_path.value().c_str()));
2851 
2852   EXPECT_COMMAND(0,
2853                  "./avbtool.py verify_image --image %s --accept_zeroed_hashtree",
2854                  vbmeta_image_path_.value().c_str());
2855 
2856   EXPECT_COMMAND(
2857       0, "./avbtool.py zero_hashtree --image %s", system_path.value().c_str());
2858 
2859   EXPECT_COMMAND(1,
2860                  "./avbtool.py verify_image --image %s",
2861                  vbmeta_image_path_.value().c_str());
2862 
2863   EXPECT_COMMAND(0,
2864                  "./avbtool.py verify_image --image %s --accept_zeroed_hashtree",
2865                  vbmeta_image_path_.value().c_str());
2866 }
2867 
TEST_F(AvbToolTest,VerifyImageWithNoHashtree)2868 TEST_F(AvbToolTest, VerifyImageWithNoHashtree) {
2869   const size_t system_partition_size = 10 * 1024 * 1024;
2870   const size_t system_image_size = 8 * 1024 * 1024;
2871   base::FilePath system_path = GenerateImage("system.img", system_image_size);
2872   EXPECT_COMMAND(0,
2873                  "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
2874                  "--partition_size %zd --partition_name system "
2875                  "--no_hashtree "
2876                  "--internal_release_string \"\" ",
2877                  system_path.value().c_str(),
2878                  system_partition_size);
2879 
2880   GenerateVBMetaImage("vbmeta.img",
2881                       "SHA256_RSA2048",
2882                       0,
2883                       base::FilePath("test/data/testkey_rsa2048.pem"),
2884                       base::StringPrintf("--include_descriptors_from_image %s ",
2885                                          system_path.value().c_str()));
2886 
2887   EXPECT_COMMAND(1,
2888                  "./avbtool.py verify_image --image %s",
2889                  vbmeta_image_path_.value().c_str());
2890 
2891   EXPECT_COMMAND(0,
2892                  "./avbtool.py verify_image --image %s --accept_zeroed_hashtree",
2893                  vbmeta_image_path_.value().c_str());
2894 }
2895 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHash)2896 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) {
2897   GenerateImageWithHashAndHashtreeSetup();
2898 
2899   // Corrupt four bytes of data in the middle of boot.img.
2900   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2901   EXPECT_EQ(AVB_IO_RESULT_OK,
2902             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2903                                                "boot",
2904                                                105 * 1024,  // offset from start
2905                                                sizeof corrupt_data,
2906                                                corrupt_data));
2907 
2908   EXPECT_COMMAND(1,
2909                  "./avbtool.py verify_image "
2910                  "--image %s ",
2911                  vbmeta_image_path_.value().c_str());
2912 }
2913 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHashtree)2914 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHashtree) {
2915   GenerateImageWithHashAndHashtreeSetup();
2916 
2917   // Corrupt four bytes of data in the middle of system.img.
2918   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2919   EXPECT_EQ(AVB_IO_RESULT_OK,
2920             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2921                                                "system",
2922                                                123 * 1024,  // offset from start
2923                                                sizeof corrupt_data,
2924                                                corrupt_data));
2925 
2926   // Do two checks - one for system.img not sparse, and one where it
2927   // is sparse.
2928   for (int n = 0; n < 2; n++) {
2929     EXPECT_COMMAND(1,
2930                    "./avbtool.py verify_image "
2931                    "--image %s ",
2932                    vbmeta_image_path_.value().c_str());
2933     if (n == 0) {
2934       EXPECT_COMMAND(0,
2935                      "img2simg %s %s.sparse",
2936                      testdir_.Append("system.img").value().c_str(),
2937                      testdir_.Append("system.img").value().c_str());
2938       EXPECT_COMMAND(0,
2939                      "mv %s.sparse %s",
2940                      testdir_.Append("system.img").value().c_str(),
2941                      testdir_.Append("system.img").value().c_str());
2942     }
2943   }
2944 }
2945 
TEST_F(AvbToolTest,VerifyImageChainPartition)2946 TEST_F(AvbToolTest, VerifyImageChainPartition) {
2947   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
2948   EXPECT_COMMAND(
2949       0,
2950       "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
2951       " --output %s",
2952       pk4096_path.value().c_str());
2953 
2954   base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey");
2955   EXPECT_COMMAND(
2956       0,
2957       "./avbtool.py extract_public_key --key test/data/testkey_rsa8192.pem"
2958       " --output %s",
2959       pk8192_path.value().c_str());
2960 
2961   GenerateVBMetaImage("vbmeta.img",
2962                       "SHA256_RSA2048",
2963                       0,
2964                       base::FilePath("test/data/testkey_rsa2048.pem"),
2965                       base::StringPrintf("--chain_partition system:1:%s ",
2966                                          pk4096_path.value().c_str()));
2967 
2968   // Should not fail (name, rollback_index, contents all correct).
2969   EXPECT_COMMAND(0,
2970                  "./avbtool.py verify_image "
2971                  "--image %s "
2972                  "--expected_chain_partition system:1:%s",
2973                  vbmeta_image_path_.value().c_str(),
2974                  pk4096_path.value().c_str());
2975 
2976   // Should fail because we didn't use --expected_chain_partition.
2977   EXPECT_COMMAND(1,
2978                  "./avbtool.py verify_image "
2979                  "--image %s ",
2980                  vbmeta_image_path_.value().c_str());
2981 
2982   // Should fail because partition name is wrong.
2983   EXPECT_COMMAND(1,
2984                  "./avbtool.py verify_image "
2985                  "--image %s "
2986                  "--expected_chain_partition xyz:1:%s",
2987                  vbmeta_image_path_.value().c_str(),
2988                  pk4096_path.value().c_str());
2989 
2990   // Should fail because rollback index location is wrong.
2991   EXPECT_COMMAND(1,
2992                  "./avbtool.py verify_image "
2993                  "--image %s "
2994                  "--expected_chain_partition system:2:%s",
2995                  vbmeta_image_path_.value().c_str(),
2996                  pk4096_path.value().c_str());
2997 
2998   // Should fail because public key blob is wrong.
2999   EXPECT_COMMAND(1,
3000                  "./avbtool.py verify_image "
3001                  "--image %s "
3002                  "--expected_chain_partition system:1:%s",
3003                  vbmeta_image_path_.value().c_str(),
3004                  pk8192_path.value().c_str());
3005 }
3006 
TEST_F(AvbToolTest,VerifyImageChainPartitionWithFollow)3007 TEST_F(AvbToolTest, VerifyImageChainPartitionWithFollow) {
3008   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
3009   EXPECT_COMMAND(
3010       0,
3011       "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
3012       " --output %s",
3013       pk4096_path.value().c_str());
3014 
3015   GenerateVBMetaImage("vbmeta.img",
3016                       "SHA256_RSA2048",
3017                       0,
3018                       base::FilePath("test/data/testkey_rsa2048.pem"),
3019                       base::StringPrintf("--chain_partition system:1:%s ",
3020                                          pk4096_path.value().c_str()));
3021 
3022   const size_t system_partition_size = 10 * 1024 * 1024;
3023   const size_t system_image_size = 8 * 1024 * 1024;
3024   base::FilePath system_path = GenerateImage("system.img", system_image_size);
3025   EXPECT_COMMAND(0,
3026                  "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
3027                  "--partition_size %zd --partition_name system "
3028                  "--algorithm SHA256_RSA4096 "
3029                  "--key test/data/testkey_rsa4096.pem "
3030                  "--internal_release_string \"\" ",
3031                  system_path.value().c_str(),
3032                  system_partition_size);
3033 
3034   // Even without --expected_chain_partition this shouldn't fail because we use
3035   // --follow_chain_partitions and system.img exists... to avoid unstable paths
3036   // (e.g. /tmp/libavb.12345) in the output we need to run this from the test
3037   // directory itself. It's a little ugly but it works.
3038   char cwdbuf[PATH_MAX];
3039   ASSERT_NE(nullptr, getcwd(cwdbuf, sizeof cwdbuf));
3040   EXPECT_COMMAND(0,
3041                  "cd %s && (%s/avbtool.py verify_image "
3042                  "--image vbmeta.img --follow_chain_partitions > out.txt)",
3043                  testdir_.value().c_str(),
3044                  cwdbuf);
3045   base::FilePath out_path = testdir_.Append("out.txt");
3046   std::string out;
3047   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3048   EXPECT_EQ(
3049       "Verifying image vbmeta.img using embedded public key\n"
3050       "vbmeta: Successfully verified SHA256_RSA2048 vbmeta struct in "
3051       "vbmeta.img\n"
3052       "system: Chained but ROLLBACK_SLOT (which is 1) and KEY (which has sha1 "
3053       "2597c218aae470a130f61162feaae70afd97f011) not specified\n"
3054       "--\n"
3055       "Verifying image system.img using embedded public key\n"
3056       "vbmeta: Successfully verified footer and SHA256_RSA4096 vbmeta struct "
3057       "in system.img\n"
3058       "system: Successfully verified sha1 hashtree of system.img for image of "
3059       "8388608 bytes\n",
3060       out);
3061 
3062   // Make sure we also follow partitions *even* when specifying
3063   // --expect_chain_partition. The output is slightly different from above.
3064   EXPECT_COMMAND(0,
3065                  "cd %s && (%s/avbtool.py verify_image "
3066                  "--image vbmeta.img --expected_chain_partition system:1:%s "
3067                  "--follow_chain_partitions > out.txt)",
3068                  testdir_.value().c_str(),
3069                  cwdbuf,
3070                  pk4096_path.value().c_str());
3071   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3072   EXPECT_EQ(
3073       "Verifying image vbmeta.img using embedded public key\n"
3074       "vbmeta: Successfully verified SHA256_RSA2048 vbmeta struct in "
3075       "vbmeta.img\n"
3076       "system: Successfully verified chain partition descriptor matches "
3077       "expected data\n"
3078       "--\n"
3079       "Verifying image system.img using embedded public key\n"
3080       "vbmeta: Successfully verified footer and SHA256_RSA4096 vbmeta struct "
3081       "in system.img\n"
3082       "system: Successfully verified sha1 hashtree of system.img for image of "
3083       "8388608 bytes\n",
3084       out);
3085 }
3086 
TEST_F(AvbToolTest,VerifyImageChainPartitionOtherVBMeta)3087 TEST_F(AvbToolTest, VerifyImageChainPartitionOtherVBMeta) {
3088   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
3089   EXPECT_COMMAND(
3090       0,
3091       "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
3092       " --output %s",
3093       pk4096_path.value().c_str());
3094 
3095   const size_t system_partition_size = 10 * 1024 * 1024;
3096   const size_t system_image_size = 8 * 1024 * 1024;
3097   base::FilePath system_path = GenerateImage("system.img", system_image_size);
3098   EXPECT_COMMAND(0,
3099                  "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
3100                  "--partition_size %zd --partition_name system "
3101                  "--internal_release_string \"\" "
3102                  "--algorithm SHA256_RSA4096 "
3103                  "--key test/data/testkey_rsa4096.pem ",
3104                  system_path.value().c_str(),
3105                  system_partition_size,
3106                  pk4096_path.value().c_str());
3107 
3108   GenerateVBMetaImage(
3109       "vbmeta.img",
3110       "SHA256_RSA2048",
3111       0,
3112       base::FilePath("test/data/testkey_rsa2048.pem"),
3113       base::StringPrintf("--chain_partition vbmeta_google:1:%s ",
3114                          pk4096_path.value().c_str()));
3115 
3116   // Should not fail (name, rollback_index, contents all correct).
3117   EXPECT_COMMAND(0,
3118                  "./avbtool.py verify_image "
3119                  "--image %s "
3120                  "--expected_chain_partition vbmeta_google:1:%s",
3121                  vbmeta_image_path_.value().c_str(),
3122                  pk4096_path.value().c_str());
3123 
3124   // Should not fail (looks in system.img image).
3125   EXPECT_COMMAND(0,
3126                  "./avbtool.py verify_image "
3127                  "--image %s ",
3128                  system_path.value().c_str());
3129 
3130   // Extract the vbmeta blob from the footer in system.img, put it into
3131   // vbmeta_google.img, and erase the footer from system.img (but keep
3132   // the hash tree in system.img)
3133   base::FilePath vbmeta_google_path = GenerateImage("vbmeta_google.img", 0);
3134   EXPECT_COMMAND(0,
3135                  "./avbtool.py extract_vbmeta_image"
3136                  " --image %s"
3137                  " --output %s",
3138                  system_path.value().c_str(),
3139                  vbmeta_google_path.value().c_str());
3140   EXPECT_COMMAND(0,
3141                  "./avbtool.py erase_footer"
3142                  " --image %s --keep_hashtree",
3143                  system_path.value().c_str());
3144 
3145   // Should not fail - looks in system.img's detached vbmeta (vbmeta_google.img)
3146   // for vbmeta blob and system.img for the actual hashtree.
3147   EXPECT_COMMAND(0,
3148                  "./avbtool.py verify_image "
3149                  "--image %s ",
3150                  vbmeta_google_path.value().c_str());
3151 }
3152 
TEST_F(AvbToolTest,PrintPartitionDigests)3153 TEST_F(AvbToolTest, PrintPartitionDigests) {
3154   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
3155   EXPECT_COMMAND(
3156       0,
3157       "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
3158       " --output %s",
3159       pk4096_path.value().c_str());
3160 
3161   const size_t boot_partition_size = 16 * 1024 * 1024;
3162   const size_t boot_image_size = 5 * 1024 * 1024;
3163   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
3164   EXPECT_COMMAND(0,
3165                  "./avbtool.py add_hash_footer"
3166                  " --image %s"
3167                  " --rollback_index 0"
3168                  " --partition_name boot"
3169                  " --partition_size %zd"
3170                  " --salt deadbeef"
3171                  " --internal_release_string \"\"",
3172                  boot_path.value().c_str(),
3173                  boot_partition_size);
3174 
3175   GenerateVBMetaImage("vbmeta.img",
3176                       "SHA256_RSA2048",
3177                       0,
3178                       base::FilePath("test/data/testkey_rsa2048.pem"),
3179                       base::StringPrintf("--chain_partition system:1:%s "
3180                                          "--include_descriptors_from_image %s",
3181                                          pk4096_path.value().c_str(),
3182                                          boot_path.value().c_str()));
3183 
3184   const size_t system_partition_size = 10 * 1024 * 1024;
3185   const size_t system_image_size = 8 * 1024 * 1024;
3186   base::FilePath system_path = GenerateImage("system.img", system_image_size);
3187   EXPECT_COMMAND(0,
3188                  "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
3189                  "--partition_size %zd --partition_name system "
3190                  "--algorithm SHA256_RSA4096 "
3191                  "--key test/data/testkey_rsa4096.pem "
3192                  "--internal_release_string \"\" ",
3193                  system_path.value().c_str(),
3194                  system_partition_size);
3195 
3196   base::FilePath out_path = testdir_.Append("out.txt");
3197   std::string out;
3198 
3199   // Normal output
3200   EXPECT_COMMAND(0,
3201                  "./avbtool.py print_partition_digests --image %s --output %s",
3202                  vbmeta_image_path_.value().c_str(),
3203                  out_path.value().c_str());
3204   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3205   EXPECT_EQ(
3206       "system: d52d93c988d336a79abe1c05240ae9a79a9b7d61\n"
3207       "boot: "
3208       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n",
3209       out);
3210 
3211   // JSON output
3212   EXPECT_COMMAND(
3213       0,
3214       "./avbtool.py print_partition_digests --image %s --json --output %s",
3215       vbmeta_image_path_.value().c_str(),
3216       out_path.value().c_str());
3217   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3218   // The trailing whitespace comes from python. If they fix that bug we need
3219   // to update this test...
3220   EXPECT_EQ(
3221       "{\n"
3222       "  \"partitions\": [\n"
3223       "    {\n"
3224       "      \"name\": \"system\",\n"
3225       "      \"digest\": \"d52d93c988d336a79abe1c05240ae9a79a9b7d61\"\n"
3226       "    },\n"
3227       "    {\n"
3228       "      \"name\": \"boot\",\n"
3229       "      \"digest\": "
3230       "\"184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\"\n"
3231       "    }\n"
3232       "  ]\n"
3233       "}",
3234       out);
3235 }
3236 
3237 class AvbToolTest_PrintRequiredVersion : public AvbToolTest {
3238  protected:
3239   const char* kOutputFile = "versions.txt";
3240 
PrintWithAddHashFooter(int target_required_minor_version)3241   void PrintWithAddHashFooter(int target_required_minor_version) {
3242     std::string extra_args;
3243     if (target_required_minor_version == 1) {
3244       // The --do_not_use_ab option will require 1.1.
3245       extra_args = "--do_not_use_ab";
3246     } else if (target_required_minor_version == 2) {
3247       extra_args = "--rollback_index_location 2";
3248     }
3249 
3250     const size_t boot_partition_size = 16 * 1024 * 1024;
3251     base::FilePath output_path = testdir_.Append(kOutputFile);
3252     EXPECT_COMMAND(0,
3253                    "./avbtool.py add_hash_footer"
3254                    " --rollback_index 0"
3255                    " --partition_name boot"
3256                    " --partition_size %zd"
3257                    " --salt deadbeef"
3258                    " --internal_release_string \"\""
3259                    " %s"
3260                    " --print_required_libavb_version > %s",
3261                    boot_partition_size,
3262                    extra_args.c_str(),
3263                    output_path.value().c_str());
3264     CheckVersion(target_required_minor_version);
3265   }
3266 
PrintWithAddHashtreeFooter(int target_required_minor_version)3267   void PrintWithAddHashtreeFooter(int target_required_minor_version) {
3268     std::string extra_args;
3269     if (target_required_minor_version == 1) {
3270       // The --do_not_use_ab option will require 1.1.
3271       extra_args = "--do_not_use_ab --check_at_most_once";
3272     } else if (target_required_minor_version == 2) {
3273       extra_args = "--rollback_index_location 2";
3274     }
3275     const size_t system_partition_size = 10 * 1024 * 1024;
3276     base::FilePath output_path = testdir_.Append(kOutputFile);
3277     EXPECT_COMMAND(0,
3278                    "./avbtool.py add_hashtree_footer --salt d00df00d "
3279                    "--partition_size %zd --partition_name system "
3280                    "--internal_release_string \"\""
3281                    " %s"
3282                    " --print_required_libavb_version > %s",
3283                    system_partition_size,
3284                    extra_args.c_str(),
3285                    output_path.value().c_str());
3286     CheckVersion(target_required_minor_version);
3287   }
3288 
PrintWithMakeVbmetaImage(int target_required_minor_version)3289   void PrintWithMakeVbmetaImage(int target_required_minor_version) {
3290     std::string extra_args;
3291     if (target_required_minor_version == 1) {
3292       // An included descriptor that requires 1.1 will require 1.1 for vbmeta.
3293       const size_t boot_partition_size = 16 * 1024 * 1024;
3294       base::FilePath image_path = GenerateImage("test_print_version", 1024);
3295       EXPECT_COMMAND(0,
3296                      "./avbtool.py add_hash_footer --salt d00df00d "
3297                      "--hash_algorithm sha256 --image %s "
3298                      "--partition_size %d --partition_name foobar "
3299                      "--algorithm SHA256_RSA2048 "
3300                      "--key test/data/testkey_rsa2048.pem "
3301                      "--internal_release_string \"\" "
3302                      "--do_not_use_ab",
3303                      image_path.value().c_str(),
3304                      (int)boot_partition_size);
3305       extra_args = base::StringPrintf("--include_descriptors_from_image %s",
3306                                       image_path.value().c_str());
3307     } else if (target_required_minor_version == 2) {
3308       extra_args = "--rollback_index_location 2";
3309     }
3310 
3311     base::FilePath output_path = testdir_.Append(kOutputFile);
3312     EXPECT_COMMAND(0,
3313                    "./avbtool.py make_vbmeta_image "
3314                    "--algorithm SHA256_RSA2048 "
3315                    "--key test/data/testkey_rsa2048.pem "
3316                    "--internal_release_string \"\""
3317                    " %s"
3318                    " --print_required_libavb_version > %s",
3319                    extra_args.c_str(),
3320                    output_path.value().c_str());
3321     CheckVersion(target_required_minor_version);
3322   }
3323 
CheckVersion(int expected_required_minor_version)3324   void CheckVersion(int expected_required_minor_version) {
3325     base::FilePath output_path = testdir_.Append(kOutputFile);
3326     std::string output;
3327     ASSERT_TRUE(base::ReadFileToString(output_path, &output));
3328     EXPECT_EQ(output,
3329               base::StringPrintf("1.%d\n", expected_required_minor_version));
3330   }
3331 };
3332 
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_0)3333 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_0) {
3334   PrintWithAddHashFooter(0);
3335 }
3336 
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_1)3337 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_1) {
3338   PrintWithAddHashFooter(1);
3339 }
3340 
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_2)3341 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_2) {
3342   PrintWithAddHashFooter(2);
3343 }
3344 
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_0)3345 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_0) {
3346   PrintWithAddHashtreeFooter(0);
3347 }
3348 
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_1)3349 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_1) {
3350   PrintWithAddHashtreeFooter(1);
3351 }
3352 
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_2)3353 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_2) {
3354   PrintWithAddHashtreeFooter(2);
3355 }
3356 
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_0)3357 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_0) {
3358   PrintWithMakeVbmetaImage(0);
3359 }
3360 
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_1)3361 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_1) {
3362   PrintWithMakeVbmetaImage(1);
3363 }
3364 
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_2)3365 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_2) {
3366   PrintWithMakeVbmetaImage(2);
3367 }
3368 
TEST_F(AvbToolTest,MakeAtxPikCertificate)3369 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
3370   base::FilePath subject_path = testdir_.Append("tmp_subject");
3371   ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
3372   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3373   EXPECT_COMMAND(
3374       0,
3375       "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
3376       pubkey_path.value().c_str());
3377 
3378   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3379   EXPECT_COMMAND(0,
3380                  "./avbtool.py make_atx_certificate"
3381                  " --subject %s"
3382                  " --subject_key %s"
3383                  " --subject_key_version 42"
3384                  " --subject_is_intermediate_authority"
3385                  " --authority_key test/data/testkey_atx_prk.pem"
3386                  " --output %s",
3387                  subject_path.value().c_str(),
3388                  pubkey_path.value().c_str(),
3389                  output_path.value().c_str());
3390 
3391   EXPECT_COMMAND(0,
3392                  "diff test/data/atx_pik_certificate.bin %s",
3393                  output_path.value().c_str());
3394 }
3395 
TEST_F(AvbToolTest,MakeAtxPskCertificate)3396 TEST_F(AvbToolTest, MakeAtxPskCertificate) {
3397   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3398   EXPECT_COMMAND(
3399       0,
3400       "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
3401       pubkey_path.value().c_str());
3402 
3403   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3404   EXPECT_COMMAND(0,
3405                  "./avbtool.py make_atx_certificate"
3406                  " --subject test/data/atx_product_id.bin"
3407                  " --subject_key %s"
3408                  " --subject_key_version 42"
3409                  " --authority_key test/data/testkey_atx_pik.pem"
3410                  " --output %s",
3411                  pubkey_path.value().c_str(),
3412                  output_path.value().c_str());
3413 
3414   EXPECT_COMMAND(0,
3415                  "diff test/data/atx_psk_certificate.bin %s",
3416                  output_path.value().c_str());
3417 }
3418 
TEST_F(AvbToolTest,MakeAtxPukCertificate)3419 TEST_F(AvbToolTest, MakeAtxPukCertificate) {
3420   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3421   EXPECT_COMMAND(
3422       0,
3423       "openssl pkey -pubout -in test/data/testkey_atx_puk.pem -out %s",
3424       pubkey_path.value().c_str());
3425 
3426   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3427   EXPECT_COMMAND(0,
3428                  "./avbtool.py make_atx_certificate"
3429                  " --subject test/data/atx_product_id.bin"
3430                  " --subject_key %s"
3431                  " --subject_key_version 42"
3432                  " --usage com.google.android.things.vboot.unlock"
3433                  " --authority_key test/data/testkey_atx_pik.pem"
3434                  " --output %s",
3435                  pubkey_path.value().c_str(),
3436                  output_path.value().c_str());
3437 
3438   EXPECT_COMMAND(0,
3439                  "diff test/data/atx_puk_certificate.bin %s",
3440                  output_path.value().c_str());
3441 }
3442 
TEST_F(AvbToolTest,MakeAtxPermanentAttributes)3443 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) {
3444   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3445   EXPECT_COMMAND(
3446       0,
3447       "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
3448       pubkey_path.value().c_str());
3449 
3450   base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
3451   EXPECT_COMMAND(0,
3452                  "./avbtool.py make_atx_permanent_attributes"
3453                  " --root_authority_key %s"
3454                  " --product_id test/data/atx_product_id.bin"
3455                  " --output %s",
3456                  pubkey_path.value().c_str(),
3457                  output_path.value().c_str());
3458 
3459   EXPECT_COMMAND(0,
3460                  "diff test/data/atx_permanent_attributes.bin %s",
3461                  output_path.value().c_str());
3462 }
3463 
TEST_F(AvbToolTest,MakeAtxMetadata)3464 TEST_F(AvbToolTest, MakeAtxMetadata) {
3465   base::FilePath output_path = testdir_.Append("tmp_metadata.bin");
3466 
3467   EXPECT_COMMAND(
3468       0,
3469       "./avbtool.py make_atx_metadata"
3470       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
3471       " --product_key_certificate test/data/atx_psk_certificate.bin"
3472       " --output %s",
3473       output_path.value().c_str());
3474 
3475   EXPECT_COMMAND(
3476       0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str());
3477 }
3478 
TEST_F(AvbToolTest,MakeAtxUnlockCredential)3479 TEST_F(AvbToolTest, MakeAtxUnlockCredential) {
3480   base::FilePath output_path = testdir_.Append("tmp_credential.bin");
3481 
3482   EXPECT_COMMAND(
3483       0,
3484       "./avbtool.py make_atx_unlock_credential"
3485       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
3486       " --unlock_key_certificate test/data/atx_puk_certificate.bin"
3487       " --challenge test/data/atx_unlock_challenge.bin"
3488       " --unlock_key test/data/testkey_atx_puk.pem"
3489       " --output %s",
3490       output_path.value().c_str());
3491 
3492   EXPECT_COMMAND(0,
3493                  "diff test/data/atx_unlock_credential.bin %s",
3494                  output_path.value().c_str());
3495 }
3496 
3497 }  // namespace avb
3498