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