/*
 * Copyright (c) 2016 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file Shim layer for TinyCrypt, making it complaint to crypto API.
 */

#include <tinycrypt/cbc_mode.h>
#include <tinycrypt/ctr_mode.h>
#include <tinycrypt/ccm_mode.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
#include <string.h>
#include <crypto/cipher.h>
#include "crypto_tc_shim_priv.h"

#define SYS_LOG_LEVEL CONFIG_SYS_LOG_CRYPTO_LEVEL
#include <logging/sys_log.h>


#define CRYPTO_MAX_SESSION CONFIG_CRYPTO_TINYCRYPT_SHIM_MAX_SESSION

static struct tc_shim_drv_state tc_driver_state[CRYPTO_MAX_SESSION];

static int do_cbc_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *op,
			  u8_t *iv)
{
	struct tc_shim_drv_state *data =  ctx->drv_sessn_state;

	if (tc_cbc_mode_encrypt(op->out_buf,
				op->out_buf_max,
				op->in_buf, op->in_len,
				iv,
				&data->session_key) == TC_CRYPTO_FAIL) {
		SYS_LOG_ERR("TC internal error during CBC encryption");
		return -EIO;
	}

	return 0;
}

static int do_cbc_decrypt(struct cipher_ctx *ctx, struct cipher_pkt *op,
			  u8_t *iv)
{
	struct tc_shim_drv_state *data =  ctx->drv_sessn_state;

	/* TinyCrypt expects the IV and cipher text to be in a contiguous
	 * buffer for efficieny
	 */
	if (iv != op->in_buf) {
		SYS_LOG_ERR("TC needs contiguous iv and ciphertext");
		return -EIO;
	}

	if (tc_cbc_mode_decrypt(op->out_buf,
			op->out_buf_max,
			op->in_buf + TC_AES_BLOCK_SIZE,
			op->in_len,
			op->in_buf, &data->session_key) == TC_CRYPTO_FAIL) {
		SYS_LOG_ERR("Func TC internal error during CBC decryption");
		return -EIO;
	}

	return 0;
}


static int do_ctr_op(struct cipher_ctx *ctx, struct cipher_pkt *op,
		     u8_t *iv)
{
	struct tc_shim_drv_state *data =  ctx->drv_sessn_state;
	u8_t ctr[16] = {0};	/* CTR mode Counter =  iv:ctr */
	int ivlen = ctx->keylen - (ctx->mode_params.ctr_info.ctr_len >> 3);

	/* Tinycrypt takes the last 4 bytes of the counter parameter as the
	 * true counter start. IV forms the first 12 bytes of the split counter.
	 */
	memcpy(ctr, iv, ivlen);

	if (tc_ctr_mode(op->out_buf, op->out_buf_max, op->in_buf,
			op->in_len, ctr,
			&data->session_key) == TC_CRYPTO_FAIL) {
		SYS_LOG_ERR("TC internal error during CTR OP");
		return -EIO;
	}

	return 0;
}

static int do_ccm_encrypt_mac(struct cipher_ctx *ctx,
			     struct cipher_aead_pkt *aead_op, u8_t *nonce)
{
	struct tc_ccm_mode_struct ccm;
	struct tc_shim_drv_state *data =  ctx->drv_sessn_state;
	struct ccm_params *ccm_param = &ctx->mode_params.ccm_info;
	struct cipher_pkt *op = aead_op->pkt;

	if (tc_ccm_config(&ccm, &data->session_key, nonce,
			ccm_param->nonce_len,
			ccm_param->tag_len) == TC_CRYPTO_FAIL) {
		SYS_LOG_ERR("TC internal error during CCM encryption config");
		return -EIO;
	}

	if (tc_ccm_generation_encryption(op->out_buf, op->out_buf_max,
					 aead_op->ad, aead_op->ad_len, op->in_buf,
					 op->in_len, &ccm) == TC_CRYPTO_FAIL) {
		SYS_LOG_ERR("TC internal error during CCM Encryption OP");
		return -EIO;
	}

	/* Looks like TinyCrypt appends the MAC to the end of out_buf as it
	 * does not give a separate hash parameter. The user needs to be aware
	 * of this and provide sufficient buffer space in output buffer to hold
	 * both encrypted output and hash
	 */
	aead_op->tag = op->out_buf + op->in_len;

	return 0;
}

static int do_ccm_decrypt_auth(struct cipher_ctx *ctx,
			       struct cipher_aead_pkt *aead_op, u8_t *nonce)
{
	struct tc_ccm_mode_struct ccm;
	struct tc_shim_drv_state *data =  ctx->drv_sessn_state;
	struct ccm_params *ccm_param = &ctx->mode_params.ccm_info;
	struct cipher_pkt *op = aead_op->pkt;

	if (tc_ccm_config(&ccm, &data->session_key, nonce,
			  ccm_param->nonce_len,
			  ccm_param->tag_len) == TC_CRYPTO_FAIL) {
		SYS_LOG_ERR("TC internal error during CCM decryption config");
		return -EIO;
	}

	/* TinyCrypt expects the hash/MAC to be present at the end of in_buf
	 * as it doesnt take a separate hash parameter. Ideally this should
	 * be moved to a ctx.flag check during session_setup, later.
	 */
	if (aead_op->tag != op->in_buf + op->in_len) {
		SYS_LOG_ERR("TC needs contiguous hash  at the end of inbuf");
		return -EIO;
	}

	if (tc_ccm_decryption_verification(op->out_buf, op->out_buf_max,
					   aead_op->ad, aead_op->ad_len,
					   op->in_buf,
					   op->in_len + ccm_param->tag_len,
					   &ccm) == TC_CRYPTO_FAIL) {
		SYS_LOG_ERR("TC internal error during CCM decryption OP");
		return -EIO;
	}

	return 0;
}

static int get_unused_session(void)
{
	int i;

	for (i = 0; i < CRYPTO_MAX_SESSION; i++) {
		if (tc_driver_state[i].in_use == 0) {
			tc_driver_state[i].in_use = 1;
			break;
		}
	}

	return i;
}

int tc_session_setup(struct device *dev, struct cipher_ctx *ctx,
		     enum cipher_algo algo, enum cipher_mode mode,
		     enum cipher_op op_type)
{
	struct tc_shim_drv_state *data;
	int idx;

	ARG_UNUSED(dev);

	/* The shim currently supports only CBC or CTR mode for AES */
	if (algo != CRYPTO_CIPHER_ALGO_AES) {
		SYS_LOG_ERR("TC Shim Unsupported algo");
		return -EINVAL;
	}

	/* TinyCrypt being a software library, only synchronous operations
	 * make sense.
	 */
	if (!(ctx->flags & CAP_SYNC_OPS)) {
		SYS_LOG_ERR("Async not supported by this driver");
		return -EINVAL;
	}

	if (ctx->keylen != TC_AES_KEY_SIZE) {
		/* TinyCrypt supports only 128 bits */
		SYS_LOG_ERR("TC Shim Unsupported key size");
		return -EINVAL;
	}

	if (op_type == CRYPTO_CIPHER_OP_ENCRYPT) {
		switch (mode) {
		case CRYPTO_CIPHER_MODE_CBC:
			ctx->ops.cbc_crypt_hndlr = do_cbc_encrypt;
			break;
		case CRYPTO_CIPHER_MODE_CTR:
			if (ctx->mode_params.ctr_info.ctr_len != 32) {
				SYS_LOG_ERR("Tinycrypt supports only 32 bit "
					    "counter");
				return -EINVAL;
			}
			ctx->ops.ctr_crypt_hndlr = do_ctr_op;
			break;
		case CRYPTO_CIPHER_MODE_CCM:
			ctx->ops.ccm_crypt_hndlr = do_ccm_encrypt_mac;
			break;
		default:
			SYS_LOG_ERR("TC Shim Unsupported mode");
			return -EINVAL;
		}
	} else {
		switch (mode) {
		case CRYPTO_CIPHER_MODE_CBC:
			ctx->ops.cbc_crypt_hndlr = do_cbc_decrypt;
			break;
		case CRYPTO_CIPHER_MODE_CTR:
			/* Maybe validate CTR length */
			if (ctx->mode_params.ctr_info.ctr_len != 32) {
				SYS_LOG_ERR("Tinycrypt supports only 32 bit "
					    "counter");
				return -EINVAL;
			}
			ctx->ops.ctr_crypt_hndlr = do_ctr_op;
			break;
		case CRYPTO_CIPHER_MODE_CCM:
			ctx->ops.ccm_crypt_hndlr = do_ccm_decrypt_auth;
			break;
		default:
			SYS_LOG_ERR("TC Shim Unsupported mode");
			return -EINVAL;
		}

	}

	ctx->ops.cipher_mode = mode;

	idx = get_unused_session();
	if (idx == CRYPTO_MAX_SESSION) {
		SYS_LOG_ERR("Max sessions in progress");
		return -ENOSPC;
	}

	data = &tc_driver_state[idx];

	if (tc_aes128_set_encrypt_key(&data->session_key, ctx->key.bit_stream)
			 == TC_CRYPTO_FAIL) {
		SYS_LOG_ERR("TC internal error in setting key");
		tc_driver_state[idx].in_use = 0;

		return -EIO;
	}

	ctx->drv_sessn_state = data;

	return 0;
}

int tc_query_caps(struct device *dev)
{
	return (CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS);
}


int tc_session_free(struct device *dev, struct cipher_ctx *sessn)
{
	struct tc_shim_drv_state *data =  sessn->drv_sessn_state;

	ARG_UNUSED(dev);
	memset(data, 0, sizeof(struct tc_shim_drv_state));
	data->in_use = 0;

	return 0;

}

static int tc_shim_init(struct device *dev)
{
	int i;

	ARG_UNUSED(dev);
	for (i = 0; i < CRYPTO_MAX_SESSION; i++) {
		tc_driver_state[i].in_use = 0;
	}
	return 0;
}




static struct crypto_driver_api crypto_enc_funcs = {
	.begin_session = tc_session_setup,
	.free_session = tc_session_free,
	.crypto_async_callback_set = NULL,
	.query_hw_caps = tc_query_caps,
};


DEVICE_AND_API_INIT(crypto_tinycrypt, CONFIG_CRYPTO_TINYCRYPT_SHIM_DRV_NAME,
		    &tc_shim_init, NULL, NULL,
		    POST_KERNEL, CONFIG_CRYPTO_INIT_PRIORITY,
		    (void *)&crypto_enc_funcs);
