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