1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #include <iostream>
26 
27 #include <endian.h>
28 #include <inttypes.h>
29 #include <string.h>
30 
31 #include <base/files/file_util.h>
32 #include <base/strings/string_split.h>
33 #include <base/strings/string_util.h>
34 #include <base/strings/stringprintf.h>
35 
36 #include <libavb/avb_sha.h>
37 #include <libavb/libavb.h>
38 
39 #include "avb_unittest_util.h"
40 
41 namespace avb {
42 
43 class AvbToolTest : public BaseAvbToolTest {
44  public:
AvbToolTest()45   AvbToolTest() {}
46 
47   void AddHashFooterTest(bool sparse_image);
48   void AddHashtreeFooterTest(bool sparse_image);
49   void AddHashtreeFooterFECTest(bool sparse_image);
50 };
51 
52 // This test ensure that the version is increased in both
53 // avb_boot_image.h and the avb tool.
TEST_F(AvbToolTest,AvbVersionInSync)54 TEST_F(AvbToolTest, AvbVersionInSync) {
55   base::FilePath path = testdir_.Append("version.txt");
56   EXPECT_COMMAND(0, "./avbtool version > %s", path.value().c_str());
57   std::string printed_version;
58   ASSERT_TRUE(base::ReadFileToString(path, &printed_version));
59   base::TrimWhitespaceASCII(printed_version, base::TRIM_ALL, &printed_version);
60   // See comments in libavb/avb_version.c and avbtool's get_release_string()
61   // about being in sync.
62   EXPECT_EQ(printed_version,
63             std::string("avbtool ") + std::string(avb_version_string()));
64 }
65 
TEST_F(AvbToolTest,DefaultReleaseString)66 TEST_F(AvbToolTest, DefaultReleaseString) {
67   GenerateVBMetaImage("vbmeta.img",
68                       "SHA256_RSA2048",
69                       0,
70                       base::FilePath("test/data/testkey_rsa2048.pem"));
71 
72   // Default release string is "avbtool " + avb_version_string().
73   AvbVBMetaImageHeader h;
74   avb_vbmeta_image_header_to_host_byte_order(
75       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
76   EXPECT_EQ(std::string("avbtool ") + std::string(avb_version_string()),
77             std::string((const char*)h.release_string));
78 }
79 
TEST_F(AvbToolTest,ReleaseStringAppend)80 TEST_F(AvbToolTest, ReleaseStringAppend) {
81   GenerateVBMetaImage("vbmeta.img",
82                       "SHA256_RSA2048",
83                       0,
84                       base::FilePath("test/data/testkey_rsa2048.pem"),
85                       "--append_to_release_string \"Woot XYZ\"");
86 
87   // Note that avbtool inserts the space by itself.
88   std::string expected_str =
89       std::string("avbtool ") + std::string(avb_version_string()) + " Woot XYZ";
90 
91   AvbVBMetaImageHeader h;
92   avb_vbmeta_image_header_to_host_byte_order(
93       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
94   EXPECT_EQ(expected_str, std::string((const char*)h.release_string));
95 }
96 
TEST_F(AvbToolTest,ReleaseStringAppendTruncated)97 TEST_F(AvbToolTest, ReleaseStringAppendTruncated) {
98   // Append enough text that truncation is sure to happen.
99   std::string append_str = "0123456789abcdef0123456789abcdef0123456789abcdef";
100   std::string expected_str = std::string("avbtool ") +
101                              std::string(avb_version_string()) + " " +
102                              append_str;
103   EXPECT_GT(expected_str.size(), (size_t)(AVB_RELEASE_STRING_SIZE - 1));
104   expected_str.resize(AVB_RELEASE_STRING_SIZE - 1);
105 
106   GenerateVBMetaImage(
107       "vbmeta.img",
108       "SHA256_RSA2048",
109       0,
110       base::FilePath("test/data/testkey_rsa2048.pem"),
111       std::string("--append_to_release_string \"") + append_str + "\"");
112 
113   // This checks that it ends with a NUL byte.
114   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
115             avb_vbmeta_image_verify(
116                 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr));
117 
118   // For good measure we also check here.
119   AvbVBMetaImageHeader h;
120   avb_vbmeta_image_header_to_host_byte_order(
121       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
122   EXPECT_EQ(expected_str, std::string((const char*)h.release_string));
123 }
124 
TEST_F(AvbToolTest,ExtractPublicKey)125 TEST_F(AvbToolTest, ExtractPublicKey) {
126   GenerateVBMetaImage("vbmeta.img",
127                       "SHA256_RSA2048",
128                       0,
129                       base::FilePath("test/data/testkey_rsa2048.pem"),
130                       "--internal_release_string \"\"");
131 
132   std::string key_data =
133       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem"));
134 
135   AvbVBMetaImageHeader h;
136   avb_vbmeta_image_header_to_host_byte_order(
137       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
138   uint8_t* d = reinterpret_cast<uint8_t*>(vbmeta_image_.data());
139   size_t auxiliary_data_block_offset =
140       sizeof(AvbVBMetaImageHeader) + h.authentication_data_block_size;
141   EXPECT_GT(h.auxiliary_data_block_size, key_data.size());
142   EXPECT_EQ(0,
143             memcmp(key_data.data(),
144                    d + auxiliary_data_block_offset + h.public_key_offset,
145                    key_data.size()));
146 }
147 
TEST_F(AvbToolTest,CheckDescriptors)148 TEST_F(AvbToolTest, CheckDescriptors) {
149   GenerateVBMetaImage("vbmeta.img",
150                       "SHA256_RSA2048",
151                       0,
152                       base::FilePath("test/data/testkey_rsa2048.pem"),
153                       "--prop foo:brillo "
154                       "--prop bar:chromeos "
155                       "--prop prisoner:24601 "
156                       "--prop hexnumber:0xcafe "
157                       "--prop hexnumber_capital:0xCAFE "
158                       "--prop large_hexnumber:0xfedcba9876543210 "
159                       "--prop larger_than_uint64:0xfedcba98765432101 "
160                       "--prop almost_a_number:423x "
161                       "--prop_from_file blob:test/data/small_blob.bin "
162                       "--internal_release_string \"\"");
163 
164   AvbVBMetaImageHeader h;
165   avb_vbmeta_image_header_to_host_byte_order(
166       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
167 
168   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
169             avb_vbmeta_image_verify(
170                 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr));
171 
172   const char* s;
173   size_t len;
174   uint64_t val;
175 
176   // Basic.
177   s = avb_property_lookup(
178       vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &len);
179   EXPECT_EQ(0, strcmp(s, "brillo"));
180   EXPECT_EQ(6U, len);
181   s = avb_property_lookup(
182       vbmeta_image_.data(), vbmeta_image_.size(), "bar", 0, &len);
183   EXPECT_EQ(0, strcmp(s, "chromeos"));
184   EXPECT_EQ(8U, len);
185   s = avb_property_lookup(
186       vbmeta_image_.data(), vbmeta_image_.size(), "non-existant", 0, &len);
187   EXPECT_EQ(0U, len);
188   EXPECT_EQ(NULL, s);
189 
190   // Numbers.
191   EXPECT_NE(
192       0,
193       avb_property_lookup_uint64(
194           vbmeta_image_.data(), vbmeta_image_.size(), "prisoner", 0, &val));
195   EXPECT_EQ(24601U, val);
196 
197   EXPECT_NE(
198       0,
199       avb_property_lookup_uint64(
200           vbmeta_image_.data(), vbmeta_image_.size(), "hexnumber", 0, &val));
201   EXPECT_EQ(0xcafeU, val);
202 
203   EXPECT_NE(0,
204             avb_property_lookup_uint64(vbmeta_image_.data(),
205                                        vbmeta_image_.size(),
206                                        "hexnumber_capital",
207                                        0,
208                                        &val));
209   EXPECT_EQ(0xcafeU, val);
210 
211   EXPECT_NE(0,
212             avb_property_lookup_uint64(vbmeta_image_.data(),
213                                        vbmeta_image_.size(),
214                                        "large_hexnumber",
215                                        0,
216                                        &val));
217   EXPECT_EQ(0xfedcba9876543210U, val);
218 
219   // We could catch overflows and return an error ... but we currently don't.
220   EXPECT_NE(0,
221             avb_property_lookup_uint64(vbmeta_image_.data(),
222                                        vbmeta_image_.size(),
223                                        "larger_than_uint64",
224                                        0,
225                                        &val));
226   EXPECT_EQ(0xedcba98765432101U, val);
227 
228   // Number-parsing failures.
229   EXPECT_EQ(0,
230             avb_property_lookup_uint64(
231                 vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &val));
232 
233   EXPECT_EQ(0,
234             avb_property_lookup_uint64(vbmeta_image_.data(),
235                                        vbmeta_image_.size(),
236                                        "almost_a_number",
237                                        0,
238                                        &val));
239 
240   // Blobs.
241   //
242   // test/data/small_blob.bin is 21 byte file full of NUL-bytes except
243   // for the string "brillo ftw!" at index 2 and '\n' at the last
244   // byte.
245   s = avb_property_lookup(
246       vbmeta_image_.data(), vbmeta_image_.size(), "blob", 0, &len);
247   EXPECT_EQ(21U, len);
248   EXPECT_EQ(0, memcmp(s, "\0\0", 2));
249   EXPECT_EQ(0, memcmp(s + 2, "brillo ftw!", 11));
250   EXPECT_EQ(0, memcmp(s + 13, "\0\0\0\0\0\0\0", 7));
251   EXPECT_EQ('\n', s[20]);
252 }
253 
TEST_F(AvbToolTest,CheckRollbackIndex)254 TEST_F(AvbToolTest, CheckRollbackIndex) {
255   uint64_t rollback_index = 42;
256   GenerateVBMetaImage("vbmeta.img",
257                       "SHA256_RSA2048",
258                       rollback_index,
259                       base::FilePath("test/data/testkey_rsa2048.pem"),
260                       "--internal_release_string \"\"");
261 
262   AvbVBMetaImageHeader h;
263   avb_vbmeta_image_header_to_host_byte_order(
264       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
265 
266   EXPECT_EQ(rollback_index, h.rollback_index);
267 }
268 
TEST_F(AvbToolTest,CheckPubkeyReturned)269 TEST_F(AvbToolTest, CheckPubkeyReturned) {
270   GenerateVBMetaImage("vbmeta.img",
271                       "SHA256_RSA2048",
272                       0,
273                       base::FilePath("test/data/testkey_rsa2048.pem"),
274                       "--internal_release_string \"\"");
275 
276   const uint8_t* pubkey = NULL;
277   size_t pubkey_length = 0;
278 
279   EXPECT_EQ(
280       AVB_VBMETA_VERIFY_RESULT_OK,
281       avb_vbmeta_image_verify(
282           vbmeta_image_.data(), vbmeta_image_.size(), &pubkey, &pubkey_length));
283 
284   AvbVBMetaImageHeader h;
285   avb_vbmeta_image_header_to_host_byte_order(
286       reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
287 
288   EXPECT_EQ(pubkey_length, h.public_key_size);
289 
290   const uint8_t* expected_pubkey =
291       vbmeta_image_.data() + sizeof(AvbVBMetaImageHeader) +
292       h.authentication_data_block_size + h.public_key_offset;
293   EXPECT_EQ(pubkey, expected_pubkey);
294 }
295 
TEST_F(AvbToolTest,Info)296 TEST_F(AvbToolTest, Info) {
297   GenerateVBMetaImage("vbmeta.img",
298                       "SHA256_RSA2048",
299                       0,
300                       base::FilePath("test/data/testkey_rsa2048.pem"),
301                       "--prop foo:brillo "
302                       "--prop bar:chromeos "
303                       "--prop prisoner:24601 "
304                       "--prop hexnumber:0xcafe "
305                       "--prop hexnumber_capital:0xCAFE "
306                       "--prop large_hexnumber:0xfedcba9876543210 "
307                       "--prop larger_than_uint64:0xfedcba98765432101 "
308                       "--prop almost_a_number:423x "
309                       "--prop_from_file blob:test/data/small_blob.bin "
310                       "--prop_from_file large_blob:test/data/large_blob.bin "
311                       "--internal_release_string \"\"");
312 
313   ASSERT_EQ(
314       "Minimum libavb version:   1.0\n"
315       "Header Block:             256 bytes\n"
316       "Authentication Block:     320 bytes\n"
317       "Auxiliary Block:          3200 bytes\n"
318       "Algorithm:                SHA256_RSA2048\n"
319       "Rollback Index:           0\n"
320       "Flags:                    0\n"
321       "Release String:           ''\n"
322       "Descriptors:\n"
323       "    Prop: foo -> 'brillo'\n"
324       "    Prop: bar -> 'chromeos'\n"
325       "    Prop: prisoner -> '24601'\n"
326       "    Prop: hexnumber -> '0xcafe'\n"
327       "    Prop: hexnumber_capital -> '0xCAFE'\n"
328       "    Prop: large_hexnumber -> '0xfedcba9876543210'\n"
329       "    Prop: larger_than_uint64 -> '0xfedcba98765432101'\n"
330       "    Prop: almost_a_number -> '423x'\n"
331       "    Prop: blob -> '\\x00\\x00brillo "
332       "ftw!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n'\n"
333       "    Prop: large_blob -> (2048 bytes)\n",
334       InfoImage(vbmeta_image_path_));
335 }
336 
collect_descriptors(const AvbDescriptor * descriptor,void * user_data)337 static bool collect_descriptors(const AvbDescriptor* descriptor,
338                                 void* user_data) {
339   std::vector<const AvbDescriptor*>* descriptors =
340       reinterpret_cast<std::vector<const AvbDescriptor*>*>(user_data);
341   descriptors->push_back(descriptor);
342   return true;  // Keep iterating.
343 }
344 
AddHashFooterTest(bool sparse_image)345 void AvbToolTest::AddHashFooterTest(bool sparse_image) {
346   const size_t rootfs_size = 1028 * 1024;
347   const size_t partition_size = 1536 * 1024;
348 
349   // Generate a 1028 KiB file with known content. Some content have
350   // been arranged to ensure FILL_DATA segments in the sparse file.
351   std::vector<uint8_t> rootfs;
352   rootfs.resize(rootfs_size);
353   for (size_t n = 0; n < rootfs_size; n++) {
354     if ((n >= 5 * 1000 && n < 105 * 1000) ||
355         (n >= 205 * 1000 && n < 305 * 1000) ||
356         (n >= 505 * 1000 && n < 605 * 1000)) {
357       rootfs[n] = uint8_t(n) & 0x03;
358     } else {
359       rootfs[n] = uint8_t(n);
360     }
361   }
362   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
363   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
364   EXPECT_EQ(rootfs_size,
365             static_cast<const size_t>(
366                 base::WriteFile(rootfs_path,
367                                 reinterpret_cast<const char*>(rootfs.data()),
368                                 rootfs.size())));
369 
370   if (sparse_image) {
371     EXPECT_COMMAND(0,
372                    "mv %s %s.unsparse",
373                    rootfs_path.value().c_str(),
374                    rootfs_path.value().c_str());
375     EXPECT_COMMAND(0,
376                    "img2simg %s.unsparse %s",
377                    rootfs_path.value().c_str(),
378                    rootfs_path.value().c_str());
379     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
380   }
381 
382   /* Do this twice to check that 'add_hash_footer' is idempotent. */
383   for (int n = 0; n < 2; n++) {
384     EXPECT_COMMAND(0,
385                    "./avbtool add_hash_footer --salt d00df00d "
386                    "--hash_algorithm sha256 --image %s "
387                    "--partition_size %d --partition_name foobar "
388                    "--algorithm SHA256_RSA2048 "
389                    "--key test/data/testkey_rsa2048.pem "
390                    "--output_vbmeta %s "
391                    "--internal_release_string \"\"",
392                    rootfs_path.value().c_str(),
393                    (int)partition_size,
394                    ext_vbmeta_path.value().c_str());
395 
396     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
397                                  "Image size:               1572864 bytes\n"
398                                  "Original image size:      1052672 bytes\n"
399                                  "VBMeta offset:            1052672\n"
400                                  "VBMeta size:              1280 bytes\n"
401                                  "--\n"
402                                  "Minimum libavb version:   1.0%s\n"
403                                  "Header Block:             256 bytes\n"
404                                  "Authentication Block:     320 bytes\n"
405                                  "Auxiliary Block:          704 bytes\n"
406                                  "Algorithm:                SHA256_RSA2048\n"
407                                  "Rollback Index:           0\n"
408                                  "Flags:                    0\n"
409                                  "Release String:           ''\n"
410                                  "Descriptors:\n"
411                                  "    Hash descriptor:\n"
412                                  "      Image Size:            1052672 bytes\n"
413                                  "      Hash Algorithm:        sha256\n"
414                                  "      Partition Name:        foobar\n"
415                                  "      Salt:                  d00df00d\n"
416                                  "      Digest:                "
417                                  "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
418                                  "5e4ed357fbcf58d88d9\n",
419                                  sparse_image ? " (Sparse)" : ""),
420               InfoImage(rootfs_path));
421 
422     ASSERT_EQ(
423         "Minimum libavb version:   1.0\n"
424         "Header Block:             256 bytes\n"
425         "Authentication Block:     320 bytes\n"
426         "Auxiliary Block:          704 bytes\n"
427         "Algorithm:                SHA256_RSA2048\n"
428         "Rollback Index:           0\n"
429         "Flags:                    0\n"
430         "Release String:           ''\n"
431         "Descriptors:\n"
432         "    Hash descriptor:\n"
433         "      Image Size:            1052672 bytes\n"
434         "      Hash Algorithm:        sha256\n"
435         "      Partition Name:        foobar\n"
436         "      Salt:                  d00df00d\n"
437         "      Digest:                "
438         "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
439         "5e4ed357fbcf58d88d9\n",
440         InfoImage(ext_vbmeta_path));
441   }
442 
443   if (sparse_image) {
444     EXPECT_COMMAND(0,
445                    "mv %s %s.sparse",
446                    rootfs_path.value().c_str(),
447                    rootfs_path.value().c_str());
448     EXPECT_COMMAND(0,
449                    "simg2img %s.sparse %s",
450                    rootfs_path.value().c_str(),
451                    rootfs_path.value().c_str());
452     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
453   }
454 
455   // Manually calculate the hash to check that it agrees with avbtool.
456   AvbSHA256Ctx hasher_ctx;
457   const uint8_t hasher_salt[4] = {0xd0, 0x0d, 0xf0, 0x0d};
458   avb_sha256_init(&hasher_ctx);
459   avb_sha256_update(&hasher_ctx, hasher_salt, 4);
460   avb_sha256_update(&hasher_ctx, rootfs.data(), rootfs_size);
461   uint8_t* hasher_digest = avb_sha256_final(&hasher_ctx);
462   EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
463             mem_to_hexstring(hasher_digest, AVB_SHA256_DIGEST_SIZE));
464 
465   // Now check that we can find the VBMeta block again from the footer.
466   std::string part_data;
467   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
468 
469   // Check footer contains correct data.
470   AvbFooter f;
471   EXPECT_NE(0,
472             avb_footer_validate_and_byteswap(
473                 reinterpret_cast<const AvbFooter*>(
474                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
475                 &f));
476   EXPECT_EQ(
477       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
478       AVB_FOOTER_MAGIC);
479   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
480   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
481   EXPECT_EQ(1052672UL, f.original_image_size);
482   EXPECT_EQ(1052672UL, f.vbmeta_offset);
483   EXPECT_EQ(1280UL, f.vbmeta_size);
484 
485   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
486   const uint8_t* vbmeta_data =
487       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
488   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
489             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
490 
491   // Collect all descriptors.
492   std::vector<const AvbDescriptor*> descriptors;
493   avb_descriptor_foreach(
494       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
495 
496   // We should only have a single descriptor and it should be a
497   // hash descriptor.
498   EXPECT_EQ(1UL, descriptors.size());
499   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, avb_be64toh(descriptors[0]->tag));
500   AvbHashDescriptor d;
501   EXPECT_NE(
502       0,
503       avb_hash_descriptor_validate_and_byteswap(
504           reinterpret_cast<const AvbHashDescriptor*>(descriptors[0]), &d));
505   EXPECT_EQ(1052672UL, d.image_size);
506   EXPECT_EQ(6UL, d.partition_name_len);
507   EXPECT_EQ(4UL, d.salt_len);
508   EXPECT_EQ(32UL, d.digest_len);
509   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
510                             sizeof(AvbHashDescriptor);
511   uint64_t o = 0;
512   EXPECT_EQ("foobar",
513             std::string(reinterpret_cast<const char*>(desc_end + o),
514                         d.partition_name_len));
515   o += d.partition_name_len;
516   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
517   o += d.salt_len;
518   EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
519             mem_to_hexstring(desc_end + o, d.digest_len));
520 
521   // Check that the footer is correctly erased.
522   EXPECT_COMMAND(
523       0, "./avbtool erase_footer --image %s", rootfs_path.value().c_str());
524   int64_t erased_footer_file_size;
525   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
526   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size);
527 
528   // Check that --do_not_append_vbmeta_image works as intended.
529   EXPECT_COMMAND(0,
530                  "./avbtool add_hash_footer --salt d00df00d "
531                  "--hash_algorithm sha256 --image %s "
532                  "--partition_size %d --partition_name foobar "
533                  "--algorithm SHA256_RSA2048 "
534                  "--key test/data/testkey_rsa2048.pem "
535                  "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
536                  "--internal_release_string \"\"",
537                  rootfs_path.value().c_str(),
538                  (int)partition_size,
539                  ext_vbmeta_path.value().c_str());
540   int64_t file_size;
541   ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
542   EXPECT_EQ(static_cast<size_t>(file_size), rootfs_size);
543   EXPECT_COMMAND(0,
544                  "diff %s %s_2nd_run",
545                  ext_vbmeta_path.value().c_str(),
546                  ext_vbmeta_path.value().c_str());
547 }
548 
TEST_F(AvbToolTest,AddHashFooter)549 TEST_F(AvbToolTest, AddHashFooter) {
550   AddHashFooterTest(false);
551 }
552 
TEST_F(AvbToolTest,AddHashFooterSparse)553 TEST_F(AvbToolTest, AddHashFooterSparse) {
554   AddHashFooterTest(true);
555 }
556 
RemoveLinesStartingWith(const std::string & str,const std::string & prefix)557 static std::string RemoveLinesStartingWith(const std::string& str,
558                                            const std::string& prefix) {
559   std::vector<std::string> lines;
560   std::string ret;
561 
562   lines = base::SplitString(
563       str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
564   for (const std::string& line : lines) {
565     if (!base::StartsWith(line, prefix, base::CompareCase::SENSITIVE)) {
566       ret += line;
567       ret += '\n';
568     }
569   }
570   return ret;
571 }
572 
TEST_F(AvbToolTest,AddHashFooterSparseWithHoleAtTheEnd)573 TEST_F(AvbToolTest, AddHashFooterSparseWithHoleAtTheEnd) {
574   const size_t partition_size = 10 * 1024 * 1024;
575   const size_t metadata_size = 128 * 1024;
576 
577   // It's not enough to run img2simg on a file with a lot of zeroes at
578   // the end since that will turn up as "Fill with value (for value =
579   // 0x00000000)" and not "Don't care". Instead, use make_ext4fs for
580   // this since it will put a big hole (e.g. "Don't care" chunk) at
581   // the end.
582   base::FilePath partition_path = testdir_.Append("partition.bin");
583   EXPECT_COMMAND(0,
584                  "make_ext4fs -s -L test -l %zd %s",
585                  partition_size - metadata_size,
586                  partition_path.value().c_str());
587 
588   EXPECT_COMMAND(0,
589                  "./avbtool add_hash_footer --salt d00df00d "
590                  "--hash_algorithm sha256 --image %s "
591                  "--partition_size %d --partition_name foobar "
592                  "--algorithm SHA256_RSA2048 "
593                  "--key test/data/testkey_rsa2048.pem "
594                  "--internal_release_string \"\"",
595                  partition_path.value().c_str(),
596                  (int)partition_size);
597 
598   // Since we may be using an arbritary version of make_ext4fs
599   // (because of different branches) the contents of the resulting
600   // disk image may slightly change. It's enough to just remove the
601   // "Digest:" line from the output to work around this.
602   std::string info =
603       RemoveLinesStartingWith(InfoImage(partition_path), "      Digest:");
604   ASSERT_EQ(
605       "Footer version:           1.0\n"
606       "Image size:               10485760 bytes\n"
607       "Original image size:      10354688 bytes\n"
608       "VBMeta offset:            10354688\n"
609       "VBMeta size:              1280 bytes\n"
610       "--\n"
611       "Minimum libavb version:   1.0 (Sparse)\n"
612       "Header Block:             256 bytes\n"
613       "Authentication Block:     320 bytes\n"
614       "Auxiliary Block:          704 bytes\n"
615       "Algorithm:                SHA256_RSA2048\n"
616       "Rollback Index:           0\n"
617       "Flags:                    0\n"
618       "Release String:           ''\n"
619       "Descriptors:\n"
620       "    Hash descriptor:\n"
621       "      Image Size:            10354688 bytes\n"
622       "      Hash Algorithm:        sha256\n"
623       "      Partition Name:        foobar\n"
624       "      Salt:                  d00df00d\n",
625       info);
626 
627   EXPECT_COMMAND(0,
628                  "mv %s %s.sparse",
629                  partition_path.value().c_str(),
630                  partition_path.value().c_str());
631   EXPECT_COMMAND(0,
632                  "simg2img %s.sparse %s",
633                  partition_path.value().c_str(),
634                  partition_path.value().c_str());
635   EXPECT_COMMAND(0, "rm -f %s.sparse", partition_path.value().c_str());
636 }
637 
AddHashtreeFooterTest(bool sparse_image)638 void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
639   const size_t rootfs_size = 1028 * 1024;
640   const size_t partition_size = 1536 * 1024;
641 
642   // Generate a 1028 KiB file with known content.
643   std::vector<uint8_t> rootfs;
644   rootfs.resize(rootfs_size);
645   for (size_t n = 0; n < rootfs_size; n++)
646     rootfs[n] = uint8_t(n);
647   base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
648   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
649   EXPECT_EQ(rootfs_size,
650             static_cast<const size_t>(
651                 base::WriteFile(rootfs_path,
652                                 reinterpret_cast<const char*>(rootfs.data()),
653                                 rootfs.size())));
654 
655   if (sparse_image) {
656     EXPECT_COMMAND(0,
657                    "mv %s %s.unsparse",
658                    rootfs_path.value().c_str(),
659                    rootfs_path.value().c_str());
660     EXPECT_COMMAND(0,
661                    "img2simg %s.unsparse %s",
662                    rootfs_path.value().c_str(),
663                    rootfs_path.value().c_str());
664     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
665   }
666 
667   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
668   for (int n = 0; n < 2; n++) {
669     EXPECT_COMMAND(0,
670                    "./avbtool add_hashtree_footer --salt d00df00d --image %s "
671                    "--partition_size %d --partition_name foobar "
672                    "--algorithm SHA256_RSA2048 "
673                    "--key test/data/testkey_rsa2048.pem "
674                    "--output_vbmeta_image %s "
675                    "--internal_release_string \"\"",
676                    rootfs_path.value().c_str(),
677                    (int)partition_size,
678                    ext_vbmeta_path.value().c_str());
679 
680     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
681                                  "Image size:               1572864 bytes\n"
682                                  "Original image size:      1052672 bytes\n"
683                                  "VBMeta offset:            1069056\n"
684                                  "VBMeta size:              1344 bytes\n"
685                                  "--\n"
686                                  "Minimum libavb version:   1.0%s\n"
687                                  "Header Block:             256 bytes\n"
688                                  "Authentication Block:     320 bytes\n"
689                                  "Auxiliary Block:          768 bytes\n"
690                                  "Algorithm:                SHA256_RSA2048\n"
691                                  "Rollback Index:           0\n"
692                                  "Flags:                    0\n"
693                                  "Release String:           ''\n"
694                                  "Descriptors:\n"
695                                  "    Hashtree descriptor:\n"
696                                  "      Version of dm-verity:  1\n"
697                                  "      Image Size:            1052672 bytes\n"
698                                  "      Tree Offset:           1052672\n"
699                                  "      Tree Size:             16384 bytes\n"
700                                  "      Data Block Size:       4096 bytes\n"
701                                  "      Hash Block Size:       4096 bytes\n"
702                                  "      FEC num roots:         0\n"
703                                  "      FEC offset:            0\n"
704                                  "      FEC size:              0 bytes\n"
705                                  "      Hash Algorithm:        sha1\n"
706                                  "      Partition Name:        foobar\n"
707                                  "      Salt:                  d00df00d\n"
708                                  "      Root Digest:           "
709                                  "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
710                                  sparse_image ? " (Sparse)" : ""),
711               InfoImage(rootfs_path));
712 
713     ASSERT_EQ(
714         "Minimum libavb version:   1.0\n"
715         "Header Block:             256 bytes\n"
716         "Authentication Block:     320 bytes\n"
717         "Auxiliary Block:          768 bytes\n"
718         "Algorithm:                SHA256_RSA2048\n"
719         "Rollback Index:           0\n"
720         "Flags:                    0\n"
721         "Release String:           ''\n"
722         "Descriptors:\n"
723         "    Hashtree descriptor:\n"
724         "      Version of dm-verity:  1\n"
725         "      Image Size:            1052672 bytes\n"
726         "      Tree Offset:           1052672\n"
727         "      Tree Size:             16384 bytes\n"
728         "      Data Block Size:       4096 bytes\n"
729         "      Hash Block Size:       4096 bytes\n"
730         "      FEC num roots:         0\n"
731         "      FEC offset:            0\n"
732         "      FEC size:              0 bytes\n"
733         "      Hash Algorithm:        sha1\n"
734         "      Partition Name:        foobar\n"
735         "      Salt:                  d00df00d\n"
736         "      Root Digest:           "
737         "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
738         InfoImage(ext_vbmeta_path));
739   }
740 
741   if (sparse_image) {
742     EXPECT_COMMAND(0,
743                    "mv %s %s.sparse",
744                    rootfs_path.value().c_str(),
745                    rootfs_path.value().c_str());
746     EXPECT_COMMAND(0,
747                    "simg2img %s.sparse %s",
748                    rootfs_path.value().c_str(),
749                    rootfs_path.value().c_str());
750     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
751   }
752 
753   // To check that we generate the correct hashtree we can use
754   // veritysetup(1) - another codebase for working with dm-verity
755   // hashtrees - to verify it.
756   //
757   // If we don't want to impose the requirement of having the
758   // veritysetup(1) command available on builders we can comment this
759   // out.
760   EXPECT_COMMAND(0,
761                  "veritysetup --no-superblock --format=1 --hash=sha1 "
762                  "--data-block-size=4096 --hash-block-size=4096 "
763                  "--salt=d00df00d "
764                  "--data-blocks=257 "
765                  "--hash-offset=1052672 "
766                  "verify "
767                  "%s %s "
768                  "e811611467dcd6e8dc4324e45f706c2bdd51db67",
769                  rootfs_path.value().c_str(),
770                  rootfs_path.value().c_str());
771 
772   // Now check that we can find the VBMeta block again from the footer.
773   std::string part_data;
774   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
775 
776   // Check footer contains correct data.
777   AvbFooter f;
778   EXPECT_NE(0,
779             avb_footer_validate_and_byteswap(
780                 reinterpret_cast<const AvbFooter*>(
781                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
782                 &f));
783   EXPECT_EQ(
784       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
785       AVB_FOOTER_MAGIC);
786   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
787   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
788   EXPECT_EQ(1052672UL, f.original_image_size);
789   EXPECT_EQ(1069056UL, f.vbmeta_offset);
790   EXPECT_EQ(1344UL, f.vbmeta_size);
791 
792   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
793   const uint8_t* vbmeta_data =
794       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
795   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
796             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
797 
798   // Collect all descriptors.
799   std::vector<const AvbDescriptor*> descriptors;
800   avb_descriptor_foreach(
801       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
802 
803   // We should only have a single descriptor and it should be a
804   // hashtree descriptor.
805   EXPECT_EQ(1UL, descriptors.size());
806   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
807   AvbHashtreeDescriptor d;
808   EXPECT_NE(
809       0,
810       avb_hashtree_descriptor_validate_and_byteswap(
811           reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
812   EXPECT_EQ(1UL, d.dm_verity_version);
813   EXPECT_EQ(1052672UL, d.image_size);
814   EXPECT_EQ(1052672UL, d.tree_offset);
815   EXPECT_EQ(16384UL, d.tree_size);
816   EXPECT_EQ(4096UL, d.data_block_size);
817   EXPECT_EQ(4096UL, d.hash_block_size);
818   EXPECT_EQ(6UL, d.partition_name_len);
819   EXPECT_EQ(4UL, d.salt_len);
820   EXPECT_EQ(20UL, d.root_digest_len);
821   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
822                             sizeof(AvbHashtreeDescriptor);
823   uint64_t o = 0;
824   EXPECT_EQ("foobar",
825             std::string(reinterpret_cast<const char*>(desc_end + o),
826                         d.partition_name_len));
827   o += d.partition_name_len;
828   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
829   o += d.salt_len;
830   EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
831             mem_to_hexstring(desc_end + o, d.root_digest_len));
832 
833   // Check that we correctly generate dm-verity kernel cmdline
834   // snippets, if requested.
835   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
836   EXPECT_COMMAND(0,
837                  "./avbtool make_vbmeta_image "
838                  "--output %s "
839                  "--setup_rootfs_from_kernel %s "
840                  "--algorithm SHA256_RSA2048 "
841                  "--key test/data/testkey_rsa2048.pem "
842                  "--internal_release_string \"\"",
843                  vbmeta_dmv_path.value().c_str(),
844                  rootfs_path.value().c_str());
845 
846   ASSERT_EQ(
847       "Minimum libavb version:   1.0\n"
848       "Header Block:             256 bytes\n"
849       "Authentication Block:     320 bytes\n"
850       "Auxiliary Block:          896 bytes\n"
851       "Algorithm:                SHA256_RSA2048\n"
852       "Rollback Index:           0\n"
853       "Flags:                    0\n"
854       "Release String:           ''\n"
855       "Descriptors:\n"
856       "    Kernel Cmdline descriptor:\n"
857       "      Flags:                 1\n"
858       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
859       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
860       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
861       "d00df00d 2 restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0'\n"
862       "    Kernel Cmdline descriptor:\n"
863       "      Flags:                 2\n"
864       "      Kernel Cmdline:        "
865       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
866       InfoImage(vbmeta_dmv_path));
867 
868   // Check that the footer is correctly erased and the hashtree
869   // remains - see above for why the constant 1069056 is used.
870   EXPECT_COMMAND(0,
871                  "./avbtool erase_footer --image %s --keep_hashtree",
872                  rootfs_path.value().c_str());
873   int64_t erased_footer_file_size;
874   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
875   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1069056UL);
876 
877   // Check that --do_not_append_vbmeta_image works as intended.
878   //
879   // For this we need to reset the size of the image to the original
880   // size because it's not possible to identify the existing hashtree.
881   EXPECT_COMMAND(
882       0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str());
883   EXPECT_COMMAND(0,
884                  "./avbtool add_hashtree_footer --salt d00df00d --image %s "
885                  "--partition_size %d --partition_name foobar "
886                  "--algorithm SHA256_RSA2048 "
887                  "--key test/data/testkey_rsa2048.pem "
888                  "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
889                  "--internal_release_string \"\"",
890                  rootfs_path.value().c_str(),
891                  (int)partition_size,
892                  ext_vbmeta_path.value().c_str());
893   int64_t file_size;
894   ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
895   EXPECT_EQ(static_cast<size_t>(file_size), 1069056UL);
896   EXPECT_COMMAND(0,
897                  "diff %s %s_2nd_run",
898                  ext_vbmeta_path.value().c_str(),
899                  ext_vbmeta_path.value().c_str());
900 }
901 
TEST_F(AvbToolTest,AddHashtreeFooter)902 TEST_F(AvbToolTest, AddHashtreeFooter) {
903   AddHashtreeFooterTest(false);
904 }
905 
TEST_F(AvbToolTest,AddHashtreeFooterSparse)906 TEST_F(AvbToolTest, AddHashtreeFooterSparse) {
907   AddHashtreeFooterTest(true);
908 }
909 
AddHashtreeFooterFECTest(bool sparse_image)910 void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
911   const size_t rootfs_size = 1028 * 1024;
912   const size_t partition_size = 1536 * 1024;
913 
914   // Generate a 1028 KiB file with known content.
915   std::vector<uint8_t> rootfs;
916   rootfs.resize(rootfs_size);
917   for (size_t n = 0; n < rootfs_size; n++)
918     rootfs[n] = uint8_t(n);
919   base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
920   EXPECT_EQ(rootfs_size,
921             static_cast<const size_t>(
922                 base::WriteFile(rootfs_path,
923                                 reinterpret_cast<const char*>(rootfs.data()),
924                                 rootfs.size())));
925 
926   if (sparse_image) {
927     EXPECT_COMMAND(0,
928                    "mv %s %s.unsparse",
929                    rootfs_path.value().c_str(),
930                    rootfs_path.value().c_str());
931     EXPECT_COMMAND(0,
932                    "img2simg %s.unsparse %s",
933                    rootfs_path.value().c_str(),
934                    rootfs_path.value().c_str());
935     EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
936   }
937 
938   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
939   for (int n = 0; n < 2; n++) {
940     EXPECT_COMMAND(0,
941                    "./avbtool add_hashtree_footer --salt d00df00d --image %s "
942                    "--partition_size %d --partition_name foobar "
943                    "--generate_fec "
944                    "--algorithm SHA256_RSA2048 "
945                    "--key test/data/testkey_rsa2048.pem "
946                    "--internal_release_string \"\"",
947                    rootfs_path.value().c_str(),
948                    (int)partition_size);
949 
950     ASSERT_EQ(base::StringPrintf("Footer version:           1.0\n"
951                                  "Image size:               1572864 bytes\n"
952                                  "Original image size:      1052672 bytes\n"
953                                  "VBMeta offset:            1085440\n"
954                                  "VBMeta size:              1344 bytes\n"
955                                  "--\n"
956                                  "Minimum libavb version:   1.0%s\n"
957                                  "Header Block:             256 bytes\n"
958                                  "Authentication Block:     320 bytes\n"
959                                  "Auxiliary Block:          768 bytes\n"
960                                  "Algorithm:                SHA256_RSA2048\n"
961                                  "Rollback Index:           0\n"
962                                  "Flags:                    0\n"
963                                  "Release String:           ''\n"
964                                  "Descriptors:\n"
965                                  "    Hashtree descriptor:\n"
966                                  "      Version of dm-verity:  1\n"
967                                  "      Image Size:            1052672 bytes\n"
968                                  "      Tree Offset:           1052672\n"
969                                  "      Tree Size:             16384 bytes\n"
970                                  "      Data Block Size:       4096 bytes\n"
971                                  "      Hash Block Size:       4096 bytes\n"
972                                  "      FEC num roots:         2\n"
973                                  "      FEC offset:            1069056\n"
974                                  "      FEC size:              16384 bytes\n"
975                                  "      Hash Algorithm:        sha1\n"
976                                  "      Partition Name:        foobar\n"
977                                  "      Salt:                  d00df00d\n"
978                                  "      Root Digest:           "
979                                  "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
980                                  sparse_image ? " (Sparse)" : ""),
981               InfoImage(rootfs_path));
982   }
983 
984   if (sparse_image) {
985     EXPECT_COMMAND(0,
986                    "mv %s %s.sparse",
987                    rootfs_path.value().c_str(),
988                    rootfs_path.value().c_str());
989     EXPECT_COMMAND(0,
990                    "simg2img %s.sparse %s",
991                    rootfs_path.value().c_str(),
992                    rootfs_path.value().c_str());
993     EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
994   }
995 
996   /* TODO: would be nice to verify that the FEC data is correct. */
997 
998   // Now check that we can find the VBMeta block again from the footer.
999   std::string part_data;
1000   ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1001 
1002   // Check footer contains correct data.
1003   AvbFooter f;
1004   EXPECT_NE(0,
1005             avb_footer_validate_and_byteswap(
1006                 reinterpret_cast<const AvbFooter*>(
1007                     part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1008                 &f));
1009   EXPECT_EQ(
1010       std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1011       AVB_FOOTER_MAGIC);
1012   EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1013   EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1014   EXPECT_EQ(1052672UL, f.original_image_size);
1015   EXPECT_EQ(1085440UL, f.vbmeta_offset);
1016   EXPECT_EQ(1344UL, f.vbmeta_size);
1017 
1018   // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1019   const uint8_t* vbmeta_data =
1020       reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1021   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1022             avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1023 
1024   // Collect all descriptors.
1025   std::vector<const AvbDescriptor*> descriptors;
1026   avb_descriptor_foreach(
1027       vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1028 
1029   // We should only have a single descriptor and it should be a
1030   // hashtree descriptor.
1031   EXPECT_EQ(1UL, descriptors.size());
1032   EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1033   AvbHashtreeDescriptor d;
1034   EXPECT_NE(
1035       0,
1036       avb_hashtree_descriptor_validate_and_byteswap(
1037           reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1038   EXPECT_EQ(1UL, d.dm_verity_version);
1039   EXPECT_EQ(1052672UL, d.image_size);
1040   EXPECT_EQ(1052672UL, d.tree_offset);
1041   EXPECT_EQ(16384UL, d.tree_size);
1042   EXPECT_EQ(4096UL, d.data_block_size);
1043   EXPECT_EQ(2UL, d.fec_num_roots);
1044   EXPECT_EQ(1069056UL, d.fec_offset);
1045   EXPECT_EQ(16384UL, d.fec_size);
1046   EXPECT_EQ(6UL, d.partition_name_len);
1047   EXPECT_EQ(4UL, d.salt_len);
1048   EXPECT_EQ(20UL, d.root_digest_len);
1049   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1050                             sizeof(AvbHashtreeDescriptor);
1051   uint64_t o = 0;
1052   EXPECT_EQ("foobar",
1053             std::string(reinterpret_cast<const char*>(desc_end + o),
1054                         d.partition_name_len));
1055   o += d.partition_name_len;
1056   EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1057   o += d.salt_len;
1058   EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1059             mem_to_hexstring(desc_end + o, d.root_digest_len));
1060 
1061   // Check that we correctly generate dm-verity kernel cmdline
1062   // snippets, if requested.
1063   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1064   EXPECT_COMMAND(0,
1065                  "./avbtool make_vbmeta_image "
1066                  "--output %s "
1067                  "--setup_rootfs_from_kernel %s "
1068                  "--algorithm SHA256_RSA2048 "
1069                  "--key test/data/testkey_rsa2048.pem "
1070                  "--internal_release_string \"\"",
1071                  vbmeta_dmv_path.value().c_str(),
1072                  rootfs_path.value().c_str());
1073 
1074   ASSERT_EQ(
1075       "Minimum libavb version:   1.0\n"
1076       "Header Block:             256 bytes\n"
1077       "Authentication Block:     320 bytes\n"
1078       "Auxiliary Block:          960 bytes\n"
1079       "Algorithm:                SHA256_RSA2048\n"
1080       "Rollback Index:           0\n"
1081       "Flags:                    0\n"
1082       "Release String:           ''\n"
1083       "Descriptors:\n"
1084       "    Kernel Cmdline descriptor:\n"
1085       "      Flags:                 1\n"
1086       "      Kernel Cmdline:        'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1087       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1088       "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1089       "d00df00d 10 restart_on_corruption ignore_zero_blocks "
1090       "use_fec_from_device "
1091       "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 261 "
1092       "fec_start 261\" root=/dev/dm-0'\n"
1093       "    Kernel Cmdline descriptor:\n"
1094       "      Flags:                 2\n"
1095       "      Kernel Cmdline:        "
1096       "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1097       InfoImage(vbmeta_dmv_path));
1098 
1099   // Check that the footer is correctly erased and the hashtree and
1100   // FEC data remains. The constant 1085440 is used because it's where
1101   // the FEC data ends (it's at offset 1069056 and size 16384).
1102   EXPECT_COMMAND(0,
1103                  "./avbtool erase_footer --image %s --keep_hashtree",
1104                  rootfs_path.value().c_str());
1105   int64_t erased_footer_file_size;
1106   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1107   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1085440UL);
1108 }
1109 
TEST_F(AvbToolTest,AddHashtreeFooterFEC)1110 TEST_F(AvbToolTest, AddHashtreeFooterFEC) {
1111   AddHashtreeFooterFECTest(false);
1112 }
1113 
TEST_F(AvbToolTest,AddHashtreeFooterFECSparse)1114 TEST_F(AvbToolTest, AddHashtreeFooterFECSparse) {
1115   AddHashtreeFooterFECTest(true);
1116 }
1117 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSize)1118 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSize) {
1119   const size_t partition_size = 10 * 1024 * 1024;
1120   base::FilePath output_path = testdir_.Append("max_size.txt");
1121 
1122   EXPECT_COMMAND(0,
1123                  "./avbtool add_hashtree_footer "
1124                  "--partition_size %zd --calc_max_image_size > %s",
1125                  partition_size,
1126                  output_path.value().c_str());
1127   std::string max_image_size_data;
1128   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1129   EXPECT_EQ("10330112\n", max_image_size_data);
1130   size_t max_image_size = atoll(max_image_size_data.c_str());
1131 
1132   // Hashtree and metadata takes up 152 KiB - compare to below with
1133   // FEC which is 244 KiB.
1134   EXPECT_EQ(152 * 1024ULL, partition_size - max_image_size);
1135 
1136   // Check that we can add a hashtree with an image this size for such
1137   // a partition size.
1138   base::FilePath system_path = GenerateImage("system", max_image_size);
1139   EXPECT_COMMAND(0,
1140                  "./avbtool add_hashtree_footer"
1141                  " --image %s"
1142                  " --partition_name system"
1143                  " --partition_size %zd"
1144                  " --salt deadbeef"
1145                  " --algorithm SHA512_RSA4096 "
1146                  " --key test/data/testkey_rsa4096.pem"
1147                  " --internal_release_string \"\"",
1148                  system_path.value().c_str(),
1149                  partition_size);
1150 }
1151 
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSizeWithFEC)1152 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) {
1153   const size_t partition_size = 10 * 1024 * 1024;
1154   base::FilePath output_path = testdir_.Append("max_size.txt");
1155 
1156   EXPECT_COMMAND(0,
1157                  "./avbtool add_hashtree_footer "
1158                  "--partition_size %zd --generate_fec "
1159                  "--calc_max_image_size > %s",
1160                  partition_size,
1161                  output_path.value().c_str());
1162   std::string max_image_size_data;
1163   EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1164   EXPECT_EQ("10235904\n", max_image_size_data);
1165   size_t max_image_size = atoll(max_image_size_data.c_str());
1166 
1167   // Hashtree, FEC codes, and metadata takes up 244 KiB - compare to
1168   // above wihtout FEC which is 152 KiB.
1169   EXPECT_EQ(244 * 1024ULL, partition_size - max_image_size);
1170 
1171   // Check that we can add a hashtree with an image this size for such
1172   // a partition size.
1173   base::FilePath system_path = GenerateImage("system", max_image_size);
1174   EXPECT_COMMAND(0,
1175                  "./avbtool add_hashtree_footer"
1176                  " --image %s"
1177                  " --partition_name system"
1178                  " --partition_size %zd"
1179                  " --salt deadbeef"
1180                  " --generate_fec "
1181                  " --algorithm SHA512_RSA4096 "
1182                  " --key test/data/testkey_rsa4096.pem"
1183                  " --internal_release_string \"\"",
1184                  system_path.value().c_str(),
1185                  partition_size);
1186 }
1187 
TEST_F(AvbToolTest,KernelCmdlineDescriptor)1188 TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
1189   base::FilePath vbmeta_path =
1190       testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
1191 
1192   EXPECT_COMMAND(0,
1193                  "./avbtool make_vbmeta_image "
1194                  "--output %s "
1195                  "--kernel_cmdline 'foo bar baz' "
1196                  "--kernel_cmdline 'second cmdline' "
1197                  "--algorithm SHA256_RSA2048 "
1198                  "--key test/data/testkey_rsa2048.pem "
1199                  "--internal_release_string \"\"",
1200                  vbmeta_path.value().c_str());
1201 
1202   ASSERT_EQ(
1203       "Minimum libavb version:   1.0\n"
1204       "Header Block:             256 bytes\n"
1205       "Authentication Block:     320 bytes\n"
1206       "Auxiliary Block:          640 bytes\n"
1207       "Algorithm:                SHA256_RSA2048\n"
1208       "Rollback Index:           0\n"
1209       "Flags:                    0\n"
1210       "Release String:           ''\n"
1211       "Descriptors:\n"
1212       "    Kernel Cmdline descriptor:\n"
1213       "      Flags:                 0\n"
1214       "      Kernel Cmdline:        'foo bar baz'\n"
1215       "    Kernel Cmdline descriptor:\n"
1216       "      Flags:                 0\n"
1217       "      Kernel Cmdline:        'second cmdline'\n",
1218       InfoImage(vbmeta_path));
1219 
1220   // Now check the VBMeta image.
1221   std::string image_data;
1222   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1223 
1224   const uint8_t* vbmeta_data =
1225       reinterpret_cast<const uint8_t*>(image_data.data());
1226   const size_t vbmeta_size = image_data.length();
1227   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1228             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1229 
1230   // Collect all descriptors.
1231   std::vector<const AvbDescriptor*> descriptors;
1232   avb_descriptor_foreach(
1233       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1234 
1235   // We should have two descriptors - check them.
1236   EXPECT_EQ(2UL, descriptors.size());
1237   AvbKernelCmdlineDescriptor d;
1238   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1239             avb_be64toh(descriptors[0]->tag));
1240   EXPECT_NE(
1241       0,
1242       avb_kernel_cmdline_descriptor_validate_and_byteswap(
1243           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]),
1244           &d));
1245   EXPECT_EQ("foo bar baz",
1246             std::string(reinterpret_cast<const char*>(descriptors[0]) +
1247                             sizeof(AvbKernelCmdlineDescriptor),
1248                         d.kernel_cmdline_length));
1249   EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1250             avb_be64toh(descriptors[1]->tag));
1251   EXPECT_NE(
1252       0,
1253       avb_kernel_cmdline_descriptor_validate_and_byteswap(
1254           reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]),
1255           &d));
1256   EXPECT_EQ("second cmdline",
1257             std::string(reinterpret_cast<const char*>(descriptors[1]) +
1258                             sizeof(AvbKernelCmdlineDescriptor),
1259                         d.kernel_cmdline_length));
1260 }
1261 
TEST_F(AvbToolTest,IncludeDescriptor)1262 TEST_F(AvbToolTest, IncludeDescriptor) {
1263   base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin");
1264   base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin");
1265   base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
1266 
1267   EXPECT_COMMAND(0,
1268                  "./avbtool make_vbmeta_image "
1269                  "--output %s "
1270                  "--kernel_cmdline 'something' "
1271                  "--prop name:value "
1272                  "--internal_release_string \"\"",
1273                  vbmeta1_path.value().c_str());
1274 
1275   EXPECT_COMMAND(0,
1276                  "./avbtool make_vbmeta_image "
1277                  "--output %s "
1278                  "--prop name2:value2 "
1279                  "--prop name3:value3 "
1280                  "--internal_release_string \"\"",
1281                  vbmeta2_path.value().c_str());
1282 
1283   EXPECT_COMMAND(0,
1284                  "./avbtool make_vbmeta_image "
1285                  "--output %s "
1286                  "--prop name4:value4 "
1287                  "--include_descriptors_from_image %s "
1288                  "--include_descriptors_from_image %s "
1289                  "--internal_release_string \"\"",
1290                  vbmeta3_path.value().c_str(),
1291                  vbmeta1_path.value().c_str(),
1292                  vbmeta2_path.value().c_str());
1293 
1294   ASSERT_EQ(
1295       "Minimum libavb version:   1.0\n"
1296       "Header Block:             256 bytes\n"
1297       "Authentication Block:     0 bytes\n"
1298       "Auxiliary Block:          256 bytes\n"
1299       "Algorithm:                NONE\n"
1300       "Rollback Index:           0\n"
1301       "Flags:                    0\n"
1302       "Release String:           ''\n"
1303       "Descriptors:\n"
1304       "    Prop: name4 -> 'value4'\n"
1305       "    Prop: name -> 'value'\n"
1306       "    Kernel Cmdline descriptor:\n"
1307       "      Flags:                 0\n"
1308       "      Kernel Cmdline:        'something'\n"
1309       "    Prop: name2 -> 'value2'\n"
1310       "    Prop: name3 -> 'value3'\n",
1311       InfoImage(vbmeta3_path));
1312 }
1313 
TEST_F(AvbToolTest,ChainedPartition)1314 TEST_F(AvbToolTest, ChainedPartition) {
1315   base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1316 
1317   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1318 
1319   EXPECT_COMMAND(
1320       0,
1321       "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1322       " --output %s",
1323       pk_path.value().c_str());
1324 
1325   EXPECT_COMMAND(
1326       0,
1327       "./avbtool make_vbmeta_image "
1328       "--output %s "
1329       "--chain_partition system:1:%s "
1330       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1331       "--internal_release_string \"\"",
1332       vbmeta_path.value().c_str(),
1333       pk_path.value().c_str());
1334 
1335   ASSERT_EQ(
1336       "Minimum libavb version:   1.0\n"
1337       "Header Block:             256 bytes\n"
1338       "Authentication Block:     320 bytes\n"
1339       "Auxiliary Block:          1152 bytes\n"
1340       "Algorithm:                SHA256_RSA2048\n"
1341       "Rollback Index:           0\n"
1342       "Flags:                    0\n"
1343       "Release String:           ''\n"
1344       "Descriptors:\n"
1345       "    Chain Partition descriptor:\n"
1346       "      Partition Name:          system\n"
1347       "      Rollback Index Location: 1\n"
1348       "      Public key (sha1):       "
1349       "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n",
1350       InfoImage(vbmeta_path));
1351 
1352   // Now check the VBMeta image.
1353   std::string image_data;
1354   ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1355 
1356   const uint8_t* vbmeta_data =
1357       reinterpret_cast<const uint8_t*>(image_data.data());
1358   const size_t vbmeta_size = image_data.length();
1359   EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1360             avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1361 
1362   // Collect all descriptors.
1363   std::vector<const AvbDescriptor*> descriptors;
1364   avb_descriptor_foreach(
1365       vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1366 
1367   // We should have one descriptor - check it.
1368   EXPECT_EQ(1UL, descriptors.size());
1369 
1370   std::string pk_data;
1371   ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data));
1372 
1373   AvbChainPartitionDescriptor d;
1374   EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
1375             avb_be64toh(descriptors[0]->tag));
1376   EXPECT_NE(
1377       0,
1378       avb_chain_partition_descriptor_validate_and_byteswap(
1379           reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]),
1380           &d));
1381   const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1382                             sizeof(AvbChainPartitionDescriptor);
1383   uint64_t o = 0;
1384   EXPECT_EQ("system",
1385             std::string(reinterpret_cast<const char*>(desc_end + o),
1386                         d.partition_name_len));
1387   o += d.partition_name_len;
1388   EXPECT_EQ(pk_data,
1389             std::string(reinterpret_cast<const char*>(descriptors[0]) +
1390                             sizeof(AvbChainPartitionDescriptor) + o,
1391                         d.public_key_len));
1392 }
1393 
TEST_F(AvbToolTest,AppendVBMetaImage)1394 TEST_F(AvbToolTest, AppendVBMetaImage) {
1395   size_t boot_size = 5 * 1024 * 1024;
1396   size_t boot_partition_size = 32 * 1024 * 1024;
1397   base::FilePath boot_path = GenerateImage("boot", boot_size);
1398 
1399   GenerateVBMetaImage("vbmeta.img",
1400                       "SHA256_RSA2048",
1401                       0,
1402                       base::FilePath("test/data/testkey_rsa2048.pem"),
1403                       std::string("--append_to_release_string \"\" "
1404                                   "--kernel_cmdline foo"));
1405 
1406   EXPECT_COMMAND(0,
1407                  "./avbtool append_vbmeta_image "
1408                  "--image %s "
1409                  "--partition_size %d "
1410                  "--vbmeta_image %s ",
1411                  boot_path.value().c_str(),
1412                  (int)boot_partition_size,
1413                  vbmeta_image_path_.value().c_str());
1414 
1415   std::string vbmeta_contents = InfoImage(vbmeta_image_path_);
1416   std::string boot_contents = InfoImage(boot_path);
1417 
1418   // Check that boot.img has the same vbmeta blob as from vbmeta.img -
1419   // we do this by inspecting 'avbtool info_image' output combined
1420   // with the known footer location given boot.img has 5 MiB known
1421   // content and the partition size is 32 MiB.
1422   ASSERT_EQ(
1423       "Minimum libavb version:   1.0\n"
1424       "Header Block:             256 bytes\n"
1425       "Authentication Block:     320 bytes\n"
1426       "Auxiliary Block:          576 bytes\n"
1427       "Algorithm:                SHA256_RSA2048\n"
1428       "Rollback Index:           0\n"
1429       "Flags:                    0\n"
1430       "Release String:           'avbtool 1.0.0 '\n"
1431       "Descriptors:\n"
1432       "    Kernel Cmdline descriptor:\n"
1433       "      Flags:                 0\n"
1434       "      Kernel Cmdline:        'foo'\n",
1435       vbmeta_contents);
1436   std::string known_footer =
1437       "Footer version:           1.0\n"
1438       "Image size:               33554432 bytes\n"
1439       "Original image size:      5242880 bytes\n"
1440       "VBMeta offset:            5242880\n"
1441       "VBMeta size:              1152 bytes\n"
1442       "--\n";
1443   ASSERT_EQ(known_footer + vbmeta_contents, boot_contents);
1444 
1445   // Also verify that the blobs are the same, bit for bit.
1446   base::File f =
1447       base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
1448   std::vector<uint8_t> loaded_vbmeta;
1449   loaded_vbmeta.resize(1152);
1450   EXPECT_EQ(
1451       f.Read(
1452           5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152),
1453       1152);
1454   EXPECT_EQ(vbmeta_image_, loaded_vbmeta);
1455 }
1456 
TEST_F(AvbToolTest,SigningHelperBasic)1457 TEST_F(AvbToolTest, SigningHelperBasic) {
1458   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1459   base::FilePath signing_helper_test_path =
1460       testdir_.Append("signing_helper_test");
1461   EXPECT_COMMAND(
1462       0,
1463       "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1464       "--output %s "
1465       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1466       "--signing_helper test/avbtool_signing_helper_test.py "
1467       "--internal_release_string \"\"",
1468       signing_helper_test_path.value().c_str(),
1469       vbmeta_path.value().c_str());
1470 
1471   // Now check the value in test file.
1472   std::string value;
1473   ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1474   EXPECT_EQ("DONE", value);
1475 }
1476 
TEST_F(AvbToolTest,SigningHelperReturnError)1477 TEST_F(AvbToolTest, SigningHelperReturnError) {
1478   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1479   EXPECT_COMMAND(
1480       1,
1481       "./avbtool make_vbmeta_image "
1482       "--output %s "
1483       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1484       "--signing_helper test/avbtool_signing_helper_test.py "
1485       "--internal_release_string \"\"",
1486       vbmeta_path.value().c_str());
1487 }
1488 
TEST_F(AvbToolTest,MakeAtxPikCertificate)1489 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
1490   base::FilePath subject_path = testdir_.Append("tmp_subject");
1491   ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
1492   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
1493   EXPECT_COMMAND(
1494       0,
1495       "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
1496       pubkey_path.value().c_str());
1497 
1498   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
1499   EXPECT_COMMAND(0,
1500                  "./avbtool make_atx_certificate"
1501                  " --subject %s"
1502                  " --subject_key %s"
1503                  " --subject_key_version 42"
1504                  " --subject_is_intermediate_authority"
1505                  " --authority_key test/data/testkey_atx_prk.pem"
1506                  " --output %s",
1507                  subject_path.value().c_str(),
1508                  pubkey_path.value().c_str(),
1509                  output_path.value().c_str());
1510 
1511   EXPECT_COMMAND(0,
1512                  "diff test/data/atx_pik_certificate.bin %s",
1513                  output_path.value().c_str());
1514 }
1515 
TEST_F(AvbToolTest,MakeAtxPskCertificate)1516 TEST_F(AvbToolTest, MakeAtxPskCertificate) {
1517   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
1518   EXPECT_COMMAND(
1519       0,
1520       "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
1521       pubkey_path.value().c_str());
1522 
1523   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
1524   EXPECT_COMMAND(0,
1525                  "./avbtool make_atx_certificate"
1526                  " --subject test/data/atx_product_id.bin"
1527                  " --subject_key %s"
1528                  " --subject_key_version 42"
1529                  " --authority_key test/data/testkey_atx_pik.pem"
1530                  " --output %s",
1531                  pubkey_path.value().c_str(),
1532                  output_path.value().c_str());
1533 
1534   EXPECT_COMMAND(0,
1535                  "diff test/data/atx_psk_certificate.bin %s",
1536                  output_path.value().c_str());
1537 }
1538 
TEST_F(AvbToolTest,MakeAtxPermanentAttributes)1539 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) {
1540   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
1541   EXPECT_COMMAND(
1542       0,
1543       "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
1544       pubkey_path.value().c_str());
1545 
1546   base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
1547   EXPECT_COMMAND(0,
1548                  "./avbtool make_atx_permanent_attributes"
1549                  " --root_authority_key %s"
1550                  " --product_id test/data/atx_product_id.bin"
1551                  " --output %s",
1552                  pubkey_path.value().c_str(),
1553                  output_path.value().c_str());
1554 
1555   EXPECT_COMMAND(0,
1556                  "diff test/data/atx_permanent_attributes.bin %s",
1557                  output_path.value().c_str());
1558 }
1559 
TEST_F(AvbToolTest,MakeAtxMetadata)1560 TEST_F(AvbToolTest, MakeAtxMetadata) {
1561   base::FilePath output_path = testdir_.Append("tmp_metadata.bin");
1562 
1563   EXPECT_COMMAND(
1564       0,
1565       "./avbtool make_atx_metadata"
1566       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
1567       " --product_key_certificate test/data/atx_psk_certificate.bin"
1568       " --output %s",
1569       output_path.value().c_str());
1570 
1571   EXPECT_COMMAND(
1572       0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str());
1573 }
1574 
1575 }  // namespace avb
1576