• 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 AddHashtreeFooterTest(bool sparse_image);
57   void AddHashtreeFooterFECTest(bool sparse_image);
58 
59   void GenerateImageWithHashAndHashtreeSetup();
60 
61   FakeAvbOps ops_;
62 };
63 
64 // This test ensure that the version is increased in both
65 // avb_boot_image.h and the avb tool.
TEST_F(AvbToolTest,AvbVersionInSync)66 TEST_F(AvbToolTest, AvbVersionInSync) {
67   base::FilePath path = testdir_.Append("version.txt");
68   EXPECT_COMMAND(0, "./avbtool version > %s", path.value().c_str());
69   std::string printed_version;
70   ASSERT_TRUE(base::ReadFileToString(path, &printed_version));
71   base::TrimWhitespaceASCII(printed_version, base::TRIM_ALL, &printed_version);
72   // See comments in libavb/avb_version.c and avbtool's get_release_string()
73   // about being in sync.
74   EXPECT_EQ(printed_version,
75             std::string("avbtool ") + std::string(avb_version_string()));
76 }
77 
TEST_F(AvbToolTest,DefaultReleaseString)78 TEST_F(AvbToolTest, DefaultReleaseString) {
79   GenerateVBMetaImage("vbmeta.img",
80                       "SHA256_RSA2048",
81                       0,
82                       base::FilePath("test/data/testkey_rsa2048.pem"));
83 
84   // Default release string is "avbtool " + avb_version_string().
85   AvbVBMetaImageHeader h;
86   avb_vbmeta_image_header_to_host_byte_order(
87       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
88   EXPECT_EQ(std::string("avbtool ") + std::string(avb_version_string()),
89             std::string((const char*)h.release_string));
90 }
91 
TEST_F(AvbToolTest,ReleaseStringAppend)92 TEST_F(AvbToolTest, ReleaseStringAppend) {
93   GenerateVBMetaImage("vbmeta.img",
94                       "SHA256_RSA2048",
95                       0,
96                       base::FilePath("test/data/testkey_rsa2048.pem"),
97                       "--append_to_release_string \"Woot XYZ\"");
98 
99   // Note that avbtool inserts the space by itself.
100   std::string expected_str =
101       std::string("avbtool ") + std::string(avb_version_string()) + " Woot XYZ";
102 
103   AvbVBMetaImageHeader h;
104   avb_vbmeta_image_header_to_host_byte_order(
105       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
106   EXPECT_EQ(expected_str, std::string((const char*)h.release_string));
107 }
108 
TEST_F(AvbToolTest,ReleaseStringAppendTruncated)109 TEST_F(AvbToolTest, ReleaseStringAppendTruncated) {
110   // Append enough text that truncation is sure to happen.
111   std::string append_str = "0123456789abcdef0123456789abcdef0123456789abcdef";
112   std::string expected_str = std::string("avbtool ") +
113                              std::string(avb_version_string()) + " " +
114                              append_str;
115   EXPECT_GT(expected_str.size(), (size_t)(AVB_RELEASE_STRING_SIZE - 1));
116   expected_str.resize(AVB_RELEASE_STRING_SIZE - 1);
117 
118   GenerateVBMetaImage(
119       "vbmeta.img",
120       "SHA256_RSA2048",
121       0,
122       base::FilePath("test/data/testkey_rsa2048.pem"),
123       std::string("--append_to_release_string \"") + append_str + "\"");
124 
125   // This checks that it ends with a NUL byte.
126   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
127             avb_vbmeta_image_verify(
128                 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr));
129 
130   // For good measure we also check here.
131   AvbVBMetaImageHeader h;
132   avb_vbmeta_image_header_to_host_byte_order(
133       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
134   EXPECT_EQ(expected_str, std::string((const char*)h.release_string));
135 }
136 
TEST_F(AvbToolTest,ExtractPublicKey)137 TEST_F(AvbToolTest, ExtractPublicKey) {
138   GenerateVBMetaImage("vbmeta.img",
139                       "SHA256_RSA2048",
140                       0,
141                       base::FilePath("test/data/testkey_rsa2048.pem"),
142                       "--internal_release_string \"\"");
143 
144   std::string key_data =
145       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem"));
146 
147   AvbVBMetaImageHeader h;
148   avb_vbmeta_image_header_to_host_byte_order(
149       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
150   uint8_t* d = reinterpret_cast<uint8_t*>(vbmeta_image_.data());
151   size_t auxiliary_data_block_offset =
152       sizeof(AvbVBMetaImageHeader) + h.authentication_data_block_size;
153   EXPECT_GT(h.auxiliary_data_block_size, key_data.size());
154   EXPECT_EQ(0,
155             memcmp(key_data.data(),
156                    d + auxiliary_data_block_offset + h.public_key_offset,
157                    key_data.size()));
158 }
159 
TEST_F(AvbToolTest,CheckDescriptors)160 TEST_F(AvbToolTest, CheckDescriptors) {
161   GenerateVBMetaImage("vbmeta.img",
162                       "SHA256_RSA2048",
163                       0,
164                       base::FilePath("test/data/testkey_rsa2048.pem"),
165                       "--prop foo:brillo "
166                       "--prop bar:chromeos "
167                       "--prop prisoner:24601 "
168                       "--prop hexnumber:0xcafe "
169                       "--prop hexnumber_capital:0xCAFE "
170                       "--prop large_hexnumber:0xfedcba9876543210 "
171                       "--prop larger_than_uint64:0xfedcba98765432101 "
172                       "--prop almost_a_number:423x "
173                       "--prop_from_file blob:test/data/small_blob.bin "
174                       "--internal_release_string \"\"");
175 
176   AvbVBMetaImageHeader h;
177   avb_vbmeta_image_header_to_host_byte_order(
178       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
179 
180   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
181             avb_vbmeta_image_verify(
182                 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr));
183 
184   const char* s;
185   size_t len;
186   uint64_t val;
187 
188   // Basic.
189   s = avb_property_lookup(
190       vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &len);
191   EXPECT_EQ(0, strcmp(s, "brillo"));
192   EXPECT_EQ(6U, len);
193   s = avb_property_lookup(
194       vbmeta_image_.data(), vbmeta_image_.size(), "bar", 0, &len);
195   EXPECT_EQ(0, strcmp(s, "chromeos"));
196   EXPECT_EQ(8U, len);
197   s = avb_property_lookup(
198       vbmeta_image_.data(), vbmeta_image_.size(), "non-existant", 0, &len);
199   EXPECT_EQ(0U, len);
200   EXPECT_EQ(NULL, s);
201 
202   // Numbers.
203   EXPECT_NE(
204       0,
205       avb_property_lookup_uint64(
206           vbmeta_image_.data(), vbmeta_image_.size(), "prisoner", 0, &val));
207   EXPECT_EQ(24601U, val);
208 
209   EXPECT_NE(
210       0,
211       avb_property_lookup_uint64(
212           vbmeta_image_.data(), vbmeta_image_.size(), "hexnumber", 0, &val));
213   EXPECT_EQ(0xcafeU, val);
214 
215   EXPECT_NE(0,
216             avb_property_lookup_uint64(vbmeta_image_.data(),
217                                        vbmeta_image_.size(),
218                                        "hexnumber_capital",
219                                        0,
220                                        &val));
221   EXPECT_EQ(0xcafeU, val);
222 
223   EXPECT_NE(0,
224             avb_property_lookup_uint64(vbmeta_image_.data(),
225                                        vbmeta_image_.size(),
226                                        "large_hexnumber",
227                                        0,
228                                        &val));
229   EXPECT_EQ(0xfedcba9876543210U, val);
230 
231   // We could catch overflows and return an error ... but we currently don't.
232   EXPECT_NE(0,
233             avb_property_lookup_uint64(vbmeta_image_.data(),
234                                        vbmeta_image_.size(),
235                                        "larger_than_uint64",
236                                        0,
237                                        &val));
238   EXPECT_EQ(0xedcba98765432101U, val);
239 
240   // Number-parsing failures.
241   EXPECT_EQ(0,
242             avb_property_lookup_uint64(
243                 vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &val));
244 
245   EXPECT_EQ(0,
246             avb_property_lookup_uint64(vbmeta_image_.data(),
247                                        vbmeta_image_.size(),
248                                        "almost_a_number",
249                                        0,
250                                        &val));
251 
252   // Blobs.
253   //
254   // test/data/small_blob.bin is 21 byte file full of NUL-bytes except
255   // for the string "brillo ftw!" at index 2 and '\n' at the last
256   // byte.
257   s = avb_property_lookup(
258       vbmeta_image_.data(), vbmeta_image_.size(), "blob", 0, &len);
259   EXPECT_EQ(21U, len);
260   EXPECT_EQ(0, memcmp(s, "\0\0", 2));
261   EXPECT_EQ(0, memcmp(s + 2, "brillo ftw!", 11));
262   EXPECT_EQ(0, memcmp(s + 13, "\0\0\0\0\0\0\0", 7));
263   EXPECT_EQ('\n', s[20]);
264 }
265 
TEST_F(AvbToolTest,Padding)266 TEST_F(AvbToolTest, Padding) {
267   GenerateVBMetaImage("vbmeta.img",
268                       "SHA256_RSA2048",
269                       0,
270                       base::FilePath("test/data/testkey_rsa2048.pem"),
271                       "--internal_release_string \"\"");
272 
273   GenerateVBMetaImage("vbmeta_padded.img",
274                       "SHA256_RSA2048",
275                       0,
276                       base::FilePath("test/data/testkey_rsa2048.pem"),
277                       "--internal_release_string \"\" --padding_size 4096");
278 
279   base::FilePath vbmeta_path = testdir_.Append("vbmeta.img");
280   base::FilePath vbmeta_padded_path = testdir_.Append("vbmeta_padded.img");
281   int64_t vbmeta_size, vbmeta_padded_size;
282   ASSERT_TRUE(base::GetFileSize(vbmeta_path, &vbmeta_size));
283   ASSERT_TRUE(base::GetFileSize(vbmeta_padded_path, &vbmeta_padded_size));
284 
285   EXPECT_NE(vbmeta_size, vbmeta_padded_size);
286 
287   // The padded size should be a multiple of 4096.
288   EXPECT_EQ(vbmeta_padded_size % 4096, 0);
289 
290   // When rounded up the unpadded size should equal the padded size.
291   int64_t vbmeta_size_rounded_up = ((vbmeta_size + 4095) / 4096) * 4096;
292   EXPECT_EQ(vbmeta_size_rounded_up, vbmeta_padded_size);
293 }
294 
TEST_F(AvbToolTest,CheckRollbackIndex)295 TEST_F(AvbToolTest, CheckRollbackIndex) {
296   uint64_t rollback_index = 42;
297   GenerateVBMetaImage("vbmeta.img",
298                       "SHA256_RSA2048",
299                       rollback_index,
300                       base::FilePath("test/data/testkey_rsa2048.pem"),
301                       "--internal_release_string \"\"");
302 
303   AvbVBMetaImageHeader h;
304   avb_vbmeta_image_header_to_host_byte_order(
305       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
306 
307   EXPECT_EQ(rollback_index, h.rollback_index);
308 }
309 
TEST_F(AvbToolTest,CheckPubkeyReturned)310 TEST_F(AvbToolTest, CheckPubkeyReturned) {
311   GenerateVBMetaImage("vbmeta.img",
312                       "SHA256_RSA2048",
313                       0,
314                       base::FilePath("test/data/testkey_rsa2048.pem"),
315                       "--internal_release_string \"\"");
316 
317   const uint8_t* pubkey = NULL;
318   size_t pubkey_length = 0;
319 
320   EXPECT_EQ(
321       AVB_VBMETA_VERIFY_RESULT_OK,
322       avb_vbmeta_image_verify(
323           vbmeta_image_.data(), vbmeta_image_.size(), &pubkey, &pubkey_length));
324 
325   AvbVBMetaImageHeader h;
326   avb_vbmeta_image_header_to_host_byte_order(
327       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
328 
329   EXPECT_EQ(pubkey_length, h.public_key_size);
330 
331   const uint8_t* expected_pubkey =
332       vbmeta_image_.data() + sizeof(AvbVBMetaImageHeader) +
333       h.authentication_data_block_size + h.public_key_offset;
334   EXPECT_EQ(pubkey, expected_pubkey);
335 }
336 
TEST_F(AvbToolTest,Info)337 TEST_F(AvbToolTest, Info) {
338   GenerateVBMetaImage("vbmeta.img",
339                       "SHA256_RSA2048",
340                       0,
341                       base::FilePath("test/data/testkey_rsa2048.pem"),
342                       "--prop foo:brillo "
343                       "--prop bar:chromeos "
344                       "--prop prisoner:24601 "
345                       "--prop hexnumber:0xcafe "
346                       "--prop hexnumber_capital:0xCAFE "
347                       "--prop large_hexnumber:0xfedcba9876543210 "
348                       "--prop larger_than_uint64:0xfedcba98765432101 "
349                       "--prop almost_a_number:423x "
350                       "--prop_from_file blob:test/data/small_blob.bin "
351                       "--prop_from_file large_blob:test/data/large_blob.bin "
352                       "--internal_release_string \"\"");
353 
354   ASSERT_EQ(
355       "Minimum libavb version:   1.0\n"
356       "Header Block:             256 bytes\n"
357       "Authentication Block:     320 bytes\n"
358       "Auxiliary Block:          3200 bytes\n"
359       "Algorithm:                SHA256_RSA2048\n"
360       "Rollback Index:           0\n"
361       "Flags:                    0\n"
362       "Release String:           ''\n"
363       "Descriptors:\n"
364       "    Prop: foo -> 'brillo'\n"
365       "    Prop: bar -> 'chromeos'\n"
366       "    Prop: prisoner -> '24601'\n"
367       "    Prop: hexnumber -> '0xcafe'\n"
368       "    Prop: hexnumber_capital -> '0xCAFE'\n"
369       "    Prop: large_hexnumber -> '0xfedcba9876543210'\n"
370       "    Prop: larger_than_uint64 -> '0xfedcba98765432101'\n"
371       "    Prop: almost_a_number -> '423x'\n"
372       "    Prop: blob -> '\\x00\\x00brillo "
373       "ftw!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n'\n"
374       "    Prop: large_blob -> (2048 bytes)\n",
375       InfoImage(vbmeta_image_path_));
376 }
377 
collect_descriptors(const AvbDescriptor * descriptor,void * user_data)378 static bool collect_descriptors(const AvbDescriptor* descriptor,
379                                 void* user_data) {
380   std::vector<const AvbDescriptor*>* descriptors =
381       reinterpret_cast<std::vector<const AvbDescriptor*>*>(user_data);
382   descriptors->push_back(descriptor);
383   return true;  // Keep iterating.
384 }
385 
AddHashFooterGetExpectedVBMetaInfo(const bool sparse_image,const uint64_t partition_size)386 static std::string AddHashFooterGetExpectedVBMetaInfo(
387     const bool sparse_image, const uint64_t partition_size) {
388   return base::StringPrintf(
389       "Footer version:           1.0\n"
390       "Image size:               %" PRIu64
391       " bytes\n"
392       "Original image size:      1052672 bytes\n"
393       "VBMeta offset:            1052672\n"
394       "VBMeta size:              1280 bytes\n"
395       "--\n"
396       "Minimum libavb version:   1.0%s\n"
397       "Header Block:             256 bytes\n"
398       "Authentication Block:     320 bytes\n"
399       "Auxiliary Block:          704 bytes\n"
400       "Algorithm:                SHA256_RSA2048\n"
401       "Rollback Index:           0\n"
402       "Flags:                    0\n"
403       "Release String:           ''\n"
404       "Descriptors:\n"
405       "    Hash descriptor:\n"
406       "      Image Size:            1052672 bytes\n"
407       "      Hash Algorithm:        sha256\n"
408       "      Partition Name:        foobar\n"
409       "      Salt:                  d00df00d\n"
410       "      Digest:                "
411       "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
412       "5e4ed357fbcf58d88d9\n"
413       "      Flags:                 0\n",
414       partition_size,
415       sparse_image ? " (Sparse)" : "");
416 }
417 
AddHashFooterTest(bool sparse_image)418 void AvbToolTest::AddHashFooterTest(bool sparse_image) {
419   const size_t rootfs_size = 1028 * 1024;
420   const size_t partition_size = 1536 * 1024;
421   const size_t resized_partition_size = 1280 * 1024;
422 
423   // Generate a 1028 KiB file with known content. Some content have
424   // been arranged to ensure FILL_DATA segments in the sparse file.
425   std::vector<uint8_t> rootfs;
426   rootfs.resize(rootfs_size);
427   for (size_t n = 0; n < rootfs_size; n++) {
428     if ((n >= 5 * 1000 && n < 105 * 1000) ||
429         (n >= 205 * 1000 && n < 305 * 1000) ||
430         (n >= 505 * 1000 && n < 605 * 1000)) {
431       rootfs[n] = uint8_t(n) & 0x03;
432     } else {
433       rootfs[n] = uint8_t(n);
434     }
435   }
436   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
437   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
438   EXPECT_EQ(rootfs_size,
439             static_cast<const size_t>(
440                 base::WriteFile(rootfs_path,
441                                 reinterpret_cast<const char*>(rootfs.data()),
442                                 rootfs.size())));
443 
444   if (sparse_image) {
445     EXPECT_COMMAND(0,
446                    "mv %s %s.unsparse",
447                    rootfs_path.value().c_str(),
448                    rootfs_path.value().c_str());
449     EXPECT_COMMAND(0,
450                    "img2simg %s.unsparse %s",
451                    rootfs_path.value().c_str(),
452                    rootfs_path.value().c_str());
453     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
454   }
455 
456   /* Do this twice to check that 'add_hash_footer' is idempotent. */
457   for (int n = 0; n < 2; n++) {
458     EXPECT_COMMAND(0,
459                    "./avbtool add_hash_footer --salt d00df00d "
460                    "--hash_algorithm sha256 --image %s "
461                    "--partition_size %d --partition_name foobar "
462                    "--algorithm SHA256_RSA2048 "
463                    "--key test/data/testkey_rsa2048.pem "
464                    "--output_vbmeta %s "
465                    "--internal_release_string \"\"",
466                    rootfs_path.value().c_str(),
467                    (int)partition_size,
468                    ext_vbmeta_path.value().c_str());
469 
470     ASSERT_EQ(AddHashFooterGetExpectedVBMetaInfo(sparse_image, partition_size),
471               InfoImage(rootfs_path));
472 
473     ASSERT_EQ(
474         "Minimum libavb version:   1.0\n"
475         "Header Block:             256 bytes\n"
476         "Authentication Block:     320 bytes\n"
477         "Auxiliary Block:          704 bytes\n"
478         "Algorithm:                SHA256_RSA2048\n"
479         "Rollback Index:           0\n"
480         "Flags:                    0\n"
481         "Release String:           ''\n"
482         "Descriptors:\n"
483         "    Hash descriptor:\n"
484         "      Image Size:            1052672 bytes\n"
485         "      Hash Algorithm:        sha256\n"
486         "      Partition Name:        foobar\n"
487         "      Salt:                  d00df00d\n"
488         "      Digest:                "
489         "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
490         "5e4ed357fbcf58d88d9\n"
491         "      Flags:                 0\n",
492         InfoImage(ext_vbmeta_path));
493   }
494 
495   // Resize the image and check that the only thing that has changed
496   // is where the footer is. First check that resizing to a smaller
497   // size than the original rootfs fails. Then resize to something
498   // larger than the original rootfs but smaller than the current
499   // partition size.
500   EXPECT_COMMAND(1,
501                  "./avbtool resize_image --image %s "
502                  "--partition_size %d",
503                  rootfs_path.value().c_str(),
504                  (int)(rootfs_size - 16 * 1024));
505   EXPECT_COMMAND(0,
506                  "./avbtool resize_image --image %s "
507                  "--partition_size %d",
508                  rootfs_path.value().c_str(),
509                  (int)resized_partition_size);
510   ASSERT_EQ(
511       AddHashFooterGetExpectedVBMetaInfo(sparse_image, resized_partition_size),
512       InfoImage(rootfs_path));
513 
514   if (sparse_image) {
515     EXPECT_COMMAND(0,
516                    "mv %s %s.sparse",
517                    rootfs_path.value().c_str(),
518                    rootfs_path.value().c_str());
519     EXPECT_COMMAND(0,
520                    "simg2img %s.sparse %s",
521                    rootfs_path.value().c_str(),
522                    rootfs_path.value().c_str());
523     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
524   }
525 
526   // Manually calculate the hash to check that it agrees with avbtool.
527   AvbSHA256Ctx hasher_ctx;
528   const uint8_t hasher_salt[4] = {0xd0, 0x0d, 0xf0, 0x0d};
529   avb_sha256_init(&hasher_ctx);
530   avb_sha256_update(&hasher_ctx, hasher_salt, 4);
531   avb_sha256_update(&hasher_ctx, rootfs.data(), rootfs_size);
532   uint8_t* hasher_digest = avb_sha256_final(&hasher_ctx);
533   EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
534             mem_to_hexstring(hasher_digest, AVB_SHA256_DIGEST_SIZE));
535 
536   // Now check that we can find the VBMeta block again from the footer.
537   std::string part_data;
538   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
539 
540   // Check footer contains correct data.
541   AvbFooter f;
542   EXPECT_NE(0,
543             avb_footer_validate_and_byteswap(
544                 reinterpret_cast<const AvbFooter*>(
545                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
546                 &f));
547   EXPECT_EQ(
548       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
549       AVB_FOOTER_MAGIC);
550   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
551   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
552   EXPECT_EQ(1052672UL, f.original_image_size);
553   EXPECT_EQ(1052672UL, f.vbmeta_offset);
554   EXPECT_EQ(1280UL, f.vbmeta_size);
555 
556   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
557   const uint8_t* vbmeta_data =
558       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
559   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
560             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
561 
562   // Collect all descriptors.
563   std::vector<const AvbDescriptor*> descriptors;
564   avb_descriptor_foreach(
565       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
566 
567   // We should only have a single descriptor and it should be a
568   // hash descriptor.
569   EXPECT_EQ(1UL, descriptors.size());
570   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, avb_be64toh(descriptors[0]->tag));
571   AvbHashDescriptor d;
572   EXPECT_NE(
573       0,
574       avb_hash_descriptor_validate_and_byteswap(
575           reinterpret_cast<const AvbHashDescriptor*>(descriptors[0]), &d));
576   EXPECT_EQ(1052672UL, d.image_size);
577   EXPECT_EQ(6UL, d.partition_name_len);
578   EXPECT_EQ(4UL, d.salt_len);
579   EXPECT_EQ(32UL, d.digest_len);
580   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
581                             sizeof(AvbHashDescriptor);
582   uint64_t o = 0;
583   EXPECT_EQ("foobar",
584             std::string(reinterpret_cast<const char*>(desc_end + o),
585                         d.partition_name_len));
586   o += d.partition_name_len;
587   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
588   o += d.salt_len;
589   EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
590             mem_to_hexstring(desc_end + o, d.digest_len));
591 
592   // Check that the footer is correctly erased.
593   EXPECT_COMMAND(
594       0, "./avbtool erase_footer --image %s", rootfs_path.value().c_str());
595   int64_t erased_footer_file_size;
596   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
597   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size);
598 
599   // Check that --do_not_append_vbmeta_image works as intended.
600   EXPECT_COMMAND(0,
601                  "./avbtool add_hash_footer --salt d00df00d "
602                  "--hash_algorithm sha256 --image %s "
603                  "--partition_size %d --partition_name foobar "
604                  "--algorithm SHA256_RSA2048 "
605                  "--key test/data/testkey_rsa2048.pem "
606                  "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
607                  "--internal_release_string \"\"",
608                  rootfs_path.value().c_str(),
609                  (int)partition_size,
610                  ext_vbmeta_path.value().c_str());
611   int64_t file_size;
612   ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
613   EXPECT_EQ(static_cast<size_t>(file_size), rootfs_size);
614   EXPECT_COMMAND(0,
615                  "diff %s %s_2nd_run",
616                  ext_vbmeta_path.value().c_str(),
617                  ext_vbmeta_path.value().c_str());
618 }
619 
TEST_F(AvbToolTest,AddHashFooter)620 TEST_F(AvbToolTest, AddHashFooter) {
621   AddHashFooterTest(false);
622 }
623 
TEST_F(AvbToolTest,AddHashFooterSparse)624 TEST_F(AvbToolTest, AddHashFooterSparse) {
625   AddHashFooterTest(true);
626 }
627 
RemoveLinesStartingWith(const std::string & str,const std::string & prefix)628 static std::string RemoveLinesStartingWith(const std::string& str,
629                                            const std::string& prefix) {
630   std::vector<std::string> lines;
631   std::string ret;
632 
633   lines = base::SplitString(
634       str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
635   for (const std::string& line : lines) {
636     if (!base::StartsWith(line, prefix, base::CompareCase::SENSITIVE)) {
637       ret += line;
638       ret += '\n';
639     }
640   }
641   return ret;
642 }
643 
TEST_F(AvbToolTest,AddHashFooterSparseWithHoleAtTheEnd)644 TEST_F(AvbToolTest, AddHashFooterSparseWithHoleAtTheEnd) {
645   const size_t partition_size = 10 * 1024 * 1024;
646   const size_t metadata_size = 128 * 1024;
647 
648   // It's not enough to run img2simg on a file with a lot of zeroes at
649   // the end since that will turn up as "Fill with value (for value =
650   // 0x00000000)" and not "Don't care". Instead, use make_ext4fs for
651   // this since it will put a big hole (e.g. "Don't care" chunk) at
652   // the end.
653   base::FilePath partition_path = testdir_.Append("partition.bin");
654   EXPECT_COMMAND(0,
655                  "make_ext4fs -s -L test -l %zd %s",
656                  partition_size - metadata_size,
657                  partition_path.value().c_str());
658 
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                  "--internal_release_string \"\"",
666                  partition_path.value().c_str(),
667                  (int)partition_size);
668 
669   // Since we may be using an arbritary version of make_ext4fs
670   // (because of different branches) the contents of the resulting
671   // disk image may slightly change. It's enough to just remove the
672   // "Digest:" line from the output to work around this.
673   std::string info =
674       RemoveLinesStartingWith(InfoImage(partition_path), "      Digest:");
675   ASSERT_EQ(
676       "Footer version:           1.0\n"
677       "Image size:               10485760 bytes\n"
678       "Original image size:      10354688 bytes\n"
679       "VBMeta offset:            10354688\n"
680       "VBMeta size:              1280 bytes\n"
681       "--\n"
682       "Minimum libavb version:   1.0 (Sparse)\n"
683       "Header Block:             256 bytes\n"
684       "Authentication Block:     320 bytes\n"
685       "Auxiliary Block:          704 bytes\n"
686       "Algorithm:                SHA256_RSA2048\n"
687       "Rollback Index:           0\n"
688       "Flags:                    0\n"
689       "Release String:           ''\n"
690       "Descriptors:\n"
691       "    Hash descriptor:\n"
692       "      Image Size:            10354688 bytes\n"
693       "      Hash Algorithm:        sha256\n"
694       "      Partition Name:        foobar\n"
695       "      Salt:                  d00df00d\n"
696       "      Flags:                 0\n",
697       info);
698 
699   EXPECT_COMMAND(0,
700                  "mv %s %s.sparse",
701                  partition_path.value().c_str(),
702                  partition_path.value().c_str());
703   EXPECT_COMMAND(0,
704                  "simg2img %s.sparse %s",
705                  partition_path.value().c_str(),
706                  partition_path.value().c_str());
707   EXPECT_COMMAND(0, "rm -f %s.sparse", partition_path.value().c_str());
708 }
709 
TEST_F(AvbToolTest,AddHashFooterCalcMaxImageSize)710 TEST_F(AvbToolTest, AddHashFooterCalcMaxImageSize) {
711   const size_t partition_size = 10 * 1024 * 1024;
712   base::FilePath output_path = testdir_.Append("max_size.txt");
713 
714   EXPECT_COMMAND(0,
715                  "./avbtool add_hash_footer "
716                  "--partition_size %zd "
717                  "--calc_max_image_size > %s",
718                  partition_size,
719                  output_path.value().c_str());
720   std::string max_image_size_data;
721   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
722   EXPECT_EQ("10416128\n", max_image_size_data);
723   size_t max_image_size = atoll(max_image_size_data.c_str());
724 
725   // Metadata takes up 68 KiB.
726   EXPECT_EQ(68 * 1024ULL, partition_size - max_image_size);
727 
728   // Check that we can add a hash footer for an image this size for
729   // such a partition size.
730   base::FilePath boot_path = GenerateImage("boot", max_image_size);
731   EXPECT_COMMAND(0,
732                  "./avbtool add_hash_footer"
733                  " --image %s"
734                  " --partition_name boot"
735                  " --partition_size %zd"
736                  " --salt deadbeef"
737                  " --algorithm SHA512_RSA4096 "
738                  " --key test/data/testkey_rsa4096.pem"
739                  " --internal_release_string \"\"",
740                  boot_path.value().c_str(),
741                  partition_size);
742 }
743 
TEST_F(AvbToolTest,AddHashFooterWithPersistentDigest)744 TEST_F(AvbToolTest, AddHashFooterWithPersistentDigest) {
745   size_t partition_size = 1024 * 1024;
746   base::FilePath path = GenerateImage("digest_location", 1024);
747   EXPECT_COMMAND(0,
748                  "./avbtool add_hash_footer --salt d00df00d "
749                  "--hash_algorithm sha256 --image %s "
750                  "--partition_size %d --partition_name foobar "
751                  "--algorithm SHA256_RSA2048 "
752                  "--key test/data/testkey_rsa2048.pem "
753                  "--internal_release_string \"\" "
754                  "--use_persistent_digest",
755                  path.value().c_str(),
756                  (int)partition_size);
757   // There are two important bits specific to these flags:
758   //   Minimum libavb version = 1.1
759   //   Hash descriptor -> Digest = (empty)
760   ASSERT_EQ(
761       "Footer version:           1.0\n"
762       "Image size:               1048576 bytes\n"
763       "Original image size:      1024 bytes\n"
764       "VBMeta offset:            4096\n"
765       "VBMeta size:              1280 bytes\n"
766       "--\n"
767       "Minimum libavb version:   1.1\n"
768       "Header Block:             256 bytes\n"
769       "Authentication Block:     320 bytes\n"
770       "Auxiliary Block:          704 bytes\n"
771       "Algorithm:                SHA256_RSA2048\n"
772       "Rollback Index:           0\n"
773       "Flags:                    0\n"
774       "Release String:           ''\n"
775       "Descriptors:\n"
776       "    Hash descriptor:\n"
777       "      Image Size:            1024 bytes\n"
778       "      Hash Algorithm:        sha256\n"
779       "      Partition Name:        foobar\n"
780       "      Salt:                  d00df00d\n"
781       "      Digest:                \n"
782       "      Flags:                 0\n",
783       InfoImage(path));
784 }
785 
TEST_F(AvbToolTest,AddHashFooterWithNoAB)786 TEST_F(AvbToolTest, AddHashFooterWithNoAB) {
787   size_t partition_size = 1024 * 1024;
788   base::FilePath path = GenerateImage("digest_location", 1024);
789   EXPECT_COMMAND(0,
790                  "./avbtool add_hash_footer --salt d00df00d "
791                  "--hash_algorithm sha256 --image %s "
792                  "--partition_size %d --partition_name foobar "
793                  "--algorithm SHA256_RSA2048 "
794                  "--key test/data/testkey_rsa2048.pem "
795                  "--internal_release_string \"\" "
796                  "--do_not_use_ab",
797                  path.value().c_str(),
798                  (int)partition_size);
799   // There are two important bits specific to these flags:
800   //   Minimum libavb version = 1.1
801   //   Hash descriptor -> Flags = 1
802   ASSERT_EQ(
803       "Footer version:           1.0\n"
804       "Image size:               1048576 bytes\n"
805       "Original image size:      1024 bytes\n"
806       "VBMeta offset:            4096\n"
807       "VBMeta size:              1280 bytes\n"
808       "--\n"
809       "Minimum libavb version:   1.1\n"
810       "Header Block:             256 bytes\n"
811       "Authentication Block:     320 bytes\n"
812       "Auxiliary Block:          704 bytes\n"
813       "Algorithm:                SHA256_RSA2048\n"
814       "Rollback Index:           0\n"
815       "Flags:                    0\n"
816       "Release String:           ''\n"
817       "Descriptors:\n"
818       "    Hash descriptor:\n"
819       "      Image Size:            1024 bytes\n"
820       "      Hash Algorithm:        sha256\n"
821       "      Partition Name:        foobar\n"
822       "      Salt:                  d00df00d\n"
823       "      Digest:                "
824       "91386fea3e251ad0c2cb6859e4f4772f37fdb69f17d46636ddc9e7fbfd3bf3d0\n"
825       "      Flags:                 1\n",
826       InfoImage(path));
827 }
828 
TEST_F(AvbToolTest,AddHashFooterWithPersistentDigestAndNoAB)829 TEST_F(AvbToolTest, AddHashFooterWithPersistentDigestAndNoAB) {
830   size_t partition_size = 1024 * 1024;
831   base::FilePath path = GenerateImage("digest_location", 1024);
832   EXPECT_COMMAND(0,
833                  "./avbtool add_hash_footer --salt d00df00d "
834                  "--hash_algorithm sha256 --image %s "
835                  "--partition_size %d --partition_name foobar "
836                  "--algorithm SHA256_RSA2048 "
837                  "--key test/data/testkey_rsa2048.pem "
838                  "--internal_release_string \"\" "
839                  "--use_persistent_digest --do_not_use_ab",
840                  path.value().c_str(),
841                  (int)partition_size);
842   // There are three important bits specific to these flags:
843   //   Minimum libavb version = 1.1
844   //   Hash descriptor -> Digest = (empty)
845   //   Hash descriptor -> Flags = 1
846   ASSERT_EQ(
847       "Footer version:           1.0\n"
848       "Image size:               1048576 bytes\n"
849       "Original image size:      1024 bytes\n"
850       "VBMeta offset:            4096\n"
851       "VBMeta size:              1280 bytes\n"
852       "--\n"
853       "Minimum libavb version:   1.1\n"
854       "Header Block:             256 bytes\n"
855       "Authentication Block:     320 bytes\n"
856       "Auxiliary Block:          704 bytes\n"
857       "Algorithm:                SHA256_RSA2048\n"
858       "Rollback Index:           0\n"
859       "Flags:                    0\n"
860       "Release String:           ''\n"
861       "Descriptors:\n"
862       "    Hash descriptor:\n"
863       "      Image Size:            1024 bytes\n"
864       "      Hash Algorithm:        sha256\n"
865       "      Partition Name:        foobar\n"
866       "      Salt:                  d00df00d\n"
867       "      Digest:                \n"
868       "      Flags:                 1\n",
869       InfoImage(path));
870 }
871 
AddHashtreeFooterTest(bool sparse_image)872 void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
873   const size_t rootfs_size = 1028 * 1024;
874   const size_t partition_size = 1536 * 1024;
875 
876   // Generate a 1028 KiB file with known content.
877   std::vector<uint8_t> rootfs;
878   rootfs.resize(rootfs_size);
879   for (size_t n = 0; n < rootfs_size; n++)
880     rootfs[n] = uint8_t(n);
881   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
882   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
883   EXPECT_EQ(rootfs_size,
884             static_cast<const size_t>(
885                 base::WriteFile(rootfs_path,
886                                 reinterpret_cast<const char*>(rootfs.data()),
887                                 rootfs.size())));
888 
889   if (sparse_image) {
890     EXPECT_COMMAND(0,
891                    "mv %s %s.unsparse",
892                    rootfs_path.value().c_str(),
893                    rootfs_path.value().c_str());
894     EXPECT_COMMAND(0,
895                    "img2simg %s.unsparse %s",
896                    rootfs_path.value().c_str(),
897                    rootfs_path.value().c_str());
898     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
899   }
900 
901   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
902   for (int n = 0; n < 2; n++) {
903     EXPECT_COMMAND(0,
904                    "./avbtool add_hashtree_footer --salt d00df00d --image %s "
905                    "--partition_size %d --partition_name foobar "
906                    "--algorithm SHA256_RSA2048 "
907                    "--key test/data/testkey_rsa2048.pem "
908                    "--output_vbmeta_image %s "
909                    "--internal_release_string \"\" "
910                    "--do_not_generate_fec",
911                    rootfs_path.value().c_str(),
912                    (int)partition_size,
913                    ext_vbmeta_path.value().c_str());
914 
915     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
916                                  "Image size:               1572864 bytes\n"
917                                  "Original image size:      1052672 bytes\n"
918                                  "VBMeta offset:            1069056\n"
919                                  "VBMeta size:              1344 bytes\n"
920                                  "--\n"
921                                  "Minimum libavb version:   1.0%s\n"
922                                  "Header Block:             256 bytes\n"
923                                  "Authentication Block:     320 bytes\n"
924                                  "Auxiliary Block:          768 bytes\n"
925                                  "Algorithm:                SHA256_RSA2048\n"
926                                  "Rollback Index:           0\n"
927                                  "Flags:                    0\n"
928                                  "Release String:           ''\n"
929                                  "Descriptors:\n"
930                                  "    Hashtree descriptor:\n"
931                                  "      Version of dm-verity:  1\n"
932                                  "      Image Size:            1052672 bytes\n"
933                                  "      Tree Offset:           1052672\n"
934                                  "      Tree Size:             16384 bytes\n"
935                                  "      Data Block Size:       4096 bytes\n"
936                                  "      Hash Block Size:       4096 bytes\n"
937                                  "      FEC num roots:         0\n"
938                                  "      FEC offset:            0\n"
939                                  "      FEC size:              0 bytes\n"
940                                  "      Hash Algorithm:        sha1\n"
941                                  "      Partition Name:        foobar\n"
942                                  "      Salt:                  d00df00d\n"
943                                  "      Root Digest:           "
944                                  "e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
945                                  "      Flags:                 0\n",
946                                  sparse_image ? " (Sparse)" : ""),
947               InfoImage(rootfs_path));
948 
949     ASSERT_EQ(
950         "Minimum libavb version:   1.0\n"
951         "Header Block:             256 bytes\n"
952         "Authentication Block:     320 bytes\n"
953         "Auxiliary Block:          768 bytes\n"
954         "Algorithm:                SHA256_RSA2048\n"
955         "Rollback Index:           0\n"
956         "Flags:                    0\n"
957         "Release String:           ''\n"
958         "Descriptors:\n"
959         "    Hashtree descriptor:\n"
960         "      Version of dm-verity:  1\n"
961         "      Image Size:            1052672 bytes\n"
962         "      Tree Offset:           1052672\n"
963         "      Tree Size:             16384 bytes\n"
964         "      Data Block Size:       4096 bytes\n"
965         "      Hash Block Size:       4096 bytes\n"
966         "      FEC num roots:         0\n"
967         "      FEC offset:            0\n"
968         "      FEC size:              0 bytes\n"
969         "      Hash Algorithm:        sha1\n"
970         "      Partition Name:        foobar\n"
971         "      Salt:                  d00df00d\n"
972         "      Root Digest:           "
973         "e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
974         "      Flags:                 0\n",
975         InfoImage(ext_vbmeta_path));
976   }
977 
978   if (sparse_image) {
979     EXPECT_COMMAND(0,
980                    "mv %s %s.sparse",
981                    rootfs_path.value().c_str(),
982                    rootfs_path.value().c_str());
983     EXPECT_COMMAND(0,
984                    "simg2img %s.sparse %s",
985                    rootfs_path.value().c_str(),
986                    rootfs_path.value().c_str());
987     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
988   }
989 
990   // To check that we generate the correct hashtree we can use
991   // veritysetup(1) - another codebase for working with dm-verity
992   // hashtrees - to verify it.
993   //
994   // If we don't want to impose the requirement of having the
995   // veritysetup(1) command available on builders we can comment this
996   // out.
997   EXPECT_COMMAND(0,
998                  "veritysetup --no-superblock --format=1 --hash=sha1 "
999                  "--data-block-size=4096 --hash-block-size=4096 "
1000                  "--salt=d00df00d "
1001                  "--data-blocks=257 "
1002                  "--hash-offset=1052672 "
1003                  "verify "
1004                  "%s %s "
1005                  "e811611467dcd6e8dc4324e45f706c2bdd51db67",
1006                  rootfs_path.value().c_str(),
1007                  rootfs_path.value().c_str());
1008 
1009   // Now check that we can find the VBMeta block again from the footer.
1010   std::string part_data;
1011   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1012 
1013   // Check footer contains correct data.
1014   AvbFooter f;
1015   EXPECT_NE(0,
1016             avb_footer_validate_and_byteswap(
1017                 reinterpret_cast<const AvbFooter*>(
1018                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1019                 &f));
1020   EXPECT_EQ(
1021       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1022       AVB_FOOTER_MAGIC);
1023   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1024   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1025   EXPECT_EQ(1052672UL, f.original_image_size);
1026   EXPECT_EQ(1069056UL, f.vbmeta_offset);
1027   EXPECT_EQ(1344UL, f.vbmeta_size);
1028 
1029   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1030   const uint8_t* vbmeta_data =
1031       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1032   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1033             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1034 
1035   // Collect all descriptors.
1036   std::vector<const AvbDescriptor*> descriptors;
1037   avb_descriptor_foreach(
1038       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1039 
1040   // We should only have a single descriptor and it should be a
1041   // hashtree descriptor.
1042   EXPECT_EQ(1UL, descriptors.size());
1043   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1044   AvbHashtreeDescriptor d;
1045   EXPECT_NE(
1046       0,
1047       avb_hashtree_descriptor_validate_and_byteswap(
1048           reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1049   EXPECT_EQ(1UL, d.dm_verity_version);
1050   EXPECT_EQ(1052672UL, d.image_size);
1051   EXPECT_EQ(1052672UL, d.tree_offset);
1052   EXPECT_EQ(16384UL, d.tree_size);
1053   EXPECT_EQ(4096UL, d.data_block_size);
1054   EXPECT_EQ(4096UL, d.hash_block_size);
1055   EXPECT_EQ(6UL, d.partition_name_len);
1056   EXPECT_EQ(4UL, d.salt_len);
1057   EXPECT_EQ(20UL, d.root_digest_len);
1058   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1059                             sizeof(AvbHashtreeDescriptor);
1060   uint64_t o = 0;
1061   EXPECT_EQ("foobar",
1062             std::string(reinterpret_cast<const char*>(desc_end + o),
1063                         d.partition_name_len));
1064   o += d.partition_name_len;
1065   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1066   o += d.salt_len;
1067   EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1068             mem_to_hexstring(desc_end + o, d.root_digest_len));
1069 
1070   // Check that we correctly generate dm-verity kernel cmdline
1071   // snippets, if requested.
1072   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1073   EXPECT_COMMAND(0,
1074                  "./avbtool make_vbmeta_image "
1075                  "--output %s "
1076                  "--setup_rootfs_from_kernel %s "
1077                  "--algorithm SHA256_RSA2048 "
1078                  "--key test/data/testkey_rsa2048.pem "
1079                  "--internal_release_string \"\"",
1080                  vbmeta_dmv_path.value().c_str(),
1081                  rootfs_path.value().c_str());
1082 
1083   ASSERT_EQ(
1084       "Minimum libavb version:   1.0\n"
1085       "Header Block:             256 bytes\n"
1086       "Authentication Block:     320 bytes\n"
1087       "Auxiliary Block:          896 bytes\n"
1088       "Algorithm:                SHA256_RSA2048\n"
1089       "Rollback Index:           0\n"
1090       "Flags:                    0\n"
1091       "Release String:           ''\n"
1092       "Descriptors:\n"
1093       "    Kernel Cmdline descriptor:\n"
1094       "      Flags:                 1\n"
1095       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1096       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1097       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1098       "d00df00d 2 $(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
1099       "    Kernel Cmdline descriptor:\n"
1100       "      Flags:                 2\n"
1101       "      Kernel Cmdline:        "
1102       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1103       InfoImage(vbmeta_dmv_path));
1104 
1105   // Check that the footer is correctly erased and the hashtree
1106   // remains - see above for why the constant 1069056 is used.
1107   EXPECT_COMMAND(0,
1108                  "./avbtool erase_footer --image %s --keep_hashtree",
1109                  rootfs_path.value().c_str());
1110   int64_t erased_footer_file_size;
1111   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1112   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1069056UL);
1113 
1114   // Check that --do_not_append_vbmeta_image works as intended.
1115   //
1116   // For this we need to reset the size of the image to the original
1117   // size because it's not possible to identify the existing hashtree.
1118   EXPECT_COMMAND(
1119       0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str());
1120   EXPECT_COMMAND(0,
1121                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1122                  "--partition_size %d --partition_name foobar "
1123                  "--algorithm SHA256_RSA2048 "
1124                  "--key test/data/testkey_rsa2048.pem "
1125                  "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
1126                  "--internal_release_string \"\" "
1127                  "--do_not_generate_fec",
1128                  rootfs_path.value().c_str(),
1129                  (int)partition_size,
1130                  ext_vbmeta_path.value().c_str());
1131   int64_t file_size;
1132   ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
1133   EXPECT_EQ(static_cast<size_t>(file_size), 1069056UL);
1134   EXPECT_COMMAND(0,
1135                  "diff %s %s_2nd_run",
1136                  ext_vbmeta_path.value().c_str(),
1137                  ext_vbmeta_path.value().c_str());
1138 }
1139 
TEST_F(AvbToolTest,AddHashtreeFooter)1140 TEST_F(AvbToolTest, AddHashtreeFooter) {
1141   AddHashtreeFooterTest(false);
1142 }
1143 
TEST_F(AvbToolTest,AddHashtreeFooterSparse)1144 TEST_F(AvbToolTest, AddHashtreeFooterSparse) {
1145   AddHashtreeFooterTest(true);
1146 }
1147 
AddHashtreeFooterFECTest(bool sparse_image)1148 void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
1149   const size_t rootfs_size = 1028 * 1024;
1150   const size_t partition_size = 1536 * 1024;
1151 
1152   // Generate a 1028 KiB file with known content.
1153   std::vector<uint8_t> rootfs;
1154   rootfs.resize(rootfs_size);
1155   for (size_t n = 0; n < rootfs_size; n++)
1156     rootfs[n] = uint8_t(n);
1157   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
1158   EXPECT_EQ(rootfs_size,
1159             static_cast<const size_t>(
1160                 base::WriteFile(rootfs_path,
1161                                 reinterpret_cast<const char*>(rootfs.data()),
1162                                 rootfs.size())));
1163 
1164   if (sparse_image) {
1165     EXPECT_COMMAND(0,
1166                    "mv %s %s.unsparse",
1167                    rootfs_path.value().c_str(),
1168                    rootfs_path.value().c_str());
1169     EXPECT_COMMAND(0,
1170                    "img2simg %s.unsparse %s",
1171                    rootfs_path.value().c_str(),
1172                    rootfs_path.value().c_str());
1173     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
1174   }
1175 
1176   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
1177   for (int n = 0; n < 2; n++) {
1178     EXPECT_COMMAND(0,
1179                    "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1180                    "--partition_size %d --partition_name foobar "
1181                    "--algorithm SHA256_RSA2048 "
1182                    "--key test/data/testkey_rsa2048.pem "
1183                    "--internal_release_string \"\"",
1184                    rootfs_path.value().c_str(),
1185                    (int)partition_size);
1186 
1187     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
1188                                  "Image size:               1572864 bytes\n"
1189                                  "Original image size:      1052672 bytes\n"
1190                                  "VBMeta offset:            1085440\n"
1191                                  "VBMeta size:              1344 bytes\n"
1192                                  "--\n"
1193                                  "Minimum libavb version:   1.0%s\n"
1194                                  "Header Block:             256 bytes\n"
1195                                  "Authentication Block:     320 bytes\n"
1196                                  "Auxiliary Block:          768 bytes\n"
1197                                  "Algorithm:                SHA256_RSA2048\n"
1198                                  "Rollback Index:           0\n"
1199                                  "Flags:                    0\n"
1200                                  "Release String:           ''\n"
1201                                  "Descriptors:\n"
1202                                  "    Hashtree descriptor:\n"
1203                                  "      Version of dm-verity:  1\n"
1204                                  "      Image Size:            1052672 bytes\n"
1205                                  "      Tree Offset:           1052672\n"
1206                                  "      Tree Size:             16384 bytes\n"
1207                                  "      Data Block Size:       4096 bytes\n"
1208                                  "      Hash Block Size:       4096 bytes\n"
1209                                  "      FEC num roots:         2\n"
1210                                  "      FEC offset:            1069056\n"
1211                                  "      FEC size:              16384 bytes\n"
1212                                  "      Hash Algorithm:        sha1\n"
1213                                  "      Partition Name:        foobar\n"
1214                                  "      Salt:                  d00df00d\n"
1215                                  "      Root Digest:           "
1216                                  "e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
1217                                  "      Flags:                 0\n",
1218                                  sparse_image ? " (Sparse)" : ""),
1219               InfoImage(rootfs_path));
1220   }
1221 
1222   if (sparse_image) {
1223     EXPECT_COMMAND(0,
1224                    "mv %s %s.sparse",
1225                    rootfs_path.value().c_str(),
1226                    rootfs_path.value().c_str());
1227     EXPECT_COMMAND(0,
1228                    "simg2img %s.sparse %s",
1229                    rootfs_path.value().c_str(),
1230                    rootfs_path.value().c_str());
1231     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
1232   }
1233 
1234   /* TODO: would be nice to verify that the FEC data is correct. */
1235 
1236   // Now check that we can find the VBMeta block again from the footer.
1237   std::string part_data;
1238   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1239 
1240   // Check footer contains correct data.
1241   AvbFooter f;
1242   EXPECT_NE(0,
1243             avb_footer_validate_and_byteswap(
1244                 reinterpret_cast<const AvbFooter*>(
1245                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1246                 &f));
1247   EXPECT_EQ(
1248       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1249       AVB_FOOTER_MAGIC);
1250   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1251   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1252   EXPECT_EQ(1052672UL, f.original_image_size);
1253   EXPECT_EQ(1085440UL, f.vbmeta_offset);
1254   EXPECT_EQ(1344UL, f.vbmeta_size);
1255 
1256   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1257   const uint8_t* vbmeta_data =
1258       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1259   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1260             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1261 
1262   // Collect all descriptors.
1263   std::vector<const AvbDescriptor*> descriptors;
1264   avb_descriptor_foreach(
1265       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1266 
1267   // We should only have a single descriptor and it should be a
1268   // hashtree descriptor.
1269   EXPECT_EQ(1UL, descriptors.size());
1270   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1271   AvbHashtreeDescriptor d;
1272   EXPECT_NE(
1273       0,
1274       avb_hashtree_descriptor_validate_and_byteswap(
1275           reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1276   EXPECT_EQ(1UL, d.dm_verity_version);
1277   EXPECT_EQ(1052672UL, d.image_size);
1278   EXPECT_EQ(1052672UL, d.tree_offset);
1279   EXPECT_EQ(16384UL, d.tree_size);
1280   EXPECT_EQ(4096UL, d.data_block_size);
1281   EXPECT_EQ(2UL, d.fec_num_roots);
1282   EXPECT_EQ(1069056UL, d.fec_offset);
1283   EXPECT_EQ(16384UL, d.fec_size);
1284   EXPECT_EQ(6UL, d.partition_name_len);
1285   EXPECT_EQ(4UL, d.salt_len);
1286   EXPECT_EQ(20UL, d.root_digest_len);
1287   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1288                             sizeof(AvbHashtreeDescriptor);
1289   uint64_t o = 0;
1290   EXPECT_EQ("foobar",
1291             std::string(reinterpret_cast<const char*>(desc_end + o),
1292                         d.partition_name_len));
1293   o += d.partition_name_len;
1294   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1295   o += d.salt_len;
1296   EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1297             mem_to_hexstring(desc_end + o, d.root_digest_len));
1298 
1299   // Check that we correctly generate dm-verity kernel cmdline
1300   // snippets, if requested.
1301   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1302   EXPECT_COMMAND(0,
1303                  "./avbtool make_vbmeta_image "
1304                  "--output %s "
1305                  "--setup_rootfs_from_kernel %s "
1306                  "--algorithm SHA256_RSA2048 "
1307                  "--key test/data/testkey_rsa2048.pem "
1308                  "--internal_release_string \"\"",
1309                  vbmeta_dmv_path.value().c_str(),
1310                  rootfs_path.value().c_str());
1311 
1312   ASSERT_EQ(
1313       "Minimum libavb version:   1.0\n"
1314       "Header Block:             256 bytes\n"
1315       "Authentication Block:     320 bytes\n"
1316       "Auxiliary Block:          960 bytes\n"
1317       "Algorithm:                SHA256_RSA2048\n"
1318       "Rollback Index:           0\n"
1319       "Flags:                    0\n"
1320       "Release String:           ''\n"
1321       "Descriptors:\n"
1322       "    Kernel Cmdline descriptor:\n"
1323       "      Flags:                 1\n"
1324       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1325       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1326       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1327       "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
1328       "use_fec_from_device "
1329       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 261 "
1330       "fec_start 261\" root=/dev/dm-0'\n"
1331       "    Kernel Cmdline descriptor:\n"
1332       "      Flags:                 2\n"
1333       "      Kernel Cmdline:        "
1334       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1335       InfoImage(vbmeta_dmv_path));
1336 
1337   // Check that the footer is correctly erased and the hashtree and
1338   // FEC data remains. The constant 1085440 is used because it's where
1339   // the FEC data ends (it's at offset 1069056 and size 16384).
1340   EXPECT_COMMAND(0,
1341                  "./avbtool erase_footer --image %s --keep_hashtree",
1342                  rootfs_path.value().c_str());
1343   int64_t erased_footer_file_size;
1344   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1345   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1085440UL);
1346 }
1347 
TEST_F(AvbToolTest,AddHashtreeFooterFEC)1348 TEST_F(AvbToolTest, AddHashtreeFooterFEC) {
1349   AddHashtreeFooterFECTest(false);
1350 }
1351 
TEST_F(AvbToolTest,AddHashtreeFooterFECSparse)1352 TEST_F(AvbToolTest, AddHashtreeFooterFECSparse) {
1353   AddHashtreeFooterFECTest(true);
1354 }
1355 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSize)1356 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSize) {
1357   const size_t partition_size = 10 * 1024 * 1024;
1358   base::FilePath output_path = testdir_.Append("max_size.txt");
1359 
1360   EXPECT_COMMAND(0,
1361                  "./avbtool add_hashtree_footer "
1362                  "--partition_size %zd --calc_max_image_size "
1363                  "--do_not_generate_fec > %s",
1364                  partition_size,
1365                  output_path.value().c_str());
1366   std::string max_image_size_data;
1367   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1368   EXPECT_EQ("10330112\n", max_image_size_data);
1369   size_t max_image_size = atoll(max_image_size_data.c_str());
1370 
1371   // Hashtree and metadata takes up 152 KiB - compare to below with
1372   // FEC which is 244 KiB.
1373   EXPECT_EQ(152 * 1024ULL, partition_size - max_image_size);
1374 
1375   // Check that we can add a hashtree with an image this size for such
1376   // a partition size.
1377   base::FilePath system_path = GenerateImage("system", max_image_size);
1378   EXPECT_COMMAND(0,
1379                  "./avbtool add_hashtree_footer"
1380                  " --image %s"
1381                  " --partition_name system"
1382                  " --partition_size %zd"
1383                  " --salt deadbeef"
1384                  " --algorithm SHA512_RSA4096 "
1385                  " --key test/data/testkey_rsa4096.pem"
1386                  " --internal_release_string \"\" "
1387                  "--do_not_generate_fec",
1388                  system_path.value().c_str(),
1389                  partition_size);
1390 }
1391 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSizeWithFEC)1392 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) {
1393   const size_t partition_size = 10 * 1024 * 1024;
1394   base::FilePath output_path = testdir_.Append("max_size.txt");
1395 
1396   EXPECT_COMMAND(0,
1397                  "./avbtool add_hashtree_footer "
1398                  "--partition_size %zd --calc_max_image_size > %s",
1399                  partition_size,
1400                  output_path.value().c_str());
1401   std::string max_image_size_data;
1402   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1403   EXPECT_EQ("10235904\n", max_image_size_data);
1404   size_t max_image_size = atoll(max_image_size_data.c_str());
1405 
1406   // Hashtree, FEC codes, and metadata takes up 244 KiB - compare to
1407   // above wihtout FEC which is 152 KiB.
1408   EXPECT_EQ(244 * 1024ULL, partition_size - max_image_size);
1409 
1410   // Check that we can add a hashtree with an image this size for such
1411   // a partition size.
1412   base::FilePath system_path = GenerateImage("system", max_image_size);
1413   EXPECT_COMMAND(0,
1414                  "./avbtool add_hashtree_footer"
1415                  " --image %s"
1416                  " --partition_name system"
1417                  " --partition_size %zd"
1418                  " --salt deadbeef"
1419                  " --algorithm SHA512_RSA4096 "
1420                  " --key test/data/testkey_rsa4096.pem"
1421                  " --internal_release_string \"\"",
1422                  system_path.value().c_str(),
1423                  partition_size);
1424 }
1425 
TEST_F(AvbToolTest,AddHashtreeFooterWithPersistentDigest)1426 TEST_F(AvbToolTest, AddHashtreeFooterWithPersistentDigest) {
1427   size_t partition_size = 10 * 1024 * 1024;
1428   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1429   EXPECT_COMMAND(0,
1430                  "./avbtool add_hashtree_footer --salt d00df00d "
1431                  "--hash_algorithm sha256 --image %s "
1432                  "--partition_size %d --partition_name foobar "
1433                  "--algorithm SHA256_RSA2048 "
1434                  "--key test/data/testkey_rsa2048.pem "
1435                  "--internal_release_string \"\" "
1436                  "--use_persistent_digest",
1437                  path.value().c_str(),
1438                  (int)partition_size);
1439   // There are two important bits here specific to --use_persistent_digest:
1440   //   Minimum libavb version = 1.1
1441   //   Hashtree descriptor -> Root Digest = (empty)
1442   ASSERT_EQ(
1443       "Footer version:           1.0\n"
1444       "Image size:               10485760 bytes\n"
1445       "Original image size:      5242880 bytes\n"
1446       "VBMeta offset:            5337088\n"
1447       "VBMeta size:              1344 bytes\n"
1448       "--\n"
1449       "Minimum libavb version:   1.1\n"
1450       "Header Block:             256 bytes\n"
1451       "Authentication Block:     320 bytes\n"
1452       "Auxiliary Block:          768 bytes\n"
1453       "Algorithm:                SHA256_RSA2048\n"
1454       "Rollback Index:           0\n"
1455       "Flags:                    0\n"
1456       "Release String:           ''\n"
1457       "Descriptors:\n"
1458       "    Hashtree descriptor:\n"
1459       "      Version of dm-verity:  1\n"
1460       "      Image Size:            5242880 bytes\n"
1461       "      Tree Offset:           5242880\n"
1462       "      Tree Size:             45056 bytes\n"
1463       "      Data Block Size:       4096 bytes\n"
1464       "      Hash Block Size:       4096 bytes\n"
1465       "      FEC num roots:         2\n"
1466       "      FEC offset:            5287936\n"
1467       "      FEC size:              49152 bytes\n"
1468       "      Hash Algorithm:        sha256\n"
1469       "      Partition Name:        foobar\n"
1470       "      Salt:                  d00df00d\n"
1471       "      Root Digest:           \n"
1472       "      Flags:                 0\n",
1473       InfoImage(path));
1474 }
1475 
TEST_F(AvbToolTest,AddHashtreeFooterWithNoAB)1476 TEST_F(AvbToolTest, AddHashtreeFooterWithNoAB) {
1477   size_t partition_size = 10 * 1024 * 1024;
1478   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1479   EXPECT_COMMAND(0,
1480                  "./avbtool add_hashtree_footer --salt d00df00d "
1481                  "--hash_algorithm sha256 --image %s "
1482                  "--partition_size %d --partition_name foobar "
1483                  "--algorithm SHA256_RSA2048 "
1484                  "--key test/data/testkey_rsa2048.pem "
1485                  "--internal_release_string \"\" "
1486                  "--do_not_use_ab",
1487                  path.value().c_str(),
1488                  (int)partition_size);
1489   // There are two important bits here we're expecting with --do_not_use_ab:
1490   //   Minimum libavb version = 1.1
1491   //   Hashtree descriptor -> Flags = 1
1492   ASSERT_EQ(
1493       "Footer version:           1.0\n"
1494       "Image size:               10485760 bytes\n"
1495       "Original image size:      5242880 bytes\n"
1496       "VBMeta offset:            5337088\n"
1497       "VBMeta size:              1344 bytes\n"
1498       "--\n"
1499       "Minimum libavb version:   1.1\n"
1500       "Header Block:             256 bytes\n"
1501       "Authentication Block:     320 bytes\n"
1502       "Auxiliary Block:          768 bytes\n"
1503       "Algorithm:                SHA256_RSA2048\n"
1504       "Rollback Index:           0\n"
1505       "Flags:                    0\n"
1506       "Release String:           ''\n"
1507       "Descriptors:\n"
1508       "    Hashtree descriptor:\n"
1509       "      Version of dm-verity:  1\n"
1510       "      Image Size:            5242880 bytes\n"
1511       "      Tree Offset:           5242880\n"
1512       "      Tree Size:             45056 bytes\n"
1513       "      Data Block Size:       4096 bytes\n"
1514       "      Hash Block Size:       4096 bytes\n"
1515       "      FEC num roots:         2\n"
1516       "      FEC offset:            5287936\n"
1517       "      FEC size:              49152 bytes\n"
1518       "      Hash Algorithm:        sha256\n"
1519       "      Partition Name:        foobar\n"
1520       "      Salt:                  d00df00d\n"
1521       "      Root Digest:           "
1522       "d0e31526f5a3f8e3f59acf726bd31ae7861ee78f9baa9195356bf479c6f9119d\n"
1523       "      Flags:                 1\n",
1524       InfoImage(path));
1525 }
1526 
TEST_F(AvbToolTest,AddHashtreeFooterWithPersistentDigestAndNoAB)1527 TEST_F(AvbToolTest, AddHashtreeFooterWithPersistentDigestAndNoAB) {
1528   size_t partition_size = 10 * 1024 * 1024;
1529   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1530   EXPECT_COMMAND(0,
1531                  "./avbtool add_hashtree_footer --salt d00df00d "
1532                  "--hash_algorithm sha256 --image %s "
1533                  "--partition_size %d --partition_name foobar "
1534                  "--algorithm SHA256_RSA2048 "
1535                  "--key test/data/testkey_rsa2048.pem "
1536                  "--internal_release_string \"\" "
1537                  "--use_persistent_digest --do_not_use_ab",
1538                  path.value().c_str(),
1539                  (int)partition_size);
1540   // There are three important bits specific to these flags:
1541   //   Minimum libavb version = 1.1
1542   //   Hashtree descriptor -> Root Digest = (empty)
1543   //   Hashtree descriptor -> Flags = 1
1544   ASSERT_EQ(
1545       "Footer version:           1.0\n"
1546       "Image size:               10485760 bytes\n"
1547       "Original image size:      5242880 bytes\n"
1548       "VBMeta offset:            5337088\n"
1549       "VBMeta size:              1344 bytes\n"
1550       "--\n"
1551       "Minimum libavb version:   1.1\n"
1552       "Header Block:             256 bytes\n"
1553       "Authentication Block:     320 bytes\n"
1554       "Auxiliary Block:          768 bytes\n"
1555       "Algorithm:                SHA256_RSA2048\n"
1556       "Rollback Index:           0\n"
1557       "Flags:                    0\n"
1558       "Release String:           ''\n"
1559       "Descriptors:\n"
1560       "    Hashtree descriptor:\n"
1561       "      Version of dm-verity:  1\n"
1562       "      Image Size:            5242880 bytes\n"
1563       "      Tree Offset:           5242880\n"
1564       "      Tree Size:             45056 bytes\n"
1565       "      Data Block Size:       4096 bytes\n"
1566       "      Hash Block Size:       4096 bytes\n"
1567       "      FEC num roots:         2\n"
1568       "      FEC offset:            5287936\n"
1569       "      FEC size:              49152 bytes\n"
1570       "      Hash Algorithm:        sha256\n"
1571       "      Partition Name:        foobar\n"
1572       "      Salt:                  d00df00d\n"
1573       "      Root Digest:           \n"
1574       "      Flags:                 1\n",
1575       InfoImage(path));
1576 }
1577 
TEST_F(AvbToolTest,KernelCmdlineDescriptor)1578 TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
1579   base::FilePath vbmeta_path =
1580       testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
1581 
1582   EXPECT_COMMAND(0,
1583                  "./avbtool make_vbmeta_image "
1584                  "--output %s "
1585                  "--kernel_cmdline 'foo bar baz' "
1586                  "--kernel_cmdline 'second cmdline' "
1587                  "--algorithm SHA256_RSA2048 "
1588                  "--key test/data/testkey_rsa2048.pem "
1589                  "--internal_release_string \"\"",
1590                  vbmeta_path.value().c_str());
1591 
1592   ASSERT_EQ(
1593       "Minimum libavb version:   1.0\n"
1594       "Header Block:             256 bytes\n"
1595       "Authentication Block:     320 bytes\n"
1596       "Auxiliary Block:          640 bytes\n"
1597       "Algorithm:                SHA256_RSA2048\n"
1598       "Rollback Index:           0\n"
1599       "Flags:                    0\n"
1600       "Release String:           ''\n"
1601       "Descriptors:\n"
1602       "    Kernel Cmdline descriptor:\n"
1603       "      Flags:                 0\n"
1604       "      Kernel Cmdline:        'foo bar baz'\n"
1605       "    Kernel Cmdline descriptor:\n"
1606       "      Flags:                 0\n"
1607       "      Kernel Cmdline:        'second cmdline'\n",
1608       InfoImage(vbmeta_path));
1609 
1610   // Now check the VBMeta image.
1611   std::string image_data;
1612   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1613 
1614   const uint8_t* vbmeta_data =
1615       reinterpret_cast<const uint8_t*>(image_data.data());
1616   const size_t vbmeta_size = image_data.length();
1617   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1618             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1619 
1620   // Collect all descriptors.
1621   std::vector<const AvbDescriptor*> descriptors;
1622   avb_descriptor_foreach(
1623       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1624 
1625   // We should have two descriptors - check them.
1626   EXPECT_EQ(2UL, descriptors.size());
1627   AvbKernelCmdlineDescriptor d;
1628   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1629             avb_be64toh(descriptors[0]->tag));
1630   EXPECT_NE(
1631       0,
1632       avb_kernel_cmdline_descriptor_validate_and_byteswap(
1633           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]),
1634           &d));
1635   EXPECT_EQ("foo bar baz",
1636             std::string(reinterpret_cast<const char*>(descriptors[0]) +
1637                             sizeof(AvbKernelCmdlineDescriptor),
1638                         d.kernel_cmdline_length));
1639   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1640             avb_be64toh(descriptors[1]->tag));
1641   EXPECT_NE(
1642       0,
1643       avb_kernel_cmdline_descriptor_validate_and_byteswap(
1644           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]),
1645           &d));
1646   EXPECT_EQ("second cmdline",
1647             std::string(reinterpret_cast<const char*>(descriptors[1]) +
1648                             sizeof(AvbKernelCmdlineDescriptor),
1649                         d.kernel_cmdline_length));
1650 }
1651 
TEST_F(AvbToolTest,AddHashFooterSmallImageWithExternalVbmeta)1652 TEST_F(AvbToolTest, AddHashFooterSmallImageWithExternalVbmeta) {
1653   const size_t image_size = 37;
1654   const size_t partition_size = 20 * 4096;
1655 
1656   std::vector<uint8_t> image(image_size, 0);
1657   for (size_t n = 0; n < image_size; n++) {
1658     image[n] = uint8_t(n);
1659   }
1660 
1661   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
1662   base::FilePath image_path = testdir_.Append("kernel.bin");
1663   EXPECT_EQ(image_size,
1664             static_cast<const size_t>(
1665                 base::WriteFile(image_path,
1666                                 reinterpret_cast<const char*>(image.data()),
1667                                 image.size())));
1668   EXPECT_COMMAND(0,
1669                  "./avbtool add_hash_footer --salt d00df00d "
1670                  "--hash_algorithm sha256 --image %s "
1671                  "--partition_size %zu --partition_name kernel "
1672                  "--algorithm SHA256_RSA2048 "
1673                  "--key test/data/testkey_rsa2048.pem "
1674                  "--output_vbmeta %s "
1675                  "--do_not_append_vbmeta_image "
1676                  "--internal_release_string \"\"",
1677                  image_path.value().c_str(),
1678                  partition_size,
1679                  ext_vbmeta_path.value().c_str());
1680 
1681   // It is not this unit test's job to check the vbmeta content.
1682 
1683   int64_t file_size;
1684   ASSERT_TRUE(base::GetFileSize(image_path, &file_size));
1685   EXPECT_EQ(static_cast<size_t>(file_size), image_size);
1686 }
1687 
TEST_F(AvbToolTest,IncludeDescriptor)1688 TEST_F(AvbToolTest, IncludeDescriptor) {
1689   base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin");
1690   base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin");
1691   base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
1692 
1693   EXPECT_COMMAND(0,
1694                  "./avbtool make_vbmeta_image "
1695                  "--output %s "
1696                  "--kernel_cmdline 'something' "
1697                  "--prop name:value "
1698                  "--internal_release_string \"\"",
1699                  vbmeta1_path.value().c_str());
1700 
1701   EXPECT_COMMAND(0,
1702                  "./avbtool make_vbmeta_image "
1703                  "--output %s "
1704                  "--prop name2:value2 "
1705                  "--prop name3:value3 "
1706                  "--internal_release_string \"\"",
1707                  vbmeta2_path.value().c_str());
1708 
1709   EXPECT_COMMAND(0,
1710                  "./avbtool make_vbmeta_image "
1711                  "--output %s "
1712                  "--prop name4:value4 "
1713                  "--include_descriptors_from_image %s "
1714                  "--include_descriptors_from_image %s "
1715                  "--internal_release_string \"\"",
1716                  vbmeta3_path.value().c_str(),
1717                  vbmeta1_path.value().c_str(),
1718                  vbmeta2_path.value().c_str());
1719 
1720   ASSERT_EQ(
1721       "Minimum libavb version:   1.0\n"
1722       "Header Block:             256 bytes\n"
1723       "Authentication Block:     0 bytes\n"
1724       "Auxiliary Block:          256 bytes\n"
1725       "Algorithm:                NONE\n"
1726       "Rollback Index:           0\n"
1727       "Flags:                    0\n"
1728       "Release String:           ''\n"
1729       "Descriptors:\n"
1730       "    Prop: name4 -> 'value4'\n"
1731       "    Prop: name -> 'value'\n"
1732       "    Kernel Cmdline descriptor:\n"
1733       "      Flags:                 0\n"
1734       "      Kernel Cmdline:        'something'\n"
1735       "    Prop: name2 -> 'value2'\n"
1736       "    Prop: name3 -> 'value3'\n",
1737       InfoImage(vbmeta3_path));
1738 }
1739 
TEST_F(AvbToolTest,ChainedPartition)1740 TEST_F(AvbToolTest, ChainedPartition) {
1741   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1742 
1743   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1744 
1745   EXPECT_COMMAND(
1746       0,
1747       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1748       " --output %s",
1749       pk_path.value().c_str());
1750 
1751   EXPECT_COMMAND(
1752       0,
1753       "./avbtool make_vbmeta_image "
1754       "--output %s "
1755       "--chain_partition system:1:%s "
1756       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1757       "--internal_release_string \"\"",
1758       vbmeta_path.value().c_str(),
1759       pk_path.value().c_str());
1760 
1761   ASSERT_EQ(
1762       "Minimum libavb version:   1.0\n"
1763       "Header Block:             256 bytes\n"
1764       "Authentication Block:     320 bytes\n"
1765       "Auxiliary Block:          1152 bytes\n"
1766       "Algorithm:                SHA256_RSA2048\n"
1767       "Rollback Index:           0\n"
1768       "Flags:                    0\n"
1769       "Release String:           ''\n"
1770       "Descriptors:\n"
1771       "    Chain Partition descriptor:\n"
1772       "      Partition Name:          system\n"
1773       "      Rollback Index Location: 1\n"
1774       "      Public key (sha1):       "
1775       "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n",
1776       InfoImage(vbmeta_path));
1777 
1778   // Now check the VBMeta image.
1779   std::string image_data;
1780   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1781 
1782   const uint8_t* vbmeta_data =
1783       reinterpret_cast<const uint8_t*>(image_data.data());
1784   const size_t vbmeta_size = image_data.length();
1785   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1786             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1787 
1788   // Collect all descriptors.
1789   std::vector<const AvbDescriptor*> descriptors;
1790   avb_descriptor_foreach(
1791       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1792 
1793   // We should have one descriptor - check it.
1794   EXPECT_EQ(1UL, descriptors.size());
1795 
1796   std::string pk_data;
1797   ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data));
1798 
1799   AvbChainPartitionDescriptor d;
1800   EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
1801             avb_be64toh(descriptors[0]->tag));
1802   EXPECT_NE(
1803       0,
1804       avb_chain_partition_descriptor_validate_and_byteswap(
1805           reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]),
1806           &d));
1807   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1808                             sizeof(AvbChainPartitionDescriptor);
1809   uint64_t o = 0;
1810   EXPECT_EQ("system",
1811             std::string(reinterpret_cast<const char*>(desc_end + o),
1812                         d.partition_name_len));
1813   o += d.partition_name_len;
1814   EXPECT_EQ(pk_data,
1815             std::string(reinterpret_cast<const char*>(descriptors[0]) +
1816                             sizeof(AvbChainPartitionDescriptor) + o,
1817                         d.public_key_len));
1818 }
1819 
TEST_F(AvbToolTest,ChainedPartitionNoLocationCollision)1820 TEST_F(AvbToolTest, ChainedPartitionNoLocationCollision) {
1821   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1822 
1823   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1824 
1825   EXPECT_COMMAND(
1826       0,
1827       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1828       " --output %s",
1829       pk_path.value().c_str());
1830 
1831   // Check that avbtool bails if the same Rollback Index Location is
1832   // used for multiple chained partitions.
1833   EXPECT_COMMAND(
1834       1,
1835       "./avbtool make_vbmeta_image "
1836       "--output %s "
1837       "--chain_partition system:1:%s "
1838       "--chain_partition other:1:%s "
1839       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1840       "--internal_release_string \"\"",
1841       vbmeta_path.value().c_str(),
1842       pk_path.value().c_str(),
1843       pk_path.value().c_str());
1844 }
1845 
TEST_F(AvbToolTest,AppendVBMetaImage)1846 TEST_F(AvbToolTest, AppendVBMetaImage) {
1847   size_t boot_size = 5 * 1024 * 1024;
1848   size_t boot_partition_size = 32 * 1024 * 1024;
1849   base::FilePath boot_path = GenerateImage("boot", boot_size);
1850 
1851   GenerateVBMetaImage("vbmeta.img",
1852                       "SHA256_RSA2048",
1853                       0,
1854                       base::FilePath("test/data/testkey_rsa2048.pem"),
1855                       std::string("--append_to_release_string \"\" "
1856                                   "--kernel_cmdline foo"));
1857 
1858   EXPECT_COMMAND(0,
1859                  "./avbtool append_vbmeta_image "
1860                  "--image %s "
1861                  "--partition_size %d "
1862                  "--vbmeta_image %s ",
1863                  boot_path.value().c_str(),
1864                  (int)boot_partition_size,
1865                  vbmeta_image_path_.value().c_str());
1866 
1867   std::string vbmeta_contents = InfoImage(vbmeta_image_path_);
1868   std::string boot_contents = InfoImage(boot_path);
1869 
1870   // Check that boot.img has the same vbmeta blob as from vbmeta.img -
1871   // we do this by inspecting 'avbtool info_image' output combined
1872   // with the known footer location given boot.img has 5 MiB known
1873   // content and the partition size is 32 MiB.
1874   ASSERT_EQ(
1875       "Minimum libavb version:   1.0\n"
1876       "Header Block:             256 bytes\n"
1877       "Authentication Block:     320 bytes\n"
1878       "Auxiliary Block:          576 bytes\n"
1879       "Algorithm:                SHA256_RSA2048\n"
1880       "Rollback Index:           0\n"
1881       "Flags:                    0\n"
1882       "Release String:           'avbtool 1.1.0 '\n"
1883       "Descriptors:\n"
1884       "    Kernel Cmdline descriptor:\n"
1885       "      Flags:                 0\n"
1886       "      Kernel Cmdline:        'foo'\n",
1887       vbmeta_contents);
1888   std::string known_footer =
1889       "Footer version:           1.0\n"
1890       "Image size:               33554432 bytes\n"
1891       "Original image size:      5242880 bytes\n"
1892       "VBMeta offset:            5242880\n"
1893       "VBMeta size:              1152 bytes\n"
1894       "--\n";
1895   ASSERT_EQ(known_footer + vbmeta_contents, boot_contents);
1896 
1897   // Also verify that the blobs are the same, bit for bit.
1898   base::File f =
1899       base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
1900   std::vector<uint8_t> loaded_vbmeta;
1901   loaded_vbmeta.resize(1152);
1902   EXPECT_EQ(
1903       f.Read(
1904           5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152),
1905       1152);
1906   EXPECT_EQ(vbmeta_image_, loaded_vbmeta);
1907 }
1908 
TEST_F(AvbToolTest,SigningHelperBasic)1909 TEST_F(AvbToolTest, SigningHelperBasic) {
1910   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1911   base::FilePath signing_helper_test_path =
1912       testdir_.Append("signing_helper_test");
1913   EXPECT_COMMAND(
1914       0,
1915       "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1916       "--output %s "
1917       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1918       "--signing_helper test/avbtool_signing_helper_test.py "
1919       "--internal_release_string \"\"",
1920       signing_helper_test_path.value().c_str(),
1921       vbmeta_path.value().c_str());
1922 
1923   // Now check the value in test file.
1924   std::string value;
1925   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1926   EXPECT_EQ("DONE", value);
1927 }
1928 
TEST_F(AvbToolTest,SigningHelperWithFilesBasic)1929 TEST_F(AvbToolTest, SigningHelperWithFilesBasic) {
1930   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1931   base::FilePath signing_helper_test_path =
1932       testdir_.Append("signing_helper_test");
1933   EXPECT_COMMAND(
1934       0,
1935       "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1936       "--output %s "
1937       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1938       "--signing_helper_with_files "
1939       "test/avbtool_signing_helper_with_files_test.py "
1940       "--internal_release_string \"\"",
1941       signing_helper_test_path.value().c_str(),
1942       vbmeta_path.value().c_str());
1943 
1944   // Now check the value in test file.
1945   std::string value;
1946   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1947   EXPECT_EQ("DONE", value);
1948 }
1949 
TEST_F(AvbToolTest,SigningHelperReturnError)1950 TEST_F(AvbToolTest, SigningHelperReturnError) {
1951   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1952   EXPECT_COMMAND(
1953       1,
1954       "./avbtool make_vbmeta_image "
1955       "--output %s "
1956       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1957       "--signing_helper test/avbtool_signing_helper_test.py "
1958       "--internal_release_string \"\"",
1959       vbmeta_path.value().c_str());
1960 }
1961 
TEST_F(AvbToolTest,SigningHelperWithFilesReturnError)1962 TEST_F(AvbToolTest, SigningHelperWithFilesReturnError) {
1963   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1964   EXPECT_COMMAND(
1965       1,
1966       "./avbtool make_vbmeta_image "
1967       "--output %s "
1968       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1969       "--signing_helper_with_files "
1970       "test/avbtool_signing_helper_with_files_test.py "
1971       "--internal_release_string \"\"",
1972       vbmeta_path.value().c_str());
1973 }
1974 
TEST_F(AvbToolTest,VerifyImageNoSignature)1975 TEST_F(AvbToolTest, VerifyImageNoSignature) {
1976   GenerateVBMetaImage("vbmeta.img",
1977                       "",  // NONE
1978                       0,
1979                       base::FilePath());
1980 
1981   EXPECT_COMMAND(0,
1982                  "./avbtool verify_image "
1983                  "--image %s ",
1984                  vbmeta_image_path_.value().c_str());
1985 }
1986 
TEST_F(AvbToolTest,VerifyImageValidSignature)1987 TEST_F(AvbToolTest, VerifyImageValidSignature) {
1988   GenerateVBMetaImage("vbmeta.img",
1989                       "SHA256_RSA2048",
1990                       0,
1991                       base::FilePath("test/data/testkey_rsa2048.pem"));
1992 
1993   EXPECT_COMMAND(0,
1994                  "./avbtool verify_image "
1995                  "--image %s ",
1996                  vbmeta_image_path_.value().c_str());
1997 }
1998 
TEST_F(AvbToolTest,VerifyImageCorruptedVBMeta)1999 TEST_F(AvbToolTest, VerifyImageCorruptedVBMeta) {
2000   GenerateVBMetaImage("vbmeta.img",
2001                       "SHA256_RSA2048",
2002                       0,
2003                       base::FilePath("test/data/testkey_rsa2048.pem"));
2004 
2005   // Corrupt four bytes of data in the end of the image. Since the aux
2006   // data is at the end and this data is signed, this will change the
2007   // value of the computed hash.
2008   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2009   EXPECT_EQ(AVB_IO_RESULT_OK,
2010             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2011                                                "vbmeta",
2012                                                -4,  // offset from end
2013                                                sizeof corrupt_data,
2014                                                corrupt_data));
2015 
2016   EXPECT_COMMAND(1,
2017                  "./avbtool verify_image "
2018                  "--image %s ",
2019                  vbmeta_image_path_.value().c_str());
2020 }
2021 
TEST_F(AvbToolTest,VerifyImageOtherKeyMatching)2022 TEST_F(AvbToolTest, VerifyImageOtherKeyMatching) {
2023   GenerateVBMetaImage("vbmeta.img",
2024                       "SHA256_RSA2048",
2025                       0,
2026                       base::FilePath("test/data/testkey_rsa2048.pem"));
2027 
2028   EXPECT_COMMAND(0,
2029                  "./avbtool verify_image "
2030                  "--image %s --key test/data/testkey_rsa2048.pem",
2031                  vbmeta_image_path_.value().c_str());
2032 }
2033 
TEST_F(AvbToolTest,VerifyImageOtherKeyNotMatching)2034 TEST_F(AvbToolTest, VerifyImageOtherKeyNotMatching) {
2035   GenerateVBMetaImage("vbmeta.img",
2036                       "SHA256_RSA2048",
2037                       0,
2038                       base::FilePath("test/data/testkey_rsa2048.pem"));
2039 
2040   EXPECT_COMMAND(1,
2041                  "./avbtool verify_image "
2042                  "--image %s --key test/data/testkey_rsa4096.pem",
2043                  vbmeta_image_path_.value().c_str());
2044 }
2045 
TEST_F(AvbToolTest,VerifyImageBrokenSignature)2046 TEST_F(AvbToolTest, VerifyImageBrokenSignature) {
2047   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2048   base::FilePath signing_helper_test_path =
2049       testdir_.Append("signing_helper_test");
2050 
2051   // Intentionally make the signer generate a wrong signature.
2052   EXPECT_COMMAND(
2053       0,
2054       "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool make_vbmeta_image "
2055       "--output %s "
2056       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2057       "--signing_helper test/avbtool_signing_helper_test.py "
2058       "--internal_release_string \"\"",
2059       vbmeta_path.value().c_str());
2060 
2061   EXPECT_COMMAND(1,
2062                  "./avbtool verify_image "
2063                  "--image %s ",
2064                  vbmeta_path.value().c_str());
2065 }
2066 
2067 // Helper to generate boot.img, unsparse system.img, and vbmeta.img.
GenerateImageWithHashAndHashtreeSetup()2068 void AvbToolTest::GenerateImageWithHashAndHashtreeSetup() {
2069   const size_t boot_partition_size = 16 * 1024 * 1024;
2070   const size_t boot_image_size = 5 * 1024 * 1024;
2071   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
2072   EXPECT_COMMAND(0,
2073                  "./avbtool add_hash_footer"
2074                  " --image %s"
2075                  " --rollback_index 0"
2076                  " --partition_name boot"
2077                  " --partition_size %zd"
2078                  " --salt deadbeef"
2079                  " --internal_release_string \"\"",
2080                  boot_path.value().c_str(),
2081                  boot_partition_size);
2082 
2083   const size_t system_partition_size = 10 * 1024 * 1024;
2084   const size_t system_image_size = 8 * 1024 * 1024;
2085   base::FilePath system_path = GenerateImage("system.img", system_image_size);
2086   EXPECT_COMMAND(0,
2087                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
2088                  "--partition_size %zd --partition_name system "
2089                  "--internal_release_string \"\" ",
2090                  system_path.value().c_str(),
2091                  system_partition_size);
2092 
2093   GenerateVBMetaImage("vbmeta.img",
2094                       "SHA256_RSA2048",
2095                       0,
2096                       base::FilePath("test/data/testkey_rsa2048.pem"),
2097                       base::StringPrintf("--include_descriptors_from_image %s "
2098                                          "--include_descriptors_from_image %s",
2099                                          boot_path.value().c_str(),
2100                                          system_path.value().c_str()));
2101 }
2102 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtree)2103 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) {
2104   GenerateImageWithHashAndHashtreeSetup();
2105 
2106   // Do two checks - one for system.img not sparse, and one where it
2107   // is sparse.
2108   for (int n = 0; n < 2; n++) {
2109     EXPECT_COMMAND(0,
2110                    "./avbtool verify_image "
2111                    "--image %s ",
2112                    vbmeta_image_path_.value().c_str());
2113     if (n == 0) {
2114       EXPECT_COMMAND(0,
2115                      "img2simg %s %s.sparse",
2116                      testdir_.Append("system.img").value().c_str(),
2117                      testdir_.Append("system.img").value().c_str());
2118       EXPECT_COMMAND(0,
2119                      "mv %s.sparse %s",
2120                      testdir_.Append("system.img").value().c_str(),
2121                      testdir_.Append("system.img").value().c_str());
2122     }
2123   }
2124 }
2125 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHash)2126 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) {
2127   GenerateImageWithHashAndHashtreeSetup();
2128 
2129   // Corrupt four bytes of data in the middle of boot.img.
2130   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2131   EXPECT_EQ(AVB_IO_RESULT_OK,
2132             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2133                                                "boot",
2134                                                105 * 1024,  // offset from start
2135                                                sizeof corrupt_data,
2136                                                corrupt_data));
2137 
2138   EXPECT_COMMAND(1,
2139                  "./avbtool verify_image "
2140                  "--image %s ",
2141                  vbmeta_image_path_.value().c_str());
2142 }
2143 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHashtree)2144 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHashtree) {
2145   GenerateImageWithHashAndHashtreeSetup();
2146 
2147   // Corrupt four bytes of data in the middle of system.img.
2148   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2149   EXPECT_EQ(AVB_IO_RESULT_OK,
2150             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2151                                                "system",
2152                                                123 * 1024,  // offset from start
2153                                                sizeof corrupt_data,
2154                                                corrupt_data));
2155 
2156   // Do two checks - one for system.img not sparse, and one where it
2157   // is sparse.
2158   for (int n = 0; n < 2; n++) {
2159     EXPECT_COMMAND(1,
2160                    "./avbtool verify_image "
2161                    "--image %s ",
2162                    vbmeta_image_path_.value().c_str());
2163     if (n == 0) {
2164       EXPECT_COMMAND(0,
2165                      "img2simg %s %s.sparse",
2166                      testdir_.Append("system.img").value().c_str(),
2167                      testdir_.Append("system.img").value().c_str());
2168       EXPECT_COMMAND(0,
2169                      "mv %s.sparse %s",
2170                      testdir_.Append("system.img").value().c_str(),
2171                      testdir_.Append("system.img").value().c_str());
2172     }
2173   }
2174 }
2175 
TEST_F(AvbToolTest,VerifyImageChainPartition)2176 TEST_F(AvbToolTest, VerifyImageChainPartition) {
2177   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
2178   EXPECT_COMMAND(
2179       0,
2180       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
2181       " --output %s",
2182       pk4096_path.value().c_str());
2183 
2184   base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey");
2185   EXPECT_COMMAND(
2186       0,
2187       "./avbtool extract_public_key --key test/data/testkey_rsa8192.pem"
2188       " --output %s",
2189       pk8192_path.value().c_str());
2190 
2191   GenerateVBMetaImage("vbmeta.img",
2192                       "SHA256_RSA2048",
2193                       0,
2194                       base::FilePath("test/data/testkey_rsa2048.pem"),
2195                       base::StringPrintf("--chain_partition system:1:%s ",
2196                                          pk4096_path.value().c_str()));
2197 
2198   // Should not fail (name, rollback_index, contents all correct).
2199   EXPECT_COMMAND(0,
2200                  "./avbtool verify_image "
2201                  "--image %s "
2202                  "--expected_chain_partition system:1:%s",
2203                  vbmeta_image_path_.value().c_str(),
2204                  pk4096_path.value().c_str());
2205 
2206   // Should fail because we didn't use --expected_chain_partition.
2207   EXPECT_COMMAND(1,
2208                  "./avbtool verify_image "
2209                  "--image %s ",
2210                  vbmeta_image_path_.value().c_str());
2211 
2212   // Should fail because partition name is wrong.
2213   EXPECT_COMMAND(1,
2214                  "./avbtool verify_image "
2215                  "--image %s "
2216                  "--expected_chain_partition xyz:1:%s",
2217                  vbmeta_image_path_.value().c_str(),
2218                  pk4096_path.value().c_str());
2219 
2220   // Should fail because rollback index location is wrong.
2221   EXPECT_COMMAND(1,
2222                  "./avbtool verify_image "
2223                  "--image %s "
2224                  "--expected_chain_partition system:2:%s",
2225                  vbmeta_image_path_.value().c_str(),
2226                  pk4096_path.value().c_str());
2227 
2228   // Should fail because public key blob is wrong.
2229   EXPECT_COMMAND(1,
2230                  "./avbtool verify_image "
2231                  "--image %s "
2232                  "--expected_chain_partition system:1:%s",
2233                  vbmeta_image_path_.value().c_str(),
2234                  pk8192_path.value().c_str());
2235 }
2236 
2237 class AvbToolTest_PrintRequiredVersion : public AvbToolTest {
2238  protected:
2239   const char* kOutputFile = "versions.txt";
2240 
PrintWithAddHashFooter(int target_required_minor_version)2241   void PrintWithAddHashFooter(int target_required_minor_version) {
2242     std::string extra_args;
2243     if (target_required_minor_version == 1) {
2244       // The --do_not_use_ab option will require 1.1.
2245       extra_args = "--do_not_use_ab";
2246     }
2247     const size_t boot_partition_size = 16 * 1024 * 1024;
2248     base::FilePath output_path = testdir_.Append(kOutputFile);
2249     EXPECT_COMMAND(0,
2250                    "./avbtool add_hash_footer"
2251                    " --rollback_index 0"
2252                    " --partition_name boot"
2253                    " --partition_size %zd"
2254                    " --salt deadbeef"
2255                    " --internal_release_string \"\""
2256                    " %s"
2257                    " --print_required_libavb_version > %s",
2258                    boot_partition_size,
2259                    extra_args.c_str(),
2260                    output_path.value().c_str());
2261     CheckVersion(target_required_minor_version);
2262   }
2263 
PrintWithAddHashtreeFooter(int target_required_minor_version)2264   void PrintWithAddHashtreeFooter(int target_required_minor_version) {
2265     std::string extra_args;
2266     if (target_required_minor_version == 1) {
2267       // The --do_not_use_ab option will require 1.1.
2268       extra_args = "--do_not_use_ab";
2269     }
2270     const size_t system_partition_size = 10 * 1024 * 1024;
2271     base::FilePath output_path = testdir_.Append(kOutputFile);
2272     EXPECT_COMMAND(0,
2273                    "./avbtool add_hashtree_footer --salt d00df00d "
2274                    "--partition_size %zd --partition_name system "
2275                    "--internal_release_string \"\""
2276                    " %s"
2277                    " --print_required_libavb_version > %s",
2278                    system_partition_size,
2279                    extra_args.c_str(),
2280                    output_path.value().c_str());
2281     CheckVersion(target_required_minor_version);
2282   }
2283 
PrintWithMakeVbmetaImage(int target_required_minor_version)2284   void PrintWithMakeVbmetaImage(int target_required_minor_version) {
2285     std::string extra_args;
2286     if (target_required_minor_version == 1) {
2287       // An included descriptor that requires 1.1 will require 1.1 for vbmeta.
2288       const size_t boot_partition_size = 16 * 1024 * 1024;
2289       base::FilePath image_path = GenerateImage("test_print_version", 1024);
2290       EXPECT_COMMAND(0,
2291                      "./avbtool add_hash_footer --salt d00df00d "
2292                      "--hash_algorithm sha256 --image %s "
2293                      "--partition_size %d --partition_name foobar "
2294                      "--algorithm SHA256_RSA2048 "
2295                      "--key test/data/testkey_rsa2048.pem "
2296                      "--internal_release_string \"\" "
2297                      "--do_not_use_ab",
2298                      image_path.value().c_str(),
2299                      (int)boot_partition_size);
2300       extra_args = base::StringPrintf("--include_descriptors_from_image %s",
2301                                       image_path.value().c_str());
2302     }
2303     base::FilePath output_path = testdir_.Append(kOutputFile);
2304     EXPECT_COMMAND(0,
2305                    "./avbtool make_vbmeta_image "
2306                    "--algorithm SHA256_RSA2048 "
2307                    "--key test/data/testkey_rsa2048.pem "
2308                    "--internal_release_string \"\""
2309                    " %s"
2310                    " --print_required_libavb_version > %s",
2311                    extra_args.c_str(),
2312                    output_path.value().c_str());
2313     CheckVersion(target_required_minor_version);
2314   }
2315 
CheckVersion(int expected_required_minor_version)2316   void CheckVersion(int expected_required_minor_version) {
2317     base::FilePath output_path = testdir_.Append(kOutputFile);
2318     std::string output;
2319     ASSERT_TRUE(base::ReadFileToString(output_path, &output));
2320     EXPECT_EQ(output,
2321               base::StringPrintf("1.%d\n", expected_required_minor_version));
2322   }
2323 };
2324 
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_0)2325 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_0) {
2326   PrintWithAddHashFooter(0);
2327 }
2328 
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_1)2329 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_1) {
2330   PrintWithAddHashFooter(1);
2331 }
2332 
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_0)2333 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_0) {
2334   PrintWithAddHashtreeFooter(0);
2335 }
2336 
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_1)2337 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_1) {
2338   PrintWithAddHashtreeFooter(1);
2339 }
2340 
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_0)2341 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_0) {
2342   PrintWithMakeVbmetaImage(0);
2343 }
2344 
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_1)2345 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_1) {
2346   PrintWithMakeVbmetaImage(1);
2347 }
2348 
TEST_F(AvbToolTest,MakeAtxPikCertificate)2349 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
2350   base::FilePath subject_path = testdir_.Append("tmp_subject");
2351   ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
2352   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
2353   EXPECT_COMMAND(
2354       0,
2355       "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
2356       pubkey_path.value().c_str());
2357 
2358   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
2359   EXPECT_COMMAND(0,
2360                  "./avbtool make_atx_certificate"
2361                  " --subject %s"
2362                  " --subject_key %s"
2363                  " --subject_key_version 42"
2364                  " --subject_is_intermediate_authority"
2365                  " --authority_key test/data/testkey_atx_prk.pem"
2366                  " --output %s",
2367                  subject_path.value().c_str(),
2368                  pubkey_path.value().c_str(),
2369                  output_path.value().c_str());
2370 
2371   EXPECT_COMMAND(0,
2372                  "diff test/data/atx_pik_certificate.bin %s",
2373                  output_path.value().c_str());
2374 }
2375 
TEST_F(AvbToolTest,MakeAtxPskCertificate)2376 TEST_F(AvbToolTest, MakeAtxPskCertificate) {
2377   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
2378   EXPECT_COMMAND(
2379       0,
2380       "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
2381       pubkey_path.value().c_str());
2382 
2383   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
2384   EXPECT_COMMAND(0,
2385                  "./avbtool make_atx_certificate"
2386                  " --subject test/data/atx_product_id.bin"
2387                  " --subject_key %s"
2388                  " --subject_key_version 42"
2389                  " --authority_key test/data/testkey_atx_pik.pem"
2390                  " --output %s",
2391                  pubkey_path.value().c_str(),
2392                  output_path.value().c_str());
2393 
2394   EXPECT_COMMAND(0,
2395                  "diff test/data/atx_psk_certificate.bin %s",
2396                  output_path.value().c_str());
2397 }
2398 
TEST_F(AvbToolTest,MakeAtxPermanentAttributes)2399 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) {
2400   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
2401   EXPECT_COMMAND(
2402       0,
2403       "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
2404       pubkey_path.value().c_str());
2405 
2406   base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
2407   EXPECT_COMMAND(0,
2408                  "./avbtool make_atx_permanent_attributes"
2409                  " --root_authority_key %s"
2410                  " --product_id test/data/atx_product_id.bin"
2411                  " --output %s",
2412                  pubkey_path.value().c_str(),
2413                  output_path.value().c_str());
2414 
2415   EXPECT_COMMAND(0,
2416                  "diff test/data/atx_permanent_attributes.bin %s",
2417                  output_path.value().c_str());
2418 }
2419 
TEST_F(AvbToolTest,MakeAtxMetadata)2420 TEST_F(AvbToolTest, MakeAtxMetadata) {
2421   base::FilePath output_path = testdir_.Append("tmp_metadata.bin");
2422 
2423   EXPECT_COMMAND(
2424       0,
2425       "./avbtool make_atx_metadata"
2426       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
2427       " --product_key_certificate test/data/atx_psk_certificate.bin"
2428       " --output %s",
2429       output_path.value().c_str());
2430 
2431   EXPECT_COMMAND(
2432       0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str());
2433 }
2434 
2435 }  // namespace avb
2436