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: 46 AvbToolTest() {} 47 48 virtual void SetUp() override { 49 BaseAvbToolTest::SetUp(); 50 ops_.set_partition_dir(testdir_); 51 ops_.set_stored_rollback_indexes({{0, 0}, {1, 0}, {2, 0}, {3, 0}}); 52 ops_.set_stored_is_device_unlocked(false); 53 } 54 55 void AddHashFooterTest(bool sparse_image); 56 void AddHashtreeFooterTest(bool sparse_image); 57 void AddHashtreeFooterFECTest(bool sparse_image); 58 59 void GenerateImageWithHashAndHashtreeSetup(); 60 61 FakeAvbOps ops_; 62 }; 63 64 // This test ensure that the version is increased in both 65 // avb_boot_image.h and the avb tool. 66 TEST_F(AvbToolTest, AvbVersionInSync) { 67 base::FilePath path = testdir_.Append("version.txt"); 68 EXPECT_COMMAND(0, "./avbtool version > %s", path.value().c_str()); 69 std::string printed_version; 70 ASSERT_TRUE(base::ReadFileToString(path, &printed_version)); 71 base::TrimWhitespaceASCII(printed_version, base::TRIM_ALL, &printed_version); 72 // See comments in libavb/avb_version.c and avbtool's get_release_string() 73 // about being in sync. 74 EXPECT_EQ(printed_version, 75 std::string("avbtool ") + std::string(avb_version_string())); 76 } 77 78 TEST_F(AvbToolTest, DefaultReleaseString) { 79 GenerateVBMetaImage("vbmeta.img", 80 "SHA256_RSA2048", 81 0, 82 base::FilePath("test/data/testkey_rsa2048.pem")); 83 84 // Default release string is "avbtool " + avb_version_string(). 85 AvbVBMetaImageHeader h; 86 avb_vbmeta_image_header_to_host_byte_order( 87 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 88 EXPECT_EQ(std::string("avbtool ") + std::string(avb_version_string()), 89 std::string((const char*)h.release_string)); 90 } 91 92 TEST_F(AvbToolTest, ReleaseStringAppend) { 93 GenerateVBMetaImage("vbmeta.img", 94 "SHA256_RSA2048", 95 0, 96 base::FilePath("test/data/testkey_rsa2048.pem"), 97 "--append_to_release_string \"Woot XYZ\""); 98 99 // Note that avbtool inserts the space by itself. 100 std::string expected_str = 101 std::string("avbtool ") + std::string(avb_version_string()) + " Woot XYZ"; 102 103 AvbVBMetaImageHeader h; 104 avb_vbmeta_image_header_to_host_byte_order( 105 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 106 EXPECT_EQ(expected_str, std::string((const char*)h.release_string)); 107 } 108 109 TEST_F(AvbToolTest, ReleaseStringAppendTruncated) { 110 // Append enough text that truncation is sure to happen. 111 std::string append_str = "0123456789abcdef0123456789abcdef0123456789abcdef"; 112 std::string expected_str = std::string("avbtool ") + 113 std::string(avb_version_string()) + " " + 114 append_str; 115 EXPECT_GT(expected_str.size(), (size_t)(AVB_RELEASE_STRING_SIZE - 1)); 116 expected_str.resize(AVB_RELEASE_STRING_SIZE - 1); 117 118 GenerateVBMetaImage( 119 "vbmeta.img", 120 "SHA256_RSA2048", 121 0, 122 base::FilePath("test/data/testkey_rsa2048.pem"), 123 std::string("--append_to_release_string \"") + append_str + "\""); 124 125 // This checks that it ends with a NUL byte. 126 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 127 avb_vbmeta_image_verify( 128 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr)); 129 130 // For good measure we also check here. 131 AvbVBMetaImageHeader h; 132 avb_vbmeta_image_header_to_host_byte_order( 133 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 134 EXPECT_EQ(expected_str, std::string((const char*)h.release_string)); 135 } 136 137 TEST_F(AvbToolTest, ExtractPublicKey) { 138 GenerateVBMetaImage("vbmeta.img", 139 "SHA256_RSA2048", 140 0, 141 base::FilePath("test/data/testkey_rsa2048.pem"), 142 "--internal_release_string \"\""); 143 144 std::string key_data = 145 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")); 146 147 AvbVBMetaImageHeader h; 148 avb_vbmeta_image_header_to_host_byte_order( 149 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 150 uint8_t* d = reinterpret_cast<uint8_t*>(vbmeta_image_.data()); 151 size_t auxiliary_data_block_offset = 152 sizeof(AvbVBMetaImageHeader) + h.authentication_data_block_size; 153 EXPECT_GT(h.auxiliary_data_block_size, key_data.size()); 154 EXPECT_EQ(0, 155 memcmp(key_data.data(), 156 d + auxiliary_data_block_offset + h.public_key_offset, 157 key_data.size())); 158 } 159 160 TEST_F(AvbToolTest, CheckDescriptors) { 161 GenerateVBMetaImage("vbmeta.img", 162 "SHA256_RSA2048", 163 0, 164 base::FilePath("test/data/testkey_rsa2048.pem"), 165 "--prop foo:brillo " 166 "--prop bar:chromeos " 167 "--prop prisoner:24601 " 168 "--prop hexnumber:0xcafe " 169 "--prop hexnumber_capital:0xCAFE " 170 "--prop large_hexnumber:0xfedcba9876543210 " 171 "--prop larger_than_uint64:0xfedcba98765432101 " 172 "--prop almost_a_number:423x " 173 "--prop_from_file blob:test/data/small_blob.bin " 174 "--internal_release_string \"\""); 175 176 AvbVBMetaImageHeader h; 177 avb_vbmeta_image_header_to_host_byte_order( 178 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 179 180 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 181 avb_vbmeta_image_verify( 182 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr)); 183 184 const char* s; 185 size_t len; 186 uint64_t val; 187 188 // Basic. 189 s = avb_property_lookup( 190 vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &len); 191 EXPECT_EQ(0, strcmp(s, "brillo")); 192 EXPECT_EQ(6U, len); 193 s = avb_property_lookup( 194 vbmeta_image_.data(), vbmeta_image_.size(), "bar", 0, &len); 195 EXPECT_EQ(0, strcmp(s, "chromeos")); 196 EXPECT_EQ(8U, len); 197 s = avb_property_lookup( 198 vbmeta_image_.data(), vbmeta_image_.size(), "non-existant", 0, &len); 199 EXPECT_EQ(0U, len); 200 EXPECT_EQ(NULL, s); 201 202 // Numbers. 203 EXPECT_NE( 204 0, 205 avb_property_lookup_uint64( 206 vbmeta_image_.data(), vbmeta_image_.size(), "prisoner", 0, &val)); 207 EXPECT_EQ(24601U, val); 208 209 EXPECT_NE( 210 0, 211 avb_property_lookup_uint64( 212 vbmeta_image_.data(), vbmeta_image_.size(), "hexnumber", 0, &val)); 213 EXPECT_EQ(0xcafeU, val); 214 215 EXPECT_NE(0, 216 avb_property_lookup_uint64(vbmeta_image_.data(), 217 vbmeta_image_.size(), 218 "hexnumber_capital", 219 0, 220 &val)); 221 EXPECT_EQ(0xcafeU, val); 222 223 EXPECT_NE(0, 224 avb_property_lookup_uint64(vbmeta_image_.data(), 225 vbmeta_image_.size(), 226 "large_hexnumber", 227 0, 228 &val)); 229 EXPECT_EQ(0xfedcba9876543210U, val); 230 231 // We could catch overflows and return an error ... but we currently don't. 232 EXPECT_NE(0, 233 avb_property_lookup_uint64(vbmeta_image_.data(), 234 vbmeta_image_.size(), 235 "larger_than_uint64", 236 0, 237 &val)); 238 EXPECT_EQ(0xedcba98765432101U, val); 239 240 // Number-parsing failures. 241 EXPECT_EQ(0, 242 avb_property_lookup_uint64( 243 vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &val)); 244 245 EXPECT_EQ(0, 246 avb_property_lookup_uint64(vbmeta_image_.data(), 247 vbmeta_image_.size(), 248 "almost_a_number", 249 0, 250 &val)); 251 252 // Blobs. 253 // 254 // test/data/small_blob.bin is 21 byte file full of NUL-bytes except 255 // for the string "brillo ftw!" at index 2 and '\n' at the last 256 // byte. 257 s = avb_property_lookup( 258 vbmeta_image_.data(), vbmeta_image_.size(), "blob", 0, &len); 259 EXPECT_EQ(21U, len); 260 EXPECT_EQ(0, memcmp(s, "\0\0", 2)); 261 EXPECT_EQ(0, memcmp(s + 2, "brillo ftw!", 11)); 262 EXPECT_EQ(0, memcmp(s + 13, "\0\0\0\0\0\0\0", 7)); 263 EXPECT_EQ('\n', s[20]); 264 } 265 266 TEST_F(AvbToolTest, Padding) { 267 GenerateVBMetaImage("vbmeta.img", 268 "SHA256_RSA2048", 269 0, 270 base::FilePath("test/data/testkey_rsa2048.pem"), 271 "--internal_release_string \"\""); 272 273 GenerateVBMetaImage("vbmeta_padded.img", 274 "SHA256_RSA2048", 275 0, 276 base::FilePath("test/data/testkey_rsa2048.pem"), 277 "--internal_release_string \"\" --padding_size 4096"); 278 279 base::FilePath vbmeta_path = testdir_.Append("vbmeta.img"); 280 base::FilePath vbmeta_padded_path = testdir_.Append("vbmeta_padded.img"); 281 int64_t vbmeta_size, vbmeta_padded_size; 282 ASSERT_TRUE(base::GetFileSize(vbmeta_path, &vbmeta_size)); 283 ASSERT_TRUE(base::GetFileSize(vbmeta_padded_path, &vbmeta_padded_size)); 284 285 EXPECT_NE(vbmeta_size, vbmeta_padded_size); 286 287 // The padded size should be a multiple of 4096. 288 EXPECT_EQ(vbmeta_padded_size % 4096, 0); 289 290 // When rounded up the unpadded size should equal the padded size. 291 int64_t vbmeta_size_rounded_up = ((vbmeta_size + 4095) / 4096) * 4096; 292 EXPECT_EQ(vbmeta_size_rounded_up, vbmeta_padded_size); 293 } 294 295 TEST_F(AvbToolTest, CheckRollbackIndex) { 296 uint64_t rollback_index = 42; 297 GenerateVBMetaImage("vbmeta.img", 298 "SHA256_RSA2048", 299 rollback_index, 300 base::FilePath("test/data/testkey_rsa2048.pem"), 301 "--internal_release_string \"\""); 302 303 AvbVBMetaImageHeader h; 304 avb_vbmeta_image_header_to_host_byte_order( 305 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 306 307 EXPECT_EQ(rollback_index, h.rollback_index); 308 } 309 310 TEST_F(AvbToolTest, CheckPubkeyReturned) { 311 GenerateVBMetaImage("vbmeta.img", 312 "SHA256_RSA2048", 313 0, 314 base::FilePath("test/data/testkey_rsa2048.pem"), 315 "--internal_release_string \"\""); 316 317 const uint8_t* pubkey = NULL; 318 size_t pubkey_length = 0; 319 320 EXPECT_EQ( 321 AVB_VBMETA_VERIFY_RESULT_OK, 322 avb_vbmeta_image_verify( 323 vbmeta_image_.data(), vbmeta_image_.size(), &pubkey, &pubkey_length)); 324 325 AvbVBMetaImageHeader h; 326 avb_vbmeta_image_header_to_host_byte_order( 327 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 328 329 EXPECT_EQ(pubkey_length, h.public_key_size); 330 331 const uint8_t* expected_pubkey = 332 vbmeta_image_.data() + sizeof(AvbVBMetaImageHeader) + 333 h.authentication_data_block_size + h.public_key_offset; 334 EXPECT_EQ(pubkey, expected_pubkey); 335 } 336 337 TEST_F(AvbToolTest, Info) { 338 GenerateVBMetaImage("vbmeta.img", 339 "SHA256_RSA2048", 340 0, 341 base::FilePath("test/data/testkey_rsa2048.pem"), 342 "--prop foo:brillo " 343 "--prop bar:chromeos " 344 "--prop prisoner:24601 " 345 "--prop hexnumber:0xcafe " 346 "--prop hexnumber_capital:0xCAFE " 347 "--prop large_hexnumber:0xfedcba9876543210 " 348 "--prop larger_than_uint64:0xfedcba98765432101 " 349 "--prop almost_a_number:423x " 350 "--prop_from_file blob:test/data/small_blob.bin " 351 "--prop_from_file large_blob:test/data/large_blob.bin " 352 "--internal_release_string \"\""); 353 354 ASSERT_EQ( 355 "Minimum libavb version: 1.0\n" 356 "Header Block: 256 bytes\n" 357 "Authentication Block: 320 bytes\n" 358 "Auxiliary Block: 3200 bytes\n" 359 "Algorithm: SHA256_RSA2048\n" 360 "Rollback Index: 0\n" 361 "Flags: 0\n" 362 "Release String: ''\n" 363 "Descriptors:\n" 364 " Prop: foo -> 'brillo'\n" 365 " Prop: bar -> 'chromeos'\n" 366 " Prop: prisoner -> '24601'\n" 367 " Prop: hexnumber -> '0xcafe'\n" 368 " Prop: hexnumber_capital -> '0xCAFE'\n" 369 " Prop: large_hexnumber -> '0xfedcba9876543210'\n" 370 " Prop: larger_than_uint64 -> '0xfedcba98765432101'\n" 371 " Prop: almost_a_number -> '423x'\n" 372 " Prop: blob -> '\\x00\\x00brillo " 373 "ftw!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n'\n" 374 " Prop: large_blob -> (2048 bytes)\n", 375 InfoImage(vbmeta_image_path_)); 376 } 377 378 static bool collect_descriptors(const AvbDescriptor* descriptor, 379 void* user_data) { 380 std::vector<const AvbDescriptor*>* descriptors = 381 reinterpret_cast<std::vector<const AvbDescriptor*>*>(user_data); 382 descriptors->push_back(descriptor); 383 return true; // Keep iterating. 384 } 385 386 static std::string AddHashFooterGetExpectedVBMetaInfo( 387 const bool sparse_image, const uint64_t partition_size) { 388 return base::StringPrintf( 389 "Footer version: 1.0\n" 390 "Image size: %" PRIu64 391 " bytes\n" 392 "Original image size: 1052672 bytes\n" 393 "VBMeta offset: 1052672\n" 394 "VBMeta size: 1280 bytes\n" 395 "--\n" 396 "Minimum libavb version: 1.0%s\n" 397 "Header Block: 256 bytes\n" 398 "Authentication Block: 320 bytes\n" 399 "Auxiliary Block: 704 bytes\n" 400 "Algorithm: SHA256_RSA2048\n" 401 "Rollback Index: 0\n" 402 "Flags: 0\n" 403 "Release String: ''\n" 404 "Descriptors:\n" 405 " Hash descriptor:\n" 406 " Image Size: 1052672 bytes\n" 407 " Hash Algorithm: sha256\n" 408 " Partition Name: foobar\n" 409 " Salt: d00df00d\n" 410 " Digest: " 411 "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f" 412 "5e4ed357fbcf58d88d9\n", 413 partition_size, 414 sparse_image ? " (Sparse)" : ""); 415 } 416 417 void AvbToolTest::AddHashFooterTest(bool sparse_image) { 418 const size_t rootfs_size = 1028 * 1024; 419 const size_t partition_size = 1536 * 1024; 420 const size_t resized_partition_size = 1280 * 1024; 421 422 // Generate a 1028 KiB file with known content. Some content have 423 // been arranged to ensure FILL_DATA segments in the sparse file. 424 std::vector<uint8_t> rootfs; 425 rootfs.resize(rootfs_size); 426 for (size_t n = 0; n < rootfs_size; n++) { 427 if ((n >= 5 * 1000 && n < 105 * 1000) || 428 (n >= 205 * 1000 && n < 305 * 1000) || 429 (n >= 505 * 1000 && n < 605 * 1000)) { 430 rootfs[n] = uint8_t(n) & 0x03; 431 } else { 432 rootfs[n] = uint8_t(n); 433 } 434 } 435 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin"); 436 base::FilePath rootfs_path = testdir_.Append("rootfs.bin"); 437 EXPECT_EQ(rootfs_size, 438 static_cast<const size_t>( 439 base::WriteFile(rootfs_path, 440 reinterpret_cast<const char*>(rootfs.data()), 441 rootfs.size()))); 442 443 if (sparse_image) { 444 EXPECT_COMMAND(0, 445 "mv %s %s.unsparse", 446 rootfs_path.value().c_str(), 447 rootfs_path.value().c_str()); 448 EXPECT_COMMAND(0, 449 "img2simg %s.unsparse %s", 450 rootfs_path.value().c_str(), 451 rootfs_path.value().c_str()); 452 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str()); 453 } 454 455 /* Do this twice to check that 'add_hash_footer' is idempotent. */ 456 for (int n = 0; n < 2; n++) { 457 EXPECT_COMMAND(0, 458 "./avbtool add_hash_footer --salt d00df00d " 459 "--hash_algorithm sha256 --image %s " 460 "--partition_size %d --partition_name foobar " 461 "--algorithm SHA256_RSA2048 " 462 "--key test/data/testkey_rsa2048.pem " 463 "--output_vbmeta %s " 464 "--internal_release_string \"\"", 465 rootfs_path.value().c_str(), 466 (int)partition_size, 467 ext_vbmeta_path.value().c_str()); 468 469 ASSERT_EQ(AddHashFooterGetExpectedVBMetaInfo(sparse_image, partition_size), 470 InfoImage(rootfs_path)); 471 472 ASSERT_EQ( 473 "Minimum libavb version: 1.0\n" 474 "Header Block: 256 bytes\n" 475 "Authentication Block: 320 bytes\n" 476 "Auxiliary Block: 704 bytes\n" 477 "Algorithm: SHA256_RSA2048\n" 478 "Rollback Index: 0\n" 479 "Flags: 0\n" 480 "Release String: ''\n" 481 "Descriptors:\n" 482 " Hash descriptor:\n" 483 " Image Size: 1052672 bytes\n" 484 " Hash Algorithm: sha256\n" 485 " Partition Name: foobar\n" 486 " Salt: d00df00d\n" 487 " Digest: " 488 "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f" 489 "5e4ed357fbcf58d88d9\n", 490 InfoImage(ext_vbmeta_path)); 491 } 492 493 // Resize the image and check that the only thing that has changed 494 // is where the footer is. First check that resizing to a smaller 495 // size than the original rootfs fails. Then resize to something 496 // larger than the original rootfs but smaller than the current 497 // partition size. 498 EXPECT_COMMAND(1, 499 "./avbtool resize_image --image %s " 500 "--partition_size %d", 501 rootfs_path.value().c_str(), 502 (int)(rootfs_size - 16 * 1024)); 503 EXPECT_COMMAND(0, 504 "./avbtool resize_image --image %s " 505 "--partition_size %d", 506 rootfs_path.value().c_str(), 507 (int)resized_partition_size); 508 ASSERT_EQ( 509 AddHashFooterGetExpectedVBMetaInfo(sparse_image, resized_partition_size), 510 InfoImage(rootfs_path)); 511 512 if (sparse_image) { 513 EXPECT_COMMAND(0, 514 "mv %s %s.sparse", 515 rootfs_path.value().c_str(), 516 rootfs_path.value().c_str()); 517 EXPECT_COMMAND(0, 518 "simg2img %s.sparse %s", 519 rootfs_path.value().c_str(), 520 rootfs_path.value().c_str()); 521 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str()); 522 } 523 524 // Manually calculate the hash to check that it agrees with avbtool. 525 AvbSHA256Ctx hasher_ctx; 526 const uint8_t hasher_salt[4] = {0xd0, 0x0d, 0xf0, 0x0d}; 527 avb_sha256_init(&hasher_ctx); 528 avb_sha256_update(&hasher_ctx, hasher_salt, 4); 529 avb_sha256_update(&hasher_ctx, rootfs.data(), rootfs_size); 530 uint8_t* hasher_digest = avb_sha256_final(&hasher_ctx); 531 EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9", 532 mem_to_hexstring(hasher_digest, AVB_SHA256_DIGEST_SIZE)); 533 534 // Now check that we can find the VBMeta block again from the footer. 535 std::string part_data; 536 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data)); 537 538 // Check footer contains correct data. 539 AvbFooter f; 540 EXPECT_NE(0, 541 avb_footer_validate_and_byteswap( 542 reinterpret_cast<const AvbFooter*>( 543 part_data.data() + part_data.size() - AVB_FOOTER_SIZE), 544 &f)); 545 EXPECT_EQ( 546 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN), 547 AVB_FOOTER_MAGIC); 548 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major); 549 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor); 550 EXPECT_EQ(1052672UL, f.original_image_size); 551 EXPECT_EQ(1052672UL, f.vbmeta_offset); 552 EXPECT_EQ(1280UL, f.vbmeta_size); 553 554 // Check that the vbmeta image at |f.vbmeta_offset| checks out. 555 const uint8_t* vbmeta_data = 556 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset); 557 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 558 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL)); 559 560 // Collect all descriptors. 561 std::vector<const AvbDescriptor*> descriptors; 562 avb_descriptor_foreach( 563 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors); 564 565 // We should only have a single descriptor and it should be a 566 // hash descriptor. 567 EXPECT_EQ(1UL, descriptors.size()); 568 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, avb_be64toh(descriptors[0]->tag)); 569 AvbHashDescriptor d; 570 EXPECT_NE( 571 0, 572 avb_hash_descriptor_validate_and_byteswap( 573 reinterpret_cast<const AvbHashDescriptor*>(descriptors[0]), &d)); 574 EXPECT_EQ(1052672UL, d.image_size); 575 EXPECT_EQ(6UL, d.partition_name_len); 576 EXPECT_EQ(4UL, d.salt_len); 577 EXPECT_EQ(32UL, d.digest_len); 578 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) + 579 sizeof(AvbHashDescriptor); 580 uint64_t o = 0; 581 EXPECT_EQ("foobar", 582 std::string(reinterpret_cast<const char*>(desc_end + o), 583 d.partition_name_len)); 584 o += d.partition_name_len; 585 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len)); 586 o += d.salt_len; 587 EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9", 588 mem_to_hexstring(desc_end + o, d.digest_len)); 589 590 // Check that the footer is correctly erased. 591 EXPECT_COMMAND( 592 0, "./avbtool erase_footer --image %s", rootfs_path.value().c_str()); 593 int64_t erased_footer_file_size; 594 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size)); 595 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size); 596 597 // Check that --do_not_append_vbmeta_image works as intended. 598 EXPECT_COMMAND(0, 599 "./avbtool add_hash_footer --salt d00df00d " 600 "--hash_algorithm sha256 --image %s " 601 "--partition_size %d --partition_name foobar " 602 "--algorithm SHA256_RSA2048 " 603 "--key test/data/testkey_rsa2048.pem " 604 "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image " 605 "--internal_release_string \"\"", 606 rootfs_path.value().c_str(), 607 (int)partition_size, 608 ext_vbmeta_path.value().c_str()); 609 int64_t file_size; 610 ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size)); 611 EXPECT_EQ(static_cast<size_t>(file_size), rootfs_size); 612 EXPECT_COMMAND(0, 613 "diff %s %s_2nd_run", 614 ext_vbmeta_path.value().c_str(), 615 ext_vbmeta_path.value().c_str()); 616 } 617 618 TEST_F(AvbToolTest, AddHashFooter) { 619 AddHashFooterTest(false); 620 } 621 622 TEST_F(AvbToolTest, AddHashFooterSparse) { 623 AddHashFooterTest(true); 624 } 625 626 static std::string RemoveLinesStartingWith(const std::string& str, 627 const std::string& prefix) { 628 std::vector<std::string> lines; 629 std::string ret; 630 631 lines = base::SplitString( 632 str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); 633 for (const std::string& line : lines) { 634 if (!base::StartsWith(line, prefix, base::CompareCase::SENSITIVE)) { 635 ret += line; 636 ret += '\n'; 637 } 638 } 639 return ret; 640 } 641 642 TEST_F(AvbToolTest, AddHashFooterSparseWithHoleAtTheEnd) { 643 const size_t partition_size = 10 * 1024 * 1024; 644 const size_t metadata_size = 128 * 1024; 645 646 // It's not enough to run img2simg on a file with a lot of zeroes at 647 // the end since that will turn up as "Fill with value (for value = 648 // 0x00000000)" and not "Don't care". Instead, use make_ext4fs for 649 // this since it will put a big hole (e.g. "Don't care" chunk) at 650 // the end. 651 base::FilePath partition_path = testdir_.Append("partition.bin"); 652 EXPECT_COMMAND(0, 653 "make_ext4fs -s -L test -l %zd %s", 654 partition_size - metadata_size, 655 partition_path.value().c_str()); 656 657 EXPECT_COMMAND(0, 658 "./avbtool add_hash_footer --salt d00df00d " 659 "--hash_algorithm sha256 --image %s " 660 "--partition_size %d --partition_name foobar " 661 "--algorithm SHA256_RSA2048 " 662 "--key test/data/testkey_rsa2048.pem " 663 "--internal_release_string \"\"", 664 partition_path.value().c_str(), 665 (int)partition_size); 666 667 // Since we may be using an arbritary version of make_ext4fs 668 // (because of different branches) the contents of the resulting 669 // disk image may slightly change. It's enough to just remove the 670 // "Digest:" line from the output to work around this. 671 std::string info = 672 RemoveLinesStartingWith(InfoImage(partition_path), " Digest:"); 673 ASSERT_EQ( 674 "Footer version: 1.0\n" 675 "Image size: 10485760 bytes\n" 676 "Original image size: 10354688 bytes\n" 677 "VBMeta offset: 10354688\n" 678 "VBMeta size: 1280 bytes\n" 679 "--\n" 680 "Minimum libavb version: 1.0 (Sparse)\n" 681 "Header Block: 256 bytes\n" 682 "Authentication Block: 320 bytes\n" 683 "Auxiliary Block: 704 bytes\n" 684 "Algorithm: SHA256_RSA2048\n" 685 "Rollback Index: 0\n" 686 "Flags: 0\n" 687 "Release String: ''\n" 688 "Descriptors:\n" 689 " Hash descriptor:\n" 690 " Image Size: 10354688 bytes\n" 691 " Hash Algorithm: sha256\n" 692 " Partition Name: foobar\n" 693 " Salt: d00df00d\n", 694 info); 695 696 EXPECT_COMMAND(0, 697 "mv %s %s.sparse", 698 partition_path.value().c_str(), 699 partition_path.value().c_str()); 700 EXPECT_COMMAND(0, 701 "simg2img %s.sparse %s", 702 partition_path.value().c_str(), 703 partition_path.value().c_str()); 704 EXPECT_COMMAND(0, "rm -f %s.sparse", partition_path.value().c_str()); 705 } 706 707 TEST_F(AvbToolTest, AddHashFooterCalcMaxImageSize) { 708 const size_t partition_size = 10 * 1024 * 1024; 709 base::FilePath output_path = testdir_.Append("max_size.txt"); 710 711 EXPECT_COMMAND(0, 712 "./avbtool add_hash_footer " 713 "--partition_size %zd " 714 "--calc_max_image_size > %s", 715 partition_size, 716 output_path.value().c_str()); 717 std::string max_image_size_data; 718 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data)); 719 EXPECT_EQ("10416128\n", max_image_size_data); 720 size_t max_image_size = atoll(max_image_size_data.c_str()); 721 722 // Metadata takes up 68 KiB. 723 EXPECT_EQ(68 * 1024ULL, partition_size - max_image_size); 724 725 // Check that we can add a hash footer for an image this size for 726 // such a partition size. 727 base::FilePath boot_path = GenerateImage("boot", max_image_size); 728 EXPECT_COMMAND(0, 729 "./avbtool add_hash_footer" 730 " --image %s" 731 " --partition_name boot" 732 " --partition_size %zd" 733 " --salt deadbeef" 734 " --algorithm SHA512_RSA4096 " 735 " --key test/data/testkey_rsa4096.pem" 736 " --internal_release_string \"\"", 737 boot_path.value().c_str(), 738 partition_size); 739 } 740 741 void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) { 742 const size_t rootfs_size = 1028 * 1024; 743 const size_t partition_size = 1536 * 1024; 744 745 // Generate a 1028 KiB file with known content. 746 std::vector<uint8_t> rootfs; 747 rootfs.resize(rootfs_size); 748 for (size_t n = 0; n < rootfs_size; n++) 749 rootfs[n] = uint8_t(n); 750 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin"); 751 base::FilePath rootfs_path = testdir_.Append("rootfs.bin"); 752 EXPECT_EQ(rootfs_size, 753 static_cast<const size_t>( 754 base::WriteFile(rootfs_path, 755 reinterpret_cast<const char*>(rootfs.data()), 756 rootfs.size()))); 757 758 if (sparse_image) { 759 EXPECT_COMMAND(0, 760 "mv %s %s.unsparse", 761 rootfs_path.value().c_str(), 762 rootfs_path.value().c_str()); 763 EXPECT_COMMAND(0, 764 "img2simg %s.unsparse %s", 765 rootfs_path.value().c_str(), 766 rootfs_path.value().c_str()); 767 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str()); 768 } 769 770 /* Do this twice to check that 'add_hashtree_footer' is idempotent. */ 771 for (int n = 0; n < 2; n++) { 772 EXPECT_COMMAND(0, 773 "./avbtool add_hashtree_footer --salt d00df00d --image %s " 774 "--partition_size %d --partition_name foobar " 775 "--algorithm SHA256_RSA2048 " 776 "--key test/data/testkey_rsa2048.pem " 777 "--output_vbmeta_image %s " 778 "--internal_release_string \"\" " 779 "--do_not_generate_fec", 780 rootfs_path.value().c_str(), 781 (int)partition_size, 782 ext_vbmeta_path.value().c_str()); 783 784 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n" 785 "Image size: 1572864 bytes\n" 786 "Original image size: 1052672 bytes\n" 787 "VBMeta offset: 1069056\n" 788 "VBMeta size: 1344 bytes\n" 789 "--\n" 790 "Minimum libavb version: 1.0%s\n" 791 "Header Block: 256 bytes\n" 792 "Authentication Block: 320 bytes\n" 793 "Auxiliary Block: 768 bytes\n" 794 "Algorithm: SHA256_RSA2048\n" 795 "Rollback Index: 0\n" 796 "Flags: 0\n" 797 "Release String: ''\n" 798 "Descriptors:\n" 799 " Hashtree descriptor:\n" 800 " Version of dm-verity: 1\n" 801 " Image Size: 1052672 bytes\n" 802 " Tree Offset: 1052672\n" 803 " Tree Size: 16384 bytes\n" 804 " Data Block Size: 4096 bytes\n" 805 " Hash Block Size: 4096 bytes\n" 806 " FEC num roots: 0\n" 807 " FEC offset: 0\n" 808 " FEC size: 0 bytes\n" 809 " Hash Algorithm: sha1\n" 810 " Partition Name: foobar\n" 811 " Salt: d00df00d\n" 812 " Root Digest: " 813 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n", 814 sparse_image ? " (Sparse)" : ""), 815 InfoImage(rootfs_path)); 816 817 ASSERT_EQ( 818 "Minimum libavb version: 1.0\n" 819 "Header Block: 256 bytes\n" 820 "Authentication Block: 320 bytes\n" 821 "Auxiliary Block: 768 bytes\n" 822 "Algorithm: SHA256_RSA2048\n" 823 "Rollback Index: 0\n" 824 "Flags: 0\n" 825 "Release String: ''\n" 826 "Descriptors:\n" 827 " Hashtree descriptor:\n" 828 " Version of dm-verity: 1\n" 829 " Image Size: 1052672 bytes\n" 830 " Tree Offset: 1052672\n" 831 " Tree Size: 16384 bytes\n" 832 " Data Block Size: 4096 bytes\n" 833 " Hash Block Size: 4096 bytes\n" 834 " FEC num roots: 0\n" 835 " FEC offset: 0\n" 836 " FEC size: 0 bytes\n" 837 " Hash Algorithm: sha1\n" 838 " Partition Name: foobar\n" 839 " Salt: d00df00d\n" 840 " Root Digest: " 841 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n", 842 InfoImage(ext_vbmeta_path)); 843 } 844 845 if (sparse_image) { 846 EXPECT_COMMAND(0, 847 "mv %s %s.sparse", 848 rootfs_path.value().c_str(), 849 rootfs_path.value().c_str()); 850 EXPECT_COMMAND(0, 851 "simg2img %s.sparse %s", 852 rootfs_path.value().c_str(), 853 rootfs_path.value().c_str()); 854 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str()); 855 } 856 857 // To check that we generate the correct hashtree we can use 858 // veritysetup(1) - another codebase for working with dm-verity 859 // hashtrees - to verify it. 860 // 861 // If we don't want to impose the requirement of having the 862 // veritysetup(1) command available on builders we can comment this 863 // out. 864 EXPECT_COMMAND(0, 865 "veritysetup --no-superblock --format=1 --hash=sha1 " 866 "--data-block-size=4096 --hash-block-size=4096 " 867 "--salt=d00df00d " 868 "--data-blocks=257 " 869 "--hash-offset=1052672 " 870 "verify " 871 "%s %s " 872 "e811611467dcd6e8dc4324e45f706c2bdd51db67", 873 rootfs_path.value().c_str(), 874 rootfs_path.value().c_str()); 875 876 // Now check that we can find the VBMeta block again from the footer. 877 std::string part_data; 878 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data)); 879 880 // Check footer contains correct data. 881 AvbFooter f; 882 EXPECT_NE(0, 883 avb_footer_validate_and_byteswap( 884 reinterpret_cast<const AvbFooter*>( 885 part_data.data() + part_data.size() - AVB_FOOTER_SIZE), 886 &f)); 887 EXPECT_EQ( 888 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN), 889 AVB_FOOTER_MAGIC); 890 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major); 891 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor); 892 EXPECT_EQ(1052672UL, f.original_image_size); 893 EXPECT_EQ(1069056UL, f.vbmeta_offset); 894 EXPECT_EQ(1344UL, f.vbmeta_size); 895 896 // Check that the vbmeta image at |f.vbmeta_offset| checks out. 897 const uint8_t* vbmeta_data = 898 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset); 899 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 900 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL)); 901 902 // Collect all descriptors. 903 std::vector<const AvbDescriptor*> descriptors; 904 avb_descriptor_foreach( 905 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors); 906 907 // We should only have a single descriptor and it should be a 908 // hashtree descriptor. 909 EXPECT_EQ(1UL, descriptors.size()); 910 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag)); 911 AvbHashtreeDescriptor d; 912 EXPECT_NE( 913 0, 914 avb_hashtree_descriptor_validate_and_byteswap( 915 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d)); 916 EXPECT_EQ(1UL, d.dm_verity_version); 917 EXPECT_EQ(1052672UL, d.image_size); 918 EXPECT_EQ(1052672UL, d.tree_offset); 919 EXPECT_EQ(16384UL, d.tree_size); 920 EXPECT_EQ(4096UL, d.data_block_size); 921 EXPECT_EQ(4096UL, d.hash_block_size); 922 EXPECT_EQ(6UL, d.partition_name_len); 923 EXPECT_EQ(4UL, d.salt_len); 924 EXPECT_EQ(20UL, d.root_digest_len); 925 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) + 926 sizeof(AvbHashtreeDescriptor); 927 uint64_t o = 0; 928 EXPECT_EQ("foobar", 929 std::string(reinterpret_cast<const char*>(desc_end + o), 930 d.partition_name_len)); 931 o += d.partition_name_len; 932 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len)); 933 o += d.salt_len; 934 EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67", 935 mem_to_hexstring(desc_end + o, d.root_digest_len)); 936 937 // Check that we correctly generate dm-verity kernel cmdline 938 // snippets, if requested. 939 base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin"); 940 EXPECT_COMMAND(0, 941 "./avbtool make_vbmeta_image " 942 "--output %s " 943 "--setup_rootfs_from_kernel %s " 944 "--algorithm SHA256_RSA2048 " 945 "--key test/data/testkey_rsa2048.pem " 946 "--internal_release_string \"\"", 947 vbmeta_dmv_path.value().c_str(), 948 rootfs_path.value().c_str()); 949 950 ASSERT_EQ( 951 "Minimum libavb version: 1.0\n" 952 "Header Block: 256 bytes\n" 953 "Authentication Block: 320 bytes\n" 954 "Auxiliary Block: 896 bytes\n" 955 "Algorithm: SHA256_RSA2048\n" 956 "Rollback Index: 0\n" 957 "Flags: 0\n" 958 "Release String: ''\n" 959 "Descriptors:\n" 960 " Kernel Cmdline descriptor:\n" 961 " Flags: 1\n" 962 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 " 963 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) " 964 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 " 965 "d00df00d 2 $(ANDROID_VERITY_MODE) ignore_zero_blocks\" root=/dev/dm-0'\n" 966 " Kernel Cmdline descriptor:\n" 967 " Flags: 2\n" 968 " Kernel Cmdline: " 969 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n", 970 InfoImage(vbmeta_dmv_path)); 971 972 // Check that the footer is correctly erased and the hashtree 973 // remains - see above for why the constant 1069056 is used. 974 EXPECT_COMMAND(0, 975 "./avbtool erase_footer --image %s --keep_hashtree", 976 rootfs_path.value().c_str()); 977 int64_t erased_footer_file_size; 978 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size)); 979 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1069056UL); 980 981 // Check that --do_not_append_vbmeta_image works as intended. 982 // 983 // For this we need to reset the size of the image to the original 984 // size because it's not possible to identify the existing hashtree. 985 EXPECT_COMMAND( 986 0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str()); 987 EXPECT_COMMAND(0, 988 "./avbtool add_hashtree_footer --salt d00df00d --image %s " 989 "--partition_size %d --partition_name foobar " 990 "--algorithm SHA256_RSA2048 " 991 "--key test/data/testkey_rsa2048.pem " 992 "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image " 993 "--internal_release_string \"\" " 994 "--do_not_generate_fec", 995 rootfs_path.value().c_str(), 996 (int)partition_size, 997 ext_vbmeta_path.value().c_str()); 998 int64_t file_size; 999 ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size)); 1000 EXPECT_EQ(static_cast<size_t>(file_size), 1069056UL); 1001 EXPECT_COMMAND(0, 1002 "diff %s %s_2nd_run", 1003 ext_vbmeta_path.value().c_str(), 1004 ext_vbmeta_path.value().c_str()); 1005 } 1006 1007 TEST_F(AvbToolTest, AddHashtreeFooter) { 1008 AddHashtreeFooterTest(false); 1009 } 1010 1011 TEST_F(AvbToolTest, AddHashtreeFooterSparse) { 1012 AddHashtreeFooterTest(true); 1013 } 1014 1015 void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) { 1016 const size_t rootfs_size = 1028 * 1024; 1017 const size_t partition_size = 1536 * 1024; 1018 1019 // Generate a 1028 KiB file with known content. 1020 std::vector<uint8_t> rootfs; 1021 rootfs.resize(rootfs_size); 1022 for (size_t n = 0; n < rootfs_size; n++) 1023 rootfs[n] = uint8_t(n); 1024 base::FilePath rootfs_path = testdir_.Append("rootfs.bin"); 1025 EXPECT_EQ(rootfs_size, 1026 static_cast<const size_t>( 1027 base::WriteFile(rootfs_path, 1028 reinterpret_cast<const char*>(rootfs.data()), 1029 rootfs.size()))); 1030 1031 if (sparse_image) { 1032 EXPECT_COMMAND(0, 1033 "mv %s %s.unsparse", 1034 rootfs_path.value().c_str(), 1035 rootfs_path.value().c_str()); 1036 EXPECT_COMMAND(0, 1037 "img2simg %s.unsparse %s", 1038 rootfs_path.value().c_str(), 1039 rootfs_path.value().c_str()); 1040 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str()); 1041 } 1042 1043 /* Do this twice to check that 'add_hashtree_footer' is idempotent. */ 1044 for (int n = 0; n < 2; n++) { 1045 EXPECT_COMMAND(0, 1046 "./avbtool add_hashtree_footer --salt d00df00d --image %s " 1047 "--partition_size %d --partition_name foobar " 1048 "--algorithm SHA256_RSA2048 " 1049 "--key test/data/testkey_rsa2048.pem " 1050 "--internal_release_string \"\"", 1051 rootfs_path.value().c_str(), 1052 (int)partition_size); 1053 1054 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n" 1055 "Image size: 1572864 bytes\n" 1056 "Original image size: 1052672 bytes\n" 1057 "VBMeta offset: 1085440\n" 1058 "VBMeta size: 1344 bytes\n" 1059 "--\n" 1060 "Minimum libavb version: 1.0%s\n" 1061 "Header Block: 256 bytes\n" 1062 "Authentication Block: 320 bytes\n" 1063 "Auxiliary Block: 768 bytes\n" 1064 "Algorithm: SHA256_RSA2048\n" 1065 "Rollback Index: 0\n" 1066 "Flags: 0\n" 1067 "Release String: ''\n" 1068 "Descriptors:\n" 1069 " Hashtree descriptor:\n" 1070 " Version of dm-verity: 1\n" 1071 " Image Size: 1052672 bytes\n" 1072 " Tree Offset: 1052672\n" 1073 " Tree Size: 16384 bytes\n" 1074 " Data Block Size: 4096 bytes\n" 1075 " Hash Block Size: 4096 bytes\n" 1076 " FEC num roots: 2\n" 1077 " FEC offset: 1069056\n" 1078 " FEC size: 16384 bytes\n" 1079 " Hash Algorithm: sha1\n" 1080 " Partition Name: foobar\n" 1081 " Salt: d00df00d\n" 1082 " Root Digest: " 1083 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n", 1084 sparse_image ? " (Sparse)" : ""), 1085 InfoImage(rootfs_path)); 1086 } 1087 1088 if (sparse_image) { 1089 EXPECT_COMMAND(0, 1090 "mv %s %s.sparse", 1091 rootfs_path.value().c_str(), 1092 rootfs_path.value().c_str()); 1093 EXPECT_COMMAND(0, 1094 "simg2img %s.sparse %s", 1095 rootfs_path.value().c_str(), 1096 rootfs_path.value().c_str()); 1097 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str()); 1098 } 1099 1100 /* TODO: would be nice to verify that the FEC data is correct. */ 1101 1102 // Now check that we can find the VBMeta block again from the footer. 1103 std::string part_data; 1104 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data)); 1105 1106 // Check footer contains correct data. 1107 AvbFooter f; 1108 EXPECT_NE(0, 1109 avb_footer_validate_and_byteswap( 1110 reinterpret_cast<const AvbFooter*>( 1111 part_data.data() + part_data.size() - AVB_FOOTER_SIZE), 1112 &f)); 1113 EXPECT_EQ( 1114 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN), 1115 AVB_FOOTER_MAGIC); 1116 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major); 1117 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor); 1118 EXPECT_EQ(1052672UL, f.original_image_size); 1119 EXPECT_EQ(1085440UL, f.vbmeta_offset); 1120 EXPECT_EQ(1344UL, f.vbmeta_size); 1121 1122 // Check that the vbmeta image at |f.vbmeta_offset| checks out. 1123 const uint8_t* vbmeta_data = 1124 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset); 1125 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 1126 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL)); 1127 1128 // Collect all descriptors. 1129 std::vector<const AvbDescriptor*> descriptors; 1130 avb_descriptor_foreach( 1131 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors); 1132 1133 // We should only have a single descriptor and it should be a 1134 // hashtree descriptor. 1135 EXPECT_EQ(1UL, descriptors.size()); 1136 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag)); 1137 AvbHashtreeDescriptor d; 1138 EXPECT_NE( 1139 0, 1140 avb_hashtree_descriptor_validate_and_byteswap( 1141 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d)); 1142 EXPECT_EQ(1UL, d.dm_verity_version); 1143 EXPECT_EQ(1052672UL, d.image_size); 1144 EXPECT_EQ(1052672UL, d.tree_offset); 1145 EXPECT_EQ(16384UL, d.tree_size); 1146 EXPECT_EQ(4096UL, d.data_block_size); 1147 EXPECT_EQ(2UL, d.fec_num_roots); 1148 EXPECT_EQ(1069056UL, d.fec_offset); 1149 EXPECT_EQ(16384UL, d.fec_size); 1150 EXPECT_EQ(6UL, d.partition_name_len); 1151 EXPECT_EQ(4UL, d.salt_len); 1152 EXPECT_EQ(20UL, d.root_digest_len); 1153 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) + 1154 sizeof(AvbHashtreeDescriptor); 1155 uint64_t o = 0; 1156 EXPECT_EQ("foobar", 1157 std::string(reinterpret_cast<const char*>(desc_end + o), 1158 d.partition_name_len)); 1159 o += d.partition_name_len; 1160 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len)); 1161 o += d.salt_len; 1162 EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67", 1163 mem_to_hexstring(desc_end + o, d.root_digest_len)); 1164 1165 // Check that we correctly generate dm-verity kernel cmdline 1166 // snippets, if requested. 1167 base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin"); 1168 EXPECT_COMMAND(0, 1169 "./avbtool make_vbmeta_image " 1170 "--output %s " 1171 "--setup_rootfs_from_kernel %s " 1172 "--algorithm SHA256_RSA2048 " 1173 "--key test/data/testkey_rsa2048.pem " 1174 "--internal_release_string \"\"", 1175 vbmeta_dmv_path.value().c_str(), 1176 rootfs_path.value().c_str()); 1177 1178 ASSERT_EQ( 1179 "Minimum libavb version: 1.0\n" 1180 "Header Block: 256 bytes\n" 1181 "Authentication Block: 320 bytes\n" 1182 "Auxiliary Block: 960 bytes\n" 1183 "Algorithm: SHA256_RSA2048\n" 1184 "Rollback Index: 0\n" 1185 "Flags: 0\n" 1186 "Release String: ''\n" 1187 "Descriptors:\n" 1188 " Kernel Cmdline descriptor:\n" 1189 " Flags: 1\n" 1190 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 " 1191 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) " 1192 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 " 1193 "d00df00d 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks " 1194 "use_fec_from_device " 1195 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 261 " 1196 "fec_start 261\" root=/dev/dm-0'\n" 1197 " Kernel Cmdline descriptor:\n" 1198 " Flags: 2\n" 1199 " Kernel Cmdline: " 1200 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n", 1201 InfoImage(vbmeta_dmv_path)); 1202 1203 // Check that the footer is correctly erased and the hashtree and 1204 // FEC data remains. The constant 1085440 is used because it's where 1205 // the FEC data ends (it's at offset 1069056 and size 16384). 1206 EXPECT_COMMAND(0, 1207 "./avbtool erase_footer --image %s --keep_hashtree", 1208 rootfs_path.value().c_str()); 1209 int64_t erased_footer_file_size; 1210 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size)); 1211 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1085440UL); 1212 } 1213 1214 TEST_F(AvbToolTest, AddHashtreeFooterFEC) { 1215 AddHashtreeFooterFECTest(false); 1216 } 1217 1218 TEST_F(AvbToolTest, AddHashtreeFooterFECSparse) { 1219 AddHashtreeFooterFECTest(true); 1220 } 1221 1222 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSize) { 1223 const size_t partition_size = 10 * 1024 * 1024; 1224 base::FilePath output_path = testdir_.Append("max_size.txt"); 1225 1226 EXPECT_COMMAND(0, 1227 "./avbtool add_hashtree_footer " 1228 "--partition_size %zd --calc_max_image_size " 1229 "--do_not_generate_fec > %s", 1230 partition_size, 1231 output_path.value().c_str()); 1232 std::string max_image_size_data; 1233 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data)); 1234 EXPECT_EQ("10330112\n", max_image_size_data); 1235 size_t max_image_size = atoll(max_image_size_data.c_str()); 1236 1237 // Hashtree and metadata takes up 152 KiB - compare to below with 1238 // FEC which is 244 KiB. 1239 EXPECT_EQ(152 * 1024ULL, partition_size - max_image_size); 1240 1241 // Check that we can add a hashtree with an image this size for such 1242 // a partition size. 1243 base::FilePath system_path = GenerateImage("system", max_image_size); 1244 EXPECT_COMMAND(0, 1245 "./avbtool add_hashtree_footer" 1246 " --image %s" 1247 " --partition_name system" 1248 " --partition_size %zd" 1249 " --salt deadbeef" 1250 " --algorithm SHA512_RSA4096 " 1251 " --key test/data/testkey_rsa4096.pem" 1252 " --internal_release_string \"\" " 1253 "--do_not_generate_fec", 1254 system_path.value().c_str(), 1255 partition_size); 1256 } 1257 1258 TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) { 1259 const size_t partition_size = 10 * 1024 * 1024; 1260 base::FilePath output_path = testdir_.Append("max_size.txt"); 1261 1262 EXPECT_COMMAND(0, 1263 "./avbtool add_hashtree_footer " 1264 "--partition_size %zd --calc_max_image_size > %s", 1265 partition_size, 1266 output_path.value().c_str()); 1267 std::string max_image_size_data; 1268 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data)); 1269 EXPECT_EQ("10235904\n", max_image_size_data); 1270 size_t max_image_size = atoll(max_image_size_data.c_str()); 1271 1272 // Hashtree, FEC codes, and metadata takes up 244 KiB - compare to 1273 // above wihtout FEC which is 152 KiB. 1274 EXPECT_EQ(244 * 1024ULL, partition_size - max_image_size); 1275 1276 // Check that we can add a hashtree with an image this size for such 1277 // a partition size. 1278 base::FilePath system_path = GenerateImage("system", max_image_size); 1279 EXPECT_COMMAND(0, 1280 "./avbtool add_hashtree_footer" 1281 " --image %s" 1282 " --partition_name system" 1283 " --partition_size %zd" 1284 " --salt deadbeef" 1285 " --algorithm SHA512_RSA4096 " 1286 " --key test/data/testkey_rsa4096.pem" 1287 " --internal_release_string \"\"", 1288 system_path.value().c_str(), 1289 partition_size); 1290 } 1291 1292 TEST_F(AvbToolTest, KernelCmdlineDescriptor) { 1293 base::FilePath vbmeta_path = 1294 testdir_.Append("vbmeta_kernel_cmdline_desc.bin"); 1295 1296 EXPECT_COMMAND(0, 1297 "./avbtool make_vbmeta_image " 1298 "--output %s " 1299 "--kernel_cmdline 'foo bar baz' " 1300 "--kernel_cmdline 'second cmdline' " 1301 "--algorithm SHA256_RSA2048 " 1302 "--key test/data/testkey_rsa2048.pem " 1303 "--internal_release_string \"\"", 1304 vbmeta_path.value().c_str()); 1305 1306 ASSERT_EQ( 1307 "Minimum libavb version: 1.0\n" 1308 "Header Block: 256 bytes\n" 1309 "Authentication Block: 320 bytes\n" 1310 "Auxiliary Block: 640 bytes\n" 1311 "Algorithm: SHA256_RSA2048\n" 1312 "Rollback Index: 0\n" 1313 "Flags: 0\n" 1314 "Release String: ''\n" 1315 "Descriptors:\n" 1316 " Kernel Cmdline descriptor:\n" 1317 " Flags: 0\n" 1318 " Kernel Cmdline: 'foo bar baz'\n" 1319 " Kernel Cmdline descriptor:\n" 1320 " Flags: 0\n" 1321 " Kernel Cmdline: 'second cmdline'\n", 1322 InfoImage(vbmeta_path)); 1323 1324 // Now check the VBMeta image. 1325 std::string image_data; 1326 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data)); 1327 1328 const uint8_t* vbmeta_data = 1329 reinterpret_cast<const uint8_t*>(image_data.data()); 1330 const size_t vbmeta_size = image_data.length(); 1331 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 1332 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL)); 1333 1334 // Collect all descriptors. 1335 std::vector<const AvbDescriptor*> descriptors; 1336 avb_descriptor_foreach( 1337 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors); 1338 1339 // We should have two descriptors - check them. 1340 EXPECT_EQ(2UL, descriptors.size()); 1341 AvbKernelCmdlineDescriptor d; 1342 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE, 1343 avb_be64toh(descriptors[0]->tag)); 1344 EXPECT_NE( 1345 0, 1346 avb_kernel_cmdline_descriptor_validate_and_byteswap( 1347 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]), 1348 &d)); 1349 EXPECT_EQ("foo bar baz", 1350 std::string(reinterpret_cast<const char*>(descriptors[0]) + 1351 sizeof(AvbKernelCmdlineDescriptor), 1352 d.kernel_cmdline_length)); 1353 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE, 1354 avb_be64toh(descriptors[1]->tag)); 1355 EXPECT_NE( 1356 0, 1357 avb_kernel_cmdline_descriptor_validate_and_byteswap( 1358 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]), 1359 &d)); 1360 EXPECT_EQ("second cmdline", 1361 std::string(reinterpret_cast<const char*>(descriptors[1]) + 1362 sizeof(AvbKernelCmdlineDescriptor), 1363 d.kernel_cmdline_length)); 1364 } 1365 1366 TEST_F(AvbToolTest, IncludeDescriptor) { 1367 base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin"); 1368 base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin"); 1369 base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin"); 1370 1371 EXPECT_COMMAND(0, 1372 "./avbtool make_vbmeta_image " 1373 "--output %s " 1374 "--kernel_cmdline 'something' " 1375 "--prop name:value " 1376 "--internal_release_string \"\"", 1377 vbmeta1_path.value().c_str()); 1378 1379 EXPECT_COMMAND(0, 1380 "./avbtool make_vbmeta_image " 1381 "--output %s " 1382 "--prop name2:value2 " 1383 "--prop name3:value3 " 1384 "--internal_release_string \"\"", 1385 vbmeta2_path.value().c_str()); 1386 1387 EXPECT_COMMAND(0, 1388 "./avbtool make_vbmeta_image " 1389 "--output %s " 1390 "--prop name4:value4 " 1391 "--include_descriptors_from_image %s " 1392 "--include_descriptors_from_image %s " 1393 "--internal_release_string \"\"", 1394 vbmeta3_path.value().c_str(), 1395 vbmeta1_path.value().c_str(), 1396 vbmeta2_path.value().c_str()); 1397 1398 ASSERT_EQ( 1399 "Minimum libavb version: 1.0\n" 1400 "Header Block: 256 bytes\n" 1401 "Authentication Block: 0 bytes\n" 1402 "Auxiliary Block: 256 bytes\n" 1403 "Algorithm: NONE\n" 1404 "Rollback Index: 0\n" 1405 "Flags: 0\n" 1406 "Release String: ''\n" 1407 "Descriptors:\n" 1408 " Prop: name4 -> 'value4'\n" 1409 " Prop: name -> 'value'\n" 1410 " Kernel Cmdline descriptor:\n" 1411 " Flags: 0\n" 1412 " Kernel Cmdline: 'something'\n" 1413 " Prop: name2 -> 'value2'\n" 1414 " Prop: name3 -> 'value3'\n", 1415 InfoImage(vbmeta3_path)); 1416 } 1417 1418 TEST_F(AvbToolTest, ChainedPartition) { 1419 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin"); 1420 1421 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey"); 1422 1423 EXPECT_COMMAND( 1424 0, 1425 "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem" 1426 " --output %s", 1427 pk_path.value().c_str()); 1428 1429 EXPECT_COMMAND( 1430 0, 1431 "./avbtool make_vbmeta_image " 1432 "--output %s " 1433 "--chain_partition system:1:%s " 1434 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1435 "--internal_release_string \"\"", 1436 vbmeta_path.value().c_str(), 1437 pk_path.value().c_str()); 1438 1439 ASSERT_EQ( 1440 "Minimum libavb version: 1.0\n" 1441 "Header Block: 256 bytes\n" 1442 "Authentication Block: 320 bytes\n" 1443 "Auxiliary Block: 1152 bytes\n" 1444 "Algorithm: SHA256_RSA2048\n" 1445 "Rollback Index: 0\n" 1446 "Flags: 0\n" 1447 "Release String: ''\n" 1448 "Descriptors:\n" 1449 " Chain Partition descriptor:\n" 1450 " Partition Name: system\n" 1451 " Rollback Index Location: 1\n" 1452 " Public key (sha1): " 1453 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n", 1454 InfoImage(vbmeta_path)); 1455 1456 // Now check the VBMeta image. 1457 std::string image_data; 1458 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data)); 1459 1460 const uint8_t* vbmeta_data = 1461 reinterpret_cast<const uint8_t*>(image_data.data()); 1462 const size_t vbmeta_size = image_data.length(); 1463 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 1464 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL)); 1465 1466 // Collect all descriptors. 1467 std::vector<const AvbDescriptor*> descriptors; 1468 avb_descriptor_foreach( 1469 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors); 1470 1471 // We should have one descriptor - check it. 1472 EXPECT_EQ(1UL, descriptors.size()); 1473 1474 std::string pk_data; 1475 ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data)); 1476 1477 AvbChainPartitionDescriptor d; 1478 EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION, 1479 avb_be64toh(descriptors[0]->tag)); 1480 EXPECT_NE( 1481 0, 1482 avb_chain_partition_descriptor_validate_and_byteswap( 1483 reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]), 1484 &d)); 1485 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) + 1486 sizeof(AvbChainPartitionDescriptor); 1487 uint64_t o = 0; 1488 EXPECT_EQ("system", 1489 std::string(reinterpret_cast<const char*>(desc_end + o), 1490 d.partition_name_len)); 1491 o += d.partition_name_len; 1492 EXPECT_EQ(pk_data, 1493 std::string(reinterpret_cast<const char*>(descriptors[0]) + 1494 sizeof(AvbChainPartitionDescriptor) + o, 1495 d.public_key_len)); 1496 } 1497 1498 TEST_F(AvbToolTest, ChainedPartitionNoLocationCollision) { 1499 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin"); 1500 1501 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey"); 1502 1503 EXPECT_COMMAND( 1504 0, 1505 "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem" 1506 " --output %s", 1507 pk_path.value().c_str()); 1508 1509 // Check that avbtool bails if the same Rollback Index Location is 1510 // used for multiple chained partitions. 1511 EXPECT_COMMAND( 1512 1, 1513 "./avbtool make_vbmeta_image " 1514 "--output %s " 1515 "--chain_partition system:1:%s " 1516 "--chain_partition other:1:%s " 1517 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1518 "--internal_release_string \"\"", 1519 vbmeta_path.value().c_str(), 1520 pk_path.value().c_str(), 1521 pk_path.value().c_str()); 1522 } 1523 1524 TEST_F(AvbToolTest, AppendVBMetaImage) { 1525 size_t boot_size = 5 * 1024 * 1024; 1526 size_t boot_partition_size = 32 * 1024 * 1024; 1527 base::FilePath boot_path = GenerateImage("boot", boot_size); 1528 1529 GenerateVBMetaImage("vbmeta.img", 1530 "SHA256_RSA2048", 1531 0, 1532 base::FilePath("test/data/testkey_rsa2048.pem"), 1533 std::string("--append_to_release_string \"\" " 1534 "--kernel_cmdline foo")); 1535 1536 EXPECT_COMMAND(0, 1537 "./avbtool append_vbmeta_image " 1538 "--image %s " 1539 "--partition_size %d " 1540 "--vbmeta_image %s ", 1541 boot_path.value().c_str(), 1542 (int)boot_partition_size, 1543 vbmeta_image_path_.value().c_str()); 1544 1545 std::string vbmeta_contents = InfoImage(vbmeta_image_path_); 1546 std::string boot_contents = InfoImage(boot_path); 1547 1548 // Check that boot.img has the same vbmeta blob as from vbmeta.img - 1549 // we do this by inspecting 'avbtool info_image' output combined 1550 // with the known footer location given boot.img has 5 MiB known 1551 // content and the partition size is 32 MiB. 1552 ASSERT_EQ( 1553 "Minimum libavb version: 1.0\n" 1554 "Header Block: 256 bytes\n" 1555 "Authentication Block: 320 bytes\n" 1556 "Auxiliary Block: 576 bytes\n" 1557 "Algorithm: SHA256_RSA2048\n" 1558 "Rollback Index: 0\n" 1559 "Flags: 0\n" 1560 "Release String: 'avbtool 1.0.0 '\n" 1561 "Descriptors:\n" 1562 " Kernel Cmdline descriptor:\n" 1563 " Flags: 0\n" 1564 " Kernel Cmdline: 'foo'\n", 1565 vbmeta_contents); 1566 std::string known_footer = 1567 "Footer version: 1.0\n" 1568 "Image size: 33554432 bytes\n" 1569 "Original image size: 5242880 bytes\n" 1570 "VBMeta offset: 5242880\n" 1571 "VBMeta size: 1152 bytes\n" 1572 "--\n"; 1573 ASSERT_EQ(known_footer + vbmeta_contents, boot_contents); 1574 1575 // Also verify that the blobs are the same, bit for bit. 1576 base::File f = 1577 base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 1578 std::vector<uint8_t> loaded_vbmeta; 1579 loaded_vbmeta.resize(1152); 1580 EXPECT_EQ( 1581 f.Read( 1582 5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152), 1583 1152); 1584 EXPECT_EQ(vbmeta_image_, loaded_vbmeta); 1585 } 1586 1587 TEST_F(AvbToolTest, SigningHelperBasic) { 1588 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin"); 1589 base::FilePath signing_helper_test_path = 1590 testdir_.Append("signing_helper_test"); 1591 EXPECT_COMMAND( 1592 0, 1593 "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image " 1594 "--output %s " 1595 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1596 "--signing_helper test/avbtool_signing_helper_test.py " 1597 "--internal_release_string \"\"", 1598 signing_helper_test_path.value().c_str(), 1599 vbmeta_path.value().c_str()); 1600 1601 // Now check the value in test file. 1602 std::string value; 1603 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value)); 1604 EXPECT_EQ("DONE", value); 1605 } 1606 1607 TEST_F(AvbToolTest, SigningHelperWithFilesBasic) { 1608 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin"); 1609 base::FilePath signing_helper_test_path = 1610 testdir_.Append("signing_helper_test"); 1611 EXPECT_COMMAND( 1612 0, 1613 "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image " 1614 "--output %s " 1615 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1616 "--signing_helper_with_files " 1617 "test/avbtool_signing_helper_with_files_test.py " 1618 "--internal_release_string \"\"", 1619 signing_helper_test_path.value().c_str(), 1620 vbmeta_path.value().c_str()); 1621 1622 // Now check the value in test file. 1623 std::string value; 1624 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value)); 1625 EXPECT_EQ("DONE", value); 1626 } 1627 1628 TEST_F(AvbToolTest, SigningHelperReturnError) { 1629 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin"); 1630 EXPECT_COMMAND( 1631 1, 1632 "./avbtool make_vbmeta_image " 1633 "--output %s " 1634 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1635 "--signing_helper test/avbtool_signing_helper_test.py " 1636 "--internal_release_string \"\"", 1637 vbmeta_path.value().c_str()); 1638 } 1639 1640 TEST_F(AvbToolTest, SigningHelperWithFilesReturnError) { 1641 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin"); 1642 EXPECT_COMMAND( 1643 1, 1644 "./avbtool make_vbmeta_image " 1645 "--output %s " 1646 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1647 "--signing_helper_with_files " 1648 "test/avbtool_signing_helper_with_files_test.py " 1649 "--internal_release_string \"\"", 1650 vbmeta_path.value().c_str()); 1651 } 1652 1653 TEST_F(AvbToolTest, VerifyImageNoSignature) { 1654 GenerateVBMetaImage("vbmeta.img", 1655 "", // NONE 1656 0, 1657 base::FilePath()); 1658 1659 EXPECT_COMMAND(0, 1660 "./avbtool verify_image " 1661 "--image %s ", 1662 vbmeta_image_path_.value().c_str()); 1663 } 1664 1665 TEST_F(AvbToolTest, VerifyImageValidSignature) { 1666 GenerateVBMetaImage("vbmeta.img", 1667 "SHA256_RSA2048", 1668 0, 1669 base::FilePath("test/data/testkey_rsa2048.pem")); 1670 1671 EXPECT_COMMAND(0, 1672 "./avbtool verify_image " 1673 "--image %s ", 1674 vbmeta_image_path_.value().c_str()); 1675 } 1676 1677 TEST_F(AvbToolTest, VerifyImageCorruptedVBMeta) { 1678 GenerateVBMetaImage("vbmeta.img", 1679 "SHA256_RSA2048", 1680 0, 1681 base::FilePath("test/data/testkey_rsa2048.pem")); 1682 1683 // Corrupt four bytes of data in the end of the image. Since the aux 1684 // data is at the end and this data is signed, this will change the 1685 // value of the computed hash. 1686 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff}; 1687 EXPECT_EQ(AVB_IO_RESULT_OK, 1688 ops_.avb_ops()->write_to_partition(ops_.avb_ops(), 1689 "vbmeta", 1690 -4, // offset from end 1691 sizeof corrupt_data, 1692 corrupt_data)); 1693 1694 EXPECT_COMMAND(1, 1695 "./avbtool verify_image " 1696 "--image %s ", 1697 vbmeta_image_path_.value().c_str()); 1698 } 1699 1700 TEST_F(AvbToolTest, VerifyImageOtherKeyMatching) { 1701 GenerateVBMetaImage("vbmeta.img", 1702 "SHA256_RSA2048", 1703 0, 1704 base::FilePath("test/data/testkey_rsa2048.pem")); 1705 1706 EXPECT_COMMAND(0, 1707 "./avbtool verify_image " 1708 "--image %s --key test/data/testkey_rsa2048.pem", 1709 vbmeta_image_path_.value().c_str()); 1710 } 1711 1712 TEST_F(AvbToolTest, VerifyImageOtherKeyNotMatching) { 1713 GenerateVBMetaImage("vbmeta.img", 1714 "SHA256_RSA2048", 1715 0, 1716 base::FilePath("test/data/testkey_rsa2048.pem")); 1717 1718 EXPECT_COMMAND(1, 1719 "./avbtool verify_image " 1720 "--image %s --key test/data/testkey_rsa4096.pem", 1721 vbmeta_image_path_.value().c_str()); 1722 } 1723 1724 TEST_F(AvbToolTest, VerifyImageBrokenSignature) { 1725 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin"); 1726 base::FilePath signing_helper_test_path = 1727 testdir_.Append("signing_helper_test"); 1728 1729 // Intentionally make the signer generate a wrong signature. 1730 EXPECT_COMMAND( 1731 0, 1732 "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool make_vbmeta_image " 1733 "--output %s " 1734 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1735 "--signing_helper test/avbtool_signing_helper_test.py " 1736 "--internal_release_string \"\"", 1737 vbmeta_path.value().c_str()); 1738 1739 EXPECT_COMMAND(1, 1740 "./avbtool verify_image " 1741 "--image %s ", 1742 vbmeta_path.value().c_str()); 1743 } 1744 1745 // Helper to generate boot.img, unsparse system.img, and vbmeta.img. 1746 void AvbToolTest::GenerateImageWithHashAndHashtreeSetup() { 1747 const size_t boot_partition_size = 16 * 1024 * 1024; 1748 const size_t boot_image_size = 5 * 1024 * 1024; 1749 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size); 1750 EXPECT_COMMAND(0, 1751 "./avbtool add_hash_footer" 1752 " --image %s" 1753 " --rollback_index 0" 1754 " --partition_name boot" 1755 " --partition_size %zd" 1756 " --salt deadbeef" 1757 " --internal_release_string \"\"", 1758 boot_path.value().c_str(), 1759 boot_partition_size); 1760 1761 const size_t system_partition_size = 10 * 1024 * 1024; 1762 const size_t system_image_size = 8 * 1024 * 1024; 1763 base::FilePath system_path = GenerateImage("system.img", system_image_size); 1764 EXPECT_COMMAND(0, 1765 "./avbtool add_hashtree_footer --salt d00df00d --image %s " 1766 "--partition_size %zd --partition_name system " 1767 "--internal_release_string \"\" ", 1768 system_path.value().c_str(), 1769 system_partition_size); 1770 1771 GenerateVBMetaImage("vbmeta.img", 1772 "SHA256_RSA2048", 1773 0, 1774 base::FilePath("test/data/testkey_rsa2048.pem"), 1775 base::StringPrintf("--include_descriptors_from_image %s " 1776 "--include_descriptors_from_image %s", 1777 boot_path.value().c_str(), 1778 system_path.value().c_str())); 1779 } 1780 1781 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) { 1782 GenerateImageWithHashAndHashtreeSetup(); 1783 1784 // Do two checks - one for system.img not sparse, and one where it 1785 // is sparse. 1786 for (int n = 0; n < 2; n++) { 1787 EXPECT_COMMAND(0, 1788 "./avbtool verify_image " 1789 "--image %s ", 1790 vbmeta_image_path_.value().c_str()); 1791 if (n == 0) { 1792 EXPECT_COMMAND(0, 1793 "img2simg %s %s.sparse", 1794 testdir_.Append("system.img").value().c_str(), 1795 testdir_.Append("system.img").value().c_str()); 1796 EXPECT_COMMAND(0, 1797 "mv %s.sparse %s", 1798 testdir_.Append("system.img").value().c_str(), 1799 testdir_.Append("system.img").value().c_str()); 1800 } 1801 } 1802 } 1803 1804 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) { 1805 GenerateImageWithHashAndHashtreeSetup(); 1806 1807 // Corrupt four bytes of data in the middle of boot.img. 1808 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff}; 1809 EXPECT_EQ(AVB_IO_RESULT_OK, 1810 ops_.avb_ops()->write_to_partition(ops_.avb_ops(), 1811 "boot", 1812 105 * 1024, // offset from start 1813 sizeof corrupt_data, 1814 corrupt_data)); 1815 1816 EXPECT_COMMAND(1, 1817 "./avbtool verify_image " 1818 "--image %s ", 1819 vbmeta_image_path_.value().c_str()); 1820 } 1821 1822 TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHashtree) { 1823 GenerateImageWithHashAndHashtreeSetup(); 1824 1825 // Corrupt four bytes of data in the middle of system.img. 1826 uint8_t corrupt_data[4] = {0xff, 0xff, 0xff, 0xff}; 1827 EXPECT_EQ(AVB_IO_RESULT_OK, 1828 ops_.avb_ops()->write_to_partition(ops_.avb_ops(), 1829 "system", 1830 123 * 1024, // offset from start 1831 sizeof corrupt_data, 1832 corrupt_data)); 1833 1834 // Do two checks - one for system.img not sparse, and one where it 1835 // is sparse. 1836 for (int n = 0; n < 2; n++) { 1837 EXPECT_COMMAND(1, 1838 "./avbtool verify_image " 1839 "--image %s ", 1840 vbmeta_image_path_.value().c_str()); 1841 if (n == 0) { 1842 EXPECT_COMMAND(0, 1843 "img2simg %s %s.sparse", 1844 testdir_.Append("system.img").value().c_str(), 1845 testdir_.Append("system.img").value().c_str()); 1846 EXPECT_COMMAND(0, 1847 "mv %s.sparse %s", 1848 testdir_.Append("system.img").value().c_str(), 1849 testdir_.Append("system.img").value().c_str()); 1850 } 1851 } 1852 } 1853 1854 TEST_F(AvbToolTest, VerifyImageChainPartition) { 1855 base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey"); 1856 EXPECT_COMMAND( 1857 0, 1858 "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem" 1859 " --output %s", 1860 pk4096_path.value().c_str()); 1861 1862 base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey"); 1863 EXPECT_COMMAND( 1864 0, 1865 "./avbtool extract_public_key --key test/data/testkey_rsa8192.pem" 1866 " --output %s", 1867 pk8192_path.value().c_str()); 1868 1869 GenerateVBMetaImage("vbmeta.img", 1870 "SHA256_RSA2048", 1871 0, 1872 base::FilePath("test/data/testkey_rsa2048.pem"), 1873 base::StringPrintf("--chain_partition system:1:%s ", 1874 pk4096_path.value().c_str())); 1875 1876 // Should not fail (name, rollback_index, contents all correct). 1877 EXPECT_COMMAND(0, 1878 "./avbtool verify_image " 1879 "--image %s " 1880 "--expected_chain_partition system:1:%s", 1881 vbmeta_image_path_.value().c_str(), 1882 pk4096_path.value().c_str()); 1883 1884 // Should fail because we didn't use --expected_chain_partition. 1885 EXPECT_COMMAND(1, 1886 "./avbtool verify_image " 1887 "--image %s ", 1888 vbmeta_image_path_.value().c_str()); 1889 1890 // Should fail because partition name is wrong. 1891 EXPECT_COMMAND(1, 1892 "./avbtool verify_image " 1893 "--image %s " 1894 "--expected_chain_partition xyz:1:%s", 1895 vbmeta_image_path_.value().c_str(), 1896 pk4096_path.value().c_str()); 1897 1898 // Should fail because rollback index location is wrong. 1899 EXPECT_COMMAND(1, 1900 "./avbtool verify_image " 1901 "--image %s " 1902 "--expected_chain_partition system:2:%s", 1903 vbmeta_image_path_.value().c_str(), 1904 pk4096_path.value().c_str()); 1905 1906 // Should fail because public key blob is wrong. 1907 EXPECT_COMMAND(1, 1908 "./avbtool verify_image " 1909 "--image %s " 1910 "--expected_chain_partition system:1:%s", 1911 vbmeta_image_path_.value().c_str(), 1912 pk8192_path.value().c_str()); 1913 } 1914 1915 TEST_F(AvbToolTest, PrintRequiredLibavbVersion) { 1916 base::FilePath output_path = testdir_.Append("versions.txt"); 1917 1918 const size_t boot_partition_size = 16 * 1024 * 1024; 1919 EXPECT_COMMAND(0, 1920 "./avbtool add_hash_footer" 1921 " --rollback_index 0" 1922 " --partition_name boot" 1923 " --partition_size %zd" 1924 " --salt deadbeef" 1925 " --internal_release_string \"\"" 1926 " --print_required_libavb_version >> %s", 1927 boot_partition_size, 1928 output_path.value().c_str()); 1929 1930 const size_t system_partition_size = 10 * 1024 * 1024; 1931 EXPECT_COMMAND(0, 1932 "./avbtool add_hashtree_footer --salt d00df00d " 1933 "--partition_size %zd --partition_name system " 1934 "--internal_release_string \"\"" 1935 " --print_required_libavb_version >> %s", 1936 system_partition_size, 1937 output_path.value().c_str()); 1938 1939 EXPECT_COMMAND(0, 1940 "./avbtool make_vbmeta_image " 1941 "--algorithm SHA256_RSA2048 " 1942 "--key test/data/testkey_rsa2048.pem " 1943 "--internal_release_string \"\"" 1944 " --print_required_libavb_version >> %s", 1945 output_path.value().c_str()); 1946 1947 // Check that "1.0\n" was printed for all three invocations. 1948 std::string versions; 1949 ASSERT_TRUE(base::ReadFileToString(output_path, &versions)); 1950 EXPECT_EQ(versions, std::string("1.0\n1.0\n1.0\n")); 1951 } 1952 1953 TEST_F(AvbToolTest, MakeAtxPikCertificate) { 1954 base::FilePath subject_path = testdir_.Append("tmp_subject"); 1955 ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16)); 1956 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem"); 1957 EXPECT_COMMAND( 1958 0, 1959 "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s", 1960 pubkey_path.value().c_str()); 1961 1962 base::FilePath output_path = testdir_.Append("tmp_certificate.bin"); 1963 EXPECT_COMMAND(0, 1964 "./avbtool make_atx_certificate" 1965 " --subject %s" 1966 " --subject_key %s" 1967 " --subject_key_version 42" 1968 " --subject_is_intermediate_authority" 1969 " --authority_key test/data/testkey_atx_prk.pem" 1970 " --output %s", 1971 subject_path.value().c_str(), 1972 pubkey_path.value().c_str(), 1973 output_path.value().c_str()); 1974 1975 EXPECT_COMMAND(0, 1976 "diff test/data/atx_pik_certificate.bin %s", 1977 output_path.value().c_str()); 1978 } 1979 1980 TEST_F(AvbToolTest, MakeAtxPskCertificate) { 1981 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem"); 1982 EXPECT_COMMAND( 1983 0, 1984 "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s", 1985 pubkey_path.value().c_str()); 1986 1987 base::FilePath output_path = testdir_.Append("tmp_certificate.bin"); 1988 EXPECT_COMMAND(0, 1989 "./avbtool make_atx_certificate" 1990 " --subject test/data/atx_product_id.bin" 1991 " --subject_key %s" 1992 " --subject_key_version 42" 1993 " --authority_key test/data/testkey_atx_pik.pem" 1994 " --output %s", 1995 pubkey_path.value().c_str(), 1996 output_path.value().c_str()); 1997 1998 EXPECT_COMMAND(0, 1999 "diff test/data/atx_psk_certificate.bin %s", 2000 output_path.value().c_str()); 2001 } 2002 2003 TEST_F(AvbToolTest, MakeAtxPermanentAttributes) { 2004 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem"); 2005 EXPECT_COMMAND( 2006 0, 2007 "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s", 2008 pubkey_path.value().c_str()); 2009 2010 base::FilePath output_path = testdir_.Append("tmp_attributes.bin"); 2011 EXPECT_COMMAND(0, 2012 "./avbtool make_atx_permanent_attributes" 2013 " --root_authority_key %s" 2014 " --product_id test/data/atx_product_id.bin" 2015 " --output %s", 2016 pubkey_path.value().c_str(), 2017 output_path.value().c_str()); 2018 2019 EXPECT_COMMAND(0, 2020 "diff test/data/atx_permanent_attributes.bin %s", 2021 output_path.value().c_str()); 2022 } 2023 2024 TEST_F(AvbToolTest, MakeAtxMetadata) { 2025 base::FilePath output_path = testdir_.Append("tmp_metadata.bin"); 2026 2027 EXPECT_COMMAND( 2028 0, 2029 "./avbtool make_atx_metadata" 2030 " --intermediate_key_certificate test/data/atx_pik_certificate.bin" 2031 " --product_key_certificate test/data/atx_psk_certificate.bin" 2032 " --output %s", 2033 output_path.value().c_str()); 2034 2035 EXPECT_COMMAND( 2036 0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str()); 2037 } 2038 2039 } // namespace avb 2040