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 " Flags: 0\n",
414 partition_size,
415 sparse_image ? " (Sparse)" : "");
416 }
417
AddHashFooterTest(bool sparse_image)418 void AvbToolTest::AddHashFooterTest(bool sparse_image) {
419 const size_t rootfs_size = 1028 * 1024;
420 const size_t partition_size = 1536 * 1024;
421 const size_t resized_partition_size = 1280 * 1024;
422
423 // Generate a 1028 KiB file with known content. Some content have
424 // been arranged to ensure FILL_DATA segments in the sparse file.
425 std::vector<uint8_t> rootfs;
426 rootfs.resize(rootfs_size);
427 for (size_t n = 0; n < rootfs_size; n++) {
428 if ((n >= 5 * 1000 && n < 105 * 1000) ||
429 (n >= 205 * 1000 && n < 305 * 1000) ||
430 (n >= 505 * 1000 && n < 605 * 1000)) {
431 rootfs[n] = uint8_t(n) & 0x03;
432 } else {
433 rootfs[n] = uint8_t(n);
434 }
435 }
436 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
437 base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
438 EXPECT_EQ(rootfs_size,
439 static_cast<const size_t>(
440 base::WriteFile(rootfs_path,
441 reinterpret_cast<const char*>(rootfs.data()),
442 rootfs.size())));
443
444 if (sparse_image) {
445 EXPECT_COMMAND(0,
446 "mv %s %s.unsparse",
447 rootfs_path.value().c_str(),
448 rootfs_path.value().c_str());
449 EXPECT_COMMAND(0,
450 "img2simg %s.unsparse %s",
451 rootfs_path.value().c_str(),
452 rootfs_path.value().c_str());
453 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
454 }
455
456 /* Do this twice to check that 'add_hash_footer' is idempotent. */
457 for (int n = 0; n < 2; n++) {
458 EXPECT_COMMAND(0,
459 "./avbtool add_hash_footer --salt d00df00d "
460 "--hash_algorithm sha256 --image %s "
461 "--partition_size %d --partition_name foobar "
462 "--algorithm SHA256_RSA2048 "
463 "--key test/data/testkey_rsa2048.pem "
464 "--output_vbmeta %s "
465 "--internal_release_string \"\"",
466 rootfs_path.value().c_str(),
467 (int)partition_size,
468 ext_vbmeta_path.value().c_str());
469
470 ASSERT_EQ(AddHashFooterGetExpectedVBMetaInfo(sparse_image, partition_size),
471 InfoImage(rootfs_path));
472
473 ASSERT_EQ(
474 "Minimum libavb version: 1.0\n"
475 "Header Block: 256 bytes\n"
476 "Authentication Block: 320 bytes\n"
477 "Auxiliary Block: 704 bytes\n"
478 "Algorithm: SHA256_RSA2048\n"
479 "Rollback Index: 0\n"
480 "Flags: 0\n"
481 "Release String: ''\n"
482 "Descriptors:\n"
483 " Hash descriptor:\n"
484 " Image Size: 1052672 bytes\n"
485 " Hash Algorithm: sha256\n"
486 " Partition Name: foobar\n"
487 " Salt: d00df00d\n"
488 " Digest: "
489 "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f"
490 "5e4ed357fbcf58d88d9\n"
491 " Flags: 0\n",
492 InfoImage(ext_vbmeta_path));
493 }
494
495 // Resize the image and check that the only thing that has changed
496 // is where the footer is. First check that resizing to a smaller
497 // size than the original rootfs fails. Then resize to something
498 // larger than the original rootfs but smaller than the current
499 // partition size.
500 EXPECT_COMMAND(1,
501 "./avbtool resize_image --image %s "
502 "--partition_size %d",
503 rootfs_path.value().c_str(),
504 (int)(rootfs_size - 16 * 1024));
505 EXPECT_COMMAND(0,
506 "./avbtool resize_image --image %s "
507 "--partition_size %d",
508 rootfs_path.value().c_str(),
509 (int)resized_partition_size);
510 ASSERT_EQ(
511 AddHashFooterGetExpectedVBMetaInfo(sparse_image, resized_partition_size),
512 InfoImage(rootfs_path));
513
514 if (sparse_image) {
515 EXPECT_COMMAND(0,
516 "mv %s %s.sparse",
517 rootfs_path.value().c_str(),
518 rootfs_path.value().c_str());
519 EXPECT_COMMAND(0,
520 "simg2img %s.sparse %s",
521 rootfs_path.value().c_str(),
522 rootfs_path.value().c_str());
523 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
524 }
525
526 // Manually calculate the hash to check that it agrees with avbtool.
527 AvbSHA256Ctx hasher_ctx;
528 const uint8_t hasher_salt[4] = {0xd0, 0x0d, 0xf0, 0x0d};
529 avb_sha256_init(&hasher_ctx);
530 avb_sha256_update(&hasher_ctx, hasher_salt, 4);
531 avb_sha256_update(&hasher_ctx, rootfs.data(), rootfs_size);
532 uint8_t* hasher_digest = avb_sha256_final(&hasher_ctx);
533 EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
534 mem_to_hexstring(hasher_digest, AVB_SHA256_DIGEST_SIZE));
535
536 // Now check that we can find the VBMeta block again from the footer.
537 std::string part_data;
538 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
539
540 // Check footer contains correct data.
541 AvbFooter f;
542 EXPECT_NE(0,
543 avb_footer_validate_and_byteswap(
544 reinterpret_cast<const AvbFooter*>(
545 part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
546 &f));
547 EXPECT_EQ(
548 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
549 AVB_FOOTER_MAGIC);
550 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
551 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
552 EXPECT_EQ(1052672UL, f.original_image_size);
553 EXPECT_EQ(1052672UL, f.vbmeta_offset);
554 EXPECT_EQ(1280UL, f.vbmeta_size);
555
556 // Check that the vbmeta image at |f.vbmeta_offset| checks out.
557 const uint8_t* vbmeta_data =
558 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
559 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
560 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
561
562 // Collect all descriptors.
563 std::vector<const AvbDescriptor*> descriptors;
564 avb_descriptor_foreach(
565 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
566
567 // We should only have a single descriptor and it should be a
568 // hash descriptor.
569 EXPECT_EQ(1UL, descriptors.size());
570 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, avb_be64toh(descriptors[0]->tag));
571 AvbHashDescriptor d;
572 EXPECT_NE(
573 0,
574 avb_hash_descriptor_validate_and_byteswap(
575 reinterpret_cast<const AvbHashDescriptor*>(descriptors[0]), &d));
576 EXPECT_EQ(1052672UL, d.image_size);
577 EXPECT_EQ(6UL, d.partition_name_len);
578 EXPECT_EQ(4UL, d.salt_len);
579 EXPECT_EQ(32UL, d.digest_len);
580 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
581 sizeof(AvbHashDescriptor);
582 uint64_t o = 0;
583 EXPECT_EQ("foobar",
584 std::string(reinterpret_cast<const char*>(desc_end + o),
585 d.partition_name_len));
586 o += d.partition_name_len;
587 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
588 o += d.salt_len;
589 EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9",
590 mem_to_hexstring(desc_end + o, d.digest_len));
591
592 // Check that the footer is correctly erased.
593 EXPECT_COMMAND(
594 0, "./avbtool erase_footer --image %s", rootfs_path.value().c_str());
595 int64_t erased_footer_file_size;
596 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
597 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size);
598
599 // Check that --do_not_append_vbmeta_image works as intended.
600 EXPECT_COMMAND(0,
601 "./avbtool add_hash_footer --salt d00df00d "
602 "--hash_algorithm sha256 --image %s "
603 "--partition_size %d --partition_name foobar "
604 "--algorithm SHA256_RSA2048 "
605 "--key test/data/testkey_rsa2048.pem "
606 "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
607 "--internal_release_string \"\"",
608 rootfs_path.value().c_str(),
609 (int)partition_size,
610 ext_vbmeta_path.value().c_str());
611 int64_t file_size;
612 ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
613 EXPECT_EQ(static_cast<size_t>(file_size), rootfs_size);
614 EXPECT_COMMAND(0,
615 "diff %s %s_2nd_run",
616 ext_vbmeta_path.value().c_str(),
617 ext_vbmeta_path.value().c_str());
618 }
619
TEST_F(AvbToolTest,AddHashFooter)620 TEST_F(AvbToolTest, AddHashFooter) {
621 AddHashFooterTest(false);
622 }
623
TEST_F(AvbToolTest,AddHashFooterSparse)624 TEST_F(AvbToolTest, AddHashFooterSparse) {
625 AddHashFooterTest(true);
626 }
627
RemoveLinesStartingWith(const std::string & str,const std::string & prefix)628 static std::string RemoveLinesStartingWith(const std::string& str,
629 const std::string& prefix) {
630 std::vector<std::string> lines;
631 std::string ret;
632
633 lines = base::SplitString(
634 str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
635 for (const std::string& line : lines) {
636 if (!base::StartsWith(line, prefix, base::CompareCase::SENSITIVE)) {
637 ret += line;
638 ret += '\n';
639 }
640 }
641 return ret;
642 }
643
TEST_F(AvbToolTest,AddHashFooterSparseWithHoleAtTheEnd)644 TEST_F(AvbToolTest, AddHashFooterSparseWithHoleAtTheEnd) {
645 const size_t partition_size = 10 * 1024 * 1024;
646 const size_t metadata_size = 128 * 1024;
647
648 // It's not enough to run img2simg on a file with a lot of zeroes at
649 // the end since that will turn up as "Fill with value (for value =
650 // 0x00000000)" and not "Don't care". Instead, use make_ext4fs for
651 // this since it will put a big hole (e.g. "Don't care" chunk) at
652 // the end.
653 base::FilePath partition_path = testdir_.Append("partition.bin");
654 EXPECT_COMMAND(0,
655 "make_ext4fs -s -L test -l %zd %s",
656 partition_size - metadata_size,
657 partition_path.value().c_str());
658
659 EXPECT_COMMAND(0,
660 "./avbtool add_hash_footer --salt d00df00d "
661 "--hash_algorithm sha256 --image %s "
662 "--partition_size %d --partition_name foobar "
663 "--algorithm SHA256_RSA2048 "
664 "--key test/data/testkey_rsa2048.pem "
665 "--internal_release_string \"\"",
666 partition_path.value().c_str(),
667 (int)partition_size);
668
669 // Since we may be using an arbritary version of make_ext4fs
670 // (because of different branches) the contents of the resulting
671 // disk image may slightly change. It's enough to just remove the
672 // "Digest:" line from the output to work around this.
673 std::string info =
674 RemoveLinesStartingWith(InfoImage(partition_path), " Digest:");
675 ASSERT_EQ(
676 "Footer version: 1.0\n"
677 "Image size: 10485760 bytes\n"
678 "Original image size: 10354688 bytes\n"
679 "VBMeta offset: 10354688\n"
680 "VBMeta size: 1280 bytes\n"
681 "--\n"
682 "Minimum libavb version: 1.0 (Sparse)\n"
683 "Header Block: 256 bytes\n"
684 "Authentication Block: 320 bytes\n"
685 "Auxiliary Block: 704 bytes\n"
686 "Algorithm: SHA256_RSA2048\n"
687 "Rollback Index: 0\n"
688 "Flags: 0\n"
689 "Release String: ''\n"
690 "Descriptors:\n"
691 " Hash descriptor:\n"
692 " Image Size: 10354688 bytes\n"
693 " Hash Algorithm: sha256\n"
694 " Partition Name: foobar\n"
695 " Salt: d00df00d\n"
696 " Flags: 0\n",
697 info);
698
699 EXPECT_COMMAND(0,
700 "mv %s %s.sparse",
701 partition_path.value().c_str(),
702 partition_path.value().c_str());
703 EXPECT_COMMAND(0,
704 "simg2img %s.sparse %s",
705 partition_path.value().c_str(),
706 partition_path.value().c_str());
707 EXPECT_COMMAND(0, "rm -f %s.sparse", partition_path.value().c_str());
708 }
709
TEST_F(AvbToolTest,AddHashFooterCalcMaxImageSize)710 TEST_F(AvbToolTest, AddHashFooterCalcMaxImageSize) {
711 const size_t partition_size = 10 * 1024 * 1024;
712 base::FilePath output_path = testdir_.Append("max_size.txt");
713
714 EXPECT_COMMAND(0,
715 "./avbtool add_hash_footer "
716 "--partition_size %zd "
717 "--calc_max_image_size > %s",
718 partition_size,
719 output_path.value().c_str());
720 std::string max_image_size_data;
721 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
722 EXPECT_EQ("10416128\n", max_image_size_data);
723 size_t max_image_size = atoll(max_image_size_data.c_str());
724
725 // Metadata takes up 68 KiB.
726 EXPECT_EQ(68 * 1024ULL, partition_size - max_image_size);
727
728 // Check that we can add a hash footer for an image this size for
729 // such a partition size.
730 base::FilePath boot_path = GenerateImage("boot", max_image_size);
731 EXPECT_COMMAND(0,
732 "./avbtool add_hash_footer"
733 " --image %s"
734 " --partition_name boot"
735 " --partition_size %zd"
736 " --salt deadbeef"
737 " --algorithm SHA512_RSA4096 "
738 " --key test/data/testkey_rsa4096.pem"
739 " --internal_release_string \"\"",
740 boot_path.value().c_str(),
741 partition_size);
742 }
743
TEST_F(AvbToolTest,AddHashFooterWithPersistentDigest)744 TEST_F(AvbToolTest, AddHashFooterWithPersistentDigest) {
745 size_t partition_size = 1024 * 1024;
746 base::FilePath path = GenerateImage("digest_location", 1024);
747 EXPECT_COMMAND(0,
748 "./avbtool add_hash_footer --salt d00df00d "
749 "--hash_algorithm sha256 --image %s "
750 "--partition_size %d --partition_name foobar "
751 "--algorithm SHA256_RSA2048 "
752 "--key test/data/testkey_rsa2048.pem "
753 "--internal_release_string \"\" "
754 "--use_persistent_digest",
755 path.value().c_str(),
756 (int)partition_size);
757 // There are two important bits specific to these flags:
758 // Minimum libavb version = 1.1
759 // Hash descriptor -> Digest = (empty)
760 ASSERT_EQ(
761 "Footer version: 1.0\n"
762 "Image size: 1048576 bytes\n"
763 "Original image size: 1024 bytes\n"
764 "VBMeta offset: 4096\n"
765 "VBMeta size: 1280 bytes\n"
766 "--\n"
767 "Minimum libavb version: 1.1\n"
768 "Header Block: 256 bytes\n"
769 "Authentication Block: 320 bytes\n"
770 "Auxiliary Block: 704 bytes\n"
771 "Algorithm: SHA256_RSA2048\n"
772 "Rollback Index: 0\n"
773 "Flags: 0\n"
774 "Release String: ''\n"
775 "Descriptors:\n"
776 " Hash descriptor:\n"
777 " Image Size: 1024 bytes\n"
778 " Hash Algorithm: sha256\n"
779 " Partition Name: foobar\n"
780 " Salt: d00df00d\n"
781 " Digest: \n"
782 " Flags: 0\n",
783 InfoImage(path));
784 }
785
TEST_F(AvbToolTest,AddHashFooterWithNoAB)786 TEST_F(AvbToolTest, AddHashFooterWithNoAB) {
787 size_t partition_size = 1024 * 1024;
788 base::FilePath path = GenerateImage("digest_location", 1024);
789 EXPECT_COMMAND(0,
790 "./avbtool add_hash_footer --salt d00df00d "
791 "--hash_algorithm sha256 --image %s "
792 "--partition_size %d --partition_name foobar "
793 "--algorithm SHA256_RSA2048 "
794 "--key test/data/testkey_rsa2048.pem "
795 "--internal_release_string \"\" "
796 "--do_not_use_ab",
797 path.value().c_str(),
798 (int)partition_size);
799 // There are two important bits specific to these flags:
800 // Minimum libavb version = 1.1
801 // Hash descriptor -> Flags = 1
802 ASSERT_EQ(
803 "Footer version: 1.0\n"
804 "Image size: 1048576 bytes\n"
805 "Original image size: 1024 bytes\n"
806 "VBMeta offset: 4096\n"
807 "VBMeta size: 1280 bytes\n"
808 "--\n"
809 "Minimum libavb version: 1.1\n"
810 "Header Block: 256 bytes\n"
811 "Authentication Block: 320 bytes\n"
812 "Auxiliary Block: 704 bytes\n"
813 "Algorithm: SHA256_RSA2048\n"
814 "Rollback Index: 0\n"
815 "Flags: 0\n"
816 "Release String: ''\n"
817 "Descriptors:\n"
818 " Hash descriptor:\n"
819 " Image Size: 1024 bytes\n"
820 " Hash Algorithm: sha256\n"
821 " Partition Name: foobar\n"
822 " Salt: d00df00d\n"
823 " Digest: "
824 "91386fea3e251ad0c2cb6859e4f4772f37fdb69f17d46636ddc9e7fbfd3bf3d0\n"
825 " Flags: 1\n",
826 InfoImage(path));
827 }
828
TEST_F(AvbToolTest,AddHashFooterWithPersistentDigestAndNoAB)829 TEST_F(AvbToolTest, AddHashFooterWithPersistentDigestAndNoAB) {
830 size_t partition_size = 1024 * 1024;
831 base::FilePath path = GenerateImage("digest_location", 1024);
832 EXPECT_COMMAND(0,
833 "./avbtool add_hash_footer --salt d00df00d "
834 "--hash_algorithm sha256 --image %s "
835 "--partition_size %d --partition_name foobar "
836 "--algorithm SHA256_RSA2048 "
837 "--key test/data/testkey_rsa2048.pem "
838 "--internal_release_string \"\" "
839 "--use_persistent_digest --do_not_use_ab",
840 path.value().c_str(),
841 (int)partition_size);
842 // There are three important bits specific to these flags:
843 // Minimum libavb version = 1.1
844 // Hash descriptor -> Digest = (empty)
845 // Hash descriptor -> Flags = 1
846 ASSERT_EQ(
847 "Footer version: 1.0\n"
848 "Image size: 1048576 bytes\n"
849 "Original image size: 1024 bytes\n"
850 "VBMeta offset: 4096\n"
851 "VBMeta size: 1280 bytes\n"
852 "--\n"
853 "Minimum libavb version: 1.1\n"
854 "Header Block: 256 bytes\n"
855 "Authentication Block: 320 bytes\n"
856 "Auxiliary Block: 704 bytes\n"
857 "Algorithm: SHA256_RSA2048\n"
858 "Rollback Index: 0\n"
859 "Flags: 0\n"
860 "Release String: ''\n"
861 "Descriptors:\n"
862 " Hash descriptor:\n"
863 " Image Size: 1024 bytes\n"
864 " Hash Algorithm: sha256\n"
865 " Partition Name: foobar\n"
866 " Salt: d00df00d\n"
867 " Digest: \n"
868 " Flags: 1\n",
869 InfoImage(path));
870 }
871
AddHashtreeFooterTest(bool sparse_image)872 void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
873 const size_t rootfs_size = 1028 * 1024;
874 const size_t partition_size = 1536 * 1024;
875
876 // Generate a 1028 KiB file with known content.
877 std::vector<uint8_t> rootfs;
878 rootfs.resize(rootfs_size);
879 for (size_t n = 0; n < rootfs_size; n++)
880 rootfs[n] = uint8_t(n);
881 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
882 base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
883 EXPECT_EQ(rootfs_size,
884 static_cast<const size_t>(
885 base::WriteFile(rootfs_path,
886 reinterpret_cast<const char*>(rootfs.data()),
887 rootfs.size())));
888
889 if (sparse_image) {
890 EXPECT_COMMAND(0,
891 "mv %s %s.unsparse",
892 rootfs_path.value().c_str(),
893 rootfs_path.value().c_str());
894 EXPECT_COMMAND(0,
895 "img2simg %s.unsparse %s",
896 rootfs_path.value().c_str(),
897 rootfs_path.value().c_str());
898 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
899 }
900
901 /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
902 for (int n = 0; n < 2; n++) {
903 EXPECT_COMMAND(0,
904 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
905 "--partition_size %d --partition_name foobar "
906 "--algorithm SHA256_RSA2048 "
907 "--key test/data/testkey_rsa2048.pem "
908 "--output_vbmeta_image %s "
909 "--internal_release_string \"\" "
910 "--do_not_generate_fec",
911 rootfs_path.value().c_str(),
912 (int)partition_size,
913 ext_vbmeta_path.value().c_str());
914
915 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n"
916 "Image size: 1572864 bytes\n"
917 "Original image size: 1052672 bytes\n"
918 "VBMeta offset: 1069056\n"
919 "VBMeta size: 1344 bytes\n"
920 "--\n"
921 "Minimum libavb version: 1.0%s\n"
922 "Header Block: 256 bytes\n"
923 "Authentication Block: 320 bytes\n"
924 "Auxiliary Block: 768 bytes\n"
925 "Algorithm: SHA256_RSA2048\n"
926 "Rollback Index: 0\n"
927 "Flags: 0\n"
928 "Release String: ''\n"
929 "Descriptors:\n"
930 " Hashtree descriptor:\n"
931 " Version of dm-verity: 1\n"
932 " Image Size: 1052672 bytes\n"
933 " Tree Offset: 1052672\n"
934 " Tree Size: 16384 bytes\n"
935 " Data Block Size: 4096 bytes\n"
936 " Hash Block Size: 4096 bytes\n"
937 " FEC num roots: 0\n"
938 " FEC offset: 0\n"
939 " FEC size: 0 bytes\n"
940 " Hash Algorithm: sha1\n"
941 " Partition Name: foobar\n"
942 " Salt: d00df00d\n"
943 " Root Digest: "
944 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
945 " Flags: 0\n",
946 sparse_image ? " (Sparse)" : ""),
947 InfoImage(rootfs_path));
948
949 ASSERT_EQ(
950 "Minimum libavb version: 1.0\n"
951 "Header Block: 256 bytes\n"
952 "Authentication Block: 320 bytes\n"
953 "Auxiliary Block: 768 bytes\n"
954 "Algorithm: SHA256_RSA2048\n"
955 "Rollback Index: 0\n"
956 "Flags: 0\n"
957 "Release String: ''\n"
958 "Descriptors:\n"
959 " Hashtree descriptor:\n"
960 " Version of dm-verity: 1\n"
961 " Image Size: 1052672 bytes\n"
962 " Tree Offset: 1052672\n"
963 " Tree Size: 16384 bytes\n"
964 " Data Block Size: 4096 bytes\n"
965 " Hash Block Size: 4096 bytes\n"
966 " FEC num roots: 0\n"
967 " FEC offset: 0\n"
968 " FEC size: 0 bytes\n"
969 " Hash Algorithm: sha1\n"
970 " Partition Name: foobar\n"
971 " Salt: d00df00d\n"
972 " Root Digest: "
973 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
974 " Flags: 0\n",
975 InfoImage(ext_vbmeta_path));
976 }
977
978 if (sparse_image) {
979 EXPECT_COMMAND(0,
980 "mv %s %s.sparse",
981 rootfs_path.value().c_str(),
982 rootfs_path.value().c_str());
983 EXPECT_COMMAND(0,
984 "simg2img %s.sparse %s",
985 rootfs_path.value().c_str(),
986 rootfs_path.value().c_str());
987 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
988 }
989
990 // To check that we generate the correct hashtree we can use
991 // veritysetup(1) - another codebase for working with dm-verity
992 // hashtrees - to verify it.
993 //
994 // If we don't want to impose the requirement of having the
995 // veritysetup(1) command available on builders we can comment this
996 // out.
997 EXPECT_COMMAND(0,
998 "veritysetup --no-superblock --format=1 --hash=sha1 "
999 "--data-block-size=4096 --hash-block-size=4096 "
1000 "--salt=d00df00d "
1001 "--data-blocks=257 "
1002 "--hash-offset=1052672 "
1003 "verify "
1004 "%s %s "
1005 "e811611467dcd6e8dc4324e45f706c2bdd51db67",
1006 rootfs_path.value().c_str(),
1007 rootfs_path.value().c_str());
1008
1009 // Now check that we can find the VBMeta block again from the footer.
1010 std::string part_data;
1011 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1012
1013 // Check footer contains correct data.
1014 AvbFooter f;
1015 EXPECT_NE(0,
1016 avb_footer_validate_and_byteswap(
1017 reinterpret_cast<const AvbFooter*>(
1018 part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1019 &f));
1020 EXPECT_EQ(
1021 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1022 AVB_FOOTER_MAGIC);
1023 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1024 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1025 EXPECT_EQ(1052672UL, f.original_image_size);
1026 EXPECT_EQ(1069056UL, f.vbmeta_offset);
1027 EXPECT_EQ(1344UL, f.vbmeta_size);
1028
1029 // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1030 const uint8_t* vbmeta_data =
1031 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1032 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1033 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1034
1035 // Collect all descriptors.
1036 std::vector<const AvbDescriptor*> descriptors;
1037 avb_descriptor_foreach(
1038 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1039
1040 // We should only have a single descriptor and it should be a
1041 // hashtree descriptor.
1042 EXPECT_EQ(1UL, descriptors.size());
1043 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1044 AvbHashtreeDescriptor d;
1045 EXPECT_NE(
1046 0,
1047 avb_hashtree_descriptor_validate_and_byteswap(
1048 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1049 EXPECT_EQ(1UL, d.dm_verity_version);
1050 EXPECT_EQ(1052672UL, d.image_size);
1051 EXPECT_EQ(1052672UL, d.tree_offset);
1052 EXPECT_EQ(16384UL, d.tree_size);
1053 EXPECT_EQ(4096UL, d.data_block_size);
1054 EXPECT_EQ(4096UL, d.hash_block_size);
1055 EXPECT_EQ(6UL, d.partition_name_len);
1056 EXPECT_EQ(4UL, d.salt_len);
1057 EXPECT_EQ(20UL, d.root_digest_len);
1058 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1059 sizeof(AvbHashtreeDescriptor);
1060 uint64_t o = 0;
1061 EXPECT_EQ("foobar",
1062 std::string(reinterpret_cast<const char*>(desc_end + o),
1063 d.partition_name_len));
1064 o += d.partition_name_len;
1065 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1066 o += d.salt_len;
1067 EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1068 mem_to_hexstring(desc_end + o, d.root_digest_len));
1069
1070 // Check that we correctly generate dm-verity kernel cmdline
1071 // snippets, if requested.
1072 base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1073 EXPECT_COMMAND(0,
1074 "./avbtool make_vbmeta_image "
1075 "--output %s "
1076 "--setup_rootfs_from_kernel %s "
1077 "--algorithm SHA256_RSA2048 "
1078 "--key test/data/testkey_rsa2048.pem "
1079 "--internal_release_string \"\"",
1080 vbmeta_dmv_path.value().c_str(),
1081 rootfs_path.value().c_str());
1082
1083 ASSERT_EQ(
1084 "Minimum libavb version: 1.0\n"
1085 "Header Block: 256 bytes\n"
1086 "Authentication Block: 320 bytes\n"
1087 "Auxiliary Block: 896 bytes\n"
1088 "Algorithm: SHA256_RSA2048\n"
1089 "Rollback Index: 0\n"
1090 "Flags: 0\n"
1091 "Release String: ''\n"
1092 "Descriptors:\n"
1093 " Kernel Cmdline descriptor:\n"
1094 " Flags: 1\n"
1095 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1096 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1097 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1098 "d00df00d 2 $(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n"
1099 " Kernel Cmdline descriptor:\n"
1100 " Flags: 2\n"
1101 " Kernel Cmdline: "
1102 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1103 InfoImage(vbmeta_dmv_path));
1104
1105 // Check that the footer is correctly erased and the hashtree
1106 // remains - see above for why the constant 1069056 is used.
1107 EXPECT_COMMAND(0,
1108 "./avbtool erase_footer --image %s --keep_hashtree",
1109 rootfs_path.value().c_str());
1110 int64_t erased_footer_file_size;
1111 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1112 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1069056UL);
1113
1114 // Check that --do_not_append_vbmeta_image works as intended.
1115 //
1116 // For this we need to reset the size of the image to the original
1117 // size because it's not possible to identify the existing hashtree.
1118 EXPECT_COMMAND(
1119 0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str());
1120 EXPECT_COMMAND(0,
1121 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1122 "--partition_size %d --partition_name foobar "
1123 "--algorithm SHA256_RSA2048 "
1124 "--key test/data/testkey_rsa2048.pem "
1125 "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image "
1126 "--internal_release_string \"\" "
1127 "--do_not_generate_fec",
1128 rootfs_path.value().c_str(),
1129 (int)partition_size,
1130 ext_vbmeta_path.value().c_str());
1131 int64_t file_size;
1132 ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size));
1133 EXPECT_EQ(static_cast<size_t>(file_size), 1069056UL);
1134 EXPECT_COMMAND(0,
1135 "diff %s %s_2nd_run",
1136 ext_vbmeta_path.value().c_str(),
1137 ext_vbmeta_path.value().c_str());
1138 }
1139
TEST_F(AvbToolTest,AddHashtreeFooter)1140 TEST_F(AvbToolTest, AddHashtreeFooter) {
1141 AddHashtreeFooterTest(false);
1142 }
1143
TEST_F(AvbToolTest,AddHashtreeFooterSparse)1144 TEST_F(AvbToolTest, AddHashtreeFooterSparse) {
1145 AddHashtreeFooterTest(true);
1146 }
1147
AddHashtreeFooterFECTest(bool sparse_image)1148 void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
1149 const size_t rootfs_size = 1028 * 1024;
1150 const size_t partition_size = 1536 * 1024;
1151
1152 // Generate a 1028 KiB file with known content.
1153 std::vector<uint8_t> rootfs;
1154 rootfs.resize(rootfs_size);
1155 for (size_t n = 0; n < rootfs_size; n++)
1156 rootfs[n] = uint8_t(n);
1157 base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
1158 EXPECT_EQ(rootfs_size,
1159 static_cast<const size_t>(
1160 base::WriteFile(rootfs_path,
1161 reinterpret_cast<const char*>(rootfs.data()),
1162 rootfs.size())));
1163
1164 if (sparse_image) {
1165 EXPECT_COMMAND(0,
1166 "mv %s %s.unsparse",
1167 rootfs_path.value().c_str(),
1168 rootfs_path.value().c_str());
1169 EXPECT_COMMAND(0,
1170 "img2simg %s.unsparse %s",
1171 rootfs_path.value().c_str(),
1172 rootfs_path.value().c_str());
1173 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str());
1174 }
1175
1176 /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
1177 for (int n = 0; n < 2; n++) {
1178 EXPECT_COMMAND(0,
1179 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
1180 "--partition_size %d --partition_name foobar "
1181 "--algorithm SHA256_RSA2048 "
1182 "--key test/data/testkey_rsa2048.pem "
1183 "--internal_release_string \"\"",
1184 rootfs_path.value().c_str(),
1185 (int)partition_size);
1186
1187 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n"
1188 "Image size: 1572864 bytes\n"
1189 "Original image size: 1052672 bytes\n"
1190 "VBMeta offset: 1085440\n"
1191 "VBMeta size: 1344 bytes\n"
1192 "--\n"
1193 "Minimum libavb version: 1.0%s\n"
1194 "Header Block: 256 bytes\n"
1195 "Authentication Block: 320 bytes\n"
1196 "Auxiliary Block: 768 bytes\n"
1197 "Algorithm: SHA256_RSA2048\n"
1198 "Rollback Index: 0\n"
1199 "Flags: 0\n"
1200 "Release String: ''\n"
1201 "Descriptors:\n"
1202 " Hashtree descriptor:\n"
1203 " Version of dm-verity: 1\n"
1204 " Image Size: 1052672 bytes\n"
1205 " Tree Offset: 1052672\n"
1206 " Tree Size: 16384 bytes\n"
1207 " Data Block Size: 4096 bytes\n"
1208 " Hash Block Size: 4096 bytes\n"
1209 " FEC num roots: 2\n"
1210 " FEC offset: 1069056\n"
1211 " FEC size: 16384 bytes\n"
1212 " Hash Algorithm: sha1\n"
1213 " Partition Name: foobar\n"
1214 " Salt: d00df00d\n"
1215 " Root Digest: "
1216 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
1217 " Flags: 0\n",
1218 sparse_image ? " (Sparse)" : ""),
1219 InfoImage(rootfs_path));
1220 }
1221
1222 if (sparse_image) {
1223 EXPECT_COMMAND(0,
1224 "mv %s %s.sparse",
1225 rootfs_path.value().c_str(),
1226 rootfs_path.value().c_str());
1227 EXPECT_COMMAND(0,
1228 "simg2img %s.sparse %s",
1229 rootfs_path.value().c_str(),
1230 rootfs_path.value().c_str());
1231 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
1232 }
1233
1234 /* TODO: would be nice to verify that the FEC data is correct. */
1235
1236 // Now check that we can find the VBMeta block again from the footer.
1237 std::string part_data;
1238 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
1239
1240 // Check footer contains correct data.
1241 AvbFooter f;
1242 EXPECT_NE(0,
1243 avb_footer_validate_and_byteswap(
1244 reinterpret_cast<const AvbFooter*>(
1245 part_data.data() + part_data.size() - AVB_FOOTER_SIZE),
1246 &f));
1247 EXPECT_EQ(
1248 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN),
1249 AVB_FOOTER_MAGIC);
1250 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major);
1251 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor);
1252 EXPECT_EQ(1052672UL, f.original_image_size);
1253 EXPECT_EQ(1085440UL, f.vbmeta_offset);
1254 EXPECT_EQ(1344UL, f.vbmeta_size);
1255
1256 // Check that the vbmeta image at |f.vbmeta_offset| checks out.
1257 const uint8_t* vbmeta_data =
1258 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset);
1259 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1260 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL));
1261
1262 // Collect all descriptors.
1263 std::vector<const AvbDescriptor*> descriptors;
1264 avb_descriptor_foreach(
1265 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors);
1266
1267 // We should only have a single descriptor and it should be a
1268 // hashtree descriptor.
1269 EXPECT_EQ(1UL, descriptors.size());
1270 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag));
1271 AvbHashtreeDescriptor d;
1272 EXPECT_NE(
1273 0,
1274 avb_hashtree_descriptor_validate_and_byteswap(
1275 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d));
1276 EXPECT_EQ(1UL, d.dm_verity_version);
1277 EXPECT_EQ(1052672UL, d.image_size);
1278 EXPECT_EQ(1052672UL, d.tree_offset);
1279 EXPECT_EQ(16384UL, d.tree_size);
1280 EXPECT_EQ(4096UL, d.data_block_size);
1281 EXPECT_EQ(2UL, d.fec_num_roots);
1282 EXPECT_EQ(1069056UL, d.fec_offset);
1283 EXPECT_EQ(16384UL, d.fec_size);
1284 EXPECT_EQ(6UL, d.partition_name_len);
1285 EXPECT_EQ(4UL, d.salt_len);
1286 EXPECT_EQ(20UL, d.root_digest_len);
1287 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1288 sizeof(AvbHashtreeDescriptor);
1289 uint64_t o = 0;
1290 EXPECT_EQ("foobar",
1291 std::string(reinterpret_cast<const char*>(desc_end + o),
1292 d.partition_name_len));
1293 o += d.partition_name_len;
1294 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len));
1295 o += d.salt_len;
1296 EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
1297 mem_to_hexstring(desc_end + o, d.root_digest_len));
1298
1299 // Check that we correctly generate dm-verity kernel cmdline
1300 // snippets, if requested.
1301 base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
1302 EXPECT_COMMAND(0,
1303 "./avbtool make_vbmeta_image "
1304 "--output %s "
1305 "--setup_rootfs_from_kernel %s "
1306 "--algorithm SHA256_RSA2048 "
1307 "--key test/data/testkey_rsa2048.pem "
1308 "--internal_release_string \"\"",
1309 vbmeta_dmv_path.value().c_str(),
1310 rootfs_path.value().c_str());
1311
1312 ASSERT_EQ(
1313 "Minimum libavb version: 1.0\n"
1314 "Header Block: 256 bytes\n"
1315 "Authentication Block: 320 bytes\n"
1316 "Auxiliary Block: 960 bytes\n"
1317 "Algorithm: SHA256_RSA2048\n"
1318 "Rollback Index: 0\n"
1319 "Flags: 0\n"
1320 "Release String: ''\n"
1321 "Descriptors:\n"
1322 " Kernel Cmdline descriptor:\n"
1323 " Flags: 1\n"
1324 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 "
1325 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
1326 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
1327 "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
1328 "use_fec_from_device "
1329 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 261 "
1330 "fec_start 261\" root=/dev/dm-0'\n"
1331 " Kernel Cmdline descriptor:\n"
1332 " Flags: 2\n"
1333 " Kernel Cmdline: "
1334 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
1335 InfoImage(vbmeta_dmv_path));
1336
1337 // Check that the footer is correctly erased and the hashtree and
1338 // FEC data remains. The constant 1085440 is used because it's where
1339 // the FEC data ends (it's at offset 1069056 and size 16384).
1340 EXPECT_COMMAND(0,
1341 "./avbtool erase_footer --image %s --keep_hashtree",
1342 rootfs_path.value().c_str());
1343 int64_t erased_footer_file_size;
1344 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
1345 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1085440UL);
1346 }
1347
TEST_F(AvbToolTest,AddHashtreeFooterFEC)1348 TEST_F(AvbToolTest, AddHashtreeFooterFEC) {
1349 AddHashtreeFooterFECTest(false);
1350 }
1351
TEST_F(AvbToolTest,AddHashtreeFooterFECSparse)1352 TEST_F(AvbToolTest, AddHashtreeFooterFECSparse) {
1353 AddHashtreeFooterFECTest(true);
1354 }
1355
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSize)1356 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSize) {
1357 const size_t partition_size = 10 * 1024 * 1024;
1358 base::FilePath output_path = testdir_.Append("max_size.txt");
1359
1360 EXPECT_COMMAND(0,
1361 "./avbtool add_hashtree_footer "
1362 "--partition_size %zd --calc_max_image_size "
1363 "--do_not_generate_fec > %s",
1364 partition_size,
1365 output_path.value().c_str());
1366 std::string max_image_size_data;
1367 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1368 EXPECT_EQ("10330112\n", max_image_size_data);
1369 size_t max_image_size = atoll(max_image_size_data.c_str());
1370
1371 // Hashtree and metadata takes up 152 KiB - compare to below with
1372 // FEC which is 244 KiB.
1373 EXPECT_EQ(152 * 1024ULL, partition_size - max_image_size);
1374
1375 // Check that we can add a hashtree with an image this size for such
1376 // a partition size.
1377 base::FilePath system_path = GenerateImage("system", max_image_size);
1378 EXPECT_COMMAND(0,
1379 "./avbtool add_hashtree_footer"
1380 " --image %s"
1381 " --partition_name system"
1382 " --partition_size %zd"
1383 " --salt deadbeef"
1384 " --algorithm SHA512_RSA4096 "
1385 " --key test/data/testkey_rsa4096.pem"
1386 " --internal_release_string \"\" "
1387 "--do_not_generate_fec",
1388 system_path.value().c_str(),
1389 partition_size);
1390 }
1391
TEST_F(AvbToolTest,AddHashtreeFooterCalcMaxImageSizeWithFEC)1392 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) {
1393 const size_t partition_size = 10 * 1024 * 1024;
1394 base::FilePath output_path = testdir_.Append("max_size.txt");
1395
1396 EXPECT_COMMAND(0,
1397 "./avbtool add_hashtree_footer "
1398 "--partition_size %zd --calc_max_image_size > %s",
1399 partition_size,
1400 output_path.value().c_str());
1401 std::string max_image_size_data;
1402 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
1403 EXPECT_EQ("10235904\n", max_image_size_data);
1404 size_t max_image_size = atoll(max_image_size_data.c_str());
1405
1406 // Hashtree, FEC codes, and metadata takes up 244 KiB - compare to
1407 // above wihtout FEC which is 152 KiB.
1408 EXPECT_EQ(244 * 1024ULL, partition_size - max_image_size);
1409
1410 // Check that we can add a hashtree with an image this size for such
1411 // a partition size.
1412 base::FilePath system_path = GenerateImage("system", max_image_size);
1413 EXPECT_COMMAND(0,
1414 "./avbtool add_hashtree_footer"
1415 " --image %s"
1416 " --partition_name system"
1417 " --partition_size %zd"
1418 " --salt deadbeef"
1419 " --algorithm SHA512_RSA4096 "
1420 " --key test/data/testkey_rsa4096.pem"
1421 " --internal_release_string \"\"",
1422 system_path.value().c_str(),
1423 partition_size);
1424 }
1425
TEST_F(AvbToolTest,AddHashtreeFooterWithPersistentDigest)1426 TEST_F(AvbToolTest, AddHashtreeFooterWithPersistentDigest) {
1427 size_t partition_size = 10 * 1024 * 1024;
1428 base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1429 EXPECT_COMMAND(0,
1430 "./avbtool add_hashtree_footer --salt d00df00d "
1431 "--hash_algorithm sha256 --image %s "
1432 "--partition_size %d --partition_name foobar "
1433 "--algorithm SHA256_RSA2048 "
1434 "--key test/data/testkey_rsa2048.pem "
1435 "--internal_release_string \"\" "
1436 "--use_persistent_digest",
1437 path.value().c_str(),
1438 (int)partition_size);
1439 // There are two important bits here specific to --use_persistent_digest:
1440 // Minimum libavb version = 1.1
1441 // Hashtree descriptor -> Root Digest = (empty)
1442 ASSERT_EQ(
1443 "Footer version: 1.0\n"
1444 "Image size: 10485760 bytes\n"
1445 "Original image size: 5242880 bytes\n"
1446 "VBMeta offset: 5337088\n"
1447 "VBMeta size: 1344 bytes\n"
1448 "--\n"
1449 "Minimum libavb version: 1.1\n"
1450 "Header Block: 256 bytes\n"
1451 "Authentication Block: 320 bytes\n"
1452 "Auxiliary Block: 768 bytes\n"
1453 "Algorithm: SHA256_RSA2048\n"
1454 "Rollback Index: 0\n"
1455 "Flags: 0\n"
1456 "Release String: ''\n"
1457 "Descriptors:\n"
1458 " Hashtree descriptor:\n"
1459 " Version of dm-verity: 1\n"
1460 " Image Size: 5242880 bytes\n"
1461 " Tree Offset: 5242880\n"
1462 " Tree Size: 45056 bytes\n"
1463 " Data Block Size: 4096 bytes\n"
1464 " Hash Block Size: 4096 bytes\n"
1465 " FEC num roots: 2\n"
1466 " FEC offset: 5287936\n"
1467 " FEC size: 49152 bytes\n"
1468 " Hash Algorithm: sha256\n"
1469 " Partition Name: foobar\n"
1470 " Salt: d00df00d\n"
1471 " Root Digest: \n"
1472 " Flags: 0\n",
1473 InfoImage(path));
1474 }
1475
TEST_F(AvbToolTest,AddHashtreeFooterWithNoAB)1476 TEST_F(AvbToolTest, AddHashtreeFooterWithNoAB) {
1477 size_t partition_size = 10 * 1024 * 1024;
1478 base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1479 EXPECT_COMMAND(0,
1480 "./avbtool add_hashtree_footer --salt d00df00d "
1481 "--hash_algorithm sha256 --image %s "
1482 "--partition_size %d --partition_name foobar "
1483 "--algorithm SHA256_RSA2048 "
1484 "--key test/data/testkey_rsa2048.pem "
1485 "--internal_release_string \"\" "
1486 "--do_not_use_ab",
1487 path.value().c_str(),
1488 (int)partition_size);
1489 // There are two important bits here we're expecting with --do_not_use_ab:
1490 // Minimum libavb version = 1.1
1491 // Hashtree descriptor -> Flags = 1
1492 ASSERT_EQ(
1493 "Footer version: 1.0\n"
1494 "Image size: 10485760 bytes\n"
1495 "Original image size: 5242880 bytes\n"
1496 "VBMeta offset: 5337088\n"
1497 "VBMeta size: 1344 bytes\n"
1498 "--\n"
1499 "Minimum libavb version: 1.1\n"
1500 "Header Block: 256 bytes\n"
1501 "Authentication Block: 320 bytes\n"
1502 "Auxiliary Block: 768 bytes\n"
1503 "Algorithm: SHA256_RSA2048\n"
1504 "Rollback Index: 0\n"
1505 "Flags: 0\n"
1506 "Release String: ''\n"
1507 "Descriptors:\n"
1508 " Hashtree descriptor:\n"
1509 " Version of dm-verity: 1\n"
1510 " Image Size: 5242880 bytes\n"
1511 " Tree Offset: 5242880\n"
1512 " Tree Size: 45056 bytes\n"
1513 " Data Block Size: 4096 bytes\n"
1514 " Hash Block Size: 4096 bytes\n"
1515 " FEC num roots: 2\n"
1516 " FEC offset: 5287936\n"
1517 " FEC size: 49152 bytes\n"
1518 " Hash Algorithm: sha256\n"
1519 " Partition Name: foobar\n"
1520 " Salt: d00df00d\n"
1521 " Root Digest: "
1522 "d0e31526f5a3f8e3f59acf726bd31ae7861ee78f9baa9195356bf479c6f9119d\n"
1523 " Flags: 1\n",
1524 InfoImage(path));
1525 }
1526
TEST_F(AvbToolTest,AddHashtreeFooterWithPersistentDigestAndNoAB)1527 TEST_F(AvbToolTest, AddHashtreeFooterWithPersistentDigestAndNoAB) {
1528 size_t partition_size = 10 * 1024 * 1024;
1529 base::FilePath path = GenerateImage("digest_location", partition_size / 2);
1530 EXPECT_COMMAND(0,
1531 "./avbtool add_hashtree_footer --salt d00df00d "
1532 "--hash_algorithm sha256 --image %s "
1533 "--partition_size %d --partition_name foobar "
1534 "--algorithm SHA256_RSA2048 "
1535 "--key test/data/testkey_rsa2048.pem "
1536 "--internal_release_string \"\" "
1537 "--use_persistent_digest --do_not_use_ab",
1538 path.value().c_str(),
1539 (int)partition_size);
1540 // There are three important bits specific to these flags:
1541 // Minimum libavb version = 1.1
1542 // Hashtree descriptor -> Root Digest = (empty)
1543 // Hashtree descriptor -> Flags = 1
1544 ASSERT_EQ(
1545 "Footer version: 1.0\n"
1546 "Image size: 10485760 bytes\n"
1547 "Original image size: 5242880 bytes\n"
1548 "VBMeta offset: 5337088\n"
1549 "VBMeta size: 1344 bytes\n"
1550 "--\n"
1551 "Minimum libavb version: 1.1\n"
1552 "Header Block: 256 bytes\n"
1553 "Authentication Block: 320 bytes\n"
1554 "Auxiliary Block: 768 bytes\n"
1555 "Algorithm: SHA256_RSA2048\n"
1556 "Rollback Index: 0\n"
1557 "Flags: 0\n"
1558 "Release String: ''\n"
1559 "Descriptors:\n"
1560 " Hashtree descriptor:\n"
1561 " Version of dm-verity: 1\n"
1562 " Image Size: 5242880 bytes\n"
1563 " Tree Offset: 5242880\n"
1564 " Tree Size: 45056 bytes\n"
1565 " Data Block Size: 4096 bytes\n"
1566 " Hash Block Size: 4096 bytes\n"
1567 " FEC num roots: 2\n"
1568 " FEC offset: 5287936\n"
1569 " FEC size: 49152 bytes\n"
1570 " Hash Algorithm: sha256\n"
1571 " Partition Name: foobar\n"
1572 " Salt: d00df00d\n"
1573 " Root Digest: \n"
1574 " Flags: 1\n",
1575 InfoImage(path));
1576 }
1577
TEST_F(AvbToolTest,KernelCmdlineDescriptor)1578 TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
1579 base::FilePath vbmeta_path =
1580 testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
1581
1582 EXPECT_COMMAND(0,
1583 "./avbtool make_vbmeta_image "
1584 "--output %s "
1585 "--kernel_cmdline 'foo bar baz' "
1586 "--kernel_cmdline 'second cmdline' "
1587 "--algorithm SHA256_RSA2048 "
1588 "--key test/data/testkey_rsa2048.pem "
1589 "--internal_release_string \"\"",
1590 vbmeta_path.value().c_str());
1591
1592 ASSERT_EQ(
1593 "Minimum libavb version: 1.0\n"
1594 "Header Block: 256 bytes\n"
1595 "Authentication Block: 320 bytes\n"
1596 "Auxiliary Block: 640 bytes\n"
1597 "Algorithm: SHA256_RSA2048\n"
1598 "Rollback Index: 0\n"
1599 "Flags: 0\n"
1600 "Release String: ''\n"
1601 "Descriptors:\n"
1602 " Kernel Cmdline descriptor:\n"
1603 " Flags: 0\n"
1604 " Kernel Cmdline: 'foo bar baz'\n"
1605 " Kernel Cmdline descriptor:\n"
1606 " Flags: 0\n"
1607 " Kernel Cmdline: 'second cmdline'\n",
1608 InfoImage(vbmeta_path));
1609
1610 // Now check the VBMeta image.
1611 std::string image_data;
1612 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1613
1614 const uint8_t* vbmeta_data =
1615 reinterpret_cast<const uint8_t*>(image_data.data());
1616 const size_t vbmeta_size = image_data.length();
1617 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1618 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1619
1620 // Collect all descriptors.
1621 std::vector<const AvbDescriptor*> descriptors;
1622 avb_descriptor_foreach(
1623 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1624
1625 // We should have two descriptors - check them.
1626 EXPECT_EQ(2UL, descriptors.size());
1627 AvbKernelCmdlineDescriptor d;
1628 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1629 avb_be64toh(descriptors[0]->tag));
1630 EXPECT_NE(
1631 0,
1632 avb_kernel_cmdline_descriptor_validate_and_byteswap(
1633 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]),
1634 &d));
1635 EXPECT_EQ("foo bar baz",
1636 std::string(reinterpret_cast<const char*>(descriptors[0]) +
1637 sizeof(AvbKernelCmdlineDescriptor),
1638 d.kernel_cmdline_length));
1639 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
1640 avb_be64toh(descriptors[1]->tag));
1641 EXPECT_NE(
1642 0,
1643 avb_kernel_cmdline_descriptor_validate_and_byteswap(
1644 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]),
1645 &d));
1646 EXPECT_EQ("second cmdline",
1647 std::string(reinterpret_cast<const char*>(descriptors[1]) +
1648 sizeof(AvbKernelCmdlineDescriptor),
1649 d.kernel_cmdline_length));
1650 }
1651
TEST_F(AvbToolTest,AddHashFooterSmallImageWithExternalVbmeta)1652 TEST_F(AvbToolTest, AddHashFooterSmallImageWithExternalVbmeta) {
1653 const size_t image_size = 37;
1654 const size_t partition_size = 20 * 4096;
1655
1656 std::vector<uint8_t> image(image_size, 0);
1657 for (size_t n = 0; n < image_size; n++) {
1658 image[n] = uint8_t(n);
1659 }
1660
1661 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
1662 base::FilePath image_path = testdir_.Append("kernel.bin");
1663 EXPECT_EQ(image_size,
1664 static_cast<const size_t>(
1665 base::WriteFile(image_path,
1666 reinterpret_cast<const char*>(image.data()),
1667 image.size())));
1668 EXPECT_COMMAND(0,
1669 "./avbtool add_hash_footer --salt d00df00d "
1670 "--hash_algorithm sha256 --image %s "
1671 "--partition_size %zu --partition_name kernel "
1672 "--algorithm SHA256_RSA2048 "
1673 "--key test/data/testkey_rsa2048.pem "
1674 "--output_vbmeta %s "
1675 "--do_not_append_vbmeta_image "
1676 "--internal_release_string \"\"",
1677 image_path.value().c_str(),
1678 partition_size,
1679 ext_vbmeta_path.value().c_str());
1680
1681 // It is not this unit test's job to check the vbmeta content.
1682
1683 int64_t file_size;
1684 ASSERT_TRUE(base::GetFileSize(image_path, &file_size));
1685 EXPECT_EQ(static_cast<size_t>(file_size), image_size);
1686 }
1687
TEST_F(AvbToolTest,IncludeDescriptor)1688 TEST_F(AvbToolTest, IncludeDescriptor) {
1689 base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin");
1690 base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin");
1691 base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
1692
1693 EXPECT_COMMAND(0,
1694 "./avbtool make_vbmeta_image "
1695 "--output %s "
1696 "--kernel_cmdline 'something' "
1697 "--prop name:value "
1698 "--internal_release_string \"\"",
1699 vbmeta1_path.value().c_str());
1700
1701 EXPECT_COMMAND(0,
1702 "./avbtool make_vbmeta_image "
1703 "--output %s "
1704 "--prop name2:value2 "
1705 "--prop name3:value3 "
1706 "--internal_release_string \"\"",
1707 vbmeta2_path.value().c_str());
1708
1709 EXPECT_COMMAND(0,
1710 "./avbtool make_vbmeta_image "
1711 "--output %s "
1712 "--prop name4:value4 "
1713 "--include_descriptors_from_image %s "
1714 "--include_descriptors_from_image %s "
1715 "--internal_release_string \"\"",
1716 vbmeta3_path.value().c_str(),
1717 vbmeta1_path.value().c_str(),
1718 vbmeta2_path.value().c_str());
1719
1720 ASSERT_EQ(
1721 "Minimum libavb version: 1.0\n"
1722 "Header Block: 256 bytes\n"
1723 "Authentication Block: 0 bytes\n"
1724 "Auxiliary Block: 256 bytes\n"
1725 "Algorithm: NONE\n"
1726 "Rollback Index: 0\n"
1727 "Flags: 0\n"
1728 "Release String: ''\n"
1729 "Descriptors:\n"
1730 " Prop: name4 -> 'value4'\n"
1731 " Prop: name -> 'value'\n"
1732 " Kernel Cmdline descriptor:\n"
1733 " Flags: 0\n"
1734 " Kernel Cmdline: 'something'\n"
1735 " Prop: name2 -> 'value2'\n"
1736 " Prop: name3 -> 'value3'\n",
1737 InfoImage(vbmeta3_path));
1738 }
1739
TEST_F(AvbToolTest,ChainedPartition)1740 TEST_F(AvbToolTest, ChainedPartition) {
1741 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1742
1743 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1744
1745 EXPECT_COMMAND(
1746 0,
1747 "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1748 " --output %s",
1749 pk_path.value().c_str());
1750
1751 EXPECT_COMMAND(
1752 0,
1753 "./avbtool make_vbmeta_image "
1754 "--output %s "
1755 "--chain_partition system:1:%s "
1756 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1757 "--internal_release_string \"\"",
1758 vbmeta_path.value().c_str(),
1759 pk_path.value().c_str());
1760
1761 ASSERT_EQ(
1762 "Minimum libavb version: 1.0\n"
1763 "Header Block: 256 bytes\n"
1764 "Authentication Block: 320 bytes\n"
1765 "Auxiliary Block: 1152 bytes\n"
1766 "Algorithm: SHA256_RSA2048\n"
1767 "Rollback Index: 0\n"
1768 "Flags: 0\n"
1769 "Release String: ''\n"
1770 "Descriptors:\n"
1771 " Chain Partition descriptor:\n"
1772 " Partition Name: system\n"
1773 " Rollback Index Location: 1\n"
1774 " Public key (sha1): "
1775 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n",
1776 InfoImage(vbmeta_path));
1777
1778 // Now check the VBMeta image.
1779 std::string image_data;
1780 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
1781
1782 const uint8_t* vbmeta_data =
1783 reinterpret_cast<const uint8_t*>(image_data.data());
1784 const size_t vbmeta_size = image_data.length();
1785 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
1786 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
1787
1788 // Collect all descriptors.
1789 std::vector<const AvbDescriptor*> descriptors;
1790 avb_descriptor_foreach(
1791 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
1792
1793 // We should have one descriptor - check it.
1794 EXPECT_EQ(1UL, descriptors.size());
1795
1796 std::string pk_data;
1797 ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data));
1798
1799 AvbChainPartitionDescriptor d;
1800 EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
1801 avb_be64toh(descriptors[0]->tag));
1802 EXPECT_NE(
1803 0,
1804 avb_chain_partition_descriptor_validate_and_byteswap(
1805 reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]),
1806 &d));
1807 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
1808 sizeof(AvbChainPartitionDescriptor);
1809 uint64_t o = 0;
1810 EXPECT_EQ("system",
1811 std::string(reinterpret_cast<const char*>(desc_end + o),
1812 d.partition_name_len));
1813 o += d.partition_name_len;
1814 EXPECT_EQ(pk_data,
1815 std::string(reinterpret_cast<const char*>(descriptors[0]) +
1816 sizeof(AvbChainPartitionDescriptor) + o,
1817 d.public_key_len));
1818 }
1819
TEST_F(AvbToolTest,ChainedPartitionNoLocationCollision)1820 TEST_F(AvbToolTest, ChainedPartitionNoLocationCollision) {
1821 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
1822
1823 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
1824
1825 EXPECT_COMMAND(
1826 0,
1827 "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
1828 " --output %s",
1829 pk_path.value().c_str());
1830
1831 // Check that avbtool bails if the same Rollback Index Location is
1832 // used for multiple chained partitions.
1833 EXPECT_COMMAND(
1834 1,
1835 "./avbtool make_vbmeta_image "
1836 "--output %s "
1837 "--chain_partition system:1:%s "
1838 "--chain_partition other:1:%s "
1839 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1840 "--internal_release_string \"\"",
1841 vbmeta_path.value().c_str(),
1842 pk_path.value().c_str(),
1843 pk_path.value().c_str());
1844 }
1845
TEST_F(AvbToolTest,AppendVBMetaImage)1846 TEST_F(AvbToolTest, AppendVBMetaImage) {
1847 size_t boot_size = 5 * 1024 * 1024;
1848 size_t boot_partition_size = 32 * 1024 * 1024;
1849 base::FilePath boot_path = GenerateImage("boot", boot_size);
1850
1851 GenerateVBMetaImage("vbmeta.img",
1852 "SHA256_RSA2048",
1853 0,
1854 base::FilePath("test/data/testkey_rsa2048.pem"),
1855 std::string("--append_to_release_string \"\" "
1856 "--kernel_cmdline foo"));
1857
1858 EXPECT_COMMAND(0,
1859 "./avbtool append_vbmeta_image "
1860 "--image %s "
1861 "--partition_size %d "
1862 "--vbmeta_image %s ",
1863 boot_path.value().c_str(),
1864 (int)boot_partition_size,
1865 vbmeta_image_path_.value().c_str());
1866
1867 std::string vbmeta_contents = InfoImage(vbmeta_image_path_);
1868 std::string boot_contents = InfoImage(boot_path);
1869
1870 // Check that boot.img has the same vbmeta blob as from vbmeta.img -
1871 // we do this by inspecting 'avbtool info_image' output combined
1872 // with the known footer location given boot.img has 5 MiB known
1873 // content and the partition size is 32 MiB.
1874 ASSERT_EQ(
1875 "Minimum libavb version: 1.0\n"
1876 "Header Block: 256 bytes\n"
1877 "Authentication Block: 320 bytes\n"
1878 "Auxiliary Block: 576 bytes\n"
1879 "Algorithm: SHA256_RSA2048\n"
1880 "Rollback Index: 0\n"
1881 "Flags: 0\n"
1882 "Release String: 'avbtool 1.1.0 '\n"
1883 "Descriptors:\n"
1884 " Kernel Cmdline descriptor:\n"
1885 " Flags: 0\n"
1886 " Kernel Cmdline: 'foo'\n",
1887 vbmeta_contents);
1888 std::string known_footer =
1889 "Footer version: 1.0\n"
1890 "Image size: 33554432 bytes\n"
1891 "Original image size: 5242880 bytes\n"
1892 "VBMeta offset: 5242880\n"
1893 "VBMeta size: 1152 bytes\n"
1894 "--\n";
1895 ASSERT_EQ(known_footer + vbmeta_contents, boot_contents);
1896
1897 // Also verify that the blobs are the same, bit for bit.
1898 base::File f =
1899 base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
1900 std::vector<uint8_t> loaded_vbmeta;
1901 loaded_vbmeta.resize(1152);
1902 EXPECT_EQ(
1903 f.Read(
1904 5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152),
1905 1152);
1906 EXPECT_EQ(vbmeta_image_, loaded_vbmeta);
1907 }
1908
TEST_F(AvbToolTest,SigningHelperBasic)1909 TEST_F(AvbToolTest, SigningHelperBasic) {
1910 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1911 base::FilePath signing_helper_test_path =
1912 testdir_.Append("signing_helper_test");
1913 EXPECT_COMMAND(
1914 0,
1915 "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1916 "--output %s "
1917 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1918 "--signing_helper test/avbtool_signing_helper_test.py "
1919 "--internal_release_string \"\"",
1920 signing_helper_test_path.value().c_str(),
1921 vbmeta_path.value().c_str());
1922
1923 // Now check the value in test file.
1924 std::string value;
1925 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1926 EXPECT_EQ("DONE", value);
1927 }
1928
TEST_F(AvbToolTest,SigningHelperWithFilesBasic)1929 TEST_F(AvbToolTest, SigningHelperWithFilesBasic) {
1930 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1931 base::FilePath signing_helper_test_path =
1932 testdir_.Append("signing_helper_test");
1933 EXPECT_COMMAND(
1934 0,
1935 "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
1936 "--output %s "
1937 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1938 "--signing_helper_with_files "
1939 "test/avbtool_signing_helper_with_files_test.py "
1940 "--internal_release_string \"\"",
1941 signing_helper_test_path.value().c_str(),
1942 vbmeta_path.value().c_str());
1943
1944 // Now check the value in test file.
1945 std::string value;
1946 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
1947 EXPECT_EQ("DONE", value);
1948 }
1949
TEST_F(AvbToolTest,SigningHelperReturnError)1950 TEST_F(AvbToolTest, SigningHelperReturnError) {
1951 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1952 EXPECT_COMMAND(
1953 1,
1954 "./avbtool make_vbmeta_image "
1955 "--output %s "
1956 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1957 "--signing_helper test/avbtool_signing_helper_test.py "
1958 "--internal_release_string \"\"",
1959 vbmeta_path.value().c_str());
1960 }
1961
TEST_F(AvbToolTest,SigningHelperWithFilesReturnError)1962 TEST_F(AvbToolTest, SigningHelperWithFilesReturnError) {
1963 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
1964 EXPECT_COMMAND(
1965 1,
1966 "./avbtool make_vbmeta_image "
1967 "--output %s "
1968 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
1969 "--signing_helper_with_files "
1970 "test/avbtool_signing_helper_with_files_test.py "
1971 "--internal_release_string \"\"",
1972 vbmeta_path.value().c_str());
1973 }
1974
TEST_F(AvbToolTest,VerifyImageNoSignature)1975 TEST_F(AvbToolTest, VerifyImageNoSignature) {
1976 GenerateVBMetaImage("vbmeta.img",
1977 "", // NONE
1978 0,
1979 base::FilePath());
1980
1981 EXPECT_COMMAND(0,
1982 "./avbtool verify_image "
1983 "--image %s ",
1984 vbmeta_image_path_.value().c_str());
1985 }
1986
TEST_F(AvbToolTest,VerifyImageValidSignature)1987 TEST_F(AvbToolTest, VerifyImageValidSignature) {
1988 GenerateVBMetaImage("vbmeta.img",
1989 "SHA256_RSA2048",
1990 0,
1991 base::FilePath("test/data/testkey_rsa2048.pem"));
1992
1993 EXPECT_COMMAND(0,
1994 "./avbtool verify_image "
1995 "--image %s ",
1996 vbmeta_image_path_.value().c_str());
1997 }
1998
TEST_F(AvbToolTest,VerifyImageCorruptedVBMeta)1999 TEST_F(AvbToolTest, VerifyImageCorruptedVBMeta) {
2000 GenerateVBMetaImage("vbmeta.img",
2001 "SHA256_RSA2048",
2002 0,
2003 base::FilePath("test/data/testkey_rsa2048.pem"));
2004
2005 // Corrupt four bytes of data in the end of the image. Since the aux
2006 // data is at the end and this data is signed, this will change the
2007 // value of the computed hash.
2008 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2009 EXPECT_EQ(AVB_IO_RESULT_OK,
2010 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2011 "vbmeta",
2012 -4, // offset from end
2013 sizeof corrupt_data,
2014 corrupt_data));
2015
2016 EXPECT_COMMAND(1,
2017 "./avbtool verify_image "
2018 "--image %s ",
2019 vbmeta_image_path_.value().c_str());
2020 }
2021
TEST_F(AvbToolTest,VerifyImageOtherKeyMatching)2022 TEST_F(AvbToolTest, VerifyImageOtherKeyMatching) {
2023 GenerateVBMetaImage("vbmeta.img",
2024 "SHA256_RSA2048",
2025 0,
2026 base::FilePath("test/data/testkey_rsa2048.pem"));
2027
2028 EXPECT_COMMAND(0,
2029 "./avbtool verify_image "
2030 "--image %s --key test/data/testkey_rsa2048.pem",
2031 vbmeta_image_path_.value().c_str());
2032 }
2033
TEST_F(AvbToolTest,VerifyImageOtherKeyNotMatching)2034 TEST_F(AvbToolTest, VerifyImageOtherKeyNotMatching) {
2035 GenerateVBMetaImage("vbmeta.img",
2036 "SHA256_RSA2048",
2037 0,
2038 base::FilePath("test/data/testkey_rsa2048.pem"));
2039
2040 EXPECT_COMMAND(1,
2041 "./avbtool verify_image "
2042 "--image %s --key test/data/testkey_rsa4096.pem",
2043 vbmeta_image_path_.value().c_str());
2044 }
2045
TEST_F(AvbToolTest,VerifyImageBrokenSignature)2046 TEST_F(AvbToolTest, VerifyImageBrokenSignature) {
2047 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2048 base::FilePath signing_helper_test_path =
2049 testdir_.Append("signing_helper_test");
2050
2051 // Intentionally make the signer generate a wrong signature.
2052 EXPECT_COMMAND(
2053 0,
2054 "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool make_vbmeta_image "
2055 "--output %s "
2056 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2057 "--signing_helper test/avbtool_signing_helper_test.py "
2058 "--internal_release_string \"\"",
2059 vbmeta_path.value().c_str());
2060
2061 EXPECT_COMMAND(1,
2062 "./avbtool verify_image "
2063 "--image %s ",
2064 vbmeta_path.value().c_str());
2065 }
2066
2067 // Helper to generate boot.img, unsparse system.img, and vbmeta.img.
GenerateImageWithHashAndHashtreeSetup()2068 void AvbToolTest::GenerateImageWithHashAndHashtreeSetup() {
2069 const size_t boot_partition_size = 16 * 1024 * 1024;
2070 const size_t boot_image_size = 5 * 1024 * 1024;
2071 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
2072 EXPECT_COMMAND(0,
2073 "./avbtool add_hash_footer"
2074 " --image %s"
2075 " --rollback_index 0"
2076 " --partition_name boot"
2077 " --partition_size %zd"
2078 " --salt deadbeef"
2079 " --internal_release_string \"\"",
2080 boot_path.value().c_str(),
2081 boot_partition_size);
2082
2083 const size_t system_partition_size = 10 * 1024 * 1024;
2084 const size_t system_image_size = 8 * 1024 * 1024;
2085 base::FilePath system_path = GenerateImage("system.img", system_image_size);
2086 EXPECT_COMMAND(0,
2087 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
2088 "--partition_size %zd --partition_name system "
2089 "--internal_release_string \"\" ",
2090 system_path.value().c_str(),
2091 system_partition_size);
2092
2093 GenerateVBMetaImage("vbmeta.img",
2094 "SHA256_RSA2048",
2095 0,
2096 base::FilePath("test/data/testkey_rsa2048.pem"),
2097 base::StringPrintf("--include_descriptors_from_image %s "
2098 "--include_descriptors_from_image %s",
2099 boot_path.value().c_str(),
2100 system_path.value().c_str()));
2101 }
2102
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtree)2103 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) {
2104 GenerateImageWithHashAndHashtreeSetup();
2105
2106 // Do two checks - one for system.img not sparse, and one where it
2107 // is sparse.
2108 for (int n = 0; n < 2; n++) {
2109 EXPECT_COMMAND(0,
2110 "./avbtool verify_image "
2111 "--image %s ",
2112 vbmeta_image_path_.value().c_str());
2113 if (n == 0) {
2114 EXPECT_COMMAND(0,
2115 "img2simg %s %s.sparse",
2116 testdir_.Append("system.img").value().c_str(),
2117 testdir_.Append("system.img").value().c_str());
2118 EXPECT_COMMAND(0,
2119 "mv %s.sparse %s",
2120 testdir_.Append("system.img").value().c_str(),
2121 testdir_.Append("system.img").value().c_str());
2122 }
2123 }
2124 }
2125
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHash)2126 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) {
2127 GenerateImageWithHashAndHashtreeSetup();
2128
2129 // Corrupt four bytes of data in the middle of boot.img.
2130 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2131 EXPECT_EQ(AVB_IO_RESULT_OK,
2132 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2133 "boot",
2134 105 * 1024, // offset from start
2135 sizeof corrupt_data,
2136 corrupt_data));
2137
2138 EXPECT_COMMAND(1,
2139 "./avbtool verify_image "
2140 "--image %s ",
2141 vbmeta_image_path_.value().c_str());
2142 }
2143
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHashtree)2144 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHashtree) {
2145 GenerateImageWithHashAndHashtreeSetup();
2146
2147 // Corrupt four bytes of data in the middle of system.img.
2148 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2149 EXPECT_EQ(AVB_IO_RESULT_OK,
2150 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2151 "system",
2152 123 * 1024, // offset from start
2153 sizeof corrupt_data,
2154 corrupt_data));
2155
2156 // Do two checks - one for system.img not sparse, and one where it
2157 // is sparse.
2158 for (int n = 0; n < 2; n++) {
2159 EXPECT_COMMAND(1,
2160 "./avbtool verify_image "
2161 "--image %s ",
2162 vbmeta_image_path_.value().c_str());
2163 if (n == 0) {
2164 EXPECT_COMMAND(0,
2165 "img2simg %s %s.sparse",
2166 testdir_.Append("system.img").value().c_str(),
2167 testdir_.Append("system.img").value().c_str());
2168 EXPECT_COMMAND(0,
2169 "mv %s.sparse %s",
2170 testdir_.Append("system.img").value().c_str(),
2171 testdir_.Append("system.img").value().c_str());
2172 }
2173 }
2174 }
2175
TEST_F(AvbToolTest,VerifyImageChainPartition)2176 TEST_F(AvbToolTest, VerifyImageChainPartition) {
2177 base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
2178 EXPECT_COMMAND(
2179 0,
2180 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
2181 " --output %s",
2182 pk4096_path.value().c_str());
2183
2184 base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey");
2185 EXPECT_COMMAND(
2186 0,
2187 "./avbtool extract_public_key --key test/data/testkey_rsa8192.pem"
2188 " --output %s",
2189 pk8192_path.value().c_str());
2190
2191 GenerateVBMetaImage("vbmeta.img",
2192 "SHA256_RSA2048",
2193 0,
2194 base::FilePath("test/data/testkey_rsa2048.pem"),
2195 base::StringPrintf("--chain_partition system:1:%s ",
2196 pk4096_path.value().c_str()));
2197
2198 // Should not fail (name, rollback_index, contents all correct).
2199 EXPECT_COMMAND(0,
2200 "./avbtool verify_image "
2201 "--image %s "
2202 "--expected_chain_partition system:1:%s",
2203 vbmeta_image_path_.value().c_str(),
2204 pk4096_path.value().c_str());
2205
2206 // Should fail because we didn't use --expected_chain_partition.
2207 EXPECT_COMMAND(1,
2208 "./avbtool verify_image "
2209 "--image %s ",
2210 vbmeta_image_path_.value().c_str());
2211
2212 // Should fail because partition name is wrong.
2213 EXPECT_COMMAND(1,
2214 "./avbtool verify_image "
2215 "--image %s "
2216 "--expected_chain_partition xyz:1:%s",
2217 vbmeta_image_path_.value().c_str(),
2218 pk4096_path.value().c_str());
2219
2220 // Should fail because rollback index location is wrong.
2221 EXPECT_COMMAND(1,
2222 "./avbtool verify_image "
2223 "--image %s "
2224 "--expected_chain_partition system:2:%s",
2225 vbmeta_image_path_.value().c_str(),
2226 pk4096_path.value().c_str());
2227
2228 // Should fail because public key blob is wrong.
2229 EXPECT_COMMAND(1,
2230 "./avbtool verify_image "
2231 "--image %s "
2232 "--expected_chain_partition system:1:%s",
2233 vbmeta_image_path_.value().c_str(),
2234 pk8192_path.value().c_str());
2235 }
2236
2237 class AvbToolTest_PrintRequiredVersion : public AvbToolTest {
2238 protected:
2239 const char* kOutputFile = "versions.txt";
2240
PrintWithAddHashFooter(int target_required_minor_version)2241 void PrintWithAddHashFooter(int target_required_minor_version) {
2242 std::string extra_args;
2243 if (target_required_minor_version == 1) {
2244 // The --do_not_use_ab option will require 1.1.
2245 extra_args = "--do_not_use_ab";
2246 }
2247 const size_t boot_partition_size = 16 * 1024 * 1024;
2248 base::FilePath output_path = testdir_.Append(kOutputFile);
2249 EXPECT_COMMAND(0,
2250 "./avbtool add_hash_footer"
2251 " --rollback_index 0"
2252 " --partition_name boot"
2253 " --partition_size %zd"
2254 " --salt deadbeef"
2255 " --internal_release_string \"\""
2256 " %s"
2257 " --print_required_libavb_version > %s",
2258 boot_partition_size,
2259 extra_args.c_str(),
2260 output_path.value().c_str());
2261 CheckVersion(target_required_minor_version);
2262 }
2263
PrintWithAddHashtreeFooter(int target_required_minor_version)2264 void PrintWithAddHashtreeFooter(int target_required_minor_version) {
2265 std::string extra_args;
2266 if (target_required_minor_version == 1) {
2267 // The --do_not_use_ab option will require 1.1.
2268 extra_args = "--do_not_use_ab";
2269 }
2270 const size_t system_partition_size = 10 * 1024 * 1024;
2271 base::FilePath output_path = testdir_.Append(kOutputFile);
2272 EXPECT_COMMAND(0,
2273 "./avbtool add_hashtree_footer --salt d00df00d "
2274 "--partition_size %zd --partition_name system "
2275 "--internal_release_string \"\""
2276 " %s"
2277 " --print_required_libavb_version > %s",
2278 system_partition_size,
2279 extra_args.c_str(),
2280 output_path.value().c_str());
2281 CheckVersion(target_required_minor_version);
2282 }
2283
PrintWithMakeVbmetaImage(int target_required_minor_version)2284 void PrintWithMakeVbmetaImage(int target_required_minor_version) {
2285 std::string extra_args;
2286 if (target_required_minor_version == 1) {
2287 // An included descriptor that requires 1.1 will require 1.1 for vbmeta.
2288 const size_t boot_partition_size = 16 * 1024 * 1024;
2289 base::FilePath image_path = GenerateImage("test_print_version", 1024);
2290 EXPECT_COMMAND(0,
2291 "./avbtool add_hash_footer --salt d00df00d "
2292 "--hash_algorithm sha256 --image %s "
2293 "--partition_size %d --partition_name foobar "
2294 "--algorithm SHA256_RSA2048 "
2295 "--key test/data/testkey_rsa2048.pem "
2296 "--internal_release_string \"\" "
2297 "--do_not_use_ab",
2298 image_path.value().c_str(),
2299 (int)boot_partition_size);
2300 extra_args = base::StringPrintf("--include_descriptors_from_image %s",
2301 image_path.value().c_str());
2302 }
2303 base::FilePath output_path = testdir_.Append(kOutputFile);
2304 EXPECT_COMMAND(0,
2305 "./avbtool make_vbmeta_image "
2306 "--algorithm SHA256_RSA2048 "
2307 "--key test/data/testkey_rsa2048.pem "
2308 "--internal_release_string \"\""
2309 " %s"
2310 " --print_required_libavb_version > %s",
2311 extra_args.c_str(),
2312 output_path.value().c_str());
2313 CheckVersion(target_required_minor_version);
2314 }
2315
CheckVersion(int expected_required_minor_version)2316 void CheckVersion(int expected_required_minor_version) {
2317 base::FilePath output_path = testdir_.Append(kOutputFile);
2318 std::string output;
2319 ASSERT_TRUE(base::ReadFileToString(output_path, &output));
2320 EXPECT_EQ(output,
2321 base::StringPrintf("1.%d\n", expected_required_minor_version));
2322 }
2323 };
2324
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_0)2325 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_0) {
2326 PrintWithAddHashFooter(0);
2327 }
2328
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_1)2329 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_1) {
2330 PrintWithAddHashFooter(1);
2331 }
2332
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_0)2333 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_0) {
2334 PrintWithAddHashtreeFooter(0);
2335 }
2336
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_1)2337 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_1) {
2338 PrintWithAddHashtreeFooter(1);
2339 }
2340
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_0)2341 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_0) {
2342 PrintWithMakeVbmetaImage(0);
2343 }
2344
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_1)2345 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_1) {
2346 PrintWithMakeVbmetaImage(1);
2347 }
2348
TEST_F(AvbToolTest,MakeAtxPikCertificate)2349 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
2350 base::FilePath subject_path = testdir_.Append("tmp_subject");
2351 ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
2352 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
2353 EXPECT_COMMAND(
2354 0,
2355 "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
2356 pubkey_path.value().c_str());
2357
2358 base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
2359 EXPECT_COMMAND(0,
2360 "./avbtool make_atx_certificate"
2361 " --subject %s"
2362 " --subject_key %s"
2363 " --subject_key_version 42"
2364 " --subject_is_intermediate_authority"
2365 " --authority_key test/data/testkey_atx_prk.pem"
2366 " --output %s",
2367 subject_path.value().c_str(),
2368 pubkey_path.value().c_str(),
2369 output_path.value().c_str());
2370
2371 EXPECT_COMMAND(0,
2372 "diff test/data/atx_pik_certificate.bin %s",
2373 output_path.value().c_str());
2374 }
2375
TEST_F(AvbToolTest,MakeAtxPskCertificate)2376 TEST_F(AvbToolTest, MakeAtxPskCertificate) {
2377 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
2378 EXPECT_COMMAND(
2379 0,
2380 "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
2381 pubkey_path.value().c_str());
2382
2383 base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
2384 EXPECT_COMMAND(0,
2385 "./avbtool make_atx_certificate"
2386 " --subject test/data/atx_product_id.bin"
2387 " --subject_key %s"
2388 " --subject_key_version 42"
2389 " --authority_key test/data/testkey_atx_pik.pem"
2390 " --output %s",
2391 pubkey_path.value().c_str(),
2392 output_path.value().c_str());
2393
2394 EXPECT_COMMAND(0,
2395 "diff test/data/atx_psk_certificate.bin %s",
2396 output_path.value().c_str());
2397 }
2398
TEST_F(AvbToolTest,MakeAtxPermanentAttributes)2399 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) {
2400 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
2401 EXPECT_COMMAND(
2402 0,
2403 "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
2404 pubkey_path.value().c_str());
2405
2406 base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
2407 EXPECT_COMMAND(0,
2408 "./avbtool make_atx_permanent_attributes"
2409 " --root_authority_key %s"
2410 " --product_id test/data/atx_product_id.bin"
2411 " --output %s",
2412 pubkey_path.value().c_str(),
2413 output_path.value().c_str());
2414
2415 EXPECT_COMMAND(0,
2416 "diff test/data/atx_permanent_attributes.bin %s",
2417 output_path.value().c_str());
2418 }
2419
TEST_F(AvbToolTest,MakeAtxMetadata)2420 TEST_F(AvbToolTest, MakeAtxMetadata) {
2421 base::FilePath output_path = testdir_.Append("tmp_metadata.bin");
2422
2423 EXPECT_COMMAND(
2424 0,
2425 "./avbtool make_atx_metadata"
2426 " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
2427 " --product_key_certificate test/data/atx_psk_certificate.bin"
2428 " --output %s",
2429 output_path.value().c_str());
2430
2431 EXPECT_COMMAND(
2432 0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str());
2433 }
2434
2435 } // namespace avb
2436