// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/dif/dif_hmac.h"

#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/memory.h"
#include "sw/device/lib/base/mmio.h"

#include "hmac_regs.h"  // Generated.

/**
 * Read the status register from `hmac`.
 *
 * @param hmac The HMAC device to read the status register from.
 * @return The contents of hmac.STATUS.
 */
static uint32_t get_status(const dif_hmac_t *hmac) {
  return mmio_region_read32(hmac->base_addr, HMAC_STATUS_REG_OFFSET);
}

/**
 * Returns the number of entries in the FIFO of `hmac`. If the FIFO is empty,
 * this function will return 0, and if the FIFO is full, this funciton will
 * return `HMAC_FIFO_MAX`.
 *
 * @param hmac The HMAC device to check the FIFO size of.
 * @return The number of entries in the HMAC FIFO.
 */
static uint32_t get_fifo_entry_count(const dif_hmac_t *hmac) {
  return bitfield_field32_read(get_status(hmac), HMAC_STATUS_FIFO_DEPTH_FIELD);
}

/**
 * A helper function for calculating `HMAC_FIFO_MAX` - `get_fifo_entry_count()`.
 */
static uint32_t get_fifo_available_space(const dif_hmac_t *hmac) {
  return HMAC_MSG_FIFO_SIZE_WORDS - get_fifo_entry_count(hmac);
}

/**
 * Convert from a `dif_hmac_interrupt_t` to the appropriate bit index.
 * INTR_STATE, INTR_ENABLE, and INTR_TEST registers have the same bit offset.
 */
static bool irq_bit_offset_get(dif_hmac_interrupt_t irq_type,
                               uint8_t *offset_out) {
  ptrdiff_t offset;
  switch (irq_type) {
    case kDifHmacInterruptHmacDone:
      offset = HMAC_INTR_COMMON_HMAC_DONE_BIT;
      break;
    case kDifHmacInterruptFifoEmpty:
      offset = HMAC_INTR_COMMON_FIFO_EMPTY_BIT;
      break;
    case kDifHmacInterruptHmacErr:
      offset = HMAC_INTR_COMMON_HMAC_ERR_BIT;
      break;
    default:
      return false;
  }

  *offset_out = offset;

  return true;
}

dif_hmac_result_t dif_hmac_init(const dif_hmac_config_t *config,
                                dif_hmac_t *hmac) {
  // Basic checks on parameters. In `kDifHmacModeHmac` mode a key is required.
  if (config == NULL || hmac == NULL) {
    return kDifHmacBadArg;
  }

  hmac->base_addr = config->base_addr;

  // Clear the config, stopping the SHA engine.
  mmio_region_write32(config->base_addr, HMAC_CFG_REG_OFFSET, 0);

  // Clear INTER.
  mmio_region_write32(config->base_addr, HMAC_INTR_STATE_REG_OFFSET,
                      (1 << HMAC_INTR_STATE_HMAC_DONE_BIT) |
                          (1 << HMAC_INTR_STATE_FIFO_EMPTY_BIT) |
                          (1 << HMAC_INTR_STATE_HMAC_ERR_BIT));

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_irq_state_get(const dif_hmac_t *hmac,
                                         dif_hmac_interrupt_t irq_type,
                                         dif_hmac_enable_t *state) {
  if (hmac == NULL || state == NULL) {
    return kDifHmacBadArg;
  }

  uint8_t offset;
  if (!irq_bit_offset_get(irq_type, &offset)) {
    return kDifHmacError;
  }

  // Get the interrupt state.
  bool enabled = mmio_region_get_bit32(hmac->base_addr,
                                       HMAC_INTR_STATE_REG_OFFSET, offset);
  *state = (enabled ? kDifHmacEnable : kDifHmacDisable);

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_irq_state_clear(const dif_hmac_t *hmac,
                                           dif_hmac_interrupt_t irq_type) {
  if (hmac == NULL) {
    return kDifHmacBadArg;
  }

  uint8_t offset;
  if (!irq_bit_offset_get(irq_type, &offset)) {
    return kDifHmacError;
  }

  // Clear the interrupt state.
  mmio_region_write_only_set_bit32(hmac->base_addr, HMAC_INTR_STATE_REG_OFFSET,
                                   offset);

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_irqs_disable(const dif_hmac_t *hmac,
                                        uint32_t *state) {
  if (hmac == NULL) {
    return kDifHmacBadArg;
  }

  // Pass the interrupt state back to the caller.
  if (state != NULL) {
    *state = mmio_region_read32(hmac->base_addr, HMAC_INTR_ENABLE_REG_OFFSET);
  }

  // Disable all interrupts.
  mmio_region_write32(hmac->base_addr, HMAC_INTR_ENABLE_REG_OFFSET, 0u);

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_irqs_restore(const dif_hmac_t *hmac,
                                        uint32_t state) {
  if (hmac == NULL) {
    return kDifHmacBadArg;
  }

  // Restore interrupt state.
  mmio_region_write32(hmac->base_addr, HMAC_INTR_ENABLE_REG_OFFSET, state);

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_irq_control(const dif_hmac_t *hmac,
                                       dif_hmac_interrupt_t irq_type,
                                       dif_hmac_enable_t enable) {
  if (hmac == NULL) {
    return kDifHmacBadArg;
  }

  uint8_t offset;
  if (!irq_bit_offset_get(irq_type, &offset)) {
    return kDifHmacError;
  }

  // Enable/Disable interrupt.
  if (enable == kDifHmacEnable) {
    mmio_region_nonatomic_set_bit32(hmac->base_addr,
                                    HMAC_INTR_ENABLE_REG_OFFSET, offset);
  } else {
    mmio_region_nonatomic_clear_bit32(hmac->base_addr,
                                      HMAC_INTR_ENABLE_REG_OFFSET, offset);
  }

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_irq_force(const dif_hmac_t *hmac,
                                     dif_hmac_interrupt_t irq_type) {
  if (hmac == NULL) {
    return kDifHmacBadArg;
  }

  uint8_t offset;
  if (!irq_bit_offset_get(irq_type, &offset)) {
    return kDifHmacError;
  }

  // Force the requested interrupt.
  mmio_region_nonatomic_set_bit32(hmac->base_addr, HMAC_INTR_TEST_REG_OFFSET,
                                  offset);

  return kDifHmacOk;
}

/**
 * Sets up the CFG value for a given per-transaction configuration.
 *
 * This only sets the right values for the ENDIAN_SWAP / DIGEST_SWAP values,
 * using the values in `config`.
 *
 * The implementation here is careful to only update `*device_config` once it
 * has calculated the entire value for the register, rather than gradually
 * updating it early. The value of `*device_config` is only updated if the
 * function returns #kDifHmacOk.
 *
 * @param[inout] device_config HMAC CFG register value to be updated;
 * @param config A per-transaction configuration.
 * @returns #kDifHmacError if the config is invalid, #kDifHmacOk if
 * `*device_config` was sucessfully updated.
 */
static dif_hmac_result_t dif_hmac_calculate_device_config_value(
    uint32_t *device_config, const dif_hmac_transaction_t config) {
  // Set the byte-order of the input message.
  bool swap_message_endianness;
  switch (config.message_endianness) {
    case kDifHmacEndiannessBig:
      swap_message_endianness = false;
      break;
    case kDifHmacEndiannessLittle:
      swap_message_endianness = true;
      break;
    default:
      return kDifHmacError;
  }

  // Set the byte-order of the digest.
  bool swap_digest_endianness;
  switch (config.digest_endianness) {
    case kDifHmacEndiannessBig:
      swap_digest_endianness = false;
      break;
    case kDifHmacEndiannessLittle:
      swap_digest_endianness = true;
      break;
    default:
      return kDifHmacError;
  }

  // `*device_config` must only be updated after the two switch statements,
  // because they can return #kDifHmacError.
  *device_config = bitfield_bit32_write(
      *device_config, HMAC_CFG_ENDIAN_SWAP_BIT, swap_message_endianness);
  *device_config = bitfield_bit32_write(
      *device_config, HMAC_CFG_DIGEST_SWAP_BIT, swap_digest_endianness);

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_mode_hmac_start(
    const dif_hmac_t *hmac, const uint8_t *key,
    const dif_hmac_transaction_t config) {
  if (hmac == NULL || key == NULL) {
    return kDifHmacBadArg;
  }

  // Set the HMAC key.
  // TODO Static assert register layout.
  mmio_region_memcpy_to_mmio32(hmac->base_addr, HMAC_KEY_0_REG_OFFSET, key,
                               HMAC_PARAM_NUM_WORDS * sizeof(uint32_t));

  // Read current CFG register value.
  uint32_t device_config =
      mmio_region_read32(hmac->base_addr, HMAC_CFG_REG_OFFSET);

  // Set the byte-order of the input message and the digest.
  dif_hmac_result_t update_result =
      dif_hmac_calculate_device_config_value(&device_config, config);
  if (update_result != kDifHmacOk) {
    return update_result;
  }

  // Set HMAC to process in HMAC mode (not SHA256-only mode).
  device_config =
      bitfield_bit32_write(device_config, HMAC_CFG_SHA_EN_BIT, true);
  device_config =
      bitfield_bit32_write(device_config, HMAC_CFG_HMAC_EN_BIT, true);
  mmio_region_write32(hmac->base_addr, HMAC_CFG_REG_OFFSET, device_config);

  // Begin HMAC operation.
  mmio_region_nonatomic_set_bit32(hmac->base_addr, HMAC_CMD_REG_OFFSET,
                                  HMAC_CMD_HASH_START_BIT);
  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_mode_sha256_start(
    const dif_hmac_t *hmac, const dif_hmac_transaction_t config) {
  if (hmac == NULL) {
    return kDifHmacBadArg;
  }

  // TODO: Clear HMAC Key? Write Zeroed HMAC Key?

  // Read current CFG register value.
  uint32_t device_config =
      mmio_region_read32(hmac->base_addr, HMAC_CFG_REG_OFFSET);

  // Set the byte-order of the input message and the digest.
  dif_hmac_result_t update_result =
      dif_hmac_calculate_device_config_value(&device_config, config);
  if (update_result != kDifHmacOk) {
    return update_result;
  }

  // Set HMAC to process in SHA256-only mode (without HMAC mode).
  device_config =
      bitfield_bit32_write(device_config, HMAC_CFG_SHA_EN_BIT, true);
  device_config =
      bitfield_bit32_write(device_config, HMAC_CFG_HMAC_EN_BIT, false);

  // Write new CFG register value.
  mmio_region_write32(hmac->base_addr, HMAC_CFG_REG_OFFSET, device_config);

  // Begin SHA256-only operation.
  mmio_region_nonatomic_set_bit32(hmac->base_addr, HMAC_CMD_REG_OFFSET,
                                  HMAC_CMD_HASH_START_BIT);

  return kDifHmacOk;
}

dif_hmac_fifo_result_t dif_hmac_fifo_push(const dif_hmac_t *hmac,
                                          const void *data, size_t len,
                                          size_t *bytes_sent) {
  if (hmac == NULL || data == NULL) {
    return kDifHmacFifoBadArg;
  }

  const uint8_t *data_sent = (const uint8_t *)data;
  size_t bytes_remaining = len;

  while (bytes_remaining > 0 && get_fifo_available_space(hmac) > 0) {
    bool word_aligned = (uintptr_t)data_sent % sizeof(uint32_t) == 0;
    size_t bytes_written = 0;

    if (bytes_remaining < sizeof(uint32_t) || !word_aligned) {
      // Individual byte writes are needed if the buffer isn't aligned or there
      // are no more full words to write.
      mmio_region_write8(hmac->base_addr, HMAC_MSG_FIFO_REG_OFFSET, *data_sent);
      bytes_written = 1;
    } else {
      // `data_sent` is word-aligned and there are still words to write.
      uint32_t word = read_32(data_sent);
      mmio_region_write32(hmac->base_addr, HMAC_MSG_FIFO_REG_OFFSET, word);
      bytes_written = sizeof(uint32_t);
    }

    bytes_remaining -= bytes_written;
    data_sent += bytes_written;
  }

  if (bytes_sent != NULL) {
    *bytes_sent = len - bytes_remaining;
  }

  if (bytes_remaining > 0) {
    return kDifHmacFifoFull;
  }

  return kDifHmacFifoOk;
}

dif_hmac_result_t dif_hmac_fifo_count_entries(const dif_hmac_t *hmac,
                                              uint32_t *num_entries) {
  if (hmac == NULL || num_entries == NULL) {
    return kDifHmacBadArg;
  }

  *num_entries = get_fifo_entry_count(hmac);

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_get_message_length(const dif_hmac_t *hmac,
                                              uint64_t *msg_len) {
  if (hmac == NULL || msg_len == NULL) {
    return kDifHmacBadArg;
  }

  uint64_t msg_lower =
      mmio_region_read32(hmac->base_addr, HMAC_MSG_LENGTH_LOWER_REG_OFFSET);
  uint64_t msg_upper =
      mmio_region_read32(hmac->base_addr, HMAC_MSG_LENGTH_UPPER_REG_OFFSET);

  *msg_len = (msg_upper << 32) | msg_lower;

  return kDifHmacOk;
}

dif_hmac_result_t dif_hmac_process(const dif_hmac_t *hmac) {
  if (hmac == NULL) {
    return kDifHmacBadArg;
  }

  mmio_region_nonatomic_set_bit32(hmac->base_addr, HMAC_CMD_REG_OFFSET,
                                  HMAC_CMD_HASH_PROCESS_BIT);
  return kDifHmacOk;
}

dif_hmac_digest_result_t dif_hmac_finish(const dif_hmac_t *hmac,
                                         dif_hmac_digest_t *digest) {
  if (hmac == NULL || digest == NULL) {
    return kDifHmacDigestBadArg;
  }

  // Check if hmac_done is asserted.
  bool done = mmio_region_get_bit32(hmac->base_addr, HMAC_INTR_STATE_REG_OFFSET,
                                    HMAC_INTR_STATE_HMAC_DONE_BIT);

  if (done) {
    // Clear hmac_done.
    mmio_region_nonatomic_set_bit32(hmac->base_addr, HMAC_INTR_STATE_REG_OFFSET,
                                    HMAC_INTR_STATE_HMAC_DONE_BIT);
  } else {
    return kDifHmacDigestProcessing;
  }

  // Read the digest.
  // TODO Static assert register layout.
  mmio_region_memcpy_from_mmio32(hmac->base_addr, HMAC_DIGEST_0_REG_OFFSET,
                                 digest->digest,
                                 HMAC_PARAM_NUM_WORDS * sizeof(uint32_t));

  // Disable HMAC and SHA256 until the next transaction, clearing the current
  // digest.
  uint32_t device_config =
      mmio_region_read32(hmac->base_addr, HMAC_CFG_REG_OFFSET);
  device_config =
      bitfield_bit32_write(device_config, HMAC_CFG_SHA_EN_BIT, false);
  device_config =
      bitfield_bit32_write(device_config, HMAC_CFG_HMAC_EN_BIT, false);
  mmio_region_write32(hmac->base_addr, HMAC_CFG_REG_OFFSET, device_config);

  return kDifHmacDigestOk;
}

dif_hmac_result_t dif_hmac_wipe_secret(const dif_hmac_t *hmac,
                                       uint32_t entropy) {
  if (hmac == NULL) {
    return kDifHmacBadArg;
  }

  mmio_region_write32(hmac->base_addr, HMAC_WIPE_SECRET_REG_OFFSET, entropy);

  return kDifHmacOk;
}
