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