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