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