• 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       partition_size,
414       sparse_image ? " (Sparse)" : "");
415 }
416 
AddHashFooterTest(bool sparse_image)417 void AvbToolTest::AddHashFooterTest(bool sparse_image) {
418   const size_t rootfs_size = 1028 * 1024;
419   const size_t partition_size = 1536 * 1024;
420   const size_t resized_partition_size = 1280 * 1024;
421 
422   // Generate a 1028 KiB file with known content. Some content have
423   // been arranged to ensure FILL_DATA segments in the sparse file.
424   std::vector<uint8_t> rootfs;
425   rootfs.resize(rootfs_size);
426   for (size_t n = 0; n < rootfs_size; n++) {
427     if ((n >= 5 * 1000 && n < 105 * 1000) ||
428         (n >= 205 * 1000 && n < 305 * 1000) ||
429         (n >= 505 * 1000 && n < 605 * 1000)) {
430       rootfs[n] = uint8_t(n) & 0x03;
431     } else {
432       rootfs[n] = uint8_t(n);
433     }
434   }
435   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
436   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
437   EXPECT_EQ(rootfs_size,
438             static_cast<const size_t>(
439                 base::WriteFile(rootfs_path,
440                                 reinterpret_cast<const char*>(rootfs.data()),
441                                 rootfs.size())));
442 
443   if (sparse_image) {
444     EXPECT_COMMAND(0,
445                    "mv %s %s.unsparse",
446                    rootfs_path.value().c_str(),
447                    rootfs_path.value().c_str());
448     EXPECT_COMMAND(0,
449                    "img2simg %s.unsparse %s",
450                    rootfs_path.value().c_str(),
451                    rootfs_path.value().c_str());
452     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
453   }
454 
455   /* Do this twice to check that 'add_hash_footer' is idempotent. */
456   for (int n = 0; n < 2; n++) {
457     EXPECT_COMMAND(0,
458                    "./avbtool add_hash_footer --salt d00df00d "
459                    "--hash_algorithm sha256 --image %s "
460                    "--partition_size %d --partition_name foobar "
461                    "--algorithm SHA256_RSA2048 "
462                    "--key test/data/testkey_rsa2048.pem "
463                    "--output_vbmeta %s "
464                    "--internal_release_string \"\"",
465                    rootfs_path.value().c_str(),
466                    (int)partition_size,
467                    ext_vbmeta_path.value().c_str());
468 
469     ASSERT_EQ(AddHashFooterGetExpectedVBMetaInfo(sparse_image, partition_size),
470               InfoImage(rootfs_path));
471 
472     ASSERT_EQ(
473         "Minimum libavb version:   1.0\n"
474         "Header Block:             256 bytes\n"
475         "Authentication Block:     320 bytes\n"
476         "Auxiliary Block:          704 bytes\n"
477         "Algorithm:                SHA256_RSA2048\n"
478         "Rollback Index:           0\n"
479         "Flags:                    0\n"
480         "Release String:           ''\n"
481         "Descriptors:\n"
482         "    Hash descriptor:\n"
483         "      Image Size:            1052672 bytes\n"
484         "      Hash Algorithm:        sha256\n"
485         "      Partition Name:        foobar\n"
486         "      Salt:                  d00df00d\n"
487         "      Digest:                "
488         "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
489         "5e4ed357fbcf58d88d9\n",
490         InfoImage(ext_vbmeta_path));
491   }
492 
493   // Resize the image and check that the only thing that has changed
494   // is where the footer is. First check that resizing to a smaller
495   // size than the original rootfs fails. Then resize to something
496   // larger than the original rootfs but smaller than the current
497   // partition size.
498   EXPECT_COMMAND(1,
499                  "./avbtool resize_image --image %s "
500                  "--partition_size %d",
501                  rootfs_path.value().c_str(),
502                  (int)(rootfs_size - 16 * 1024));
503   EXPECT_COMMAND(0,
504                  "./avbtool resize_image --image %s "
505                  "--partition_size %d",
506                  rootfs_path.value().c_str(),
507                  (int)resized_partition_size);
508   ASSERT_EQ(
509       AddHashFooterGetExpectedVBMetaInfo(sparse_image, resized_partition_size),
510       InfoImage(rootfs_path));
511 
512   if (sparse_image) {
513     EXPECT_COMMAND(0,
514                    "mv %s %s.sparse",
515                    rootfs_path.value().c_str(),
516                    rootfs_path.value().c_str());
517     EXPECT_COMMAND(0,
518                    "simg2img %s.sparse %s",
519                    rootfs_path.value().c_str(),
520                    rootfs_path.value().c_str());
521     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
522   }
523 
524   // Manually calculate the hash to check that it agrees with avbtool.
525   AvbSHA256Ctx hasher_ctx;
526   const uint8_t hasher_salt[4] = {0xd0, 0x0d, 0xf0, 0x0d};
527   avb_sha256_init(&hasher_ctx);
528   avb_sha256_update(&hasher_ctx, hasher_salt, 4);
529   avb_sha256_update(&hasher_ctx, rootfs.data(), rootfs_size);
530   uint8_t* hasher_digest = avb_sha256_final(&hasher_ctx);
531   EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
532             mem_to_hexstring(hasher_digest, AVB_SHA256_DIGEST_SIZE));
533 
534   // Now check that we can find the VBMeta block again from the footer.
535   std::string part_data;
536   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
537 
538   // Check footer contains correct data.
539   AvbFooter f;
540   EXPECT_NE(0,
541             avb_footer_validate_and_byteswap(
542                 reinterpret_cast<const AvbFooter*>(
543                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
544                 &f));
545   EXPECT_EQ(
546       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
547       AVB_FOOTER_MAGIC);
548   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
549   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
550   EXPECT_EQ(1052672UL, f.original_image_size);
551   EXPECT_EQ(1052672UL, f.vbmeta_offset);
552   EXPECT_EQ(1280UL, f.vbmeta_size);
553 
554   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
555   const uint8_t* vbmeta_data =
556       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
557   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
558             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
559 
560   // Collect all descriptors.
561   std::vector<const AvbDescriptor*> descriptors;
562   avb_descriptor_foreach(
563       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
564 
565   // We should only have a single descriptor and it should be a
566   // hash descriptor.
567   EXPECT_EQ(1UL, descriptors.size());
568   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, avb_be64toh(descriptors[0]->tag));
569   AvbHashDescriptor d;
570   EXPECT_NE(
571       0,
572       avb_hash_descriptor_validate_and_byteswap(
573           reinterpret_cast<const AvbHashDescriptor*>(descriptors[0]), &d));
574   EXPECT_EQ(1052672UL, d.image_size);
575   EXPECT_EQ(6UL, d.partition_name_len);
576   EXPECT_EQ(4UL, d.salt_len);
577   EXPECT_EQ(32UL, d.digest_len);
578   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
579                             sizeof(AvbHashDescriptor);
580   uint64_t o = 0;
581   EXPECT_EQ("foobar",
582             std::string(reinterpret_cast<const char*>(desc_end + o),
583                         d.partition_name_len));
584   o += d.partition_name_len;
585   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
586   o += d.salt_len;
587   EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
588             mem_to_hexstring(desc_end + o, d.digest_len));
589 
590   // Check that the footer is correctly erased.
591   EXPECT_COMMAND(
592       0, "./avbtool erase_footer --image %s", rootfs_path.value().c_str());
593   int64_t erased_footer_file_size;
594   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
595   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size);
596 
597   // Check that --do_not_append_vbmeta_image works as intended.
598   EXPECT_COMMAND(0,
599                  "./avbtool add_hash_footer --salt d00df00d "
600                  "--hash_algorithm sha256 --image %s "
601                  "--partition_size %d --partition_name foobar "
602                  "--algorithm SHA256_RSA2048 "
603                  "--key test/data/testkey_rsa2048.pem "
604                  "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
605                  "--internal_release_string \"\"",
606                  rootfs_path.value().c_str(),
607                  (int)partition_size,
608                  ext_vbmeta_path.value().c_str());
609   int64_t file_size;
610   ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
611   EXPECT_EQ(static_cast<size_t>(file_size), rootfs_size);
612   EXPECT_COMMAND(0,
613                  "diff %s %s_2nd_run",
614                  ext_vbmeta_path.value().c_str(),
615                  ext_vbmeta_path.value().c_str());
616 }
617 
TEST_F(AvbToolTest,AddHashFooter)618 TEST_F(AvbToolTest, AddHashFooter) {
619   AddHashFooterTest(false);
620 }
621 
TEST_F(AvbToolTest,AddHashFooterSparse)622 TEST_F(AvbToolTest, AddHashFooterSparse) {
623   AddHashFooterTest(true);
624 }
625 
RemoveLinesStartingWith(const std::string & str,const std::string & prefix)626 static std::string RemoveLinesStartingWith(const std::string& str,
627                                            const std::string& prefix) {
628   std::vector<std::string> lines;
629   std::string ret;
630 
631   lines = base::SplitString(
632       str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
633   for (const std::string& line : lines) {
634     if (!base::StartsWith(line, prefix, base::CompareCase::SENSITIVE)) {
635       ret += line;
636       ret += '\n';
637     }
638   }
639   return ret;
640 }
641 
TEST_F(AvbToolTest,AddHashFooterSparseWithHoleAtTheEnd)642 TEST_F(AvbToolTest, AddHashFooterSparseWithHoleAtTheEnd) {
643   const size_t partition_size = 10 * 1024 * 1024;
644   const size_t metadata_size = 128 * 1024;
645 
646   // It's not enough to run img2simg on a file with a lot of zeroes at
647   // the end since that will turn up as "Fill with value (for value =
648   // 0x00000000)" and not "Don't care". Instead, use make_ext4fs for
649   // this since it will put a big hole (e.g. "Don't care" chunk) at
650   // the end.
651   base::FilePath partition_path = testdir_.Append("partition.bin");
652   EXPECT_COMMAND(0,
653                  "make_ext4fs -s -L test -l %zd %s",
654                  partition_size - metadata_size,
655                  partition_path.value().c_str());
656 
657   EXPECT_COMMAND(0,
658                  "./avbtool add_hash_footer --salt d00df00d "
659                  "--hash_algorithm sha256 --image %s "
660                  "--partition_size %d --partition_name foobar "
661                  "--algorithm SHA256_RSA2048 "
662                  "--key test/data/testkey_rsa2048.pem "
663                  "--internal_release_string \"\"",
664                  partition_path.value().c_str(),
665                  (int)partition_size);
666 
667   // Since we may be using an arbritary version of make_ext4fs
668   // (because of different branches) the contents of the resulting
669   // disk image may slightly change. It's enough to just remove the
670   // "Digest:" line from the output to work around this.
671   std::string info =
672       RemoveLinesStartingWith(InfoImage(partition_path), "      Digest:");
673   ASSERT_EQ(
674       "Footer version:           1.0\n"
675       "Image size:               10485760 bytes\n"
676       "Original image size:      10354688 bytes\n"
677       "VBMeta offset:            10354688\n"
678       "VBMeta size:              1280 bytes\n"
679       "--\n"
680       "Minimum libavb version:   1.0 (Sparse)\n"
681       "Header Block:             256 bytes\n"
682       "Authentication Block:     320 bytes\n"
683       "Auxiliary Block:          704 bytes\n"
684       "Algorithm:                SHA256_RSA2048\n"
685       "Rollback Index:           0\n"
686       "Flags:                    0\n"
687       "Release String:           ''\n"
688       "Descriptors:\n"
689       "    Hash descriptor:\n"
690       "      Image Size:            10354688 bytes\n"
691       "      Hash Algorithm:        sha256\n"
692       "      Partition Name:        foobar\n"
693       "      Salt:                  d00df00d\n",
694       info);
695 
696   EXPECT_COMMAND(0,
697                  "mv %s %s.sparse",
698                  partition_path.value().c_str(),
699                  partition_path.value().c_str());
700   EXPECT_COMMAND(0,
701                  "simg2img %s.sparse %s",
702                  partition_path.value().c_str(),
703                  partition_path.value().c_str());
704   EXPECT_COMMAND(0, "rm -f %s.sparse", partition_path.value().c_str());
705 }
706 
TEST_F(AvbToolTest,AddHashFooterCalcMaxImageSize)707 TEST_F(AvbToolTest, AddHashFooterCalcMaxImageSize) {
708   const size_t partition_size = 10 * 1024 * 1024;
709   base::FilePath output_path = testdir_.Append("max_size.txt");
710 
711   EXPECT_COMMAND(0,
712                  "./avbtool add_hash_footer "
713                  "--partition_size %zd "
714                  "--calc_max_image_size > %s",
715                  partition_size,
716                  output_path.value().c_str());
717   std::string max_image_size_data;
718   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
719   EXPECT_EQ("10416128\n", max_image_size_data);
720   size_t max_image_size = atoll(max_image_size_data.c_str());
721 
722   // Metadata takes up 68 KiB.
723   EXPECT_EQ(68 * 1024ULL, partition_size - max_image_size);
724 
725   // Check that we can add a hash footer for an image this size for
726   // such a partition size.
727   base::FilePath boot_path = GenerateImage("boot", max_image_size);
728   EXPECT_COMMAND(0,
729                  "./avbtool add_hash_footer"
730                  " --image %s"
731                  " --partition_name boot"
732                  " --partition_size %zd"
733                  " --salt deadbeef"
734                  " --algorithm SHA512_RSA4096 "
735                  " --key test/data/testkey_rsa4096.pem"
736                  " --internal_release_string \"\"",
737                  boot_path.value().c_str(),
738                  partition_size);
739 }
740 
AddHashtreeFooterTest(bool sparse_image)741 void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
742   const size_t rootfs_size = 1028 * 1024;
743   const size_t partition_size = 1536 * 1024;
744 
745   // Generate a 1028 KiB file with known content.
746   std::vector<uint8_t> rootfs;
747   rootfs.resize(rootfs_size);
748   for (size_t n = 0; n < rootfs_size; n++)
749     rootfs[n] = uint8_t(n);
750   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
751   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
752   EXPECT_EQ(rootfs_size,
753             static_cast<const size_t>(
754                 base::WriteFile(rootfs_path,
755                                 reinterpret_cast<const char*>(rootfs.data()),
756                                 rootfs.size())));
757 
758   if (sparse_image) {
759     EXPECT_COMMAND(0,
760                    "mv %s %s.unsparse",
761                    rootfs_path.value().c_str(),
762                    rootfs_path.value().c_str());
763     EXPECT_COMMAND(0,
764                    "img2simg %s.unsparse %s",
765                    rootfs_path.value().c_str(),
766                    rootfs_path.value().c_str());
767     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
768   }
769 
770   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
771   for (int n = 0; n < 2; n++) {
772     EXPECT_COMMAND(0,
773                    "./avbtool add_hashtree_footer --salt d00df00d --image %s "
774                    "--partition_size %d --partition_name foobar "
775                    "--algorithm SHA256_RSA2048 "
776                    "--key test/data/testkey_rsa2048.pem "
777                    "--output_vbmeta_image %s "
778                    "--internal_release_string \"\" "
779                    "--do_not_generate_fec",
780                    rootfs_path.value().c_str(),
781                    (int)partition_size,
782                    ext_vbmeta_path.value().c_str());
783 
784     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
785                                  "Image size:               1572864 bytes\n"
786                                  "Original image size:      1052672 bytes\n"
787                                  "VBMeta offset:            1069056\n"
788                                  "VBMeta size:              1344 bytes\n"
789                                  "--\n"
790                                  "Minimum libavb version:   1.0%s\n"
791                                  "Header Block:             256 bytes\n"
792                                  "Authentication Block:     320 bytes\n"
793                                  "Auxiliary Block:          768 bytes\n"
794                                  "Algorithm:                SHA256_RSA2048\n"
795                                  "Rollback Index:           0\n"
796                                  "Flags:                    0\n"
797                                  "Release String:           ''\n"
798                                  "Descriptors:\n"
799                                  "    Hashtree descriptor:\n"
800                                  "      Version of dm-verity:  1\n"
801                                  "      Image Size:            1052672 bytes\n"
802                                  "      Tree Offset:           1052672\n"
803                                  "      Tree Size:             16384 bytes\n"
804                                  "      Data Block Size:       4096 bytes\n"
805                                  "      Hash Block Size:       4096 bytes\n"
806                                  "      FEC num roots:         0\n"
807                                  "      FEC offset:            0\n"
808                                  "      FEC size:              0 bytes\n"
809                                  "      Hash Algorithm:        sha1\n"
810                                  "      Partition Name:        foobar\n"
811                                  "      Salt:                  d00df00d\n"
812                                  "      Root Digest:           "
813                                  "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
814                                  sparse_image ? " (Sparse)" : ""),
815               InfoImage(rootfs_path));
816 
817     ASSERT_EQ(
818         "Minimum libavb version:   1.0\n"
819         "Header Block:             256 bytes\n"
820         "Authentication Block:     320 bytes\n"
821         "Auxiliary Block:          768 bytes\n"
822         "Algorithm:                SHA256_RSA2048\n"
823         "Rollback Index:           0\n"
824         "Flags:                    0\n"
825         "Release String:           ''\n"
826         "Descriptors:\n"
827         "    Hashtree descriptor:\n"
828         "      Version of dm-verity:  1\n"
829         "      Image Size:            1052672 bytes\n"
830         "      Tree Offset:           1052672\n"
831         "      Tree Size:             16384 bytes\n"
832         "      Data Block Size:       4096 bytes\n"
833         "      Hash Block Size:       4096 bytes\n"
834         "      FEC num roots:         0\n"
835         "      FEC offset:            0\n"
836         "      FEC size:              0 bytes\n"
837         "      Hash Algorithm:        sha1\n"
838         "      Partition Name:        foobar\n"
839         "      Salt:                  d00df00d\n"
840         "      Root Digest:           "
841         "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
842         InfoImage(ext_vbmeta_path));
843   }
844 
845   if (sparse_image) {
846     EXPECT_COMMAND(0,
847                    "mv %s %s.sparse",
848                    rootfs_path.value().c_str(),
849                    rootfs_path.value().c_str());
850     EXPECT_COMMAND(0,
851                    "simg2img %s.sparse %s",
852                    rootfs_path.value().c_str(),
853                    rootfs_path.value().c_str());
854     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
855   }
856 
857   // To check that we generate the correct hashtree we can use
858   // veritysetup(1) - another codebase for working with dm-verity
859   // hashtrees - to verify it.
860   //
861   // If we don't want to impose the requirement of having the
862   // veritysetup(1) command available on builders we can comment this
863   // out.
864   EXPECT_COMMAND(0,
865                  "veritysetup --no-superblock --format=1 --hash=sha1 "
866                  "--data-block-size=4096 --hash-block-size=4096 "
867                  "--salt=d00df00d "
868                  "--data-blocks=257 "
869                  "--hash-offset=1052672 "
870                  "verify "
871                  "%s %s "
872                  "e811611467dcd6e8dc4324e45f706c2bdd51db67",
873                  rootfs_path.value().c_str(),
874                  rootfs_path.value().c_str());
875 
876   // Now check that we can find the VBMeta block again from the footer.
877   std::string part_data;
878   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
879 
880   // Check footer contains correct data.
881   AvbFooter f;
882   EXPECT_NE(0,
883             avb_footer_validate_and_byteswap(
884                 reinterpret_cast<const AvbFooter*>(
885                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
886                 &f));
887   EXPECT_EQ(
888       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
889       AVB_FOOTER_MAGIC);
890   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
891   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
892   EXPECT_EQ(1052672UL, f.original_image_size);
893   EXPECT_EQ(1069056UL, f.vbmeta_offset);
894   EXPECT_EQ(1344UL, f.vbmeta_size);
895 
896   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
897   const uint8_t* vbmeta_data =
898       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
899   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
900             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
901 
902   // Collect all descriptors.
903   std::vector<const AvbDescriptor*> descriptors;
904   avb_descriptor_foreach(
905       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
906 
907   // We should only have a single descriptor and it should be a
908   // hashtree descriptor.
909   EXPECT_EQ(1UL, descriptors.size());
910   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
911   AvbHashtreeDescriptor d;
912   EXPECT_NE(
913       0,
914       avb_hashtree_descriptor_validate_and_byteswap(
915           reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
916   EXPECT_EQ(1UL, d.dm_verity_version);
917   EXPECT_EQ(1052672UL, d.image_size);
918   EXPECT_EQ(1052672UL, d.tree_offset);
919   EXPECT_EQ(16384UL, d.tree_size);
920   EXPECT_EQ(4096UL, d.data_block_size);
921   EXPECT_EQ(4096UL, d.hash_block_size);
922   EXPECT_EQ(6UL, d.partition_name_len);
923   EXPECT_EQ(4UL, d.salt_len);
924   EXPECT_EQ(20UL, d.root_digest_len);
925   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
926                             sizeof(AvbHashtreeDescriptor);
927   uint64_t o = 0;
928   EXPECT_EQ("foobar",
929             std::string(reinterpret_cast<const char*>(desc_end + o),
930                         d.partition_name_len));
931   o += d.partition_name_len;
932   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
933   o += d.salt_len;
934   EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
935             mem_to_hexstring(desc_end + o, d.root_digest_len));
936 
937   // Check that we correctly generate dm-verity kernel cmdline
938   // snippets, if requested.
939   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
940   EXPECT_COMMAND(0,
941                  "./avbtool make_vbmeta_image "
942                  "--output %s "
943                  "--setup_rootfs_from_kernel %s "
944                  "--algorithm SHA256_RSA2048 "
945                  "--key test/data/testkey_rsa2048.pem "
946                  "--internal_release_string \"\"",
947                  vbmeta_dmv_path.value().c_str(),
948                  rootfs_path.value().c_str());
949 
950   ASSERT_EQ(
951       "Minimum libavb version:   1.0\n"
952       "Header Block:             256 bytes\n"
953       "Authentication Block:     320 bytes\n"
954       "Auxiliary Block:          896 bytes\n"
955       "Algorithm:                SHA256_RSA2048\n"
956       "Rollback Index:           0\n"
957       "Flags:                    0\n"
958       "Release String:           ''\n"
959       "Descriptors:\n"
960       "    Kernel Cmdline descriptor:\n"
961       "      Flags:                 1\n"
962       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
963       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
964       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
965       "d00df00d 2 $(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
966       "    Kernel Cmdline descriptor:\n"
967       "      Flags:                 2\n"
968       "      Kernel Cmdline:        "
969       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
970       InfoImage(vbmeta_dmv_path));
971 
972   // Check that the footer is correctly erased and the hashtree
973   // remains - see above for why the constant 1069056 is used.
974   EXPECT_COMMAND(0,
975                  "./avbtool erase_footer --image %s --keep_hashtree",
976                  rootfs_path.value().c_str());
977   int64_t erased_footer_file_size;
978   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
979   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1069056UL);
980 
981   // Check that --do_not_append_vbmeta_image works as intended.
982   //
983   // For this we need to reset the size of the image to the original
984   // size because it's not possible to identify the existing hashtree.
985   EXPECT_COMMAND(
986       0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str());
987   EXPECT_COMMAND(0,
988                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
989                  "--partition_size %d --partition_name foobar "
990                  "--algorithm SHA256_RSA2048 "
991                  "--key test/data/testkey_rsa2048.pem "
992                  "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
993                  "--internal_release_string \"\" "
994                  "--do_not_generate_fec",
995                  rootfs_path.value().c_str(),
996                  (int)partition_size,
997                  ext_vbmeta_path.value().c_str());
998   int64_t file_size;
999   ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
1000   EXPECT_EQ(static_cast<size_t>(file_size), 1069056UL);
1001   EXPECT_COMMAND(0,
1002                  "diff %s %s_2nd_run",
1003                  ext_vbmeta_path.value().c_str(),
1004                  ext_vbmeta_path.value().c_str());
1005 }
1006 
TEST_F(AvbToolTest,AddHashtreeFooter)1007 TEST_F(AvbToolTest, AddHashtreeFooter) {
1008   AddHashtreeFooterTest(false);
1009 }
1010 
TEST_F(AvbToolTest,AddHashtreeFooterSparse)1011 TEST_F(AvbToolTest, AddHashtreeFooterSparse) {
1012   AddHashtreeFooterTest(true);
1013 }
1014 
AddHashtreeFooterFECTest(bool sparse_image)1015 void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
1016   const size_t rootfs_size = 1028 * 1024;
1017   const size_t partition_size = 1536 * 1024;
1018 
1019   // Generate a 1028 KiB file with known content.
1020   std::vector<uint8_t> rootfs;
1021   rootfs.resize(rootfs_size);
1022   for (size_t n = 0; n < rootfs_size; n++)
1023     rootfs[n] = uint8_t(n);
1024   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
1025   EXPECT_EQ(rootfs_size,
1026             static_cast<const size_t>(
1027                 base::WriteFile(rootfs_path,
1028                                 reinterpret_cast<const char*>(rootfs.data()),
1029                                 rootfs.size())));
1030 
1031   if (sparse_image) {
1032     EXPECT_COMMAND(0,
1033                    "mv %s %s.unsparse",
1034                    rootfs_path.value().c_str(),
1035                    rootfs_path.value().c_str());
1036     EXPECT_COMMAND(0,
1037                    "img2simg %s.unsparse %s",
1038                    rootfs_path.value().c_str(),
1039                    rootfs_path.value().c_str());
1040     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
1041   }
1042 
1043   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
1044   for (int n = 0; n < 2; n++) {
1045     EXPECT_COMMAND(0,
1046                    "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1047                    "--partition_size %d --partition_name foobar "
1048                    "--algorithm SHA256_RSA2048 "
1049                    "--key test/data/testkey_rsa2048.pem "
1050                    "--internal_release_string \"\"",
1051                    rootfs_path.value().c_str(),
1052                    (int)partition_size);
1053 
1054     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
1055                                  "Image size:               1572864 bytes\n"
1056                                  "Original image size:      1052672 bytes\n"
1057                                  "VBMeta offset:            1085440\n"
1058                                  "VBMeta size:              1344 bytes\n"
1059                                  "--\n"
1060                                  "Minimum libavb version:   1.0%s\n"
1061                                  "Header Block:             256 bytes\n"
1062                                  "Authentication Block:     320 bytes\n"
1063                                  "Auxiliary Block:          768 bytes\n"
1064                                  "Algorithm:                SHA256_RSA2048\n"
1065                                  "Rollback Index:           0\n"
1066                                  "Flags:                    0\n"
1067                                  "Release String:           ''\n"
1068                                  "Descriptors:\n"
1069                                  "    Hashtree descriptor:\n"
1070                                  "      Version of dm-verity:  1\n"
1071                                  "      Image Size:            1052672 bytes\n"
1072                                  "      Tree Offset:           1052672\n"
1073                                  "      Tree Size:             16384 bytes\n"
1074                                  "      Data Block Size:       4096 bytes\n"
1075                                  "      Hash Block Size:       4096 bytes\n"
1076                                  "      FEC num roots:         2\n"
1077                                  "      FEC offset:            1069056\n"
1078                                  "      FEC size:              16384 bytes\n"
1079                                  "      Hash Algorithm:        sha1\n"
1080                                  "      Partition Name:        foobar\n"
1081                                  "      Salt:                  d00df00d\n"
1082                                  "      Root Digest:           "
1083                                  "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
1084                                  sparse_image ? " (Sparse)" : ""),
1085               InfoImage(rootfs_path));
1086   }
1087 
1088   if (sparse_image) {
1089     EXPECT_COMMAND(0,
1090                    "mv %s %s.sparse",
1091                    rootfs_path.value().c_str(),
1092                    rootfs_path.value().c_str());
1093     EXPECT_COMMAND(0,
1094                    "simg2img %s.sparse %s",
1095                    rootfs_path.value().c_str(),
1096                    rootfs_path.value().c_str());
1097     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
1098   }
1099 
1100   /* TODO: would be nice to verify that the FEC data is correct. */
1101 
1102   // Now check that we can find the VBMeta block again from the footer.
1103   std::string part_data;
1104   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1105 
1106   // Check footer contains correct data.
1107   AvbFooter f;
1108   EXPECT_NE(0,
1109             avb_footer_validate_and_byteswap(
1110                 reinterpret_cast<const AvbFooter*>(
1111                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1112                 &f));
1113   EXPECT_EQ(
1114       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1115       AVB_FOOTER_MAGIC);
1116   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1117   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1118   EXPECT_EQ(1052672UL, f.original_image_size);
1119   EXPECT_EQ(1085440UL, f.vbmeta_offset);
1120   EXPECT_EQ(1344UL, f.vbmeta_size);
1121 
1122   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1123   const uint8_t* vbmeta_data =
1124       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1125   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1126             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1127 
1128   // Collect all descriptors.
1129   std::vector<const AvbDescriptor*> descriptors;
1130   avb_descriptor_foreach(
1131       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1132 
1133   // We should only have a single descriptor and it should be a
1134   // hashtree descriptor.
1135   EXPECT_EQ(1UL, descriptors.size());
1136   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1137   AvbHashtreeDescriptor d;
1138   EXPECT_NE(
1139       0,
1140       avb_hashtree_descriptor_validate_and_byteswap(
1141           reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1142   EXPECT_EQ(1UL, d.dm_verity_version);
1143   EXPECT_EQ(1052672UL, d.image_size);
1144   EXPECT_EQ(1052672UL, d.tree_offset);
1145   EXPECT_EQ(16384UL, d.tree_size);
1146   EXPECT_EQ(4096UL, d.data_block_size);
1147   EXPECT_EQ(2UL, d.fec_num_roots);
1148   EXPECT_EQ(1069056UL, d.fec_offset);
1149   EXPECT_EQ(16384UL, d.fec_size);
1150   EXPECT_EQ(6UL, d.partition_name_len);
1151   EXPECT_EQ(4UL, d.salt_len);
1152   EXPECT_EQ(20UL, d.root_digest_len);
1153   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1154                             sizeof(AvbHashtreeDescriptor);
1155   uint64_t o = 0;
1156   EXPECT_EQ("foobar",
1157             std::string(reinterpret_cast<const char*>(desc_end + o),
1158                         d.partition_name_len));
1159   o += d.partition_name_len;
1160   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1161   o += d.salt_len;
1162   EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1163             mem_to_hexstring(desc_end + o, d.root_digest_len));
1164 
1165   // Check that we correctly generate dm-verity kernel cmdline
1166   // snippets, if requested.
1167   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1168   EXPECT_COMMAND(0,
1169                  "./avbtool make_vbmeta_image "
1170                  "--output %s "
1171                  "--setup_rootfs_from_kernel %s "
1172                  "--algorithm SHA256_RSA2048 "
1173                  "--key test/data/testkey_rsa2048.pem "
1174                  "--internal_release_string \"\"",
1175                  vbmeta_dmv_path.value().c_str(),
1176                  rootfs_path.value().c_str());
1177 
1178   ASSERT_EQ(
1179       "Minimum libavb version:   1.0\n"
1180       "Header Block:             256 bytes\n"
1181       "Authentication Block:     320 bytes\n"
1182       "Auxiliary Block:          960 bytes\n"
1183       "Algorithm:                SHA256_RSA2048\n"
1184       "Rollback Index:           0\n"
1185       "Flags:                    0\n"
1186       "Release String:           ''\n"
1187       "Descriptors:\n"
1188       "    Kernel Cmdline descriptor:\n"
1189       "      Flags:                 1\n"
1190       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1191       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1192       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1193       "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
1194       "use_fec_from_device "
1195       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 261 "
1196       "fec_start 261\" root=/dev/dm-0'\n"
1197       "    Kernel Cmdline descriptor:\n"
1198       "      Flags:                 2\n"
1199       "      Kernel Cmdline:        "
1200       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1201       InfoImage(vbmeta_dmv_path));
1202 
1203   // Check that the footer is correctly erased and the hashtree and
1204   // FEC data remains. The constant 1085440 is used because it's where
1205   // the FEC data ends (it's at offset 1069056 and size 16384).
1206   EXPECT_COMMAND(0,
1207                  "./avbtool erase_footer --image %s --keep_hashtree",
1208                  rootfs_path.value().c_str());
1209   int64_t erased_footer_file_size;
1210   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1211   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1085440UL);
1212 }
1213 
TEST_F(AvbToolTest,AddHashtreeFooterFEC)1214 TEST_F(AvbToolTest, AddHashtreeFooterFEC) {
1215   AddHashtreeFooterFECTest(false);
1216 }
1217 
TEST_F(AvbToolTest,AddHashtreeFooterFECSparse)1218 TEST_F(AvbToolTest, AddHashtreeFooterFECSparse) {
1219   AddHashtreeFooterFECTest(true);
1220 }
1221 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSize)1222 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSize) {
1223   const size_t partition_size = 10 * 1024 * 1024;
1224   base::FilePath output_path = testdir_.Append("max_size.txt");
1225 
1226   EXPECT_COMMAND(0,
1227                  "./avbtool add_hashtree_footer "
1228                  "--partition_size %zd --calc_max_image_size "
1229                  "--do_not_generate_fec > %s",
1230                  partition_size,
1231                  output_path.value().c_str());
1232   std::string max_image_size_data;
1233   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1234   EXPECT_EQ("10330112\n", max_image_size_data);
1235   size_t max_image_size = atoll(max_image_size_data.c_str());
1236 
1237   // Hashtree and metadata takes up 152 KiB - compare to below with
1238   // FEC which is 244 KiB.
1239   EXPECT_EQ(152 * 1024ULL, partition_size - max_image_size);
1240 
1241   // Check that we can add a hashtree with an image this size for such
1242   // a partition size.
1243   base::FilePath system_path = GenerateImage("system", max_image_size);
1244   EXPECT_COMMAND(0,
1245                  "./avbtool add_hashtree_footer"
1246                  " --image %s"
1247                  " --partition_name system"
1248                  " --partition_size %zd"
1249                  " --salt deadbeef"
1250                  " --algorithm SHA512_RSA4096 "
1251                  " --key test/data/testkey_rsa4096.pem"
1252                  " --internal_release_string \"\" "
1253                  "--do_not_generate_fec",
1254                  system_path.value().c_str(),
1255                  partition_size);
1256 }
1257 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSizeWithFEC)1258 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) {
1259   const size_t partition_size = 10 * 1024 * 1024;
1260   base::FilePath output_path = testdir_.Append("max_size.txt");
1261 
1262   EXPECT_COMMAND(0,
1263                  "./avbtool add_hashtree_footer "
1264                  "--partition_size %zd --calc_max_image_size > %s",
1265                  partition_size,
1266                  output_path.value().c_str());
1267   std::string max_image_size_data;
1268   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1269   EXPECT_EQ("10235904\n", max_image_size_data);
1270   size_t max_image_size = atoll(max_image_size_data.c_str());
1271 
1272   // Hashtree, FEC codes, and metadata takes up 244 KiB - compare to
1273   // above wihtout FEC which is 152 KiB.
1274   EXPECT_EQ(244 * 1024ULL, partition_size - max_image_size);
1275 
1276   // Check that we can add a hashtree with an image this size for such
1277   // a partition size.
1278   base::FilePath system_path = GenerateImage("system", max_image_size);
1279   EXPECT_COMMAND(0,
1280                  "./avbtool add_hashtree_footer"
1281                  " --image %s"
1282                  " --partition_name system"
1283                  " --partition_size %zd"
1284                  " --salt deadbeef"
1285                  " --algorithm SHA512_RSA4096 "
1286                  " --key test/data/testkey_rsa4096.pem"
1287                  " --internal_release_string \"\"",
1288                  system_path.value().c_str(),
1289                  partition_size);
1290 }
1291 
TEST_F(AvbToolTest,KernelCmdlineDescriptor)1292 TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
1293   base::FilePath vbmeta_path =
1294       testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
1295 
1296   EXPECT_COMMAND(0,
1297                  "./avbtool make_vbmeta_image "
1298                  "--output %s "
1299                  "--kernel_cmdline 'foo bar baz' "
1300                  "--kernel_cmdline 'second cmdline' "
1301                  "--algorithm SHA256_RSA2048 "
1302                  "--key test/data/testkey_rsa2048.pem "
1303                  "--internal_release_string \"\"",
1304                  vbmeta_path.value().c_str());
1305 
1306   ASSERT_EQ(
1307       "Minimum libavb version:   1.0\n"
1308       "Header Block:             256 bytes\n"
1309       "Authentication Block:     320 bytes\n"
1310       "Auxiliary Block:          640 bytes\n"
1311       "Algorithm:                SHA256_RSA2048\n"
1312       "Rollback Index:           0\n"
1313       "Flags:                    0\n"
1314       "Release String:           ''\n"
1315       "Descriptors:\n"
1316       "    Kernel Cmdline descriptor:\n"
1317       "      Flags:                 0\n"
1318       "      Kernel Cmdline:        'foo bar baz'\n"
1319       "    Kernel Cmdline descriptor:\n"
1320       "      Flags:                 0\n"
1321       "      Kernel Cmdline:        'second cmdline'\n",
1322       InfoImage(vbmeta_path));
1323 
1324   // Now check the VBMeta image.
1325   std::string image_data;
1326   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1327 
1328   const uint8_t* vbmeta_data =
1329       reinterpret_cast<const uint8_t*>(image_data.data());
1330   const size_t vbmeta_size = image_data.length();
1331   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1332             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1333 
1334   // Collect all descriptors.
1335   std::vector<const AvbDescriptor*> descriptors;
1336   avb_descriptor_foreach(
1337       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1338 
1339   // We should have two descriptors - check them.
1340   EXPECT_EQ(2UL, descriptors.size());
1341   AvbKernelCmdlineDescriptor d;
1342   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1343             avb_be64toh(descriptors[0]->tag));
1344   EXPECT_NE(
1345       0,
1346       avb_kernel_cmdline_descriptor_validate_and_byteswap(
1347           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]),
1348           &d));
1349   EXPECT_EQ("foo bar baz",
1350             std::string(reinterpret_cast<const char*>(descriptors[0]) +
1351                             sizeof(AvbKernelCmdlineDescriptor),
1352                         d.kernel_cmdline_length));
1353   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1354             avb_be64toh(descriptors[1]->tag));
1355   EXPECT_NE(
1356       0,
1357       avb_kernel_cmdline_descriptor_validate_and_byteswap(
1358           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]),
1359           &d));
1360   EXPECT_EQ("second cmdline",
1361             std::string(reinterpret_cast<const char*>(descriptors[1]) +
1362                             sizeof(AvbKernelCmdlineDescriptor),
1363                         d.kernel_cmdline_length));
1364 }
1365 
TEST_F(AvbToolTest,IncludeDescriptor)1366 TEST_F(AvbToolTest, IncludeDescriptor) {
1367   base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin");
1368   base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin");
1369   base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
1370 
1371   EXPECT_COMMAND(0,
1372                  "./avbtool make_vbmeta_image "
1373                  "--output %s "
1374                  "--kernel_cmdline 'something' "
1375                  "--prop name:value "
1376                  "--internal_release_string \"\"",
1377                  vbmeta1_path.value().c_str());
1378 
1379   EXPECT_COMMAND(0,
1380                  "./avbtool make_vbmeta_image "
1381                  "--output %s "
1382                  "--prop name2:value2 "
1383                  "--prop name3:value3 "
1384                  "--internal_release_string \"\"",
1385                  vbmeta2_path.value().c_str());
1386 
1387   EXPECT_COMMAND(0,
1388                  "./avbtool make_vbmeta_image "
1389                  "--output %s "
1390                  "--prop name4:value4 "
1391                  "--include_descriptors_from_image %s "
1392                  "--include_descriptors_from_image %s "
1393                  "--internal_release_string \"\"",
1394                  vbmeta3_path.value().c_str(),
1395                  vbmeta1_path.value().c_str(),
1396                  vbmeta2_path.value().c_str());
1397 
1398   ASSERT_EQ(
1399       "Minimum libavb version:   1.0\n"
1400       "Header Block:             256 bytes\n"
1401       "Authentication Block:     0 bytes\n"
1402       "Auxiliary Block:          256 bytes\n"
1403       "Algorithm:                NONE\n"
1404       "Rollback Index:           0\n"
1405       "Flags:                    0\n"
1406       "Release String:           ''\n"
1407       "Descriptors:\n"
1408       "    Prop: name4 -> 'value4'\n"
1409       "    Prop: name -> 'value'\n"
1410       "    Kernel Cmdline descriptor:\n"
1411       "      Flags:                 0\n"
1412       "      Kernel Cmdline:        'something'\n"
1413       "    Prop: name2 -> 'value2'\n"
1414       "    Prop: name3 -> 'value3'\n",
1415       InfoImage(vbmeta3_path));
1416 }
1417 
TEST_F(AvbToolTest,ChainedPartition)1418 TEST_F(AvbToolTest, ChainedPartition) {
1419   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1420 
1421   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1422 
1423   EXPECT_COMMAND(
1424       0,
1425       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1426       " --output %s",
1427       pk_path.value().c_str());
1428 
1429   EXPECT_COMMAND(
1430       0,
1431       "./avbtool make_vbmeta_image "
1432       "--output %s "
1433       "--chain_partition system:1:%s "
1434       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1435       "--internal_release_string \"\"",
1436       vbmeta_path.value().c_str(),
1437       pk_path.value().c_str());
1438 
1439   ASSERT_EQ(
1440       "Minimum libavb version:   1.0\n"
1441       "Header Block:             256 bytes\n"
1442       "Authentication Block:     320 bytes\n"
1443       "Auxiliary Block:          1152 bytes\n"
1444       "Algorithm:                SHA256_RSA2048\n"
1445       "Rollback Index:           0\n"
1446       "Flags:                    0\n"
1447       "Release String:           ''\n"
1448       "Descriptors:\n"
1449       "    Chain Partition descriptor:\n"
1450       "      Partition Name:          system\n"
1451       "      Rollback Index Location: 1\n"
1452       "      Public key (sha1):       "
1453       "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n",
1454       InfoImage(vbmeta_path));
1455 
1456   // Now check the VBMeta image.
1457   std::string image_data;
1458   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1459 
1460   const uint8_t* vbmeta_data =
1461       reinterpret_cast<const uint8_t*>(image_data.data());
1462   const size_t vbmeta_size = image_data.length();
1463   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1464             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1465 
1466   // Collect all descriptors.
1467   std::vector<const AvbDescriptor*> descriptors;
1468   avb_descriptor_foreach(
1469       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1470 
1471   // We should have one descriptor - check it.
1472   EXPECT_EQ(1UL, descriptors.size());
1473 
1474   std::string pk_data;
1475   ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data));
1476 
1477   AvbChainPartitionDescriptor d;
1478   EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
1479             avb_be64toh(descriptors[0]->tag));
1480   EXPECT_NE(
1481       0,
1482       avb_chain_partition_descriptor_validate_and_byteswap(
1483           reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]),
1484           &d));
1485   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1486                             sizeof(AvbChainPartitionDescriptor);
1487   uint64_t o = 0;
1488   EXPECT_EQ("system",
1489             std::string(reinterpret_cast<const char*>(desc_end + o),
1490                         d.partition_name_len));
1491   o += d.partition_name_len;
1492   EXPECT_EQ(pk_data,
1493             std::string(reinterpret_cast<const char*>(descriptors[0]) +
1494                             sizeof(AvbChainPartitionDescriptor) + o,
1495                         d.public_key_len));
1496 }
1497 
TEST_F(AvbToolTest,ChainedPartitionNoLocationCollision)1498 TEST_F(AvbToolTest, ChainedPartitionNoLocationCollision) {
1499   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1500 
1501   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1502 
1503   EXPECT_COMMAND(
1504       0,
1505       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1506       " --output %s",
1507       pk_path.value().c_str());
1508 
1509   // Check that avbtool bails if the same Rollback Index Location is
1510   // used for multiple chained partitions.
1511   EXPECT_COMMAND(
1512       1,
1513       "./avbtool make_vbmeta_image "
1514       "--output %s "
1515       "--chain_partition system:1:%s "
1516       "--chain_partition other:1:%s "
1517       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1518       "--internal_release_string \"\"",
1519       vbmeta_path.value().c_str(),
1520       pk_path.value().c_str(),
1521       pk_path.value().c_str());
1522 }
1523 
TEST_F(AvbToolTest,AppendVBMetaImage)1524 TEST_F(AvbToolTest, AppendVBMetaImage) {
1525   size_t boot_size = 5 * 1024 * 1024;
1526   size_t boot_partition_size = 32 * 1024 * 1024;
1527   base::FilePath boot_path = GenerateImage("boot", boot_size);
1528 
1529   GenerateVBMetaImage("vbmeta.img",
1530                       "SHA256_RSA2048",
1531                       0,
1532                       base::FilePath("test/data/testkey_rsa2048.pem"),
1533                       std::string("--append_to_release_string \"\" "
1534                                   "--kernel_cmdline foo"));
1535 
1536   EXPECT_COMMAND(0,
1537                  "./avbtool append_vbmeta_image "
1538                  "--image %s "
1539                  "--partition_size %d "
1540                  "--vbmeta_image %s ",
1541                  boot_path.value().c_str(),
1542                  (int)boot_partition_size,
1543                  vbmeta_image_path_.value().c_str());
1544 
1545   std::string vbmeta_contents = InfoImage(vbmeta_image_path_);
1546   std::string boot_contents = InfoImage(boot_path);
1547 
1548   // Check that boot.img has the same vbmeta blob as from vbmeta.img -
1549   // we do this by inspecting 'avbtool info_image' output combined
1550   // with the known footer location given boot.img has 5 MiB known
1551   // content and the partition size is 32 MiB.
1552   ASSERT_EQ(
1553       "Minimum libavb version:   1.0\n"
1554       "Header Block:             256 bytes\n"
1555       "Authentication Block:     320 bytes\n"
1556       "Auxiliary Block:          576 bytes\n"
1557       "Algorithm:                SHA256_RSA2048\n"
1558       "Rollback Index:           0\n"
1559       "Flags:                    0\n"
1560       "Release String:           'avbtool 1.0.0 '\n"
1561       "Descriptors:\n"
1562       "    Kernel Cmdline descriptor:\n"
1563       "      Flags:                 0\n"
1564       "      Kernel Cmdline:        'foo'\n",
1565       vbmeta_contents);
1566   std::string known_footer =
1567       "Footer version:           1.0\n"
1568       "Image size:               33554432 bytes\n"
1569       "Original image size:      5242880 bytes\n"
1570       "VBMeta offset:            5242880\n"
1571       "VBMeta size:              1152 bytes\n"
1572       "--\n";
1573   ASSERT_EQ(known_footer + vbmeta_contents, boot_contents);
1574 
1575   // Also verify that the blobs are the same, bit for bit.
1576   base::File f =
1577       base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
1578   std::vector<uint8_t> loaded_vbmeta;
1579   loaded_vbmeta.resize(1152);
1580   EXPECT_EQ(
1581       f.Read(
1582           5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152),
1583       1152);
1584   EXPECT_EQ(vbmeta_image_, loaded_vbmeta);
1585 }
1586 
TEST_F(AvbToolTest,SigningHelperBasic)1587 TEST_F(AvbToolTest, SigningHelperBasic) {
1588   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1589   base::FilePath signing_helper_test_path =
1590       testdir_.Append("signing_helper_test");
1591   EXPECT_COMMAND(
1592       0,
1593       "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1594       "--output %s "
1595       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1596       "--signing_helper test/avbtool_signing_helper_test.py "
1597       "--internal_release_string \"\"",
1598       signing_helper_test_path.value().c_str(),
1599       vbmeta_path.value().c_str());
1600 
1601   // Now check the value in test file.
1602   std::string value;
1603   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1604   EXPECT_EQ("DONE", value);
1605 }
1606 
TEST_F(AvbToolTest,SigningHelperWithFilesBasic)1607 TEST_F(AvbToolTest, SigningHelperWithFilesBasic) {
1608   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1609   base::FilePath signing_helper_test_path =
1610       testdir_.Append("signing_helper_test");
1611   EXPECT_COMMAND(
1612       0,
1613       "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1614       "--output %s "
1615       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1616       "--signing_helper_with_files "
1617       "test/avbtool_signing_helper_with_files_test.py "
1618       "--internal_release_string \"\"",
1619       signing_helper_test_path.value().c_str(),
1620       vbmeta_path.value().c_str());
1621 
1622   // Now check the value in test file.
1623   std::string value;
1624   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1625   EXPECT_EQ("DONE", value);
1626 }
1627 
TEST_F(AvbToolTest,SigningHelperReturnError)1628 TEST_F(AvbToolTest, SigningHelperReturnError) {
1629   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1630   EXPECT_COMMAND(
1631       1,
1632       "./avbtool make_vbmeta_image "
1633       "--output %s "
1634       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1635       "--signing_helper test/avbtool_signing_helper_test.py "
1636       "--internal_release_string \"\"",
1637       vbmeta_path.value().c_str());
1638 }
1639 
TEST_F(AvbToolTest,SigningHelperWithFilesReturnError)1640 TEST_F(AvbToolTest, SigningHelperWithFilesReturnError) {
1641   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1642   EXPECT_COMMAND(
1643       1,
1644       "./avbtool make_vbmeta_image "
1645       "--output %s "
1646       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1647       "--signing_helper_with_files "
1648       "test/avbtool_signing_helper_with_files_test.py "
1649       "--internal_release_string \"\"",
1650       vbmeta_path.value().c_str());
1651 }
1652 
TEST_F(AvbToolTest,VerifyImageNoSignature)1653 TEST_F(AvbToolTest, VerifyImageNoSignature) {
1654   GenerateVBMetaImage("vbmeta.img",
1655                       "",  // NONE
1656                       0,
1657                       base::FilePath());
1658 
1659   EXPECT_COMMAND(0,
1660                  "./avbtool verify_image "
1661                  "--image %s ",
1662                  vbmeta_image_path_.value().c_str());
1663 }
1664 
TEST_F(AvbToolTest,VerifyImageValidSignature)1665 TEST_F(AvbToolTest, VerifyImageValidSignature) {
1666   GenerateVBMetaImage("vbmeta.img",
1667                       "SHA256_RSA2048",
1668                       0,
1669                       base::FilePath("test/data/testkey_rsa2048.pem"));
1670 
1671   EXPECT_COMMAND(0,
1672                  "./avbtool verify_image "
1673                  "--image %s ",
1674                  vbmeta_image_path_.value().c_str());
1675 }
1676 
TEST_F(AvbToolTest,VerifyImageCorruptedVBMeta)1677 TEST_F(AvbToolTest, VerifyImageCorruptedVBMeta) {
1678   GenerateVBMetaImage("vbmeta.img",
1679                       "SHA256_RSA2048",
1680                       0,
1681                       base::FilePath("test/data/testkey_rsa2048.pem"));
1682 
1683   // Corrupt four bytes of data in the end of the image. Since the aux
1684   // data is at the end and this data is signed, this will change the
1685   // value of the computed hash.
1686   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
1687   EXPECT_EQ(AVB_IO_RESULT_OK,
1688             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
1689                                                "vbmeta",
1690                                                -4,  // offset from end
1691                                                sizeof corrupt_data,
1692                                                corrupt_data));
1693 
1694   EXPECT_COMMAND(1,
1695                  "./avbtool verify_image "
1696                  "--image %s ",
1697                  vbmeta_image_path_.value().c_str());
1698 }
1699 
TEST_F(AvbToolTest,VerifyImageOtherKeyMatching)1700 TEST_F(AvbToolTest, VerifyImageOtherKeyMatching) {
1701   GenerateVBMetaImage("vbmeta.img",
1702                       "SHA256_RSA2048",
1703                       0,
1704                       base::FilePath("test/data/testkey_rsa2048.pem"));
1705 
1706   EXPECT_COMMAND(0,
1707                  "./avbtool verify_image "
1708                  "--image %s --key test/data/testkey_rsa2048.pem",
1709                  vbmeta_image_path_.value().c_str());
1710 }
1711 
TEST_F(AvbToolTest,VerifyImageOtherKeyNotMatching)1712 TEST_F(AvbToolTest, VerifyImageOtherKeyNotMatching) {
1713   GenerateVBMetaImage("vbmeta.img",
1714                       "SHA256_RSA2048",
1715                       0,
1716                       base::FilePath("test/data/testkey_rsa2048.pem"));
1717 
1718   EXPECT_COMMAND(1,
1719                  "./avbtool verify_image "
1720                  "--image %s --key test/data/testkey_rsa4096.pem",
1721                  vbmeta_image_path_.value().c_str());
1722 }
1723 
TEST_F(AvbToolTest,VerifyImageBrokenSignature)1724 TEST_F(AvbToolTest, VerifyImageBrokenSignature) {
1725   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1726   base::FilePath signing_helper_test_path =
1727       testdir_.Append("signing_helper_test");
1728 
1729   // Intentionally make the signer generate a wrong signature.
1730   EXPECT_COMMAND(
1731       0,
1732       "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool make_vbmeta_image "
1733       "--output %s "
1734       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1735       "--signing_helper test/avbtool_signing_helper_test.py "
1736       "--internal_release_string \"\"",
1737       vbmeta_path.value().c_str());
1738 
1739   EXPECT_COMMAND(1,
1740                  "./avbtool verify_image "
1741                  "--image %s ",
1742                  vbmeta_path.value().c_str());
1743 }
1744 
1745 // Helper to generate boot.img, unsparse system.img, and vbmeta.img.
GenerateImageWithHashAndHashtreeSetup()1746 void AvbToolTest::GenerateImageWithHashAndHashtreeSetup() {
1747   const size_t boot_partition_size = 16 * 1024 * 1024;
1748   const size_t boot_image_size = 5 * 1024 * 1024;
1749   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
1750   EXPECT_COMMAND(0,
1751                  "./avbtool add_hash_footer"
1752                  " --image %s"
1753                  " --rollback_index 0"
1754                  " --partition_name boot"
1755                  " --partition_size %zd"
1756                  " --salt deadbeef"
1757                  " --internal_release_string \"\"",
1758                  boot_path.value().c_str(),
1759                  boot_partition_size);
1760 
1761   const size_t system_partition_size = 10 * 1024 * 1024;
1762   const size_t system_image_size = 8 * 1024 * 1024;
1763   base::FilePath system_path = GenerateImage("system.img", system_image_size);
1764   EXPECT_COMMAND(0,
1765                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1766                  "--partition_size %zd --partition_name system "
1767                  "--internal_release_string \"\" ",
1768                  system_path.value().c_str(),
1769                  system_partition_size);
1770 
1771   GenerateVBMetaImage("vbmeta.img",
1772                       "SHA256_RSA2048",
1773                       0,
1774                       base::FilePath("test/data/testkey_rsa2048.pem"),
1775                       base::StringPrintf("--include_descriptors_from_image %s "
1776                                          "--include_descriptors_from_image %s",
1777                                          boot_path.value().c_str(),
1778                                          system_path.value().c_str()));
1779 }
1780 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtree)1781 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) {
1782   GenerateImageWithHashAndHashtreeSetup();
1783 
1784   // Do two checks - one for system.img not sparse, and one where it
1785   // is sparse.
1786   for (int n = 0; n < 2; n++) {
1787     EXPECT_COMMAND(0,
1788                    "./avbtool verify_image "
1789                    "--image %s ",
1790                    vbmeta_image_path_.value().c_str());
1791     if (n == 0) {
1792       EXPECT_COMMAND(0,
1793                      "img2simg %s %s.sparse",
1794                      testdir_.Append("system.img").value().c_str(),
1795                      testdir_.Append("system.img").value().c_str());
1796       EXPECT_COMMAND(0,
1797                      "mv %s.sparse %s",
1798                      testdir_.Append("system.img").value().c_str(),
1799                      testdir_.Append("system.img").value().c_str());
1800     }
1801   }
1802 }
1803 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHash)1804 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) {
1805   GenerateImageWithHashAndHashtreeSetup();
1806 
1807   // Corrupt four bytes of data in the middle of boot.img.
1808   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
1809   EXPECT_EQ(AVB_IO_RESULT_OK,
1810             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
1811                                                "boot",
1812                                                105 * 1024,  // offset from start
1813                                                sizeof corrupt_data,
1814                                                corrupt_data));
1815 
1816   EXPECT_COMMAND(1,
1817                  "./avbtool verify_image "
1818                  "--image %s ",
1819                  vbmeta_image_path_.value().c_str());
1820 }
1821 
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHashtree)1822 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHashtree) {
1823   GenerateImageWithHashAndHashtreeSetup();
1824 
1825   // Corrupt four bytes of data in the middle of system.img.
1826   uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
1827   EXPECT_EQ(AVB_IO_RESULT_OK,
1828             ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
1829                                                "system",
1830                                                123 * 1024,  // offset from start
1831                                                sizeof corrupt_data,
1832                                                corrupt_data));
1833 
1834   // Do two checks - one for system.img not sparse, and one where it
1835   // is sparse.
1836   for (int n = 0; n < 2; n++) {
1837     EXPECT_COMMAND(1,
1838                    "./avbtool verify_image "
1839                    "--image %s ",
1840                    vbmeta_image_path_.value().c_str());
1841     if (n == 0) {
1842       EXPECT_COMMAND(0,
1843                      "img2simg %s %s.sparse",
1844                      testdir_.Append("system.img").value().c_str(),
1845                      testdir_.Append("system.img").value().c_str());
1846       EXPECT_COMMAND(0,
1847                      "mv %s.sparse %s",
1848                      testdir_.Append("system.img").value().c_str(),
1849                      testdir_.Append("system.img").value().c_str());
1850     }
1851   }
1852 }
1853 
TEST_F(AvbToolTest,VerifyImageChainPartition)1854 TEST_F(AvbToolTest, VerifyImageChainPartition) {
1855   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
1856   EXPECT_COMMAND(
1857       0,
1858       "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
1859       " --output %s",
1860       pk4096_path.value().c_str());
1861 
1862   base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey");
1863   EXPECT_COMMAND(
1864       0,
1865       "./avbtool extract_public_key --key test/data/testkey_rsa8192.pem"
1866       " --output %s",
1867       pk8192_path.value().c_str());
1868 
1869   GenerateVBMetaImage("vbmeta.img",
1870                       "SHA256_RSA2048",
1871                       0,
1872                       base::FilePath("test/data/testkey_rsa2048.pem"),
1873                       base::StringPrintf("--chain_partition system:1:%s ",
1874                                          pk4096_path.value().c_str()));
1875 
1876   // Should not fail (name, rollback_index, contents all correct).
1877   EXPECT_COMMAND(0,
1878                  "./avbtool verify_image "
1879                  "--image %s "
1880                  "--expected_chain_partition system:1:%s",
1881                  vbmeta_image_path_.value().c_str(),
1882                  pk4096_path.value().c_str());
1883 
1884   // Should fail because we didn't use --expected_chain_partition.
1885   EXPECT_COMMAND(1,
1886                  "./avbtool verify_image "
1887                  "--image %s ",
1888                  vbmeta_image_path_.value().c_str());
1889 
1890   // Should fail because partition name is wrong.
1891   EXPECT_COMMAND(1,
1892                  "./avbtool verify_image "
1893                  "--image %s "
1894                  "--expected_chain_partition xyz:1:%s",
1895                  vbmeta_image_path_.value().c_str(),
1896                  pk4096_path.value().c_str());
1897 
1898   // Should fail because rollback index location is wrong.
1899   EXPECT_COMMAND(1,
1900                  "./avbtool verify_image "
1901                  "--image %s "
1902                  "--expected_chain_partition system:2:%s",
1903                  vbmeta_image_path_.value().c_str(),
1904                  pk4096_path.value().c_str());
1905 
1906   // Should fail because public key blob is wrong.
1907   EXPECT_COMMAND(1,
1908                  "./avbtool verify_image "
1909                  "--image %s "
1910                  "--expected_chain_partition system:1:%s",
1911                  vbmeta_image_path_.value().c_str(),
1912                  pk8192_path.value().c_str());
1913 }
1914 
TEST_F(AvbToolTest,PrintRequiredLibavbVersion)1915 TEST_F(AvbToolTest, PrintRequiredLibavbVersion) {
1916   base::FilePath output_path = testdir_.Append("versions.txt");
1917 
1918   const size_t boot_partition_size = 16 * 1024 * 1024;
1919   EXPECT_COMMAND(0,
1920                  "./avbtool add_hash_footer"
1921                  " --rollback_index 0"
1922                  " --partition_name boot"
1923                  " --partition_size %zd"
1924                  " --salt deadbeef"
1925                  " --internal_release_string \"\""
1926                  " --print_required_libavb_version >> %s",
1927                  boot_partition_size,
1928                  output_path.value().c_str());
1929 
1930   const size_t system_partition_size = 10 * 1024 * 1024;
1931   EXPECT_COMMAND(0,
1932                  "./avbtool add_hashtree_footer --salt d00df00d "
1933                  "--partition_size %zd --partition_name system "
1934                  "--internal_release_string \"\""
1935                  " --print_required_libavb_version >> %s",
1936                  system_partition_size,
1937                  output_path.value().c_str());
1938 
1939   EXPECT_COMMAND(0,
1940                  "./avbtool make_vbmeta_image "
1941                  "--algorithm SHA256_RSA2048 "
1942                  "--key test/data/testkey_rsa2048.pem "
1943                  "--internal_release_string \"\""
1944                  " --print_required_libavb_version >> %s",
1945                  output_path.value().c_str());
1946 
1947   // Check that "1.0\n" was printed for all three invocations.
1948   std::string versions;
1949   ASSERT_TRUE(base::ReadFileToString(output_path, &versions));
1950   EXPECT_EQ(versions, std::string("1.0\n1.0\n1.0\n"));
1951 }
1952 
TEST_F(AvbToolTest,MakeAtxPikCertificate)1953 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
1954   base::FilePath subject_path = testdir_.Append("tmp_subject");
1955   ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
1956   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
1957   EXPECT_COMMAND(
1958       0,
1959       "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
1960       pubkey_path.value().c_str());
1961 
1962   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
1963   EXPECT_COMMAND(0,
1964                  "./avbtool make_atx_certificate"
1965                  " --subject %s"
1966                  " --subject_key %s"
1967                  " --subject_key_version 42"
1968                  " --subject_is_intermediate_authority"
1969                  " --authority_key test/data/testkey_atx_prk.pem"
1970                  " --output %s",
1971                  subject_path.value().c_str(),
1972                  pubkey_path.value().c_str(),
1973                  output_path.value().c_str());
1974 
1975   EXPECT_COMMAND(0,
1976                  "diff test/data/atx_pik_certificate.bin %s",
1977                  output_path.value().c_str());
1978 }
1979 
TEST_F(AvbToolTest,MakeAtxPskCertificate)1980 TEST_F(AvbToolTest, MakeAtxPskCertificate) {
1981   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
1982   EXPECT_COMMAND(
1983       0,
1984       "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
1985       pubkey_path.value().c_str());
1986 
1987   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
1988   EXPECT_COMMAND(0,
1989                  "./avbtool make_atx_certificate"
1990                  " --subject test/data/atx_product_id.bin"
1991                  " --subject_key %s"
1992                  " --subject_key_version 42"
1993                  " --authority_key test/data/testkey_atx_pik.pem"
1994                  " --output %s",
1995                  pubkey_path.value().c_str(),
1996                  output_path.value().c_str());
1997 
1998   EXPECT_COMMAND(0,
1999                  "diff test/data/atx_psk_certificate.bin %s",
2000                  output_path.value().c_str());
2001 }
2002 
TEST_F(AvbToolTest,MakeAtxPermanentAttributes)2003 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) {
2004   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
2005   EXPECT_COMMAND(
2006       0,
2007       "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
2008       pubkey_path.value().c_str());
2009 
2010   base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
2011   EXPECT_COMMAND(0,
2012                  "./avbtool make_atx_permanent_attributes"
2013                  " --root_authority_key %s"
2014                  " --product_id test/data/atx_product_id.bin"
2015                  " --output %s",
2016                  pubkey_path.value().c_str(),
2017                  output_path.value().c_str());
2018 
2019   EXPECT_COMMAND(0,
2020                  "diff test/data/atx_permanent_attributes.bin %s",
2021                  output_path.value().c_str());
2022 }
2023 
TEST_F(AvbToolTest,MakeAtxMetadata)2024 TEST_F(AvbToolTest, MakeAtxMetadata) {
2025   base::FilePath output_path = testdir_.Append("tmp_metadata.bin");
2026 
2027   EXPECT_COMMAND(
2028       0,
2029       "./avbtool make_atx_metadata"
2030       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
2031       " --product_key_certificate test/data/atx_psk_certificate.bin"
2032       " --output %s",
2033       output_path.value().c_str());
2034 
2035   EXPECT_COMMAND(
2036       0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str());
2037 }
2038 
2039 }  // namespace avb
2040