// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2014-2019, Linaro Limited
 */

#include <assert.h>
#include <crypto/crypto.h>
#include <crypto/crypto_impl.h>
#include <stdlib.h>
#include <string.h>
#include <tee_api_types.h>
#include <tee/tee_cryp_utl.h>
#include <util.h>


/* From libtomcrypt doc:
 *	Ciphertext stealing is a method of dealing with messages
 *	in CBC mode which are not a multiple of the block
 *	length.  This is accomplished by encrypting the last
 *	ciphertext block in ECB mode, and XOR'ing the output
 *	against the last partial block of plaintext. LibTomCrypt
 *	does not support this mode directly but it is fairly
 *	easy to emulate with a call to the cipher's
 *	ecb encrypt() callback function.
 *	The more sane way to deal with partial blocks is to pad
 *	them with zeroes, and then use CBC normally
 */

/*
 * From Global Platform: CTS = CBC-CS3
 */

struct cts_ctx {
	struct crypto_cipher_ctx ctx;
	struct crypto_cipher_ctx *ecb;
	struct crypto_cipher_ctx *cbc;
	TEE_OperationMode mode;
};

static const struct crypto_cipher_ops cts_ops;

static struct cts_ctx *to_cts_ctx(struct crypto_cipher_ctx *ctx)
{
	assert(ctx && ctx->ops == &cts_ops);

	return container_of(ctx, struct cts_ctx, ctx);
}

static TEE_Result cts_init(struct crypto_cipher_ctx *ctx,
			   TEE_OperationMode mode, const uint8_t *key1,
			   size_t key1_len, const uint8_t *key2,
			   size_t key2_len, const uint8_t *iv, size_t iv_len)
{
	TEE_Result res = TEE_SUCCESS;
	struct cts_ctx *c = to_cts_ctx(ctx);

	c->mode = mode;

	res = crypto_cipher_init(c->ecb, mode, key1, key1_len, key2, key2_len,
				 iv, iv_len);
	if (res)
		return res;

	return crypto_cipher_init(c->cbc, mode, key1, key1_len, key2, key2_len,
				  iv, iv_len);
}

/*
 * From http://en.wikipedia.org/wiki/Ciphertext_stealing
 * CBC ciphertext stealing encryption using a standard
 * CBC interface:
 *	1. Pad the last partial plaintext block with 0.
 *	2. Encrypt the whole padded plaintext using the
 *	   standard CBC mode.
 *	3. Swap the last two ciphertext blocks.
 *	4. Truncate the ciphertext to the length of the
 *	   original plaintext.
 *
 * CBC ciphertext stealing decryption using a standard
 * CBC interface
 *	1. Dn = Decrypt (K, Cn-1). Decrypt the second to last
 *	   ciphertext block.
 *	2. Cn = Cn || Tail (Dn, B-M). Pad the ciphertext to the
 *	   nearest multiple of the block size using the last
 *	   B-M bits of block cipher decryption of the
 *	   second-to-last ciphertext block.
 *	3. Swap the last two ciphertext blocks.
 *	4. Decrypt the (modified) ciphertext using the standard
 *	   CBC mode.
 *	5. Truncate the plaintext to the length of the original
 *	   ciphertext.
 */
static TEE_Result cbc_cts_update(void *cbc_ctx, void *ecb_ctx,
				 TEE_OperationMode mode, bool last_block,
				 const uint8_t *data, size_t len, uint8_t *dst)
{
	TEE_Result res = TEE_SUCCESS;
	uint8_t  tmp2_block[64] = { 0 };
	uint8_t tmp_block[64] = { 0 };
	int len_last_block = 0;
	int block_size = 16;
	int nb_blocks = 0;

	if (!last_block)
		return tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD,
					    mode, last_block, data, len, dst);

	/* Compute the last block length and check constraints */
	nb_blocks = (len + block_size - 1) / block_size;
	if (nb_blocks < 2)
		return TEE_ERROR_BAD_STATE;
	len_last_block = len % block_size;
	if (len_last_block == 0)
		len_last_block = block_size;

	if (mode == TEE_MODE_ENCRYPT) {
		memcpy(tmp_block,
		       data + ((nb_blocks - 1) * block_size),
		       len_last_block);
		memset(tmp_block + len_last_block,
		       0,
		       block_size - len_last_block);

		res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD,
					   mode, 0, data,
					   (nb_blocks - 1) * block_size, dst);
		if (res != TEE_SUCCESS)
			return res;

		memcpy(dst + (nb_blocks - 1) * block_size,
		       dst + (nb_blocks - 2) * block_size,
		       len_last_block);

		res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD,
					   mode, 0, tmp_block, block_size,
					   dst + (nb_blocks - 2) * block_size);
		if (res != TEE_SUCCESS)
			return res;
	} else {
		/* 1. Decrypt the second to last ciphertext block */
		res = tee_do_cipher_update(ecb_ctx, TEE_ALG_AES_ECB_NOPAD,
					   mode, 0,
					   data + (nb_blocks - 2) * block_size,
					   block_size, tmp2_block);
		if (res != TEE_SUCCESS)
			return res;

		/* 2. Cn = Cn || Tail (Dn, B-M) */
		memcpy(tmp_block, data + ((nb_blocks - 1) * block_size),
		       len_last_block);
		memcpy(tmp_block + len_last_block, tmp2_block + len_last_block,
		       block_size - len_last_block);

		/* 3. Swap the last two ciphertext blocks */
		/* done by passing the correct buffers in step 4. */

		/* 4. Decrypt the (modified) ciphertext */
		if (nb_blocks > 2) {
			res = tee_do_cipher_update(cbc_ctx,
						   TEE_ALG_AES_CBC_NOPAD, mode,
						   0, data,
						   (nb_blocks - 2) *
						   block_size, dst);
			if (res != TEE_SUCCESS)
				return res;
		}

		res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD,
					   mode, 0, tmp_block, block_size,
					   dst +
					   ((nb_blocks - 2) * block_size));
		if (res != TEE_SUCCESS)
			return res;

		res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD,
					   mode, 0, data +
					   ((nb_blocks - 2) * block_size),
					   block_size, tmp_block);
		if (res != TEE_SUCCESS)
			return res;

		/* 5. Truncate the plaintext */
		memcpy(dst + (nb_blocks - 1) * block_size, tmp_block,
		       len_last_block);
	}
	return TEE_SUCCESS;
}

static TEE_Result cts_update(struct crypto_cipher_ctx *ctx, bool last_block,
			     const uint8_t *data, size_t len, uint8_t *dst)
{
	struct cts_ctx *c = to_cts_ctx(ctx);

	return cbc_cts_update(c->cbc, c->ecb, c->mode, last_block, data, len,
			      dst);
}

static void cts_final(struct crypto_cipher_ctx *ctx)
{
	struct cts_ctx *c = to_cts_ctx(ctx);

	crypto_cipher_final(c->cbc);
	crypto_cipher_final(c->ecb);
}

static void cts_free_ctx(struct crypto_cipher_ctx *ctx)
{
	struct cts_ctx *c = to_cts_ctx(ctx);

	crypto_cipher_free_ctx(c->cbc);
	crypto_cipher_free_ctx(c->ecb);
	free(c);
}

static void cts_copy_state(struct crypto_cipher_ctx *dst_ctx,
			   struct crypto_cipher_ctx *src_ctx)
{
	struct cts_ctx *src = to_cts_ctx(src_ctx);
	struct cts_ctx *dst = to_cts_ctx(dst_ctx);

	crypto_cipher_copy_state(dst->cbc, src->cbc);
	crypto_cipher_copy_state(dst->ecb, src->ecb);
}

static const struct crypto_cipher_ops cts_ops = {
	.init = cts_init,
	.update = cts_update,
	.final = cts_final,
	.free_ctx = cts_free_ctx,
	.copy_state = cts_copy_state,
};

TEE_Result crypto_aes_cts_alloc_ctx(struct crypto_cipher_ctx **ctx)
{
	TEE_Result res = TEE_SUCCESS;
	struct cts_ctx *c = calloc(1, sizeof(*c));

	if (!c)
		return TEE_ERROR_OUT_OF_MEMORY;

	res = crypto_aes_ecb_alloc_ctx(&c->ecb);
	if (res)
		goto err;
	res = crypto_aes_cbc_alloc_ctx(&c->cbc);
	if (res)
		goto err;

	c->ctx.ops = &cts_ops;
	*ctx = &c->ctx;

	return TEE_SUCCESS;
err:
	crypto_cipher_free_ctx(c->ecb);
	free(c);

	return res;
}
