/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "avb_user_verity.h"

/* Maximum allow length (in bytes) of a partition name, including
 * ab_suffix.
 */
#define AVB_PART_NAME_MAX_SIZE 32

/* Loads the toplevel AvbVBMetaImageHeader from the slot denoted by
 * |ab_suffix| into |vbmeta_image|. No validation, verification, or
 * byteswapping is performed.
 *
 * If successful, |true| is returned and the partition it was loaded
 * from is returned in |out_partition_name| and the offset on said
 * partition is returned in |out_vbmeta_offset|.
 */
bool load_top_level_vbmeta_header(
    AvbOps* ops,
    const char* ab_suffix,
    uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE],
    char out_partition_name[AVB_PART_NAME_MAX_SIZE],
    uint64_t* out_vbmeta_offset) {
  uint64_t vbmeta_offset = 0;
  size_t num_read;
  bool ret = false;
  AvbIOResult io_res;

  /* Construct full partition name. */
  if (!avb_str_concat(out_partition_name,
                      AVB_PART_NAME_MAX_SIZE,
                      "vbmeta",
                      6,
                      ab_suffix,
                      avb_strlen(ab_suffix))) {
    avb_error("Partition name and suffix does not fit.\n");
    goto out;
  }

  /* Only read the header, not the entire struct. */
  io_res = ops->read_from_partition(ops,
                                    out_partition_name,
                                    vbmeta_offset,
                                    AVB_VBMETA_IMAGE_HEADER_SIZE,
                                    vbmeta_image,
                                    &num_read);
  if (io_res == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
    AvbFooter footer;

    /* Try looking for the vbmeta struct in 'boot' via the footer. */
    if (!avb_str_concat(out_partition_name,
                        AVB_PART_NAME_MAX_SIZE,
                        "boot",
                        4,
                        ab_suffix,
                        avb_strlen(ab_suffix))) {
      avb_error("Partition name and suffix does not fit.\n");
      goto out;
    }
    io_res = ops->read_from_partition(ops,
                                      out_partition_name,
                                      -AVB_FOOTER_SIZE,
                                      AVB_FOOTER_SIZE,
                                      &footer,
                                      &num_read);
    if (io_res != AVB_IO_RESULT_OK) {
      avb_errorv("Error loading footer from partition '",
                 out_partition_name,
                 "'\n",
                 NULL);
      goto out;
    }

    if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
      avb_errorv("Data from '",
                 out_partition_name,
                 "' does not look like a vbmeta footer.\n",
                 NULL);
      goto out;
    }

    vbmeta_offset = avb_be64toh(footer.vbmeta_offset);
    io_res = ops->read_from_partition(ops,
                                      out_partition_name,
                                      vbmeta_offset,
                                      AVB_VBMETA_IMAGE_HEADER_SIZE,
                                      vbmeta_image,
                                      &num_read);
  }

  if (io_res != AVB_IO_RESULT_OK) {
    avb_errorv(
        "Error loading from partition '", out_partition_name, "'\n", NULL);
    goto out;
  }

  if (out_vbmeta_offset != NULL) {
    *out_vbmeta_offset = vbmeta_offset;
  }

  ret = true;

out:
  return ret;
}

bool avb_user_verity_get(AvbOps* ops,
                         const char* ab_suffix,
                         bool* out_verity_enabled) {
  uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
  char partition_name[AVB_PART_NAME_MAX_SIZE];        /* 32 bytes. */
  AvbVBMetaImageHeader* header;
  uint32_t flags;
  bool ret = false;

  if (!load_top_level_vbmeta_header(
          ops, ab_suffix, vbmeta_image, partition_name, NULL)) {
    goto out;
  }

  if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
    avb_errorv("Data from '",
               partition_name,
               "' does not look like a vbmeta header.\n",
               NULL);
    goto out;
  }

  /* Set/clear the HASHTREE_DISABLED bit, as requested. */
  header = (AvbVBMetaImageHeader*)vbmeta_image;
  flags = avb_be32toh(header->flags);

  if (out_verity_enabled != NULL) {
    *out_verity_enabled = !(flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
  }

  ret = true;

out:
  return ret;
}

bool avb_user_verity_set(AvbOps* ops,
                         const char* ab_suffix,
                         bool enable_verity) {
  uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
  char partition_name[AVB_PART_NAME_MAX_SIZE];        /* 32 bytes. */
  uint64_t vbmeta_offset;
  AvbIOResult io_res;
  AvbVBMetaImageHeader* header;
  uint32_t flags;
  bool ret = false;

  if (!load_top_level_vbmeta_header(
          ops, ab_suffix, vbmeta_image, partition_name, &vbmeta_offset)) {
    goto out;
  }

  if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
    avb_errorv("Data from '",
               partition_name,
               "' does not look like a vbmeta header.\n",
               NULL);
    goto out;
  }

  /* Set/clear the HASHTREE_DISABLED bit, as requested. */
  header = (AvbVBMetaImageHeader*)vbmeta_image;
  flags = avb_be32toh(header->flags);
  flags &= ~AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED;
  if (!enable_verity) {
    flags |= AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED;
  }
  header->flags = avb_htobe32(flags);

  /* Write the header. */
  io_res = ops->write_to_partition(ops,
                                   partition_name,
                                   vbmeta_offset,
                                   AVB_VBMETA_IMAGE_HEADER_SIZE,
                                   vbmeta_image);
  if (io_res != AVB_IO_RESULT_OK) {
    avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
    goto out;
  }

  ret = true;

out:
  return ret;
}
