/*
 * Copyright (c) 2022 Nuvoton Technology Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT nuvoton_npcx_sha

#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/crypto/crypto.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sha_npcx, CONFIG_CRYPTO_LOG_LEVEL);

#include "soc_ncl.h"

#define NPCX_HASH_CAPS_SUPPORT  (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS)
#define NPCX_SHA256_HANDLE_SIZE DT_INST_PROP(0, context_buffer_size)
#define NPCX_SHA_MAX_SESSION    1

/* The following table holds the function pointer for each SHA API in NPCX ROM. */
struct npcx_ncl_sha {
	/* Get the SHA context size required by SHA APIs. */
	uint32_t (*get_context_size)(void);
	/* Initial SHA context. */
	enum ncl_status (*init_context)(void *ctx);
	/* Finalize SHA context. */
	enum ncl_status (*finalize_context)(void *ctx);
	/* Initiate the SHA hardware module and setups needed parameters. */
	enum ncl_status (*init)(void *ctx);
	/*
	 * Prepare the context buffer for a SHA calculation -  by loading the
	 * initial SHA-256/384/512 parameters.
	 */
	enum ncl_status (*start)(void *ctx, enum ncl_sha_type type);
	/*
	 * Updates the SHA calculation with the additional data. When the
	 * function returns, the hardware and memory buffer shall be ready to
	 * accept new data * buffers for SHA calculation and changes to the data
	 * in data buffer should no longer effect the SHA calculation.
	 */
	enum ncl_status (*update)(void *ctx, const uint8_t *data, uint32_t Len);
	/* Return the SHA result (digest.) */
	enum ncl_status (*finish)(void *ctx, uint8_t *hashDigest);
	/* Perform a complete SHA calculation */
	enum ncl_status (*calc)(void *ctx, enum ncl_sha_type type, const uint8_t *data,
				uint32_t Len, uint8_t *hashDigest);
	/* Power on/off the SHA module. */
	enum ncl_status (*power)(void *ctx, uint8_t enable);
	/* Reset the SHA hardware and terminate any in-progress operations. */
	enum ncl_status (*reset)(void *ctx);
};

/* The start address of the SHA API table. */
#define NPCX_NCL_SHA ((const struct npcx_ncl_sha *)DT_INST_REG_ADDR(0))

struct npcx_sha_context {
	uint8_t handle[NPCX_SHA256_HANDLE_SIZE];
} __aligned(4);

struct npcx_sha_session {
	struct npcx_sha_context npcx_sha_ctx;
	enum hash_algo algo;
	bool in_use;
};

struct npcx_sha_session npcx_sessions[NPCX_SHA_MAX_SESSION];

static int npcx_get_unused_session_index(void)
{
	int i;

	for (i = 0; i < NPCX_SHA_MAX_SESSION; i++) {
		if (!npcx_sessions[i].in_use) {
			npcx_sessions[i].in_use = true;
			return i;
		}
	}

	return -1;
}
static int npcx_sha_compute(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish)
{
	enum ncl_status ret;
	struct npcx_sha_session *npcx_session = ctx->drv_sessn_state;
	struct npcx_sha_context *npcx_ctx = &npcx_session->npcx_sha_ctx;
	enum ncl_sha_type sha_type;

	switch (npcx_session->algo) {
	case CRYPTO_HASH_ALGO_SHA256:
		sha_type = NCL_SHA_TYPE_2_256;
		break;
	case CRYPTO_HASH_ALGO_SHA384:
		sha_type = NCL_SHA_TYPE_2_384;
		break;
	case CRYPTO_HASH_ALGO_SHA512:
		sha_type = NCL_SHA_TYPE_2_512;
		break;
	default:
		LOG_ERR("Unexpected algo: %d", npcx_session->algo);
		return -EINVAL;
	}

	if (!ctx->started) {
		ret = NPCX_NCL_SHA->start(npcx_ctx->handle, sha_type);
		if (ret != NCL_STATUS_OK) {
			LOG_ERR("Could not compute the hash, err:%d", ret);
			return -EINVAL;
		}
		ctx->started = true;
	}

	if (pkt->in_len != 0) {
		ret = NPCX_NCL_SHA->update(npcx_ctx->handle, pkt->in_buf, pkt->in_len);
		if (ret != NCL_STATUS_OK) {
			LOG_ERR("Could not update the hash, err:%d", ret);
			ctx->started = false;
			return -EINVAL;
		}
	}

	if (finish) {
		ctx->started = false;
		ret = NPCX_NCL_SHA->finish(npcx_ctx->handle, pkt->out_buf);
		if (ret != NCL_STATUS_OK) {
			LOG_ERR("Could not compute the hash, err:%d", ret);
			return -EINVAL;
		}
	}

	return 0;
}

static int npcx_hash_session_setup(const struct device *dev, struct hash_ctx *ctx,
				   enum hash_algo algo)
{
	int ctx_idx;
	struct npcx_sha_context *npcx_ctx;

	if (ctx->flags & ~(NPCX_HASH_CAPS_SUPPORT)) {
		LOG_ERR("Unsupported flag");
		return -EINVAL;
	}

	if ((algo != CRYPTO_HASH_ALGO_SHA256) && (algo != CRYPTO_HASH_ALGO_SHA384) &&
	    (algo != CRYPTO_HASH_ALGO_SHA512)) {
		LOG_ERR("Unsupported algo: %d", algo);
		return -EINVAL;
	}

	ctx_idx = npcx_get_unused_session_index();
	if (ctx_idx < 0) {
		LOG_ERR("No free session for now");
		return -ENOSPC;
	}

	npcx_sessions[ctx_idx].algo = algo;

	ctx->drv_sessn_state = &npcx_sessions[ctx_idx];
	ctx->started = false;
	ctx->hash_hndlr = npcx_sha_compute;

	npcx_ctx = &npcx_sessions[ctx_idx].npcx_sha_ctx;
	NPCX_NCL_SHA->init_context(npcx_ctx->handle);
	NPCX_NCL_SHA->power(npcx_ctx->handle, 1);
	NPCX_NCL_SHA->init(npcx_ctx->handle);
	NPCX_NCL_SHA->reset(npcx_ctx->handle);

	return 0;
}

static int npcx_hash_session_free(const struct device *dev, struct hash_ctx *ctx)
{
	struct npcx_sha_session *npcx_session = ctx->drv_sessn_state;
	struct npcx_sha_context *npcx_ctx = &npcx_session->npcx_sha_ctx;

	NPCX_NCL_SHA->reset(npcx_ctx->handle);
	NPCX_NCL_SHA->power(npcx_ctx->handle, 0);
	NPCX_NCL_SHA->finalize_context(npcx_ctx->handle);
	npcx_session->in_use = false;

	return 0;
}

static int npcx_query_caps(const struct device *dev)
{
	return NPCX_HASH_CAPS_SUPPORT;
}

static int npcx_hash_init(const struct device *dev)
{
	uint32_t handle_size_required;

	handle_size_required = NPCX_NCL_SHA->get_context_size();
	if (handle_size_required != NPCX_SHA256_HANDLE_SIZE) {
		LOG_ERR("Pre-alloc buf size doesn't match required buf size (%d)",
			handle_size_required);
		return -ENOSR;
	}

	return 0;
}

static const struct crypto_driver_api npcx_crypto_api = {
	.hash_begin_session = npcx_hash_session_setup,
	.hash_free_session = npcx_hash_session_free,
	.query_hw_caps = npcx_query_caps,
};

DEVICE_DT_INST_DEFINE(0, npcx_hash_init, NULL, NULL, NULL, POST_KERNEL, CONFIG_CRYPTO_INIT_PRIORITY,
		      &npcx_crypto_api);
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
	     "only one 'nuvoton,npcx-sha' compatible node can be supported");
