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