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