1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <iostream>
26
27 #include <endian.h>
28 #include <inttypes.h>
29 #include <string.h>
30
31 #include <base/files/file_util.h>
32 #include <base/strings/string_split.h>
33 #include <base/strings/string_util.h>
34 #include <base/strings/stringprintf.h>
35
36 #include <libavb/avb_sha.h>
37 #include <libavb/libavb.h>
38
39 #include "avb_unittest_util.h"
40 #include "fake_avb_ops.h"
41
42 namespace avb {
43
44 class AvbToolTest : public BaseAvbToolTest {
45 public:
AvbToolTest()46 AvbToolTest() {}
47
SetUp()48 virtual void SetUp() override {
49 BaseAvbToolTest::SetUp();
50 ops_.set_partition_dir(testdir_);
51 ops_.set_stored_rollback_indexes({{0, 0}, {1, 0}, {2, 0}, {3, 0}});
52 ops_.set_stored_is_device_unlocked(false);
53 }
54
55 void AddHashFooterTest(bool sparse_image);
56 void AddHashtreeFooterTest(bool sparse_image);
57 void AddHashtreeFooterFECTest(bool sparse_image);
58
59 void GenerateImageWithHashAndHashtreeSetup();
60
61 FakeAvbOps ops_;
62 };
63
64 // This test ensure that the version is increased in both
65 // avb_boot_image.h and the avb tool.
TEST_F(AvbToolTest,AvbVersionInSync)66 TEST_F(AvbToolTest, AvbVersionInSync) {
67 base::FilePath path = testdir_.Append("version.txt");
68 EXPECT_COMMAND(0, "./avbtool version > %s", path.value().c_str());
69 std::string printed_version;
70 ASSERT_TRUE(base::ReadFileToString(path, &printed_version));
71 base::TrimWhitespaceASCII(printed_version, base::TRIM_ALL, &printed_version);
72 // See comments in libavb/avb_version.c and avbtool's get_release_string()
73 // about being in sync.
74 EXPECT_EQ(printed_version,
75 std::string("avbtool ") + std::string(avb_version_string()));
76 }
77
TEST_F(AvbToolTest,DefaultReleaseString)78 TEST_F(AvbToolTest, DefaultReleaseString) {
79 GenerateVBMetaImage("vbmeta.img",
80 "SHA256_RSA2048",
81 0,
82 base::FilePath("test/data/testkey_rsa2048.pem"));
83
84 // Default release string is "avbtool " + avb_version_string().
85 AvbVBMetaImageHeader h;
86 avb_vbmeta_image_header_to_host_byte_order(
87 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
88 EXPECT_EQ(std::string("avbtool ") + std::string(avb_version_string()),
89 std::string((const char*)h.release_string));
90 }
91
TEST_F(AvbToolTest,ReleaseStringAppend)92 TEST_F(AvbToolTest, ReleaseStringAppend) {
93 GenerateVBMetaImage("vbmeta.img",
94 "SHA256_RSA2048",
95 0,
96 base::FilePath("test/data/testkey_rsa2048.pem"),
97 "--append_to_release_string \"Woot XYZ\"");
98
99 // Note that avbtool inserts the space by itself.
100 std::string expected_str =
101 std::string("avbtool ") + std::string(avb_version_string()) + " Woot XYZ";
102
103 AvbVBMetaImageHeader h;
104 avb_vbmeta_image_header_to_host_byte_order(
105 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
106 EXPECT_EQ(expected_str, std::string((const char*)h.release_string));
107 }
108
TEST_F(AvbToolTest,ReleaseStringAppendTruncated)109 TEST_F(AvbToolTest, ReleaseStringAppendTruncated) {
110 // Append enough text that truncation is sure to happen.
111 std::string append_str = "0123456789abcdef0123456789abcdef0123456789abcdef";
112 std::string expected_str = std::string("avbtool ") +
113 std::string(avb_version_string()) + " " +
114 append_str;
115 EXPECT_GT(expected_str.size(), (size_t)(AVB_RELEASE_STRING_SIZE - 1));
116 expected_str.resize(AVB_RELEASE_STRING_SIZE - 1);
117
118 GenerateVBMetaImage(
119 "vbmeta.img",
120 "SHA256_RSA2048",
121 0,
122 base::FilePath("test/data/testkey_rsa2048.pem"),
123 std::string("--append_to_release_string \"") + append_str + "\"");
124
125 // This checks that it ends with a NUL byte.
126 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
127 avb_vbmeta_image_verify(
128 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr));
129
130 // For good measure we also check here.
131 AvbVBMetaImageHeader h;
132 avb_vbmeta_image_header_to_host_byte_order(
133 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
134 EXPECT_EQ(expected_str, std::string((const char*)h.release_string));
135 }
136
TEST_F(AvbToolTest,ExtractPublicKey)137 TEST_F(AvbToolTest, ExtractPublicKey) {
138 GenerateVBMetaImage("vbmeta.img",
139 "SHA256_RSA2048",
140 0,
141 base::FilePath("test/data/testkey_rsa2048.pem"),
142 "--internal_release_string \"\"");
143
144 std::string key_data =
145 PublicKeyAVB(base::FilePath("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 base::FilePath("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 base::FilePath("test/data/testkey_rsa2048.pem"),
271 "--internal_release_string \"\"");
272
273 GenerateVBMetaImage("vbmeta_padded.img",
274 "SHA256_RSA2048",
275 0,
276 base::FilePath("test/data/testkey_rsa2048.pem"),
277 "--internal_release_string \"\" --padding_size 4096");
278
279 base::FilePath vbmeta_path = testdir_.Append("vbmeta.img");
280 base::FilePath vbmeta_padded_path = testdir_.Append("vbmeta_padded.img");
281 int64_t vbmeta_size, vbmeta_padded_size;
282 ASSERT_TRUE(base::GetFileSize(vbmeta_path, &vbmeta_size));
283 ASSERT_TRUE(base::GetFileSize(vbmeta_padded_path, &vbmeta_padded_size));
284
285 EXPECT_NE(vbmeta_size, vbmeta_padded_size);
286
287 // The padded size should be a multiple of 4096.
288 EXPECT_EQ(vbmeta_padded_size % 4096, 0);
289
290 // When rounded up the unpadded size should equal the padded size.
291 int64_t vbmeta_size_rounded_up = ((vbmeta_size + 4095) / 4096) * 4096;
292 EXPECT_EQ(vbmeta_size_rounded_up, vbmeta_padded_size);
293 }
294
TEST_F(AvbToolTest,CheckRollbackIndex)295 TEST_F(AvbToolTest, CheckRollbackIndex) {
296 uint64_t rollback_index = 42;
297 GenerateVBMetaImage("vbmeta.img",
298 "SHA256_RSA2048",
299 rollback_index,
300 base::FilePath("test/data/testkey_rsa2048.pem"),
301 "--internal_release_string \"\"");
302
303 AvbVBMetaImageHeader h;
304 avb_vbmeta_image_header_to_host_byte_order(
305 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
306
307 EXPECT_EQ(rollback_index, h.rollback_index);
308 }
309
TEST_F(AvbToolTest,CheckPubkeyReturned)310 TEST_F(AvbToolTest, CheckPubkeyReturned) {
311 GenerateVBMetaImage("vbmeta.img",
312 "SHA256_RSA2048",
313 0,
314 base::FilePath("test/data/testkey_rsa2048.pem"),
315 "--internal_release_string \"\"");
316
317 const uint8_t* pubkey = NULL;
318 size_t pubkey_length = 0;
319
320 EXPECT_EQ(
321 AVB_VBMETA_VERIFY_RESULT_OK,
322 avb_vbmeta_image_verify(
323 vbmeta_image_.data(), vbmeta_image_.size(), &pubkey, &pubkey_length));
324
325 AvbVBMetaImageHeader h;
326 avb_vbmeta_image_header_to_host_byte_order(
327 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);
328
329 EXPECT_EQ(pubkey_length, h.public_key_size);
330
331 const uint8_t* expected_pubkey =
332 vbmeta_image_.data() + sizeof(AvbVBMetaImageHeader) +
333 h.authentication_data_block_size + h.public_key_offset;
334 EXPECT_EQ(pubkey, expected_pubkey);
335 }
336
TEST_F(AvbToolTest,Info)337 TEST_F(AvbToolTest, Info) {
338 GenerateVBMetaImage("vbmeta.img",
339 "SHA256_RSA2048",
340 0,
341 base::FilePath("test/data/testkey_rsa2048.pem"),
342 "--prop foo:brillo "
343 "--prop bar:chromeos "
344 "--prop prisoner:24601 "
345 "--prop hexnumber:0xcafe "
346 "--prop hexnumber_capital:0xCAFE "
347 "--prop large_hexnumber:0xfedcba9876543210 "
348 "--prop larger_than_uint64:0xfedcba98765432101 "
349 "--prop almost_a_number:423x "
350 "--prop_from_file blob:test/data/small_blob.bin "
351 "--prop_from_file large_blob:test/data/large_blob.bin "
352 "--internal_release_string \"\"");
353
354 ASSERT_EQ(
355 "Minimum libavb version: 1.0\n"
356 "Header Block: 256 bytes\n"
357 "Authentication Block: 320 bytes\n"
358 "Auxiliary Block: 3200 bytes\n"
359 "Algorithm: SHA256_RSA2048\n"
360 "Rollback Index: 0\n"
361 "Flags: 0\n"
362 "Release String: ''\n"
363 "Descriptors:\n"
364 " Prop: foo -> 'brillo'\n"
365 " Prop: bar -> 'chromeos'\n"
366 " Prop: prisoner -> '24601'\n"
367 " Prop: hexnumber -> '0xcafe'\n"
368 " Prop: hexnumber_capital -> '0xCAFE'\n"
369 " Prop: large_hexnumber -> '0xfedcba9876543210'\n"
370 " Prop: larger_than_uint64 -> '0xfedcba98765432101'\n"
371 " Prop: almost_a_number -> '423x'\n"
372 " Prop: blob -> '\\x00\\x00brillo "
373 "ftw!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n'\n"
374 " Prop: large_blob -> (2048 bytes)\n",
375 InfoImage(vbmeta_image_path_));
376 }
377
collect_descriptors(const AvbDescriptor * descriptor,void * user_data)378 static bool collect_descriptors(const AvbDescriptor* descriptor,
379 void* user_data) {
380 std::vector<const AvbDescriptor*>* descriptors =
381 reinterpret_cast<std::vector<const AvbDescriptor*>*>(user_data);
382 descriptors->push_back(descriptor);
383 return true; // Keep iterating.
384 }
385
AddHashFooterGetExpectedVBMetaInfo(const bool sparse_image,const uint64_t partition_size)386 static std::string AddHashFooterGetExpectedVBMetaInfo(
387 const bool sparse_image, const uint64_t partition_size) {
388 return base::StringPrintf(
389 "Footer version: 1.0\n"
390 "Image size: %" PRIu64
391 " bytes\n"
392 "Original image size: 1052672 bytes\n"
393 "VBMeta offset: 1052672\n"
394 "VBMeta size: 1280 bytes\n"
395 "--\n"
396 "Minimum libavb version: 1.0%s\n"
397 "Header Block: 256 bytes\n"
398 "Authentication Block: 320 bytes\n"
399 "Auxiliary Block: 704 bytes\n"
400 "Algorithm: SHA256_RSA2048\n"
401 "Rollback Index: 0\n"
402 "Flags: 0\n"
403 "Release String: ''\n"
404 "Descriptors:\n"
405 " Hash descriptor:\n"
406 " Image Size: 1052672 bytes\n"
407 " Hash Algorithm: sha256\n"
408 " Partition Name: foobar\n"
409 " Salt: d00df00d\n"
410 " Digest: "
411 "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
412 "5e4ed357fbcf58d88d9\n",
413 partition_size,
414 sparse_image ? " (Sparse)" : "");
415 }
416
AddHashFooterTest(bool sparse_image)417 void AvbToolTest::AddHashFooterTest(bool sparse_image) {
418 const size_t rootfs_size = 1028 * 1024;
419 const size_t partition_size = 1536 * 1024;
420 const size_t resized_partition_size = 1280 * 1024;
421
422 // Generate a 1028 KiB file with known content. Some content have
423 // been arranged to ensure FILL_DATA segments in the sparse file.
424 std::vector<uint8_t> rootfs;
425 rootfs.resize(rootfs_size);
426 for (size_t n = 0; n < rootfs_size; n++) {
427 if ((n >= 5 * 1000 && n < 105 * 1000) ||
428 (n >= 205 * 1000 && n < 305 * 1000) ||
429 (n >= 505 * 1000 && n < 605 * 1000)) {
430 rootfs[n] = uint8_t(n) & 0x03;
431 } else {
432 rootfs[n] = uint8_t(n);
433 }
434 }
435 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
436 base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
437 EXPECT_EQ(rootfs_size,
438 static_cast<const size_t>(
439 base::WriteFile(rootfs_path,
440 reinterpret_cast<const char*>(rootfs.data()),
441 rootfs.size())));
442
443 if (sparse_image) {
444 EXPECT_COMMAND(0,
445 "mv %s %s.unsparse",
446 rootfs_path.value().c_str(),
447 rootfs_path.value().c_str());
448 EXPECT_COMMAND(0,
449 "img2simg %s.unsparse %s",
450 rootfs_path.value().c_str(),
451 rootfs_path.value().c_str());
452 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
453 }
454
455 /* Do this twice to check that 'add_hash_footer' is idempotent. */
456 for (int n = 0; n < 2; n++) {
457 EXPECT_COMMAND(0,
458 "./avbtool add_hash_footer --salt d00df00d "
459 "--hash_algorithm sha256 --image %s "
460 "--partition_size %d --partition_name foobar "
461 "--algorithm SHA256_RSA2048 "
462 "--key test/data/testkey_rsa2048.pem "
463 "--output_vbmeta %s "
464 "--internal_release_string \"\"",
465 rootfs_path.value().c_str(),
466 (int)partition_size,
467 ext_vbmeta_path.value().c_str());
468
469 ASSERT_EQ(AddHashFooterGetExpectedVBMetaInfo(sparse_image, partition_size),
470 InfoImage(rootfs_path));
471
472 ASSERT_EQ(
473 "Minimum libavb version: 1.0\n"
474 "Header Block: 256 bytes\n"
475 "Authentication Block: 320 bytes\n"
476 "Auxiliary Block: 704 bytes\n"
477 "Algorithm: SHA256_RSA2048\n"
478 "Rollback Index: 0\n"
479 "Flags: 0\n"
480 "Release String: ''\n"
481 "Descriptors:\n"
482 " Hash descriptor:\n"
483 " Image Size: 1052672 bytes\n"
484 " Hash Algorithm: sha256\n"
485 " Partition Name: foobar\n"
486 " Salt: d00df00d\n"
487 " Digest: "
488 "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
489 "5e4ed357fbcf58d88d9\n",
490 InfoImage(ext_vbmeta_path));
491 }
492
493 // Resize the image and check that the only thing that has changed
494 // is where the footer is. First check that resizing to a smaller
495 // size than the original rootfs fails. Then resize to something
496 // larger than the original rootfs but smaller than the current
497 // partition size.
498 EXPECT_COMMAND(1,
499 "./avbtool resize_image --image %s "
500 "--partition_size %d",
501 rootfs_path.value().c_str(),
502 (int)(rootfs_size - 16 * 1024));
503 EXPECT_COMMAND(0,
504 "./avbtool resize_image --image %s "
505 "--partition_size %d",
506 rootfs_path.value().c_str(),
507 (int)resized_partition_size);
508 ASSERT_EQ(
509 AddHashFooterGetExpectedVBMetaInfo(sparse_image, resized_partition_size),
510 InfoImage(rootfs_path));
511
512 if (sparse_image) {
513 EXPECT_COMMAND(0,
514 "mv %s %s.sparse",
515 rootfs_path.value().c_str(),
516 rootfs_path.value().c_str());
517 EXPECT_COMMAND(0,
518 "simg2img %s.sparse %s",
519 rootfs_path.value().c_str(),
520 rootfs_path.value().c_str());
521 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
522 }
523
524 // Manually calculate the hash to check that it agrees with avbtool.
525 AvbSHA256Ctx hasher_ctx;
526 const uint8_t hasher_salt[4] = {0xd0, 0x0d, 0xf0, 0x0d};
527 avb_sha256_init(&hasher_ctx);
528 avb_sha256_update(&hasher_ctx, hasher_salt, 4);
529 avb_sha256_update(&hasher_ctx, rootfs.data(), rootfs_size);
530 uint8_t* hasher_digest = avb_sha256_final(&hasher_ctx);
531 EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
532 mem_to_hexstring(hasher_digest, AVB_SHA256_DIGEST_SIZE));
533
534 // Now check that we can find the VBMeta block again from the footer.
535 std::string part_data;
536 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
537
538 // Check footer contains correct data.
539 AvbFooter f;
540 EXPECT_NE(0,
541 avb_footer_validate_and_byteswap(
542 reinterpret_cast<const AvbFooter*>(
543 part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
544 &f));
545 EXPECT_EQ(
546 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
547 AVB_FOOTER_MAGIC);
548 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
549 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
550 EXPECT_EQ(1052672UL, f.original_image_size);
551 EXPECT_EQ(1052672UL, f.vbmeta_offset);
552 EXPECT_EQ(1280UL, f.vbmeta_size);
553
554 // Check that the vbmeta image at |f.vbmeta_offset| checks out.
555 const uint8_t* vbmeta_data =
556 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
557 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
558 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
559
560 // Collect all descriptors.
561 std::vector<const AvbDescriptor*> descriptors;
562 avb_descriptor_foreach(
563 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
564
565 // We should only have a single descriptor and it should be a
566 // hash descriptor.
567 EXPECT_EQ(1UL, descriptors.size());
568 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, avb_be64toh(descriptors[0]->tag));
569 AvbHashDescriptor d;
570 EXPECT_NE(
571 0,
572 avb_hash_descriptor_validate_and_byteswap(
573 reinterpret_cast<const AvbHashDescriptor*>(descriptors[0]), &d));
574 EXPECT_EQ(1052672UL, d.image_size);
575 EXPECT_EQ(6UL, d.partition_name_len);
576 EXPECT_EQ(4UL, d.salt_len);
577 EXPECT_EQ(32UL, d.digest_len);
578 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
579 sizeof(AvbHashDescriptor);
580 uint64_t o = 0;
581 EXPECT_EQ("foobar",
582 std::string(reinterpret_cast<const char*>(desc_end + o),
583 d.partition_name_len));
584 o += d.partition_name_len;
585 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
586 o += d.salt_len;
587 EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
588 mem_to_hexstring(desc_end + o, d.digest_len));
589
590 // Check that the footer is correctly erased.
591 EXPECT_COMMAND(
592 0, "./avbtool erase_footer --image %s", rootfs_path.value().c_str());
593 int64_t erased_footer_file_size;
594 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
595 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size);
596
597 // Check that --do_not_append_vbmeta_image works as intended.
598 EXPECT_COMMAND(0,
599 "./avbtool add_hash_footer --salt d00df00d "
600 "--hash_algorithm sha256 --image %s "
601 "--partition_size %d --partition_name foobar "
602 "--algorithm SHA256_RSA2048 "
603 "--key test/data/testkey_rsa2048.pem "
604 "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
605 "--internal_release_string \"\"",
606 rootfs_path.value().c_str(),
607 (int)partition_size,
608 ext_vbmeta_path.value().c_str());
609 int64_t file_size;
610 ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
611 EXPECT_EQ(static_cast<size_t>(file_size), rootfs_size);
612 EXPECT_COMMAND(0,
613 "diff %s %s_2nd_run",
614 ext_vbmeta_path.value().c_str(),
615 ext_vbmeta_path.value().c_str());
616 }
617
TEST_F(AvbToolTest,AddHashFooter)618 TEST_F(AvbToolTest, AddHashFooter) {
619 AddHashFooterTest(false);
620 }
621
TEST_F(AvbToolTest,AddHashFooterSparse)622 TEST_F(AvbToolTest, AddHashFooterSparse) {
623 AddHashFooterTest(true);
624 }
625
RemoveLinesStartingWith(const std::string & str,const std::string & prefix)626 static std::string RemoveLinesStartingWith(const std::string& str,
627 const std::string& prefix) {
628 std::vector<std::string> lines;
629 std::string ret;
630
631 lines = base::SplitString(
632 str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
633 for (const std::string& line : lines) {
634 if (!base::StartsWith(line, prefix, base::CompareCase::SENSITIVE)) {
635 ret += line;
636 ret += '\n';
637 }
638 }
639 return ret;
640 }
641
TEST_F(AvbToolTest,AddHashFooterSparseWithHoleAtTheEnd)642 TEST_F(AvbToolTest, AddHashFooterSparseWithHoleAtTheEnd) {
643 const size_t partition_size = 10 * 1024 * 1024;
644 const size_t metadata_size = 128 * 1024;
645
646 // It's not enough to run img2simg on a file with a lot of zeroes at
647 // the end since that will turn up as "Fill with value (for value =
648 // 0x00000000)" and not "Don't care". Instead, use make_ext4fs for
649 // this since it will put a big hole (e.g. "Don't care" chunk) at
650 // the end.
651 base::FilePath partition_path = testdir_.Append("partition.bin");
652 EXPECT_COMMAND(0,
653 "make_ext4fs -s -L test -l %zd %s",
654 partition_size - metadata_size,
655 partition_path.value().c_str());
656
657 EXPECT_COMMAND(0,
658 "./avbtool add_hash_footer --salt d00df00d "
659 "--hash_algorithm sha256 --image %s "
660 "--partition_size %d --partition_name foobar "
661 "--algorithm SHA256_RSA2048 "
662 "--key test/data/testkey_rsa2048.pem "
663 "--internal_release_string \"\"",
664 partition_path.value().c_str(),
665 (int)partition_size);
666
667 // Since we may be using an arbritary version of make_ext4fs
668 // (because of different branches) the contents of the resulting
669 // disk image may slightly change. It's enough to just remove the
670 // "Digest:" line from the output to work around this.
671 std::string info =
672 RemoveLinesStartingWith(InfoImage(partition_path), " Digest:");
673 ASSERT_EQ(
674 "Footer version: 1.0\n"
675 "Image size: 10485760 bytes\n"
676 "Original image size: 10354688 bytes\n"
677 "VBMeta offset: 10354688\n"
678 "VBMeta size: 1280 bytes\n"
679 "--\n"
680 "Minimum libavb version: 1.0 (Sparse)\n"
681 "Header Block: 256 bytes\n"
682 "Authentication Block: 320 bytes\n"
683 "Auxiliary Block: 704 bytes\n"
684 "Algorithm: SHA256_RSA2048\n"
685 "Rollback Index: 0\n"
686 "Flags: 0\n"
687 "Release String: ''\n"
688 "Descriptors:\n"
689 " Hash descriptor:\n"
690 " Image Size: 10354688 bytes\n"
691 " Hash Algorithm: sha256\n"
692 " Partition Name: foobar\n"
693 " Salt: d00df00d\n",
694 info);
695
696 EXPECT_COMMAND(0,
697 "mv %s %s.sparse",
698 partition_path.value().c_str(),
699 partition_path.value().c_str());
700 EXPECT_COMMAND(0,
701 "simg2img %s.sparse %s",
702 partition_path.value().c_str(),
703 partition_path.value().c_str());
704 EXPECT_COMMAND(0, "rm -f %s.sparse", partition_path.value().c_str());
705 }
706
TEST_F(AvbToolTest,AddHashFooterCalcMaxImageSize)707 TEST_F(AvbToolTest, AddHashFooterCalcMaxImageSize) {
708 const size_t partition_size = 10 * 1024 * 1024;
709 base::FilePath output_path = testdir_.Append("max_size.txt");
710
711 EXPECT_COMMAND(0,
712 "./avbtool add_hash_footer "
713 "--partition_size %zd "
714 "--calc_max_image_size > %s",
715 partition_size,
716 output_path.value().c_str());
717 std::string max_image_size_data;
718 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
719 EXPECT_EQ("10416128\n", max_image_size_data);
720 size_t max_image_size = atoll(max_image_size_data.c_str());
721
722 // Metadata takes up 68 KiB.
723 EXPECT_EQ(68 * 1024ULL, partition_size - max_image_size);
724
725 // Check that we can add a hash footer for an image this size for
726 // such a partition size.
727 base::FilePath boot_path = GenerateImage("boot", max_image_size);
728 EXPECT_COMMAND(0,
729 "./avbtool add_hash_footer"
730 " --image %s"
731 " --partition_name boot"
732 " --partition_size %zd"
733 " --salt deadbeef"
734 " --algorithm SHA512_RSA4096 "
735 " --key test/data/testkey_rsa4096.pem"
736 " --internal_release_string \"\"",
737 boot_path.value().c_str(),
738 partition_size);
739 }
740
AddHashtreeFooterTest(bool sparse_image)741 void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
742 const size_t rootfs_size = 1028 * 1024;
743 const size_t partition_size = 1536 * 1024;
744
745 // Generate a 1028 KiB file with known content.
746 std::vector<uint8_t> rootfs;
747 rootfs.resize(rootfs_size);
748 for (size_t n = 0; n < rootfs_size; n++)
749 rootfs[n] = uint8_t(n);
750 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
751 base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
752 EXPECT_EQ(rootfs_size,
753 static_cast<const size_t>(
754 base::WriteFile(rootfs_path,
755 reinterpret_cast<const char*>(rootfs.data()),
756 rootfs.size())));
757
758 if (sparse_image) {
759 EXPECT_COMMAND(0,
760 "mv %s %s.unsparse",
761 rootfs_path.value().c_str(),
762 rootfs_path.value().c_str());
763 EXPECT_COMMAND(0,
764 "img2simg %s.unsparse %s",
765 rootfs_path.value().c_str(),
766 rootfs_path.value().c_str());
767 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
768 }
769
770 /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
771 for (int n = 0; n < 2; n++) {
772 EXPECT_COMMAND(0,
773 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
774 "--partition_size %d --partition_name foobar "
775 "--algorithm SHA256_RSA2048 "
776 "--key test/data/testkey_rsa2048.pem "
777 "--output_vbmeta_image %s "
778 "--internal_release_string \"\" "
779 "--do_not_generate_fec",
780 rootfs_path.value().c_str(),
781 (int)partition_size,
782 ext_vbmeta_path.value().c_str());
783
784 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n"
785 "Image size: 1572864 bytes\n"
786 "Original image size: 1052672 bytes\n"
787 "VBMeta offset: 1069056\n"
788 "VBMeta size: 1344 bytes\n"
789 "--\n"
790 "Minimum libavb version: 1.0%s\n"
791 "Header Block: 256 bytes\n"
792 "Authentication Block: 320 bytes\n"
793 "Auxiliary Block: 768 bytes\n"
794 "Algorithm: SHA256_RSA2048\n"
795 "Rollback Index: 0\n"
796 "Flags: 0\n"
797 "Release String: ''\n"
798 "Descriptors:\n"
799 " Hashtree descriptor:\n"
800 " Version of dm-verity: 1\n"
801 " Image Size: 1052672 bytes\n"
802 " Tree Offset: 1052672\n"
803 " Tree Size: 16384 bytes\n"
804 " Data Block Size: 4096 bytes\n"
805 " Hash Block Size: 4096 bytes\n"
806 " FEC num roots: 0\n"
807 " FEC offset: 0\n"
808 " FEC size: 0 bytes\n"
809 " Hash Algorithm: sha1\n"
810 " Partition Name: foobar\n"
811 " Salt: d00df00d\n"
812 " Root Digest: "
813 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
814 sparse_image ? " (Sparse)" : ""),
815 InfoImage(rootfs_path));
816
817 ASSERT_EQ(
818 "Minimum libavb version: 1.0\n"
819 "Header Block: 256 bytes\n"
820 "Authentication Block: 320 bytes\n"
821 "Auxiliary Block: 768 bytes\n"
822 "Algorithm: SHA256_RSA2048\n"
823 "Rollback Index: 0\n"
824 "Flags: 0\n"
825 "Release String: ''\n"
826 "Descriptors:\n"
827 " Hashtree descriptor:\n"
828 " Version of dm-verity: 1\n"
829 " Image Size: 1052672 bytes\n"
830 " Tree Offset: 1052672\n"
831 " Tree Size: 16384 bytes\n"
832 " Data Block Size: 4096 bytes\n"
833 " Hash Block Size: 4096 bytes\n"
834 " FEC num roots: 0\n"
835 " FEC offset: 0\n"
836 " FEC size: 0 bytes\n"
837 " Hash Algorithm: sha1\n"
838 " Partition Name: foobar\n"
839 " Salt: d00df00d\n"
840 " Root Digest: "
841 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
842 InfoImage(ext_vbmeta_path));
843 }
844
845 if (sparse_image) {
846 EXPECT_COMMAND(0,
847 "mv %s %s.sparse",
848 rootfs_path.value().c_str(),
849 rootfs_path.value().c_str());
850 EXPECT_COMMAND(0,
851 "simg2img %s.sparse %s",
852 rootfs_path.value().c_str(),
853 rootfs_path.value().c_str());
854 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
855 }
856
857 // To check that we generate the correct hashtree we can use
858 // veritysetup(1) - another codebase for working with dm-verity
859 // hashtrees - to verify it.
860 //
861 // If we don't want to impose the requirement of having the
862 // veritysetup(1) command available on builders we can comment this
863 // out.
864 EXPECT_COMMAND(0,
865 "veritysetup --no-superblock --format=1 --hash=sha1 "
866 "--data-block-size=4096 --hash-block-size=4096 "
867 "--salt=d00df00d "
868 "--data-blocks=257 "
869 "--hash-offset=1052672 "
870 "verify "
871 "%s %s "
872 "e811611467dcd6e8dc4324e45f706c2bdd51db67",
873 rootfs_path.value().c_str(),
874 rootfs_path.value().c_str());
875
876 // Now check that we can find the VBMeta block again from the footer.
877 std::string part_data;
878 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
879
880 // Check footer contains correct data.
881 AvbFooter f;
882 EXPECT_NE(0,
883 avb_footer_validate_and_byteswap(
884 reinterpret_cast<const AvbFooter*>(
885 part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
886 &f));
887 EXPECT_EQ(
888 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
889 AVB_FOOTER_MAGIC);
890 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
891 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
892 EXPECT_EQ(1052672UL, f.original_image_size);
893 EXPECT_EQ(1069056UL, f.vbmeta_offset);
894 EXPECT_EQ(1344UL, f.vbmeta_size);
895
896 // Check that the vbmeta image at |f.vbmeta_offset| checks out.
897 const uint8_t* vbmeta_data =
898 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
899 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
900 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
901
902 // Collect all descriptors.
903 std::vector<const AvbDescriptor*> descriptors;
904 avb_descriptor_foreach(
905 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
906
907 // We should only have a single descriptor and it should be a
908 // hashtree descriptor.
909 EXPECT_EQ(1UL, descriptors.size());
910 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
911 AvbHashtreeDescriptor d;
912 EXPECT_NE(
913 0,
914 avb_hashtree_descriptor_validate_and_byteswap(
915 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
916 EXPECT_EQ(1UL, d.dm_verity_version);
917 EXPECT_EQ(1052672UL, d.image_size);
918 EXPECT_EQ(1052672UL, d.tree_offset);
919 EXPECT_EQ(16384UL, d.tree_size);
920 EXPECT_EQ(4096UL, d.data_block_size);
921 EXPECT_EQ(4096UL, d.hash_block_size);
922 EXPECT_EQ(6UL, d.partition_name_len);
923 EXPECT_EQ(4UL, d.salt_len);
924 EXPECT_EQ(20UL, d.root_digest_len);
925 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
926 sizeof(AvbHashtreeDescriptor);
927 uint64_t o = 0;
928 EXPECT_EQ("foobar",
929 std::string(reinterpret_cast<const char*>(desc_end + o),
930 d.partition_name_len));
931 o += d.partition_name_len;
932 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
933 o += d.salt_len;
934 EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
935 mem_to_hexstring(desc_end + o, d.root_digest_len));
936
937 // Check that we correctly generate dm-verity kernel cmdline
938 // snippets, if requested.
939 base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
940 EXPECT_COMMAND(0,
941 "./avbtool make_vbmeta_image "
942 "--output %s "
943 "--setup_rootfs_from_kernel %s "
944 "--algorithm SHA256_RSA2048 "
945 "--key test/data/testkey_rsa2048.pem "
946 "--internal_release_string \"\"",
947 vbmeta_dmv_path.value().c_str(),
948 rootfs_path.value().c_str());
949
950 ASSERT_EQ(
951 "Minimum libavb version: 1.0\n"
952 "Header Block: 256 bytes\n"
953 "Authentication Block: 320 bytes\n"
954 "Auxiliary Block: 896 bytes\n"
955 "Algorithm: SHA256_RSA2048\n"
956 "Rollback Index: 0\n"
957 "Flags: 0\n"
958 "Release String: ''\n"
959 "Descriptors:\n"
960 " Kernel Cmdline descriptor:\n"
961 " Flags: 1\n"
962 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 "
963 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
964 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
965 "d00df00d 2 $(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
966 " Kernel Cmdline descriptor:\n"
967 " Flags: 2\n"
968 " Kernel Cmdline: "
969 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
970 InfoImage(vbmeta_dmv_path));
971
972 // Check that the footer is correctly erased and the hashtree
973 // remains - see above for why the constant 1069056 is used.
974 EXPECT_COMMAND(0,
975 "./avbtool erase_footer --image %s --keep_hashtree",
976 rootfs_path.value().c_str());
977 int64_t erased_footer_file_size;
978 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
979 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1069056UL);
980
981 // Check that --do_not_append_vbmeta_image works as intended.
982 //
983 // For this we need to reset the size of the image to the original
984 // size because it's not possible to identify the existing hashtree.
985 EXPECT_COMMAND(
986 0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str());
987 EXPECT_COMMAND(0,
988 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
989 "--partition_size %d --partition_name foobar "
990 "--algorithm SHA256_RSA2048 "
991 "--key test/data/testkey_rsa2048.pem "
992 "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
993 "--internal_release_string \"\" "
994 "--do_not_generate_fec",
995 rootfs_path.value().c_str(),
996 (int)partition_size,
997 ext_vbmeta_path.value().c_str());
998 int64_t file_size;
999 ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
1000 EXPECT_EQ(static_cast<size_t>(file_size), 1069056UL);
1001 EXPECT_COMMAND(0,
1002 "diff %s %s_2nd_run",
1003 ext_vbmeta_path.value().c_str(),
1004 ext_vbmeta_path.value().c_str());
1005 }
1006
TEST_F(AvbToolTest,AddHashtreeFooter)1007 TEST_F(AvbToolTest, AddHashtreeFooter) {
1008 AddHashtreeFooterTest(false);
1009 }
1010
TEST_F(AvbToolTest,AddHashtreeFooterSparse)1011 TEST_F(AvbToolTest, AddHashtreeFooterSparse) {
1012 AddHashtreeFooterTest(true);
1013 }
1014
AddHashtreeFooterFECTest(bool sparse_image)1015 void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
1016 const size_t rootfs_size = 1028 * 1024;
1017 const size_t partition_size = 1536 * 1024;
1018
1019 // Generate a 1028 KiB file with known content.
1020 std::vector<uint8_t> rootfs;
1021 rootfs.resize(rootfs_size);
1022 for (size_t n = 0; n < rootfs_size; n++)
1023 rootfs[n] = uint8_t(n);
1024 base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
1025 EXPECT_EQ(rootfs_size,
1026 static_cast<const size_t>(
1027 base::WriteFile(rootfs_path,
1028 reinterpret_cast<const char*>(rootfs.data()),
1029 rootfs.size())));
1030
1031 if (sparse_image) {
1032 EXPECT_COMMAND(0,
1033 "mv %s %s.unsparse",
1034 rootfs_path.value().c_str(),
1035 rootfs_path.value().c_str());
1036 EXPECT_COMMAND(0,
1037 "img2simg %s.unsparse %s",
1038 rootfs_path.value().c_str(),
1039 rootfs_path.value().c_str());
1040 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
1041 }
1042
1043 /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
1044 for (int n = 0; n < 2; n++) {
1045 EXPECT_COMMAND(0,
1046 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1047 "--partition_size %d --partition_name foobar "
1048 "--algorithm SHA256_RSA2048 "
1049 "--key test/data/testkey_rsa2048.pem "
1050 "--internal_release_string \"\"",
1051 rootfs_path.value().c_str(),
1052 (int)partition_size);
1053
1054 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n"
1055 "Image size: 1572864 bytes\n"
1056 "Original image size: 1052672 bytes\n"
1057 "VBMeta offset: 1085440\n"
1058 "VBMeta size: 1344 bytes\n"
1059 "--\n"
1060 "Minimum libavb version: 1.0%s\n"
1061 "Header Block: 256 bytes\n"
1062 "Authentication Block: 320 bytes\n"
1063 "Auxiliary Block: 768 bytes\n"
1064 "Algorithm: SHA256_RSA2048\n"
1065 "Rollback Index: 0\n"
1066 "Flags: 0\n"
1067 "Release String: ''\n"
1068 "Descriptors:\n"
1069 " Hashtree descriptor:\n"
1070 " Version of dm-verity: 1\n"
1071 " Image Size: 1052672 bytes\n"
1072 " Tree Offset: 1052672\n"
1073 " Tree Size: 16384 bytes\n"
1074 " Data Block Size: 4096 bytes\n"
1075 " Hash Block Size: 4096 bytes\n"
1076 " FEC num roots: 2\n"
1077 " FEC offset: 1069056\n"
1078 " FEC size: 16384 bytes\n"
1079 " Hash Algorithm: sha1\n"
1080 " Partition Name: foobar\n"
1081 " Salt: d00df00d\n"
1082 " Root Digest: "
1083 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n",
1084 sparse_image ? " (Sparse)" : ""),
1085 InfoImage(rootfs_path));
1086 }
1087
1088 if (sparse_image) {
1089 EXPECT_COMMAND(0,
1090 "mv %s %s.sparse",
1091 rootfs_path.value().c_str(),
1092 rootfs_path.value().c_str());
1093 EXPECT_COMMAND(0,
1094 "simg2img %s.sparse %s",
1095 rootfs_path.value().c_str(),
1096 rootfs_path.value().c_str());
1097 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
1098 }
1099
1100 /* TODO: would be nice to verify that the FEC data is correct. */
1101
1102 // Now check that we can find the VBMeta block again from the footer.
1103 std::string part_data;
1104 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1105
1106 // Check footer contains correct data.
1107 AvbFooter f;
1108 EXPECT_NE(0,
1109 avb_footer_validate_and_byteswap(
1110 reinterpret_cast<const AvbFooter*>(
1111 part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1112 &f));
1113 EXPECT_EQ(
1114 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1115 AVB_FOOTER_MAGIC);
1116 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1117 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1118 EXPECT_EQ(1052672UL, f.original_image_size);
1119 EXPECT_EQ(1085440UL, f.vbmeta_offset);
1120 EXPECT_EQ(1344UL, f.vbmeta_size);
1121
1122 // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1123 const uint8_t* vbmeta_data =
1124 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1125 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1126 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1127
1128 // Collect all descriptors.
1129 std::vector<const AvbDescriptor*> descriptors;
1130 avb_descriptor_foreach(
1131 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1132
1133 // We should only have a single descriptor and it should be a
1134 // hashtree descriptor.
1135 EXPECT_EQ(1UL, descriptors.size());
1136 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1137 AvbHashtreeDescriptor d;
1138 EXPECT_NE(
1139 0,
1140 avb_hashtree_descriptor_validate_and_byteswap(
1141 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1142 EXPECT_EQ(1UL, d.dm_verity_version);
1143 EXPECT_EQ(1052672UL, d.image_size);
1144 EXPECT_EQ(1052672UL, d.tree_offset);
1145 EXPECT_EQ(16384UL, d.tree_size);
1146 EXPECT_EQ(4096UL, d.data_block_size);
1147 EXPECT_EQ(2UL, d.fec_num_roots);
1148 EXPECT_EQ(1069056UL, d.fec_offset);
1149 EXPECT_EQ(16384UL, d.fec_size);
1150 EXPECT_EQ(6UL, d.partition_name_len);
1151 EXPECT_EQ(4UL, d.salt_len);
1152 EXPECT_EQ(20UL, d.root_digest_len);
1153 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1154 sizeof(AvbHashtreeDescriptor);
1155 uint64_t o = 0;
1156 EXPECT_EQ("foobar",
1157 std::string(reinterpret_cast<const char*>(desc_end + o),
1158 d.partition_name_len));
1159 o += d.partition_name_len;
1160 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1161 o += d.salt_len;
1162 EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1163 mem_to_hexstring(desc_end + o, d.root_digest_len));
1164
1165 // Check that we correctly generate dm-verity kernel cmdline
1166 // snippets, if requested.
1167 base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1168 EXPECT_COMMAND(0,
1169 "./avbtool make_vbmeta_image "
1170 "--output %s "
1171 "--setup_rootfs_from_kernel %s "
1172 "--algorithm SHA256_RSA2048 "
1173 "--key test/data/testkey_rsa2048.pem "
1174 "--internal_release_string \"\"",
1175 vbmeta_dmv_path.value().c_str(),
1176 rootfs_path.value().c_str());
1177
1178 ASSERT_EQ(
1179 "Minimum libavb version: 1.0\n"
1180 "Header Block: 256 bytes\n"
1181 "Authentication Block: 320 bytes\n"
1182 "Auxiliary Block: 960 bytes\n"
1183 "Algorithm: SHA256_RSA2048\n"
1184 "Rollback Index: 0\n"
1185 "Flags: 0\n"
1186 "Release String: ''\n"
1187 "Descriptors:\n"
1188 " Kernel Cmdline descriptor:\n"
1189 " Flags: 1\n"
1190 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1191 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1192 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1193 "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
1194 "use_fec_from_device "
1195 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 261 "
1196 "fec_start 261\" root=/dev/dm-0'\n"
1197 " Kernel Cmdline descriptor:\n"
1198 " Flags: 2\n"
1199 " Kernel Cmdline: "
1200 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1201 InfoImage(vbmeta_dmv_path));
1202
1203 // Check that the footer is correctly erased and the hashtree and
1204 // FEC data remains. The constant 1085440 is used because it's where
1205 // the FEC data ends (it's at offset 1069056 and size 16384).
1206 EXPECT_COMMAND(0,
1207 "./avbtool erase_footer --image %s --keep_hashtree",
1208 rootfs_path.value().c_str());
1209 int64_t erased_footer_file_size;
1210 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1211 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1085440UL);
1212 }
1213
TEST_F(AvbToolTest,AddHashtreeFooterFEC)1214 TEST_F(AvbToolTest, AddHashtreeFooterFEC) {
1215 AddHashtreeFooterFECTest(false);
1216 }
1217
TEST_F(AvbToolTest,AddHashtreeFooterFECSparse)1218 TEST_F(AvbToolTest, AddHashtreeFooterFECSparse) {
1219 AddHashtreeFooterFECTest(true);
1220 }
1221
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSize)1222 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSize) {
1223 const size_t partition_size = 10 * 1024 * 1024;
1224 base::FilePath output_path = testdir_.Append("max_size.txt");
1225
1226 EXPECT_COMMAND(0,
1227 "./avbtool add_hashtree_footer "
1228 "--partition_size %zd --calc_max_image_size "
1229 "--do_not_generate_fec > %s",
1230 partition_size,
1231 output_path.value().c_str());
1232 std::string max_image_size_data;
1233 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1234 EXPECT_EQ("10330112\n", max_image_size_data);
1235 size_t max_image_size = atoll(max_image_size_data.c_str());
1236
1237 // Hashtree and metadata takes up 152 KiB - compare to below with
1238 // FEC which is 244 KiB.
1239 EXPECT_EQ(152 * 1024ULL, partition_size - max_image_size);
1240
1241 // Check that we can add a hashtree with an image this size for such
1242 // a partition size.
1243 base::FilePath system_path = GenerateImage("system", max_image_size);
1244 EXPECT_COMMAND(0,
1245 "./avbtool add_hashtree_footer"
1246 " --image %s"
1247 " --partition_name system"
1248 " --partition_size %zd"
1249 " --salt deadbeef"
1250 " --algorithm SHA512_RSA4096 "
1251 " --key test/data/testkey_rsa4096.pem"
1252 " --internal_release_string \"\" "
1253 "--do_not_generate_fec",
1254 system_path.value().c_str(),
1255 partition_size);
1256 }
1257
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSizeWithFEC)1258 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) {
1259 const size_t partition_size = 10 * 1024 * 1024;
1260 base::FilePath output_path = testdir_.Append("max_size.txt");
1261
1262 EXPECT_COMMAND(0,
1263 "./avbtool add_hashtree_footer "
1264 "--partition_size %zd --calc_max_image_size > %s",
1265 partition_size,
1266 output_path.value().c_str());
1267 std::string max_image_size_data;
1268 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1269 EXPECT_EQ("10235904\n", max_image_size_data);
1270 size_t max_image_size = atoll(max_image_size_data.c_str());
1271
1272 // Hashtree, FEC codes, and metadata takes up 244 KiB - compare to
1273 // above wihtout FEC which is 152 KiB.
1274 EXPECT_EQ(244 * 1024ULL, partition_size - max_image_size);
1275
1276 // Check that we can add a hashtree with an image this size for such
1277 // a partition size.
1278 base::FilePath system_path = GenerateImage("system", max_image_size);
1279 EXPECT_COMMAND(0,
1280 "./avbtool add_hashtree_footer"
1281 " --image %s"
1282 " --partition_name system"
1283 " --partition_size %zd"
1284 " --salt deadbeef"
1285 " --algorithm SHA512_RSA4096 "
1286 " --key test/data/testkey_rsa4096.pem"
1287 " --internal_release_string \"\"",
1288 system_path.value().c_str(),
1289 partition_size);
1290 }
1291
TEST_F(AvbToolTest,KernelCmdlineDescriptor)1292 TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
1293 base::FilePath vbmeta_path =
1294 testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
1295
1296 EXPECT_COMMAND(0,
1297 "./avbtool make_vbmeta_image "
1298 "--output %s "
1299 "--kernel_cmdline 'foo bar baz' "
1300 "--kernel_cmdline 'second cmdline' "
1301 "--algorithm SHA256_RSA2048 "
1302 "--key test/data/testkey_rsa2048.pem "
1303 "--internal_release_string \"\"",
1304 vbmeta_path.value().c_str());
1305
1306 ASSERT_EQ(
1307 "Minimum libavb version: 1.0\n"
1308 "Header Block: 256 bytes\n"
1309 "Authentication Block: 320 bytes\n"
1310 "Auxiliary Block: 640 bytes\n"
1311 "Algorithm: SHA256_RSA2048\n"
1312 "Rollback Index: 0\n"
1313 "Flags: 0\n"
1314 "Release String: ''\n"
1315 "Descriptors:\n"
1316 " Kernel Cmdline descriptor:\n"
1317 " Flags: 0\n"
1318 " Kernel Cmdline: 'foo bar baz'\n"
1319 " Kernel Cmdline descriptor:\n"
1320 " Flags: 0\n"
1321 " Kernel Cmdline: 'second cmdline'\n",
1322 InfoImage(vbmeta_path));
1323
1324 // Now check the VBMeta image.
1325 std::string image_data;
1326 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1327
1328 const uint8_t* vbmeta_data =
1329 reinterpret_cast<const uint8_t*>(image_data.data());
1330 const size_t vbmeta_size = image_data.length();
1331 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1332 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1333
1334 // Collect all descriptors.
1335 std::vector<const AvbDescriptor*> descriptors;
1336 avb_descriptor_foreach(
1337 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1338
1339 // We should have two descriptors - check them.
1340 EXPECT_EQ(2UL, descriptors.size());
1341 AvbKernelCmdlineDescriptor d;
1342 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1343 avb_be64toh(descriptors[0]->tag));
1344 EXPECT_NE(
1345 0,
1346 avb_kernel_cmdline_descriptor_validate_and_byteswap(
1347 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]),
1348 &d));
1349 EXPECT_EQ("foo bar baz",
1350 std::string(reinterpret_cast<const char*>(descriptors[0]) +
1351 sizeof(AvbKernelCmdlineDescriptor),
1352 d.kernel_cmdline_length));
1353 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1354 avb_be64toh(descriptors[1]->tag));
1355 EXPECT_NE(
1356 0,
1357 avb_kernel_cmdline_descriptor_validate_and_byteswap(
1358 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]),
1359 &d));
1360 EXPECT_EQ("second cmdline",
1361 std::string(reinterpret_cast<const char*>(descriptors[1]) +
1362 sizeof(AvbKernelCmdlineDescriptor),
1363 d.kernel_cmdline_length));
1364 }
1365
TEST_F(AvbToolTest,IncludeDescriptor)1366 TEST_F(AvbToolTest, IncludeDescriptor) {
1367 base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin");
1368 base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin");
1369 base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
1370
1371 EXPECT_COMMAND(0,
1372 "./avbtool make_vbmeta_image "
1373 "--output %s "
1374 "--kernel_cmdline 'something' "
1375 "--prop name:value "
1376 "--internal_release_string \"\"",
1377 vbmeta1_path.value().c_str());
1378
1379 EXPECT_COMMAND(0,
1380 "./avbtool make_vbmeta_image "
1381 "--output %s "
1382 "--prop name2:value2 "
1383 "--prop name3:value3 "
1384 "--internal_release_string \"\"",
1385 vbmeta2_path.value().c_str());
1386
1387 EXPECT_COMMAND(0,
1388 "./avbtool make_vbmeta_image "
1389 "--output %s "
1390 "--prop name4:value4 "
1391 "--include_descriptors_from_image %s "
1392 "--include_descriptors_from_image %s "
1393 "--internal_release_string \"\"",
1394 vbmeta3_path.value().c_str(),
1395 vbmeta1_path.value().c_str(),
1396 vbmeta2_path.value().c_str());
1397
1398 ASSERT_EQ(
1399 "Minimum libavb version: 1.0\n"
1400 "Header Block: 256 bytes\n"
1401 "Authentication Block: 0 bytes\n"
1402 "Auxiliary Block: 256 bytes\n"
1403 "Algorithm: NONE\n"
1404 "Rollback Index: 0\n"
1405 "Flags: 0\n"
1406 "Release String: ''\n"
1407 "Descriptors:\n"
1408 " Prop: name4 -> 'value4'\n"
1409 " Prop: name -> 'value'\n"
1410 " Kernel Cmdline descriptor:\n"
1411 " Flags: 0\n"
1412 " Kernel Cmdline: 'something'\n"
1413 " Prop: name2 -> 'value2'\n"
1414 " Prop: name3 -> 'value3'\n",
1415 InfoImage(vbmeta3_path));
1416 }
1417
TEST_F(AvbToolTest,ChainedPartition)1418 TEST_F(AvbToolTest, ChainedPartition) {
1419 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1420
1421 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1422
1423 EXPECT_COMMAND(
1424 0,
1425 "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1426 " --output %s",
1427 pk_path.value().c_str());
1428
1429 EXPECT_COMMAND(
1430 0,
1431 "./avbtool make_vbmeta_image "
1432 "--output %s "
1433 "--chain_partition system:1:%s "
1434 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1435 "--internal_release_string \"\"",
1436 vbmeta_path.value().c_str(),
1437 pk_path.value().c_str());
1438
1439 ASSERT_EQ(
1440 "Minimum libavb version: 1.0\n"
1441 "Header Block: 256 bytes\n"
1442 "Authentication Block: 320 bytes\n"
1443 "Auxiliary Block: 1152 bytes\n"
1444 "Algorithm: SHA256_RSA2048\n"
1445 "Rollback Index: 0\n"
1446 "Flags: 0\n"
1447 "Release String: ''\n"
1448 "Descriptors:\n"
1449 " Chain Partition descriptor:\n"
1450 " Partition Name: system\n"
1451 " Rollback Index Location: 1\n"
1452 " Public key (sha1): "
1453 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n",
1454 InfoImage(vbmeta_path));
1455
1456 // Now check the VBMeta image.
1457 std::string image_data;
1458 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1459
1460 const uint8_t* vbmeta_data =
1461 reinterpret_cast<const uint8_t*>(image_data.data());
1462 const size_t vbmeta_size = image_data.length();
1463 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1464 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1465
1466 // Collect all descriptors.
1467 std::vector<const AvbDescriptor*> descriptors;
1468 avb_descriptor_foreach(
1469 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1470
1471 // We should have one descriptor - check it.
1472 EXPECT_EQ(1UL, descriptors.size());
1473
1474 std::string pk_data;
1475 ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data));
1476
1477 AvbChainPartitionDescriptor d;
1478 EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
1479 avb_be64toh(descriptors[0]->tag));
1480 EXPECT_NE(
1481 0,
1482 avb_chain_partition_descriptor_validate_and_byteswap(
1483 reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]),
1484 &d));
1485 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1486 sizeof(AvbChainPartitionDescriptor);
1487 uint64_t o = 0;
1488 EXPECT_EQ("system",
1489 std::string(reinterpret_cast<const char*>(desc_end + o),
1490 d.partition_name_len));
1491 o += d.partition_name_len;
1492 EXPECT_EQ(pk_data,
1493 std::string(reinterpret_cast<const char*>(descriptors[0]) +
1494 sizeof(AvbChainPartitionDescriptor) + o,
1495 d.public_key_len));
1496 }
1497
TEST_F(AvbToolTest,ChainedPartitionNoLocationCollision)1498 TEST_F(AvbToolTest, ChainedPartitionNoLocationCollision) {
1499 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1500
1501 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1502
1503 EXPECT_COMMAND(
1504 0,
1505 "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1506 " --output %s",
1507 pk_path.value().c_str());
1508
1509 // Check that avbtool bails if the same Rollback Index Location is
1510 // used for multiple chained partitions.
1511 EXPECT_COMMAND(
1512 1,
1513 "./avbtool make_vbmeta_image "
1514 "--output %s "
1515 "--chain_partition system:1:%s "
1516 "--chain_partition other:1:%s "
1517 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1518 "--internal_release_string \"\"",
1519 vbmeta_path.value().c_str(),
1520 pk_path.value().c_str(),
1521 pk_path.value().c_str());
1522 }
1523
TEST_F(AvbToolTest,AppendVBMetaImage)1524 TEST_F(AvbToolTest, AppendVBMetaImage) {
1525 size_t boot_size = 5 * 1024 * 1024;
1526 size_t boot_partition_size = 32 * 1024 * 1024;
1527 base::FilePath boot_path = GenerateImage("boot", boot_size);
1528
1529 GenerateVBMetaImage("vbmeta.img",
1530 "SHA256_RSA2048",
1531 0,
1532 base::FilePath("test/data/testkey_rsa2048.pem"),
1533 std::string("--append_to_release_string \"\" "
1534 "--kernel_cmdline foo"));
1535
1536 EXPECT_COMMAND(0,
1537 "./avbtool append_vbmeta_image "
1538 "--image %s "
1539 "--partition_size %d "
1540 "--vbmeta_image %s ",
1541 boot_path.value().c_str(),
1542 (int)boot_partition_size,
1543 vbmeta_image_path_.value().c_str());
1544
1545 std::string vbmeta_contents = InfoImage(vbmeta_image_path_);
1546 std::string boot_contents = InfoImage(boot_path);
1547
1548 // Check that boot.img has the same vbmeta blob as from vbmeta.img -
1549 // we do this by inspecting 'avbtool info_image' output combined
1550 // with the known footer location given boot.img has 5 MiB known
1551 // content and the partition size is 32 MiB.
1552 ASSERT_EQ(
1553 "Minimum libavb version: 1.0\n"
1554 "Header Block: 256 bytes\n"
1555 "Authentication Block: 320 bytes\n"
1556 "Auxiliary Block: 576 bytes\n"
1557 "Algorithm: SHA256_RSA2048\n"
1558 "Rollback Index: 0\n"
1559 "Flags: 0\n"
1560 "Release String: 'avbtool 1.0.0 '\n"
1561 "Descriptors:\n"
1562 " Kernel Cmdline descriptor:\n"
1563 " Flags: 0\n"
1564 " Kernel Cmdline: 'foo'\n",
1565 vbmeta_contents);
1566 std::string known_footer =
1567 "Footer version: 1.0\n"
1568 "Image size: 33554432 bytes\n"
1569 "Original image size: 5242880 bytes\n"
1570 "VBMeta offset: 5242880\n"
1571 "VBMeta size: 1152 bytes\n"
1572 "--\n";
1573 ASSERT_EQ(known_footer + vbmeta_contents, boot_contents);
1574
1575 // Also verify that the blobs are the same, bit for bit.
1576 base::File f =
1577 base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
1578 std::vector<uint8_t> loaded_vbmeta;
1579 loaded_vbmeta.resize(1152);
1580 EXPECT_EQ(
1581 f.Read(
1582 5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152),
1583 1152);
1584 EXPECT_EQ(vbmeta_image_, loaded_vbmeta);
1585 }
1586
TEST_F(AvbToolTest,SigningHelperBasic)1587 TEST_F(AvbToolTest, SigningHelperBasic) {
1588 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1589 base::FilePath signing_helper_test_path =
1590 testdir_.Append("signing_helper_test");
1591 EXPECT_COMMAND(
1592 0,
1593 "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1594 "--output %s "
1595 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1596 "--signing_helper test/avbtool_signing_helper_test.py "
1597 "--internal_release_string \"\"",
1598 signing_helper_test_path.value().c_str(),
1599 vbmeta_path.value().c_str());
1600
1601 // Now check the value in test file.
1602 std::string value;
1603 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1604 EXPECT_EQ("DONE", value);
1605 }
1606
TEST_F(AvbToolTest,SigningHelperWithFilesBasic)1607 TEST_F(AvbToolTest, SigningHelperWithFilesBasic) {
1608 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1609 base::FilePath signing_helper_test_path =
1610 testdir_.Append("signing_helper_test");
1611 EXPECT_COMMAND(
1612 0,
1613 "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1614 "--output %s "
1615 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1616 "--signing_helper_with_files "
1617 "test/avbtool_signing_helper_with_files_test.py "
1618 "--internal_release_string \"\"",
1619 signing_helper_test_path.value().c_str(),
1620 vbmeta_path.value().c_str());
1621
1622 // Now check the value in test file.
1623 std::string value;
1624 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1625 EXPECT_EQ("DONE", value);
1626 }
1627
TEST_F(AvbToolTest,SigningHelperReturnError)1628 TEST_F(AvbToolTest, SigningHelperReturnError) {
1629 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1630 EXPECT_COMMAND(
1631 1,
1632 "./avbtool make_vbmeta_image "
1633 "--output %s "
1634 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1635 "--signing_helper test/avbtool_signing_helper_test.py "
1636 "--internal_release_string \"\"",
1637 vbmeta_path.value().c_str());
1638 }
1639
TEST_F(AvbToolTest,SigningHelperWithFilesReturnError)1640 TEST_F(AvbToolTest, SigningHelperWithFilesReturnError) {
1641 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1642 EXPECT_COMMAND(
1643 1,
1644 "./avbtool make_vbmeta_image "
1645 "--output %s "
1646 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1647 "--signing_helper_with_files "
1648 "test/avbtool_signing_helper_with_files_test.py "
1649 "--internal_release_string \"\"",
1650 vbmeta_path.value().c_str());
1651 }
1652
TEST_F(AvbToolTest,VerifyImageNoSignature)1653 TEST_F(AvbToolTest, VerifyImageNoSignature) {
1654 GenerateVBMetaImage("vbmeta.img",
1655 "", // NONE
1656 0,
1657 base::FilePath());
1658
1659 EXPECT_COMMAND(0,
1660 "./avbtool verify_image "
1661 "--image %s ",
1662 vbmeta_image_path_.value().c_str());
1663 }
1664
TEST_F(AvbToolTest,VerifyImageValidSignature)1665 TEST_F(AvbToolTest, VerifyImageValidSignature) {
1666 GenerateVBMetaImage("vbmeta.img",
1667 "SHA256_RSA2048",
1668 0,
1669 base::FilePath("test/data/testkey_rsa2048.pem"));
1670
1671 EXPECT_COMMAND(0,
1672 "./avbtool verify_image "
1673 "--image %s ",
1674 vbmeta_image_path_.value().c_str());
1675 }
1676
TEST_F(AvbToolTest,VerifyImageCorruptedVBMeta)1677 TEST_F(AvbToolTest, VerifyImageCorruptedVBMeta) {
1678 GenerateVBMetaImage("vbmeta.img",
1679 "SHA256_RSA2048",
1680 0,
1681 base::FilePath("test/data/testkey_rsa2048.pem"));
1682
1683 // Corrupt four bytes of data in the end of the image. Since the aux
1684 // data is at the end and this data is signed, this will change the
1685 // value of the computed hash.
1686 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
1687 EXPECT_EQ(AVB_IO_RESULT_OK,
1688 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
1689 "vbmeta",
1690 -4, // offset from end
1691 sizeof corrupt_data,
1692 corrupt_data));
1693
1694 EXPECT_COMMAND(1,
1695 "./avbtool verify_image "
1696 "--image %s ",
1697 vbmeta_image_path_.value().c_str());
1698 }
1699
TEST_F(AvbToolTest,VerifyImageOtherKeyMatching)1700 TEST_F(AvbToolTest, VerifyImageOtherKeyMatching) {
1701 GenerateVBMetaImage("vbmeta.img",
1702 "SHA256_RSA2048",
1703 0,
1704 base::FilePath("test/data/testkey_rsa2048.pem"));
1705
1706 EXPECT_COMMAND(0,
1707 "./avbtool verify_image "
1708 "--image %s --key test/data/testkey_rsa2048.pem",
1709 vbmeta_image_path_.value().c_str());
1710 }
1711
TEST_F(AvbToolTest,VerifyImageOtherKeyNotMatching)1712 TEST_F(AvbToolTest, VerifyImageOtherKeyNotMatching) {
1713 GenerateVBMetaImage("vbmeta.img",
1714 "SHA256_RSA2048",
1715 0,
1716 base::FilePath("test/data/testkey_rsa2048.pem"));
1717
1718 EXPECT_COMMAND(1,
1719 "./avbtool verify_image "
1720 "--image %s --key test/data/testkey_rsa4096.pem",
1721 vbmeta_image_path_.value().c_str());
1722 }
1723
TEST_F(AvbToolTest,VerifyImageBrokenSignature)1724 TEST_F(AvbToolTest, VerifyImageBrokenSignature) {
1725 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1726 base::FilePath signing_helper_test_path =
1727 testdir_.Append("signing_helper_test");
1728
1729 // Intentionally make the signer generate a wrong signature.
1730 EXPECT_COMMAND(
1731 0,
1732 "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool make_vbmeta_image "
1733 "--output %s "
1734 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1735 "--signing_helper test/avbtool_signing_helper_test.py "
1736 "--internal_release_string \"\"",
1737 vbmeta_path.value().c_str());
1738
1739 EXPECT_COMMAND(1,
1740 "./avbtool verify_image "
1741 "--image %s ",
1742 vbmeta_path.value().c_str());
1743 }
1744
1745 // Helper to generate boot.img, unsparse system.img, and vbmeta.img.
GenerateImageWithHashAndHashtreeSetup()1746 void AvbToolTest::GenerateImageWithHashAndHashtreeSetup() {
1747 const size_t boot_partition_size = 16 * 1024 * 1024;
1748 const size_t boot_image_size = 5 * 1024 * 1024;
1749 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
1750 EXPECT_COMMAND(0,
1751 "./avbtool add_hash_footer"
1752 " --image %s"
1753 " --rollback_index 0"
1754 " --partition_name boot"
1755 " --partition_size %zd"
1756 " --salt deadbeef"
1757 " --internal_release_string \"\"",
1758 boot_path.value().c_str(),
1759 boot_partition_size);
1760
1761 const size_t system_partition_size = 10 * 1024 * 1024;
1762 const size_t system_image_size = 8 * 1024 * 1024;
1763 base::FilePath system_path = GenerateImage("system.img", system_image_size);
1764 EXPECT_COMMAND(0,
1765 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1766 "--partition_size %zd --partition_name system "
1767 "--internal_release_string \"\" ",
1768 system_path.value().c_str(),
1769 system_partition_size);
1770
1771 GenerateVBMetaImage("vbmeta.img",
1772 "SHA256_RSA2048",
1773 0,
1774 base::FilePath("test/data/testkey_rsa2048.pem"),
1775 base::StringPrintf("--include_descriptors_from_image %s "
1776 "--include_descriptors_from_image %s",
1777 boot_path.value().c_str(),
1778 system_path.value().c_str()));
1779 }
1780
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtree)1781 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) {
1782 GenerateImageWithHashAndHashtreeSetup();
1783
1784 // Do two checks - one for system.img not sparse, and one where it
1785 // is sparse.
1786 for (int n = 0; n < 2; n++) {
1787 EXPECT_COMMAND(0,
1788 "./avbtool verify_image "
1789 "--image %s ",
1790 vbmeta_image_path_.value().c_str());
1791 if (n == 0) {
1792 EXPECT_COMMAND(0,
1793 "img2simg %s %s.sparse",
1794 testdir_.Append("system.img").value().c_str(),
1795 testdir_.Append("system.img").value().c_str());
1796 EXPECT_COMMAND(0,
1797 "mv %s.sparse %s",
1798 testdir_.Append("system.img").value().c_str(),
1799 testdir_.Append("system.img").value().c_str());
1800 }
1801 }
1802 }
1803
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHash)1804 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) {
1805 GenerateImageWithHashAndHashtreeSetup();
1806
1807 // Corrupt four bytes of data in the middle of boot.img.
1808 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
1809 EXPECT_EQ(AVB_IO_RESULT_OK,
1810 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
1811 "boot",
1812 105 * 1024, // offset from start
1813 sizeof corrupt_data,
1814 corrupt_data));
1815
1816 EXPECT_COMMAND(1,
1817 "./avbtool verify_image "
1818 "--image %s ",
1819 vbmeta_image_path_.value().c_str());
1820 }
1821
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHashtree)1822 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHashtree) {
1823 GenerateImageWithHashAndHashtreeSetup();
1824
1825 // Corrupt four bytes of data in the middle of system.img.
1826 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
1827 EXPECT_EQ(AVB_IO_RESULT_OK,
1828 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
1829 "system",
1830 123 * 1024, // offset from start
1831 sizeof corrupt_data,
1832 corrupt_data));
1833
1834 // Do two checks - one for system.img not sparse, and one where it
1835 // is sparse.
1836 for (int n = 0; n < 2; n++) {
1837 EXPECT_COMMAND(1,
1838 "./avbtool verify_image "
1839 "--image %s ",
1840 vbmeta_image_path_.value().c_str());
1841 if (n == 0) {
1842 EXPECT_COMMAND(0,
1843 "img2simg %s %s.sparse",
1844 testdir_.Append("system.img").value().c_str(),
1845 testdir_.Append("system.img").value().c_str());
1846 EXPECT_COMMAND(0,
1847 "mv %s.sparse %s",
1848 testdir_.Append("system.img").value().c_str(),
1849 testdir_.Append("system.img").value().c_str());
1850 }
1851 }
1852 }
1853
TEST_F(AvbToolTest,VerifyImageChainPartition)1854 TEST_F(AvbToolTest, VerifyImageChainPartition) {
1855 base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
1856 EXPECT_COMMAND(
1857 0,
1858 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
1859 " --output %s",
1860 pk4096_path.value().c_str());
1861
1862 base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey");
1863 EXPECT_COMMAND(
1864 0,
1865 "./avbtool extract_public_key --key test/data/testkey_rsa8192.pem"
1866 " --output %s",
1867 pk8192_path.value().c_str());
1868
1869 GenerateVBMetaImage("vbmeta.img",
1870 "SHA256_RSA2048",
1871 0,
1872 base::FilePath("test/data/testkey_rsa2048.pem"),
1873 base::StringPrintf("--chain_partition system:1:%s ",
1874 pk4096_path.value().c_str()));
1875
1876 // Should not fail (name, rollback_index, contents all correct).
1877 EXPECT_COMMAND(0,
1878 "./avbtool verify_image "
1879 "--image %s "
1880 "--expected_chain_partition system:1:%s",
1881 vbmeta_image_path_.value().c_str(),
1882 pk4096_path.value().c_str());
1883
1884 // Should fail because we didn't use --expected_chain_partition.
1885 EXPECT_COMMAND(1,
1886 "./avbtool verify_image "
1887 "--image %s ",
1888 vbmeta_image_path_.value().c_str());
1889
1890 // Should fail because partition name is wrong.
1891 EXPECT_COMMAND(1,
1892 "./avbtool verify_image "
1893 "--image %s "
1894 "--expected_chain_partition xyz:1:%s",
1895 vbmeta_image_path_.value().c_str(),
1896 pk4096_path.value().c_str());
1897
1898 // Should fail because rollback index location is wrong.
1899 EXPECT_COMMAND(1,
1900 "./avbtool verify_image "
1901 "--image %s "
1902 "--expected_chain_partition system:2:%s",
1903 vbmeta_image_path_.value().c_str(),
1904 pk4096_path.value().c_str());
1905
1906 // Should fail because public key blob is wrong.
1907 EXPECT_COMMAND(1,
1908 "./avbtool verify_image "
1909 "--image %s "
1910 "--expected_chain_partition system:1:%s",
1911 vbmeta_image_path_.value().c_str(),
1912 pk8192_path.value().c_str());
1913 }
1914
TEST_F(AvbToolTest,PrintRequiredLibavbVersion)1915 TEST_F(AvbToolTest, PrintRequiredLibavbVersion) {
1916 base::FilePath output_path = testdir_.Append("versions.txt");
1917
1918 const size_t boot_partition_size = 16 * 1024 * 1024;
1919 EXPECT_COMMAND(0,
1920 "./avbtool add_hash_footer"
1921 " --rollback_index 0"
1922 " --partition_name boot"
1923 " --partition_size %zd"
1924 " --salt deadbeef"
1925 " --internal_release_string \"\""
1926 " --print_required_libavb_version >> %s",
1927 boot_partition_size,
1928 output_path.value().c_str());
1929
1930 const size_t system_partition_size = 10 * 1024 * 1024;
1931 EXPECT_COMMAND(0,
1932 "./avbtool add_hashtree_footer --salt d00df00d "
1933 "--partition_size %zd --partition_name system "
1934 "--internal_release_string \"\""
1935 " --print_required_libavb_version >> %s",
1936 system_partition_size,
1937 output_path.value().c_str());
1938
1939 EXPECT_COMMAND(0,
1940 "./avbtool make_vbmeta_image "
1941 "--algorithm SHA256_RSA2048 "
1942 "--key test/data/testkey_rsa2048.pem "
1943 "--internal_release_string \"\""
1944 " --print_required_libavb_version >> %s",
1945 output_path.value().c_str());
1946
1947 // Check that "1.0\n" was printed for all three invocations.
1948 std::string versions;
1949 ASSERT_TRUE(base::ReadFileToString(output_path, &versions));
1950 EXPECT_EQ(versions, std::string("1.0\n1.0\n1.0\n"));
1951 }
1952
TEST_F(AvbToolTest,MakeAtxPikCertificate)1953 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
1954 base::FilePath subject_path = testdir_.Append("tmp_subject");
1955 ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
1956 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
1957 EXPECT_COMMAND(
1958 0,
1959 "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
1960 pubkey_path.value().c_str());
1961
1962 base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
1963 EXPECT_COMMAND(0,
1964 "./avbtool make_atx_certificate"
1965 " --subject %s"
1966 " --subject_key %s"
1967 " --subject_key_version 42"
1968 " --subject_is_intermediate_authority"
1969 " --authority_key test/data/testkey_atx_prk.pem"
1970 " --output %s",
1971 subject_path.value().c_str(),
1972 pubkey_path.value().c_str(),
1973 output_path.value().c_str());
1974
1975 EXPECT_COMMAND(0,
1976 "diff test/data/atx_pik_certificate.bin %s",
1977 output_path.value().c_str());
1978 }
1979
TEST_F(AvbToolTest,MakeAtxPskCertificate)1980 TEST_F(AvbToolTest, MakeAtxPskCertificate) {
1981 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
1982 EXPECT_COMMAND(
1983 0,
1984 "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
1985 pubkey_path.value().c_str());
1986
1987 base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
1988 EXPECT_COMMAND(0,
1989 "./avbtool make_atx_certificate"
1990 " --subject test/data/atx_product_id.bin"
1991 " --subject_key %s"
1992 " --subject_key_version 42"
1993 " --authority_key test/data/testkey_atx_pik.pem"
1994 " --output %s",
1995 pubkey_path.value().c_str(),
1996 output_path.value().c_str());
1997
1998 EXPECT_COMMAND(0,
1999 "diff test/data/atx_psk_certificate.bin %s",
2000 output_path.value().c_str());
2001 }
2002
TEST_F(AvbToolTest,MakeAtxPermanentAttributes)2003 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) {
2004 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
2005 EXPECT_COMMAND(
2006 0,
2007 "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
2008 pubkey_path.value().c_str());
2009
2010 base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
2011 EXPECT_COMMAND(0,
2012 "./avbtool make_atx_permanent_attributes"
2013 " --root_authority_key %s"
2014 " --product_id test/data/atx_product_id.bin"
2015 " --output %s",
2016 pubkey_path.value().c_str(),
2017 output_path.value().c_str());
2018
2019 EXPECT_COMMAND(0,
2020 "diff test/data/atx_permanent_attributes.bin %s",
2021 output_path.value().c_str());
2022 }
2023
TEST_F(AvbToolTest,MakeAtxMetadata)2024 TEST_F(AvbToolTest, MakeAtxMetadata) {
2025 base::FilePath output_path = testdir_.Append("tmp_metadata.bin");
2026
2027 EXPECT_COMMAND(
2028 0,
2029 "./avbtool make_atx_metadata"
2030 " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
2031 " --product_key_certificate test/data/atx_psk_certificate.bin"
2032 " --output %s",
2033 output_path.value().c_str());
2034
2035 EXPECT_COMMAND(
2036 0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str());
2037 }
2038
2039 } // namespace avb
2040