/*
 * Copyright (C) 2016 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_property_descriptor.h"
#include "avb_util.h"

bool avb_property_descriptor_validate_and_byteswap(
    const AvbPropertyDescriptor* src, AvbPropertyDescriptor* dest) {
  uint64_t expected_size;

  avb_memcpy(dest, src, sizeof(AvbPropertyDescriptor));

  if (!avb_descriptor_validate_and_byteswap((const AvbDescriptor*)src,
                                            (AvbDescriptor*)dest))
    return false;

  if (dest->parent_descriptor.tag != AVB_DESCRIPTOR_TAG_PROPERTY) {
    avb_error("Invalid tag for property descriptor.\n");
    return false;
  }

  dest->key_num_bytes = avb_be64toh(dest->key_num_bytes);
  dest->value_num_bytes = avb_be64toh(dest->value_num_bytes);

  /* Check that key and value are fully contained. */
  expected_size = sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor) + 2;
  if (!avb_safe_add_to(&expected_size, dest->key_num_bytes) ||
      !avb_safe_add_to(&expected_size, dest->value_num_bytes)) {
    avb_error("Overflow while adding up sizes.\n");
    return false;
  }
  if (expected_size > dest->parent_descriptor.num_bytes_following) {
    avb_error("Descriptor payload size overflow.\n");
    return false;
  }

  return true;
}

typedef struct {
  const char* key;
  size_t key_size;
  const char* ret_value;
  size_t ret_value_size;
} PropertyIteratorData;

static bool property_lookup_desc_foreach(const AvbDescriptor* header,
                                         void* user_data) {
  PropertyIteratorData* data = (PropertyIteratorData*)user_data;
  AvbPropertyDescriptor prop_desc;
  const uint8_t* p;
  bool ret = true;

  if (header->tag != AVB_DESCRIPTOR_TAG_PROPERTY) goto out;

  if (!avb_property_descriptor_validate_and_byteswap(
          (const AvbPropertyDescriptor*)header, &prop_desc))
    goto out;

  p = (const uint8_t*)header;
  if (p[sizeof(AvbPropertyDescriptor) + prop_desc.key_num_bytes] != 0) {
    avb_error("No terminating NUL byte in key.\n");
    goto out;
  }

  if (data->key_size == prop_desc.key_num_bytes) {
    if (avb_memcmp(p + sizeof(AvbPropertyDescriptor), data->key,
                   data->key_size) == 0) {
      data->ret_value = (const char*)(p + sizeof(AvbPropertyDescriptor) +
                                      prop_desc.key_num_bytes + 1);
      data->ret_value_size = prop_desc.value_num_bytes;
      /* Stop iterating. */
      ret = false;
      goto out;
    }
  }

out:
  return ret;
}

const char* avb_property_lookup(const uint8_t* image_data, size_t image_size,
                                const char* key, size_t key_size,
                                size_t* out_value_size) {
  PropertyIteratorData data;

  if (key_size == 0) key_size = avb_strlen(key);

  data.key = key;
  data.key_size = key_size;

  if (avb_descriptor_foreach(image_data, image_size,
                             property_lookup_desc_foreach, &data) == 0) {
    if (out_value_size != NULL) *out_value_size = data.ret_value_size;
    return data.ret_value;
  }

  if (out_value_size != NULL) *out_value_size = 0;
  return NULL;
}

bool avb_property_lookup_uint64(const uint8_t* image_data, size_t image_size,
                                const char* key, size_t key_size,
                                uint64_t* out_value) {
  const char* value;
  bool ret = false;
  uint64_t parsed_val;
  int base;
  int n;

  value = avb_property_lookup(image_data, image_size, key, key_size, NULL);
  if (value == NULL) goto out;

  base = 10;
  if (avb_memcmp(value, "0x", 2) == 0) {
    base = 16;
    value += 2;
  }

  parsed_val = 0;
  for (n = 0; value[n] != '\0'; n++) {
    int c = value[n];
    int digit;

    parsed_val *= base;

    if (c >= '0' && c <= '9') {
      digit = c - '0';
    } else if (base == 16 && c >= 'a' && c <= 'f') {
      digit = c - 'a' + 10;
    } else if (base == 16 && c >= 'A' && c <= 'F') {
      digit = c - 'A' + 10;
    } else {
      avb_error("Invalid digit.\n");
      goto out;
    }

    parsed_val += digit;
  }

  ret = true;
  if (out_value != NULL) *out_value = parsed_val;

out:
  return ret;
}
