uboot/lib/libavb/avb_slot_verify.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright (C) 2016 The Android Open Source Project
   4 */
   5
   6#include "avb_slot_verify.h"
   7#include "avb_chain_partition_descriptor.h"
   8#include "avb_cmdline.h"
   9#include "avb_footer.h"
  10#include "avb_hash_descriptor.h"
  11#include "avb_hashtree_descriptor.h"
  12#include "avb_kernel_cmdline_descriptor.h"
  13#include "avb_sha.h"
  14#include "avb_util.h"
  15#include "avb_vbmeta_image.h"
  16#include "avb_version.h"
  17#include <log.h>
  18#include <malloc.h>
  19
  20/* Maximum number of partitions that can be loaded with avb_slot_verify(). */
  21#define MAX_NUMBER_OF_LOADED_PARTITIONS 32
  22
  23/* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
  24#define MAX_NUMBER_OF_VBMETA_IMAGES 32
  25
  26/* Maximum size of a vbmeta image - 64 KiB. */
  27#define VBMETA_MAX_SIZE (64 * 1024)
  28
  29static AvbSlotVerifyResult initialize_persistent_digest(
  30    AvbOps* ops,
  31    const char* part_name,
  32    const char* persistent_value_name,
  33    size_t digest_size,
  34    const uint8_t* initial_digest,
  35    uint8_t* out_digest);
  36
  37/* Helper function to see if we should continue with verification in
  38 * allow_verification_error=true mode if something goes wrong. See the
  39 * comments for the avb_slot_verify() function for more information.
  40 */
  41static inline bool result_should_continue(AvbSlotVerifyResult result) {
  42  switch (result) {
  43    case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
  44    case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
  45    case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
  46    case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
  47    case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
  48      return false;
  49
  50    case AVB_SLOT_VERIFY_RESULT_OK:
  51    case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
  52    case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
  53    case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
  54      return true;
  55  }
  56
  57  return false;
  58}
  59
  60static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
  61                                               const char* part_name,
  62                                               uint64_t image_size,
  63                                               uint8_t** out_image_buf,
  64                                               bool* out_image_preloaded) {
  65  size_t part_num_read;
  66  AvbIOResult io_ret;
  67
  68  /* Make sure that we do not overwrite existing data. */
  69  avb_assert(*out_image_buf == NULL);
  70  avb_assert(!*out_image_preloaded);
  71
  72  /* We are going to implicitly cast image_size from uint64_t to size_t in the
  73   * following code, so we need to make sure that the cast is safe. */
  74  if (image_size != (size_t)(image_size)) {
  75    avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
  76    return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
  77  }
  78
  79  /* Try use a preloaded one. */
  80  if (ops->get_preloaded_partition != NULL) {
  81    io_ret = ops->get_preloaded_partition(
  82        ops, part_name, image_size, out_image_buf, &part_num_read);
  83    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
  84      return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
  85    } else if (io_ret != AVB_IO_RESULT_OK) {
  86      avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
  87      return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  88    }
  89
  90    if (*out_image_buf != NULL) {
  91      if (part_num_read != image_size) {
  92        avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
  93        return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
  94      }
  95      *out_image_preloaded = true;
  96    }
  97  }
  98
  99  /* Allocate and copy the partition. */
 100  if (!*out_image_preloaded) {
 101    *out_image_buf = avb_malloc(image_size);
 102    if (*out_image_buf == NULL) {
 103      return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 104    }
 105
 106    io_ret = ops->read_from_partition(ops,
 107                                      part_name,
 108                                      0 /* offset */,
 109                                      image_size,
 110                                      *out_image_buf,
 111                                      &part_num_read);
 112    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 113      return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 114    } else if (io_ret != AVB_IO_RESULT_OK) {
 115      avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
 116      return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 117    }
 118    if (part_num_read != image_size) {
 119      avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
 120      return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 121    }
 122  }
 123
 124  return AVB_SLOT_VERIFY_RESULT_OK;
 125}
 126
 127/* Reads a persistent digest stored as a named persistent value corresponding to
 128 * the given |part_name|. The value is returned in |out_digest| which must point
 129 * to |expected_digest_size| bytes. If there is no digest stored for |part_name|
 130 * it can be initialized by providing a non-NULL |initial_digest| of length
 131 * |expected_digest_size|. This automatic initialization will only occur if the
 132 * device is currently locked. The |initial_digest| may be NULL.
 133 *
 134 * Returns AVB_SLOT_VERIFY_RESULT_OK on success, otherwise returns an
 135 * AVB_SLOT_VERIFY_RESULT_ERROR_* error code.
 136 *
 137 * If the value does not exist, is not supported, or is not populated, and
 138 * |initial_digest| is NULL, returns
 139 * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA. If |expected_digest_size| does
 140 * not match the stored digest size, also returns
 141 * AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA.
 142 */
 143static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops,
 144                                                  const char* part_name,
 145                                                  size_t expected_digest_size,
 146                                                  const uint8_t* initial_digest,
 147                                                  uint8_t* out_digest) {
 148  char* persistent_value_name = NULL;
 149  AvbIOResult io_ret = AVB_IO_RESULT_OK;
 150  size_t stored_digest_size = 0;
 151
 152  if (ops->read_persistent_value == NULL) {
 153    avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
 154    return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 155  }
 156  persistent_value_name =
 157      avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX, part_name, NULL);
 158  if (persistent_value_name == NULL) {
 159    return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 160  }
 161
 162  io_ret = ops->read_persistent_value(ops,
 163                                      persistent_value_name,
 164                                      expected_digest_size,
 165                                      out_digest,
 166                                      &stored_digest_size);
 167
 168  // If no such named persistent value exists and an initial digest value was
 169  // given, initialize the named persistent value with the given digest. If
 170  // initialized successfully, this will recurse into this function but with a
 171  // NULL initial_digest.
 172  if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE && initial_digest) {
 173    AvbSlotVerifyResult ret =
 174        initialize_persistent_digest(ops,
 175                                     part_name,
 176                                     persistent_value_name,
 177                                     expected_digest_size,
 178                                     initial_digest,
 179                                     out_digest);
 180    avb_free(persistent_value_name);
 181    return ret;
 182  }
 183  avb_free(persistent_value_name);
 184
 185  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 186    return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 187  } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
 188    // Treat a missing persistent value as a verification error, which is
 189    // ignoreable, rather than a metadata error which is not.
 190    avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
 191    return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
 192  } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
 193             io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE) {
 194    avb_errorv(
 195        part_name, ": Persistent digest is not of expected size.\n", NULL);
 196    return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 197  } else if (io_ret != AVB_IO_RESULT_OK) {
 198    avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
 199    return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 200  } else if (expected_digest_size != stored_digest_size) {
 201    avb_errorv(
 202        part_name, ": Persistent digest is not of expected size.\n", NULL);
 203    return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 204  }
 205  return AVB_SLOT_VERIFY_RESULT_OK;
 206}
 207
 208static AvbSlotVerifyResult initialize_persistent_digest(
 209    AvbOps* ops,
 210    const char* part_name,
 211    const char* persistent_value_name,
 212    size_t digest_size,
 213    const uint8_t* initial_digest,
 214    uint8_t* out_digest) {
 215  AvbSlotVerifyResult ret;
 216  AvbIOResult io_ret = AVB_IO_RESULT_OK;
 217  bool is_device_unlocked = true;
 218
 219  io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
 220  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 221    return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 222  } else if (io_ret != AVB_IO_RESULT_OK) {
 223    avb_error("Error getting device lock state.\n");
 224    return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 225  }
 226
 227  if (is_device_unlocked) {
 228    avb_debugv(part_name,
 229               ": Digest does not exist, device unlocked so not initializing "
 230               "digest.\n",
 231               NULL);
 232    return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
 233  }
 234
 235  // Device locked; initialize digest with given initial value.
 236  avb_debugv(part_name,
 237             ": Digest does not exist, initializing persistent digest.\n",
 238             NULL);
 239  io_ret = ops->write_persistent_value(
 240      ops, persistent_value_name, digest_size, initial_digest);
 241  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 242    return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 243  } else if (io_ret != AVB_IO_RESULT_OK) {
 244    avb_errorv(part_name, ": Error initializing persistent digest.\n", NULL);
 245    return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 246  }
 247
 248  // To ensure that the digest value was written successfully - and avoid a
 249  // scenario where the digest is simply 'initialized' on every verify - recurse
 250  // into read_persistent_digest to read back the written value. The NULL
 251  // initial_digest ensures that this will not recurse again.
 252  ret = read_persistent_digest(ops, part_name, digest_size, NULL, out_digest);
 253  if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
 254    avb_errorv(part_name,
 255               ": Reading back initialized persistent digest failed!\n",
 256               NULL);
 257  }
 258  return ret;
 259}
 260
 261static AvbSlotVerifyResult load_and_verify_hash_partition(
 262    AvbOps* ops,
 263    const char* const* requested_partitions,
 264    const char* ab_suffix,
 265    bool allow_verification_error,
 266    const AvbDescriptor* descriptor,
 267    AvbSlotVerifyData* slot_data) {
 268  AvbHashDescriptor hash_desc;
 269  const uint8_t* desc_partition_name = NULL;
 270  const uint8_t* desc_salt;
 271  const uint8_t* desc_digest;
 272  char part_name[AVB_PART_NAME_MAX_SIZE];
 273  AvbSlotVerifyResult ret;
 274  AvbIOResult io_ret;
 275  uint8_t* image_buf = NULL;
 276  bool image_preloaded = false;
 277  uint8_t* digest;
 278  size_t digest_len;
 279  const char* found;
 280  uint64_t image_size;
 281  size_t expected_digest_len = 0;
 282  uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
 283  const uint8_t* expected_digest = NULL;
 284
 285  if (!avb_hash_descriptor_validate_and_byteswap(
 286          (const AvbHashDescriptor*)descriptor, &hash_desc)) {
 287    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 288    goto out;
 289  }
 290
 291  desc_partition_name =
 292      ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
 293  desc_salt = desc_partition_name + hash_desc.partition_name_len;
 294  desc_digest = desc_salt + hash_desc.salt_len;
 295
 296  if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
 297    avb_error("Partition name is not valid UTF-8.\n");
 298    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 299    goto out;
 300  }
 301
 302  /* Don't bother loading or validating unless the partition was
 303   * requested in the first place.
 304   */
 305  found = avb_strv_find_str(requested_partitions,
 306                            (const char*)desc_partition_name,
 307                            hash_desc.partition_name_len);
 308  if (found == NULL) {
 309    ret = AVB_SLOT_VERIFY_RESULT_OK;
 310    goto out;
 311  }
 312
 313  if ((hash_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0) {
 314    /* No ab_suffix, just copy the partition name as is. */
 315    if (hash_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
 316      avb_error("Partition name does not fit.\n");
 317      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 318      goto out;
 319    }
 320    avb_memcpy(part_name, desc_partition_name, hash_desc.partition_name_len);
 321    part_name[hash_desc.partition_name_len] = '\0';
 322  } else if (hash_desc.digest_len == 0 && avb_strlen(ab_suffix) != 0) {
 323    /* No ab_suffix allowed for partitions without a digest in the descriptor
 324     * because these partitions hold data unique to this device and are not
 325     * updated using an A/B scheme.
 326     */
 327    avb_error("Cannot use A/B with a persistent digest.\n");
 328    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 329    goto out;
 330  } else {
 331    /* Add ab_suffix to the partition name. */
 332    if (!avb_str_concat(part_name,
 333                        sizeof part_name,
 334                        (const char*)desc_partition_name,
 335                        hash_desc.partition_name_len,
 336                        ab_suffix,
 337                        avb_strlen(ab_suffix))) {
 338      avb_error("Partition name and suffix does not fit.\n");
 339      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 340      goto out;
 341    }
 342  }
 343
 344  /* If we're allowing verification errors then hash_desc.image_size
 345   * may no longer match what's in the partition... so in this case
 346   * just load the entire partition.
 347   *
 348   * For example, this can happen if a developer does 'fastboot flash
 349   * boot /path/to/new/and/bigger/boot.img'. We want this to work
 350   * since it's such a common workflow.
 351   */
 352  image_size = hash_desc.image_size;
 353  if (allow_verification_error) {
 354    io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
 355    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 356      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 357      goto out;
 358    } else if (io_ret != AVB_IO_RESULT_OK) {
 359      avb_errorv(part_name, ": Error determining partition size.\n", NULL);
 360      ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 361      goto out;
 362    }
 363    avb_debugv(part_name, ": Loading entire partition.\n", NULL);
 364  }
 365
 366  ret = load_full_partition(
 367      ops, part_name, image_size, &image_buf, &image_preloaded);
 368  if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
 369    goto out;
 370  }
 371  // Although only one of the type might be used, we have to defined the
 372  // structure here so that they would live outside the 'if/else' scope to be
 373  // used later.
 374  AvbSHA256Ctx sha256_ctx;
 375  AvbSHA512Ctx sha512_ctx;
 376  size_t image_size_to_hash = hash_desc.image_size;
 377  // If we allow verification error and the whole partition is smaller than
 378  // image size in hash descriptor, we just hash the whole partition.
 379  if (image_size_to_hash > image_size) {
 380    image_size_to_hash = image_size;
 381  }
 382  if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
 383    avb_sha256_init(&sha256_ctx);
 384    avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
 385    avb_sha256_update(&sha256_ctx, image_buf, image_size_to_hash);
 386    digest = avb_sha256_final(&sha256_ctx);
 387    digest_len = AVB_SHA256_DIGEST_SIZE;
 388  } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
 389    avb_sha512_init(&sha512_ctx);
 390    avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
 391    avb_sha512_update(&sha512_ctx, image_buf, image_size_to_hash);
 392    digest = avb_sha512_final(&sha512_ctx);
 393    digest_len = AVB_SHA512_DIGEST_SIZE;
 394  } else {
 395    avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
 396    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 397    goto out;
 398  }
 399
 400  if (hash_desc.digest_len == 0) {
 401    /* Expect a match to a persistent digest. */
 402    avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
 403    expected_digest_len = digest_len;
 404    expected_digest = expected_digest_buf;
 405    avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
 406    /* Pass |digest| as the |initial_digest| so devices not yet initialized get
 407     * initialized to the current partition digest.
 408     */
 409    ret = read_persistent_digest(
 410        ops, part_name, digest_len, digest, expected_digest_buf);
 411    if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
 412      goto out;
 413    }
 414  } else {
 415    /* Expect a match to the digest in the descriptor. */
 416    expected_digest_len = hash_desc.digest_len;
 417    expected_digest = desc_digest;
 418  }
 419
 420  if (digest_len != expected_digest_len) {
 421    avb_errorv(
 422        part_name, ": Digest in descriptor not of expected size.\n", NULL);
 423    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 424    goto out;
 425  }
 426
 427  if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
 428    avb_errorv(part_name,
 429               ": Hash of data does not match digest in descriptor.\n",
 430               NULL);
 431    ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
 432    goto out;
 433  }
 434
 435  ret = AVB_SLOT_VERIFY_RESULT_OK;
 436
 437out:
 438
 439  /* If it worked and something was loaded, copy to slot_data. */
 440  if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
 441      image_buf != NULL) {
 442    AvbPartitionData* loaded_partition;
 443    if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
 444      avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
 445      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 446      goto fail;
 447    }
 448    loaded_partition =
 449        &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
 450    loaded_partition->partition_name = avb_strdup(found);
 451    loaded_partition->data_size = image_size;
 452    loaded_partition->data = image_buf;
 453    loaded_partition->preloaded = image_preloaded;
 454    image_buf = NULL;
 455  }
 456
 457fail:
 458  if (image_buf != NULL && !image_preloaded) {
 459    avb_free(image_buf);
 460  }
 461  return ret;
 462}
 463
 464static AvbSlotVerifyResult load_requested_partitions(
 465    AvbOps* ops,
 466    const char* const* requested_partitions,
 467    const char* ab_suffix,
 468    AvbSlotVerifyData* slot_data) {
 469  AvbSlotVerifyResult ret;
 470  uint8_t* image_buf = NULL;
 471  bool image_preloaded = false;
 472  size_t n;
 473
 474  for (n = 0; requested_partitions[n] != NULL; n++) {
 475    char part_name[AVB_PART_NAME_MAX_SIZE];
 476    AvbIOResult io_ret;
 477    uint64_t image_size;
 478    AvbPartitionData* loaded_partition;
 479
 480    if (!avb_str_concat(part_name,
 481                        sizeof part_name,
 482                        requested_partitions[n],
 483                        avb_strlen(requested_partitions[n]),
 484                        ab_suffix,
 485                        avb_strlen(ab_suffix))) {
 486      avb_error("Partition name and suffix does not fit.\n");
 487      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 488      goto out;
 489    }
 490
 491    io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
 492    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 493      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 494      goto out;
 495    } else if (io_ret != AVB_IO_RESULT_OK) {
 496      avb_errorv(part_name, ": Error determining partition size.\n", NULL);
 497      ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 498      goto out;
 499    }
 500    avb_debugv(part_name, ": Loading entire partition.\n", NULL);
 501
 502    ret = load_full_partition(
 503        ops, part_name, image_size, &image_buf, &image_preloaded);
 504    if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
 505      goto out;
 506    }
 507
 508    /* Move to slot_data. */
 509    if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
 510      avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
 511      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 512      goto out;
 513    }
 514    loaded_partition =
 515        &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
 516    loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
 517    if (loaded_partition->partition_name == NULL) {
 518      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 519      goto out;
 520    }
 521    loaded_partition->data_size = image_size;
 522    loaded_partition->data = image_buf; /* Transferring the owner. */
 523    loaded_partition->preloaded = image_preloaded;
 524    image_buf = NULL;
 525    image_preloaded = false;
 526  }
 527
 528  ret = AVB_SLOT_VERIFY_RESULT_OK;
 529
 530out:
 531  /* Free the current buffer if any. */
 532  if (image_buf != NULL && !image_preloaded) {
 533    avb_free(image_buf);
 534  }
 535  /* Buffers that are already saved in slot_data will be handled by the caller
 536   * even on failure. */
 537  return ret;
 538}
 539
 540static AvbSlotVerifyResult load_and_verify_vbmeta(
 541    AvbOps* ops,
 542    const char* const* requested_partitions,
 543    const char* ab_suffix,
 544    AvbSlotVerifyFlags flags,
 545    bool allow_verification_error,
 546    AvbVBMetaImageFlags toplevel_vbmeta_flags,
 547    int rollback_index_location,
 548    const char* partition_name,
 549    size_t partition_name_len,
 550    const uint8_t* expected_public_key,
 551    size_t expected_public_key_length,
 552    AvbSlotVerifyData* slot_data,
 553    AvbAlgorithmType* out_algorithm_type,
 554    AvbCmdlineSubstList* out_additional_cmdline_subst) {
 555  char full_partition_name[AVB_PART_NAME_MAX_SIZE];
 556  AvbSlotVerifyResult ret;
 557  AvbIOResult io_ret;
 558  size_t vbmeta_offset;
 559  size_t vbmeta_size;
 560  uint8_t* vbmeta_buf = NULL;
 561  size_t vbmeta_num_read;
 562  AvbVBMetaVerifyResult vbmeta_ret;
 563  const uint8_t* pk_data;
 564  size_t pk_len;
 565  AvbVBMetaImageHeader vbmeta_header;
 566  uint64_t stored_rollback_index;
 567  const AvbDescriptor** descriptors = NULL;
 568  size_t num_descriptors;
 569  size_t n;
 570  bool is_main_vbmeta;
 571  bool look_for_vbmeta_footer;
 572  AvbVBMetaData* vbmeta_image_data = NULL;
 573
 574  ret = AVB_SLOT_VERIFY_RESULT_OK;
 575
 576  avb_assert(slot_data != NULL);
 577
 578  /* Since we allow top-level vbmeta in 'boot', use
 579   * rollback_index_location to determine whether we're the main
 580   * vbmeta struct.
 581   */
 582  is_main_vbmeta = false;
 583  if (rollback_index_location == 0) {
 584    if ((flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) == 0) {
 585      is_main_vbmeta = true;
 586    }
 587  }
 588
 589  /* Don't use footers for vbmeta partitions ('vbmeta' or
 590   * 'vbmeta_<partition_name>').
 591   */
 592  look_for_vbmeta_footer = true;
 593  if (avb_strncmp(partition_name, "vbmeta", avb_strlen("vbmeta")) == 0) {
 594    look_for_vbmeta_footer = false;
 595  }
 596
 597  if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
 598    avb_error("Partition name is not valid UTF-8.\n");
 599    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 600    goto out;
 601  }
 602
 603  /* Construct full partition name e.g. system_a. */
 604  if (!avb_str_concat(full_partition_name,
 605                      sizeof full_partition_name,
 606                      partition_name,
 607                      partition_name_len,
 608                      ab_suffix,
 609                      avb_strlen(ab_suffix))) {
 610    avb_error("Partition name and suffix does not fit.\n");
 611    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 612    goto out;
 613  }
 614
 615  /* If we're loading from the main vbmeta partition, the vbmeta struct is in
 616   * the beginning. Otherwise we may have to locate it via a footer... if no
 617   * footer is found, we look in the beginning to support e.g. vbmeta_<org>
 618   * partitions holding data for e.g. super partitions (b/80195851 for
 619   * rationale).
 620   */
 621  vbmeta_offset = 0;
 622  vbmeta_size = VBMETA_MAX_SIZE;
 623  if (look_for_vbmeta_footer) {
 624    uint8_t footer_buf[AVB_FOOTER_SIZE];
 625    size_t footer_num_read;
 626    AvbFooter footer;
 627
 628    io_ret = ops->read_from_partition(ops,
 629                                      full_partition_name,
 630                                      -AVB_FOOTER_SIZE,
 631                                      AVB_FOOTER_SIZE,
 632                                      footer_buf,
 633                                      &footer_num_read);
 634    if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 635      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 636      goto out;
 637    } else if (io_ret != AVB_IO_RESULT_OK) {
 638      avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
 639      ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 640      goto out;
 641    }
 642    avb_assert(footer_num_read == AVB_FOOTER_SIZE);
 643
 644    if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
 645                                          &footer)) {
 646      avb_debugv(full_partition_name, ": No footer detected.\n", NULL);
 647    } else {
 648      /* Basic footer sanity check since the data is untrusted. */
 649      if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
 650        avb_errorv(
 651            full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
 652      } else {
 653        vbmeta_offset = footer.vbmeta_offset;
 654        vbmeta_size = footer.vbmeta_size;
 655      }
 656    }
 657  }
 658
 659  vbmeta_buf = avb_malloc(vbmeta_size);
 660  if (vbmeta_buf == NULL) {
 661    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 662    goto out;
 663  }
 664
 665  if (vbmeta_offset != 0) {
 666    avb_debugv("Loading vbmeta struct in footer from partition '",
 667               full_partition_name,
 668               "'.\n",
 669               NULL);
 670  } else {
 671    avb_debugv("Loading vbmeta struct from partition '",
 672               full_partition_name,
 673               "'.\n",
 674               NULL);
 675  }
 676
 677  io_ret = ops->read_from_partition(ops,
 678                                    full_partition_name,
 679                                    vbmeta_offset,
 680                                    vbmeta_size,
 681                                    vbmeta_buf,
 682                                    &vbmeta_num_read);
 683  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 684    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 685    goto out;
 686  } else if (io_ret != AVB_IO_RESULT_OK) {
 687    /* If we're looking for 'vbmeta' but there is no such partition,
 688     * go try to get it from the boot partition instead.
 689     */
 690    if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
 691        !look_for_vbmeta_footer) {
 692      avb_debugv(full_partition_name,
 693                 ": No such partition. Trying 'boot' instead.\n",
 694                 NULL);
 695      ret = load_and_verify_vbmeta(ops,
 696                                   requested_partitions,
 697                                   ab_suffix,
 698                                   flags,
 699                                   allow_verification_error,
 700                                   0 /* toplevel_vbmeta_flags */,
 701                                   0 /* rollback_index_location */,
 702                                   "boot",
 703                                   avb_strlen("boot"),
 704                                   NULL /* expected_public_key */,
 705                                   0 /* expected_public_key_length */,
 706                                   slot_data,
 707                                   out_algorithm_type,
 708                                   out_additional_cmdline_subst);
 709      goto out;
 710    } else {
 711      avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
 712      ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 713      goto out;
 714    }
 715  }
 716  avb_assert(vbmeta_num_read <= vbmeta_size);
 717
 718  /* Check if the image is properly signed and get the public key used
 719   * to sign the image.
 720   */
 721  vbmeta_ret =
 722      avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
 723  switch (vbmeta_ret) {
 724    case AVB_VBMETA_VERIFY_RESULT_OK:
 725      avb_assert(pk_data != NULL && pk_len > 0);
 726      break;
 727
 728    case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
 729    case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
 730    case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
 731      ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
 732      avb_errorv(full_partition_name,
 733                 ": Error verifying vbmeta image: ",
 734                 avb_vbmeta_verify_result_to_string(vbmeta_ret),
 735                 "\n",
 736                 NULL);
 737      if (!allow_verification_error) {
 738        goto out;
 739      }
 740      break;
 741
 742    case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
 743      /* No way to continue this case. */
 744      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 745      avb_errorv(full_partition_name,
 746                 ": Error verifying vbmeta image: invalid vbmeta header\n",
 747                 NULL);
 748      goto out;
 749
 750    case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
 751      /* No way to continue this case. */
 752      ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
 753      avb_errorv(full_partition_name,
 754                 ": Error verifying vbmeta image: unsupported AVB version\n",
 755                 NULL);
 756      goto out;
 757  }
 758
 759  /* Byteswap the header. */
 760  avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
 761                                             &vbmeta_header);
 762
 763  /* If we're the toplevel, assign flags so they'll be passed down. */
 764  if (is_main_vbmeta) {
 765    toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
 766  } else {
 767    if (vbmeta_header.flags != 0) {
 768      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 769      avb_errorv(full_partition_name,
 770                 ": chained vbmeta image has non-zero flags\n",
 771                 NULL);
 772      goto out;
 773    }
 774  }
 775
 776  uint32_t rollback_index_location_to_use = rollback_index_location;
 777
 778  /* Check if key used to make signature matches what is expected. */
 779  if (pk_data != NULL) {
 780    if (expected_public_key != NULL) {
 781      avb_assert(!is_main_vbmeta);
 782      if (expected_public_key_length != pk_len ||
 783          avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
 784        avb_errorv(full_partition_name,
 785                   ": Public key used to sign data does not match key in chain "
 786                   "partition descriptor.\n",
 787                   NULL);
 788        ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
 789        if (!allow_verification_error) {
 790          goto out;
 791        }
 792      }
 793    } else {
 794      bool key_is_trusted = false;
 795      const uint8_t* pk_metadata = NULL;
 796      size_t pk_metadata_len = 0;
 797
 798      if (vbmeta_header.public_key_metadata_size > 0) {
 799        pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
 800                      vbmeta_header.authentication_data_block_size +
 801                      vbmeta_header.public_key_metadata_offset;
 802        pk_metadata_len = vbmeta_header.public_key_metadata_size;
 803      }
 804
 805      // If we're not using a vbmeta partition, need to use another AvbOps...
 806      if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
 807        io_ret = ops->validate_public_key_for_partition(
 808            ops,
 809            full_partition_name,
 810            pk_data,
 811            pk_len,
 812            pk_metadata,
 813            pk_metadata_len,
 814            &key_is_trusted,
 815            &rollback_index_location_to_use);
 816      } else {
 817        avb_assert(is_main_vbmeta);
 818        io_ret = ops->validate_vbmeta_public_key(ops,
 819                                                 pk_data,
 820                                                 pk_len,
 821                                                 pk_metadata,
 822                                                 pk_metadata_len,
 823                                                 &key_is_trusted);
 824      }
 825
 826      if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 827        ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 828        goto out;
 829      } else if (io_ret != AVB_IO_RESULT_OK) {
 830        avb_errorv(full_partition_name,
 831                   ": Error while checking public key used to sign data.\n",
 832                   NULL);
 833        ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 834        goto out;
 835      }
 836      if (!key_is_trusted) {
 837        avb_errorv(full_partition_name,
 838                   ": Public key used to sign data rejected.\n",
 839                   NULL);
 840        ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
 841        if (!allow_verification_error) {
 842          goto out;
 843        }
 844      }
 845    }
 846  }
 847
 848  /* Check rollback index. */
 849  io_ret = ops->read_rollback_index(
 850      ops, rollback_index_location_to_use, &stored_rollback_index);
 851  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
 852    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 853    goto out;
 854  } else if (io_ret != AVB_IO_RESULT_OK) {
 855    avb_errorv(full_partition_name,
 856               ": Error getting rollback index for location.\n",
 857               NULL);
 858    ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
 859    goto out;
 860  }
 861  if (vbmeta_header.rollback_index < stored_rollback_index) {
 862    avb_errorv(
 863        full_partition_name,
 864        ": Image rollback index is less than the stored rollback index.\n",
 865        NULL);
 866    ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
 867    if (!allow_verification_error) {
 868      goto out;
 869    }
 870  }
 871
 872  /* Copy vbmeta to vbmeta_images before recursing. */
 873  if (is_main_vbmeta) {
 874    avb_assert(slot_data->num_vbmeta_images == 0);
 875  } else {
 876    if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
 877      avb_assert(slot_data->num_vbmeta_images > 0);
 878    }
 879  }
 880  if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
 881    avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
 882    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
 883    goto out;
 884  }
 885  vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
 886  vbmeta_image_data->partition_name = avb_strdup(partition_name);
 887  vbmeta_image_data->vbmeta_data = vbmeta_buf;
 888  /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
 889   * and this includes data past the end of the image. Pass the
 890   * actual size of the vbmeta image. Also, no need to use
 891   * avb_safe_add() since the header has already been verified.
 892   */
 893  vbmeta_image_data->vbmeta_size =
 894      sizeof(AvbVBMetaImageHeader) +
 895      vbmeta_header.authentication_data_block_size +
 896      vbmeta_header.auxiliary_data_block_size;
 897  vbmeta_image_data->verify_result = vbmeta_ret;
 898
 899  /* If verification has been disabled by setting a bit in the image,
 900   * we're done... except that we need to load the entirety of the
 901   * requested partitions.
 902   */
 903  if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
 904    AvbSlotVerifyResult sub_ret;
 905    avb_debugv(
 906        full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
 907    /* If load_requested_partitions() fail it is always a fatal
 908     * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
 909     * than recoverable (e.g. one where result_should_continue()
 910     * returns true) and we want to convey that error.
 911     */
 912    sub_ret = load_requested_partitions(
 913        ops, requested_partitions, ab_suffix, slot_data);
 914    if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
 915      ret = sub_ret;
 916    }
 917    goto out;
 918  }
 919
 920  /* Now go through all descriptors and take the appropriate action:
 921   *
 922   * - hash descriptor: Load data from partition, calculate hash, and
 923   *   checks that it matches what's in the hash descriptor.
 924   *
 925   * - hashtree descriptor: Do nothing since verification happens
 926   *   on-the-fly from within the OS. (Unless the descriptor uses a
 927   *   persistent digest, in which case we need to find it).
 928   *
 929   * - chained partition descriptor: Load the footer, load the vbmeta
 930   *   image, verify vbmeta image (includes rollback checks, hash
 931   *   checks, bail on chained partitions).
 932   */
 933  descriptors =
 934      avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
 935  for (n = 0; n < num_descriptors; n++) {
 936    AvbDescriptor desc;
 937
 938    if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
 939      avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
 940      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 941      goto out;
 942    }
 943
 944    switch (desc.tag) {
 945      case AVB_DESCRIPTOR_TAG_HASH: {
 946        AvbSlotVerifyResult sub_ret;
 947        sub_ret = load_and_verify_hash_partition(ops,
 948                                                 requested_partitions,
 949                                                 ab_suffix,
 950                                                 allow_verification_error,
 951                                                 descriptors[n],
 952                                                 slot_data);
 953        if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
 954          ret = sub_ret;
 955          if (!allow_verification_error || !result_should_continue(ret)) {
 956            goto out;
 957          }
 958        }
 959      } break;
 960
 961      case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
 962        AvbSlotVerifyResult sub_ret;
 963        AvbChainPartitionDescriptor chain_desc;
 964        const uint8_t* chain_partition_name;
 965        const uint8_t* chain_public_key;
 966
 967        /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
 968        if (!is_main_vbmeta) {
 969          avb_errorv(full_partition_name,
 970                     ": Encountered chain descriptor not in main image.\n",
 971                     NULL);
 972          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 973          goto out;
 974        }
 975
 976        if (!avb_chain_partition_descriptor_validate_and_byteswap(
 977                (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
 978          avb_errorv(full_partition_name,
 979                     ": Chain partition descriptor is invalid.\n",
 980                     NULL);
 981          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 982          goto out;
 983        }
 984
 985        if (chain_desc.rollback_index_location == 0) {
 986          avb_errorv(full_partition_name,
 987                     ": Chain partition has invalid "
 988                     "rollback_index_location field.\n",
 989                     NULL);
 990          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
 991          goto out;
 992        }
 993
 994        chain_partition_name = ((const uint8_t*)descriptors[n]) +
 995                               sizeof(AvbChainPartitionDescriptor);
 996        chain_public_key = chain_partition_name + chain_desc.partition_name_len;
 997
 998        sub_ret =
 999            load_and_verify_vbmeta(ops,
1000                                   requested_partitions,
1001                                   ab_suffix,
1002                                   flags,
1003                                   allow_verification_error,
1004                                   toplevel_vbmeta_flags,
1005                                   chain_desc.rollback_index_location,
1006                                   (const char*)chain_partition_name,
1007                                   chain_desc.partition_name_len,
1008                                   chain_public_key,
1009                                   chain_desc.public_key_len,
1010                                   slot_data,
1011                                   NULL, /* out_algorithm_type */
1012                                   NULL /* out_additional_cmdline_subst */);
1013        if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1014          ret = sub_ret;
1015          if (!result_should_continue(ret)) {
1016            goto out;
1017          }
1018        }
1019      } break;
1020
1021      case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
1022        const uint8_t* kernel_cmdline;
1023        AvbKernelCmdlineDescriptor kernel_cmdline_desc;
1024        bool apply_cmdline;
1025
1026        if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
1027                (AvbKernelCmdlineDescriptor*)descriptors[n],
1028                &kernel_cmdline_desc)) {
1029          avb_errorv(full_partition_name,
1030                     ": Kernel cmdline descriptor is invalid.\n",
1031                     NULL);
1032          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1033          goto out;
1034        }
1035
1036        kernel_cmdline = ((const uint8_t*)descriptors[n]) +
1037                         sizeof(AvbKernelCmdlineDescriptor);
1038
1039        if (!avb_validate_utf8(kernel_cmdline,
1040                               kernel_cmdline_desc.kernel_cmdline_length)) {
1041          avb_errorv(full_partition_name,
1042                     ": Kernel cmdline is not valid UTF-8.\n",
1043                     NULL);
1044          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1045          goto out;
1046        }
1047
1048        /* Compare the flags for top-level VBMeta struct with flags in
1049         * the command-line descriptor so command-line snippets only
1050         * intended for a certain mode (dm-verity enabled/disabled)
1051         * are skipped if applicable.
1052         */
1053        apply_cmdline = true;
1054        if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
1055          if (kernel_cmdline_desc.flags &
1056              AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
1057            apply_cmdline = false;
1058          }
1059        } else {
1060          if (kernel_cmdline_desc.flags &
1061              AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
1062            apply_cmdline = false;
1063          }
1064        }
1065
1066        if (apply_cmdline) {
1067          if (slot_data->cmdline == NULL) {
1068            slot_data->cmdline =
1069                avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
1070            if (slot_data->cmdline == NULL) {
1071              ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1072              goto out;
1073            }
1074            avb_memcpy(slot_data->cmdline,
1075                       kernel_cmdline,
1076                       kernel_cmdline_desc.kernel_cmdline_length);
1077          } else {
1078            /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
1079            size_t orig_size = avb_strlen(slot_data->cmdline);
1080            size_t new_size =
1081                orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
1082            char* new_cmdline = avb_calloc(new_size);
1083            if (new_cmdline == NULL) {
1084              ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1085              goto out;
1086            }
1087            avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
1088            new_cmdline[orig_size] = ' ';
1089            avb_memcpy(new_cmdline + orig_size + 1,
1090                       kernel_cmdline,
1091                       kernel_cmdline_desc.kernel_cmdline_length);
1092            avb_free(slot_data->cmdline);
1093            slot_data->cmdline = new_cmdline;
1094          }
1095        }
1096      } break;
1097
1098      case AVB_DESCRIPTOR_TAG_HASHTREE: {
1099        AvbHashtreeDescriptor hashtree_desc;
1100
1101        if (!avb_hashtree_descriptor_validate_and_byteswap(
1102                (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
1103          avb_errorv(
1104              full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
1105          ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1106          goto out;
1107        }
1108
1109        /* We only need to continue when there is no digest in the descriptor.
1110         * This is because the only processing here is to find the digest and
1111         * make it available on the kernel command line.
1112         */
1113        if (hashtree_desc.root_digest_len == 0) {
1114          char part_name[AVB_PART_NAME_MAX_SIZE];
1115          size_t digest_len = 0;
1116          uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
1117          const uint8_t* desc_partition_name =
1118              ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
1119
1120          if (!avb_validate_utf8(desc_partition_name,
1121                                 hashtree_desc.partition_name_len)) {
1122            avb_error("Partition name is not valid UTF-8.\n");
1123            ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1124            goto out;
1125          }
1126
1127          /* No ab_suffix for partitions without a digest in the descriptor
1128           * because these partitions hold data unique to this device and are
1129           * not updated using an A/B scheme.
1130           */
1131          if ((hashtree_desc.flags &
1132               AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
1133              avb_strlen(ab_suffix) != 0) {
1134            avb_error("Cannot use A/B with a persistent root digest.\n");
1135            ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1136            goto out;
1137          }
1138          if (hashtree_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
1139            avb_error("Partition name does not fit.\n");
1140            ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1141            goto out;
1142          }
1143          avb_memcpy(
1144              part_name, desc_partition_name, hashtree_desc.partition_name_len);
1145          part_name[hashtree_desc.partition_name_len] = '\0';
1146
1147          /* Determine the expected digest size from the hash algorithm. */
1148          if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
1149              0) {
1150            digest_len = AVB_SHA1_DIGEST_SIZE;
1151          } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1152                                "sha256") == 0) {
1153            digest_len = AVB_SHA256_DIGEST_SIZE;
1154          } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
1155                                "sha512") == 0) {
1156            digest_len = AVB_SHA512_DIGEST_SIZE;
1157          } else {
1158            avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
1159            ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1160            goto out;
1161          }
1162
1163          ret = read_persistent_digest(ops,
1164                                       part_name,
1165                                       digest_len,
1166                                       NULL /* initial_digest */,
1167                                       digest_buf);
1168          if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1169            goto out;
1170          }
1171
1172          if (out_additional_cmdline_subst) {
1173            ret =
1174                avb_add_root_digest_substitution(part_name,
1175                                                 digest_buf,
1176                                                 digest_len,
1177                                                 out_additional_cmdline_subst);
1178            if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
1179              goto out;
1180            }
1181          }
1182        }
1183      } break;
1184
1185      case AVB_DESCRIPTOR_TAG_PROPERTY:
1186        /* Do nothing. */
1187        break;
1188    }
1189  }
1190
1191  if (rollback_index_location < 0 ||
1192      rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
1193    avb_errorv(
1194        full_partition_name, ": Invalid rollback_index_location.\n", NULL);
1195    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
1196    goto out;
1197  }
1198
1199  slot_data->rollback_indexes[rollback_index_location] =
1200      vbmeta_header.rollback_index;
1201
1202  if (out_algorithm_type != NULL) {
1203    *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
1204  }
1205
1206out:
1207  /* If |vbmeta_image_data| isn't NULL it means that it adopted
1208   * |vbmeta_buf| so in that case don't free it here.
1209   */
1210  if (vbmeta_image_data == NULL) {
1211    if (vbmeta_buf != NULL) {
1212      avb_free(vbmeta_buf);
1213    }
1214  }
1215  if (descriptors != NULL) {
1216    avb_free(descriptors);
1217  }
1218  return ret;
1219}
1220
1221static AvbIOResult avb_manage_hashtree_error_mode(
1222    AvbOps* ops,
1223    AvbSlotVerifyFlags flags,
1224    AvbSlotVerifyData* data,
1225    AvbHashtreeErrorMode* out_hashtree_error_mode) {
1226  AvbHashtreeErrorMode ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1227  AvbIOResult io_ret = AVB_IO_RESULT_OK;
1228  uint8_t vbmeta_digest_sha256[AVB_SHA256_DIGEST_SIZE];
1229  uint8_t stored_vbmeta_digest_sha256[AVB_SHA256_DIGEST_SIZE];
1230  size_t num_bytes_read;
1231
1232  avb_assert(out_hashtree_error_mode != NULL);
1233  avb_assert(ops->read_persistent_value != NULL);
1234  avb_assert(ops->write_persistent_value != NULL);
1235
1236  // If we're rebooting because of dm-verity corruption, make a note of
1237  // the vbmeta hash so we can stay in 'eio' mode until things change.
1238  if (flags & AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION) {
1239    avb_debug(
1240        "Rebooting because of dm-verity corruption - "
1241        "recording OS instance and using 'eio' mode.\n");
1242    avb_slot_verify_data_calculate_vbmeta_digest(
1243        data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest_sha256);
1244    io_ret = ops->write_persistent_value(ops,
1245                                         AVB_NPV_MANAGED_VERITY_MODE,
1246                                         AVB_SHA256_DIGEST_SIZE,
1247                                         vbmeta_digest_sha256);
1248    if (io_ret != AVB_IO_RESULT_OK) {
1249      avb_error("Error writing to " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1250      goto out;
1251    }
1252    ret = AVB_HASHTREE_ERROR_MODE_EIO;
1253    io_ret = AVB_IO_RESULT_OK;
1254    goto out;
1255  }
1256
1257  // See if we're in 'eio' mode.
1258  io_ret = ops->read_persistent_value(ops,
1259                                      AVB_NPV_MANAGED_VERITY_MODE,
1260                                      AVB_SHA256_DIGEST_SIZE,
1261                                      stored_vbmeta_digest_sha256,
1262                                      &num_bytes_read);
1263  if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE ||
1264      (io_ret == AVB_IO_RESULT_OK && num_bytes_read == 0)) {
1265    // This is the usual case ('eio' mode not set).
1266    avb_debug("No dm-verity corruption - using in 'restart' mode.\n");
1267    ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1268    io_ret = AVB_IO_RESULT_OK;
1269    goto out;
1270  } else if (io_ret != AVB_IO_RESULT_OK) {
1271    avb_error("Error reading from " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1272    goto out;
1273  }
1274  if (num_bytes_read != AVB_SHA256_DIGEST_SIZE) {
1275    avb_error(
1276        "Unexpected number of bytes read from " AVB_NPV_MANAGED_VERITY_MODE
1277        ".\n");
1278    io_ret = AVB_IO_RESULT_ERROR_IO;
1279    goto out;
1280  }
1281
1282  // OK, so we're currently in 'eio' mode and the vbmeta digest of the OS
1283  // that caused this is in |stored_vbmeta_digest_sha256| ... now see if
1284  // the OS we're dealing with now is the same.
1285  avb_slot_verify_data_calculate_vbmeta_digest(
1286      data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest_sha256);
1287  if (avb_memcmp(vbmeta_digest_sha256,
1288                 stored_vbmeta_digest_sha256,
1289                 AVB_SHA256_DIGEST_SIZE) == 0) {
1290    // It's the same so we're still in 'eio' mode.
1291    avb_debug("Same OS instance detected - staying in 'eio' mode.\n");
1292    ret = AVB_HASHTREE_ERROR_MODE_EIO;
1293    io_ret = AVB_IO_RESULT_OK;
1294  } else {
1295    // It did change!
1296    avb_debug(
1297        "New OS instance detected - changing from 'eio' to 'restart' mode.\n");
1298    io_ret =
1299        ops->write_persistent_value(ops,
1300                                    AVB_NPV_MANAGED_VERITY_MODE,
1301                                    0,  // This clears the persistent property.
1302                                    vbmeta_digest_sha256);
1303    if (io_ret != AVB_IO_RESULT_OK) {
1304      avb_error("Error clearing " AVB_NPV_MANAGED_VERITY_MODE ".\n");
1305      goto out;
1306    }
1307    ret = AVB_HASHTREE_ERROR_MODE_RESTART;
1308    io_ret = AVB_IO_RESULT_OK;
1309  }
1310
1311out:
1312  *out_hashtree_error_mode = ret;
1313  return io_ret;
1314}
1315
1316static bool has_system_partition(AvbOps* ops, const char* ab_suffix) {
1317  char part_name[AVB_PART_NAME_MAX_SIZE];
1318  char* system_part_name = "system";
1319  char guid_buf[37];
1320  AvbIOResult io_ret;
1321
1322  if (!avb_str_concat(part_name,
1323                      sizeof part_name,
1324                      system_part_name,
1325                      avb_strlen(system_part_name),
1326                      ab_suffix,
1327                      avb_strlen(ab_suffix))) {
1328    avb_error("System partition name and suffix does not fit.\n");
1329    return false;
1330  }
1331
1332  io_ret = ops->get_unique_guid_for_partition(
1333      ops, part_name, guid_buf, sizeof guid_buf);
1334  if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
1335    avb_debug("No system partition.\n");
1336    return false;
1337  } else if (io_ret != AVB_IO_RESULT_OK) {
1338    avb_error("Error getting unique GUID for system partition.\n");
1339    return false;
1340  }
1341
1342  return true;
1343}
1344
1345AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
1346                                    const char* const* requested_partitions,
1347                                    const char* ab_suffix,
1348                                    AvbSlotVerifyFlags flags,
1349                                    AvbHashtreeErrorMode hashtree_error_mode,
1350                                    AvbSlotVerifyData** out_data) {
1351  AvbSlotVerifyResult ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1352  AvbSlotVerifyData* slot_data = NULL;
1353  AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
1354  bool using_boot_for_vbmeta = false;
1355  AvbVBMetaImageHeader toplevel_vbmeta;
1356  bool allow_verification_error =
1357      (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
1358  AvbCmdlineSubstList* additional_cmdline_subst = NULL;
1359
1360  /* Fail early if we're missing the AvbOps needed for slot verification. */
1361  avb_assert(ops->read_is_device_unlocked != NULL);
1362  avb_assert(ops->read_from_partition != NULL);
1363  avb_assert(ops->get_size_of_partition != NULL);
1364  avb_assert(ops->read_rollback_index != NULL);
1365  avb_assert(ops->get_unique_guid_for_partition != NULL);
1366
1367  if (out_data != NULL) {
1368    *out_data = NULL;
1369  }
1370
1371  /* Allowing dm-verity errors defeats the purpose of verified boot so
1372   * only allow this if set up to allow verification errors
1373   * (e.g. typically only UNLOCKED mode).
1374   */
1375  if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
1376      !allow_verification_error) {
1377    ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1378    goto fail;
1379  }
1380
1381  /* Make sure passed-in AvbOps support persistent values if
1382   * asking for libavb to manage verity state.
1383   */
1384  if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
1385    if (ops->read_persistent_value == NULL ||
1386        ops->write_persistent_value == NULL) {
1387      avb_error(
1388          "Persistent values required for "
1389          "AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO "
1390          "but are not implemented in given AvbOps.\n");
1391      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1392      goto fail;
1393    }
1394  }
1395
1396  /* Make sure passed-in AvbOps support verifying public keys and getting
1397   * rollback index location if not using a vbmeta partition.
1398   */
1399  if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
1400    if (ops->validate_public_key_for_partition == NULL) {
1401      avb_error(
1402          "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
1403          "validate_public_key_for_partition() operation isn't implemented.\n");
1404      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1405      goto fail;
1406    }
1407  } else {
1408    avb_assert(ops->validate_vbmeta_public_key != NULL);
1409  }
1410
1411  slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
1412  if (slot_data == NULL) {
1413    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1414    goto fail;
1415  }
1416  slot_data->vbmeta_images =
1417      avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
1418  if (slot_data->vbmeta_images == NULL) {
1419    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1420    goto fail;
1421  }
1422  slot_data->loaded_partitions =
1423      avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
1424  if (slot_data->loaded_partitions == NULL) {
1425    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1426    goto fail;
1427  }
1428
1429  additional_cmdline_subst = avb_new_cmdline_subst_list();
1430  if (additional_cmdline_subst == NULL) {
1431    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1432    goto fail;
1433  }
1434
1435  if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
1436    if (requested_partitions == NULL || requested_partitions[0] == NULL) {
1437      avb_fatal(
1438          "Requested partitions cannot be empty when using "
1439          "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
1440      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
1441      goto fail;
1442    }
1443
1444    /* No vbmeta partition, go through each of the requested partitions... */
1445    for (size_t n = 0; requested_partitions[n] != NULL; n++) {
1446      ret = load_and_verify_vbmeta(ops,
1447                                   requested_partitions,
1448                                   ab_suffix,
1449                                   flags,
1450                                   allow_verification_error,
1451                                   0 /* toplevel_vbmeta_flags */,
1452                                   0 /* rollback_index_location */,
1453                                   requested_partitions[n],
1454                                   avb_strlen(requested_partitions[n]),
1455                                   NULL /* expected_public_key */,
1456                                   0 /* expected_public_key_length */,
1457                                   slot_data,
1458                                   &algorithm_type,
1459                                   additional_cmdline_subst);
1460      if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1461        goto fail;
1462      }
1463    }
1464
1465  } else {
1466    /* Usual path, load "vbmeta"... */
1467    ret = load_and_verify_vbmeta(ops,
1468                                 requested_partitions,
1469                                 ab_suffix,
1470                                 flags,
1471                                 allow_verification_error,
1472                                 0 /* toplevel_vbmeta_flags */,
1473                                 0 /* rollback_index_location */,
1474                                 "vbmeta",
1475                                 avb_strlen("vbmeta"),
1476                                 NULL /* expected_public_key */,
1477                                 0 /* expected_public_key_length */,
1478                                 slot_data,
1479                                 &algorithm_type,
1480                                 additional_cmdline_subst);
1481    if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
1482      goto fail;
1483    }
1484  }
1485
1486  if (!result_should_continue(ret)) {
1487    goto fail;
1488  }
1489
1490  /* If things check out, mangle the kernel command-line as needed. */
1491  if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
1492    if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
1493      avb_assert(
1494          avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
1495      using_boot_for_vbmeta = true;
1496    }
1497  }
1498
1499  /* Byteswap top-level vbmeta header since we'll need it below. */
1500  avb_vbmeta_image_header_to_host_byte_order(
1501      (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
1502      &toplevel_vbmeta);
1503
1504  /* Fill in |ab_suffix| field. */
1505  slot_data->ab_suffix = avb_strdup(ab_suffix);
1506  if (slot_data->ab_suffix == NULL) {
1507    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1508    goto fail;
1509  }
1510
1511  /* If verification is disabled, we are done ... we specifically
1512   * don't want to add any androidboot.* options since verification
1513   * is disabled.
1514   */
1515  if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
1516    /* Since verification is disabled we didn't process any
1517     * descriptors and thus there's no cmdline... so set root= such
1518     * that the system partition is mounted.
1519     */
1520    avb_assert(slot_data->cmdline == NULL);
1521    // Devices with dynamic partitions won't have system partition.
1522    // Instead, it has a large super partition to accommodate *.img files.
1523    // See b/119551429 for details.
1524    if (has_system_partition(ops, ab_suffix)) {
1525      slot_data->cmdline =
1526          avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
1527    } else {
1528      // The |cmdline| field should be a NUL-terminated string.
1529      slot_data->cmdline = avb_strdup("");
1530    }
1531    if (slot_data->cmdline == NULL) {
1532      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1533      goto fail;
1534    }
1535  } else {
1536    /* If requested, manage dm-verity mode... */
1537    AvbHashtreeErrorMode resolved_hashtree_error_mode = hashtree_error_mode;
1538    if (hashtree_error_mode ==
1539        AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
1540      AvbIOResult io_ret;
1541      io_ret = avb_manage_hashtree_error_mode(
1542          ops, flags, slot_data, &resolved_hashtree_error_mode);
1543      if (io_ret != AVB_IO_RESULT_OK) {
1544        ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
1545        if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
1546          ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1547        }
1548        goto fail;
1549      }
1550    }
1551    slot_data->resolved_hashtree_error_mode = resolved_hashtree_error_mode;
1552
1553    /* Add options... */
1554    AvbSlotVerifyResult sub_ret;
1555    sub_ret = avb_append_options(ops,
1556                                 flags,
1557                                 slot_data,
1558                                 &toplevel_vbmeta,
1559                                 algorithm_type,
1560                                 hashtree_error_mode,
1561                                 resolved_hashtree_error_mode);
1562    if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
1563      ret = sub_ret;
1564      goto fail;
1565    }
1566  }
1567
1568  /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
1569  if (slot_data->cmdline != NULL && avb_strlen(slot_data->cmdline) != 0) {
1570    char* new_cmdline;
1571    new_cmdline = avb_sub_cmdline(ops,
1572                                  slot_data->cmdline,
1573                                  ab_suffix,
1574                                  using_boot_for_vbmeta,
1575                                  additional_cmdline_subst);
1576    if (new_cmdline != slot_data->cmdline) {
1577      if (new_cmdline == NULL) {
1578        ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
1579        goto fail;
1580      }
1581      avb_free(slot_data->cmdline);
1582      slot_data->cmdline = new_cmdline;
1583    }
1584  }
1585
1586  if (out_data != NULL) {
1587    *out_data = slot_data;
1588  } else {
1589    avb_slot_verify_data_free(slot_data);
1590  }
1591
1592  avb_free_cmdline_subst_list(additional_cmdline_subst);
1593  additional_cmdline_subst = NULL;
1594
1595  if (!allow_verification_error) {
1596    avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
1597  }
1598
1599  return ret;
1600
1601fail:
1602  if (slot_data != NULL) {
1603    avb_slot_verify_data_free(slot_data);
1604  }
1605  if (additional_cmdline_subst != NULL) {
1606    avb_free_cmdline_subst_list(additional_cmdline_subst);
1607  }
1608  return ret;
1609}
1610
1611void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
1612  if (data->ab_suffix != NULL) {
1613    avb_free(data->ab_suffix);
1614  }
1615  if (data->cmdline != NULL) {
1616    avb_free(data->cmdline);
1617  }
1618  if (data->vbmeta_images != NULL) {
1619    size_t n;
1620    for (n = 0; n < data->num_vbmeta_images; n++) {
1621      AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
1622      if (vbmeta_image->partition_name != NULL) {
1623        avb_free(vbmeta_image->partition_name);
1624      }
1625      if (vbmeta_image->vbmeta_data != NULL) {
1626        avb_free(vbmeta_image->vbmeta_data);
1627      }
1628    }
1629    avb_free(data->vbmeta_images);
1630  }
1631  if (data->loaded_partitions != NULL) {
1632    size_t n;
1633    for (n = 0; n < data->num_loaded_partitions; n++) {
1634      AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
1635      if (loaded_partition->partition_name != NULL) {
1636        avb_free(loaded_partition->partition_name);
1637      }
1638      if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
1639        avb_free(loaded_partition->data);
1640      }
1641    }
1642    avb_free(data->loaded_partitions);
1643  }
1644  avb_free(data);
1645}
1646
1647const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
1648  const char* ret = NULL;
1649
1650  switch (result) {
1651    case AVB_SLOT_VERIFY_RESULT_OK:
1652      ret = "OK";
1653      break;
1654    case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
1655      ret = "ERROR_OOM";
1656      break;
1657    case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
1658      ret = "ERROR_IO";
1659      break;
1660    case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
1661      ret = "ERROR_VERIFICATION";
1662      break;
1663    case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
1664      ret = "ERROR_ROLLBACK_INDEX";
1665      break;
1666    case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
1667      ret = "ERROR_PUBLIC_KEY_REJECTED";
1668      break;
1669    case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
1670      ret = "ERROR_INVALID_METADATA";
1671      break;
1672    case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
1673      ret = "ERROR_UNSUPPORTED_VERSION";
1674      break;
1675    case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
1676      ret = "ERROR_INVALID_ARGUMENT";
1677      break;
1678      /* Do not add a 'default:' case here because of -Wswitch. */
1679  }
1680
1681  if (ret == NULL) {
1682    avb_error("Unknown AvbSlotVerifyResult value.\n");
1683    ret = "(unknown)";
1684  }
1685
1686  return ret;
1687}
1688
1689void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
1690                                                  AvbDigestType digest_type,
1691                                                  uint8_t* out_digest) {
1692  bool ret = false;
1693  size_t n;
1694
1695  switch (digest_type) {
1696    case AVB_DIGEST_TYPE_SHA256: {
1697      AvbSHA256Ctx ctx;
1698      avb_sha256_init(&ctx);
1699      for (n = 0; n < data->num_vbmeta_images; n++) {
1700        avb_sha256_update(&ctx,
1701                          data->vbmeta_images[n].vbmeta_data,
1702                          data->vbmeta_images[n].vbmeta_size);
1703      }
1704      avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
1705      ret = true;
1706    } break;
1707
1708    case AVB_DIGEST_TYPE_SHA512: {
1709      AvbSHA512Ctx ctx;
1710      avb_sha512_init(&ctx);
1711      for (n = 0; n < data->num_vbmeta_images; n++) {
1712        avb_sha512_update(&ctx,
1713                          data->vbmeta_images[n].vbmeta_data,
1714                          data->vbmeta_images[n].vbmeta_size);
1715      }
1716      avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
1717      ret = true;
1718    } break;
1719
1720      /* Do not add a 'default:' case here because of -Wswitch. */
1721  }
1722
1723  if (!ret) {
1724    avb_fatal("Unknown digest type");
1725  }
1726}
1727