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