/*
 * 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|.
 */
static 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;
}
