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