• 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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,AddHashtreeFooterWithCheckAtMostOnce)2009 TEST_F(AvbToolTest, AddHashtreeFooterWithCheckAtMostOnce) {
2010   size_t partition_size = 10 * 1024 * 1024;
2011   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
2012   EXPECT_COMMAND(0,
2013                  "./avbtool add_hashtree_footer --salt d00df00d "
2014                  "--hash_algorithm sha256 --image %s "
2015                  "--partition_size %d --partition_name foobar "
2016                  "--algorithm SHA256_RSA2048 "
2017                  "--key test/data/testkey_rsa2048.pem "
2018                  "--internal_release_string \"\" "
2019                  "--check_at_most_once",
2020                  path.value().c_str(),
2021                  (int)partition_size);
2022   // There are two important bits here we're expecting with --check_at_most_once:
2023   //   Minimum libavb version = 1.1
2024   //   Hashtree descriptor -> Flags = 2
2025   ASSERT_EQ(
2026       "Footer version:           1.0\n"
2027       "Image size:               10485760 bytes\n"
2028       "Original image size:      5242880 bytes\n"
2029       "VBMeta offset:            5337088\n"
2030       "VBMeta size:              1344 bytes\n"
2031       "--\n"
2032       "Minimum libavb version:   1.1\n"
2033       "Header Block:             256 bytes\n"
2034       "Authentication Block:     320 bytes\n"
2035       "Auxiliary Block:          768 bytes\n"
2036       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2037       "Algorithm:                SHA256_RSA2048\n"
2038       "Rollback Index:           0\n"
2039       "Flags:                    0\n"
2040       "Rollback Index Location:  0\n"
2041       "Release String:           ''\n"
2042       "Descriptors:\n"
2043       "    Hashtree descriptor:\n"
2044       "      Version of dm-verity:  1\n"
2045       "      Image Size:            5242880 bytes\n"
2046       "      Tree Offset:           5242880\n"
2047       "      Tree Size:             45056 bytes\n"
2048       "      Data Block Size:       4096 bytes\n"
2049       "      Hash Block Size:       4096 bytes\n"
2050       "      FEC num roots:         2\n"
2051       "      FEC offset:            5287936\n"
2052       "      FEC size:              49152 bytes\n"
2053       "      Hash Algorithm:        sha256\n"
2054       "      Partition Name:        foobar\n"
2055       "      Salt:                  d00df00d\n"
2056       "      Root Digest:           "
2057       "d0e31526f5a3f8e3f59acf726bd31ae7861ee78f9baa9195356bf479c6f9119d\n"
2058       "      Flags:                 2\n",
2059       InfoImage(path));
2060 }
2061 
TEST_F(AvbToolTest,KernelCmdlineDescriptor)2062 TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
2063   base::FilePath vbmeta_path =
2064       testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
2065 
2066   EXPECT_COMMAND(0,
2067                  "./avbtool make_vbmeta_image "
2068                  "--output %s "
2069                  "--kernel_cmdline 'foo bar baz' "
2070                  "--kernel_cmdline 'second cmdline' "
2071                  "--algorithm SHA256_RSA2048 "
2072                  "--key test/data/testkey_rsa2048.pem "
2073                  "--internal_release_string \"\"",
2074                  vbmeta_path.value().c_str());
2075 
2076   ASSERT_EQ(
2077       "Minimum libavb version:   1.0\n"
2078       "Header Block:             256 bytes\n"
2079       "Authentication Block:     320 bytes\n"
2080       "Auxiliary Block:          640 bytes\n"
2081       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2082       "Algorithm:                SHA256_RSA2048\n"
2083       "Rollback Index:           0\n"
2084       "Flags:                    0\n"
2085       "Rollback Index Location:  0\n"
2086       "Release String:           ''\n"
2087       "Descriptors:\n"
2088       "    Kernel Cmdline descriptor:\n"
2089       "      Flags:                 0\n"
2090       "      Kernel Cmdline:        'foo bar baz'\n"
2091       "    Kernel Cmdline descriptor:\n"
2092       "      Flags:                 0\n"
2093       "      Kernel Cmdline:        'second cmdline'\n",
2094       InfoImage(vbmeta_path));
2095 
2096   // Now check the VBMeta image.
2097   std::string image_data;
2098   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
2099 
2100   const uint8_t* vbmeta_data =
2101       reinterpret_cast<const uint8_t*>(image_data.data());
2102   const size_t vbmeta_size = image_data.length();
2103   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
2104             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
2105 
2106   // Collect all descriptors.
2107   std::vector<const AvbDescriptor*> descriptors;
2108   avb_descriptor_foreach(
2109       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
2110 
2111   // We should have two descriptors - check them.
2112   EXPECT_EQ(2UL, descriptors.size());
2113   AvbKernelCmdlineDescriptor d;
2114   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
2115             avb_be64toh(descriptors[0]->tag));
2116   EXPECT_NE(
2117       0,
2118       avb_kernel_cmdline_descriptor_validate_and_byteswap(
2119           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]),
2120           &d));
2121   EXPECT_EQ("foo bar baz",
2122             std::string(reinterpret_cast<const char*>(descriptors[0]) +
2123                             sizeof(AvbKernelCmdlineDescriptor),
2124                         d.kernel_cmdline_length));
2125   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
2126             avb_be64toh(descriptors[1]->tag));
2127   EXPECT_NE(
2128       0,
2129       avb_kernel_cmdline_descriptor_validate_and_byteswap(
2130           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]),
2131           &d));
2132   EXPECT_EQ("second cmdline",
2133             std::string(reinterpret_cast<const char*>(descriptors[1]) +
2134                             sizeof(AvbKernelCmdlineDescriptor),
2135                         d.kernel_cmdline_length));
2136 }
2137 
TEST_F(AvbToolTest,CalculateKernelCmdline)2138 TEST_F(AvbToolTest, CalculateKernelCmdline) {
2139   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2140   EXPECT_COMMAND(0,
2141                  "./avbtool make_vbmeta_image "
2142                  "--output %s "
2143                  "--kernel_cmdline 'foo bar baz' "
2144                  "--kernel_cmdline 'second cmdline' "
2145                  "--algorithm SHA256_RSA2048 "
2146                  "--key test/data/testkey_rsa2048.pem "
2147                  "--internal_release_string \"\"",
2148                  vbmeta_path.value().c_str());
2149 
2150   base::FilePath out_path = testdir_.Append("out.txt");
2151   std::string out;
2152   EXPECT_COMMAND(0,
2153                  "./avbtool calculate_kernel_cmdline --image %s > %s",
2154                  vbmeta_path.value().c_str(),
2155                  out_path.value().c_str());
2156   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2157   EXPECT_EQ(out, "foo bar baz second cmdline");
2158 }
2159 
TEST_F(AvbToolTest,CalculateKernelCmdlineChainedAndWithFlags)2160 TEST_F(AvbToolTest, CalculateKernelCmdlineChainedAndWithFlags) {
2161   const size_t rootfs_size = 1028 * 1024;
2162   const size_t partition_size = 1536 * 1024;
2163 
2164   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2165 
2166   // Generate a 1028 KiB file with known content, add a hashtree, and cmdline
2167   // descriptors for setting up this hashtree. Notably this will create *two*
2168   // cmdline descriptors so we can test calculate_kernel_cmdline's
2169   // --hashtree_disabled option.
2170   std::vector<uint8_t> rootfs;
2171   rootfs.resize(rootfs_size);
2172   for (size_t n = 0; n < rootfs_size; n++)
2173     rootfs[n] = uint8_t(n);
2174   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
2175   EXPECT_EQ(rootfs_size,
2176             static_cast<const size_t>(
2177                 base::WriteFile(rootfs_path,
2178                                 reinterpret_cast<const char*>(rootfs.data()),
2179                                 rootfs.size())));
2180 
2181   EXPECT_COMMAND(
2182       0,
2183       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
2184       " --output %s",
2185       pk_path.value().c_str());
2186 
2187   EXPECT_COMMAND(0,
2188                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
2189                  "--partition_size %d --partition_name rootfs "
2190                  "--algorithm SHA256_RSA2048 "
2191                  "--key test/data/testkey_rsa2048.pem "
2192                  "--internal_release_string \"\" "
2193                  "--setup_as_rootfs_from_kernel",
2194                  rootfs_path.value().c_str(),
2195                  (int)partition_size);
2196   EXPECT_EQ(
2197       "Footer version:           1.0\n"
2198       "Image size:               1572864 bytes\n"
2199       "Original image size:      1052672 bytes\n"
2200       "VBMeta offset:            1085440\n"
2201       "VBMeta size:              1792 bytes\n"
2202       "--\n"
2203       "Minimum libavb version:   1.0\n"
2204       "Header Block:             256 bytes\n"
2205       "Authentication Block:     320 bytes\n"
2206       "Auxiliary Block:          1216 bytes\n"
2207       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2208       "Algorithm:                SHA256_RSA2048\n"
2209       "Rollback Index:           0\n"
2210       "Flags:                    0\n"
2211       "Rollback Index Location:  0\n"
2212       "Release String:           ''\n"
2213       "Descriptors:\n"
2214       "    Hashtree descriptor:\n"
2215       "      Version of dm-verity:  1\n"
2216       "      Image Size:            1052672 bytes\n"
2217       "      Tree Offset:           1052672\n"
2218       "      Tree Size:             16384 bytes\n"
2219       "      Data Block Size:       4096 bytes\n"
2220       "      Hash Block Size:       4096 bytes\n"
2221       "      FEC num roots:         2\n"
2222       "      FEC offset:            1069056\n"
2223       "      FEC size:              16384 bytes\n"
2224       "      Hash Algorithm:        sha1\n"
2225       "      Partition Name:        rootfs\n"
2226       "      Salt:                  d00df00d\n"
2227       "      Root Digest:           e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
2228       "      Flags:                 0\n"
2229       "    Kernel Cmdline descriptor:\n"
2230       "      Flags:                 1\n"
2231       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
2232       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
2233       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
2234       "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
2235       "use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 "
2236       "fec_blocks 261 fec_start 261\" root=/dev/dm-0'\n"
2237       "    Kernel Cmdline descriptor:\n"
2238       "      Flags:                 2\n"
2239       "      Kernel Cmdline:        "
2240       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
2241       InfoImage(rootfs_path));
2242 
2243   // Chain to the rootfs.img and include two cmdline descriptors.
2244   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2245   EXPECT_COMMAND(0,
2246                  "./avbtool make_vbmeta_image "
2247                  "--output %s "
2248                  "--kernel_cmdline 'foo bar baz' "
2249                  "--kernel_cmdline 'second cmdline' "
2250                  "--chain_partition rootfs:1:%s "
2251                  "--algorithm SHA256_RSA2048 "
2252                  "--key test/data/testkey_rsa2048.pem "
2253                  "--internal_release_string \"\"",
2254                  vbmeta_path.value().c_str(),
2255                  pk_path.value().c_str());
2256   EXPECT_EQ(
2257       "Minimum libavb version:   1.0\n"
2258       "Header Block:             256 bytes\n"
2259       "Authentication Block:     320 bytes\n"
2260       "Auxiliary Block:          1280 bytes\n"
2261       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2262       "Algorithm:                SHA256_RSA2048\n"
2263       "Rollback Index:           0\n"
2264       "Flags:                    0\n"
2265       "Rollback Index Location:  0\n"
2266       "Release String:           ''\n"
2267       "Descriptors:\n"
2268       "    Chain Partition descriptor:\n"
2269       "      Partition Name:          rootfs\n"
2270       "      Rollback Index Location: 1\n"
2271       "      Public key (sha1):       "
2272       "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2273       "    Kernel Cmdline descriptor:\n"
2274       "      Flags:                 0\n"
2275       "      Kernel Cmdline:        'foo bar baz'\n"
2276       "    Kernel Cmdline descriptor:\n"
2277       "      Flags:                 0\n"
2278       "      Kernel Cmdline:        'second cmdline'\n",
2279       InfoImage(vbmeta_path));
2280 
2281   base::FilePath out_path = testdir_.Append("out.txt");
2282   std::string out;
2283 
2284   // First check the kernel cmdline without --hashtree_disabled - compare with
2285   // above info_image output.
2286   EXPECT_COMMAND(0,
2287                  "./avbtool calculate_kernel_cmdline --image %s > %s",
2288                  vbmeta_path.value().c_str(),
2289                  out_path.value().c_str());
2290   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2291   EXPECT_EQ(
2292       "dm=\"1 vroot none ro 1,0 2056 verity 1 "
2293       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
2294       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
2295       "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
2296       "use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 "
2297       "fec_blocks 261 fec_start 261\" root=/dev/dm-0 foo bar baz second "
2298       "cmdline",
2299       out);
2300 
2301   // Then check the kernel cmdline with --hashtree_disabled - compare with above
2302   // info_image output.
2303   EXPECT_COMMAND(
2304       0,
2305       "./avbtool calculate_kernel_cmdline --image %s --hashtree_disabled > %s",
2306       vbmeta_path.value().c_str(),
2307       out_path.value().c_str());
2308   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2309   EXPECT_EQ(
2310       "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID) foo bar baz second cmdline",
2311       out);
2312 }
2313 
TEST_F(AvbToolTest,AddHashFooterSmallImageWithExternalVbmeta)2314 TEST_F(AvbToolTest, AddHashFooterSmallImageWithExternalVbmeta) {
2315   const size_t image_size = 37;
2316   const size_t partition_size = 20 * 4096;
2317 
2318   std::vector<uint8_t> image(image_size, 0);
2319   for (size_t n = 0; n < image_size; n++) {
2320     image[n] = uint8_t(n);
2321   }
2322 
2323   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
2324   base::FilePath image_path = testdir_.Append("kernel.bin");
2325   EXPECT_EQ(image_size,
2326             static_cast<const size_t>(
2327                 base::WriteFile(image_path,
2328                                 reinterpret_cast<const char*>(image.data()),
2329                                 image.size())));
2330   EXPECT_COMMAND(0,
2331                  "./avbtool add_hash_footer --salt d00df00d "
2332                  "--hash_algorithm sha256 --image %s "
2333                  "--partition_size %zu --partition_name kernel "
2334                  "--algorithm SHA256_RSA2048 "
2335                  "--key test/data/testkey_rsa2048.pem "
2336                  "--output_vbmeta %s "
2337                  "--do_not_append_vbmeta_image "
2338                  "--internal_release_string \"\"",
2339                  image_path.value().c_str(),
2340                  partition_size,
2341                  ext_vbmeta_path.value().c_str());
2342 
2343   // It is not this unit test's job to check the vbmeta content.
2344 
2345   int64_t file_size;
2346   ASSERT_TRUE(base::GetFileSize(image_path, &file_size));
2347   EXPECT_EQ(static_cast<size_t>(file_size), image_size);
2348 }
2349 
TEST_F(AvbToolTest,IncludeDescriptor)2350 TEST_F(AvbToolTest, IncludeDescriptor) {
2351   base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin");
2352   base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin");
2353   base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
2354 
2355   EXPECT_COMMAND(0,
2356                  "./avbtool make_vbmeta_image "
2357                  "--output %s "
2358                  "--kernel_cmdline 'something' "
2359                  "--prop name:value "
2360                  "--internal_release_string \"\"",
2361                  vbmeta1_path.value().c_str());
2362 
2363   EXPECT_COMMAND(0,
2364                  "./avbtool make_vbmeta_image "
2365                  "--output %s "
2366                  "--prop name2:value2 "
2367                  "--prop name3:value3 "
2368                  "--internal_release_string \"\"",
2369                  vbmeta2_path.value().c_str());
2370 
2371   EXPECT_COMMAND(0,
2372                  "./avbtool make_vbmeta_image "
2373                  "--output %s "
2374                  "--prop name4:value4 "
2375                  "--include_descriptors_from_image %s "
2376                  "--include_descriptors_from_image %s "
2377                  "--internal_release_string \"\"",
2378                  vbmeta3_path.value().c_str(),
2379                  vbmeta1_path.value().c_str(),
2380                  vbmeta2_path.value().c_str());
2381 
2382   ASSERT_EQ(
2383       "Minimum libavb version:   1.0\n"
2384       "Header Block:             256 bytes\n"
2385       "Authentication Block:     0 bytes\n"
2386       "Auxiliary Block:          256 bytes\n"
2387       "Algorithm:                NONE\n"
2388       "Rollback Index:           0\n"
2389       "Flags:                    0\n"
2390       "Rollback Index Location:  0\n"
2391       "Release String:           ''\n"
2392       "Descriptors:\n"
2393       "    Prop: name4 -> 'value4'\n"
2394       "    Prop: name -> 'value'\n"
2395       "    Kernel Cmdline descriptor:\n"
2396       "      Flags:                 0\n"
2397       "      Kernel Cmdline:        'something'\n"
2398       "    Prop: name2 -> 'value2'\n"
2399       "    Prop: name3 -> 'value3'\n",
2400       InfoImage(vbmeta3_path));
2401 }
2402 
TEST_F(AvbToolTest,ChainedPartition)2403 TEST_F(AvbToolTest, ChainedPartition) {
2404   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
2405 
2406   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2407 
2408   EXPECT_COMMAND(
2409       0,
2410       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
2411       " --output %s",
2412       pk_path.value().c_str());
2413 
2414   EXPECT_COMMAND(
2415       0,
2416       "./avbtool make_vbmeta_image "
2417       "--output %s "
2418       "--chain_partition system:1:%s "
2419       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2420       "--internal_release_string \"\"",
2421       vbmeta_path.value().c_str(),
2422       pk_path.value().c_str());
2423 
2424   ASSERT_EQ(
2425       "Minimum libavb version:   1.0\n"
2426       "Header Block:             256 bytes\n"
2427       "Authentication Block:     320 bytes\n"
2428       "Auxiliary Block:          1152 bytes\n"
2429       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2430       "Algorithm:                SHA256_RSA2048\n"
2431       "Rollback Index:           0\n"
2432       "Flags:                    0\n"
2433       "Rollback Index Location:  0\n"
2434       "Release String:           ''\n"
2435       "Descriptors:\n"
2436       "    Chain Partition descriptor:\n"
2437       "      Partition Name:          system\n"
2438       "      Rollback Index Location: 1\n"
2439       "      Public key (sha1):       "
2440       "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n",
2441       InfoImage(vbmeta_path));
2442 
2443   // Now check the VBMeta image.
2444   std::string image_data;
2445   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
2446 
2447   const uint8_t* vbmeta_data =
2448       reinterpret_cast<const uint8_t*>(image_data.data());
2449   const size_t vbmeta_size = image_data.length();
2450   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
2451             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
2452 
2453   // Collect all descriptors.
2454   std::vector<const AvbDescriptor*> descriptors;
2455   avb_descriptor_foreach(
2456       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
2457 
2458   // We should have one descriptor - check it.
2459   EXPECT_EQ(1UL, descriptors.size());
2460 
2461   std::string pk_data;
2462   ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data));
2463 
2464   AvbChainPartitionDescriptor d;
2465   EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
2466             avb_be64toh(descriptors[0]->tag));
2467   EXPECT_NE(
2468       0,
2469       avb_chain_partition_descriptor_validate_and_byteswap(
2470           reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]),
2471           &d));
2472   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
2473                             sizeof(AvbChainPartitionDescriptor);
2474   uint64_t o = 0;
2475   EXPECT_EQ("system",
2476             std::string(reinterpret_cast<const char*>(desc_end + o),
2477                         d.partition_name_len));
2478   o += d.partition_name_len;
2479   EXPECT_EQ(pk_data,
2480             std::string(reinterpret_cast<const char*>(descriptors[0]) +
2481                             sizeof(AvbChainPartitionDescriptor) + o,
2482                         d.public_key_len));
2483 }
2484 
TEST_F(AvbToolTest,ChainedPartitionNoLocationCollision)2485 TEST_F(AvbToolTest, ChainedPartitionNoLocationCollision) {
2486   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
2487 
2488   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2489 
2490   EXPECT_COMMAND(
2491       0,
2492       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
2493       " --output %s",
2494       pk_path.value().c_str());
2495 
2496   // Check that avbtool bails if the same Rollback Index Location is
2497   // used for multiple chained partitions.
2498   EXPECT_COMMAND(
2499       1,
2500       "./avbtool make_vbmeta_image "
2501       "--output %s "
2502       "--chain_partition system:1:%s "
2503       "--chain_partition other:1:%s "
2504       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2505       "--internal_release_string \"\"",
2506       vbmeta_path.value().c_str(),
2507       pk_path.value().c_str(),
2508       pk_path.value().c_str());
2509 }
2510 
TEST_F(AvbToolTest,AppendVBMetaImage)2511 TEST_F(AvbToolTest, AppendVBMetaImage) {
2512   size_t boot_size = 5 * 1024 * 1024;
2513   size_t boot_partition_size = 32 * 1024 * 1024;
2514   base::FilePath boot_path = GenerateImage("boot", boot_size);
2515 
2516   GenerateVBMetaImage("vbmeta.img",
2517                       "SHA256_RSA2048",
2518                       0,
2519                       base::FilePath("test/data/testkey_rsa2048.pem"),
2520                       std::string("--append_to_release_string \"\" "
2521                                   "--kernel_cmdline foo"));
2522 
2523   EXPECT_COMMAND(0,
2524                  "./avbtool append_vbmeta_image "
2525                  "--image %s "
2526                  "--partition_size %d "
2527                  "--vbmeta_image %s ",
2528                  boot_path.value().c_str(),
2529                  (int)boot_partition_size,
2530                  vbmeta_image_path_.value().c_str());
2531 
2532   std::string vbmeta_contents = InfoImage(vbmeta_image_path_);
2533   std::string boot_contents = InfoImage(boot_path);
2534 
2535   // Check that boot.img has the same vbmeta blob as from vbmeta.img -
2536   // we do this by inspecting 'avbtool info_image' output combined
2537   // with the known footer location given boot.img has 5 MiB known
2538   // content and the partition size is 32 MiB.
2539   ASSERT_EQ(
2540       "Minimum libavb version:   1.0\n"
2541       "Header Block:             256 bytes\n"
2542       "Authentication Block:     320 bytes\n"
2543       "Auxiliary Block:          576 bytes\n"
2544       "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2545       "Algorithm:                SHA256_RSA2048\n"
2546       "Rollback Index:           0\n"
2547       "Flags:                    0\n"
2548       "Rollback Index Location:  0\n"
2549       "Release String:           'avbtool 1.2.0 '\n"
2550       "Descriptors:\n"
2551       "    Kernel Cmdline descriptor:\n"
2552       "      Flags:                 0\n"
2553       "      Kernel Cmdline:        'foo'\n",
2554       vbmeta_contents);
2555   std::string known_footer =
2556       "Footer version:           1.0\n"
2557       "Image size:               33554432 bytes\n"
2558       "Original image size:      5242880 bytes\n"
2559       "VBMeta offset:            5242880\n"
2560       "VBMeta size:              1152 bytes\n"
2561       "--\n";
2562   ASSERT_EQ(known_footer + vbmeta_contents, boot_contents);
2563 
2564   // Also verify that the blobs are the same, bit for bit.
2565   base::File f =
2566       base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
2567   std::vector<uint8_t> loaded_vbmeta;
2568   loaded_vbmeta.resize(1152);
2569   EXPECT_EQ(
2570       f.Read(
2571           5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152),
2572       1152);
2573   EXPECT_EQ(vbmeta_image_, loaded_vbmeta);
2574 }
2575 
TEST_F(AvbToolTest,SigningHelperBasic)2576 TEST_F(AvbToolTest, SigningHelperBasic) {
2577   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2578   base::FilePath signing_helper_test_path =
2579       testdir_.Append("signing_helper_test");
2580   EXPECT_COMMAND(
2581       0,
2582       "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
2583       "--output %s "
2584       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2585       "--signing_helper test/avbtool_signing_helper_test.py "
2586       "--internal_release_string \"\"",
2587       signing_helper_test_path.value().c_str(),
2588       vbmeta_path.value().c_str());
2589 
2590   // Now check the value in test file.
2591   std::string value;
2592   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
2593   EXPECT_EQ("DONE", value);
2594 }
2595 
TEST_F(AvbToolTest,SigningHelperWithFilesBasic)2596 TEST_F(AvbToolTest, SigningHelperWithFilesBasic) {
2597   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2598   base::FilePath signing_helper_test_path =
2599       testdir_.Append("signing_helper_test");
2600   EXPECT_COMMAND(
2601       0,
2602       "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
2603       "--output %s "
2604       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2605       "--signing_helper_with_files "
2606       "test/avbtool_signing_helper_with_files_test.py "
2607       "--internal_release_string \"\"",
2608       signing_helper_test_path.value().c_str(),
2609       vbmeta_path.value().c_str());
2610 
2611   // Now check the value in test file.
2612   std::string value;
2613   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
2614   EXPECT_EQ("DONE", value);
2615 }
2616 
TEST_F(AvbToolTest,SigningHelperReturnError)2617 TEST_F(AvbToolTest, SigningHelperReturnError) {
2618   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2619   EXPECT_COMMAND(
2620       1,
2621       "./avbtool make_vbmeta_image "
2622       "--output %s "
2623       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2624       "--signing_helper test/avbtool_signing_helper_test.py "
2625       "--internal_release_string \"\"",
2626       vbmeta_path.value().c_str());
2627 }
2628 
TEST_F(AvbToolTest,SigningHelperWithFilesReturnError)2629 TEST_F(AvbToolTest, SigningHelperWithFilesReturnError) {
2630   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2631   EXPECT_COMMAND(
2632       1,
2633       "./avbtool make_vbmeta_image "
2634       "--output %s "
2635       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2636       "--signing_helper_with_files "
2637       "test/avbtool_signing_helper_with_files_test.py "
2638       "--internal_release_string \"\"",
2639       vbmeta_path.value().c_str());
2640 }
2641 
TEST_F(AvbToolTest,VerifyImageNoSignature)2642 TEST_F(AvbToolTest, VerifyImageNoSignature) {
2643   GenerateVBMetaImage("vbmeta.img",
2644                       "",  // NONE
2645                       0,
2646                       base::FilePath());
2647 
2648   EXPECT_COMMAND(0,
2649                  "./avbtool verify_image "
2650                  "--image %s ",
2651                  vbmeta_image_path_.value().c_str());
2652 }
2653 
TEST_F(AvbToolTest,VerifyImageValidSignature)2654 TEST_F(AvbToolTest, VerifyImageValidSignature) {
2655   GenerateVBMetaImage("vbmeta.img",
2656                       "SHA256_RSA2048",
2657                       0,
2658                       base::FilePath("test/data/testkey_rsa2048.pem"));
2659 
2660   EXPECT_COMMAND(0,
2661                  "./avbtool verify_image "
2662                  "--image %s ",
2663                  vbmeta_image_path_.value().c_str());
2664 }
2665 
TEST_F(AvbToolTest,VerifyImageCorruptedVBMeta)2666 TEST_F(AvbToolTest, VerifyImageCorruptedVBMeta) {
2667   GenerateVBMetaImage("vbmeta.img",
2668                       "SHA256_RSA2048",
2669                       0,
2670                       base::FilePath("test/data/testkey_rsa2048.pem"));
2671 
2672   // Corrupt four bytes of data in the end of the image. Since the aux
2673   // data is at the end and this data is signed, this will change the
2674   // value of the computed hash.
2675   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2676   EXPECT_EQ(AVB_IO_RESULT_OK,
2677             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2678                                                "vbmeta",
2679                                                -4,  // offset from end
2680                                                sizeof corrupt_data,
2681                                                corrupt_data));
2682 
2683   EXPECT_COMMAND(1,
2684                  "./avbtool verify_image "
2685                  "--image %s ",
2686                  vbmeta_image_path_.value().c_str());
2687 }
2688 
TEST_F(AvbToolTest,VerifyImageOtherKeyMatching)2689 TEST_F(AvbToolTest, VerifyImageOtherKeyMatching) {
2690   GenerateVBMetaImage("vbmeta.img",
2691                       "SHA256_RSA2048",
2692                       0,
2693                       base::FilePath("test/data/testkey_rsa2048.pem"));
2694 
2695   EXPECT_COMMAND(0,
2696                  "./avbtool verify_image "
2697                  "--image %s --key test/data/testkey_rsa2048.pem",
2698                  vbmeta_image_path_.value().c_str());
2699 }
2700 
TEST_F(AvbToolTest,VerifyImageOtherKeyNotMatching)2701 TEST_F(AvbToolTest, VerifyImageOtherKeyNotMatching) {
2702   GenerateVBMetaImage("vbmeta.img",
2703                       "SHA256_RSA2048",
2704                       0,
2705                       base::FilePath("test/data/testkey_rsa2048.pem"));
2706 
2707   EXPECT_COMMAND(1,
2708                  "./avbtool verify_image "
2709                  "--image %s --key test/data/testkey_rsa4096.pem",
2710                  vbmeta_image_path_.value().c_str());
2711 }
2712 
TEST_F(AvbToolTest,VerifyImageBrokenSignature)2713 TEST_F(AvbToolTest, VerifyImageBrokenSignature) {
2714   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2715   base::FilePath signing_helper_test_path =
2716       testdir_.Append("signing_helper_test");
2717 
2718   // Intentionally make the signer generate a wrong signature.
2719   EXPECT_COMMAND(
2720       0,
2721       "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool make_vbmeta_image "
2722       "--output %s "
2723       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2724       "--signing_helper test/avbtool_signing_helper_test.py "
2725       "--internal_release_string \"\"",
2726       vbmeta_path.value().c_str());
2727 
2728   EXPECT_COMMAND(1,
2729                  "./avbtool verify_image "
2730                  "--image %s ",
2731                  vbmeta_path.value().c_str());
2732 }
2733 
2734 // Helper to generate boot.img, unsparse system.img, and vbmeta.img.
GenerateImageWithHashAndHashtreeSetup()2735 void AvbToolTest::GenerateImageWithHashAndHashtreeSetup() {
2736   const size_t boot_partition_size = 16 * 1024 * 1024;
2737   const size_t boot_image_size = 5 * 1024 * 1024;
2738   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
2739   EXPECT_COMMAND(0,
2740                  "./avbtool add_hash_footer"
2741                  " --image %s"
2742                  " --rollback_index 0"
2743                  " --partition_name boot"
2744                  " --partition_size %zd"
2745                  " --salt deadbeef"
2746                  " --internal_release_string \"\"",
2747                  boot_path.value().c_str(),
2748                  boot_partition_size);
2749 
2750   const size_t system_partition_size = 10 * 1024 * 1024;
2751   const size_t system_image_size = 8 * 1024 * 1024;
2752   base::FilePath system_path = GenerateImage("system.img", system_image_size);
2753   EXPECT_COMMAND(0,
2754                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
2755                  "--partition_size %zd --partition_name system "
2756                  "--internal_release_string \"\" ",
2757                  system_path.value().c_str(),
2758                  system_partition_size);
2759 
2760   GenerateVBMetaImage("vbmeta.img",
2761                       "SHA256_RSA2048",
2762                       0,
2763                       base::FilePath("test/data/testkey_rsa2048.pem"),
2764                       base::StringPrintf("--include_descriptors_from_image %s "
2765                                          "--include_descriptors_from_image %s",
2766                                          boot_path.value().c_str(),
2767                                          system_path.value().c_str()));
2768 }
2769 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtree)2770 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) {
2771   GenerateImageWithHashAndHashtreeSetup();
2772 
2773   // Do two checks - one for system.img not sparse, and one where it
2774   // is sparse.
2775   for (int n = 0; n < 2; n++) {
2776     EXPECT_COMMAND(0,
2777                    "./avbtool verify_image "
2778                    "--image %s ",
2779                    vbmeta_image_path_.value().c_str());
2780     if (n == 0) {
2781       EXPECT_COMMAND(0,
2782                      "img2simg %s %s.sparse",
2783                      testdir_.Append("system.img").value().c_str(),
2784                      testdir_.Append("system.img").value().c_str());
2785       EXPECT_COMMAND(0,
2786                      "mv %s.sparse %s",
2787                      testdir_.Append("system.img").value().c_str(),
2788                      testdir_.Append("system.img").value().c_str());
2789     }
2790   }
2791 }
2792 
TEST_F(AvbToolTest,VerifyImageWithHashAndZeroedHashtree)2793 TEST_F(AvbToolTest, VerifyImageWithHashAndZeroedHashtree) {
2794   const size_t system_partition_size = 10 * 1024 * 1024;
2795   const size_t system_image_size = 8 * 1024 * 1024;
2796   base::FilePath system_path = GenerateImage("system.img", system_image_size);
2797   EXPECT_COMMAND(0,
2798                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
2799                  "--partition_size %zd --partition_name system "
2800                  "--internal_release_string \"\" ",
2801                  system_path.value().c_str(),
2802                  system_partition_size);
2803 
2804   GenerateVBMetaImage("vbmeta.img",
2805                       "SHA256_RSA2048",
2806                       0,
2807                       base::FilePath("test/data/testkey_rsa2048.pem"),
2808                       base::StringPrintf("--include_descriptors_from_image %s ",
2809                                          system_path.value().c_str()));
2810 
2811   EXPECT_COMMAND(0,
2812                  "./avbtool verify_image --image %s --accept_zeroed_hashtree",
2813                  vbmeta_image_path_.value().c_str());
2814 
2815   EXPECT_COMMAND(
2816       0, "./avbtool zero_hashtree --image %s", system_path.value().c_str());
2817 
2818   EXPECT_COMMAND(1,
2819                  "./avbtool verify_image --image %s",
2820                  vbmeta_image_path_.value().c_str());
2821 
2822   EXPECT_COMMAND(0,
2823                  "./avbtool verify_image --image %s --accept_zeroed_hashtree",
2824                  vbmeta_image_path_.value().c_str());
2825 }
2826 
TEST_F(AvbToolTest,VerifyImageWithNoHashtree)2827 TEST_F(AvbToolTest, VerifyImageWithNoHashtree) {
2828   const size_t system_partition_size = 10 * 1024 * 1024;
2829   const size_t system_image_size = 8 * 1024 * 1024;
2830   base::FilePath system_path = GenerateImage("system.img", system_image_size);
2831   EXPECT_COMMAND(0,
2832                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
2833                  "--partition_size %zd --partition_name system "
2834                  "--no_hashtree "
2835                  "--internal_release_string \"\" ",
2836                  system_path.value().c_str(),
2837                  system_partition_size);
2838 
2839   GenerateVBMetaImage("vbmeta.img",
2840                       "SHA256_RSA2048",
2841                       0,
2842                       base::FilePath("test/data/testkey_rsa2048.pem"),
2843                       base::StringPrintf("--include_descriptors_from_image %s ",
2844                                          system_path.value().c_str()));
2845 
2846   EXPECT_COMMAND(1,
2847                  "./avbtool verify_image --image %s",
2848                  vbmeta_image_path_.value().c_str());
2849 
2850   EXPECT_COMMAND(0,
2851                  "./avbtool verify_image --image %s --accept_zeroed_hashtree",
2852                  vbmeta_image_path_.value().c_str());
2853 }
2854 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHash)2855 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) {
2856   GenerateImageWithHashAndHashtreeSetup();
2857 
2858   // Corrupt four bytes of data in the middle of boot.img.
2859   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2860   EXPECT_EQ(AVB_IO_RESULT_OK,
2861             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2862                                                "boot",
2863                                                105 * 1024,  // offset from start
2864                                                sizeof corrupt_data,
2865                                                corrupt_data));
2866 
2867   EXPECT_COMMAND(1,
2868                  "./avbtool verify_image "
2869                  "--image %s ",
2870                  vbmeta_image_path_.value().c_str());
2871 }
2872 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHashtree)2873 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHashtree) {
2874   GenerateImageWithHashAndHashtreeSetup();
2875 
2876   // Corrupt four bytes of data in the middle of system.img.
2877   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2878   EXPECT_EQ(AVB_IO_RESULT_OK,
2879             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2880                                                "system",
2881                                                123 * 1024,  // offset from start
2882                                                sizeof corrupt_data,
2883                                                corrupt_data));
2884 
2885   // Do two checks - one for system.img not sparse, and one where it
2886   // is sparse.
2887   for (int n = 0; n < 2; n++) {
2888     EXPECT_COMMAND(1,
2889                    "./avbtool verify_image "
2890                    "--image %s ",
2891                    vbmeta_image_path_.value().c_str());
2892     if (n == 0) {
2893       EXPECT_COMMAND(0,
2894                      "img2simg %s %s.sparse",
2895                      testdir_.Append("system.img").value().c_str(),
2896                      testdir_.Append("system.img").value().c_str());
2897       EXPECT_COMMAND(0,
2898                      "mv %s.sparse %s",
2899                      testdir_.Append("system.img").value().c_str(),
2900                      testdir_.Append("system.img").value().c_str());
2901     }
2902   }
2903 }
2904 
TEST_F(AvbToolTest,VerifyImageChainPartition)2905 TEST_F(AvbToolTest, VerifyImageChainPartition) {
2906   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
2907   EXPECT_COMMAND(
2908       0,
2909       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
2910       " --output %s",
2911       pk4096_path.value().c_str());
2912 
2913   base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey");
2914   EXPECT_COMMAND(
2915       0,
2916       "./avbtool extract_public_key --key test/data/testkey_rsa8192.pem"
2917       " --output %s",
2918       pk8192_path.value().c_str());
2919 
2920   GenerateVBMetaImage("vbmeta.img",
2921                       "SHA256_RSA2048",
2922                       0,
2923                       base::FilePath("test/data/testkey_rsa2048.pem"),
2924                       base::StringPrintf("--chain_partition system:1:%s ",
2925                                          pk4096_path.value().c_str()));
2926 
2927   // Should not fail (name, rollback_index, contents all correct).
2928   EXPECT_COMMAND(0,
2929                  "./avbtool verify_image "
2930                  "--image %s "
2931                  "--expected_chain_partition system:1:%s",
2932                  vbmeta_image_path_.value().c_str(),
2933                  pk4096_path.value().c_str());
2934 
2935   // Should fail because we didn't use --expected_chain_partition.
2936   EXPECT_COMMAND(1,
2937                  "./avbtool verify_image "
2938                  "--image %s ",
2939                  vbmeta_image_path_.value().c_str());
2940 
2941   // Should fail because partition name is wrong.
2942   EXPECT_COMMAND(1,
2943                  "./avbtool verify_image "
2944                  "--image %s "
2945                  "--expected_chain_partition xyz:1:%s",
2946                  vbmeta_image_path_.value().c_str(),
2947                  pk4096_path.value().c_str());
2948 
2949   // Should fail because rollback index location is wrong.
2950   EXPECT_COMMAND(1,
2951                  "./avbtool verify_image "
2952                  "--image %s "
2953                  "--expected_chain_partition system:2:%s",
2954                  vbmeta_image_path_.value().c_str(),
2955                  pk4096_path.value().c_str());
2956 
2957   // Should fail because public key blob is wrong.
2958   EXPECT_COMMAND(1,
2959                  "./avbtool verify_image "
2960                  "--image %s "
2961                  "--expected_chain_partition system:1:%s",
2962                  vbmeta_image_path_.value().c_str(),
2963                  pk8192_path.value().c_str());
2964 }
2965 
TEST_F(AvbToolTest,VerifyImageChainPartitionWithFollow)2966 TEST_F(AvbToolTest, VerifyImageChainPartitionWithFollow) {
2967   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
2968   EXPECT_COMMAND(
2969       0,
2970       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
2971       " --output %s",
2972       pk4096_path.value().c_str());
2973 
2974   GenerateVBMetaImage("vbmeta.img",
2975                       "SHA256_RSA2048",
2976                       0,
2977                       base::FilePath("test/data/testkey_rsa2048.pem"),
2978                       base::StringPrintf("--chain_partition system:1:%s ",
2979                                          pk4096_path.value().c_str()));
2980 
2981   const size_t system_partition_size = 10 * 1024 * 1024;
2982   const size_t system_image_size = 8 * 1024 * 1024;
2983   base::FilePath system_path = GenerateImage("system.img", system_image_size);
2984   EXPECT_COMMAND(0,
2985                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
2986                  "--partition_size %zd --partition_name system "
2987                  "--algorithm SHA256_RSA4096 "
2988                  "--key test/data/testkey_rsa4096.pem "
2989                  "--internal_release_string \"\" ",
2990                  system_path.value().c_str(),
2991                  system_partition_size);
2992 
2993   // Even without --expected_chain_partition this shouldn't fail because we use
2994   // --follow_chain_partitions and system.img exists... to avoid unstable paths
2995   // (e.g. /tmp/libavb.12345) in the output we need to run this from the test
2996   // directory itself. It's a little ugly but it works.
2997   char cwdbuf[PATH_MAX];
2998   ASSERT_NE(nullptr, getcwd(cwdbuf, sizeof cwdbuf));
2999   EXPECT_COMMAND(0,
3000                  "cd %s && (%s/avbtool verify_image "
3001                  "--image vbmeta.img --follow_chain_partitions > out.txt)",
3002                  testdir_.value().c_str(),
3003                  cwdbuf);
3004   base::FilePath out_path = testdir_.Append("out.txt");
3005   std::string out;
3006   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3007   EXPECT_EQ(
3008       "Verifying image vbmeta.img using embedded public key\n"
3009       "vbmeta: Successfully verified SHA256_RSA2048 vbmeta struct in "
3010       "vbmeta.img\n"
3011       "system: Chained but ROLLBACK_SLOT (which is 1) and KEY (which has sha1 "
3012       "2597c218aae470a130f61162feaae70afd97f011) not specified\n"
3013       "--\n"
3014       "Verifying image system.img using embedded public key\n"
3015       "vbmeta: Successfully verified footer and SHA256_RSA4096 vbmeta struct "
3016       "in system.img\n"
3017       "system: Successfully verified sha1 hashtree of system.img for image of "
3018       "8388608 bytes\n",
3019       out);
3020 
3021   // Make sure we also follow partitions *even* when specifying
3022   // --expect_chain_partition. The output is slightly different from above.
3023   EXPECT_COMMAND(0,
3024                  "cd %s && (%s/avbtool verify_image "
3025                  "--image vbmeta.img --expected_chain_partition system:1:%s "
3026                  "--follow_chain_partitions > out.txt)",
3027                  testdir_.value().c_str(),
3028                  cwdbuf,
3029                  pk4096_path.value().c_str());
3030   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3031   EXPECT_EQ(
3032       "Verifying image vbmeta.img using embedded public key\n"
3033       "vbmeta: Successfully verified SHA256_RSA2048 vbmeta struct in "
3034       "vbmeta.img\n"
3035       "system: Successfully verified chain partition descriptor matches "
3036       "expected data\n"
3037       "--\n"
3038       "Verifying image system.img using embedded public key\n"
3039       "vbmeta: Successfully verified footer and SHA256_RSA4096 vbmeta struct "
3040       "in system.img\n"
3041       "system: Successfully verified sha1 hashtree of system.img for image of "
3042       "8388608 bytes\n",
3043       out);
3044 }
3045 
TEST_F(AvbToolTest,VerifyImageChainPartitionOtherVBMeta)3046 TEST_F(AvbToolTest, VerifyImageChainPartitionOtherVBMeta) {
3047   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
3048   EXPECT_COMMAND(
3049       0,
3050       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
3051       " --output %s",
3052       pk4096_path.value().c_str());
3053 
3054   const size_t system_partition_size = 10 * 1024 * 1024;
3055   const size_t system_image_size = 8 * 1024 * 1024;
3056   base::FilePath system_path = GenerateImage("system.img", system_image_size);
3057   EXPECT_COMMAND(0,
3058                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
3059                  "--partition_size %zd --partition_name system "
3060                  "--internal_release_string \"\" "
3061                  "--algorithm SHA256_RSA4096 "
3062                  "--key test/data/testkey_rsa4096.pem ",
3063                  system_path.value().c_str(),
3064                  system_partition_size,
3065                  pk4096_path.value().c_str());
3066 
3067   GenerateVBMetaImage(
3068       "vbmeta.img",
3069       "SHA256_RSA2048",
3070       0,
3071       base::FilePath("test/data/testkey_rsa2048.pem"),
3072       base::StringPrintf("--chain_partition vbmeta_google:1:%s ",
3073                          pk4096_path.value().c_str()));
3074 
3075   // Should not fail (name, rollback_index, contents all correct).
3076   EXPECT_COMMAND(0,
3077                  "./avbtool verify_image "
3078                  "--image %s "
3079                  "--expected_chain_partition vbmeta_google:1:%s",
3080                  vbmeta_image_path_.value().c_str(),
3081                  pk4096_path.value().c_str());
3082 
3083   // Should not fail (looks in system.img image).
3084   EXPECT_COMMAND(0,
3085                  "./avbtool verify_image "
3086                  "--image %s ",
3087                  system_path.value().c_str());
3088 
3089   // Extract the vbmeta blob from the footer in system.img, put it into
3090   // vbmeta_google.img, and erase the footer from system.img (but keep
3091   // the hash tree in system.img)
3092   base::FilePath vbmeta_google_path = GenerateImage("vbmeta_google.img", 0);
3093   EXPECT_COMMAND(0,
3094                  "./avbtool extract_vbmeta_image"
3095                  " --image %s"
3096                  " --output %s",
3097                  system_path.value().c_str(),
3098                  vbmeta_google_path.value().c_str());
3099   EXPECT_COMMAND(0,
3100                  "./avbtool erase_footer"
3101                  " --image %s --keep_hashtree",
3102                  system_path.value().c_str());
3103 
3104   // Should not fail - looks in system.img's detached vbmeta (vbmeta_google.img)
3105   // for vbmeta blob and system.img for the actual hashtree.
3106   EXPECT_COMMAND(0,
3107                  "./avbtool verify_image "
3108                  "--image %s ",
3109                  vbmeta_google_path.value().c_str());
3110 }
3111 
TEST_F(AvbToolTest,PrintPartitionDigests)3112 TEST_F(AvbToolTest, PrintPartitionDigests) {
3113   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
3114   EXPECT_COMMAND(
3115       0,
3116       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
3117       " --output %s",
3118       pk4096_path.value().c_str());
3119 
3120   const size_t boot_partition_size = 16 * 1024 * 1024;
3121   const size_t boot_image_size = 5 * 1024 * 1024;
3122   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
3123   EXPECT_COMMAND(0,
3124                  "./avbtool add_hash_footer"
3125                  " --image %s"
3126                  " --rollback_index 0"
3127                  " --partition_name boot"
3128                  " --partition_size %zd"
3129                  " --salt deadbeef"
3130                  " --internal_release_string \"\"",
3131                  boot_path.value().c_str(),
3132                  boot_partition_size);
3133 
3134   GenerateVBMetaImage("vbmeta.img",
3135                       "SHA256_RSA2048",
3136                       0,
3137                       base::FilePath("test/data/testkey_rsa2048.pem"),
3138                       base::StringPrintf("--chain_partition system:1:%s "
3139                                          "--include_descriptors_from_image %s",
3140                                          pk4096_path.value().c_str(),
3141                                          boot_path.value().c_str()));
3142 
3143   const size_t system_partition_size = 10 * 1024 * 1024;
3144   const size_t system_image_size = 8 * 1024 * 1024;
3145   base::FilePath system_path = GenerateImage("system.img", system_image_size);
3146   EXPECT_COMMAND(0,
3147                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
3148                  "--partition_size %zd --partition_name system "
3149                  "--algorithm SHA256_RSA4096 "
3150                  "--key test/data/testkey_rsa4096.pem "
3151                  "--internal_release_string \"\" ",
3152                  system_path.value().c_str(),
3153                  system_partition_size);
3154 
3155   base::FilePath out_path = testdir_.Append("out.txt");
3156   std::string out;
3157 
3158   // Normal output
3159   EXPECT_COMMAND(0,
3160                  "./avbtool print_partition_digests --image %s --output %s",
3161                  vbmeta_image_path_.value().c_str(),
3162                  out_path.value().c_str());
3163   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3164   EXPECT_EQ(
3165       "system: d52d93c988d336a79abe1c05240ae9a79a9b7d61\n"
3166       "boot: "
3167       "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n",
3168       out);
3169 
3170   // JSON output
3171   EXPECT_COMMAND(
3172       0,
3173       "./avbtool print_partition_digests --image %s --json --output %s",
3174       vbmeta_image_path_.value().c_str(),
3175       out_path.value().c_str());
3176   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3177   // The trailing whitespace comes from python. If they fix that bug we need
3178   // to update this test...
3179   EXPECT_EQ(
3180       "{\n"
3181       "  \"partitions\": [\n"
3182       "    {\n"
3183       "      \"name\": \"system\",\n"
3184       "      \"digest\": \"d52d93c988d336a79abe1c05240ae9a79a9b7d61\"\n"
3185       "    },\n"
3186       "    {\n"
3187       "      \"name\": \"boot\",\n"
3188       "      \"digest\": "
3189       "\"184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\"\n"
3190       "    }\n"
3191       "  ]\n"
3192       "}",
3193       out);
3194 }
3195 
3196 class AvbToolTest_PrintRequiredVersion : public AvbToolTest {
3197  protected:
3198   const char* kOutputFile = "versions.txt";
3199 
PrintWithAddHashFooter(int target_required_minor_version)3200   void PrintWithAddHashFooter(int target_required_minor_version) {
3201     std::string extra_args;
3202     if (target_required_minor_version == 1) {
3203       // The --do_not_use_ab option will require 1.1.
3204       extra_args = "--do_not_use_ab";
3205     } else if (target_required_minor_version == 2) {
3206       extra_args = "--rollback_index_location 2";
3207     }
3208 
3209     const size_t boot_partition_size = 16 * 1024 * 1024;
3210     base::FilePath output_path = testdir_.Append(kOutputFile);
3211     EXPECT_COMMAND(0,
3212                    "./avbtool add_hash_footer"
3213                    " --rollback_index 0"
3214                    " --partition_name boot"
3215                    " --partition_size %zd"
3216                    " --salt deadbeef"
3217                    " --internal_release_string \"\""
3218                    " %s"
3219                    " --print_required_libavb_version > %s",
3220                    boot_partition_size,
3221                    extra_args.c_str(),
3222                    output_path.value().c_str());
3223     CheckVersion(target_required_minor_version);
3224   }
3225 
PrintWithAddHashtreeFooter(int target_required_minor_version)3226   void PrintWithAddHashtreeFooter(int target_required_minor_version) {
3227     std::string extra_args;
3228     if (target_required_minor_version == 1) {
3229       // The --do_not_use_ab option will require 1.1.
3230       extra_args = "--do_not_use_ab --check_at_most_once";
3231     } else if (target_required_minor_version == 2) {
3232       extra_args = "--rollback_index_location 2";
3233     }
3234     const size_t system_partition_size = 10 * 1024 * 1024;
3235     base::FilePath output_path = testdir_.Append(kOutputFile);
3236     EXPECT_COMMAND(0,
3237                    "./avbtool add_hashtree_footer --salt d00df00d "
3238                    "--partition_size %zd --partition_name system "
3239                    "--internal_release_string \"\""
3240                    " %s"
3241                    " --print_required_libavb_version > %s",
3242                    system_partition_size,
3243                    extra_args.c_str(),
3244                    output_path.value().c_str());
3245     CheckVersion(target_required_minor_version);
3246   }
3247 
PrintWithMakeVbmetaImage(int target_required_minor_version)3248   void PrintWithMakeVbmetaImage(int target_required_minor_version) {
3249     std::string extra_args;
3250     if (target_required_minor_version == 1) {
3251       // An included descriptor that requires 1.1 will require 1.1 for vbmeta.
3252       const size_t boot_partition_size = 16 * 1024 * 1024;
3253       base::FilePath image_path = GenerateImage("test_print_version", 1024);
3254       EXPECT_COMMAND(0,
3255                      "./avbtool add_hash_footer --salt d00df00d "
3256                      "--hash_algorithm sha256 --image %s "
3257                      "--partition_size %d --partition_name foobar "
3258                      "--algorithm SHA256_RSA2048 "
3259                      "--key test/data/testkey_rsa2048.pem "
3260                      "--internal_release_string \"\" "
3261                      "--do_not_use_ab",
3262                      image_path.value().c_str(),
3263                      (int)boot_partition_size);
3264       extra_args = base::StringPrintf("--include_descriptors_from_image %s",
3265                                       image_path.value().c_str());
3266     } else if (target_required_minor_version == 2) {
3267       extra_args = "--rollback_index_location 2";
3268     }
3269 
3270     base::FilePath output_path = testdir_.Append(kOutputFile);
3271     EXPECT_COMMAND(0,
3272                    "./avbtool make_vbmeta_image "
3273                    "--algorithm SHA256_RSA2048 "
3274                    "--key test/data/testkey_rsa2048.pem "
3275                    "--internal_release_string \"\""
3276                    " %s"
3277                    " --print_required_libavb_version > %s",
3278                    extra_args.c_str(),
3279                    output_path.value().c_str());
3280     CheckVersion(target_required_minor_version);
3281   }
3282 
CheckVersion(int expected_required_minor_version)3283   void CheckVersion(int expected_required_minor_version) {
3284     base::FilePath output_path = testdir_.Append(kOutputFile);
3285     std::string output;
3286     ASSERT_TRUE(base::ReadFileToString(output_path, &output));
3287     EXPECT_EQ(output,
3288               base::StringPrintf("1.%d\n", expected_required_minor_version));
3289   }
3290 };
3291 
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_0)3292 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_0) {
3293   PrintWithAddHashFooter(0);
3294 }
3295 
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_1)3296 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_1) {
3297   PrintWithAddHashFooter(1);
3298 }
3299 
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_2)3300 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_2) {
3301   PrintWithAddHashFooter(2);
3302 }
3303 
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_0)3304 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_0) {
3305   PrintWithAddHashtreeFooter(0);
3306 }
3307 
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_1)3308 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_1) {
3309   PrintWithAddHashtreeFooter(1);
3310 }
3311 
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_2)3312 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_2) {
3313   PrintWithAddHashtreeFooter(2);
3314 }
3315 
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_0)3316 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_0) {
3317   PrintWithMakeVbmetaImage(0);
3318 }
3319 
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_1)3320 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_1) {
3321   PrintWithMakeVbmetaImage(1);
3322 }
3323 
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_2)3324 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_2) {
3325   PrintWithMakeVbmetaImage(2);
3326 }
3327 
TEST_F(AvbToolTest,MakeAtxPikCertificate)3328 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
3329   base::FilePath subject_path = testdir_.Append("tmp_subject");
3330   ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
3331   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3332   EXPECT_COMMAND(
3333       0,
3334       "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
3335       pubkey_path.value().c_str());
3336 
3337   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3338   EXPECT_COMMAND(0,
3339                  "./avbtool make_atx_certificate"
3340                  " --subject %s"
3341                  " --subject_key %s"
3342                  " --subject_key_version 42"
3343                  " --subject_is_intermediate_authority"
3344                  " --authority_key test/data/testkey_atx_prk.pem"
3345                  " --output %s",
3346                  subject_path.value().c_str(),
3347                  pubkey_path.value().c_str(),
3348                  output_path.value().c_str());
3349 
3350   EXPECT_COMMAND(0,
3351                  "diff test/data/atx_pik_certificate.bin %s",
3352                  output_path.value().c_str());
3353 }
3354 
TEST_F(AvbToolTest,MakeAtxPskCertificate)3355 TEST_F(AvbToolTest, MakeAtxPskCertificate) {
3356   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3357   EXPECT_COMMAND(
3358       0,
3359       "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
3360       pubkey_path.value().c_str());
3361 
3362   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3363   EXPECT_COMMAND(0,
3364                  "./avbtool make_atx_certificate"
3365                  " --subject test/data/atx_product_id.bin"
3366                  " --subject_key %s"
3367                  " --subject_key_version 42"
3368                  " --authority_key test/data/testkey_atx_pik.pem"
3369                  " --output %s",
3370                  pubkey_path.value().c_str(),
3371                  output_path.value().c_str());
3372 
3373   EXPECT_COMMAND(0,
3374                  "diff test/data/atx_psk_certificate.bin %s",
3375                  output_path.value().c_str());
3376 }
3377 
TEST_F(AvbToolTest,MakeAtxPukCertificate)3378 TEST_F(AvbToolTest, MakeAtxPukCertificate) {
3379   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3380   EXPECT_COMMAND(
3381       0,
3382       "openssl pkey -pubout -in test/data/testkey_atx_puk.pem -out %s",
3383       pubkey_path.value().c_str());
3384 
3385   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3386   EXPECT_COMMAND(0,
3387                  "./avbtool make_atx_certificate"
3388                  " --subject test/data/atx_product_id.bin"
3389                  " --subject_key %s"
3390                  " --subject_key_version 42"
3391                  " --usage com.google.android.things.vboot.unlock"
3392                  " --authority_key test/data/testkey_atx_pik.pem"
3393                  " --output %s",
3394                  pubkey_path.value().c_str(),
3395                  output_path.value().c_str());
3396 
3397   EXPECT_COMMAND(0,
3398                  "diff test/data/atx_puk_certificate.bin %s",
3399                  output_path.value().c_str());
3400 }
3401 
TEST_F(AvbToolTest,MakeAtxPermanentAttributes)3402 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) {
3403   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3404   EXPECT_COMMAND(
3405       0,
3406       "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
3407       pubkey_path.value().c_str());
3408 
3409   base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
3410   EXPECT_COMMAND(0,
3411                  "./avbtool make_atx_permanent_attributes"
3412                  " --root_authority_key %s"
3413                  " --product_id test/data/atx_product_id.bin"
3414                  " --output %s",
3415                  pubkey_path.value().c_str(),
3416                  output_path.value().c_str());
3417 
3418   EXPECT_COMMAND(0,
3419                  "diff test/data/atx_permanent_attributes.bin %s",
3420                  output_path.value().c_str());
3421 }
3422 
TEST_F(AvbToolTest,MakeAtxMetadata)3423 TEST_F(AvbToolTest, MakeAtxMetadata) {
3424   base::FilePath output_path = testdir_.Append("tmp_metadata.bin");
3425 
3426   EXPECT_COMMAND(
3427       0,
3428       "./avbtool make_atx_metadata"
3429       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
3430       " --product_key_certificate test/data/atx_psk_certificate.bin"
3431       " --output %s",
3432       output_path.value().c_str());
3433 
3434   EXPECT_COMMAND(
3435       0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str());
3436 }
3437 
TEST_F(AvbToolTest,MakeAtxUnlockCredential)3438 TEST_F(AvbToolTest, MakeAtxUnlockCredential) {
3439   base::FilePath output_path = testdir_.Append("tmp_credential.bin");
3440 
3441   EXPECT_COMMAND(
3442       0,
3443       "./avbtool make_atx_unlock_credential"
3444       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
3445       " --unlock_key_certificate test/data/atx_puk_certificate.bin"
3446       " --challenge test/data/atx_unlock_challenge.bin"
3447       " --unlock_key test/data/testkey_atx_puk.pem"
3448       " --output %s",
3449       output_path.value().c_str());
3450 
3451   EXPECT_COMMAND(0,
3452                  "diff test/data/atx_unlock_credential.bin %s",
3453                  output_path.value().c_str());
3454 }
3455 
3456 }  // namespace avb
3457