/*
 * 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_verification.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_verification_get(AvbOps* ops,
                               const char* ab_suffix,
                               bool* out_verification_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 VERIFICATION_DISABLED bit, as requested. */
  header = (AvbVBMetaImageHeader*)vbmeta_image;
  flags = avb_be32toh(header->flags);

  if (out_verification_enabled != NULL) {
    *out_verification_enabled =
        !(flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
  }

  ret = true;

out:
  return ret;
}

bool avb_user_verification_set(AvbOps* ops,
                               const char* ab_suffix,
                               bool enable_verification) {
  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 VERIFICATION_DISABLED bit, as requested. */
  header = (AvbVBMetaImageHeader*)vbmeta_image;
  flags = avb_be32toh(header->flags);
  flags &= ~AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
  if (!enable_verification) {
    flags |= AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_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;
}
