xref: /optee_os/core/crypto/cbc-mac.c (revision 5da36a2473928a821089a37f8d0ca585e7a7cfcc)
1*5da36a24SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*5da36a24SJens Wiklander /*
3*5da36a24SJens Wiklander  * Copyright (c) 2014-2019, Linaro Limited
4*5da36a24SJens Wiklander  */
5*5da36a24SJens Wiklander 
6*5da36a24SJens Wiklander /*
7*5da36a24SJens Wiklander  * This is implemented here as being the plain text which is encoded with IV=0.
8*5da36a24SJens Wiklander  * Result of the CBC-MAC is the last 16-bytes cipher.
9*5da36a24SJens Wiklander  */
10*5da36a24SJens Wiklander 
11*5da36a24SJens Wiklander #include <assert.h>
12*5da36a24SJens Wiklander #include <crypto/crypto.h>
13*5da36a24SJens Wiklander #include <crypto/crypto_impl.h>
14*5da36a24SJens Wiklander #include <stdlib.h>
15*5da36a24SJens Wiklander #include <string.h>
16*5da36a24SJens Wiklander #include <types_ext.h>
17*5da36a24SJens Wiklander #include <util.h>
18*5da36a24SJens Wiklander 
19*5da36a24SJens Wiklander #define CBCMAC_MAX_BLOCK_LEN 16
20*5da36a24SJens Wiklander 
21*5da36a24SJens Wiklander struct crypto_cbc_mac_ctx {
22*5da36a24SJens Wiklander 	struct crypto_mac_ctx ctx;
23*5da36a24SJens Wiklander 	void *cbc_ctx;
24*5da36a24SJens Wiklander 	uint32_t cbc_algo;
25*5da36a24SJens Wiklander 	uint8_t block[CBCMAC_MAX_BLOCK_LEN];
26*5da36a24SJens Wiklander 	uint8_t digest[CBCMAC_MAX_BLOCK_LEN];
27*5da36a24SJens Wiklander 	unsigned char current_block_len;
28*5da36a24SJens Wiklander 	unsigned char block_len;
29*5da36a24SJens Wiklander 	bool is_computed;
30*5da36a24SJens Wiklander 	bool pkcs5_pad;
31*5da36a24SJens Wiklander };
32*5da36a24SJens Wiklander 
33*5da36a24SJens Wiklander static const struct crypto_mac_ops crypto_cbc_mac_ops;
34*5da36a24SJens Wiklander 
35*5da36a24SJens Wiklander static struct crypto_cbc_mac_ctx *to_cbc_mac_ctx(struct crypto_mac_ctx *ctx)
36*5da36a24SJens Wiklander {
37*5da36a24SJens Wiklander 	assert(ctx && ctx->ops == &crypto_cbc_mac_ops);
38*5da36a24SJens Wiklander 
39*5da36a24SJens Wiklander 	return container_of(ctx, struct crypto_cbc_mac_ctx, ctx);
40*5da36a24SJens Wiklander }
41*5da36a24SJens Wiklander 
42*5da36a24SJens Wiklander static TEE_Result crypto_cbc_mac_init(struct crypto_mac_ctx *ctx,
43*5da36a24SJens Wiklander 				      const uint8_t *key, size_t len)
44*5da36a24SJens Wiklander {
45*5da36a24SJens Wiklander 	struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx);
46*5da36a24SJens Wiklander 
47*5da36a24SJens Wiklander 	memset(mc->block, 0, sizeof(mc->block));
48*5da36a24SJens Wiklander 	memset(mc->digest, 0, sizeof(mc->digest));
49*5da36a24SJens Wiklander 	mc->current_block_len = 0;
50*5da36a24SJens Wiklander 	mc->is_computed = false;
51*5da36a24SJens Wiklander 
52*5da36a24SJens Wiklander 	/* IV should be zero and mc->block happens to be zero at this stage */
53*5da36a24SJens Wiklander 	return crypto_cipher_init(mc->cbc_ctx, mc->cbc_algo, TEE_MODE_ENCRYPT,
54*5da36a24SJens Wiklander 				  key, len, NULL, 0, mc->block, mc->block_len);
55*5da36a24SJens Wiklander }
56*5da36a24SJens Wiklander 
57*5da36a24SJens Wiklander static TEE_Result crypto_cbc_mac_update(struct crypto_mac_ctx *ctx,
58*5da36a24SJens Wiklander 					const uint8_t *data, size_t len)
59*5da36a24SJens Wiklander {
60*5da36a24SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
61*5da36a24SJens Wiklander 	struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx);
62*5da36a24SJens Wiklander 
63*5da36a24SJens Wiklander 	if ((mc->current_block_len > 0) &&
64*5da36a24SJens Wiklander 	    (len + mc->current_block_len >= mc->block_len)) {
65*5da36a24SJens Wiklander 		size_t pad_len = mc->block_len - mc->current_block_len;
66*5da36a24SJens Wiklander 
67*5da36a24SJens Wiklander 		memcpy(mc->block + mc->current_block_len, data, pad_len);
68*5da36a24SJens Wiklander 		data += pad_len;
69*5da36a24SJens Wiklander 		len -= pad_len;
70*5da36a24SJens Wiklander 		res = crypto_cipher_update(mc->cbc_ctx, mc->cbc_algo,
71*5da36a24SJens Wiklander 					   TEE_MODE_ENCRYPT, false, mc->block,
72*5da36a24SJens Wiklander 					   mc->block_len, mc->digest);
73*5da36a24SJens Wiklander 		if (res)
74*5da36a24SJens Wiklander 			return res;
75*5da36a24SJens Wiklander 		mc->is_computed = 1;
76*5da36a24SJens Wiklander 		mc->current_block_len = 0;
77*5da36a24SJens Wiklander 	}
78*5da36a24SJens Wiklander 
79*5da36a24SJens Wiklander 	while (len >= mc->block_len) {
80*5da36a24SJens Wiklander 		res = crypto_cipher_update(mc->cbc_ctx, mc->cbc_algo,
81*5da36a24SJens Wiklander 					   TEE_MODE_ENCRYPT, false, data,
82*5da36a24SJens Wiklander 					   mc->block_len, mc->digest);
83*5da36a24SJens Wiklander 		if (res)
84*5da36a24SJens Wiklander 			return res;
85*5da36a24SJens Wiklander 		mc->is_computed = 1;
86*5da36a24SJens Wiklander 		data += mc->block_len;
87*5da36a24SJens Wiklander 		len -= mc->block_len;
88*5da36a24SJens Wiklander 	}
89*5da36a24SJens Wiklander 
90*5da36a24SJens Wiklander 	if (len > 0) {
91*5da36a24SJens Wiklander 		assert(mc->current_block_len + len < mc->block_len);
92*5da36a24SJens Wiklander 		memcpy(mc->block + mc->current_block_len, data, len);
93*5da36a24SJens Wiklander 		mc->current_block_len += len;
94*5da36a24SJens Wiklander 	}
95*5da36a24SJens Wiklander 
96*5da36a24SJens Wiklander 	return TEE_SUCCESS;
97*5da36a24SJens Wiklander }
98*5da36a24SJens Wiklander 
99*5da36a24SJens Wiklander static TEE_Result crypto_cbc_mac_final(struct crypto_mac_ctx *ctx,
100*5da36a24SJens Wiklander 				       uint8_t *digest, size_t digest_len)
101*5da36a24SJens Wiklander {
102*5da36a24SJens Wiklander 	struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx);
103*5da36a24SJens Wiklander 
104*5da36a24SJens Wiklander 	if (mc->pkcs5_pad) {
105*5da36a24SJens Wiklander 		/*
106*5da36a24SJens Wiklander 		 * Padding is in whole bytes. The value of each added
107*5da36a24SJens Wiklander 		 * byte is the number of bytes that are added, i.e. N
108*5da36a24SJens Wiklander 		 * bytes, each of value N are added
109*5da36a24SJens Wiklander 		 */
110*5da36a24SJens Wiklander 		size_t pad_len = mc->block_len - mc->current_block_len;
111*5da36a24SJens Wiklander 
112*5da36a24SJens Wiklander 		memset(mc->block + mc->current_block_len, pad_len, pad_len);
113*5da36a24SJens Wiklander 		mc->current_block_len = 0;
114*5da36a24SJens Wiklander 		if (crypto_cbc_mac_update(ctx, mc->block, mc->block_len))
115*5da36a24SJens Wiklander 			return TEE_ERROR_BAD_STATE;
116*5da36a24SJens Wiklander 	}
117*5da36a24SJens Wiklander 
118*5da36a24SJens Wiklander 	if (!mc->is_computed || mc->current_block_len)
119*5da36a24SJens Wiklander 		return TEE_ERROR_BAD_STATE;
120*5da36a24SJens Wiklander 
121*5da36a24SJens Wiklander 	memcpy(digest, mc->digest, MIN(digest_len, mc->block_len));
122*5da36a24SJens Wiklander 	crypto_cipher_final(mc->cbc_ctx, mc->cbc_algo);
123*5da36a24SJens Wiklander 
124*5da36a24SJens Wiklander 	return TEE_SUCCESS;
125*5da36a24SJens Wiklander }
126*5da36a24SJens Wiklander 
127*5da36a24SJens Wiklander static void crypto_cbc_mac_free_ctx(struct crypto_mac_ctx *ctx)
128*5da36a24SJens Wiklander {
129*5da36a24SJens Wiklander 	struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx);
130*5da36a24SJens Wiklander 
131*5da36a24SJens Wiklander 	crypto_cipher_free_ctx(mc->cbc_ctx, mc->cbc_algo);
132*5da36a24SJens Wiklander 	free(mc);
133*5da36a24SJens Wiklander }
134*5da36a24SJens Wiklander 
135*5da36a24SJens Wiklander static void crypto_cbc_mac_copy_state(struct crypto_mac_ctx *dst_ctx,
136*5da36a24SJens Wiklander 				      struct crypto_mac_ctx *src_ctx)
137*5da36a24SJens Wiklander {
138*5da36a24SJens Wiklander 	struct crypto_cbc_mac_ctx *dst = to_cbc_mac_ctx(dst_ctx);
139*5da36a24SJens Wiklander 	struct crypto_cbc_mac_ctx *src = to_cbc_mac_ctx(src_ctx);
140*5da36a24SJens Wiklander 
141*5da36a24SJens Wiklander 	assert(dst->block_len == src->block_len);
142*5da36a24SJens Wiklander 	assert(dst->pkcs5_pad == src->pkcs5_pad);
143*5da36a24SJens Wiklander 	assert(dst->cbc_algo == src->cbc_algo);
144*5da36a24SJens Wiklander 
145*5da36a24SJens Wiklander 	crypto_cipher_copy_state(dst->cbc_ctx, src->cbc_ctx, src->cbc_algo);
146*5da36a24SJens Wiklander 	memcpy(dst->block, src->block, sizeof(dst->block));
147*5da36a24SJens Wiklander 	memcpy(dst->digest, src->digest, sizeof(dst->digest));
148*5da36a24SJens Wiklander 	dst->current_block_len = src->current_block_len;
149*5da36a24SJens Wiklander 	dst->is_computed = src->is_computed;
150*5da36a24SJens Wiklander }
151*5da36a24SJens Wiklander 
152*5da36a24SJens Wiklander static const struct crypto_mac_ops crypto_cbc_mac_ops = {
153*5da36a24SJens Wiklander 	.init = crypto_cbc_mac_init,
154*5da36a24SJens Wiklander 	.update = crypto_cbc_mac_update,
155*5da36a24SJens Wiklander 	.final = crypto_cbc_mac_final,
156*5da36a24SJens Wiklander 	.free_ctx = crypto_cbc_mac_free_ctx,
157*5da36a24SJens Wiklander 	.copy_state = crypto_cbc_mac_copy_state,
158*5da36a24SJens Wiklander };
159*5da36a24SJens Wiklander 
160*5da36a24SJens Wiklander static TEE_Result crypto_cbc_mac_alloc_ctx(struct crypto_mac_ctx **ctx_ret,
161*5da36a24SJens Wiklander 					   uint32_t cbc_algo, bool pkcs5_pad)
162*5da36a24SJens Wiklander {
163*5da36a24SJens Wiklander 	TEE_Result res;
164*5da36a24SJens Wiklander 	void *cbc_ctx = NULL;
165*5da36a24SJens Wiklander 	struct crypto_cbc_mac_ctx *ctx = NULL;
166*5da36a24SJens Wiklander 	size_t block_size = 0;
167*5da36a24SJens Wiklander 
168*5da36a24SJens Wiklander 	res = crypto_cipher_get_block_size(cbc_algo, &block_size);
169*5da36a24SJens Wiklander 	if (res)
170*5da36a24SJens Wiklander 		return res;
171*5da36a24SJens Wiklander 
172*5da36a24SJens Wiklander 	res = crypto_cipher_alloc_ctx(&cbc_ctx, cbc_algo);
173*5da36a24SJens Wiklander 	if (res)
174*5da36a24SJens Wiklander 		return res;
175*5da36a24SJens Wiklander 
176*5da36a24SJens Wiklander 	ctx = calloc(1, sizeof(*ctx));
177*5da36a24SJens Wiklander 	if (!ctx) {
178*5da36a24SJens Wiklander 		crypto_cipher_free_ctx(cbc_ctx, cbc_algo);
179*5da36a24SJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
180*5da36a24SJens Wiklander 	}
181*5da36a24SJens Wiklander 
182*5da36a24SJens Wiklander 	ctx->cbc_ctx = cbc_ctx;
183*5da36a24SJens Wiklander 	ctx->cbc_algo = cbc_algo;
184*5da36a24SJens Wiklander 	ctx->pkcs5_pad = pkcs5_pad;
185*5da36a24SJens Wiklander 	ctx->block_len = block_size;
186*5da36a24SJens Wiklander 	ctx->ctx.ops = &crypto_cbc_mac_ops;
187*5da36a24SJens Wiklander 	*ctx_ret = &ctx->ctx;
188*5da36a24SJens Wiklander 
189*5da36a24SJens Wiklander 	return TEE_SUCCESS;
190*5da36a24SJens Wiklander }
191*5da36a24SJens Wiklander 
192*5da36a24SJens Wiklander TEE_Result crypto_aes_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx)
193*5da36a24SJens Wiklander {
194*5da36a24SJens Wiklander 	return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_AES_CBC_NOPAD, false);
195*5da36a24SJens Wiklander }
196*5da36a24SJens Wiklander 
197*5da36a24SJens Wiklander TEE_Result crypto_aes_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx)
198*5da36a24SJens Wiklander {
199*5da36a24SJens Wiklander 	return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_AES_CBC_NOPAD, true);
200*5da36a24SJens Wiklander }
201*5da36a24SJens Wiklander 
202*5da36a24SJens Wiklander TEE_Result crypto_des_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx)
203*5da36a24SJens Wiklander {
204*5da36a24SJens Wiklander 	return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES_CBC_NOPAD, false);
205*5da36a24SJens Wiklander }
206*5da36a24SJens Wiklander 
207*5da36a24SJens Wiklander TEE_Result crypto_des_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx)
208*5da36a24SJens Wiklander {
209*5da36a24SJens Wiklander 	return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES_CBC_NOPAD, true);
210*5da36a24SJens Wiklander }
211*5da36a24SJens Wiklander 
212*5da36a24SJens Wiklander TEE_Result crypto_des3_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx)
213*5da36a24SJens Wiklander {
214*5da36a24SJens Wiklander 	return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES3_CBC_NOPAD, false);
215*5da36a24SJens Wiklander }
216*5da36a24SJens Wiklander 
217*5da36a24SJens Wiklander TEE_Result crypto_des3_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx)
218*5da36a24SJens Wiklander {
219*5da36a24SJens Wiklander 	return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES3_CBC_NOPAD, true);
220*5da36a24SJens Wiklander }
221