xref: /optee_os/core/crypto/aes-cts.c (revision 17c68af4b1c81277d45d0792528b7dc8063f4a34)
1*17c68af4SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*17c68af4SJens Wiklander /*
3*17c68af4SJens Wiklander  * Copyright (c) 2014-2019, Linaro Limited
4*17c68af4SJens Wiklander  */
5*17c68af4SJens Wiklander 
6*17c68af4SJens Wiklander #include <assert.h>
7*17c68af4SJens Wiklander #include <crypto/crypto.h>
8*17c68af4SJens Wiklander #include <crypto/crypto_impl.h>
9*17c68af4SJens Wiklander #include <stdlib.h>
10*17c68af4SJens Wiklander #include <tee_api_types.h>
11*17c68af4SJens Wiklander #include <tee/tee_cryp_utl.h>
12*17c68af4SJens Wiklander #include <util.h>
13*17c68af4SJens Wiklander 
14*17c68af4SJens Wiklander 
15*17c68af4SJens Wiklander /* From libtomcrypt doc:
16*17c68af4SJens Wiklander  *	Ciphertext stealing is a method of dealing with messages
17*17c68af4SJens Wiklander  *	in CBC mode which are not a multiple of the block
18*17c68af4SJens Wiklander  *	length.  This is accomplished by encrypting the last
19*17c68af4SJens Wiklander  *	ciphertext block in ECB mode, and XOR'ing the output
20*17c68af4SJens Wiklander  *	against the last partial block of plaintext. LibTomCrypt
21*17c68af4SJens Wiklander  *	does not support this mode directly but it is fairly
22*17c68af4SJens Wiklander  *	easy to emulate with a call to the cipher's
23*17c68af4SJens Wiklander  *	ecb encrypt() callback function.
24*17c68af4SJens Wiklander  *	The more sane way to deal with partial blocks is to pad
25*17c68af4SJens Wiklander  *	them with zeroes, and then use CBC normally
26*17c68af4SJens Wiklander  */
27*17c68af4SJens Wiklander 
28*17c68af4SJens Wiklander /*
29*17c68af4SJens Wiklander  * From Global Platform: CTS = CBC-CS3
30*17c68af4SJens Wiklander  */
31*17c68af4SJens Wiklander 
32*17c68af4SJens Wiklander struct cts_ctx {
33*17c68af4SJens Wiklander 	struct crypto_cipher_ctx ctx;
34*17c68af4SJens Wiklander 	struct crypto_cipher_ctx *ecb;
35*17c68af4SJens Wiklander 	struct crypto_cipher_ctx *cbc;
36*17c68af4SJens Wiklander 	TEE_OperationMode mode;
37*17c68af4SJens Wiklander };
38*17c68af4SJens Wiklander 
39*17c68af4SJens Wiklander static const struct crypto_cipher_ops cts_ops;
40*17c68af4SJens Wiklander 
41*17c68af4SJens Wiklander static struct cts_ctx *to_cts_ctx(struct crypto_cipher_ctx *ctx)
42*17c68af4SJens Wiklander {
43*17c68af4SJens Wiklander 	assert(ctx && ctx->ops == &cts_ops);
44*17c68af4SJens Wiklander 
45*17c68af4SJens Wiklander 	return container_of(ctx, struct cts_ctx, ctx);
46*17c68af4SJens Wiklander }
47*17c68af4SJens Wiklander 
48*17c68af4SJens Wiklander static TEE_Result cts_init(struct crypto_cipher_ctx *ctx,
49*17c68af4SJens Wiklander 			   TEE_OperationMode mode, const uint8_t *key1,
50*17c68af4SJens Wiklander 			   size_t key1_len, const uint8_t *key2,
51*17c68af4SJens Wiklander 			   size_t key2_len, const uint8_t *iv, size_t iv_len)
52*17c68af4SJens Wiklander {
53*17c68af4SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
54*17c68af4SJens Wiklander 	struct cts_ctx *c = to_cts_ctx(ctx);
55*17c68af4SJens Wiklander 
56*17c68af4SJens Wiklander 	c->mode = mode;
57*17c68af4SJens Wiklander 
58*17c68af4SJens Wiklander 	res = crypto_cipher_init(c->ecb, TEE_ALG_AES_ECB_NOPAD, mode, key1,
59*17c68af4SJens Wiklander 				 key1_len, key2, key2_len, iv, iv_len);
60*17c68af4SJens Wiklander 	if (res)
61*17c68af4SJens Wiklander 		return res;
62*17c68af4SJens Wiklander 
63*17c68af4SJens Wiklander 	return crypto_cipher_init(c->cbc, TEE_ALG_AES_CBC_NOPAD, mode, key1,
64*17c68af4SJens Wiklander 				  key1_len, key2, key2_len, iv, iv_len);
65*17c68af4SJens Wiklander }
66*17c68af4SJens Wiklander 
67*17c68af4SJens Wiklander static TEE_Result cts_update(struct crypto_cipher_ctx *ctx, bool last_block,
68*17c68af4SJens Wiklander 			     const uint8_t *data, size_t len, uint8_t *dst)
69*17c68af4SJens Wiklander {
70*17c68af4SJens Wiklander 	struct cts_ctx *c = to_cts_ctx(ctx);
71*17c68af4SJens Wiklander 
72*17c68af4SJens Wiklander 	return tee_aes_cbc_cts_update(c->cbc, c->ecb, c->mode, last_block,
73*17c68af4SJens Wiklander 				      data, len, dst);
74*17c68af4SJens Wiklander }
75*17c68af4SJens Wiklander 
76*17c68af4SJens Wiklander static void cts_final(struct crypto_cipher_ctx *ctx)
77*17c68af4SJens Wiklander {
78*17c68af4SJens Wiklander 	struct cts_ctx *c = to_cts_ctx(ctx);
79*17c68af4SJens Wiklander 
80*17c68af4SJens Wiklander 	crypto_cipher_final(c->cbc, TEE_ALG_AES_CBC_NOPAD);
81*17c68af4SJens Wiklander 	crypto_cipher_final(c->ecb, TEE_ALG_AES_ECB_NOPAD);
82*17c68af4SJens Wiklander }
83*17c68af4SJens Wiklander 
84*17c68af4SJens Wiklander static void cts_free_ctx(struct crypto_cipher_ctx *ctx)
85*17c68af4SJens Wiklander {
86*17c68af4SJens Wiklander 	struct cts_ctx *c = to_cts_ctx(ctx);
87*17c68af4SJens Wiklander 
88*17c68af4SJens Wiklander 	crypto_cipher_free_ctx(c->cbc, TEE_ALG_AES_CBC_NOPAD);
89*17c68af4SJens Wiklander 	crypto_cipher_free_ctx(c->ecb, TEE_ALG_AES_ECB_NOPAD);
90*17c68af4SJens Wiklander 	free(c);
91*17c68af4SJens Wiklander }
92*17c68af4SJens Wiklander 
93*17c68af4SJens Wiklander static void cts_copy_state(struct crypto_cipher_ctx *dst_ctx,
94*17c68af4SJens Wiklander 			   struct crypto_cipher_ctx *src_ctx)
95*17c68af4SJens Wiklander {
96*17c68af4SJens Wiklander 	struct cts_ctx *src = to_cts_ctx(src_ctx);
97*17c68af4SJens Wiklander 	struct cts_ctx *dst = to_cts_ctx(dst_ctx);
98*17c68af4SJens Wiklander 
99*17c68af4SJens Wiklander 	crypto_cipher_copy_state(dst->cbc, src->cbc, TEE_ALG_AES_CBC_NOPAD);
100*17c68af4SJens Wiklander 	crypto_cipher_copy_state(dst->ecb, src->ecb, TEE_ALG_AES_ECB_NOPAD);
101*17c68af4SJens Wiklander }
102*17c68af4SJens Wiklander 
103*17c68af4SJens Wiklander static const struct crypto_cipher_ops cts_ops = {
104*17c68af4SJens Wiklander 	.init = cts_init,
105*17c68af4SJens Wiklander 	.update = cts_update,
106*17c68af4SJens Wiklander 	.final = cts_final,
107*17c68af4SJens Wiklander 	.free_ctx = cts_free_ctx,
108*17c68af4SJens Wiklander 	.copy_state = cts_copy_state,
109*17c68af4SJens Wiklander };
110*17c68af4SJens Wiklander 
111*17c68af4SJens Wiklander TEE_Result crypto_aes_cts_alloc_ctx(struct crypto_cipher_ctx **ctx)
112*17c68af4SJens Wiklander {
113*17c68af4SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
114*17c68af4SJens Wiklander 	struct cts_ctx *c = calloc(1, sizeof(*c));
115*17c68af4SJens Wiklander 
116*17c68af4SJens Wiklander 	if (!c)
117*17c68af4SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
118*17c68af4SJens Wiklander 
119*17c68af4SJens Wiklander 	res = crypto_aes_ecb_alloc_ctx(&c->ecb);
120*17c68af4SJens Wiklander 	if (res)
121*17c68af4SJens Wiklander 		goto err;
122*17c68af4SJens Wiklander 	res = crypto_aes_cbc_alloc_ctx(&c->cbc);
123*17c68af4SJens Wiklander 	if (res)
124*17c68af4SJens Wiklander 		goto err;
125*17c68af4SJens Wiklander 
126*17c68af4SJens Wiklander 	c->ctx.ops = &cts_ops;
127*17c68af4SJens Wiklander 	*ctx = &c->ctx;
128*17c68af4SJens Wiklander 
129*17c68af4SJens Wiklander 	return TEE_SUCCESS;
130*17c68af4SJens Wiklander err:
131*17c68af4SJens Wiklander 	crypto_cipher_free_ctx(c->ecb, TEE_ALG_AES_ECB_NOPAD);
132*17c68af4SJens Wiklander 	free(c);
133*17c68af4SJens Wiklander 
134*17c68af4SJens Wiklander 	return res;
135*17c68af4SJens Wiklander }
136