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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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.py 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,AddHashtreeFooterRoundImageSize)2009 TEST_F(AvbToolTest, AddHashtreeFooterRoundImageSize) {
2010 // Image size needs not to be a multiple of block size (4096 bytes) if
2011 // --partition_size is specified. avbtool will round the image size being
2012 // a multiple of block size, prior to add an AVB footer.
2013 size_t image_size = 70 * 1024;
2014 base::FilePath path = GenerateImage("data.bin", image_size);
2015
2016 size_t partition_size = 10 * 1024 * 1024;
2017 // Note that there is --partition_size here.
2018 EXPECT_COMMAND(0,
2019 "./avbtool.py add_hashtree_footer --salt d00df00d "
2020 "--image %s "
2021 "--algorithm SHA256_RSA2048 "
2022 "--key test/data/testkey_rsa2048.pem "
2023 "--partition_size %d --partition_name foobar "
2024 "--internal_release_string \"\" ",
2025 path.value().c_str(),
2026 (int)partition_size);
2027 }
2028
TEST_F(AvbToolTest,AddHashtreeFooterNoWrongPartitionSize)2029 TEST_F(AvbToolTest, AddHashtreeFooterNoWrongPartitionSize) {
2030 // Partition size must be a multiple of block size (4096 bytes) and this
2031 // one isn't...
2032 size_t partition_size = 10 * 1024 * 1024 + 1024;
2033
2034 // Image size doesn't matter in this case.
2035 size_t image_size = 70 * 1024;
2036 base::FilePath path = GenerateImage("data.bin", image_size);
2037
2038 // ... so we expect this command to fail.
2039 EXPECT_COMMAND(1,
2040 "./avbtool.py add_hashtree_footer --salt d00df00d "
2041 "--image %s "
2042 "--algorithm SHA256_RSA2048 "
2043 "--key test/data/testkey_rsa2048.pem "
2044 "--partition_size %d --partition_name foobar "
2045 "--internal_release_string \"\" ",
2046 path.value().c_str(),
2047 (int)partition_size);
2048 }
2049
TEST_F(AvbToolTest,AddHashtreeFooterWithCheckAtMostOnce)2050 TEST_F(AvbToolTest, AddHashtreeFooterWithCheckAtMostOnce) {
2051 size_t partition_size = 10 * 1024 * 1024;
2052 base::FilePath path = GenerateImage("digest_location", partition_size / 2);
2053 EXPECT_COMMAND(0,
2054 "./avbtool.py add_hashtree_footer --salt d00df00d "
2055 "--hash_algorithm sha256 --image %s "
2056 "--partition_size %d --partition_name foobar "
2057 "--algorithm SHA256_RSA2048 "
2058 "--key test/data/testkey_rsa2048.pem "
2059 "--internal_release_string \"\" "
2060 "--check_at_most_once",
2061 path.value().c_str(),
2062 (int)partition_size);
2063 // There are two important bits here we're expecting with --check_at_most_once:
2064 // Minimum libavb version = 1.1
2065 // Hashtree descriptor -> Flags = 2
2066 ASSERT_EQ(
2067 "Footer version: 1.0\n"
2068 "Image size: 10485760 bytes\n"
2069 "Original image size: 5242880 bytes\n"
2070 "VBMeta offset: 5337088\n"
2071 "VBMeta size: 1344 bytes\n"
2072 "--\n"
2073 "Minimum libavb version: 1.1\n"
2074 "Header Block: 256 bytes\n"
2075 "Authentication Block: 320 bytes\n"
2076 "Auxiliary Block: 768 bytes\n"
2077 "Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2078 "Algorithm: SHA256_RSA2048\n"
2079 "Rollback Index: 0\n"
2080 "Flags: 0\n"
2081 "Rollback Index Location: 0\n"
2082 "Release String: ''\n"
2083 "Descriptors:\n"
2084 " Hashtree descriptor:\n"
2085 " Version of dm-verity: 1\n"
2086 " Image Size: 5242880 bytes\n"
2087 " Tree Offset: 5242880\n"
2088 " Tree Size: 45056 bytes\n"
2089 " Data Block Size: 4096 bytes\n"
2090 " Hash Block Size: 4096 bytes\n"
2091 " FEC num roots: 2\n"
2092 " FEC offset: 5287936\n"
2093 " FEC size: 49152 bytes\n"
2094 " Hash Algorithm: sha256\n"
2095 " Partition Name: foobar\n"
2096 " Salt: d00df00d\n"
2097 " Root Digest: "
2098 "d0e31526f5a3f8e3f59acf726bd31ae7861ee78f9baa9195356bf479c6f9119d\n"
2099 " Flags: 2\n",
2100 InfoImage(path));
2101 }
2102
TEST_F(AvbToolTest,KernelCmdlineDescriptor)2103 TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
2104 base::FilePath vbmeta_path =
2105 testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
2106
2107 EXPECT_COMMAND(0,
2108 "./avbtool.py make_vbmeta_image "
2109 "--output %s "
2110 "--kernel_cmdline 'foo bar baz' "
2111 "--kernel_cmdline 'second cmdline' "
2112 "--algorithm SHA256_RSA2048 "
2113 "--key test/data/testkey_rsa2048.pem "
2114 "--internal_release_string \"\"",
2115 vbmeta_path.value().c_str());
2116
2117 ASSERT_EQ(
2118 "Minimum libavb version: 1.0\n"
2119 "Header Block: 256 bytes\n"
2120 "Authentication Block: 320 bytes\n"
2121 "Auxiliary Block: 640 bytes\n"
2122 "Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2123 "Algorithm: SHA256_RSA2048\n"
2124 "Rollback Index: 0\n"
2125 "Flags: 0\n"
2126 "Rollback Index Location: 0\n"
2127 "Release String: ''\n"
2128 "Descriptors:\n"
2129 " Kernel Cmdline descriptor:\n"
2130 " Flags: 0\n"
2131 " Kernel Cmdline: 'foo bar baz'\n"
2132 " Kernel Cmdline descriptor:\n"
2133 " Flags: 0\n"
2134 " Kernel Cmdline: 'second cmdline'\n",
2135 InfoImage(vbmeta_path));
2136
2137 // Now check the VBMeta image.
2138 std::string image_data;
2139 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
2140
2141 const uint8_t* vbmeta_data =
2142 reinterpret_cast<const uint8_t*>(image_data.data());
2143 const size_t vbmeta_size = image_data.length();
2144 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
2145 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
2146
2147 // Collect all descriptors.
2148 std::vector<const AvbDescriptor*> descriptors;
2149 avb_descriptor_foreach(
2150 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
2151
2152 // We should have two descriptors - check them.
2153 EXPECT_EQ(2UL, descriptors.size());
2154 AvbKernelCmdlineDescriptor d;
2155 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
2156 avb_be64toh(descriptors[0]->tag));
2157 EXPECT_NE(
2158 0,
2159 avb_kernel_cmdline_descriptor_validate_and_byteswap(
2160 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]),
2161 &d));
2162 EXPECT_EQ("foo bar baz",
2163 std::string(reinterpret_cast<const char*>(descriptors[0]) +
2164 sizeof(AvbKernelCmdlineDescriptor),
2165 d.kernel_cmdline_length));
2166 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
2167 avb_be64toh(descriptors[1]->tag));
2168 EXPECT_NE(
2169 0,
2170 avb_kernel_cmdline_descriptor_validate_and_byteswap(
2171 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]),
2172 &d));
2173 EXPECT_EQ("second cmdline",
2174 std::string(reinterpret_cast<const char*>(descriptors[1]) +
2175 sizeof(AvbKernelCmdlineDescriptor),
2176 d.kernel_cmdline_length));
2177 }
2178
TEST_F(AvbToolTest,CalculateKernelCmdline)2179 TEST_F(AvbToolTest, CalculateKernelCmdline) {
2180 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2181 EXPECT_COMMAND(0,
2182 "./avbtool.py make_vbmeta_image "
2183 "--output %s "
2184 "--kernel_cmdline 'foo bar baz' "
2185 "--kernel_cmdline 'second cmdline' "
2186 "--algorithm SHA256_RSA2048 "
2187 "--key test/data/testkey_rsa2048.pem "
2188 "--internal_release_string \"\"",
2189 vbmeta_path.value().c_str());
2190
2191 base::FilePath out_path = testdir_.Append("out.txt");
2192 std::string out;
2193 EXPECT_COMMAND(0,
2194 "./avbtool.py calculate_kernel_cmdline --image %s > %s",
2195 vbmeta_path.value().c_str(),
2196 out_path.value().c_str());
2197 ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2198 EXPECT_EQ(out, "foo bar baz second cmdline");
2199 }
2200
TEST_F(AvbToolTest,CalculateKernelCmdlineChainedAndWithFlags)2201 TEST_F(AvbToolTest, CalculateKernelCmdlineChainedAndWithFlags) {
2202 const size_t rootfs_size = 1028 * 1024;
2203 const size_t partition_size = 1536 * 1024;
2204
2205 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2206
2207 // Generate a 1028 KiB file with known content, add a hashtree, and cmdline
2208 // descriptors for setting up this hashtree. Notably this will create *two*
2209 // cmdline descriptors so we can test calculate_kernel_cmdline's
2210 // --hashtree_disabled option.
2211 std::vector<uint8_t> rootfs;
2212 rootfs.resize(rootfs_size);
2213 for (size_t n = 0; n < rootfs_size; n++)
2214 rootfs[n] = uint8_t(n);
2215 base::FilePath rootfs_path = testdir_.Append("rootfs.bin");
2216 EXPECT_EQ(rootfs_size,
2217 static_cast<const size_t>(
2218 base::WriteFile(rootfs_path,
2219 reinterpret_cast<const char*>(rootfs.data()),
2220 rootfs.size())));
2221
2222 EXPECT_COMMAND(
2223 0,
2224 "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
2225 " --output %s",
2226 pk_path.value().c_str());
2227
2228 EXPECT_COMMAND(0,
2229 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
2230 "--partition_size %d --partition_name rootfs "
2231 "--algorithm SHA256_RSA2048 "
2232 "--key test/data/testkey_rsa2048.pem "
2233 "--internal_release_string \"\" "
2234 "--setup_as_rootfs_from_kernel",
2235 rootfs_path.value().c_str(),
2236 (int)partition_size);
2237 EXPECT_EQ(
2238 "Footer version: 1.0\n"
2239 "Image size: 1572864 bytes\n"
2240 "Original image size: 1052672 bytes\n"
2241 "VBMeta offset: 1085440\n"
2242 "VBMeta size: 1792 bytes\n"
2243 "--\n"
2244 "Minimum libavb version: 1.0\n"
2245 "Header Block: 256 bytes\n"
2246 "Authentication Block: 320 bytes\n"
2247 "Auxiliary Block: 1216 bytes\n"
2248 "Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2249 "Algorithm: SHA256_RSA2048\n"
2250 "Rollback Index: 0\n"
2251 "Flags: 0\n"
2252 "Rollback Index Location: 0\n"
2253 "Release String: ''\n"
2254 "Descriptors:\n"
2255 " Hashtree descriptor:\n"
2256 " Version of dm-verity: 1\n"
2257 " Image Size: 1052672 bytes\n"
2258 " Tree Offset: 1052672\n"
2259 " Tree Size: 16384 bytes\n"
2260 " Data Block Size: 4096 bytes\n"
2261 " Hash Block Size: 4096 bytes\n"
2262 " FEC num roots: 2\n"
2263 " FEC offset: 1069056\n"
2264 " FEC size: 16384 bytes\n"
2265 " Hash Algorithm: sha1\n"
2266 " Partition Name: rootfs\n"
2267 " Salt: d00df00d\n"
2268 " Root Digest: e811611467dcd6e8dc4324e45f706c2bdd51db67\n"
2269 " Flags: 0\n"
2270 " Kernel Cmdline descriptor:\n"
2271 " Flags: 1\n"
2272 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 "
2273 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
2274 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
2275 "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
2276 "use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 "
2277 "fec_blocks 261 fec_start 261\" root=/dev/dm-0'\n"
2278 " Kernel Cmdline descriptor:\n"
2279 " Flags: 2\n"
2280 " Kernel Cmdline: "
2281 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n",
2282 InfoImage(rootfs_path));
2283
2284 // Chain to the rootfs.img and include two cmdline descriptors.
2285 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2286 EXPECT_COMMAND(0,
2287 "./avbtool.py make_vbmeta_image "
2288 "--output %s "
2289 "--kernel_cmdline 'foo bar baz' "
2290 "--kernel_cmdline 'second cmdline' "
2291 "--chain_partition rootfs:1:%s "
2292 "--algorithm SHA256_RSA2048 "
2293 "--key test/data/testkey_rsa2048.pem "
2294 "--internal_release_string \"\"",
2295 vbmeta_path.value().c_str(),
2296 pk_path.value().c_str());
2297 EXPECT_EQ(
2298 "Minimum libavb version: 1.0\n"
2299 "Header Block: 256 bytes\n"
2300 "Authentication Block: 320 bytes\n"
2301 "Auxiliary Block: 1280 bytes\n"
2302 "Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2303 "Algorithm: SHA256_RSA2048\n"
2304 "Rollback Index: 0\n"
2305 "Flags: 0\n"
2306 "Rollback Index Location: 0\n"
2307 "Release String: ''\n"
2308 "Descriptors:\n"
2309 " Chain Partition descriptor:\n"
2310 " Partition Name: rootfs\n"
2311 " Rollback Index Location: 1\n"
2312 " Public key (sha1): "
2313 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2314 " Kernel Cmdline descriptor:\n"
2315 " Flags: 0\n"
2316 " Kernel Cmdline: 'foo bar baz'\n"
2317 " Kernel Cmdline descriptor:\n"
2318 " Flags: 0\n"
2319 " Kernel Cmdline: 'second cmdline'\n",
2320 InfoImage(vbmeta_path));
2321
2322 base::FilePath out_path = testdir_.Append("out.txt");
2323 std::string out;
2324
2325 // First check the kernel cmdline without --hashtree_disabled - compare with
2326 // above info_image output.
2327 EXPECT_COMMAND(0,
2328 "./avbtool.py calculate_kernel_cmdline --image %s > %s",
2329 vbmeta_path.value().c_str(),
2330 out_path.value().c_str());
2331 ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2332 EXPECT_EQ(
2333 "dm=\"1 vroot none ro 1,0 2056 verity 1 "
2334 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) "
2335 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 "
2336 "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks "
2337 "use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 "
2338 "fec_blocks 261 fec_start 261\" root=/dev/dm-0 foo bar baz second "
2339 "cmdline",
2340 out);
2341
2342 // Then check the kernel cmdline with --hashtree_disabled - compare with above
2343 // info_image output.
2344 EXPECT_COMMAND(
2345 0,
2346 "./avbtool.py calculate_kernel_cmdline --image %s --hashtree_disabled > %s",
2347 vbmeta_path.value().c_str(),
2348 out_path.value().c_str());
2349 ASSERT_TRUE(base::ReadFileToString(out_path, &out));
2350 EXPECT_EQ(
2351 "root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID) foo bar baz second cmdline",
2352 out);
2353 }
2354
TEST_F(AvbToolTest,AddHashFooterSmallImageWithExternalVbmeta)2355 TEST_F(AvbToolTest, AddHashFooterSmallImageWithExternalVbmeta) {
2356 const size_t image_size = 37;
2357 const size_t partition_size = 20 * 4096;
2358
2359 std::vector<uint8_t> image(image_size, 0);
2360 for (size_t n = 0; n < image_size; n++) {
2361 image[n] = uint8_t(n);
2362 }
2363
2364 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin");
2365 base::FilePath image_path = testdir_.Append("kernel.bin");
2366 EXPECT_EQ(image_size,
2367 static_cast<const size_t>(
2368 base::WriteFile(image_path,
2369 reinterpret_cast<const char*>(image.data()),
2370 image.size())));
2371 EXPECT_COMMAND(0,
2372 "./avbtool.py add_hash_footer --salt d00df00d "
2373 "--hash_algorithm sha256 --image %s "
2374 "--partition_size %zu --partition_name kernel "
2375 "--algorithm SHA256_RSA2048 "
2376 "--key test/data/testkey_rsa2048.pem "
2377 "--output_vbmeta %s "
2378 "--do_not_append_vbmeta_image "
2379 "--internal_release_string \"\"",
2380 image_path.value().c_str(),
2381 partition_size,
2382 ext_vbmeta_path.value().c_str());
2383
2384 // It is not this unit test's job to check the vbmeta content.
2385
2386 int64_t file_size;
2387 ASSERT_TRUE(base::GetFileSize(image_path, &file_size));
2388 EXPECT_EQ(static_cast<size_t>(file_size), image_size);
2389 }
2390
TEST_F(AvbToolTest,IncludeDescriptor)2391 TEST_F(AvbToolTest, IncludeDescriptor) {
2392 base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin");
2393 base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin");
2394 base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
2395
2396 EXPECT_COMMAND(0,
2397 "./avbtool.py make_vbmeta_image "
2398 "--output %s "
2399 "--kernel_cmdline 'something' "
2400 "--prop name:value "
2401 "--internal_release_string \"\"",
2402 vbmeta1_path.value().c_str());
2403
2404 EXPECT_COMMAND(0,
2405 "./avbtool.py make_vbmeta_image "
2406 "--output %s "
2407 "--prop name2:value2 "
2408 "--prop name3:value3 "
2409 "--internal_release_string \"\"",
2410 vbmeta2_path.value().c_str());
2411
2412 EXPECT_COMMAND(0,
2413 "./avbtool.py make_vbmeta_image "
2414 "--output %s "
2415 "--prop name4:value4 "
2416 "--include_descriptors_from_image %s "
2417 "--include_descriptors_from_image %s "
2418 "--internal_release_string \"\"",
2419 vbmeta3_path.value().c_str(),
2420 vbmeta1_path.value().c_str(),
2421 vbmeta2_path.value().c_str());
2422
2423 ASSERT_EQ(
2424 "Minimum libavb version: 1.0\n"
2425 "Header Block: 256 bytes\n"
2426 "Authentication Block: 0 bytes\n"
2427 "Auxiliary Block: 256 bytes\n"
2428 "Algorithm: NONE\n"
2429 "Rollback Index: 0\n"
2430 "Flags: 0\n"
2431 "Rollback Index Location: 0\n"
2432 "Release String: ''\n"
2433 "Descriptors:\n"
2434 " Prop: name4 -> 'value4'\n"
2435 " Prop: name -> 'value'\n"
2436 " Kernel Cmdline descriptor:\n"
2437 " Flags: 0\n"
2438 " Kernel Cmdline: 'something'\n"
2439 " Prop: name2 -> 'value2'\n"
2440 " Prop: name3 -> 'value3'\n",
2441 InfoImage(vbmeta3_path));
2442 }
2443
TEST_F(AvbToolTest,ChainedPartition)2444 TEST_F(AvbToolTest, ChainedPartition) {
2445 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
2446
2447 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2448
2449 EXPECT_COMMAND(
2450 0,
2451 "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
2452 " --output %s",
2453 pk_path.value().c_str());
2454
2455 EXPECT_COMMAND(
2456 0,
2457 "./avbtool.py make_vbmeta_image "
2458 "--output %s "
2459 "--chain_partition system:1:%s "
2460 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2461 "--internal_release_string \"\"",
2462 vbmeta_path.value().c_str(),
2463 pk_path.value().c_str());
2464
2465 ASSERT_EQ(
2466 "Minimum libavb version: 1.0\n"
2467 "Header Block: 256 bytes\n"
2468 "Authentication Block: 320 bytes\n"
2469 "Auxiliary Block: 1152 bytes\n"
2470 "Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2471 "Algorithm: SHA256_RSA2048\n"
2472 "Rollback Index: 0\n"
2473 "Flags: 0\n"
2474 "Rollback Index Location: 0\n"
2475 "Release String: ''\n"
2476 "Descriptors:\n"
2477 " Chain Partition descriptor:\n"
2478 " Partition Name: system\n"
2479 " Rollback Index Location: 1\n"
2480 " Public key (sha1): "
2481 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n",
2482 InfoImage(vbmeta_path));
2483
2484 // Now check the VBMeta image.
2485 std::string image_data;
2486 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data));
2487
2488 const uint8_t* vbmeta_data =
2489 reinterpret_cast<const uint8_t*>(image_data.data());
2490 const size_t vbmeta_size = image_data.length();
2491 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
2492 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL));
2493
2494 // Collect all descriptors.
2495 std::vector<const AvbDescriptor*> descriptors;
2496 avb_descriptor_foreach(
2497 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors);
2498
2499 // We should have one descriptor - check it.
2500 EXPECT_EQ(1UL, descriptors.size());
2501
2502 std::string pk_data;
2503 ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data));
2504
2505 AvbChainPartitionDescriptor d;
2506 EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
2507 avb_be64toh(descriptors[0]->tag));
2508 EXPECT_NE(
2509 0,
2510 avb_chain_partition_descriptor_validate_and_byteswap(
2511 reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]),
2512 &d));
2513 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) +
2514 sizeof(AvbChainPartitionDescriptor);
2515 uint64_t o = 0;
2516 EXPECT_EQ("system",
2517 std::string(reinterpret_cast<const char*>(desc_end + o),
2518 d.partition_name_len));
2519 o += d.partition_name_len;
2520 EXPECT_EQ(pk_data,
2521 std::string(reinterpret_cast<const char*>(descriptors[0]) +
2522 sizeof(AvbChainPartitionDescriptor) + o,
2523 d.public_key_len));
2524 }
2525
TEST_F(AvbToolTest,ChainedPartitionNoLocationCollision)2526 TEST_F(AvbToolTest, ChainedPartitionNoLocationCollision) {
2527 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin");
2528
2529 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
2530
2531 EXPECT_COMMAND(
2532 0,
2533 "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
2534 " --output %s",
2535 pk_path.value().c_str());
2536
2537 // Check that avbtool bails if the same Rollback Index Location is
2538 // used for multiple chained partitions.
2539 EXPECT_COMMAND(
2540 1,
2541 "./avbtool.py make_vbmeta_image "
2542 "--output %s "
2543 "--chain_partition system:1:%s "
2544 "--chain_partition other:1:%s "
2545 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2546 "--internal_release_string \"\"",
2547 vbmeta_path.value().c_str(),
2548 pk_path.value().c_str(),
2549 pk_path.value().c_str());
2550 }
2551
TEST_F(AvbToolTest,AppendVBMetaImage)2552 TEST_F(AvbToolTest, AppendVBMetaImage) {
2553 size_t boot_size = 5 * 1024 * 1024;
2554 size_t boot_partition_size = 32 * 1024 * 1024;
2555 base::FilePath boot_path = GenerateImage("boot", boot_size);
2556
2557 GenerateVBMetaImage("vbmeta.img",
2558 "SHA256_RSA2048",
2559 0,
2560 base::FilePath("test/data/testkey_rsa2048.pem"),
2561 std::string("--append_to_release_string \"\" "
2562 "--kernel_cmdline foo"));
2563
2564 EXPECT_COMMAND(0,
2565 "./avbtool.py append_vbmeta_image "
2566 "--image %s "
2567 "--partition_size %d "
2568 "--vbmeta_image %s ",
2569 boot_path.value().c_str(),
2570 (int)boot_partition_size,
2571 vbmeta_image_path_.value().c_str());
2572
2573 std::string vbmeta_contents = InfoImage(vbmeta_image_path_);
2574 std::string boot_contents = InfoImage(boot_path);
2575
2576 // Check that boot.img has the same vbmeta blob as from vbmeta.img -
2577 // we do this by inspecting 'avbtool info_image' output combined
2578 // with the known footer location given boot.img has 5 MiB known
2579 // content and the partition size is 32 MiB.
2580 ASSERT_EQ(
2581 "Minimum libavb version: 1.0\n"
2582 "Header Block: 256 bytes\n"
2583 "Authentication Block: 320 bytes\n"
2584 "Auxiliary Block: 576 bytes\n"
2585 "Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
2586 "Algorithm: SHA256_RSA2048\n"
2587 "Rollback Index: 0\n"
2588 "Flags: 0\n"
2589 "Rollback Index Location: 0\n"
2590 "Release String: 'avbtool 1.2.0 '\n"
2591 "Descriptors:\n"
2592 " Kernel Cmdline descriptor:\n"
2593 " Flags: 0\n"
2594 " Kernel Cmdline: 'foo'\n",
2595 vbmeta_contents);
2596 std::string known_footer =
2597 "Footer version: 1.0\n"
2598 "Image size: 33554432 bytes\n"
2599 "Original image size: 5242880 bytes\n"
2600 "VBMeta offset: 5242880\n"
2601 "VBMeta size: 1152 bytes\n"
2602 "--\n";
2603 ASSERT_EQ(known_footer + vbmeta_contents, boot_contents);
2604
2605 // Also verify that the blobs are the same, bit for bit.
2606 base::File f =
2607 base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
2608 std::vector<uint8_t> loaded_vbmeta;
2609 loaded_vbmeta.resize(1152);
2610 EXPECT_EQ(
2611 f.Read(
2612 5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152),
2613 1152);
2614 EXPECT_EQ(vbmeta_image_, loaded_vbmeta);
2615 }
2616
TEST_F(AvbToolTest,SigningHelperBasic)2617 TEST_F(AvbToolTest, SigningHelperBasic) {
2618 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2619 base::FilePath signing_helper_test_path =
2620 testdir_.Append("signing_helper_test");
2621 EXPECT_COMMAND(
2622 0,
2623 "SIGNING_HELPER_TEST=\"%s\" ./avbtool.py make_vbmeta_image "
2624 "--output %s "
2625 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2626 "--signing_helper test/avbtool_signing_helper_test.py "
2627 "--internal_release_string \"\"",
2628 signing_helper_test_path.value().c_str(),
2629 vbmeta_path.value().c_str());
2630
2631 // Now check the value in test file.
2632 std::string value;
2633 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
2634 EXPECT_EQ("DONE", value);
2635 }
2636
TEST_F(AvbToolTest,SigningHelperWithFilesBasic)2637 TEST_F(AvbToolTest, SigningHelperWithFilesBasic) {
2638 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2639 base::FilePath signing_helper_test_path =
2640 testdir_.Append("signing_helper_test");
2641 EXPECT_COMMAND(
2642 0,
2643 "SIGNING_HELPER_TEST=\"%s\" ./avbtool.py make_vbmeta_image "
2644 "--output %s "
2645 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2646 "--signing_helper_with_files "
2647 "test/avbtool_signing_helper_with_files_test.py "
2648 "--internal_release_string \"\"",
2649 signing_helper_test_path.value().c_str(),
2650 vbmeta_path.value().c_str());
2651
2652 // Now check the value in test file.
2653 std::string value;
2654 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value));
2655 EXPECT_EQ("DONE", value);
2656 }
2657
TEST_F(AvbToolTest,SigningHelperReturnError)2658 TEST_F(AvbToolTest, SigningHelperReturnError) {
2659 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2660 EXPECT_COMMAND(
2661 1,
2662 "./avbtool.py make_vbmeta_image "
2663 "--output %s "
2664 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2665 "--signing_helper test/avbtool_signing_helper_test.py "
2666 "--internal_release_string \"\"",
2667 vbmeta_path.value().c_str());
2668 }
2669
TEST_F(AvbToolTest,SigningHelperWithFilesReturnError)2670 TEST_F(AvbToolTest, SigningHelperWithFilesReturnError) {
2671 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2672 EXPECT_COMMAND(
2673 1,
2674 "./avbtool.py make_vbmeta_image "
2675 "--output %s "
2676 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2677 "--signing_helper_with_files "
2678 "test/avbtool_signing_helper_with_files_test.py "
2679 "--internal_release_string \"\"",
2680 vbmeta_path.value().c_str());
2681 }
2682
TEST_F(AvbToolTest,VerifyImageNoSignature)2683 TEST_F(AvbToolTest, VerifyImageNoSignature) {
2684 GenerateVBMetaImage("vbmeta.img",
2685 "", // NONE
2686 0,
2687 base::FilePath());
2688
2689 EXPECT_COMMAND(0,
2690 "./avbtool.py verify_image "
2691 "--image %s ",
2692 vbmeta_image_path_.value().c_str());
2693 }
2694
TEST_F(AvbToolTest,VerifyImageValidSignature)2695 TEST_F(AvbToolTest, VerifyImageValidSignature) {
2696 GenerateVBMetaImage("vbmeta.img",
2697 "SHA256_RSA2048",
2698 0,
2699 base::FilePath("test/data/testkey_rsa2048.pem"));
2700
2701 EXPECT_COMMAND(0,
2702 "./avbtool.py verify_image "
2703 "--image %s ",
2704 vbmeta_image_path_.value().c_str());
2705 }
2706
TEST_F(AvbToolTest,VerifyImageCorruptedVBMeta)2707 TEST_F(AvbToolTest, VerifyImageCorruptedVBMeta) {
2708 GenerateVBMetaImage("vbmeta.img",
2709 "SHA256_RSA2048",
2710 0,
2711 base::FilePath("test/data/testkey_rsa2048.pem"));
2712
2713 // Corrupt four bytes of data in the end of the image. Since the aux
2714 // data is at the end and this data is signed, this will change the
2715 // value of the computed hash.
2716 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2717 EXPECT_EQ(AVB_IO_RESULT_OK,
2718 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2719 "vbmeta",
2720 -4, // offset from end
2721 sizeof corrupt_data,
2722 corrupt_data));
2723
2724 EXPECT_COMMAND(1,
2725 "./avbtool.py verify_image "
2726 "--image %s ",
2727 vbmeta_image_path_.value().c_str());
2728 }
2729
TEST_F(AvbToolTest,VerifyImageOtherKeyMatching)2730 TEST_F(AvbToolTest, VerifyImageOtherKeyMatching) {
2731 GenerateVBMetaImage("vbmeta.img",
2732 "SHA256_RSA2048",
2733 0,
2734 base::FilePath("test/data/testkey_rsa2048.pem"));
2735
2736 EXPECT_COMMAND(0,
2737 "./avbtool.py verify_image "
2738 "--image %s --key test/data/testkey_rsa2048.pem",
2739 vbmeta_image_path_.value().c_str());
2740 }
2741
TEST_F(AvbToolTest,VerifyImageOtherKeyNotMatching)2742 TEST_F(AvbToolTest, VerifyImageOtherKeyNotMatching) {
2743 GenerateVBMetaImage("vbmeta.img",
2744 "SHA256_RSA2048",
2745 0,
2746 base::FilePath("test/data/testkey_rsa2048.pem"));
2747
2748 EXPECT_COMMAND(1,
2749 "./avbtool.py verify_image "
2750 "--image %s --key test/data/testkey_rsa4096.pem",
2751 vbmeta_image_path_.value().c_str());
2752 }
2753
TEST_F(AvbToolTest,VerifyImageBrokenSignature)2754 TEST_F(AvbToolTest, VerifyImageBrokenSignature) {
2755 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
2756 base::FilePath signing_helper_test_path =
2757 testdir_.Append("signing_helper_test");
2758
2759 // Intentionally make the signer generate a wrong signature.
2760 EXPECT_COMMAND(
2761 0,
2762 "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool.py make_vbmeta_image "
2763 "--output %s "
2764 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
2765 "--signing_helper test/avbtool_signing_helper_test.py "
2766 "--internal_release_string \"\"",
2767 vbmeta_path.value().c_str());
2768
2769 EXPECT_COMMAND(1,
2770 "./avbtool.py verify_image "
2771 "--image %s ",
2772 vbmeta_path.value().c_str());
2773 }
2774
2775 // Helper to generate boot.img, unsparse system.img, and vbmeta.img.
GenerateImageWithHashAndHashtreeSetup()2776 void AvbToolTest::GenerateImageWithHashAndHashtreeSetup() {
2777 const size_t boot_partition_size = 16 * 1024 * 1024;
2778 const size_t boot_image_size = 5 * 1024 * 1024;
2779 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
2780 EXPECT_COMMAND(0,
2781 "./avbtool.py add_hash_footer"
2782 " --image %s"
2783 " --rollback_index 0"
2784 " --partition_name boot"
2785 " --partition_size %zd"
2786 " --salt deadbeef"
2787 " --internal_release_string \"\"",
2788 boot_path.value().c_str(),
2789 boot_partition_size);
2790
2791 const size_t system_partition_size = 10 * 1024 * 1024;
2792 const size_t system_image_size = 8 * 1024 * 1024;
2793 base::FilePath system_path = GenerateImage("system.img", system_image_size);
2794 EXPECT_COMMAND(0,
2795 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
2796 "--partition_size %zd --partition_name system "
2797 "--internal_release_string \"\" ",
2798 system_path.value().c_str(),
2799 system_partition_size);
2800
2801 GenerateVBMetaImage("vbmeta.img",
2802 "SHA256_RSA2048",
2803 0,
2804 base::FilePath("test/data/testkey_rsa2048.pem"),
2805 base::StringPrintf("--include_descriptors_from_image %s "
2806 "--include_descriptors_from_image %s",
2807 boot_path.value().c_str(),
2808 system_path.value().c_str()));
2809 }
2810
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtree)2811 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) {
2812 GenerateImageWithHashAndHashtreeSetup();
2813
2814 // Do two checks - one for system.img not sparse, and one where it
2815 // is sparse.
2816 for (int n = 0; n < 2; n++) {
2817 EXPECT_COMMAND(0,
2818 "./avbtool.py verify_image "
2819 "--image %s ",
2820 vbmeta_image_path_.value().c_str());
2821 if (n == 0) {
2822 EXPECT_COMMAND(0,
2823 "img2simg %s %s.sparse",
2824 testdir_.Append("system.img").value().c_str(),
2825 testdir_.Append("system.img").value().c_str());
2826 EXPECT_COMMAND(0,
2827 "mv %s.sparse %s",
2828 testdir_.Append("system.img").value().c_str(),
2829 testdir_.Append("system.img").value().c_str());
2830 }
2831 }
2832 }
2833
TEST_F(AvbToolTest,VerifyImageWithHashAndZeroedHashtree)2834 TEST_F(AvbToolTest, VerifyImageWithHashAndZeroedHashtree) {
2835 const size_t system_partition_size = 10 * 1024 * 1024;
2836 const size_t system_image_size = 8 * 1024 * 1024;
2837 base::FilePath system_path = GenerateImage("system.img", system_image_size);
2838 EXPECT_COMMAND(0,
2839 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
2840 "--partition_size %zd --partition_name system "
2841 "--internal_release_string \"\" ",
2842 system_path.value().c_str(),
2843 system_partition_size);
2844
2845 GenerateVBMetaImage("vbmeta.img",
2846 "SHA256_RSA2048",
2847 0,
2848 base::FilePath("test/data/testkey_rsa2048.pem"),
2849 base::StringPrintf("--include_descriptors_from_image %s ",
2850 system_path.value().c_str()));
2851
2852 EXPECT_COMMAND(0,
2853 "./avbtool.py verify_image --image %s --accept_zeroed_hashtree",
2854 vbmeta_image_path_.value().c_str());
2855
2856 EXPECT_COMMAND(
2857 0, "./avbtool.py zero_hashtree --image %s", system_path.value().c_str());
2858
2859 EXPECT_COMMAND(1,
2860 "./avbtool.py verify_image --image %s",
2861 vbmeta_image_path_.value().c_str());
2862
2863 EXPECT_COMMAND(0,
2864 "./avbtool.py verify_image --image %s --accept_zeroed_hashtree",
2865 vbmeta_image_path_.value().c_str());
2866 }
2867
TEST_F(AvbToolTest,VerifyImageWithNoHashtree)2868 TEST_F(AvbToolTest, VerifyImageWithNoHashtree) {
2869 const size_t system_partition_size = 10 * 1024 * 1024;
2870 const size_t system_image_size = 8 * 1024 * 1024;
2871 base::FilePath system_path = GenerateImage("system.img", system_image_size);
2872 EXPECT_COMMAND(0,
2873 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
2874 "--partition_size %zd --partition_name system "
2875 "--no_hashtree "
2876 "--internal_release_string \"\" ",
2877 system_path.value().c_str(),
2878 system_partition_size);
2879
2880 GenerateVBMetaImage("vbmeta.img",
2881 "SHA256_RSA2048",
2882 0,
2883 base::FilePath("test/data/testkey_rsa2048.pem"),
2884 base::StringPrintf("--include_descriptors_from_image %s ",
2885 system_path.value().c_str()));
2886
2887 EXPECT_COMMAND(1,
2888 "./avbtool.py verify_image --image %s",
2889 vbmeta_image_path_.value().c_str());
2890
2891 EXPECT_COMMAND(0,
2892 "./avbtool.py verify_image --image %s --accept_zeroed_hashtree",
2893 vbmeta_image_path_.value().c_str());
2894 }
2895
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHash)2896 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) {
2897 GenerateImageWithHashAndHashtreeSetup();
2898
2899 // Corrupt four bytes of data in the middle of boot.img.
2900 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2901 EXPECT_EQ(AVB_IO_RESULT_OK,
2902 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2903 "boot",
2904 105 * 1024, // offset from start
2905 sizeof corrupt_data,
2906 corrupt_data));
2907
2908 EXPECT_COMMAND(1,
2909 "./avbtool.py verify_image "
2910 "--image %s ",
2911 vbmeta_image_path_.value().c_str());
2912 }
2913
TEST_F(AvbToolTest,VerifyImageWithHashAndHashtreeCorruptHashtree)2914 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHashtree) {
2915 GenerateImageWithHashAndHashtreeSetup();
2916
2917 // Corrupt four bytes of data in the middle of system.img.
2918 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff};
2919 EXPECT_EQ(AVB_IO_RESULT_OK,
2920 ops_.avb_ops()->write_to_partition(ops_.avb_ops(),
2921 "system",
2922 123 * 1024, // offset from start
2923 sizeof corrupt_data,
2924 corrupt_data));
2925
2926 // Do two checks - one for system.img not sparse, and one where it
2927 // is sparse.
2928 for (int n = 0; n < 2; n++) {
2929 EXPECT_COMMAND(1,
2930 "./avbtool.py verify_image "
2931 "--image %s ",
2932 vbmeta_image_path_.value().c_str());
2933 if (n == 0) {
2934 EXPECT_COMMAND(0,
2935 "img2simg %s %s.sparse",
2936 testdir_.Append("system.img").value().c_str(),
2937 testdir_.Append("system.img").value().c_str());
2938 EXPECT_COMMAND(0,
2939 "mv %s.sparse %s",
2940 testdir_.Append("system.img").value().c_str(),
2941 testdir_.Append("system.img").value().c_str());
2942 }
2943 }
2944 }
2945
TEST_F(AvbToolTest,VerifyImageChainPartition)2946 TEST_F(AvbToolTest, VerifyImageChainPartition) {
2947 base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
2948 EXPECT_COMMAND(
2949 0,
2950 "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
2951 " --output %s",
2952 pk4096_path.value().c_str());
2953
2954 base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey");
2955 EXPECT_COMMAND(
2956 0,
2957 "./avbtool.py extract_public_key --key test/data/testkey_rsa8192.pem"
2958 " --output %s",
2959 pk8192_path.value().c_str());
2960
2961 GenerateVBMetaImage("vbmeta.img",
2962 "SHA256_RSA2048",
2963 0,
2964 base::FilePath("test/data/testkey_rsa2048.pem"),
2965 base::StringPrintf("--chain_partition system:1:%s ",
2966 pk4096_path.value().c_str()));
2967
2968 // Should not fail (name, rollback_index, contents all correct).
2969 EXPECT_COMMAND(0,
2970 "./avbtool.py verify_image "
2971 "--image %s "
2972 "--expected_chain_partition system:1:%s",
2973 vbmeta_image_path_.value().c_str(),
2974 pk4096_path.value().c_str());
2975
2976 // Should fail because we didn't use --expected_chain_partition.
2977 EXPECT_COMMAND(1,
2978 "./avbtool.py verify_image "
2979 "--image %s ",
2980 vbmeta_image_path_.value().c_str());
2981
2982 // Should fail because partition name is wrong.
2983 EXPECT_COMMAND(1,
2984 "./avbtool.py verify_image "
2985 "--image %s "
2986 "--expected_chain_partition xyz:1:%s",
2987 vbmeta_image_path_.value().c_str(),
2988 pk4096_path.value().c_str());
2989
2990 // Should fail because rollback index location is wrong.
2991 EXPECT_COMMAND(1,
2992 "./avbtool.py verify_image "
2993 "--image %s "
2994 "--expected_chain_partition system:2:%s",
2995 vbmeta_image_path_.value().c_str(),
2996 pk4096_path.value().c_str());
2997
2998 // Should fail because public key blob is wrong.
2999 EXPECT_COMMAND(1,
3000 "./avbtool.py verify_image "
3001 "--image %s "
3002 "--expected_chain_partition system:1:%s",
3003 vbmeta_image_path_.value().c_str(),
3004 pk8192_path.value().c_str());
3005 }
3006
TEST_F(AvbToolTest,VerifyImageChainPartitionWithFollow)3007 TEST_F(AvbToolTest, VerifyImageChainPartitionWithFollow) {
3008 base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
3009 EXPECT_COMMAND(
3010 0,
3011 "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
3012 " --output %s",
3013 pk4096_path.value().c_str());
3014
3015 GenerateVBMetaImage("vbmeta.img",
3016 "SHA256_RSA2048",
3017 0,
3018 base::FilePath("test/data/testkey_rsa2048.pem"),
3019 base::StringPrintf("--chain_partition system:1:%s ",
3020 pk4096_path.value().c_str()));
3021
3022 const size_t system_partition_size = 10 * 1024 * 1024;
3023 const size_t system_image_size = 8 * 1024 * 1024;
3024 base::FilePath system_path = GenerateImage("system.img", system_image_size);
3025 EXPECT_COMMAND(0,
3026 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
3027 "--partition_size %zd --partition_name system "
3028 "--algorithm SHA256_RSA4096 "
3029 "--key test/data/testkey_rsa4096.pem "
3030 "--internal_release_string \"\" ",
3031 system_path.value().c_str(),
3032 system_partition_size);
3033
3034 // Even without --expected_chain_partition this shouldn't fail because we use
3035 // --follow_chain_partitions and system.img exists... to avoid unstable paths
3036 // (e.g. /tmp/libavb.12345) in the output we need to run this from the test
3037 // directory itself. It's a little ugly but it works.
3038 char cwdbuf[PATH_MAX];
3039 ASSERT_NE(nullptr, getcwd(cwdbuf, sizeof cwdbuf));
3040 EXPECT_COMMAND(0,
3041 "cd %s && (%s/avbtool.py verify_image "
3042 "--image vbmeta.img --follow_chain_partitions > out.txt)",
3043 testdir_.value().c_str(),
3044 cwdbuf);
3045 base::FilePath out_path = testdir_.Append("out.txt");
3046 std::string out;
3047 ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3048 EXPECT_EQ(
3049 "Verifying image vbmeta.img using embedded public key\n"
3050 "vbmeta: Successfully verified SHA256_RSA2048 vbmeta struct in "
3051 "vbmeta.img\n"
3052 "system: Chained but ROLLBACK_SLOT (which is 1) and KEY (which has sha1 "
3053 "2597c218aae470a130f61162feaae70afd97f011) not specified\n"
3054 "--\n"
3055 "Verifying image system.img using embedded public key\n"
3056 "vbmeta: Successfully verified footer and SHA256_RSA4096 vbmeta struct "
3057 "in system.img\n"
3058 "system: Successfully verified sha1 hashtree of system.img for image of "
3059 "8388608 bytes\n",
3060 out);
3061
3062 // Make sure we also follow partitions *even* when specifying
3063 // --expect_chain_partition. The output is slightly different from above.
3064 EXPECT_COMMAND(0,
3065 "cd %s && (%s/avbtool.py verify_image "
3066 "--image vbmeta.img --expected_chain_partition system:1:%s "
3067 "--follow_chain_partitions > out.txt)",
3068 testdir_.value().c_str(),
3069 cwdbuf,
3070 pk4096_path.value().c_str());
3071 ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3072 EXPECT_EQ(
3073 "Verifying image vbmeta.img using embedded public key\n"
3074 "vbmeta: Successfully verified SHA256_RSA2048 vbmeta struct in "
3075 "vbmeta.img\n"
3076 "system: Successfully verified chain partition descriptor matches "
3077 "expected data\n"
3078 "--\n"
3079 "Verifying image system.img using embedded public key\n"
3080 "vbmeta: Successfully verified footer and SHA256_RSA4096 vbmeta struct "
3081 "in system.img\n"
3082 "system: Successfully verified sha1 hashtree of system.img for image of "
3083 "8388608 bytes\n",
3084 out);
3085 }
3086
TEST_F(AvbToolTest,VerifyImageChainPartitionOtherVBMeta)3087 TEST_F(AvbToolTest, VerifyImageChainPartitionOtherVBMeta) {
3088 base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
3089 EXPECT_COMMAND(
3090 0,
3091 "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
3092 " --output %s",
3093 pk4096_path.value().c_str());
3094
3095 const size_t system_partition_size = 10 * 1024 * 1024;
3096 const size_t system_image_size = 8 * 1024 * 1024;
3097 base::FilePath system_path = GenerateImage("system.img", system_image_size);
3098 EXPECT_COMMAND(0,
3099 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
3100 "--partition_size %zd --partition_name system "
3101 "--internal_release_string \"\" "
3102 "--algorithm SHA256_RSA4096 "
3103 "--key test/data/testkey_rsa4096.pem ",
3104 system_path.value().c_str(),
3105 system_partition_size,
3106 pk4096_path.value().c_str());
3107
3108 GenerateVBMetaImage(
3109 "vbmeta.img",
3110 "SHA256_RSA2048",
3111 0,
3112 base::FilePath("test/data/testkey_rsa2048.pem"),
3113 base::StringPrintf("--chain_partition vbmeta_google:1:%s ",
3114 pk4096_path.value().c_str()));
3115
3116 // Should not fail (name, rollback_index, contents all correct).
3117 EXPECT_COMMAND(0,
3118 "./avbtool.py verify_image "
3119 "--image %s "
3120 "--expected_chain_partition vbmeta_google:1:%s",
3121 vbmeta_image_path_.value().c_str(),
3122 pk4096_path.value().c_str());
3123
3124 // Should not fail (looks in system.img image).
3125 EXPECT_COMMAND(0,
3126 "./avbtool.py verify_image "
3127 "--image %s ",
3128 system_path.value().c_str());
3129
3130 // Extract the vbmeta blob from the footer in system.img, put it into
3131 // vbmeta_google.img, and erase the footer from system.img (but keep
3132 // the hash tree in system.img)
3133 base::FilePath vbmeta_google_path = GenerateImage("vbmeta_google.img", 0);
3134 EXPECT_COMMAND(0,
3135 "./avbtool.py extract_vbmeta_image"
3136 " --image %s"
3137 " --output %s",
3138 system_path.value().c_str(),
3139 vbmeta_google_path.value().c_str());
3140 EXPECT_COMMAND(0,
3141 "./avbtool.py erase_footer"
3142 " --image %s --keep_hashtree",
3143 system_path.value().c_str());
3144
3145 // Should not fail - looks in system.img's detached vbmeta (vbmeta_google.img)
3146 // for vbmeta blob and system.img for the actual hashtree.
3147 EXPECT_COMMAND(0,
3148 "./avbtool.py verify_image "
3149 "--image %s ",
3150 vbmeta_google_path.value().c_str());
3151 }
3152
TEST_F(AvbToolTest,PrintPartitionDigests)3153 TEST_F(AvbToolTest, PrintPartitionDigests) {
3154 base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
3155 EXPECT_COMMAND(
3156 0,
3157 "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
3158 " --output %s",
3159 pk4096_path.value().c_str());
3160
3161 const size_t boot_partition_size = 16 * 1024 * 1024;
3162 const size_t boot_image_size = 5 * 1024 * 1024;
3163 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
3164 EXPECT_COMMAND(0,
3165 "./avbtool.py add_hash_footer"
3166 " --image %s"
3167 " --rollback_index 0"
3168 " --partition_name boot"
3169 " --partition_size %zd"
3170 " --salt deadbeef"
3171 " --internal_release_string \"\"",
3172 boot_path.value().c_str(),
3173 boot_partition_size);
3174
3175 GenerateVBMetaImage("vbmeta.img",
3176 "SHA256_RSA2048",
3177 0,
3178 base::FilePath("test/data/testkey_rsa2048.pem"),
3179 base::StringPrintf("--chain_partition system:1:%s "
3180 "--include_descriptors_from_image %s",
3181 pk4096_path.value().c_str(),
3182 boot_path.value().c_str()));
3183
3184 const size_t system_partition_size = 10 * 1024 * 1024;
3185 const size_t system_image_size = 8 * 1024 * 1024;
3186 base::FilePath system_path = GenerateImage("system.img", system_image_size);
3187 EXPECT_COMMAND(0,
3188 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
3189 "--partition_size %zd --partition_name system "
3190 "--algorithm SHA256_RSA4096 "
3191 "--key test/data/testkey_rsa4096.pem "
3192 "--internal_release_string \"\" ",
3193 system_path.value().c_str(),
3194 system_partition_size);
3195
3196 base::FilePath out_path = testdir_.Append("out.txt");
3197 std::string out;
3198
3199 // Normal output
3200 EXPECT_COMMAND(0,
3201 "./avbtool.py print_partition_digests --image %s --output %s",
3202 vbmeta_image_path_.value().c_str(),
3203 out_path.value().c_str());
3204 ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3205 EXPECT_EQ(
3206 "system: d52d93c988d336a79abe1c05240ae9a79a9b7d61\n"
3207 "boot: "
3208 "184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\n",
3209 out);
3210
3211 // JSON output
3212 EXPECT_COMMAND(
3213 0,
3214 "./avbtool.py print_partition_digests --image %s --json --output %s",
3215 vbmeta_image_path_.value().c_str(),
3216 out_path.value().c_str());
3217 ASSERT_TRUE(base::ReadFileToString(out_path, &out));
3218 // The trailing whitespace comes from python. If they fix that bug we need
3219 // to update this test...
3220 EXPECT_EQ(
3221 "{\n"
3222 " \"partitions\": [\n"
3223 " {\n"
3224 " \"name\": \"system\",\n"
3225 " \"digest\": \"d52d93c988d336a79abe1c05240ae9a79a9b7d61\"\n"
3226 " },\n"
3227 " {\n"
3228 " \"name\": \"boot\",\n"
3229 " \"digest\": "
3230 "\"184cb36243adb8b87d2d8c4802de32125fe294ec46753d732144ee65df68a23d\"\n"
3231 " }\n"
3232 " ]\n"
3233 "}",
3234 out);
3235 }
3236
3237 class AvbToolTest_PrintRequiredVersion : public AvbToolTest {
3238 protected:
3239 const char* kOutputFile = "versions.txt";
3240
PrintWithAddHashFooter(int target_required_minor_version)3241 void PrintWithAddHashFooter(int target_required_minor_version) {
3242 std::string extra_args;
3243 if (target_required_minor_version == 1) {
3244 // The --do_not_use_ab option will require 1.1.
3245 extra_args = "--do_not_use_ab";
3246 } else if (target_required_minor_version == 2) {
3247 extra_args = "--rollback_index_location 2";
3248 }
3249
3250 const size_t boot_partition_size = 16 * 1024 * 1024;
3251 base::FilePath output_path = testdir_.Append(kOutputFile);
3252 EXPECT_COMMAND(0,
3253 "./avbtool.py add_hash_footer"
3254 " --rollback_index 0"
3255 " --partition_name boot"
3256 " --partition_size %zd"
3257 " --salt deadbeef"
3258 " --internal_release_string \"\""
3259 " %s"
3260 " --print_required_libavb_version > %s",
3261 boot_partition_size,
3262 extra_args.c_str(),
3263 output_path.value().c_str());
3264 CheckVersion(target_required_minor_version);
3265 }
3266
PrintWithAddHashtreeFooter(int target_required_minor_version)3267 void PrintWithAddHashtreeFooter(int target_required_minor_version) {
3268 std::string extra_args;
3269 if (target_required_minor_version == 1) {
3270 // The --do_not_use_ab option will require 1.1.
3271 extra_args = "--do_not_use_ab --check_at_most_once";
3272 } else if (target_required_minor_version == 2) {
3273 extra_args = "--rollback_index_location 2";
3274 }
3275 const size_t system_partition_size = 10 * 1024 * 1024;
3276 base::FilePath output_path = testdir_.Append(kOutputFile);
3277 EXPECT_COMMAND(0,
3278 "./avbtool.py add_hashtree_footer --salt d00df00d "
3279 "--partition_size %zd --partition_name system "
3280 "--internal_release_string \"\""
3281 " %s"
3282 " --print_required_libavb_version > %s",
3283 system_partition_size,
3284 extra_args.c_str(),
3285 output_path.value().c_str());
3286 CheckVersion(target_required_minor_version);
3287 }
3288
PrintWithMakeVbmetaImage(int target_required_minor_version)3289 void PrintWithMakeVbmetaImage(int target_required_minor_version) {
3290 std::string extra_args;
3291 if (target_required_minor_version == 1) {
3292 // An included descriptor that requires 1.1 will require 1.1 for vbmeta.
3293 const size_t boot_partition_size = 16 * 1024 * 1024;
3294 base::FilePath image_path = GenerateImage("test_print_version", 1024);
3295 EXPECT_COMMAND(0,
3296 "./avbtool.py add_hash_footer --salt d00df00d "
3297 "--hash_algorithm sha256 --image %s "
3298 "--partition_size %d --partition_name foobar "
3299 "--algorithm SHA256_RSA2048 "
3300 "--key test/data/testkey_rsa2048.pem "
3301 "--internal_release_string \"\" "
3302 "--do_not_use_ab",
3303 image_path.value().c_str(),
3304 (int)boot_partition_size);
3305 extra_args = base::StringPrintf("--include_descriptors_from_image %s",
3306 image_path.value().c_str());
3307 } else if (target_required_minor_version == 2) {
3308 extra_args = "--rollback_index_location 2";
3309 }
3310
3311 base::FilePath output_path = testdir_.Append(kOutputFile);
3312 EXPECT_COMMAND(0,
3313 "./avbtool.py make_vbmeta_image "
3314 "--algorithm SHA256_RSA2048 "
3315 "--key test/data/testkey_rsa2048.pem "
3316 "--internal_release_string \"\""
3317 " %s"
3318 " --print_required_libavb_version > %s",
3319 extra_args.c_str(),
3320 output_path.value().c_str());
3321 CheckVersion(target_required_minor_version);
3322 }
3323
CheckVersion(int expected_required_minor_version)3324 void CheckVersion(int expected_required_minor_version) {
3325 base::FilePath output_path = testdir_.Append(kOutputFile);
3326 std::string output;
3327 ASSERT_TRUE(base::ReadFileToString(output_path, &output));
3328 EXPECT_EQ(output,
3329 base::StringPrintf("1.%d\n", expected_required_minor_version));
3330 }
3331 };
3332
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_0)3333 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_0) {
3334 PrintWithAddHashFooter(0);
3335 }
3336
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_1)3337 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_1) {
3338 PrintWithAddHashFooter(1);
3339 }
3340
TEST_F(AvbToolTest_PrintRequiredVersion,HashFooter_1_2)3341 TEST_F(AvbToolTest_PrintRequiredVersion, HashFooter_1_2) {
3342 PrintWithAddHashFooter(2);
3343 }
3344
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_0)3345 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_0) {
3346 PrintWithAddHashtreeFooter(0);
3347 }
3348
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_1)3349 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_1) {
3350 PrintWithAddHashtreeFooter(1);
3351 }
3352
TEST_F(AvbToolTest_PrintRequiredVersion,HashtreeFooter_1_2)3353 TEST_F(AvbToolTest_PrintRequiredVersion, HashtreeFooter_1_2) {
3354 PrintWithAddHashtreeFooter(2);
3355 }
3356
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_0)3357 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_0) {
3358 PrintWithMakeVbmetaImage(0);
3359 }
3360
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_1)3361 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_1) {
3362 PrintWithMakeVbmetaImage(1);
3363 }
3364
TEST_F(AvbToolTest_PrintRequiredVersion,Vbmeta_1_2)3365 TEST_F(AvbToolTest_PrintRequiredVersion, Vbmeta_1_2) {
3366 PrintWithMakeVbmetaImage(2);
3367 }
3368
TEST_F(AvbToolTest,MakeAtxPikCertificate)3369 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
3370 base::FilePath subject_path = testdir_.Append("tmp_subject");
3371 ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
3372 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3373 EXPECT_COMMAND(
3374 0,
3375 "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
3376 pubkey_path.value().c_str());
3377
3378 base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3379 EXPECT_COMMAND(0,
3380 "./avbtool.py make_atx_certificate"
3381 " --subject %s"
3382 " --subject_key %s"
3383 " --subject_key_version 42"
3384 " --subject_is_intermediate_authority"
3385 " --authority_key test/data/testkey_atx_prk.pem"
3386 " --output %s",
3387 subject_path.value().c_str(),
3388 pubkey_path.value().c_str(),
3389 output_path.value().c_str());
3390
3391 EXPECT_COMMAND(0,
3392 "diff test/data/atx_pik_certificate.bin %s",
3393 output_path.value().c_str());
3394 }
3395
TEST_F(AvbToolTest,MakeAtxPskCertificate)3396 TEST_F(AvbToolTest, MakeAtxPskCertificate) {
3397 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3398 EXPECT_COMMAND(
3399 0,
3400 "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
3401 pubkey_path.value().c_str());
3402
3403 base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3404 EXPECT_COMMAND(0,
3405 "./avbtool.py make_atx_certificate"
3406 " --subject test/data/atx_product_id.bin"
3407 " --subject_key %s"
3408 " --subject_key_version 42"
3409 " --authority_key test/data/testkey_atx_pik.pem"
3410 " --output %s",
3411 pubkey_path.value().c_str(),
3412 output_path.value().c_str());
3413
3414 EXPECT_COMMAND(0,
3415 "diff test/data/atx_psk_certificate.bin %s",
3416 output_path.value().c_str());
3417 }
3418
TEST_F(AvbToolTest,MakeAtxPukCertificate)3419 TEST_F(AvbToolTest, MakeAtxPukCertificate) {
3420 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3421 EXPECT_COMMAND(
3422 0,
3423 "openssl pkey -pubout -in test/data/testkey_atx_puk.pem -out %s",
3424 pubkey_path.value().c_str());
3425
3426 base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
3427 EXPECT_COMMAND(0,
3428 "./avbtool.py make_atx_certificate"
3429 " --subject test/data/atx_product_id.bin"
3430 " --subject_key %s"
3431 " --subject_key_version 42"
3432 " --usage com.google.android.things.vboot.unlock"
3433 " --authority_key test/data/testkey_atx_pik.pem"
3434 " --output %s",
3435 pubkey_path.value().c_str(),
3436 output_path.value().c_str());
3437
3438 EXPECT_COMMAND(0,
3439 "diff test/data/atx_puk_certificate.bin %s",
3440 output_path.value().c_str());
3441 }
3442
TEST_F(AvbToolTest,MakeAtxPermanentAttributes)3443 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) {
3444 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
3445 EXPECT_COMMAND(
3446 0,
3447 "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
3448 pubkey_path.value().c_str());
3449
3450 base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
3451 EXPECT_COMMAND(0,
3452 "./avbtool.py make_atx_permanent_attributes"
3453 " --root_authority_key %s"
3454 " --product_id test/data/atx_product_id.bin"
3455 " --output %s",
3456 pubkey_path.value().c_str(),
3457 output_path.value().c_str());
3458
3459 EXPECT_COMMAND(0,
3460 "diff test/data/atx_permanent_attributes.bin %s",
3461 output_path.value().c_str());
3462 }
3463
TEST_F(AvbToolTest,MakeAtxMetadata)3464 TEST_F(AvbToolTest, MakeAtxMetadata) {
3465 base::FilePath output_path = testdir_.Append("tmp_metadata.bin");
3466
3467 EXPECT_COMMAND(
3468 0,
3469 "./avbtool.py make_atx_metadata"
3470 " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
3471 " --product_key_certificate test/data/atx_psk_certificate.bin"
3472 " --output %s",
3473 output_path.value().c_str());
3474
3475 EXPECT_COMMAND(
3476 0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str());
3477 }
3478
TEST_F(AvbToolTest,MakeAtxUnlockCredential)3479 TEST_F(AvbToolTest, MakeAtxUnlockCredential) {
3480 base::FilePath output_path = testdir_.Append("tmp_credential.bin");
3481
3482 EXPECT_COMMAND(
3483 0,
3484 "./avbtool.py make_atx_unlock_credential"
3485 " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
3486 " --unlock_key_certificate test/data/atx_puk_certificate.bin"
3487 " --challenge test/data/atx_unlock_challenge.bin"
3488 " --unlock_key test/data/testkey_atx_puk.pem"
3489 " --output %s",
3490 output_path.value().c_str());
3491
3492 EXPECT_COMMAND(0,
3493 "diff test/data/atx_unlock_credential.bin %s",
3494 output_path.value().c_str());
3495 }
3496
3497 } // namespace avb
3498