/*
 * AMD Cryptographic Coprocessor (CCP) AES XTS crypto API support
 *
 * Copyright (C) 2013 Advanced Micro Devices, Inc.
 *
 * Author: Tom Lendacky <thomas.lendacky@amd.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/module.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/scatterlist.h>
#include <linux/crypto.h>
#include <crypto/algapi.h>
#include <crypto/aes.h>
#include <crypto/scatterwalk.h>

#include "ccp-crypto.h"


struct ccp_aes_xts_def {
	const char *name;
	const char *drv_name;
};

static struct ccp_aes_xts_def aes_xts_algs[] = {
	{
		.name		= "xts(aes)",
		.drv_name	= "xts-aes-ccp",
	},
};

struct ccp_unit_size_map {
	unsigned int size;
	u32 value;
};

static struct ccp_unit_size_map unit_size_map[] = {
	{
		.size	= 4096,
		.value	= CCP_XTS_AES_UNIT_SIZE_4096,
	},
	{
		.size	= 2048,
		.value	= CCP_XTS_AES_UNIT_SIZE_2048,
	},
	{
		.size	= 1024,
		.value	= CCP_XTS_AES_UNIT_SIZE_1024,
	},
	{
		.size	= 512,
		.value	= CCP_XTS_AES_UNIT_SIZE_512,
	},
	{
		.size	= 256,
		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
	},
	{
		.size	= 128,
		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
	},
	{
		.size	= 64,
		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
	},
	{
		.size	= 32,
		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
	},
	{
		.size	= 16,
		.value	= CCP_XTS_AES_UNIT_SIZE_16,
	},
	{
		.size	= 1,
		.value	= CCP_XTS_AES_UNIT_SIZE__LAST,
	},
};

static int ccp_aes_xts_complete(struct crypto_async_request *async_req, int ret)
{
	struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);

	if (ret)
		return ret;

	memcpy(req->info, rctx->iv, AES_BLOCK_SIZE);

	return 0;
}

static int ccp_aes_xts_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
			      unsigned int key_len)
{
	struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm));

	/* Only support 128-bit AES key with a 128-bit Tweak key,
	 * otherwise use the fallback
	 */
	switch (key_len) {
	case AES_KEYSIZE_128 * 2:
		memcpy(ctx->u.aes.key, key, key_len);
		break;
	}
	ctx->u.aes.key_len = key_len / 2;
	sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);

	return crypto_ablkcipher_setkey(ctx->u.aes.tfm_ablkcipher, key,
					key_len);
}

static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
			     unsigned int encrypt)
{
	struct crypto_tfm *tfm =
		crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
	struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
	unsigned int unit;
	u32 unit_size;
	int ret;

	if (!ctx->u.aes.key_len)
		return -EINVAL;

	if (req->nbytes & (AES_BLOCK_SIZE - 1))
		return -EINVAL;

	if (!req->info)
		return -EINVAL;

	unit_size = CCP_XTS_AES_UNIT_SIZE__LAST;
	if (req->nbytes <= unit_size_map[0].size) {
		for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) {
			if (!(req->nbytes & (unit_size_map[unit].size - 1))) {
				unit_size = unit_size_map[unit].value;
				break;
			}
		}
	}

	if ((unit_size == CCP_XTS_AES_UNIT_SIZE__LAST) ||
	    (ctx->u.aes.key_len != AES_KEYSIZE_128)) {
		/* Use the fallback to process the request for any
		 * unsupported unit sizes or key sizes
		 */
		ablkcipher_request_set_tfm(req, ctx->u.aes.tfm_ablkcipher);
		ret = (encrypt) ? crypto_ablkcipher_encrypt(req) :
				  crypto_ablkcipher_decrypt(req);
		ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));

		return ret;
	}

	memcpy(rctx->iv, req->info, AES_BLOCK_SIZE);
	sg_init_one(&rctx->iv_sg, rctx->iv, AES_BLOCK_SIZE);

	memset(&rctx->cmd, 0, sizeof(rctx->cmd));
	INIT_LIST_HEAD(&rctx->cmd.entry);
	rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
	rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
					   : CCP_AES_ACTION_DECRYPT;
	rctx->cmd.u.xts.unit_size = unit_size;
	rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
	rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
	rctx->cmd.u.xts.iv = &rctx->iv_sg;
	rctx->cmd.u.xts.iv_len = AES_BLOCK_SIZE;
	rctx->cmd.u.xts.src = req->src;
	rctx->cmd.u.xts.src_len = req->nbytes;
	rctx->cmd.u.xts.dst = req->dst;

	ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);

	return ret;
}

static int ccp_aes_xts_encrypt(struct ablkcipher_request *req)
{
	return ccp_aes_xts_crypt(req, 1);
}

static int ccp_aes_xts_decrypt(struct ablkcipher_request *req)
{
	return ccp_aes_xts_crypt(req, 0);
}

static int ccp_aes_xts_cra_init(struct crypto_tfm *tfm)
{
	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
	struct crypto_ablkcipher *fallback_tfm;

	ctx->complete = ccp_aes_xts_complete;
	ctx->u.aes.key_len = 0;

	fallback_tfm = crypto_alloc_ablkcipher(crypto_tfm_alg_name(tfm), 0,
					       CRYPTO_ALG_ASYNC |
					       CRYPTO_ALG_NEED_FALLBACK);
	if (IS_ERR(fallback_tfm)) {
		pr_warn("could not load fallback driver %s\n",
			crypto_tfm_alg_name(tfm));
		return PTR_ERR(fallback_tfm);
	}
	ctx->u.aes.tfm_ablkcipher = fallback_tfm;

	tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx) +
				      fallback_tfm->base.crt_ablkcipher.reqsize;

	return 0;
}

static void ccp_aes_xts_cra_exit(struct crypto_tfm *tfm)
{
	struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);

	if (ctx->u.aes.tfm_ablkcipher)
		crypto_free_ablkcipher(ctx->u.aes.tfm_ablkcipher);
	ctx->u.aes.tfm_ablkcipher = NULL;
}


static int ccp_register_aes_xts_alg(struct list_head *head,
				    const struct ccp_aes_xts_def *def)
{
	struct ccp_crypto_ablkcipher_alg *ccp_alg;
	struct crypto_alg *alg;
	int ret;

	ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
	if (!ccp_alg)
		return -ENOMEM;

	INIT_LIST_HEAD(&ccp_alg->entry);

	alg = &ccp_alg->alg;

	snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
	snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
		 def->drv_name);
	alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
			 CRYPTO_ALG_KERN_DRIVER_ONLY |
			 CRYPTO_ALG_NEED_FALLBACK;
	alg->cra_blocksize = AES_BLOCK_SIZE;
	alg->cra_ctxsize = sizeof(struct ccp_ctx);
	alg->cra_priority = CCP_CRA_PRIORITY;
	alg->cra_type = &crypto_ablkcipher_type;
	alg->cra_ablkcipher.setkey = ccp_aes_xts_setkey;
	alg->cra_ablkcipher.encrypt = ccp_aes_xts_encrypt;
	alg->cra_ablkcipher.decrypt = ccp_aes_xts_decrypt;
	alg->cra_ablkcipher.min_keysize = AES_MIN_KEY_SIZE * 2;
	alg->cra_ablkcipher.max_keysize = AES_MAX_KEY_SIZE * 2;
	alg->cra_ablkcipher.ivsize = AES_BLOCK_SIZE;
	alg->cra_init = ccp_aes_xts_cra_init;
	alg->cra_exit = ccp_aes_xts_cra_exit;
	alg->cra_module = THIS_MODULE;

	ret = crypto_register_alg(alg);
	if (ret) {
		pr_err("%s ablkcipher algorithm registration error (%d)\n",
			alg->cra_name, ret);
		kfree(ccp_alg);
		return ret;
	}

	list_add(&ccp_alg->entry, head);

	return 0;
}

int ccp_register_aes_xts_algs(struct list_head *head)
{
	int i, ret;

	for (i = 0; i < ARRAY_SIZE(aes_xts_algs); i++) {
		ret = ccp_register_aes_xts_alg(head, &aes_xts_algs[i]);
		if (ret)
			return ret;
	}

	return 0;
}
