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