Home | History | Annotate | Download | only in libavb
      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 
     18 /* Maximum number of partitions that can be loaded with avb_slot_verify(). */
     19 #define MAX_NUMBER_OF_LOADED_PARTITIONS 32
     20 
     21 /* Maximum number of vbmeta images that can be loaded with avb_slot_verify(). */
     22 #define MAX_NUMBER_OF_VBMETA_IMAGES 32
     23 
     24 /* Maximum size of a vbmeta image - 64 KiB. */
     25 #define VBMETA_MAX_SIZE (64 * 1024)
     26 
     27 /* Helper function to see if we should continue with verification in
     28  * allow_verification_error=true mode if something goes wrong. See the
     29  * comments for the avb_slot_verify() function for more information.
     30  */
     31 static inline bool result_should_continue(AvbSlotVerifyResult result) {
     32   switch (result) {
     33     case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
     34     case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
     35     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
     36     case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
     37     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
     38       return false;
     39 
     40     case AVB_SLOT_VERIFY_RESULT_OK:
     41     case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
     42     case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
     43     case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
     44       return true;
     45   }
     46 
     47   return false;
     48 }
     49 
     50 static AvbSlotVerifyResult load_full_partition(AvbOps* ops,
     51                                                const char* part_name,
     52                                                uint64_t image_size,
     53                                                uint8_t** out_image_buf,
     54                                                bool* out_image_preloaded) {
     55   size_t part_num_read;
     56   AvbIOResult io_ret;
     57 
     58   /* Make sure that we do not overwrite existing data. */
     59   avb_assert(*out_image_buf == NULL);
     60   avb_assert(!*out_image_preloaded);
     61 
     62   /* We are going to implicitly cast image_size from uint64_t to size_t in the
     63    * following code, so we need to make sure that the cast is safe. */
     64   if (image_size != (size_t)(image_size)) {
     65     avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
     66     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
     67   }
     68 
     69   /* Try use a preloaded one. */
     70   if (ops->get_preloaded_partition != NULL) {
     71     io_ret = ops->get_preloaded_partition(
     72         ops, part_name, image_size, out_image_buf, &part_num_read);
     73     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
     74       return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     75     } else if (io_ret != AVB_IO_RESULT_OK) {
     76       avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
     77       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
     78     }
     79 
     80     if (*out_image_buf != NULL) {
     81       if (part_num_read != image_size) {
     82         avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
     83         return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
     84       }
     85       *out_image_preloaded = true;
     86     }
     87   }
     88 
     89   /* Allocate and copy the partition. */
     90   if (!*out_image_preloaded) {
     91     *out_image_buf = avb_malloc(image_size);
     92     if (*out_image_buf == NULL) {
     93       return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     94     }
     95 
     96     io_ret = ops->read_from_partition(ops,
     97                                       part_name,
     98                                       0 /* offset */,
     99                                       image_size,
    100                                       *out_image_buf,
    101                                       &part_num_read);
    102     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
    103       return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    104     } else if (io_ret != AVB_IO_RESULT_OK) {
    105       avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
    106       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    107     }
    108     if (part_num_read != image_size) {
    109       avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
    110       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    111     }
    112   }
    113 
    114   return AVB_SLOT_VERIFY_RESULT_OK;
    115 }
    116 
    117 static AvbSlotVerifyResult read_persistent_digest(AvbOps* ops,
    118                                                   const char* part_name,
    119                                                   size_t expected_digest_size,
    120                                                   uint8_t* out_digest) {
    121   char* persistent_value_name = NULL;
    122   AvbIOResult io_ret = AVB_IO_RESULT_OK;
    123   size_t stored_digest_size = 0;
    124 
    125   if (ops->read_persistent_value == NULL) {
    126     avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
    127     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    128   }
    129   persistent_value_name =
    130       avb_strdupv(AVB_NPV_PERSISTENT_DIGEST_PREFIX, part_name, NULL);
    131   if (persistent_value_name == NULL) {
    132     return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    133   }
    134   io_ret = ops->read_persistent_value(ops,
    135                                       persistent_value_name,
    136                                       expected_digest_size,
    137                                       out_digest,
    138                                       &stored_digest_size);
    139   avb_free(persistent_value_name);
    140   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
    141     return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    142   } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
    143     avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
    144     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    145   } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
    146              io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE ||
    147              expected_digest_size != stored_digest_size) {
    148     avb_errorv(
    149         part_name, ": Persistent digest is not of expected size.\n", NULL);
    150     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    151   } else if (io_ret != AVB_IO_RESULT_OK) {
    152     avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
    153     return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    154   }
    155   return AVB_SLOT_VERIFY_RESULT_OK;
    156 }
    157 
    158 static AvbSlotVerifyResult load_and_verify_hash_partition(
    159     AvbOps* ops,
    160     const char* const* requested_partitions,
    161     const char* ab_suffix,
    162     bool allow_verification_error,
    163     const AvbDescriptor* descriptor,
    164     AvbSlotVerifyData* slot_data) {
    165   AvbHashDescriptor hash_desc;
    166   const uint8_t* desc_partition_name = NULL;
    167   const uint8_t* desc_salt;
    168   const uint8_t* desc_digest;
    169   char part_name[AVB_PART_NAME_MAX_SIZE];
    170   AvbSlotVerifyResult ret;
    171   AvbIOResult io_ret;
    172   uint8_t* image_buf = NULL;
    173   bool image_preloaded = false;
    174   uint8_t* digest;
    175   size_t digest_len;
    176   const char* found;
    177   uint64_t image_size;
    178   size_t expected_digest_len = 0;
    179   uint8_t expected_digest_buf[AVB_SHA512_DIGEST_SIZE];
    180   const uint8_t* expected_digest = NULL;
    181 
    182   if (!avb_hash_descriptor_validate_and_byteswap(
    183           (const AvbHashDescriptor*)descriptor, &hash_desc)) {
    184     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    185     goto out;
    186   }
    187 
    188   desc_partition_name =
    189       ((const uint8_t*)descriptor) + sizeof(AvbHashDescriptor);
    190   desc_salt = desc_partition_name + hash_desc.partition_name_len;
    191   desc_digest = desc_salt + hash_desc.salt_len;
    192 
    193   if (!avb_validate_utf8(desc_partition_name, hash_desc.partition_name_len)) {
    194     avb_error("Partition name is not valid UTF-8.\n");
    195     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    196     goto out;
    197   }
    198 
    199   /* Don't bother loading or validating unless the partition was
    200    * requested in the first place.
    201    */
    202   found = avb_strv_find_str(requested_partitions,
    203                             (const char*)desc_partition_name,
    204                             hash_desc.partition_name_len);
    205   if (found == NULL) {
    206     ret = AVB_SLOT_VERIFY_RESULT_OK;
    207     goto out;
    208   }
    209 
    210   if ((hash_desc.flags & AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) != 0) {
    211     /* No ab_suffix, just copy the partition name as is. */
    212     if (hash_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
    213       avb_error("Partition name does not fit.\n");
    214       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    215       goto out;
    216     }
    217     avb_memcpy(part_name, desc_partition_name, hash_desc.partition_name_len);
    218     part_name[hash_desc.partition_name_len] = '\0';
    219   } else if (hash_desc.digest_len == 0 && avb_strlen(ab_suffix) != 0) {
    220     /* No ab_suffix allowed for partitions without a digest in the descriptor
    221      * because these partitions hold data unique to this device and are not
    222      * updated using an A/B scheme.
    223      */
    224     avb_error("Cannot use A/B with a persistent digest.\n");
    225     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    226     goto out;
    227   } else {
    228     /* Add ab_suffix to the partition name. */
    229     if (!avb_str_concat(part_name,
    230                         sizeof part_name,
    231                         (const char*)desc_partition_name,
    232                         hash_desc.partition_name_len,
    233                         ab_suffix,
    234                         avb_strlen(ab_suffix))) {
    235       avb_error("Partition name and suffix does not fit.\n");
    236       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    237       goto out;
    238     }
    239   }
    240 
    241   /* If we're allowing verification errors then hash_desc.image_size
    242    * may no longer match what's in the partition... so in this case
    243    * just load the entire partition.
    244    *
    245    * For example, this can happen if a developer does 'fastboot flash
    246    * boot /path/to/new/and/bigger/boot.img'. We want this to work
    247    * since it's such a common workflow.
    248    */
    249   image_size = hash_desc.image_size;
    250   if (allow_verification_error) {
    251     if (ops->get_size_of_partition == NULL) {
    252       avb_errorv(part_name,
    253                  ": The get_size_of_partition() operation is "
    254                  "not implemented so we may not load the entire partition. "
    255                  "Please implement.",
    256                  NULL);
    257     } else {
    258       io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
    259       if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
    260         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    261         goto out;
    262       } else if (io_ret != AVB_IO_RESULT_OK) {
    263         avb_errorv(part_name, ": Error determining partition size.\n", NULL);
    264         ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    265         goto out;
    266       }
    267       avb_debugv(part_name, ": Loading entire partition.\n", NULL);
    268     }
    269   }
    270 
    271   ret = load_full_partition(
    272       ops, part_name, image_size, &image_buf, &image_preloaded);
    273   if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
    274     goto out;
    275   }
    276 
    277   if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
    278     AvbSHA256Ctx sha256_ctx;
    279     avb_sha256_init(&sha256_ctx);
    280     avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
    281     avb_sha256_update(&sha256_ctx, image_buf, hash_desc.image_size);
    282     digest = avb_sha256_final(&sha256_ctx);
    283     digest_len = AVB_SHA256_DIGEST_SIZE;
    284   } else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
    285     AvbSHA512Ctx sha512_ctx;
    286     avb_sha512_init(&sha512_ctx);
    287     avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
    288     avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
    289     digest = avb_sha512_final(&sha512_ctx);
    290     digest_len = AVB_SHA512_DIGEST_SIZE;
    291   } else {
    292     avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
    293     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    294     goto out;
    295   }
    296 
    297   if (hash_desc.digest_len == 0) {
    298     // Expect a match to a persistent digest.
    299     avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
    300     expected_digest_len = digest_len;
    301     expected_digest = expected_digest_buf;
    302     avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
    303     ret =
    304         read_persistent_digest(ops, part_name, digest_len, expected_digest_buf);
    305     if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
    306       goto out;
    307     }
    308   } else {
    309     // Expect a match to the digest in the descriptor.
    310     expected_digest_len = hash_desc.digest_len;
    311     expected_digest = desc_digest;
    312   }
    313 
    314   if (digest_len != expected_digest_len) {
    315     avb_errorv(
    316         part_name, ": Digest in descriptor not of expected size.\n", NULL);
    317     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    318     goto out;
    319   }
    320 
    321   if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
    322     avb_errorv(part_name,
    323                ": Hash of data does not match digest in descriptor.\n",
    324                NULL);
    325     ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
    326     goto out;
    327   }
    328 
    329   ret = AVB_SLOT_VERIFY_RESULT_OK;
    330 
    331 out:
    332 
    333   /* If it worked and something was loaded, copy to slot_data. */
    334   if ((ret == AVB_SLOT_VERIFY_RESULT_OK || result_should_continue(ret)) &&
    335       image_buf != NULL) {
    336     AvbPartitionData* loaded_partition;
    337     if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
    338       avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
    339       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    340       goto fail;
    341     }
    342     loaded_partition =
    343         &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
    344     loaded_partition->partition_name = avb_strdup(found);
    345     loaded_partition->data_size = image_size;
    346     loaded_partition->data = image_buf;
    347     loaded_partition->preloaded = image_preloaded;
    348     image_buf = NULL;
    349   }
    350 
    351 fail:
    352   if (image_buf != NULL && !image_preloaded) {
    353     avb_free(image_buf);
    354   }
    355   return ret;
    356 }
    357 
    358 static AvbSlotVerifyResult load_requested_partitions(
    359     AvbOps* ops,
    360     const char* const* requested_partitions,
    361     const char* ab_suffix,
    362     AvbSlotVerifyData* slot_data) {
    363   AvbSlotVerifyResult ret;
    364   uint8_t* image_buf = NULL;
    365   bool image_preloaded = false;
    366   size_t n;
    367 
    368   if (ops->get_size_of_partition == NULL) {
    369     avb_error("get_size_of_partition() not implemented.\n");
    370     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
    371     goto out;
    372   }
    373 
    374   for (n = 0; requested_partitions[n] != NULL; n++) {
    375     char part_name[AVB_PART_NAME_MAX_SIZE];
    376     AvbIOResult io_ret;
    377     uint64_t image_size;
    378     AvbPartitionData* loaded_partition;
    379 
    380     if (!avb_str_concat(part_name,
    381                         sizeof part_name,
    382                         requested_partitions[n],
    383                         avb_strlen(requested_partitions[n]),
    384                         ab_suffix,
    385                         avb_strlen(ab_suffix))) {
    386       avb_error("Partition name and suffix does not fit.\n");
    387       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    388       goto out;
    389     }
    390 
    391     io_ret = ops->get_size_of_partition(ops, part_name, &image_size);
    392     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
    393       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    394       goto out;
    395     } else if (io_ret != AVB_IO_RESULT_OK) {
    396       avb_errorv(part_name, ": Error determining partition size.\n", NULL);
    397       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    398       goto out;
    399     }
    400     avb_debugv(part_name, ": Loading entire partition.\n", NULL);
    401 
    402     ret = load_full_partition(
    403         ops, part_name, image_size, &image_buf, &image_preloaded);
    404     if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
    405       goto out;
    406     }
    407 
    408     /* Move to slot_data. */
    409     if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
    410       avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
    411       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    412       goto out;
    413     }
    414     loaded_partition =
    415         &slot_data->loaded_partitions[slot_data->num_loaded_partitions++];
    416     loaded_partition->partition_name = avb_strdup(requested_partitions[n]);
    417     if (loaded_partition->partition_name == NULL) {
    418       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    419       goto out;
    420     }
    421     loaded_partition->data_size = image_size;
    422     loaded_partition->data = image_buf; /* Transferring the owner. */
    423     loaded_partition->preloaded = image_preloaded;
    424     image_buf = NULL;
    425     image_preloaded = false;
    426   }
    427 
    428   ret = AVB_SLOT_VERIFY_RESULT_OK;
    429 
    430 out:
    431   /* Free the current buffer if any. */
    432   if (image_buf != NULL && !image_preloaded) {
    433     avb_free(image_buf);
    434   }
    435   /* Buffers that are already saved in slot_data will be handled by the caller
    436    * even on failure. */
    437   return ret;
    438 }
    439 
    440 static AvbSlotVerifyResult load_and_verify_vbmeta(
    441     AvbOps* ops,
    442     const char* const* requested_partitions,
    443     const char* ab_suffix,
    444     bool allow_verification_error,
    445     AvbVBMetaImageFlags toplevel_vbmeta_flags,
    446     int rollback_index_location,
    447     const char* partition_name,
    448     size_t partition_name_len,
    449     const uint8_t* expected_public_key,
    450     size_t expected_public_key_length,
    451     AvbSlotVerifyData* slot_data,
    452     AvbAlgorithmType* out_algorithm_type,
    453     AvbCmdlineSubstList* out_additional_cmdline_subst) {
    454   char full_partition_name[AVB_PART_NAME_MAX_SIZE];
    455   AvbSlotVerifyResult ret;
    456   AvbIOResult io_ret;
    457   size_t vbmeta_offset;
    458   size_t vbmeta_size;
    459   uint8_t* vbmeta_buf = NULL;
    460   size_t vbmeta_num_read;
    461   AvbVBMetaVerifyResult vbmeta_ret;
    462   const uint8_t* pk_data;
    463   size_t pk_len;
    464   AvbVBMetaImageHeader vbmeta_header;
    465   uint64_t stored_rollback_index;
    466   const AvbDescriptor** descriptors = NULL;
    467   size_t num_descriptors;
    468   size_t n;
    469   bool is_main_vbmeta;
    470   bool is_vbmeta_partition;
    471   AvbVBMetaData* vbmeta_image_data = NULL;
    472 
    473   ret = AVB_SLOT_VERIFY_RESULT_OK;
    474 
    475   avb_assert(slot_data != NULL);
    476 
    477   /* Since we allow top-level vbmeta in 'boot', use
    478    * rollback_index_location to determine whether we're the main
    479    * vbmeta struct.
    480    */
    481   is_main_vbmeta = (rollback_index_location == 0);
    482   is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
    483 
    484   if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
    485     avb_error("Partition name is not valid UTF-8.\n");
    486     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    487     goto out;
    488   }
    489 
    490   /* Construct full partition name. */
    491   if (!avb_str_concat(full_partition_name,
    492                       sizeof full_partition_name,
    493                       partition_name,
    494                       partition_name_len,
    495                       ab_suffix,
    496                       avb_strlen(ab_suffix))) {
    497     avb_error("Partition name and suffix does not fit.\n");
    498     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    499     goto out;
    500   }
    501 
    502   avb_debugv("Loading vbmeta struct from partition '",
    503              full_partition_name,
    504              "'.\n",
    505              NULL);
    506 
    507   /* If we're loading from the main vbmeta partition, the vbmeta
    508    * struct is in the beginning. Otherwise we have to locate it via a
    509    * footer.
    510    */
    511   if (is_vbmeta_partition) {
    512     vbmeta_offset = 0;
    513     vbmeta_size = VBMETA_MAX_SIZE;
    514   } else {
    515     uint8_t footer_buf[AVB_FOOTER_SIZE];
    516     size_t footer_num_read;
    517     AvbFooter footer;
    518 
    519     io_ret = ops->read_from_partition(ops,
    520                                       full_partition_name,
    521                                       -AVB_FOOTER_SIZE,
    522                                       AVB_FOOTER_SIZE,
    523                                       footer_buf,
    524                                       &footer_num_read);
    525     if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
    526       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    527       goto out;
    528     } else if (io_ret != AVB_IO_RESULT_OK) {
    529       avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
    530       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    531       goto out;
    532     }
    533     avb_assert(footer_num_read == AVB_FOOTER_SIZE);
    534 
    535     if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
    536                                           &footer)) {
    537       avb_errorv(full_partition_name, ": Error validating footer.\n", NULL);
    538       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    539       goto out;
    540     }
    541 
    542     /* Basic footer sanity check since the data is untrusted. */
    543     if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
    544       avb_errorv(
    545           full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
    546       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    547       goto out;
    548     }
    549 
    550     vbmeta_offset = footer.vbmeta_offset;
    551     vbmeta_size = footer.vbmeta_size;
    552   }
    553 
    554   vbmeta_buf = avb_malloc(vbmeta_size);
    555   if (vbmeta_buf == NULL) {
    556     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    557     goto out;
    558   }
    559 
    560   io_ret = ops->read_from_partition(ops,
    561                                     full_partition_name,
    562                                     vbmeta_offset,
    563                                     vbmeta_size,
    564                                     vbmeta_buf,
    565                                     &vbmeta_num_read);
    566   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
    567     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    568     goto out;
    569   } else if (io_ret != AVB_IO_RESULT_OK) {
    570     /* If we're looking for 'vbmeta' but there is no such partition,
    571      * go try to get it from the boot partition instead.
    572      */
    573     if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
    574         is_vbmeta_partition) {
    575       avb_debugv(full_partition_name,
    576                  ": No such partition. Trying 'boot' instead.\n",
    577                  NULL);
    578       ret = load_and_verify_vbmeta(ops,
    579                                    requested_partitions,
    580                                    ab_suffix,
    581                                    allow_verification_error,
    582                                    0 /* toplevel_vbmeta_flags */,
    583                                    0 /* rollback_index_location */,
    584                                    "boot",
    585                                    avb_strlen("boot"),
    586                                    NULL /* expected_public_key */,
    587                                    0 /* expected_public_key_length */,
    588                                    slot_data,
    589                                    out_algorithm_type,
    590                                    out_additional_cmdline_subst);
    591       goto out;
    592     } else {
    593       avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
    594       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    595       goto out;
    596     }
    597   }
    598   avb_assert(vbmeta_num_read <= vbmeta_size);
    599 
    600   /* Check if the image is properly signed and get the public key used
    601    * to sign the image.
    602    */
    603   vbmeta_ret =
    604       avb_vbmeta_image_verify(vbmeta_buf, vbmeta_num_read, &pk_data, &pk_len);
    605   switch (vbmeta_ret) {
    606     case AVB_VBMETA_VERIFY_RESULT_OK:
    607       avb_assert(pk_data != NULL && pk_len > 0);
    608       break;
    609 
    610     case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
    611     case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
    612     case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
    613       ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
    614       avb_errorv(full_partition_name,
    615                  ": Error verifying vbmeta image: ",
    616                  avb_vbmeta_verify_result_to_string(vbmeta_ret),
    617                  "\n",
    618                  NULL);
    619       if (!allow_verification_error) {
    620         goto out;
    621       }
    622       break;
    623 
    624     case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
    625       /* No way to continue this case. */
    626       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    627       avb_errorv(full_partition_name,
    628                  ": Error verifying vbmeta image: invalid vbmeta header\n",
    629                  NULL);
    630       goto out;
    631 
    632     case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
    633       /* No way to continue this case. */
    634       ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
    635       avb_errorv(full_partition_name,
    636                  ": Error verifying vbmeta image: unsupported AVB version\n",
    637                  NULL);
    638       goto out;
    639   }
    640 
    641   /* Byteswap the header. */
    642   avb_vbmeta_image_header_to_host_byte_order((AvbVBMetaImageHeader*)vbmeta_buf,
    643                                              &vbmeta_header);
    644 
    645   /* If we're the toplevel, assign flags so they'll be passed down. */
    646   if (is_main_vbmeta) {
    647     toplevel_vbmeta_flags = (AvbVBMetaImageFlags)vbmeta_header.flags;
    648   } else {
    649     if (vbmeta_header.flags != 0) {
    650       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    651       avb_errorv(full_partition_name,
    652                  ": chained vbmeta image has non-zero flags\n",
    653                  NULL);
    654       goto out;
    655     }
    656   }
    657 
    658   /* Check if key used to make signature matches what is expected. */
    659   if (pk_data != NULL) {
    660     if (expected_public_key != NULL) {
    661       avb_assert(!is_main_vbmeta);
    662       if (expected_public_key_length != pk_len ||
    663           avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
    664         avb_errorv(full_partition_name,
    665                    ": Public key used to sign data does not match key in chain "
    666                    "partition descriptor.\n",
    667                    NULL);
    668         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
    669         if (!allow_verification_error) {
    670           goto out;
    671         }
    672       }
    673     } else {
    674       bool key_is_trusted = false;
    675       const uint8_t* pk_metadata = NULL;
    676       size_t pk_metadata_len = 0;
    677 
    678       if (vbmeta_header.public_key_metadata_size > 0) {
    679         pk_metadata = vbmeta_buf + sizeof(AvbVBMetaImageHeader) +
    680                       vbmeta_header.authentication_data_block_size +
    681                       vbmeta_header.public_key_metadata_offset;
    682         pk_metadata_len = vbmeta_header.public_key_metadata_size;
    683       }
    684 
    685       avb_assert(is_main_vbmeta);
    686       io_ret = ops->validate_vbmeta_public_key(
    687           ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
    688       if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
    689         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    690         goto out;
    691       } else if (io_ret != AVB_IO_RESULT_OK) {
    692         avb_errorv(full_partition_name,
    693                    ": Error while checking public key used to sign data.\n",
    694                    NULL);
    695         ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    696         goto out;
    697       }
    698       if (!key_is_trusted) {
    699         avb_errorv(full_partition_name,
    700                    ": Public key used to sign data rejected.\n",
    701                    NULL);
    702         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
    703         if (!allow_verification_error) {
    704           goto out;
    705         }
    706       }
    707     }
    708   }
    709 
    710   /* Check rollback index. */
    711   io_ret = ops->read_rollback_index(
    712       ops, rollback_index_location, &stored_rollback_index);
    713   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
    714     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    715     goto out;
    716   } else if (io_ret != AVB_IO_RESULT_OK) {
    717     avb_errorv(full_partition_name,
    718                ": Error getting rollback index for location.\n",
    719                NULL);
    720     ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
    721     goto out;
    722   }
    723   if (vbmeta_header.rollback_index < stored_rollback_index) {
    724     avb_errorv(
    725         full_partition_name,
    726         ": Image rollback index is less than the stored rollback index.\n",
    727         NULL);
    728     ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
    729     if (!allow_verification_error) {
    730       goto out;
    731     }
    732   }
    733 
    734   /* Copy vbmeta to vbmeta_images before recursing. */
    735   if (is_main_vbmeta) {
    736     avb_assert(slot_data->num_vbmeta_images == 0);
    737   } else {
    738     avb_assert(slot_data->num_vbmeta_images > 0);
    739   }
    740   if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
    741     avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
    742     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    743     goto out;
    744   }
    745   vbmeta_image_data = &slot_data->vbmeta_images[slot_data->num_vbmeta_images++];
    746   vbmeta_image_data->partition_name = avb_strdup(partition_name);
    747   vbmeta_image_data->vbmeta_data = vbmeta_buf;
    748   /* Note that |vbmeta_buf| is actually |vbmeta_num_read| bytes long
    749    * and this includes data past the end of the image. Pass the
    750    * actual size of the vbmeta image. Also, no need to use
    751    * avb_safe_add() since the header has already been verified.
    752    */
    753   vbmeta_image_data->vbmeta_size =
    754       sizeof(AvbVBMetaImageHeader) +
    755       vbmeta_header.authentication_data_block_size +
    756       vbmeta_header.auxiliary_data_block_size;
    757   vbmeta_image_data->verify_result = vbmeta_ret;
    758 
    759   /* If verification has been disabled by setting a bit in the image,
    760    * we're done... except that we need to load the entirety of the
    761    * requested partitions.
    762    */
    763   if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
    764     AvbSlotVerifyResult sub_ret;
    765     avb_debugv(
    766         full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
    767     /* If load_requested_partitions() fail it is always a fatal
    768      * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
    769      * than recoverable (e.g. one where result_should_continue()
    770      * returns true) and we want to convey that error.
    771      */
    772     sub_ret = load_requested_partitions(
    773         ops, requested_partitions, ab_suffix, slot_data);
    774     if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
    775       ret = sub_ret;
    776     }
    777     goto out;
    778   }
    779 
    780   /* Now go through all descriptors and take the appropriate action:
    781    *
    782    * - hash descriptor: Load data from partition, calculate hash, and
    783    *   checks that it matches what's in the hash descriptor.
    784    *
    785    * - hashtree descriptor: Do nothing since verification happens
    786    *   on-the-fly from within the OS. (Unless the descriptor uses a
    787    *   persistent digest, in which case we need to find it).
    788    *
    789    * - chained partition descriptor: Load the footer, load the vbmeta
    790    *   image, verify vbmeta image (includes rollback checks, hash
    791    *   checks, bail on chained partitions).
    792    */
    793   descriptors =
    794       avb_descriptor_get_all(vbmeta_buf, vbmeta_num_read, &num_descriptors);
    795   for (n = 0; n < num_descriptors; n++) {
    796     AvbDescriptor desc;
    797 
    798     if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
    799       avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
    800       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    801       goto out;
    802     }
    803 
    804     switch (desc.tag) {
    805       case AVB_DESCRIPTOR_TAG_HASH: {
    806         AvbSlotVerifyResult sub_ret;
    807         sub_ret = load_and_verify_hash_partition(ops,
    808                                                  requested_partitions,
    809                                                  ab_suffix,
    810                                                  allow_verification_error,
    811                                                  descriptors[n],
    812                                                  slot_data);
    813         if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
    814           ret = sub_ret;
    815           if (!allow_verification_error || !result_should_continue(ret)) {
    816             goto out;
    817           }
    818         }
    819       } break;
    820 
    821       case AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: {
    822         AvbSlotVerifyResult sub_ret;
    823         AvbChainPartitionDescriptor chain_desc;
    824         const uint8_t* chain_partition_name;
    825         const uint8_t* chain_public_key;
    826 
    827         /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
    828         if (!is_main_vbmeta) {
    829           avb_errorv(full_partition_name,
    830                      ": Encountered chain descriptor not in main image.\n",
    831                      NULL);
    832           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    833           goto out;
    834         }
    835 
    836         if (!avb_chain_partition_descriptor_validate_and_byteswap(
    837                 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
    838           avb_errorv(full_partition_name,
    839                      ": Chain partition descriptor is invalid.\n",
    840                      NULL);
    841           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    842           goto out;
    843         }
    844 
    845         if (chain_desc.rollback_index_location == 0) {
    846           avb_errorv(full_partition_name,
    847                      ": Chain partition has invalid "
    848                      "rollback_index_location field.\n",
    849                      NULL);
    850           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    851           goto out;
    852         }
    853 
    854         chain_partition_name = ((const uint8_t*)descriptors[n]) +
    855                                sizeof(AvbChainPartitionDescriptor);
    856         chain_public_key = chain_partition_name + chain_desc.partition_name_len;
    857 
    858         sub_ret =
    859             load_and_verify_vbmeta(ops,
    860                                    requested_partitions,
    861                                    ab_suffix,
    862                                    allow_verification_error,
    863                                    toplevel_vbmeta_flags,
    864                                    chain_desc.rollback_index_location,
    865                                    (const char*)chain_partition_name,
    866                                    chain_desc.partition_name_len,
    867                                    chain_public_key,
    868                                    chain_desc.public_key_len,
    869                                    slot_data,
    870                                    NULL, /* out_algorithm_type */
    871                                    NULL /* out_additional_cmdline_subst */);
    872         if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
    873           ret = sub_ret;
    874           if (!result_should_continue(ret)) {
    875             goto out;
    876           }
    877         }
    878       } break;
    879 
    880       case AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: {
    881         const uint8_t* kernel_cmdline;
    882         AvbKernelCmdlineDescriptor kernel_cmdline_desc;
    883         bool apply_cmdline;
    884 
    885         if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
    886                 (AvbKernelCmdlineDescriptor*)descriptors[n],
    887                 &kernel_cmdline_desc)) {
    888           avb_errorv(full_partition_name,
    889                      ": Kernel cmdline descriptor is invalid.\n",
    890                      NULL);
    891           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    892           goto out;
    893         }
    894 
    895         kernel_cmdline = ((const uint8_t*)descriptors[n]) +
    896                          sizeof(AvbKernelCmdlineDescriptor);
    897 
    898         if (!avb_validate_utf8(kernel_cmdline,
    899                                kernel_cmdline_desc.kernel_cmdline_length)) {
    900           avb_errorv(full_partition_name,
    901                      ": Kernel cmdline is not valid UTF-8.\n",
    902                      NULL);
    903           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    904           goto out;
    905         }
    906 
    907         /* Compare the flags for top-level VBMeta struct with flags in
    908          * the command-line descriptor so command-line snippets only
    909          * intended for a certain mode (dm-verity enabled/disabled)
    910          * are skipped if applicable.
    911          */
    912         apply_cmdline = true;
    913         if (toplevel_vbmeta_flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED) {
    914           if (kernel_cmdline_desc.flags &
    915               AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) {
    916             apply_cmdline = false;
    917           }
    918         } else {
    919           if (kernel_cmdline_desc.flags &
    920               AVB_KERNEL_CMDLINE_FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) {
    921             apply_cmdline = false;
    922           }
    923         }
    924 
    925         if (apply_cmdline) {
    926           if (slot_data->cmdline == NULL) {
    927             slot_data->cmdline =
    928                 avb_calloc(kernel_cmdline_desc.kernel_cmdline_length + 1);
    929             if (slot_data->cmdline == NULL) {
    930               ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    931               goto out;
    932             }
    933             avb_memcpy(slot_data->cmdline,
    934                        kernel_cmdline,
    935                        kernel_cmdline_desc.kernel_cmdline_length);
    936           } else {
    937             /* new cmdline is: <existing_cmdline> + ' ' + <newcmdline> + '\0' */
    938             size_t orig_size = avb_strlen(slot_data->cmdline);
    939             size_t new_size =
    940                 orig_size + 1 + kernel_cmdline_desc.kernel_cmdline_length + 1;
    941             char* new_cmdline = avb_calloc(new_size);
    942             if (new_cmdline == NULL) {
    943               ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
    944               goto out;
    945             }
    946             avb_memcpy(new_cmdline, slot_data->cmdline, orig_size);
    947             new_cmdline[orig_size] = ' ';
    948             avb_memcpy(new_cmdline + orig_size + 1,
    949                        kernel_cmdline,
    950                        kernel_cmdline_desc.kernel_cmdline_length);
    951             avb_free(slot_data->cmdline);
    952             slot_data->cmdline = new_cmdline;
    953           }
    954         }
    955       } break;
    956 
    957       case AVB_DESCRIPTOR_TAG_HASHTREE: {
    958         AvbHashtreeDescriptor hashtree_desc;
    959 
    960         if (!avb_hashtree_descriptor_validate_and_byteswap(
    961                 (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
    962           avb_errorv(
    963               full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
    964           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    965           goto out;
    966         }
    967 
    968         /* We only need to continue when there is no digest in the descriptor.
    969          * This is because the only processing here is to find the digest and
    970          * make it available on the kernel command line.
    971          */
    972         if (hashtree_desc.root_digest_len == 0) {
    973           char part_name[AVB_PART_NAME_MAX_SIZE];
    974           size_t digest_len = 0;
    975           uint8_t digest_buf[AVB_SHA512_DIGEST_SIZE];
    976           const uint8_t* desc_partition_name =
    977               ((const uint8_t*)descriptors[n]) + sizeof(AvbHashtreeDescriptor);
    978 
    979           if (!avb_validate_utf8(desc_partition_name,
    980                                  hashtree_desc.partition_name_len)) {
    981             avb_error("Partition name is not valid UTF-8.\n");
    982             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    983             goto out;
    984           }
    985 
    986           /* No ab_suffix for partitions without a digest in the descriptor
    987            * because these partitions hold data unique to this device and are
    988            * not updated using an A/B scheme.
    989            */
    990           if ((hashtree_desc.flags &
    991                AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB) == 0 &&
    992               avb_strlen(ab_suffix) != 0) {
    993             avb_error("Cannot use A/B with a persistent root digest.\n");
    994             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
    995             goto out;
    996           }
    997           if (hashtree_desc.partition_name_len >= AVB_PART_NAME_MAX_SIZE) {
    998             avb_error("Partition name does not fit.\n");
    999             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
   1000             goto out;
   1001           }
   1002           avb_memcpy(
   1003               part_name, desc_partition_name, hashtree_desc.partition_name_len);
   1004           part_name[hashtree_desc.partition_name_len] = '\0';
   1005 
   1006           /* Determine the expected digest size from the hash algorithm. */
   1007           if (avb_strcmp((const char*)hashtree_desc.hash_algorithm, "sha1") ==
   1008               0) {
   1009             digest_len = AVB_SHA1_DIGEST_SIZE;
   1010           } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
   1011                                 "sha256") == 0) {
   1012             digest_len = AVB_SHA256_DIGEST_SIZE;
   1013           } else if (avb_strcmp((const char*)hashtree_desc.hash_algorithm,
   1014                                 "sha512") == 0) {
   1015             digest_len = AVB_SHA512_DIGEST_SIZE;
   1016           } else {
   1017             avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
   1018             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
   1019             goto out;
   1020           }
   1021 
   1022           ret = read_persistent_digest(ops, part_name, digest_len, digest_buf);
   1023           if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
   1024             goto out;
   1025           }
   1026 
   1027           if (out_additional_cmdline_subst) {
   1028             ret =
   1029                 avb_add_root_digest_substitution(part_name,
   1030                                                  digest_buf,
   1031                                                  digest_len,
   1032                                                  out_additional_cmdline_subst);
   1033             if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
   1034               goto out;
   1035             }
   1036           }
   1037         }
   1038       } break;
   1039 
   1040       case AVB_DESCRIPTOR_TAG_PROPERTY:
   1041         /* Do nothing. */
   1042         break;
   1043     }
   1044   }
   1045 
   1046   if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
   1047     avb_errorv(
   1048         full_partition_name, ": Invalid rollback_index_location.\n", NULL);
   1049     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
   1050     goto out;
   1051   }
   1052 
   1053   slot_data->rollback_indexes[rollback_index_location] =
   1054       vbmeta_header.rollback_index;
   1055 
   1056   if (out_algorithm_type != NULL) {
   1057     *out_algorithm_type = (AvbAlgorithmType)vbmeta_header.algorithm_type;
   1058   }
   1059 
   1060 out:
   1061   /* If |vbmeta_image_data| isn't NULL it means that it adopted
   1062    * |vbmeta_buf| so in that case don't free it here.
   1063    */
   1064   if (vbmeta_image_data == NULL) {
   1065     if (vbmeta_buf != NULL) {
   1066       avb_free(vbmeta_buf);
   1067     }
   1068   }
   1069   if (descriptors != NULL) {
   1070     avb_free(descriptors);
   1071   }
   1072   return ret;
   1073 }
   1074 
   1075 AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
   1076                                     const char* const* requested_partitions,
   1077                                     const char* ab_suffix,
   1078                                     AvbSlotVerifyFlags flags,
   1079                                     AvbHashtreeErrorMode hashtree_error_mode,
   1080                                     AvbSlotVerifyData** out_data) {
   1081   AvbSlotVerifyResult ret;
   1082   AvbSlotVerifyData* slot_data = NULL;
   1083   AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
   1084   bool using_boot_for_vbmeta = false;
   1085   AvbVBMetaImageHeader toplevel_vbmeta;
   1086   bool allow_verification_error =
   1087       (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR);
   1088   AvbCmdlineSubstList* additional_cmdline_subst = NULL;
   1089 
   1090   /* Fail early if we're missing the AvbOps needed for slot verification.
   1091    *
   1092    * For now, handle get_size_of_partition() not being implemented. In
   1093    * a later release we may change that.
   1094    */
   1095   avb_assert(ops->read_is_device_unlocked != NULL);
   1096   avb_assert(ops->read_from_partition != NULL);
   1097   avb_assert(ops->validate_vbmeta_public_key != NULL);
   1098   avb_assert(ops->read_rollback_index != NULL);
   1099   avb_assert(ops->get_unique_guid_for_partition != NULL);
   1100 
   1101   if (out_data != NULL) {
   1102     *out_data = NULL;
   1103   }
   1104 
   1105   /* Allowing dm-verity errors defeats the purpose of verified boot so
   1106    * only allow this if set up to allow verification errors
   1107    * (e.g. typically only UNLOCKED mode).
   1108    */
   1109   if (hashtree_error_mode == AVB_HASHTREE_ERROR_MODE_LOGGING &&
   1110       !allow_verification_error) {
   1111     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
   1112     goto fail;
   1113   }
   1114 
   1115   slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
   1116   if (slot_data == NULL) {
   1117     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
   1118     goto fail;
   1119   }
   1120   slot_data->vbmeta_images =
   1121       avb_calloc(sizeof(AvbVBMetaData) * MAX_NUMBER_OF_VBMETA_IMAGES);
   1122   if (slot_data->vbmeta_images == NULL) {
   1123     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
   1124     goto fail;
   1125   }
   1126   slot_data->loaded_partitions =
   1127       avb_calloc(sizeof(AvbPartitionData) * MAX_NUMBER_OF_LOADED_PARTITIONS);
   1128   if (slot_data->loaded_partitions == NULL) {
   1129     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
   1130     goto fail;
   1131   }
   1132 
   1133   additional_cmdline_subst = avb_new_cmdline_subst_list();
   1134   if (additional_cmdline_subst == NULL) {
   1135     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
   1136     goto fail;
   1137   }
   1138 
   1139   ret = load_and_verify_vbmeta(ops,
   1140                                requested_partitions,
   1141                                ab_suffix,
   1142                                allow_verification_error,
   1143                                0 /* toplevel_vbmeta_flags */,
   1144                                0 /* rollback_index_location */,
   1145                                "vbmeta",
   1146                                avb_strlen("vbmeta"),
   1147                                NULL /* expected_public_key */,
   1148                                0 /* expected_public_key_length */,
   1149                                slot_data,
   1150                                &algorithm_type,
   1151                                additional_cmdline_subst);
   1152   if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
   1153     goto fail;
   1154   }
   1155 
   1156   /* If things check out, mangle the kernel command-line as needed. */
   1157   if (result_should_continue(ret)) {
   1158     if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
   1159       avb_assert(
   1160           avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
   1161       using_boot_for_vbmeta = true;
   1162     }
   1163 
   1164     /* Byteswap top-level vbmeta header since we'll need it below. */
   1165     avb_vbmeta_image_header_to_host_byte_order(
   1166         (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
   1167         &toplevel_vbmeta);
   1168 
   1169     /* Fill in |ab_suffix| field. */
   1170     slot_data->ab_suffix = avb_strdup(ab_suffix);
   1171     if (slot_data->ab_suffix == NULL) {
   1172       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
   1173       goto fail;
   1174     }
   1175 
   1176     /* If verification is disabled, we are done ... we specifically
   1177      * don't want to add any androidboot.* options since verification
   1178      * is disabled.
   1179      */
   1180     if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
   1181       /* Since verification is disabled we didn't process any
   1182        * descriptors and thus there's no cmdline... so set root= such
   1183        * that the system partition is mounted.
   1184        */
   1185       avb_assert(slot_data->cmdline == NULL);
   1186       slot_data->cmdline =
   1187           avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
   1188       if (slot_data->cmdline == NULL) {
   1189         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
   1190         goto fail;
   1191       }
   1192     } else {
   1193       /* Add options - any failure in avb_append_options() is either an
   1194        * I/O or OOM error.
   1195        */
   1196       AvbSlotVerifyResult sub_ret = avb_append_options(ops,
   1197                                                        slot_data,
   1198                                                        &toplevel_vbmeta,
   1199                                                        algorithm_type,
   1200                                                        hashtree_error_mode);
   1201       if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
   1202         ret = sub_ret;
   1203         goto fail;
   1204       }
   1205     }
   1206 
   1207     /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
   1208     if (slot_data->cmdline != NULL) {
   1209       char* new_cmdline;
   1210       new_cmdline = avb_sub_cmdline(ops,
   1211                                     slot_data->cmdline,
   1212                                     ab_suffix,
   1213                                     using_boot_for_vbmeta,
   1214                                     additional_cmdline_subst);
   1215       if (new_cmdline != slot_data->cmdline) {
   1216         if (new_cmdline == NULL) {
   1217           ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
   1218           goto fail;
   1219         }
   1220         avb_free(slot_data->cmdline);
   1221         slot_data->cmdline = new_cmdline;
   1222       }
   1223     }
   1224 
   1225     if (out_data != NULL) {
   1226       *out_data = slot_data;
   1227     } else {
   1228       avb_slot_verify_data_free(slot_data);
   1229     }
   1230   }
   1231 
   1232   avb_free_cmdline_subst_list(additional_cmdline_subst);
   1233   additional_cmdline_subst = NULL;
   1234 
   1235   if (!allow_verification_error) {
   1236     avb_assert(ret == AVB_SLOT_VERIFY_RESULT_OK);
   1237   }
   1238 
   1239   return ret;
   1240 
   1241 fail:
   1242   if (slot_data != NULL) {
   1243     avb_slot_verify_data_free(slot_data);
   1244   }
   1245   if (additional_cmdline_subst != NULL) {
   1246     avb_free_cmdline_subst_list(additional_cmdline_subst);
   1247   }
   1248   return ret;
   1249 }
   1250 
   1251 void avb_slot_verify_data_free(AvbSlotVerifyData* data) {
   1252   if (data->ab_suffix != NULL) {
   1253     avb_free(data->ab_suffix);
   1254   }
   1255   if (data->cmdline != NULL) {
   1256     avb_free(data->cmdline);
   1257   }
   1258   if (data->vbmeta_images != NULL) {
   1259     size_t n;
   1260     for (n = 0; n < data->num_vbmeta_images; n++) {
   1261       AvbVBMetaData* vbmeta_image = &data->vbmeta_images[n];
   1262       if (vbmeta_image->partition_name != NULL) {
   1263         avb_free(vbmeta_image->partition_name);
   1264       }
   1265       if (vbmeta_image->vbmeta_data != NULL) {
   1266         avb_free(vbmeta_image->vbmeta_data);
   1267       }
   1268     }
   1269     avb_free(data->vbmeta_images);
   1270   }
   1271   if (data->loaded_partitions != NULL) {
   1272     size_t n;
   1273     for (n = 0; n < data->num_loaded_partitions; n++) {
   1274       AvbPartitionData* loaded_partition = &data->loaded_partitions[n];
   1275       if (loaded_partition->partition_name != NULL) {
   1276         avb_free(loaded_partition->partition_name);
   1277       }
   1278       if (loaded_partition->data != NULL && !loaded_partition->preloaded) {
   1279         avb_free(loaded_partition->data);
   1280       }
   1281     }
   1282     avb_free(data->loaded_partitions);
   1283   }
   1284   avb_free(data);
   1285 }
   1286 
   1287 const char* avb_slot_verify_result_to_string(AvbSlotVerifyResult result) {
   1288   const char* ret = NULL;
   1289 
   1290   switch (result) {
   1291     case AVB_SLOT_VERIFY_RESULT_OK:
   1292       ret = "OK";
   1293       break;
   1294     case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
   1295       ret = "ERROR_OOM";
   1296       break;
   1297     case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
   1298       ret = "ERROR_IO";
   1299       break;
   1300     case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
   1301       ret = "ERROR_VERIFICATION";
   1302       break;
   1303     case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
   1304       ret = "ERROR_ROLLBACK_INDEX";
   1305       break;
   1306     case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
   1307       ret = "ERROR_PUBLIC_KEY_REJECTED";
   1308       break;
   1309     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
   1310       ret = "ERROR_INVALID_METADATA";
   1311       break;
   1312     case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
   1313       ret = "ERROR_UNSUPPORTED_VERSION";
   1314       break;
   1315     case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT:
   1316       ret = "ERROR_INVALID_ARGUMENT";
   1317       break;
   1318       /* Do not add a 'default:' case here because of -Wswitch. */
   1319   }
   1320 
   1321   if (ret == NULL) {
   1322     avb_error("Unknown AvbSlotVerifyResult value.\n");
   1323     ret = "(unknown)";
   1324   }
   1325 
   1326   return ret;
   1327 }
   1328 
   1329 void avb_slot_verify_data_calculate_vbmeta_digest(AvbSlotVerifyData* data,
   1330                                                   AvbDigestType digest_type,
   1331                                                   uint8_t* out_digest) {
   1332   bool ret = false;
   1333   size_t n;
   1334 
   1335   switch (digest_type) {
   1336     case AVB_DIGEST_TYPE_SHA256: {
   1337       AvbSHA256Ctx ctx;
   1338       avb_sha256_init(&ctx);
   1339       for (n = 0; n < data->num_vbmeta_images; n++) {
   1340         avb_sha256_update(&ctx,
   1341                           data->vbmeta_images[n].vbmeta_data,
   1342                           data->vbmeta_images[n].vbmeta_size);
   1343       }
   1344       avb_memcpy(out_digest, avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE);
   1345       ret = true;
   1346     } break;
   1347 
   1348     case AVB_DIGEST_TYPE_SHA512: {
   1349       AvbSHA512Ctx ctx;
   1350       avb_sha512_init(&ctx);
   1351       for (n = 0; n < data->num_vbmeta_images; n++) {
   1352         avb_sha512_update(&ctx,
   1353                           data->vbmeta_images[n].vbmeta_data,
   1354                           data->vbmeta_images[n].vbmeta_size);
   1355       }
   1356       avb_memcpy(out_digest, avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE);
   1357       ret = true;
   1358     } break;
   1359 
   1360       /* Do not add a 'default:' case here because of -Wswitch. */
   1361   }
   1362 
   1363   if (!ret) {
   1364     avb_fatal("Unknown digest type");
   1365   }
   1366 }
   1367