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 41namespace avb { 42 43class AvbToolTest : public BaseAvbToolTest { 44 public: 45 AvbToolTest() {} 46 47 void AddHashFooterTest(bool sparse_image); 48 void AddHashtreeFooterTest(bool sparse_image); 49 void AddHashtreeFooterFECTest(bool sparse_image); 50}; 51 52// This test ensure that the version is increased in both 53// avb_boot_image.h and the avb tool. 54TEST_F(AvbToolTest, AvbVersionInSync) { 55 base::FilePath path = testdir_.Append("version.txt"); 56 EXPECT_COMMAND(0, "./avbtool version > %s", path.value().c_str()); 57 std::string printed_version; 58 ASSERT_TRUE(base::ReadFileToString(path, &printed_version)); 59 base::TrimWhitespaceASCII(printed_version, base::TRIM_ALL, &printed_version); 60 // See comments in libavb/avb_version.c and avbtool's get_release_string() 61 // about being in sync. 62 EXPECT_EQ(printed_version, 63 std::string("avbtool ") + std::string(avb_version_string())); 64} 65 66TEST_F(AvbToolTest, DefaultReleaseString) { 67 GenerateVBMetaImage("vbmeta.img", 68 "SHA256_RSA2048", 69 0, 70 base::FilePath("test/data/testkey_rsa2048.pem")); 71 72 // Default release string is "avbtool " + avb_version_string(). 73 AvbVBMetaImageHeader h; 74 avb_vbmeta_image_header_to_host_byte_order( 75 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 76 EXPECT_EQ(std::string("avbtool ") + std::string(avb_version_string()), 77 std::string((const char*)h.release_string)); 78} 79 80TEST_F(AvbToolTest, ReleaseStringAppend) { 81 GenerateVBMetaImage("vbmeta.img", 82 "SHA256_RSA2048", 83 0, 84 base::FilePath("test/data/testkey_rsa2048.pem"), 85 "--append_to_release_string \"Woot XYZ\""); 86 87 // Note that avbtool inserts the space by itself. 88 std::string expected_str = 89 std::string("avbtool ") + std::string(avb_version_string()) + " Woot XYZ"; 90 91 AvbVBMetaImageHeader h; 92 avb_vbmeta_image_header_to_host_byte_order( 93 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 94 EXPECT_EQ(expected_str, std::string((const char*)h.release_string)); 95} 96 97TEST_F(AvbToolTest, ReleaseStringAppendTruncated) { 98 // Append enough text that truncation is sure to happen. 99 std::string append_str = "0123456789abcdef0123456789abcdef0123456789abcdef"; 100 std::string expected_str = std::string("avbtool ") + 101 std::string(avb_version_string()) + " " + 102 append_str; 103 EXPECT_GT(expected_str.size(), (size_t)(AVB_RELEASE_STRING_SIZE - 1)); 104 expected_str.resize(AVB_RELEASE_STRING_SIZE - 1); 105 106 GenerateVBMetaImage( 107 "vbmeta.img", 108 "SHA256_RSA2048", 109 0, 110 base::FilePath("test/data/testkey_rsa2048.pem"), 111 std::string("--append_to_release_string \"") + append_str + "\""); 112 113 // This checks that it ends with a NUL byte. 114 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 115 avb_vbmeta_image_verify( 116 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr)); 117 118 // For good measure we also check here. 119 AvbVBMetaImageHeader h; 120 avb_vbmeta_image_header_to_host_byte_order( 121 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 122 EXPECT_EQ(expected_str, std::string((const char*)h.release_string)); 123} 124 125TEST_F(AvbToolTest, ExtractPublicKey) { 126 GenerateVBMetaImage("vbmeta.img", 127 "SHA256_RSA2048", 128 0, 129 base::FilePath("test/data/testkey_rsa2048.pem"), 130 "--internal_release_string \"\""); 131 132 std::string key_data = 133 PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")); 134 135 AvbVBMetaImageHeader h; 136 avb_vbmeta_image_header_to_host_byte_order( 137 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 138 uint8_t* d = reinterpret_cast<uint8_t*>(vbmeta_image_.data()); 139 size_t auxiliary_data_block_offset = 140 sizeof(AvbVBMetaImageHeader) + h.authentication_data_block_size; 141 EXPECT_GT(h.auxiliary_data_block_size, key_data.size()); 142 EXPECT_EQ(0, 143 memcmp(key_data.data(), 144 d + auxiliary_data_block_offset + h.public_key_offset, 145 key_data.size())); 146} 147 148TEST_F(AvbToolTest, CheckDescriptors) { 149 GenerateVBMetaImage("vbmeta.img", 150 "SHA256_RSA2048", 151 0, 152 base::FilePath("test/data/testkey_rsa2048.pem"), 153 "--prop foo:brillo " 154 "--prop bar:chromeos " 155 "--prop prisoner:24601 " 156 "--prop hexnumber:0xcafe " 157 "--prop hexnumber_capital:0xCAFE " 158 "--prop large_hexnumber:0xfedcba9876543210 " 159 "--prop larger_than_uint64:0xfedcba98765432101 " 160 "--prop almost_a_number:423x " 161 "--prop_from_file blob:test/data/small_blob.bin " 162 "--internal_release_string \"\""); 163 164 AvbVBMetaImageHeader h; 165 avb_vbmeta_image_header_to_host_byte_order( 166 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 167 168 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 169 avb_vbmeta_image_verify( 170 vbmeta_image_.data(), vbmeta_image_.size(), nullptr, nullptr)); 171 172 const char* s; 173 size_t len; 174 uint64_t val; 175 176 // Basic. 177 s = avb_property_lookup( 178 vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &len); 179 EXPECT_EQ(0, strcmp(s, "brillo")); 180 EXPECT_EQ(6U, len); 181 s = avb_property_lookup( 182 vbmeta_image_.data(), vbmeta_image_.size(), "bar", 0, &len); 183 EXPECT_EQ(0, strcmp(s, "chromeos")); 184 EXPECT_EQ(8U, len); 185 s = avb_property_lookup( 186 vbmeta_image_.data(), vbmeta_image_.size(), "non-existant", 0, &len); 187 EXPECT_EQ(0U, len); 188 EXPECT_EQ(NULL, s); 189 190 // Numbers. 191 EXPECT_NE( 192 0, 193 avb_property_lookup_uint64( 194 vbmeta_image_.data(), vbmeta_image_.size(), "prisoner", 0, &val)); 195 EXPECT_EQ(24601U, val); 196 197 EXPECT_NE( 198 0, 199 avb_property_lookup_uint64( 200 vbmeta_image_.data(), vbmeta_image_.size(), "hexnumber", 0, &val)); 201 EXPECT_EQ(0xcafeU, val); 202 203 EXPECT_NE(0, 204 avb_property_lookup_uint64(vbmeta_image_.data(), 205 vbmeta_image_.size(), 206 "hexnumber_capital", 207 0, 208 &val)); 209 EXPECT_EQ(0xcafeU, val); 210 211 EXPECT_NE(0, 212 avb_property_lookup_uint64(vbmeta_image_.data(), 213 vbmeta_image_.size(), 214 "large_hexnumber", 215 0, 216 &val)); 217 EXPECT_EQ(0xfedcba9876543210U, val); 218 219 // We could catch overflows and return an error ... but we currently don't. 220 EXPECT_NE(0, 221 avb_property_lookup_uint64(vbmeta_image_.data(), 222 vbmeta_image_.size(), 223 "larger_than_uint64", 224 0, 225 &val)); 226 EXPECT_EQ(0xedcba98765432101U, val); 227 228 // Number-parsing failures. 229 EXPECT_EQ(0, 230 avb_property_lookup_uint64( 231 vbmeta_image_.data(), vbmeta_image_.size(), "foo", 0, &val)); 232 233 EXPECT_EQ(0, 234 avb_property_lookup_uint64(vbmeta_image_.data(), 235 vbmeta_image_.size(), 236 "almost_a_number", 237 0, 238 &val)); 239 240 // Blobs. 241 // 242 // test/data/small_blob.bin is 21 byte file full of NUL-bytes except 243 // for the string "brillo ftw!" at index 2 and '\n' at the last 244 // byte. 245 s = avb_property_lookup( 246 vbmeta_image_.data(), vbmeta_image_.size(), "blob", 0, &len); 247 EXPECT_EQ(21U, len); 248 EXPECT_EQ(0, memcmp(s, "\0\0", 2)); 249 EXPECT_EQ(0, memcmp(s + 2, "brillo ftw!", 11)); 250 EXPECT_EQ(0, memcmp(s + 13, "\0\0\0\0\0\0\0", 7)); 251 EXPECT_EQ('\n', s[20]); 252} 253 254TEST_F(AvbToolTest, CheckRollbackIndex) { 255 uint64_t rollback_index = 42; 256 GenerateVBMetaImage("vbmeta.img", 257 "SHA256_RSA2048", 258 rollback_index, 259 base::FilePath("test/data/testkey_rsa2048.pem"), 260 "--internal_release_string \"\""); 261 262 AvbVBMetaImageHeader h; 263 avb_vbmeta_image_header_to_host_byte_order( 264 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 265 266 EXPECT_EQ(rollback_index, h.rollback_index); 267} 268 269TEST_F(AvbToolTest, CheckPubkeyReturned) { 270 GenerateVBMetaImage("vbmeta.img", 271 "SHA256_RSA2048", 272 0, 273 base::FilePath("test/data/testkey_rsa2048.pem"), 274 "--internal_release_string \"\""); 275 276 const uint8_t* pubkey = NULL; 277 size_t pubkey_length = 0; 278 279 EXPECT_EQ( 280 AVB_VBMETA_VERIFY_RESULT_OK, 281 avb_vbmeta_image_verify( 282 vbmeta_image_.data(), vbmeta_image_.size(), &pubkey, &pubkey_length)); 283 284 AvbVBMetaImageHeader h; 285 avb_vbmeta_image_header_to_host_byte_order( 286 reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h); 287 288 EXPECT_EQ(pubkey_length, h.public_key_size); 289 290 const uint8_t* expected_pubkey = 291 vbmeta_image_.data() + sizeof(AvbVBMetaImageHeader) + 292 h.authentication_data_block_size + h.public_key_offset; 293 EXPECT_EQ(pubkey, expected_pubkey); 294} 295 296TEST_F(AvbToolTest, Info) { 297 GenerateVBMetaImage("vbmeta.img", 298 "SHA256_RSA2048", 299 0, 300 base::FilePath("test/data/testkey_rsa2048.pem"), 301 "--prop foo:brillo " 302 "--prop bar:chromeos " 303 "--prop prisoner:24601 " 304 "--prop hexnumber:0xcafe " 305 "--prop hexnumber_capital:0xCAFE " 306 "--prop large_hexnumber:0xfedcba9876543210 " 307 "--prop larger_than_uint64:0xfedcba98765432101 " 308 "--prop almost_a_number:423x " 309 "--prop_from_file blob:test/data/small_blob.bin " 310 "--prop_from_file large_blob:test/data/large_blob.bin " 311 "--internal_release_string \"\""); 312 313 ASSERT_EQ( 314 "Minimum libavb version: 1.0\n" 315 "Header Block: 256 bytes\n" 316 "Authentication Block: 320 bytes\n" 317 "Auxiliary Block: 3200 bytes\n" 318 "Algorithm: SHA256_RSA2048\n" 319 "Rollback Index: 0\n" 320 "Flags: 0\n" 321 "Release String: ''\n" 322 "Descriptors:\n" 323 " Prop: foo -> 'brillo'\n" 324 " Prop: bar -> 'chromeos'\n" 325 " Prop: prisoner -> '24601'\n" 326 " Prop: hexnumber -> '0xcafe'\n" 327 " Prop: hexnumber_capital -> '0xCAFE'\n" 328 " Prop: large_hexnumber -> '0xfedcba9876543210'\n" 329 " Prop: larger_than_uint64 -> '0xfedcba98765432101'\n" 330 " Prop: almost_a_number -> '423x'\n" 331 " Prop: blob -> '\\x00\\x00brillo " 332 "ftw!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n'\n" 333 " Prop: large_blob -> (2048 bytes)\n", 334 InfoImage(vbmeta_image_path_)); 335} 336 337static bool collect_descriptors(const AvbDescriptor* descriptor, 338 void* user_data) { 339 std::vector<const AvbDescriptor*>* descriptors = 340 reinterpret_cast<std::vector<const AvbDescriptor*>*>(user_data); 341 descriptors->push_back(descriptor); 342 return true; // Keep iterating. 343} 344 345void AvbToolTest::AddHashFooterTest(bool sparse_image) { 346 const size_t rootfs_size = 1028 * 1024; 347 const size_t partition_size = 1536 * 1024; 348 349 // Generate a 1028 KiB file with known content. Some content have 350 // been arranged to ensure FILL_DATA segments in the sparse file. 351 std::vector<uint8_t> rootfs; 352 rootfs.resize(rootfs_size); 353 for (size_t n = 0; n < rootfs_size; n++) { 354 if ((n >= 5 * 1000 && n < 105 * 1000) || 355 (n >= 205 * 1000 && n < 305 * 1000) || 356 (n >= 505 * 1000 && n < 605 * 1000)) { 357 rootfs[n] = uint8_t(n) & 0x03; 358 } else { 359 rootfs[n] = uint8_t(n); 360 } 361 } 362 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin"); 363 base::FilePath rootfs_path = testdir_.Append("rootfs.bin"); 364 EXPECT_EQ(rootfs_size, 365 static_cast<const size_t>( 366 base::WriteFile(rootfs_path, 367 reinterpret_cast<const char*>(rootfs.data()), 368 rootfs.size()))); 369 370 if (sparse_image) { 371 EXPECT_COMMAND(0, 372 "mv %s %s.unsparse", 373 rootfs_path.value().c_str(), 374 rootfs_path.value().c_str()); 375 EXPECT_COMMAND(0, 376 "img2simg %s.unsparse %s", 377 rootfs_path.value().c_str(), 378 rootfs_path.value().c_str()); 379 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str()); 380 } 381 382 /* Do this twice to check that 'add_hash_footer' is idempotent. */ 383 for (int n = 0; n < 2; n++) { 384 EXPECT_COMMAND(0, 385 "./avbtool add_hash_footer --salt d00df00d " 386 "--hash_algorithm sha256 --image %s " 387 "--partition_size %d --partition_name foobar " 388 "--algorithm SHA256_RSA2048 " 389 "--key test/data/testkey_rsa2048.pem " 390 "--output_vbmeta %s " 391 "--internal_release_string \"\"", 392 rootfs_path.value().c_str(), 393 (int)partition_size, 394 ext_vbmeta_path.value().c_str()); 395 396 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n" 397 "Image size: 1572864 bytes\n" 398 "Original image size: 1052672 bytes\n" 399 "VBMeta offset: 1052672\n" 400 "VBMeta size: 1280 bytes\n" 401 "--\n" 402 "Minimum libavb version: 1.0%s\n" 403 "Header Block: 256 bytes\n" 404 "Authentication Block: 320 bytes\n" 405 "Auxiliary Block: 704 bytes\n" 406 "Algorithm: SHA256_RSA2048\n" 407 "Rollback Index: 0\n" 408 "Flags: 0\n" 409 "Release String: ''\n" 410 "Descriptors:\n" 411 " Hash descriptor:\n" 412 " Image Size: 1052672 bytes\n" 413 " Hash Algorithm: sha256\n" 414 " Partition Name: foobar\n" 415 " Salt: d00df00d\n" 416 " Digest: " 417 "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f" 418 "5e4ed357fbcf58d88d9\n", 419 sparse_image ? " (Sparse)" : ""), 420 InfoImage(rootfs_path)); 421 422 ASSERT_EQ( 423 "Minimum libavb version: 1.0\n" 424 "Header Block: 256 bytes\n" 425 "Authentication Block: 320 bytes\n" 426 "Auxiliary Block: 704 bytes\n" 427 "Algorithm: SHA256_RSA2048\n" 428 "Rollback Index: 0\n" 429 "Flags: 0\n" 430 "Release String: ''\n" 431 "Descriptors:\n" 432 " Hash descriptor:\n" 433 " Image Size: 1052672 bytes\n" 434 " Hash Algorithm: sha256\n" 435 " Partition Name: foobar\n" 436 " Salt: d00df00d\n" 437 " Digest: " 438 "9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f" 439 "5e4ed357fbcf58d88d9\n", 440 InfoImage(ext_vbmeta_path)); 441 } 442 443 if (sparse_image) { 444 EXPECT_COMMAND(0, 445 "mv %s %s.sparse", 446 rootfs_path.value().c_str(), 447 rootfs_path.value().c_str()); 448 EXPECT_COMMAND(0, 449 "simg2img %s.sparse %s", 450 rootfs_path.value().c_str(), 451 rootfs_path.value().c_str()); 452 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str()); 453 } 454 455 // Manually calculate the hash to check that it agrees with avbtool. 456 AvbSHA256Ctx hasher_ctx; 457 const uint8_t hasher_salt[4] = {0xd0, 0x0d, 0xf0, 0x0d}; 458 avb_sha256_init(&hasher_ctx); 459 avb_sha256_update(&hasher_ctx, hasher_salt, 4); 460 avb_sha256_update(&hasher_ctx, rootfs.data(), rootfs_size); 461 uint8_t* hasher_digest = avb_sha256_final(&hasher_ctx); 462 EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9", 463 mem_to_hexstring(hasher_digest, AVB_SHA256_DIGEST_SIZE)); 464 465 // Now check that we can find the VBMeta block again from the footer. 466 std::string part_data; 467 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data)); 468 469 // Check footer contains correct data. 470 AvbFooter f; 471 EXPECT_NE(0, 472 avb_footer_validate_and_byteswap( 473 reinterpret_cast<const AvbFooter*>( 474 part_data.data() + part_data.size() - AVB_FOOTER_SIZE), 475 &f)); 476 EXPECT_EQ( 477 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN), 478 AVB_FOOTER_MAGIC); 479 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major); 480 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor); 481 EXPECT_EQ(1052672UL, f.original_image_size); 482 EXPECT_EQ(1052672UL, f.vbmeta_offset); 483 EXPECT_EQ(1280UL, f.vbmeta_size); 484 485 // Check that the vbmeta image at |f.vbmeta_offset| checks out. 486 const uint8_t* vbmeta_data = 487 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset); 488 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 489 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL)); 490 491 // Collect all descriptors. 492 std::vector<const AvbDescriptor*> descriptors; 493 avb_descriptor_foreach( 494 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors); 495 496 // We should only have a single descriptor and it should be a 497 // hash descriptor. 498 EXPECT_EQ(1UL, descriptors.size()); 499 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, avb_be64toh(descriptors[0]->tag)); 500 AvbHashDescriptor d; 501 EXPECT_NE( 502 0, 503 avb_hash_descriptor_validate_and_byteswap( 504 reinterpret_cast<const AvbHashDescriptor*>(descriptors[0]), &d)); 505 EXPECT_EQ(1052672UL, d.image_size); 506 EXPECT_EQ(6UL, d.partition_name_len); 507 EXPECT_EQ(4UL, d.salt_len); 508 EXPECT_EQ(32UL, d.digest_len); 509 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) + 510 sizeof(AvbHashDescriptor); 511 uint64_t o = 0; 512 EXPECT_EQ("foobar", 513 std::string(reinterpret_cast<const char*>(desc_end + o), 514 d.partition_name_len)); 515 o += d.partition_name_len; 516 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len)); 517 o += d.salt_len; 518 EXPECT_EQ("9a58cc996d405e08a1e00f96dbfe9104fedf41cb83b1f5e4ed357fbcf58d88d9", 519 mem_to_hexstring(desc_end + o, d.digest_len)); 520 521 // Check that the footer is correctly erased. 522 EXPECT_COMMAND( 523 0, "./avbtool erase_footer --image %s", rootfs_path.value().c_str()); 524 int64_t erased_footer_file_size; 525 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size)); 526 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size); 527 528 // Check that --do_not_append_vbmeta_image works as intended. 529 EXPECT_COMMAND(0, 530 "./avbtool add_hash_footer --salt d00df00d " 531 "--hash_algorithm sha256 --image %s " 532 "--partition_size %d --partition_name foobar " 533 "--algorithm SHA256_RSA2048 " 534 "--key test/data/testkey_rsa2048.pem " 535 "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image " 536 "--internal_release_string \"\"", 537 rootfs_path.value().c_str(), 538 (int)partition_size, 539 ext_vbmeta_path.value().c_str()); 540 int64_t file_size; 541 ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size)); 542 EXPECT_EQ(static_cast<size_t>(file_size), rootfs_size); 543 EXPECT_COMMAND(0, 544 "diff %s %s_2nd_run", 545 ext_vbmeta_path.value().c_str(), 546 ext_vbmeta_path.value().c_str()); 547} 548 549TEST_F(AvbToolTest, AddHashFooter) { 550 AddHashFooterTest(false); 551} 552 553TEST_F(AvbToolTest, AddHashFooterSparse) { 554 AddHashFooterTest(true); 555} 556 557static std::string RemoveLinesStartingWith(const std::string& str, 558 const std::string& prefix) { 559 std::vector<std::string> lines; 560 std::string ret; 561 562 lines = base::SplitString( 563 str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); 564 for (const std::string& line : lines) { 565 if (!base::StartsWith(line, prefix, base::CompareCase::SENSITIVE)) { 566 ret += line; 567 ret += '\n'; 568 } 569 } 570 return ret; 571} 572 573TEST_F(AvbToolTest, AddHashFooterSparseWithHoleAtTheEnd) { 574 const size_t partition_size = 10 * 1024 * 1024; 575 const size_t metadata_size = 128 * 1024; 576 577 // It's not enough to run img2simg on a file with a lot of zeroes at 578 // the end since that will turn up as "Fill with value (for value = 579 // 0x00000000)" and not "Don't care". Instead, use make_ext4fs for 580 // this since it will put a big hole (e.g. "Don't care" chunk) at 581 // the end. 582 base::FilePath partition_path = testdir_.Append("partition.bin"); 583 EXPECT_COMMAND(0, 584 "make_ext4fs -s -L test -l %zd %s", 585 partition_size - metadata_size, 586 partition_path.value().c_str()); 587 588 EXPECT_COMMAND(0, 589 "./avbtool add_hash_footer --salt d00df00d " 590 "--hash_algorithm sha256 --image %s " 591 "--partition_size %d --partition_name foobar " 592 "--algorithm SHA256_RSA2048 " 593 "--key test/data/testkey_rsa2048.pem " 594 "--internal_release_string \"\"", 595 partition_path.value().c_str(), 596 (int)partition_size); 597 598 // Since we may be using an arbritary version of make_ext4fs 599 // (because of different branches) the contents of the resulting 600 // disk image may slightly change. It's enough to just remove the 601 // "Digest:" line from the output to work around this. 602 std::string info = 603 RemoveLinesStartingWith(InfoImage(partition_path), " Digest:"); 604 ASSERT_EQ( 605 "Footer version: 1.0\n" 606 "Image size: 10485760 bytes\n" 607 "Original image size: 10354688 bytes\n" 608 "VBMeta offset: 10354688\n" 609 "VBMeta size: 1280 bytes\n" 610 "--\n" 611 "Minimum libavb version: 1.0 (Sparse)\n" 612 "Header Block: 256 bytes\n" 613 "Authentication Block: 320 bytes\n" 614 "Auxiliary Block: 704 bytes\n" 615 "Algorithm: SHA256_RSA2048\n" 616 "Rollback Index: 0\n" 617 "Flags: 0\n" 618 "Release String: ''\n" 619 "Descriptors:\n" 620 " Hash descriptor:\n" 621 " Image Size: 10354688 bytes\n" 622 " Hash Algorithm: sha256\n" 623 " Partition Name: foobar\n" 624 " Salt: d00df00d\n", 625 info); 626 627 EXPECT_COMMAND(0, 628 "mv %s %s.sparse", 629 partition_path.value().c_str(), 630 partition_path.value().c_str()); 631 EXPECT_COMMAND(0, 632 "simg2img %s.sparse %s", 633 partition_path.value().c_str(), 634 partition_path.value().c_str()); 635 EXPECT_COMMAND(0, "rm -f %s.sparse", partition_path.value().c_str()); 636} 637 638void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) { 639 const size_t rootfs_size = 1028 * 1024; 640 const size_t partition_size = 1536 * 1024; 641 642 // Generate a 1028 KiB file with known content. 643 std::vector<uint8_t> rootfs; 644 rootfs.resize(rootfs_size); 645 for (size_t n = 0; n < rootfs_size; n++) 646 rootfs[n] = uint8_t(n); 647 base::FilePath ext_vbmeta_path = testdir_.Append("ext_vbmeta.bin"); 648 base::FilePath rootfs_path = testdir_.Append("rootfs.bin"); 649 EXPECT_EQ(rootfs_size, 650 static_cast<const size_t>( 651 base::WriteFile(rootfs_path, 652 reinterpret_cast<const char*>(rootfs.data()), 653 rootfs.size()))); 654 655 if (sparse_image) { 656 EXPECT_COMMAND(0, 657 "mv %s %s.unsparse", 658 rootfs_path.value().c_str(), 659 rootfs_path.value().c_str()); 660 EXPECT_COMMAND(0, 661 "img2simg %s.unsparse %s", 662 rootfs_path.value().c_str(), 663 rootfs_path.value().c_str()); 664 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str()); 665 } 666 667 /* Do this twice to check that 'add_hashtree_footer' is idempotent. */ 668 for (int n = 0; n < 2; n++) { 669 EXPECT_COMMAND(0, 670 "./avbtool add_hashtree_footer --salt d00df00d --image %s " 671 "--partition_size %d --partition_name foobar " 672 "--algorithm SHA256_RSA2048 " 673 "--key test/data/testkey_rsa2048.pem " 674 "--output_vbmeta_image %s " 675 "--internal_release_string \"\"", 676 rootfs_path.value().c_str(), 677 (int)partition_size, 678 ext_vbmeta_path.value().c_str()); 679 680 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n" 681 "Image size: 1572864 bytes\n" 682 "Original image size: 1052672 bytes\n" 683 "VBMeta offset: 1069056\n" 684 "VBMeta size: 1344 bytes\n" 685 "--\n" 686 "Minimum libavb version: 1.0%s\n" 687 "Header Block: 256 bytes\n" 688 "Authentication Block: 320 bytes\n" 689 "Auxiliary Block: 768 bytes\n" 690 "Algorithm: SHA256_RSA2048\n" 691 "Rollback Index: 0\n" 692 "Flags: 0\n" 693 "Release String: ''\n" 694 "Descriptors:\n" 695 " Hashtree descriptor:\n" 696 " Version of dm-verity: 1\n" 697 " Image Size: 1052672 bytes\n" 698 " Tree Offset: 1052672\n" 699 " Tree Size: 16384 bytes\n" 700 " Data Block Size: 4096 bytes\n" 701 " Hash Block Size: 4096 bytes\n" 702 " FEC num roots: 0\n" 703 " FEC offset: 0\n" 704 " FEC size: 0 bytes\n" 705 " Hash Algorithm: sha1\n" 706 " Partition Name: foobar\n" 707 " Salt: d00df00d\n" 708 " Root Digest: " 709 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n", 710 sparse_image ? " (Sparse)" : ""), 711 InfoImage(rootfs_path)); 712 713 ASSERT_EQ( 714 "Minimum libavb version: 1.0\n" 715 "Header Block: 256 bytes\n" 716 "Authentication Block: 320 bytes\n" 717 "Auxiliary Block: 768 bytes\n" 718 "Algorithm: SHA256_RSA2048\n" 719 "Rollback Index: 0\n" 720 "Flags: 0\n" 721 "Release String: ''\n" 722 "Descriptors:\n" 723 " Hashtree descriptor:\n" 724 " Version of dm-verity: 1\n" 725 " Image Size: 1052672 bytes\n" 726 " Tree Offset: 1052672\n" 727 " Tree Size: 16384 bytes\n" 728 " Data Block Size: 4096 bytes\n" 729 " Hash Block Size: 4096 bytes\n" 730 " FEC num roots: 0\n" 731 " FEC offset: 0\n" 732 " FEC size: 0 bytes\n" 733 " Hash Algorithm: sha1\n" 734 " Partition Name: foobar\n" 735 " Salt: d00df00d\n" 736 " Root Digest: " 737 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n", 738 InfoImage(ext_vbmeta_path)); 739 } 740 741 if (sparse_image) { 742 EXPECT_COMMAND(0, 743 "mv %s %s.sparse", 744 rootfs_path.value().c_str(), 745 rootfs_path.value().c_str()); 746 EXPECT_COMMAND(0, 747 "simg2img %s.sparse %s", 748 rootfs_path.value().c_str(), 749 rootfs_path.value().c_str()); 750 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str()); 751 } 752 753 // To check that we generate the correct hashtree we can use 754 // veritysetup(1) - another codebase for working with dm-verity 755 // hashtrees - to verify it. 756 // 757 // If we don't want to impose the requirement of having the 758 // veritysetup(1) command available on builders we can comment this 759 // out. 760 EXPECT_COMMAND(0, 761 "veritysetup --no-superblock --format=1 --hash=sha1 " 762 "--data-block-size=4096 --hash-block-size=4096 " 763 "--salt=d00df00d " 764 "--data-blocks=257 " 765 "--hash-offset=1052672 " 766 "verify " 767 "%s %s " 768 "e811611467dcd6e8dc4324e45f706c2bdd51db67", 769 rootfs_path.value().c_str(), 770 rootfs_path.value().c_str()); 771 772 // Now check that we can find the VBMeta block again from the footer. 773 std::string part_data; 774 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data)); 775 776 // Check footer contains correct data. 777 AvbFooter f; 778 EXPECT_NE(0, 779 avb_footer_validate_and_byteswap( 780 reinterpret_cast<const AvbFooter*>( 781 part_data.data() + part_data.size() - AVB_FOOTER_SIZE), 782 &f)); 783 EXPECT_EQ( 784 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN), 785 AVB_FOOTER_MAGIC); 786 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major); 787 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor); 788 EXPECT_EQ(1052672UL, f.original_image_size); 789 EXPECT_EQ(1069056UL, f.vbmeta_offset); 790 EXPECT_EQ(1344UL, f.vbmeta_size); 791 792 // Check that the vbmeta image at |f.vbmeta_offset| checks out. 793 const uint8_t* vbmeta_data = 794 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset); 795 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 796 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL)); 797 798 // Collect all descriptors. 799 std::vector<const AvbDescriptor*> descriptors; 800 avb_descriptor_foreach( 801 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors); 802 803 // We should only have a single descriptor and it should be a 804 // hashtree descriptor. 805 EXPECT_EQ(1UL, descriptors.size()); 806 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag)); 807 AvbHashtreeDescriptor d; 808 EXPECT_NE( 809 0, 810 avb_hashtree_descriptor_validate_and_byteswap( 811 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d)); 812 EXPECT_EQ(1UL, d.dm_verity_version); 813 EXPECT_EQ(1052672UL, d.image_size); 814 EXPECT_EQ(1052672UL, d.tree_offset); 815 EXPECT_EQ(16384UL, d.tree_size); 816 EXPECT_EQ(4096UL, d.data_block_size); 817 EXPECT_EQ(4096UL, d.hash_block_size); 818 EXPECT_EQ(6UL, d.partition_name_len); 819 EXPECT_EQ(4UL, d.salt_len); 820 EXPECT_EQ(20UL, d.root_digest_len); 821 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) + 822 sizeof(AvbHashtreeDescriptor); 823 uint64_t o = 0; 824 EXPECT_EQ("foobar", 825 std::string(reinterpret_cast<const char*>(desc_end + o), 826 d.partition_name_len)); 827 o += d.partition_name_len; 828 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len)); 829 o += d.salt_len; 830 EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67", 831 mem_to_hexstring(desc_end + o, d.root_digest_len)); 832 833 // Check that we correctly generate dm-verity kernel cmdline 834 // snippets, if requested. 835 base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin"); 836 EXPECT_COMMAND(0, 837 "./avbtool make_vbmeta_image " 838 "--output %s " 839 "--setup_rootfs_from_kernel %s " 840 "--algorithm SHA256_RSA2048 " 841 "--key test/data/testkey_rsa2048.pem " 842 "--internal_release_string \"\"", 843 vbmeta_dmv_path.value().c_str(), 844 rootfs_path.value().c_str()); 845 846 ASSERT_EQ( 847 "Minimum libavb version: 1.0\n" 848 "Header Block: 256 bytes\n" 849 "Authentication Block: 320 bytes\n" 850 "Auxiliary Block: 896 bytes\n" 851 "Algorithm: SHA256_RSA2048\n" 852 "Rollback Index: 0\n" 853 "Flags: 0\n" 854 "Release String: ''\n" 855 "Descriptors:\n" 856 " Kernel Cmdline descriptor:\n" 857 " Flags: 1\n" 858 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 " 859 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) " 860 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 " 861 "d00df00d 2 restart_on_corruption ignore_zero_blocks\" root=/dev/dm-0'\n" 862 " Kernel Cmdline descriptor:\n" 863 " Flags: 2\n" 864 " Kernel Cmdline: " 865 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n", 866 InfoImage(vbmeta_dmv_path)); 867 868 // Check that the footer is correctly erased and the hashtree 869 // remains - see above for why the constant 1069056 is used. 870 EXPECT_COMMAND(0, 871 "./avbtool erase_footer --image %s --keep_hashtree", 872 rootfs_path.value().c_str()); 873 int64_t erased_footer_file_size; 874 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size)); 875 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1069056UL); 876 877 // Check that --do_not_append_vbmeta_image works as intended. 878 // 879 // For this we need to reset the size of the image to the original 880 // size because it's not possible to identify the existing hashtree. 881 EXPECT_COMMAND( 882 0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str()); 883 EXPECT_COMMAND(0, 884 "./avbtool add_hashtree_footer --salt d00df00d --image %s " 885 "--partition_size %d --partition_name foobar " 886 "--algorithm SHA256_RSA2048 " 887 "--key test/data/testkey_rsa2048.pem " 888 "--output_vbmeta %s_2nd_run --do_not_append_vbmeta_image " 889 "--internal_release_string \"\"", 890 rootfs_path.value().c_str(), 891 (int)partition_size, 892 ext_vbmeta_path.value().c_str()); 893 int64_t file_size; 894 ASSERT_TRUE(base::GetFileSize(rootfs_path, &file_size)); 895 EXPECT_EQ(static_cast<size_t>(file_size), 1069056UL); 896 EXPECT_COMMAND(0, 897 "diff %s %s_2nd_run", 898 ext_vbmeta_path.value().c_str(), 899 ext_vbmeta_path.value().c_str()); 900} 901 902TEST_F(AvbToolTest, AddHashtreeFooter) { 903 AddHashtreeFooterTest(false); 904} 905 906TEST_F(AvbToolTest, AddHashtreeFooterSparse) { 907 AddHashtreeFooterTest(true); 908} 909 910void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) { 911 const size_t rootfs_size = 1028 * 1024; 912 const size_t partition_size = 1536 * 1024; 913 914 // Generate a 1028 KiB file with known content. 915 std::vector<uint8_t> rootfs; 916 rootfs.resize(rootfs_size); 917 for (size_t n = 0; n < rootfs_size; n++) 918 rootfs[n] = uint8_t(n); 919 base::FilePath rootfs_path = testdir_.Append("rootfs.bin"); 920 EXPECT_EQ(rootfs_size, 921 static_cast<const size_t>( 922 base::WriteFile(rootfs_path, 923 reinterpret_cast<const char*>(rootfs.data()), 924 rootfs.size()))); 925 926 if (sparse_image) { 927 EXPECT_COMMAND(0, 928 "mv %s %s.unsparse", 929 rootfs_path.value().c_str(), 930 rootfs_path.value().c_str()); 931 EXPECT_COMMAND(0, 932 "img2simg %s.unsparse %s", 933 rootfs_path.value().c_str(), 934 rootfs_path.value().c_str()); 935 EXPECT_COMMAND(0, "rm -f %s.unsparse", rootfs_path.value().c_str()); 936 } 937 938 /* Do this twice to check that 'add_hashtree_footer' is idempotent. */ 939 for (int n = 0; n < 2; n++) { 940 EXPECT_COMMAND(0, 941 "./avbtool add_hashtree_footer --salt d00df00d --image %s " 942 "--partition_size %d --partition_name foobar " 943 "--generate_fec " 944 "--algorithm SHA256_RSA2048 " 945 "--key test/data/testkey_rsa2048.pem " 946 "--internal_release_string \"\"", 947 rootfs_path.value().c_str(), 948 (int)partition_size); 949 950 ASSERT_EQ(base::StringPrintf("Footer version: 1.0\n" 951 "Image size: 1572864 bytes\n" 952 "Original image size: 1052672 bytes\n" 953 "VBMeta offset: 1085440\n" 954 "VBMeta size: 1344 bytes\n" 955 "--\n" 956 "Minimum libavb version: 1.0%s\n" 957 "Header Block: 256 bytes\n" 958 "Authentication Block: 320 bytes\n" 959 "Auxiliary Block: 768 bytes\n" 960 "Algorithm: SHA256_RSA2048\n" 961 "Rollback Index: 0\n" 962 "Flags: 0\n" 963 "Release String: ''\n" 964 "Descriptors:\n" 965 " Hashtree descriptor:\n" 966 " Version of dm-verity: 1\n" 967 " Image Size: 1052672 bytes\n" 968 " Tree Offset: 1052672\n" 969 " Tree Size: 16384 bytes\n" 970 " Data Block Size: 4096 bytes\n" 971 " Hash Block Size: 4096 bytes\n" 972 " FEC num roots: 2\n" 973 " FEC offset: 1069056\n" 974 " FEC size: 16384 bytes\n" 975 " Hash Algorithm: sha1\n" 976 " Partition Name: foobar\n" 977 " Salt: d00df00d\n" 978 " Root Digest: " 979 "e811611467dcd6e8dc4324e45f706c2bdd51db67\n", 980 sparse_image ? " (Sparse)" : ""), 981 InfoImage(rootfs_path)); 982 } 983 984 if (sparse_image) { 985 EXPECT_COMMAND(0, 986 "mv %s %s.sparse", 987 rootfs_path.value().c_str(), 988 rootfs_path.value().c_str()); 989 EXPECT_COMMAND(0, 990 "simg2img %s.sparse %s", 991 rootfs_path.value().c_str(), 992 rootfs_path.value().c_str()); 993 EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str()); 994 } 995 996 /* TODO: would be nice to verify that the FEC data is correct. */ 997 998 // Now check that we can find the VBMeta block again from the footer. 999 std::string part_data; 1000 ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data)); 1001 1002 // Check footer contains correct data. 1003 AvbFooter f; 1004 EXPECT_NE(0, 1005 avb_footer_validate_and_byteswap( 1006 reinterpret_cast<const AvbFooter*>( 1007 part_data.data() + part_data.size() - AVB_FOOTER_SIZE), 1008 &f)); 1009 EXPECT_EQ( 1010 std::string(reinterpret_cast<const char*>(f.magic), AVB_FOOTER_MAGIC_LEN), 1011 AVB_FOOTER_MAGIC); 1012 EXPECT_EQ(AVB_FOOTER_VERSION_MAJOR, (int)f.version_major); 1013 EXPECT_EQ(AVB_FOOTER_VERSION_MINOR, (int)f.version_minor); 1014 EXPECT_EQ(1052672UL, f.original_image_size); 1015 EXPECT_EQ(1085440UL, f.vbmeta_offset); 1016 EXPECT_EQ(1344UL, f.vbmeta_size); 1017 1018 // Check that the vbmeta image at |f.vbmeta_offset| checks out. 1019 const uint8_t* vbmeta_data = 1020 reinterpret_cast<const uint8_t*>(part_data.data() + f.vbmeta_offset); 1021 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 1022 avb_vbmeta_image_verify(vbmeta_data, f.vbmeta_size, NULL, NULL)); 1023 1024 // Collect all descriptors. 1025 std::vector<const AvbDescriptor*> descriptors; 1026 avb_descriptor_foreach( 1027 vbmeta_data, f.vbmeta_size, collect_descriptors, &descriptors); 1028 1029 // We should only have a single descriptor and it should be a 1030 // hashtree descriptor. 1031 EXPECT_EQ(1UL, descriptors.size()); 1032 EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, avb_be64toh(descriptors[0]->tag)); 1033 AvbHashtreeDescriptor d; 1034 EXPECT_NE( 1035 0, 1036 avb_hashtree_descriptor_validate_and_byteswap( 1037 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[0]), &d)); 1038 EXPECT_EQ(1UL, d.dm_verity_version); 1039 EXPECT_EQ(1052672UL, d.image_size); 1040 EXPECT_EQ(1052672UL, d.tree_offset); 1041 EXPECT_EQ(16384UL, d.tree_size); 1042 EXPECT_EQ(4096UL, d.data_block_size); 1043 EXPECT_EQ(2UL, d.fec_num_roots); 1044 EXPECT_EQ(1069056UL, d.fec_offset); 1045 EXPECT_EQ(16384UL, d.fec_size); 1046 EXPECT_EQ(6UL, d.partition_name_len); 1047 EXPECT_EQ(4UL, d.salt_len); 1048 EXPECT_EQ(20UL, d.root_digest_len); 1049 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) + 1050 sizeof(AvbHashtreeDescriptor); 1051 uint64_t o = 0; 1052 EXPECT_EQ("foobar", 1053 std::string(reinterpret_cast<const char*>(desc_end + o), 1054 d.partition_name_len)); 1055 o += d.partition_name_len; 1056 EXPECT_EQ("d00df00d", mem_to_hexstring(desc_end + o, d.salt_len)); 1057 o += d.salt_len; 1058 EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67", 1059 mem_to_hexstring(desc_end + o, d.root_digest_len)); 1060 1061 // Check that we correctly generate dm-verity kernel cmdline 1062 // snippets, if requested. 1063 base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin"); 1064 EXPECT_COMMAND(0, 1065 "./avbtool make_vbmeta_image " 1066 "--output %s " 1067 "--setup_rootfs_from_kernel %s " 1068 "--algorithm SHA256_RSA2048 " 1069 "--key test/data/testkey_rsa2048.pem " 1070 "--internal_release_string \"\"", 1071 vbmeta_dmv_path.value().c_str(), 1072 rootfs_path.value().c_str()); 1073 1074 ASSERT_EQ( 1075 "Minimum libavb version: 1.0\n" 1076 "Header Block: 256 bytes\n" 1077 "Authentication Block: 320 bytes\n" 1078 "Auxiliary Block: 960 bytes\n" 1079 "Algorithm: SHA256_RSA2048\n" 1080 "Rollback Index: 0\n" 1081 "Flags: 0\n" 1082 "Release String: ''\n" 1083 "Descriptors:\n" 1084 " Kernel Cmdline descriptor:\n" 1085 " Flags: 1\n" 1086 " Kernel Cmdline: 'dm=\"1 vroot none ro 1,0 2056 verity 1 " 1087 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) " 1088 "4096 4096 257 257 sha1 e811611467dcd6e8dc4324e45f706c2bdd51db67 " 1089 "d00df00d 10 restart_on_corruption ignore_zero_blocks " 1090 "use_fec_from_device " 1091 "PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 261 " 1092 "fec_start 261\" root=/dev/dm-0'\n" 1093 " Kernel Cmdline descriptor:\n" 1094 " Flags: 2\n" 1095 " Kernel Cmdline: " 1096 "'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'\n", 1097 InfoImage(vbmeta_dmv_path)); 1098 1099 // Check that the footer is correctly erased and the hashtree and 1100 // FEC data remains. The constant 1085440 is used because it's where 1101 // the FEC data ends (it's at offset 1069056 and size 16384). 1102 EXPECT_COMMAND(0, 1103 "./avbtool erase_footer --image %s --keep_hashtree", 1104 rootfs_path.value().c_str()); 1105 int64_t erased_footer_file_size; 1106 ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size)); 1107 EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), 1085440UL); 1108} 1109 1110TEST_F(AvbToolTest, AddHashtreeFooterFEC) { 1111 AddHashtreeFooterFECTest(false); 1112} 1113 1114TEST_F(AvbToolTest, AddHashtreeFooterFECSparse) { 1115 AddHashtreeFooterFECTest(true); 1116} 1117 1118TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSize) { 1119 const size_t partition_size = 10 * 1024 * 1024; 1120 base::FilePath output_path = testdir_.Append("max_size.txt"); 1121 1122 EXPECT_COMMAND(0, 1123 "./avbtool add_hashtree_footer " 1124 "--partition_size %zd --calc_max_image_size > %s", 1125 partition_size, 1126 output_path.value().c_str()); 1127 std::string max_image_size_data; 1128 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data)); 1129 EXPECT_EQ("10330112\n", max_image_size_data); 1130 size_t max_image_size = atoll(max_image_size_data.c_str()); 1131 1132 // Hashtree and metadata takes up 152 KiB - compare to below with 1133 // FEC which is 244 KiB. 1134 EXPECT_EQ(152 * 1024ULL, partition_size - max_image_size); 1135 1136 // Check that we can add a hashtree with an image this size for such 1137 // a partition size. 1138 base::FilePath system_path = GenerateImage("system", max_image_size); 1139 EXPECT_COMMAND(0, 1140 "./avbtool add_hashtree_footer" 1141 " --image %s" 1142 " --partition_name system" 1143 " --partition_size %zd" 1144 " --salt deadbeef" 1145 " --algorithm SHA512_RSA4096 " 1146 " --key test/data/testkey_rsa4096.pem" 1147 " --internal_release_string \"\"", 1148 system_path.value().c_str(), 1149 partition_size); 1150} 1151 1152TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) { 1153 const size_t partition_size = 10 * 1024 * 1024; 1154 base::FilePath output_path = testdir_.Append("max_size.txt"); 1155 1156 EXPECT_COMMAND(0, 1157 "./avbtool add_hashtree_footer " 1158 "--partition_size %zd --generate_fec " 1159 "--calc_max_image_size > %s", 1160 partition_size, 1161 output_path.value().c_str()); 1162 std::string max_image_size_data; 1163 EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data)); 1164 EXPECT_EQ("10235904\n", max_image_size_data); 1165 size_t max_image_size = atoll(max_image_size_data.c_str()); 1166 1167 // Hashtree, FEC codes, and metadata takes up 244 KiB - compare to 1168 // above wihtout FEC which is 152 KiB. 1169 EXPECT_EQ(244 * 1024ULL, partition_size - max_image_size); 1170 1171 // Check that we can add a hashtree with an image this size for such 1172 // a partition size. 1173 base::FilePath system_path = GenerateImage("system", max_image_size); 1174 EXPECT_COMMAND(0, 1175 "./avbtool add_hashtree_footer" 1176 " --image %s" 1177 " --partition_name system" 1178 " --partition_size %zd" 1179 " --salt deadbeef" 1180 " --generate_fec " 1181 " --algorithm SHA512_RSA4096 " 1182 " --key test/data/testkey_rsa4096.pem" 1183 " --internal_release_string \"\"", 1184 system_path.value().c_str(), 1185 partition_size); 1186} 1187 1188TEST_F(AvbToolTest, KernelCmdlineDescriptor) { 1189 base::FilePath vbmeta_path = 1190 testdir_.Append("vbmeta_kernel_cmdline_desc.bin"); 1191 1192 EXPECT_COMMAND(0, 1193 "./avbtool make_vbmeta_image " 1194 "--output %s " 1195 "--kernel_cmdline 'foo bar baz' " 1196 "--kernel_cmdline 'second cmdline' " 1197 "--algorithm SHA256_RSA2048 " 1198 "--key test/data/testkey_rsa2048.pem " 1199 "--internal_release_string \"\"", 1200 vbmeta_path.value().c_str()); 1201 1202 ASSERT_EQ( 1203 "Minimum libavb version: 1.0\n" 1204 "Header Block: 256 bytes\n" 1205 "Authentication Block: 320 bytes\n" 1206 "Auxiliary Block: 640 bytes\n" 1207 "Algorithm: SHA256_RSA2048\n" 1208 "Rollback Index: 0\n" 1209 "Flags: 0\n" 1210 "Release String: ''\n" 1211 "Descriptors:\n" 1212 " Kernel Cmdline descriptor:\n" 1213 " Flags: 0\n" 1214 " Kernel Cmdline: 'foo bar baz'\n" 1215 " Kernel Cmdline descriptor:\n" 1216 " Flags: 0\n" 1217 " Kernel Cmdline: 'second cmdline'\n", 1218 InfoImage(vbmeta_path)); 1219 1220 // Now check the VBMeta image. 1221 std::string image_data; 1222 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data)); 1223 1224 const uint8_t* vbmeta_data = 1225 reinterpret_cast<const uint8_t*>(image_data.data()); 1226 const size_t vbmeta_size = image_data.length(); 1227 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 1228 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL)); 1229 1230 // Collect all descriptors. 1231 std::vector<const AvbDescriptor*> descriptors; 1232 avb_descriptor_foreach( 1233 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors); 1234 1235 // We should have two descriptors - check them. 1236 EXPECT_EQ(2UL, descriptors.size()); 1237 AvbKernelCmdlineDescriptor d; 1238 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE, 1239 avb_be64toh(descriptors[0]->tag)); 1240 EXPECT_NE( 1241 0, 1242 avb_kernel_cmdline_descriptor_validate_and_byteswap( 1243 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[0]), 1244 &d)); 1245 EXPECT_EQ("foo bar baz", 1246 std::string(reinterpret_cast<const char*>(descriptors[0]) + 1247 sizeof(AvbKernelCmdlineDescriptor), 1248 d.kernel_cmdline_length)); 1249 EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE, 1250 avb_be64toh(descriptors[1]->tag)); 1251 EXPECT_NE( 1252 0, 1253 avb_kernel_cmdline_descriptor_validate_and_byteswap( 1254 reinterpret_cast<const AvbKernelCmdlineDescriptor*>(descriptors[1]), 1255 &d)); 1256 EXPECT_EQ("second cmdline", 1257 std::string(reinterpret_cast<const char*>(descriptors[1]) + 1258 sizeof(AvbKernelCmdlineDescriptor), 1259 d.kernel_cmdline_length)); 1260} 1261 1262TEST_F(AvbToolTest, IncludeDescriptor) { 1263 base::FilePath vbmeta1_path = testdir_.Append("vbmeta_id1.bin"); 1264 base::FilePath vbmeta2_path = testdir_.Append("vbmeta_id2.bin"); 1265 base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin"); 1266 1267 EXPECT_COMMAND(0, 1268 "./avbtool make_vbmeta_image " 1269 "--output %s " 1270 "--kernel_cmdline 'something' " 1271 "--prop name:value " 1272 "--internal_release_string \"\"", 1273 vbmeta1_path.value().c_str()); 1274 1275 EXPECT_COMMAND(0, 1276 "./avbtool make_vbmeta_image " 1277 "--output %s " 1278 "--prop name2:value2 " 1279 "--prop name3:value3 " 1280 "--internal_release_string \"\"", 1281 vbmeta2_path.value().c_str()); 1282 1283 EXPECT_COMMAND(0, 1284 "./avbtool make_vbmeta_image " 1285 "--output %s " 1286 "--prop name4:value4 " 1287 "--include_descriptors_from_image %s " 1288 "--include_descriptors_from_image %s " 1289 "--internal_release_string \"\"", 1290 vbmeta3_path.value().c_str(), 1291 vbmeta1_path.value().c_str(), 1292 vbmeta2_path.value().c_str()); 1293 1294 ASSERT_EQ( 1295 "Minimum libavb version: 1.0\n" 1296 "Header Block: 256 bytes\n" 1297 "Authentication Block: 0 bytes\n" 1298 "Auxiliary Block: 256 bytes\n" 1299 "Algorithm: NONE\n" 1300 "Rollback Index: 0\n" 1301 "Flags: 0\n" 1302 "Release String: ''\n" 1303 "Descriptors:\n" 1304 " Prop: name4 -> 'value4'\n" 1305 " Prop: name -> 'value'\n" 1306 " Kernel Cmdline descriptor:\n" 1307 " Flags: 0\n" 1308 " Kernel Cmdline: 'something'\n" 1309 " Prop: name2 -> 'value2'\n" 1310 " Prop: name3 -> 'value3'\n", 1311 InfoImage(vbmeta3_path)); 1312} 1313 1314TEST_F(AvbToolTest, ChainedPartition) { 1315 base::FilePath vbmeta_path = testdir_.Append("vbmeta_cp.bin"); 1316 1317 base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey"); 1318 1319 EXPECT_COMMAND( 1320 0, 1321 "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem" 1322 " --output %s", 1323 pk_path.value().c_str()); 1324 1325 EXPECT_COMMAND( 1326 0, 1327 "./avbtool make_vbmeta_image " 1328 "--output %s " 1329 "--chain_partition system:1:%s " 1330 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1331 "--internal_release_string \"\"", 1332 vbmeta_path.value().c_str(), 1333 pk_path.value().c_str()); 1334 1335 ASSERT_EQ( 1336 "Minimum libavb version: 1.0\n" 1337 "Header Block: 256 bytes\n" 1338 "Authentication Block: 320 bytes\n" 1339 "Auxiliary Block: 1152 bytes\n" 1340 "Algorithm: SHA256_RSA2048\n" 1341 "Rollback Index: 0\n" 1342 "Flags: 0\n" 1343 "Release String: ''\n" 1344 "Descriptors:\n" 1345 " Chain Partition descriptor:\n" 1346 " Partition Name: system\n" 1347 " Rollback Index Location: 1\n" 1348 " Public key (sha1): " 1349 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n", 1350 InfoImage(vbmeta_path)); 1351 1352 // Now check the VBMeta image. 1353 std::string image_data; 1354 ASSERT_TRUE(base::ReadFileToString(vbmeta_path, &image_data)); 1355 1356 const uint8_t* vbmeta_data = 1357 reinterpret_cast<const uint8_t*>(image_data.data()); 1358 const size_t vbmeta_size = image_data.length(); 1359 EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK, 1360 avb_vbmeta_image_verify(vbmeta_data, vbmeta_size, NULL, NULL)); 1361 1362 // Collect all descriptors. 1363 std::vector<const AvbDescriptor*> descriptors; 1364 avb_descriptor_foreach( 1365 vbmeta_data, vbmeta_size, collect_descriptors, &descriptors); 1366 1367 // We should have one descriptor - check it. 1368 EXPECT_EQ(1UL, descriptors.size()); 1369 1370 std::string pk_data; 1371 ASSERT_TRUE(base::ReadFileToString(pk_path, &pk_data)); 1372 1373 AvbChainPartitionDescriptor d; 1374 EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION, 1375 avb_be64toh(descriptors[0]->tag)); 1376 EXPECT_NE( 1377 0, 1378 avb_chain_partition_descriptor_validate_and_byteswap( 1379 reinterpret_cast<const AvbChainPartitionDescriptor*>(descriptors[0]), 1380 &d)); 1381 const uint8_t* desc_end = reinterpret_cast<const uint8_t*>(descriptors[0]) + 1382 sizeof(AvbChainPartitionDescriptor); 1383 uint64_t o = 0; 1384 EXPECT_EQ("system", 1385 std::string(reinterpret_cast<const char*>(desc_end + o), 1386 d.partition_name_len)); 1387 o += d.partition_name_len; 1388 EXPECT_EQ(pk_data, 1389 std::string(reinterpret_cast<const char*>(descriptors[0]) + 1390 sizeof(AvbChainPartitionDescriptor) + o, 1391 d.public_key_len)); 1392} 1393 1394TEST_F(AvbToolTest, AppendVBMetaImage) { 1395 size_t boot_size = 5 * 1024 * 1024; 1396 size_t boot_partition_size = 32 * 1024 * 1024; 1397 base::FilePath boot_path = GenerateImage("boot", boot_size); 1398 1399 GenerateVBMetaImage("vbmeta.img", 1400 "SHA256_RSA2048", 1401 0, 1402 base::FilePath("test/data/testkey_rsa2048.pem"), 1403 std::string("--append_to_release_string \"\" " 1404 "--kernel_cmdline foo")); 1405 1406 EXPECT_COMMAND(0, 1407 "./avbtool append_vbmeta_image " 1408 "--image %s " 1409 "--partition_size %d " 1410 "--vbmeta_image %s ", 1411 boot_path.value().c_str(), 1412 (int)boot_partition_size, 1413 vbmeta_image_path_.value().c_str()); 1414 1415 std::string vbmeta_contents = InfoImage(vbmeta_image_path_); 1416 std::string boot_contents = InfoImage(boot_path); 1417 1418 // Check that boot.img has the same vbmeta blob as from vbmeta.img - 1419 // we do this by inspecting 'avbtool info_image' output combined 1420 // with the known footer location given boot.img has 5 MiB known 1421 // content and the partition size is 32 MiB. 1422 ASSERT_EQ( 1423 "Minimum libavb version: 1.0\n" 1424 "Header Block: 256 bytes\n" 1425 "Authentication Block: 320 bytes\n" 1426 "Auxiliary Block: 576 bytes\n" 1427 "Algorithm: SHA256_RSA2048\n" 1428 "Rollback Index: 0\n" 1429 "Flags: 0\n" 1430 "Release String: 'avbtool 1.0.0 '\n" 1431 "Descriptors:\n" 1432 " Kernel Cmdline descriptor:\n" 1433 " Flags: 0\n" 1434 " Kernel Cmdline: 'foo'\n", 1435 vbmeta_contents); 1436 std::string known_footer = 1437 "Footer version: 1.0\n" 1438 "Image size: 33554432 bytes\n" 1439 "Original image size: 5242880 bytes\n" 1440 "VBMeta offset: 5242880\n" 1441 "VBMeta size: 1152 bytes\n" 1442 "--\n"; 1443 ASSERT_EQ(known_footer + vbmeta_contents, boot_contents); 1444 1445 // Also verify that the blobs are the same, bit for bit. 1446 base::File f = 1447 base::File(boot_path, base::File::FLAG_OPEN | base::File::FLAG_READ); 1448 std::vector<uint8_t> loaded_vbmeta; 1449 loaded_vbmeta.resize(1152); 1450 EXPECT_EQ( 1451 f.Read( 1452 5 * 1024 * 1024, reinterpret_cast<char*>(loaded_vbmeta.data()), 1152), 1453 1152); 1454 EXPECT_EQ(vbmeta_image_, loaded_vbmeta); 1455} 1456 1457TEST_F(AvbToolTest, SigningHelperBasic) { 1458 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin"); 1459 base::FilePath signing_helper_test_path = 1460 testdir_.Append("signing_helper_test"); 1461 EXPECT_COMMAND( 1462 0, 1463 "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image " 1464 "--output %s " 1465 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1466 "--signing_helper test/avbtool_signing_helper_test.py " 1467 "--internal_release_string \"\"", 1468 signing_helper_test_path.value().c_str(), 1469 vbmeta_path.value().c_str()); 1470 1471 // Now check the value in test file. 1472 std::string value; 1473 ASSERT_TRUE(base::ReadFileToString(signing_helper_test_path, &value)); 1474 EXPECT_EQ("DONE", value); 1475} 1476 1477TEST_F(AvbToolTest, SigningHelperReturnError) { 1478 base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin"); 1479 EXPECT_COMMAND( 1480 1, 1481 "./avbtool make_vbmeta_image " 1482 "--output %s " 1483 "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem " 1484 "--signing_helper test/avbtool_signing_helper_test.py " 1485 "--internal_release_string \"\"", 1486 vbmeta_path.value().c_str()); 1487} 1488 1489TEST_F(AvbToolTest, MakeAtxPikCertificate) { 1490 base::FilePath subject_path = testdir_.Append("tmp_subject"); 1491 ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16)); 1492 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem"); 1493 EXPECT_COMMAND( 1494 0, 1495 "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s", 1496 pubkey_path.value().c_str()); 1497 1498 base::FilePath output_path = testdir_.Append("tmp_certificate.bin"); 1499 EXPECT_COMMAND(0, 1500 "./avbtool make_atx_certificate" 1501 " --subject %s" 1502 " --subject_key %s" 1503 " --subject_key_version 42" 1504 " --subject_is_intermediate_authority" 1505 " --authority_key test/data/testkey_atx_prk.pem" 1506 " --output %s", 1507 subject_path.value().c_str(), 1508 pubkey_path.value().c_str(), 1509 output_path.value().c_str()); 1510 1511 EXPECT_COMMAND(0, 1512 "diff test/data/atx_pik_certificate.bin %s", 1513 output_path.value().c_str()); 1514} 1515 1516TEST_F(AvbToolTest, MakeAtxPskCertificate) { 1517 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem"); 1518 EXPECT_COMMAND( 1519 0, 1520 "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s", 1521 pubkey_path.value().c_str()); 1522 1523 base::FilePath output_path = testdir_.Append("tmp_certificate.bin"); 1524 EXPECT_COMMAND(0, 1525 "./avbtool make_atx_certificate" 1526 " --subject test/data/atx_product_id.bin" 1527 " --subject_key %s" 1528 " --subject_key_version 42" 1529 " --authority_key test/data/testkey_atx_pik.pem" 1530 " --output %s", 1531 pubkey_path.value().c_str(), 1532 output_path.value().c_str()); 1533 1534 EXPECT_COMMAND(0, 1535 "diff test/data/atx_psk_certificate.bin %s", 1536 output_path.value().c_str()); 1537} 1538 1539TEST_F(AvbToolTest, MakeAtxPermanentAttributes) { 1540 base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem"); 1541 EXPECT_COMMAND( 1542 0, 1543 "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s", 1544 pubkey_path.value().c_str()); 1545 1546 base::FilePath output_path = testdir_.Append("tmp_attributes.bin"); 1547 EXPECT_COMMAND(0, 1548 "./avbtool make_atx_permanent_attributes" 1549 " --root_authority_key %s" 1550 " --product_id test/data/atx_product_id.bin" 1551 " --output %s", 1552 pubkey_path.value().c_str(), 1553 output_path.value().c_str()); 1554 1555 EXPECT_COMMAND(0, 1556 "diff test/data/atx_permanent_attributes.bin %s", 1557 output_path.value().c_str()); 1558} 1559 1560TEST_F(AvbToolTest, MakeAtxMetadata) { 1561 base::FilePath output_path = testdir_.Append("tmp_metadata.bin"); 1562 1563 EXPECT_COMMAND( 1564 0, 1565 "./avbtool make_atx_metadata" 1566 " --intermediate_key_certificate test/data/atx_pik_certificate.bin" 1567 " --product_key_certificate test/data/atx_psk_certificate.bin" 1568 " --output %s", 1569 output_path.value().c_str()); 1570 1571 EXPECT_COMMAND( 1572 0, "diff test/data/atx_metadata.bin %s", output_path.value().c_str()); 1573} 1574 1575} // namespace avb 1576