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 "fs_mgr_avb.h" 18 19 #include <fcntl.h> 20 #include <libgen.h> 21 #include <string.h> 22 #include <sys/ioctl.h> 23 #include <sys/types.h> 24 25 #include <sstream> 26 #include <string> 27 #include <vector> 28 29 #include <android-base/file.h> 30 #include <android-base/parseint.h> 31 #include <android-base/properties.h> 32 #include <android-base/stringprintf.h> 33 #include <android-base/strings.h> 34 #include <android-base/unique_fd.h> 35 #include <libavb/libavb.h> 36 37 #include "fs_mgr.h" 38 #include "fs_mgr_priv.h" 39 #include "fs_mgr_priv_avb_ops.h" 40 #include "fs_mgr_priv_dm_ioctl.h" 41 #include "fs_mgr_priv_sha.h" 42 43 static inline bool nibble_value(const char& c, uint8_t* value) { 44 FS_MGR_CHECK(value != nullptr); 45 46 switch (c) { 47 case '0' ... '9': 48 *value = c - '0'; 49 break; 50 case 'a' ... 'f': 51 *value = c - 'a' + 10; 52 break; 53 case 'A' ... 'F': 54 *value = c - 'A' + 10; 55 break; 56 default: 57 return false; 58 } 59 60 return true; 61 } 62 63 static bool hex_to_bytes(uint8_t* bytes, size_t bytes_len, const std::string& hex) { 64 FS_MGR_CHECK(bytes != nullptr); 65 66 if (hex.size() % 2 != 0) { 67 return false; 68 } 69 if (hex.size() / 2 > bytes_len) { 70 return false; 71 } 72 for (size_t i = 0, j = 0, n = hex.size(); i < n; i += 2, ++j) { 73 uint8_t high; 74 if (!nibble_value(hex[i], &high)) { 75 return false; 76 } 77 uint8_t low; 78 if (!nibble_value(hex[i + 1], &low)) { 79 return false; 80 } 81 bytes[j] = (high << 4) | low; 82 } 83 return true; 84 } 85 86 static std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) { 87 FS_MGR_CHECK(bytes != nullptr); 88 89 static const char* hex_digits = "0123456789abcdef"; 90 std::string hex; 91 92 for (size_t i = 0; i < bytes_len; i++) { 93 hex.push_back(hex_digits[(bytes[i] & 0xF0) >> 4]); 94 hex.push_back(hex_digits[bytes[i] & 0x0F]); 95 } 96 return hex; 97 } 98 99 template <typename Hasher> 100 static std::pair<size_t, bool> verify_vbmeta_digest(const AvbSlotVerifyData& verify_data, 101 const uint8_t* expected_digest) { 102 size_t total_size = 0; 103 Hasher hasher; 104 for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) { 105 hasher.update(verify_data.vbmeta_images[n].vbmeta_data, 106 verify_data.vbmeta_images[n].vbmeta_size); 107 total_size += verify_data.vbmeta_images[n].vbmeta_size; 108 } 109 110 bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0); 111 112 return std::make_pair(total_size, matched); 113 } 114 115 // Reads the following values from kernel cmdline and provides the 116 // VerifyVbmetaImages() to verify AvbSlotVerifyData. 117 // - androidboot.vbmeta.hash_alg 118 // - androidboot.vbmeta.size 119 // - androidboot.vbmeta.digest 120 class FsManagerAvbVerifier { 121 public: 122 // The factory method to return a unique_ptr<FsManagerAvbVerifier> 123 static std::unique_ptr<FsManagerAvbVerifier> Create(); 124 bool VerifyVbmetaImages(const AvbSlotVerifyData& verify_data); 125 126 protected: 127 FsManagerAvbVerifier() = default; 128 129 private: 130 enum HashAlgorithm { 131 kInvalid = 0, 132 kSHA256 = 1, 133 kSHA512 = 2, 134 }; 135 136 HashAlgorithm hash_alg_; 137 uint8_t digest_[SHA512_DIGEST_LENGTH]; 138 size_t vbmeta_size_; 139 }; 140 141 std::unique_ptr<FsManagerAvbVerifier> FsManagerAvbVerifier::Create() { 142 std::string cmdline; 143 if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) { 144 PERROR << "Failed to read /proc/cmdline"; 145 return nullptr; 146 } 147 148 std::unique_ptr<FsManagerAvbVerifier> avb_verifier(new FsManagerAvbVerifier()); 149 if (!avb_verifier) { 150 LERROR << "Failed to create unique_ptr<FsManagerAvbVerifier>"; 151 return nullptr; 152 } 153 154 std::string digest; 155 std::string hash_alg; 156 for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { 157 std::vector<std::string> pieces = android::base::Split(entry, "="); 158 const std::string& key = pieces[0]; 159 const std::string& value = pieces[1]; 160 161 if (key == "androidboot.vbmeta.hash_alg") { 162 hash_alg = value; 163 } else if (key == "androidboot.vbmeta.size") { 164 if (!android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) { 165 return nullptr; 166 } 167 } else if (key == "androidboot.vbmeta.digest") { 168 digest = value; 169 } 170 } 171 172 // Reads hash algorithm. 173 size_t expected_digest_size = 0; 174 if (hash_alg == "sha256") { 175 expected_digest_size = SHA256_DIGEST_LENGTH * 2; 176 avb_verifier->hash_alg_ = kSHA256; 177 } else if (hash_alg == "sha512") { 178 expected_digest_size = SHA512_DIGEST_LENGTH * 2; 179 avb_verifier->hash_alg_ = kSHA512; 180 } else { 181 LERROR << "Unknown hash algorithm: " << hash_alg.c_str(); 182 return nullptr; 183 } 184 185 // Reads digest. 186 if (digest.size() != expected_digest_size) { 187 LERROR << "Unexpected digest size: " << digest.size() 188 << " (expected: " << expected_digest_size << ")"; 189 return nullptr; 190 } 191 192 if (!hex_to_bytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) { 193 LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str(); 194 return nullptr; 195 } 196 197 return avb_verifier; 198 } 199 200 bool FsManagerAvbVerifier::VerifyVbmetaImages(const AvbSlotVerifyData& verify_data) { 201 if (verify_data.num_vbmeta_images == 0) { 202 LERROR << "No vbmeta images"; 203 return false; 204 } 205 206 size_t total_size = 0; 207 bool digest_matched = false; 208 209 if (hash_alg_ == kSHA256) { 210 std::tie(total_size, digest_matched) = 211 verify_vbmeta_digest<SHA256Hasher>(verify_data, digest_); 212 } else if (hash_alg_ == kSHA512) { 213 std::tie(total_size, digest_matched) = 214 verify_vbmeta_digest<SHA512Hasher>(verify_data, digest_); 215 } 216 217 if (total_size != vbmeta_size_) { 218 LERROR << "total vbmeta size mismatch: " << total_size << " (expected: " << vbmeta_size_ 219 << ")"; 220 return false; 221 } 222 223 if (!digest_matched) { 224 LERROR << "vbmeta digest mismatch"; 225 return false; 226 } 227 228 return true; 229 } 230 231 // Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel. 232 // See the following link for more details: 233 // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity 234 static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc, 235 const std::string& salt, const std::string& root_digest, 236 const std::string& blk_device) { 237 // Loads androidboot.veritymode from kernel cmdline. 238 std::string verity_mode; 239 if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) { 240 verity_mode = "enforcing"; // Defaults to enforcing when it's absent. 241 } 242 243 // Converts veritymode to the format used in kernel. 244 std::string dm_verity_mode; 245 if (verity_mode == "enforcing") { 246 dm_verity_mode = "restart_on_corruption"; 247 } else if (verity_mode == "logging") { 248 dm_verity_mode = "ignore_corruption"; 249 } else if (verity_mode != "eio") { // Default dm_verity_mode is eio. 250 LERROR << "Unknown androidboot.veritymode: " << verity_mode; 251 return ""; 252 } 253 254 // dm-verity construction parameters: 255 // <version> <dev> <hash_dev> 256 // <data_block_size> <hash_block_size> 257 // <num_data_blocks> <hash_start_block> 258 // <algorithm> <digest> <salt> 259 // [<#opt_params> <opt_params>] 260 std::ostringstream verity_table; 261 verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " " 262 << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " " 263 << hashtree_desc.image_size / hashtree_desc.data_block_size << " " 264 << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " " 265 << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt; 266 267 // Continued from the above optional parameters: 268 // [<#opt_params> <opt_params>] 269 int optional_argc = 0; 270 std::ostringstream optional_args; 271 272 // dm-verity optional parameters for FEC (forward error correction): 273 // use_fec_from_device <fec_dev> 274 // fec_roots <num> 275 // fec_blocks <num> 276 // fec_start <offset> 277 if (hashtree_desc.fec_size > 0) { 278 // Note that fec_blocks is the size that FEC covers, *NOT* the 279 // size of the FEC data. Since we use FEC for everything up until 280 // the FEC data, it's the same as the offset (fec_start). 281 optional_argc += 8; 282 // clang-format off 283 optional_args << "use_fec_from_device " << blk_device 284 << " fec_roots " << hashtree_desc.fec_num_roots 285 << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size 286 << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size 287 << " "; 288 // clang-format on 289 } 290 291 if (!dm_verity_mode.empty()) { 292 optional_argc += 1; 293 optional_args << dm_verity_mode << " "; 294 } 295 296 // Always use ignore_zero_blocks. 297 optional_argc += 1; 298 optional_args << "ignore_zero_blocks"; 299 300 verity_table << " " << optional_argc << " " << optional_args.str(); 301 return verity_table.str(); 302 } 303 304 static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd, 305 uint64_t image_size, const std::string& verity_table) { 306 fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG); 307 308 // The buffer consists of [dm_ioctl][dm_target_spec][verity_params]. 309 char* buffer = (char*)io; 310 311 // Builds the dm_target_spec arguments. 312 struct dm_target_spec* dm_target = (struct dm_target_spec*)&buffer[sizeof(struct dm_ioctl)]; 313 io->target_count = 1; 314 dm_target->status = 0; 315 dm_target->sector_start = 0; 316 dm_target->length = image_size / 512; 317 strcpy(dm_target->target_type, "verity"); 318 319 // Builds the verity params. 320 char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 321 size_t bufsize = DM_BUF_SIZE - (verity_params - buffer); 322 323 LINFO << "Loading verity table: '" << verity_table << "'"; 324 325 // Copies verity_table to verity_params (including the terminating null byte). 326 if (verity_table.size() > bufsize - 1) { 327 LERROR << "Verity table size too large: " << verity_table.size() 328 << " (max allowable size: " << bufsize - 1 << ")"; 329 return false; 330 } 331 memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1); 332 333 // Sets ext target boundary. 334 verity_params += verity_table.size() + 1; 335 verity_params = (char*)(((unsigned long)verity_params + 7) & ~7); 336 dm_target->next = verity_params - buffer; 337 338 // Sends the ioctl to load the verity table. 339 if (ioctl(fd, DM_TABLE_LOAD, io)) { 340 PERROR << "Error loading verity table"; 341 return false; 342 } 343 344 return true; 345 } 346 347 static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, 348 const AvbHashtreeDescriptor& hashtree_desc, 349 const std::string& salt, const std::string& root_digest, 350 bool wait_for_verity_dev) { 351 // Gets the device mapper fd. 352 android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR)); 353 if (fd < 0) { 354 PERROR << "Error opening device mapper"; 355 return false; 356 } 357 358 // Creates the device. 359 alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; 360 struct dm_ioctl* io = (struct dm_ioctl*)buffer; 361 const std::string mount_point(basename(fstab_entry->mount_point)); 362 if (!fs_mgr_create_verity_device(io, mount_point, fd)) { 363 LERROR << "Couldn't create verity device!"; 364 return false; 365 } 366 367 // Gets the name of the device file. 368 std::string verity_blk_name; 369 if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) { 370 LERROR << "Couldn't get verity device number!"; 371 return false; 372 } 373 374 std::string verity_table = 375 construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device); 376 if (verity_table.empty()) { 377 LERROR << "Failed to construct verity table."; 378 return false; 379 } 380 381 // Loads the verity mapping table. 382 if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) { 383 LERROR << "Couldn't load verity table!"; 384 return false; 385 } 386 387 // Activates the device. 388 if (!fs_mgr_resume_verity_table(io, mount_point, fd)) { 389 return false; 390 } 391 392 // Marks the underlying block device as read-only. 393 fs_mgr_set_blk_ro(fstab_entry->blk_device); 394 395 // Updates fstab_rec->blk_device to verity device name. 396 free(fstab_entry->blk_device); 397 fstab_entry->blk_device = strdup(verity_blk_name.c_str()); 398 399 // Makes sure we've set everything up properly. 400 if (wait_for_verity_dev && !fs_mgr_wait_for_file(verity_blk_name, 1s)) { 401 return false; 402 } 403 404 return true; 405 } 406 407 static bool get_hashtree_descriptor(const std::string& partition_name, 408 const AvbSlotVerifyData& verify_data, 409 AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt, 410 std::string* out_digest) { 411 bool found = false; 412 const uint8_t* desc_partition_name; 413 414 for (size_t i = 0; i < verify_data.num_vbmeta_images && !found; i++) { 415 // Get descriptors from vbmeta_images[i]. 416 size_t num_descriptors; 417 std::unique_ptr<const AvbDescriptor* [], decltype(&avb_free)> descriptors( 418 avb_descriptor_get_all(verify_data.vbmeta_images[i].vbmeta_data, 419 verify_data.vbmeta_images[i].vbmeta_size, &num_descriptors), 420 avb_free); 421 422 if (!descriptors || num_descriptors < 1) { 423 continue; 424 } 425 426 // Ensures that hashtree descriptor is in /vbmeta or /boot or in 427 // the same partition for verity setup. 428 std::string vbmeta_partition_name(verify_data.vbmeta_images[i].partition_name); 429 if (vbmeta_partition_name != "vbmeta" && 430 vbmeta_partition_name != "boot" && // for legacy device to append top-level vbmeta 431 vbmeta_partition_name != partition_name) { 432 LWARNING << "Skip vbmeta image at " << verify_data.vbmeta_images[i].partition_name 433 << " for partition: " << partition_name.c_str(); 434 continue; 435 } 436 437 for (size_t j = 0; j < num_descriptors && !found; j++) { 438 AvbDescriptor desc; 439 if (!avb_descriptor_validate_and_byteswap(descriptors[j], &desc)) { 440 LWARNING << "Descriptor[" << j << "] is invalid"; 441 continue; 442 } 443 if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) { 444 desc_partition_name = (const uint8_t*)descriptors[j] + sizeof(AvbHashtreeDescriptor); 445 if (!avb_hashtree_descriptor_validate_and_byteswap( 446 (AvbHashtreeDescriptor*)descriptors[j], out_hashtree_desc)) { 447 continue; 448 } 449 if (out_hashtree_desc->partition_name_len != partition_name.length()) { 450 continue; 451 } 452 // Notes that desc_partition_name is not NUL-terminated. 453 std::string hashtree_partition_name((const char*)desc_partition_name, 454 out_hashtree_desc->partition_name_len); 455 if (hashtree_partition_name == partition_name) { 456 found = true; 457 } 458 } 459 } 460 } 461 462 if (!found) { 463 LERROR << "Partition descriptor not found: " << partition_name.c_str(); 464 return false; 465 } 466 467 const uint8_t* desc_salt = desc_partition_name + out_hashtree_desc->partition_name_len; 468 *out_salt = bytes_to_hex(desc_salt, out_hashtree_desc->salt_len); 469 470 const uint8_t* desc_digest = desc_salt + out_hashtree_desc->salt_len; 471 *out_digest = bytes_to_hex(desc_digest, out_hashtree_desc->root_digest_len); 472 473 return true; 474 } 475 476 FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) { 477 FsManagerAvbOps avb_ops(fstab); 478 return DoOpen(&avb_ops); 479 } 480 481 FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlink_map) { 482 if (by_name_symlink_map.empty()) { 483 LERROR << "Empty by_name_symlink_map when opening FsManagerAvbHandle"; 484 return nullptr; 485 } 486 FsManagerAvbOps avb_ops(std::move(by_name_symlink_map)); 487 return DoOpen(&avb_ops); 488 } 489 490 FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) { 491 bool is_device_unlocked = fs_mgr_is_device_unlocked(); 492 493 FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle()); 494 if (!avb_handle) { 495 LERROR << "Failed to allocate FsManagerAvbHandle"; 496 return nullptr; 497 } 498 499 AvbSlotVerifyFlags flags = is_device_unlocked ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR 500 : AVB_SLOT_VERIFY_FLAGS_NONE; 501 AvbSlotVerifyResult verify_result = 502 avb_ops->AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->avb_slot_data_); 503 504 // Only allow two verify results: 505 // - AVB_SLOT_VERIFY_RESULT_OK. 506 // - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state). 507 // If the device is UNLOCKED, i.e., |allow_verification_error| is true for 508 // AvbSlotVerify(), then the following return values are all non-fatal: 509 // * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION 510 // * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED 511 // * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX 512 // The latter two results were checked by bootloader prior to start fs_mgr so 513 // we just need to handle the first result here. See *dummy* operations in 514 // FsManagerAvbOps and the comments in external/avb/libavb/avb_slot_verify.h 515 // for more details. 516 switch (verify_result) { 517 case AVB_SLOT_VERIFY_RESULT_OK: 518 avb_handle->status_ = kAvbHandleSuccess; 519 break; 520 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: 521 if (!is_device_unlocked) { 522 LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED"; 523 return nullptr; 524 } 525 avb_handle->status_ = kAvbHandleVerificationError; 526 break; 527 default: 528 LERROR << "avb_slot_verify failed, result: " << verify_result; 529 return nullptr; 530 } 531 532 // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version". 533 avb_handle->avb_version_ = 534 android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR); 535 536 // Checks whether FLAGS_VERIFICATION_DISABLED is set: 537 // - Only the top-level vbmeta struct is read. 538 // - vbmeta struct in other partitions are NOT processed, including AVB HASH descriptor(s) 539 // and AVB HASHTREE descriptor(s). 540 AvbVBMetaImageHeader vbmeta_header; 541 avb_vbmeta_image_header_to_host_byte_order( 542 (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data, 543 &vbmeta_header); 544 bool verification_disabled = 545 ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED); 546 547 if (verification_disabled) { 548 avb_handle->status_ = kAvbHandleVerificationDisabled; 549 } else { 550 // Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline. 551 std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create(); 552 if (!avb_verifier) { 553 LERROR << "Failed to create FsManagerAvbVerifier"; 554 return nullptr; 555 } 556 if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) { 557 LERROR << "VerifyVbmetaImages failed"; 558 return nullptr; 559 } 560 561 // Checks whether FLAGS_HASHTREE_DISABLED is set. 562 bool hashtree_disabled = 563 ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED); 564 if (hashtree_disabled) { 565 avb_handle->status_ = kAvbHandleHashtreeDisabled; 566 } 567 } 568 569 LINFO << "Returning avb_handle with status: " << avb_handle->status_; 570 return avb_handle; 571 } 572 573 SetUpAvbHashtreeResult FsManagerAvbHandle::SetUpAvbHashtree(struct fstab_rec* fstab_entry, 574 bool wait_for_verity_dev) { 575 if (!fstab_entry || status_ == kAvbHandleUninitialized || !avb_slot_data_ || 576 avb_slot_data_->num_vbmeta_images < 1) { 577 return SetUpAvbHashtreeResult::kFail; 578 } 579 580 if (status_ == kAvbHandleHashtreeDisabled || status_ == kAvbHandleVerificationDisabled) { 581 LINFO << "AVB HASHTREE disabled on: " << fstab_entry->mount_point; 582 return SetUpAvbHashtreeResult::kDisabled; 583 } 584 585 // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor 586 // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix. 587 std::string partition_name(basename(fstab_entry->blk_device)); 588 if (fstab_entry->fs_mgr_flags & MF_SLOTSELECT) { 589 auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix()); 590 if (ab_suffix != std::string::npos) { 591 partition_name.erase(ab_suffix); 592 } 593 } 594 595 AvbHashtreeDescriptor hashtree_descriptor; 596 std::string salt; 597 std::string root_digest; 598 if (!get_hashtree_descriptor(partition_name, *avb_slot_data_, &hashtree_descriptor, &salt, 599 &root_digest)) { 600 return SetUpAvbHashtreeResult::kFail; 601 } 602 603 // Converts HASHTREE descriptor to verity_table_params. 604 if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest, 605 wait_for_verity_dev)) { 606 return SetUpAvbHashtreeResult::kFail; 607 } 608 609 return SetUpAvbHashtreeResult::kSuccess; 610 } 611