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