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