fs_mgr_avb.cpp revision 72ffff70fcd540a38b0a344386d10315c3b560c1
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <errno.h> 18#include <fcntl.h> 19#include <inttypes.h> 20#include <libgen.h> 21#include <stdio.h> 22#include <string.h> 23#include <sys/stat.h> 24#include <sys/types.h> 25#include <unistd.h> 26#include <vector> 27 28#include <android-base/file.h> 29#include <android-base/parseint.h> 30#include <android-base/properties.h> 31#include <android-base/strings.h> 32#include <android-base/unique_fd.h> 33#include <cutils/properties.h> 34#include <libavb/libavb.h> 35#include <openssl/sha.h> 36#include <sys/ioctl.h> 37#include <utils/Compat.h> 38 39#include "fs_mgr.h" 40#include "fs_mgr_avb_ops.h" 41#include "fs_mgr_priv.h" 42#include "fs_mgr_priv_avb.h" 43#include "fs_mgr_priv_dm_ioctl.h" 44#include "fs_mgr_priv_sha.h" 45 46/* The format of dm-verity construction parameters: 47 * <version> <dev> <hash_dev> <data_block_size> <hash_block_size> 48 * <num_data_blocks> <hash_start_block> <algorithm> <digest> <salt> 49 */ 50#define VERITY_TABLE_FORMAT \ 51 "%u %s %s %u %u " \ 52 "%" PRIu64 " %" PRIu64 " %s %s %s " 53 54#define VERITY_TABLE_PARAMS(hashtree_desc, blk_device, digest, salt) \ 55 hashtree_desc.dm_verity_version, blk_device, blk_device, \ 56 hashtree_desc.data_block_size, hashtree_desc.hash_block_size, \ 57 hashtree_desc.image_size / \ 58 hashtree_desc.data_block_size, /* num_data_blocks. */ \ 59 hashtree_desc.tree_offset / \ 60 hashtree_desc.hash_block_size, /* hash_start_block. */ \ 61 (char *)hashtree_desc.hash_algorithm, digest, salt 62 63#define VERITY_TABLE_OPT_RESTART "restart_on_corruption" 64#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks" 65 66/* The default format of dm-verity optional parameters: 67 * <#opt_params> ignore_zero_blocks restart_on_corruption 68 */ 69#define VERITY_TABLE_OPT_DEFAULT_FORMAT "2 %s %s" 70#define VERITY_TABLE_OPT_DEFAULT_PARAMS \ 71 VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART 72 73/* The FEC (forward error correction) format of dm-verity optional parameters: 74 * <#opt_params> use_fec_from_device <fec_dev> 75 * fec_roots <num> fec_blocks <num> fec_start <offset> 76 * ignore_zero_blocks restart_on_corruption 77 */ 78#define VERITY_TABLE_OPT_FEC_FORMAT \ 79 "10 use_fec_from_device %s fec_roots %u fec_blocks %" PRIu64 \ 80 " fec_start %" PRIu64 " %s %s" 81 82/* Note that fec_blocks is the size that FEC covers, *not* the 83 * size of the FEC data. Since we use FEC for everything up until 84 * the FEC data, it's the same as the offset (fec_start). 85 */ 86#define VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device) \ 87 blk_device, hashtree_desc.fec_num_roots, \ 88 hashtree_desc.fec_offset / \ 89 hashtree_desc.data_block_size, /* fec_blocks */ \ 90 hashtree_desc.fec_offset / \ 91 hashtree_desc.data_block_size, /* fec_start */ \ 92 VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART 93 94AvbSlotVerifyData *fs_mgr_avb_verify_data = nullptr; 95AvbOps *fs_mgr_avb_ops = nullptr; 96 97enum HashAlgorithm { 98 kInvalid = 0, 99 kSHA256 = 1, 100 kSHA512 = 2, 101}; 102 103struct androidboot_vbmeta { 104 HashAlgorithm hash_alg; 105 uint8_t digest[SHA512_DIGEST_LENGTH]; 106 size_t vbmeta_size; 107 bool allow_verification_error; 108}; 109 110androidboot_vbmeta fs_mgr_vbmeta_prop; 111 112static inline bool nibble_value(const char &c, uint8_t *value) 113{ 114 FS_MGR_CHECK(value != nullptr); 115 116 switch (c) { 117 case '0' ... '9': 118 *value = c - '0'; 119 break; 120 case 'a' ... 'f': 121 *value = c - 'a' + 10; 122 break; 123 case 'A' ... 'F': 124 *value = c - 'A' + 10; 125 break; 126 default: 127 return false; 128 } 129 130 return true; 131} 132 133static bool hex_to_bytes(uint8_t *bytes, 134 size_t bytes_len, 135 const std::string &hex) 136{ 137 FS_MGR_CHECK(bytes != nullptr); 138 139 if (hex.size() % 2 != 0) { 140 return false; 141 } 142 if (hex.size() / 2 > bytes_len) { 143 return false; 144 } 145 for (size_t i = 0, j = 0, n = hex.size(); i < n; i += 2, ++j) { 146 uint8_t high; 147 if (!nibble_value(hex[i], &high)) { 148 return false; 149 } 150 uint8_t low; 151 if (!nibble_value(hex[i + 1], &low)) { 152 return false; 153 } 154 bytes[j] = (high << 4) | low; 155 } 156 return true; 157} 158 159static std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len) 160{ 161 FS_MGR_CHECK(bytes != nullptr); 162 163 static const char *hex_digits = "0123456789abcdef"; 164 std::string hex; 165 166 for (size_t i = 0; i < bytes_len; i++) { 167 hex.push_back(hex_digits[(bytes[i] & 0xF0) >> 4]); 168 hex.push_back(hex_digits[bytes[i] & 0x0F]); 169 } 170 return hex; 171} 172 173static bool load_vbmeta_prop(androidboot_vbmeta *vbmeta_prop) 174{ 175 FS_MGR_CHECK(vbmeta_prop != nullptr); 176 177 std::string cmdline; 178 android::base::ReadFileToString("/proc/cmdline", &cmdline); 179 180 std::string hash_alg; 181 std::string digest; 182 183 for (const auto &entry : 184 android::base::Split(android::base::Trim(cmdline), " ")) { 185 std::vector<std::string> pieces = android::base::Split(entry, "="); 186 const std::string &key = pieces[0]; 187 const std::string &value = pieces[1]; 188 189 if (key == "androidboot.vbmeta.device_state") { 190 vbmeta_prop->allow_verification_error = (value == "unlocked"); 191 } else if (key == "androidboot.vbmeta.hash_alg") { 192 hash_alg = value; 193 } else if (key == "androidboot.vbmeta.size") { 194 if (!android::base::ParseUint(value.c_str(), 195 &vbmeta_prop->vbmeta_size)) { 196 return false; 197 } 198 } else if (key == "androidboot.vbmeta.digest") { 199 digest = value; 200 } 201 } 202 203 // Reads hash algorithm. 204 size_t expected_digest_size = 0; 205 if (hash_alg == "sha256") { 206 expected_digest_size = SHA256_DIGEST_LENGTH * 2; 207 vbmeta_prop->hash_alg = kSHA256; 208 } else if (hash_alg == "sha512") { 209 expected_digest_size = SHA512_DIGEST_LENGTH * 2; 210 vbmeta_prop->hash_alg = kSHA512; 211 } else { 212 LERROR << "Unknown hash algorithm: " << hash_alg.c_str(); 213 return false; 214 } 215 216 // Reads digest. 217 if (digest.size() != expected_digest_size) { 218 LERROR << "Unexpected digest size: " << digest.size() 219 << " (expected: " << expected_digest_size << ")"; 220 return false; 221 } 222 223 if (!hex_to_bytes(vbmeta_prop->digest, sizeof(vbmeta_prop->digest), 224 digest)) { 225 LERROR << "Hash digest contains non-hexidecimal character: " 226 << digest.c_str(); 227 return false; 228 } 229 230 return true; 231} 232 233template <typename Hasher> 234static std::pair<size_t, bool> verify_vbmeta_digest( 235 const AvbSlotVerifyData &verify_data, const androidboot_vbmeta &vbmeta_prop) 236{ 237 size_t total_size = 0; 238 Hasher hasher; 239 for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) { 240 hasher.update(verify_data.vbmeta_images[n].vbmeta_data, 241 verify_data.vbmeta_images[n].vbmeta_size); 242 total_size += verify_data.vbmeta_images[n].vbmeta_size; 243 } 244 245 bool matched = (memcmp(hasher.finalize(), vbmeta_prop.digest, 246 Hasher::DIGEST_SIZE) == 0); 247 248 return std::make_pair(total_size, matched); 249} 250 251static bool verify_vbmeta_images(const AvbSlotVerifyData &verify_data, 252 const androidboot_vbmeta &vbmeta_prop) 253{ 254 if (verify_data.num_vbmeta_images == 0) { 255 LERROR << "No vbmeta images"; 256 return false; 257 } 258 259 size_t total_size = 0; 260 bool digest_matched = false; 261 262 if (vbmeta_prop.hash_alg == kSHA256) { 263 std::tie(total_size, digest_matched) = 264 verify_vbmeta_digest<SHA256Hasher>(verify_data, vbmeta_prop); 265 } else if (vbmeta_prop.hash_alg == kSHA512) { 266 std::tie(total_size, digest_matched) = 267 verify_vbmeta_digest<SHA512Hasher>(verify_data, vbmeta_prop); 268 } 269 270 if (total_size != vbmeta_prop.vbmeta_size) { 271 LERROR << "total vbmeta size mismatch: " << total_size 272 << " (expected: " << vbmeta_prop.vbmeta_size << ")"; 273 return false; 274 } 275 276 if (!digest_matched) { 277 LERROR << "vbmeta digest mismatch"; 278 return false; 279 } 280 281 return true; 282} 283 284static bool hashtree_load_verity_table( 285 struct dm_ioctl *io, 286 const std::string &dm_device_name, 287 int fd, 288 const std::string &blk_device, 289 const AvbHashtreeDescriptor &hashtree_desc, 290 const std::string &salt, 291 const std::string &root_digest) 292{ 293 fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG); 294 295 // The buffer consists of [dm_ioctl][dm_target_spec][verity_params]. 296 char *buffer = (char *)io; 297 298 // Builds the dm_target_spec arguments. 299 struct dm_target_spec *dm_target = 300 (struct dm_target_spec *)&buffer[sizeof(struct dm_ioctl)]; 301 io->target_count = 1; 302 dm_target->status = 0; 303 dm_target->sector_start = 0; 304 dm_target->length = hashtree_desc.image_size / 512; 305 strcpy(dm_target->target_type, "verity"); 306 307 // Builds the verity params. 308 char *verity_params = 309 buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 310 size_t bufsize = DM_BUF_SIZE - (verity_params - buffer); 311 312 int res = 0; 313 if (hashtree_desc.fec_size > 0) { 314 res = snprintf( 315 verity_params, bufsize, 316 VERITY_TABLE_FORMAT VERITY_TABLE_OPT_FEC_FORMAT, 317 VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), 318 root_digest.c_str(), salt.c_str()), 319 VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device.c_str())); 320 } else { 321 res = snprintf(verity_params, bufsize, 322 VERITY_TABLE_FORMAT VERITY_TABLE_OPT_DEFAULT_FORMAT, 323 VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), 324 root_digest.c_str(), salt.c_str()), 325 VERITY_TABLE_OPT_DEFAULT_PARAMS); 326 } 327 328 if (res < 0 || (size_t)res >= bufsize) { 329 LERROR << "Error building verity table; insufficient buffer size?"; 330 return false; 331 } 332 333 LINFO << "Loading verity table: '" << verity_params << "'"; 334 335 // Sets ext target boundary. 336 verity_params += strlen(verity_params) + 1; 337 verity_params = (char *)(((unsigned long)verity_params + 7) & ~7); 338 dm_target->next = verity_params - buffer; 339 340 // Sends the ioctl to load the verity table. 341 if (ioctl(fd, DM_TABLE_LOAD, io)) { 342 PERROR << "Error loading verity table"; 343 return false; 344 } 345 346 return true; 347} 348 349static bool hashtree_dm_verity_setup(struct fstab_rec *fstab_entry, 350 const AvbHashtreeDescriptor &hashtree_desc, 351 const std::string &salt, 352 const std::string &root_digest) 353{ 354 // Gets the device mapper fd. 355 android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR)); 356 if (fd < 0) { 357 PERROR << "Error opening device mapper"; 358 return false; 359 } 360 361 // Creates the device. 362 alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; 363 struct dm_ioctl *io = (struct dm_ioctl *)buffer; 364 const std::string mount_point(basename(fstab_entry->mount_point)); 365 if (!fs_mgr_create_verity_device(io, mount_point, fd)) { 366 LERROR << "Couldn't create verity device!"; 367 return false; 368 } 369 370 // Gets the name of the device file. 371 std::string verity_blk_name; 372 if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) { 373 LERROR << "Couldn't get verity device number!"; 374 return false; 375 } 376 377 // Loads the verity mapping table. 378 if (!hashtree_load_verity_table(io, mount_point, fd, 379 std::string(fstab_entry->blk_device), 380 hashtree_desc, salt, root_digest)) { 381 LERROR << "Couldn't load verity table!"; 382 return false; 383 } 384 385 // Activates the device. 386 if (!fs_mgr_resume_verity_table(io, mount_point, fd)) { 387 return false; 388 } 389 390 // Marks the underlying block device as read-only. 391 fs_mgr_set_blk_ro(fstab_entry->blk_device); 392 393 // TODO(bowgotsai): support verified all partition at boot. 394 // Updates fstab_rec->blk_device to verity device name. 395 free(fstab_entry->blk_device); 396 fstab_entry->blk_device = strdup(verity_blk_name.c_str()); 397 398 // Makes sure we've set everything up properly. 399 if (fs_mgr_test_access(verity_blk_name.c_str()) < 0) { 400 return false; 401 } 402 403 return true; 404} 405 406static bool get_hashtree_descriptor(const std::string &partition_name, 407 const AvbSlotVerifyData &verify_data, 408 AvbHashtreeDescriptor *out_hashtree_desc, 409 std::string *out_salt, 410 std::string *out_digest) 411{ 412 bool found = false; 413 const uint8_t *desc_partition_name; 414 415 for (size_t i = 0; i < verify_data.num_vbmeta_images && !found; i++) { 416 // Get descriptors from vbmeta_images[i]. 417 size_t num_descriptors; 418 std::unique_ptr<const AvbDescriptor *[], decltype(&avb_free)> 419 descriptors( 420 avb_descriptor_get_all(verify_data.vbmeta_images[i].vbmeta_data, 421 verify_data.vbmeta_images[i].vbmeta_size, 422 &num_descriptors), 423 avb_free); 424 425 if (!descriptors || num_descriptors < 1) { 426 continue; 427 } 428 429 // Ensures that hashtree descriptor is either in /vbmeta or in 430 // the same partition for verity setup. 431 std::string vbmeta_partition_name( 432 verify_data.vbmeta_images[i].partition_name); 433 if (vbmeta_partition_name != "vbmeta" && 434 vbmeta_partition_name != partition_name) { 435 LWARNING << "Skip vbmeta image at " 436 << verify_data.vbmeta_images[i].partition_name 437 << " for partition: " << partition_name.c_str(); 438 continue; 439 } 440 441 for (size_t j = 0; j < num_descriptors && !found; j++) { 442 AvbDescriptor desc; 443 if (!avb_descriptor_validate_and_byteswap(descriptors[j], &desc)) { 444 LWARNING << "Descriptor[" << j << "] is invalid"; 445 continue; 446 } 447 if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) { 448 desc_partition_name = (const uint8_t *)descriptors[j] + 449 sizeof(AvbHashtreeDescriptor); 450 if (!avb_hashtree_descriptor_validate_and_byteswap( 451 (AvbHashtreeDescriptor *)descriptors[j], 452 out_hashtree_desc)) { 453 continue; 454 } 455 if (out_hashtree_desc->partition_name_len != 456 partition_name.length()) { 457 continue; 458 } 459 // Notes that desc_partition_name is not NUL-terminated. 460 std::string hashtree_partition_name( 461 (const char *)desc_partition_name, 462 out_hashtree_desc->partition_name_len); 463 if (hashtree_partition_name == partition_name) { 464 found = true; 465 } 466 } 467 } 468 } 469 470 if (!found) { 471 LERROR << "Partition descriptor not found: " << partition_name.c_str(); 472 return false; 473 } 474 475 const uint8_t *desc_salt = 476 desc_partition_name + out_hashtree_desc->partition_name_len; 477 *out_salt = bytes_to_hex(desc_salt, out_hashtree_desc->salt_len); 478 479 const uint8_t *desc_digest = desc_salt + out_hashtree_desc->salt_len; 480 *out_digest = bytes_to_hex(desc_digest, out_hashtree_desc->root_digest_len); 481 482 return true; 483} 484 485static bool init_is_avb_used() 486{ 487 // When AVB is used, boot loader should set androidboot.vbmeta.{hash_alg, 488 // size, digest} in kernel cmdline. They will then be imported by init 489 // process to system properties: ro.boot.vbmeta.{hash_alg, size, digest}. 490 // 491 // Checks hash_alg as an indicator for whether AVB is used. 492 // We don't have to parse and check all of them here. The check will 493 // be done in fs_mgr_load_vbmeta_images() and FS_MGR_SETUP_AVB_FAIL will 494 // be returned when there is an error. 495 496 std::string hash_alg = 497 android::base::GetProperty("ro.boot.vbmeta.hash_alg", ""); 498 499 if (hash_alg == "sha256" || hash_alg == "sha512") { 500 return true; 501 } 502 503 return false; 504} 505 506bool fs_mgr_is_avb_used() 507{ 508 static bool result = init_is_avb_used(); 509 return result; 510} 511 512int fs_mgr_load_vbmeta_images(struct fstab *fstab) 513{ 514 FS_MGR_CHECK(fstab != nullptr); 515 516 // Gets the expected hash value of vbmeta images from 517 // kernel cmdline. 518 if (!load_vbmeta_prop(&fs_mgr_vbmeta_prop)) { 519 return FS_MGR_SETUP_AVB_FAIL; 520 } 521 522 fs_mgr_avb_ops = fs_mgr_dummy_avb_ops_new(fstab); 523 if (fs_mgr_avb_ops == nullptr) { 524 LERROR << "Failed to allocate dummy avb_ops"; 525 return FS_MGR_SETUP_AVB_FAIL; 526 } 527 528 // Invokes avb_slot_verify() to load and verify all vbmeta images. 529 // Sets requested_partitions to nullptr as it's to copy the contents 530 // of HASH partitions into fs_mgr_avb_verify_data, which is not required as 531 // fs_mgr only deals with HASHTREE partitions. 532 const char *requested_partitions[] = {nullptr}; 533 const char *ab_suffix = 534 android::base::GetProperty("ro.boot.slot_suffix", "").c_str(); 535 AvbSlotVerifyResult verify_result = avb_slot_verify( 536 fs_mgr_avb_ops, requested_partitions, ab_suffix, 537 fs_mgr_vbmeta_prop.allow_verification_error, &fs_mgr_avb_verify_data); 538 539 // Only allow two verify results: 540 // - AVB_SLOT_VERIFY_RESULT_OK. 541 // - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state). 542 if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) { 543 if (!fs_mgr_vbmeta_prop.allow_verification_error) { 544 LERROR << "ERROR_VERIFICATION isn't allowed"; 545 goto fail; 546 } 547 } else if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) { 548 LERROR << "avb_slot_verify failed, result: " << verify_result; 549 goto fail; 550 } 551 552 // Verifies vbmeta images against the digest passed from bootloader. 553 if (!verify_vbmeta_images(*fs_mgr_avb_verify_data, fs_mgr_vbmeta_prop)) { 554 LERROR << "verify_vbmeta_images failed"; 555 goto fail; 556 } else { 557 // Checks whether FLAGS_HASHTREE_DISABLED is set. 558 AvbVBMetaImageHeader vbmeta_header; 559 avb_vbmeta_image_header_to_host_byte_order( 560 (AvbVBMetaImageHeader *)fs_mgr_avb_verify_data->vbmeta_images[0] 561 .vbmeta_data, 562 &vbmeta_header); 563 564 bool hashtree_disabled = ((AvbVBMetaImageFlags)vbmeta_header.flags & 565 AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED); 566 if (hashtree_disabled) { 567 return FS_MGR_SETUP_AVB_HASHTREE_DISABLED; 568 } 569 } 570 571 if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) { 572 return FS_MGR_SETUP_AVB_SUCCESS; 573 } 574 575fail: 576 fs_mgr_unload_vbmeta_images(); 577 return FS_MGR_SETUP_AVB_FAIL; 578} 579 580void fs_mgr_unload_vbmeta_images() 581{ 582 if (fs_mgr_avb_verify_data != nullptr) { 583 avb_slot_verify_data_free(fs_mgr_avb_verify_data); 584 } 585 586 if (fs_mgr_avb_ops != nullptr) { 587 fs_mgr_dummy_avb_ops_free(fs_mgr_avb_ops); 588 } 589} 590 591int fs_mgr_setup_avb(struct fstab_rec *fstab_entry) 592{ 593 if (!fstab_entry || !fs_mgr_avb_verify_data || 594 fs_mgr_avb_verify_data->num_vbmeta_images < 1) { 595 return FS_MGR_SETUP_AVB_FAIL; 596 } 597 598 std::string partition_name(basename(fstab_entry->mount_point)); 599 if (!avb_validate_utf8((const uint8_t *)partition_name.c_str(), 600 partition_name.length())) { 601 LERROR << "Partition name: " << partition_name.c_str() 602 << " is not valid UTF-8."; 603 return FS_MGR_SETUP_AVB_FAIL; 604 } 605 606 AvbHashtreeDescriptor hashtree_descriptor; 607 std::string salt; 608 std::string root_digest; 609 if (!get_hashtree_descriptor(partition_name, *fs_mgr_avb_verify_data, 610 &hashtree_descriptor, &salt, &root_digest)) { 611 return FS_MGR_SETUP_AVB_FAIL; 612 } 613 614 // Converts HASHTREE descriptor to verity_table_params. 615 if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, 616 root_digest)) { 617 return FS_MGR_SETUP_AVB_FAIL; 618 } 619 620 return FS_MGR_SETUP_AVB_SUCCESS; 621} 622