xref: /optee_os/core/lib/libtomcrypt/ccm.c (revision f1e9b21b29bdc21a51c6c1a4b8df7eb5e2bd5189)
1*f1e9b21bSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*f1e9b21bSJens Wiklander /*
3*f1e9b21bSJens Wiklander  * Copyright (c) 2014-2019, Linaro Limited
4*f1e9b21bSJens Wiklander  */
5*f1e9b21bSJens Wiklander 
6*f1e9b21bSJens Wiklander #include <assert.h>
7*f1e9b21bSJens Wiklander #include <crypto/crypto.h>
8*f1e9b21bSJens Wiklander #include <crypto/crypto_impl.h>
9*f1e9b21bSJens Wiklander #include <stdlib.h>
10*f1e9b21bSJens Wiklander #include <string.h>
11*f1e9b21bSJens Wiklander #include <tee_api_types.h>
12*f1e9b21bSJens Wiklander #include <tomcrypt.h>
13*f1e9b21bSJens Wiklander #include <util.h>
14*f1e9b21bSJens Wiklander 
15*f1e9b21bSJens Wiklander #define TEE_CCM_KEY_MAX_LENGTH		32
16*f1e9b21bSJens Wiklander #define TEE_CCM_NONCE_MAX_LENGTH	13
17*f1e9b21bSJens Wiklander #define TEE_CCM_TAG_MAX_LENGTH		16
18*f1e9b21bSJens Wiklander 
19*f1e9b21bSJens Wiklander struct tee_ccm_state {
20*f1e9b21bSJens Wiklander 	struct crypto_authenc_ctx aectx;
21*f1e9b21bSJens Wiklander 	ccm_state ctx;			/* the ccm state as defined by LTC */
22*f1e9b21bSJens Wiklander 	size_t tag_len;			/* tag length */
23*f1e9b21bSJens Wiklander };
24*f1e9b21bSJens Wiklander 
25*f1e9b21bSJens Wiklander static const struct crypto_authenc_ops aes_ccm_ops;
26*f1e9b21bSJens Wiklander 
27*f1e9b21bSJens Wiklander TEE_Result crypto_aes_ccm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret)
28*f1e9b21bSJens Wiklander {
29*f1e9b21bSJens Wiklander 	struct tee_ccm_state *ctx = calloc(1, sizeof(*ctx));
30*f1e9b21bSJens Wiklander 
31*f1e9b21bSJens Wiklander 	if (!ctx)
32*f1e9b21bSJens Wiklander 		return TEE_ERROR_OUT_OF_MEMORY;
33*f1e9b21bSJens Wiklander 	ctx->aectx.ops = &aes_ccm_ops;
34*f1e9b21bSJens Wiklander 
35*f1e9b21bSJens Wiklander 	*ctx_ret = &ctx->aectx;
36*f1e9b21bSJens Wiklander 	return TEE_SUCCESS;
37*f1e9b21bSJens Wiklander }
38*f1e9b21bSJens Wiklander 
39*f1e9b21bSJens Wiklander static struct tee_ccm_state *to_tee_ccm_state(struct crypto_authenc_ctx *aectx)
40*f1e9b21bSJens Wiklander {
41*f1e9b21bSJens Wiklander 	assert(aectx && aectx->ops == &aes_ccm_ops);
42*f1e9b21bSJens Wiklander 
43*f1e9b21bSJens Wiklander 	return container_of(aectx, struct tee_ccm_state, aectx);
44*f1e9b21bSJens Wiklander }
45*f1e9b21bSJens Wiklander 
46*f1e9b21bSJens Wiklander static void crypto_aes_ccm_free_ctx(struct crypto_authenc_ctx *aectx)
47*f1e9b21bSJens Wiklander {
48*f1e9b21bSJens Wiklander 	free(to_tee_ccm_state(aectx));
49*f1e9b21bSJens Wiklander }
50*f1e9b21bSJens Wiklander 
51*f1e9b21bSJens Wiklander static void crypto_aes_ccm_copy_state(struct crypto_authenc_ctx *dst_aectx,
52*f1e9b21bSJens Wiklander 				      struct crypto_authenc_ctx *src_aectx)
53*f1e9b21bSJens Wiklander {
54*f1e9b21bSJens Wiklander 	struct tee_ccm_state *dst_ctx = to_tee_ccm_state(dst_aectx);
55*f1e9b21bSJens Wiklander 	struct tee_ccm_state *src_ctx = to_tee_ccm_state(src_aectx);
56*f1e9b21bSJens Wiklander 
57*f1e9b21bSJens Wiklander 	dst_ctx->ctx = src_ctx->ctx;
58*f1e9b21bSJens Wiklander 	dst_ctx->tag_len = src_ctx->tag_len;
59*f1e9b21bSJens Wiklander }
60*f1e9b21bSJens Wiklander 
61*f1e9b21bSJens Wiklander static TEE_Result crypto_aes_ccm_init(struct crypto_authenc_ctx *aectx,
62*f1e9b21bSJens Wiklander 				      TEE_OperationMode mode __unused,
63*f1e9b21bSJens Wiklander 				      const uint8_t *key, size_t key_len,
64*f1e9b21bSJens Wiklander 				      const uint8_t *nonce, size_t nonce_len,
65*f1e9b21bSJens Wiklander 				      size_t tag_len, size_t aad_len,
66*f1e9b21bSJens Wiklander 				      size_t payload_len)
67*f1e9b21bSJens Wiklander {
68*f1e9b21bSJens Wiklander 	int ltc_res = 0;
69*f1e9b21bSJens Wiklander 	int ltc_cipherindex = find_cipher("aes");
70*f1e9b21bSJens Wiklander 	struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
71*f1e9b21bSJens Wiklander 
72*f1e9b21bSJens Wiklander 	if (ltc_cipherindex < 0)
73*f1e9b21bSJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
74*f1e9b21bSJens Wiklander 
75*f1e9b21bSJens Wiklander 	/* reset the state */
76*f1e9b21bSJens Wiklander 	memset(&ccm->ctx, 0, sizeof(ccm->ctx));
77*f1e9b21bSJens Wiklander 	ccm->tag_len = tag_len;
78*f1e9b21bSJens Wiklander 
79*f1e9b21bSJens Wiklander 	/* Check the key length */
80*f1e9b21bSJens Wiklander 	if ((!key) || (key_len > TEE_CCM_KEY_MAX_LENGTH))
81*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
82*f1e9b21bSJens Wiklander 
83*f1e9b21bSJens Wiklander 	/* check the nonce */
84*f1e9b21bSJens Wiklander 	if (nonce_len > TEE_CCM_NONCE_MAX_LENGTH)
85*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
86*f1e9b21bSJens Wiklander 
87*f1e9b21bSJens Wiklander 	/* check the tag len */
88*f1e9b21bSJens Wiklander 	if ((tag_len < 4) || (tag_len > TEE_CCM_TAG_MAX_LENGTH) ||
89*f1e9b21bSJens Wiklander 	    (tag_len % 2 != 0))
90*f1e9b21bSJens Wiklander 		return TEE_ERROR_NOT_SUPPORTED;
91*f1e9b21bSJens Wiklander 
92*f1e9b21bSJens Wiklander 	ltc_res = ccm_init(&ccm->ctx, ltc_cipherindex, key, key_len,
93*f1e9b21bSJens Wiklander 			   payload_len, tag_len, aad_len);
94*f1e9b21bSJens Wiklander 	if (ltc_res != CRYPT_OK)
95*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_STATE;
96*f1e9b21bSJens Wiklander 
97*f1e9b21bSJens Wiklander 	/* Add the IV */
98*f1e9b21bSJens Wiklander 	ltc_res = ccm_add_nonce(&ccm->ctx, nonce, nonce_len);
99*f1e9b21bSJens Wiklander 	if (ltc_res != CRYPT_OK)
100*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_STATE;
101*f1e9b21bSJens Wiklander 
102*f1e9b21bSJens Wiklander 	return TEE_SUCCESS;
103*f1e9b21bSJens Wiklander }
104*f1e9b21bSJens Wiklander 
105*f1e9b21bSJens Wiklander static TEE_Result crypto_aes_ccm_update_aad(struct crypto_authenc_ctx *aectx,
106*f1e9b21bSJens Wiklander 					    const uint8_t *data, size_t len)
107*f1e9b21bSJens Wiklander {
108*f1e9b21bSJens Wiklander 	struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
109*f1e9b21bSJens Wiklander 	int ltc_res = 0;
110*f1e9b21bSJens Wiklander 
111*f1e9b21bSJens Wiklander 	/* Add the AAD (note: aad can be NULL if aadlen == 0) */
112*f1e9b21bSJens Wiklander 	ltc_res = ccm_add_aad(&ccm->ctx, data, len);
113*f1e9b21bSJens Wiklander 	if (ltc_res != CRYPT_OK)
114*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_STATE;
115*f1e9b21bSJens Wiklander 
116*f1e9b21bSJens Wiklander 	return TEE_SUCCESS;
117*f1e9b21bSJens Wiklander }
118*f1e9b21bSJens Wiklander 
119*f1e9b21bSJens Wiklander static TEE_Result
120*f1e9b21bSJens Wiklander crypto_aes_ccm_update_payload(struct crypto_authenc_ctx *aectx,
121*f1e9b21bSJens Wiklander 			      TEE_OperationMode mode, const uint8_t *src_data,
122*f1e9b21bSJens Wiklander 			      size_t len, uint8_t *dst_data)
123*f1e9b21bSJens Wiklander {
124*f1e9b21bSJens Wiklander 	int ltc_res = 0;
125*f1e9b21bSJens Wiklander 	int dir = 0;
126*f1e9b21bSJens Wiklander 	struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
127*f1e9b21bSJens Wiklander 	unsigned char *pt = NULL;
128*f1e9b21bSJens Wiklander 	unsigned char *ct = NULL;
129*f1e9b21bSJens Wiklander 
130*f1e9b21bSJens Wiklander 	if (mode == TEE_MODE_ENCRYPT) {
131*f1e9b21bSJens Wiklander 		pt = (unsigned char *)src_data;
132*f1e9b21bSJens Wiklander 		ct = dst_data;
133*f1e9b21bSJens Wiklander 		dir = CCM_ENCRYPT;
134*f1e9b21bSJens Wiklander 	} else {
135*f1e9b21bSJens Wiklander 		pt = dst_data;
136*f1e9b21bSJens Wiklander 		ct = (unsigned char *)src_data;
137*f1e9b21bSJens Wiklander 		dir = CCM_DECRYPT;
138*f1e9b21bSJens Wiklander 	}
139*f1e9b21bSJens Wiklander 	ltc_res = ccm_process(&ccm->ctx, pt, len, ct, dir);
140*f1e9b21bSJens Wiklander 	if (ltc_res != CRYPT_OK)
141*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_STATE;
142*f1e9b21bSJens Wiklander 
143*f1e9b21bSJens Wiklander 	return TEE_SUCCESS;
144*f1e9b21bSJens Wiklander }
145*f1e9b21bSJens Wiklander 
146*f1e9b21bSJens Wiklander static TEE_Result crypto_aes_ccm_enc_final(struct crypto_authenc_ctx *aectx,
147*f1e9b21bSJens Wiklander 					   const uint8_t *src_data,
148*f1e9b21bSJens Wiklander 					   size_t len, uint8_t *dst_data,
149*f1e9b21bSJens Wiklander 					   uint8_t *dst_tag,
150*f1e9b21bSJens Wiklander 					   size_t *dst_tag_len)
151*f1e9b21bSJens Wiklander {
152*f1e9b21bSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
153*f1e9b21bSJens Wiklander 	struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
154*f1e9b21bSJens Wiklander 	int ltc_res = 0;
155*f1e9b21bSJens Wiklander 
156*f1e9b21bSJens Wiklander 	/* Finalize the remaining buffer */
157*f1e9b21bSJens Wiklander 	res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data,
158*f1e9b21bSJens Wiklander 					    len, dst_data);
159*f1e9b21bSJens Wiklander 	if (res != TEE_SUCCESS)
160*f1e9b21bSJens Wiklander 		return res;
161*f1e9b21bSJens Wiklander 
162*f1e9b21bSJens Wiklander 	/* Check the tag length */
163*f1e9b21bSJens Wiklander 	if (*dst_tag_len < ccm->tag_len) {
164*f1e9b21bSJens Wiklander 		*dst_tag_len = ccm->tag_len;
165*f1e9b21bSJens Wiklander 		return TEE_ERROR_SHORT_BUFFER;
166*f1e9b21bSJens Wiklander 	}
167*f1e9b21bSJens Wiklander 	*dst_tag_len = ccm->tag_len;
168*f1e9b21bSJens Wiklander 
169*f1e9b21bSJens Wiklander 	/* Compute the tag */
170*f1e9b21bSJens Wiklander 	ltc_res = ccm_done(&ccm->ctx, dst_tag,
171*f1e9b21bSJens Wiklander 			   (unsigned long *)dst_tag_len);
172*f1e9b21bSJens Wiklander 	if (ltc_res != CRYPT_OK)
173*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_STATE;
174*f1e9b21bSJens Wiklander 
175*f1e9b21bSJens Wiklander 	return TEE_SUCCESS;
176*f1e9b21bSJens Wiklander }
177*f1e9b21bSJens Wiklander 
178*f1e9b21bSJens Wiklander static TEE_Result crypto_aes_ccm_dec_final(struct crypto_authenc_ctx *aectx,
179*f1e9b21bSJens Wiklander 					   const uint8_t *src_data, size_t len,
180*f1e9b21bSJens Wiklander 					   uint8_t *dst_data,
181*f1e9b21bSJens Wiklander 					   const uint8_t *tag, size_t tag_len)
182*f1e9b21bSJens Wiklander {
183*f1e9b21bSJens Wiklander 	TEE_Result res = TEE_ERROR_BAD_STATE;
184*f1e9b21bSJens Wiklander 	struct tee_ccm_state *ccm = to_tee_ccm_state(aectx);
185*f1e9b21bSJens Wiklander 	int ltc_res = 0;
186*f1e9b21bSJens Wiklander 	uint8_t dst_tag[TEE_CCM_TAG_MAX_LENGTH] = { 0 };
187*f1e9b21bSJens Wiklander 	unsigned long ltc_tag_len = tag_len;
188*f1e9b21bSJens Wiklander 
189*f1e9b21bSJens Wiklander 	if (tag_len == 0)
190*f1e9b21bSJens Wiklander 		return TEE_ERROR_SHORT_BUFFER;
191*f1e9b21bSJens Wiklander 	if (tag_len > TEE_CCM_TAG_MAX_LENGTH)
192*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_STATE;
193*f1e9b21bSJens Wiklander 
194*f1e9b21bSJens Wiklander 	/* Process the last buffer, if any */
195*f1e9b21bSJens Wiklander 	res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_DECRYPT, src_data,
196*f1e9b21bSJens Wiklander 					    len, dst_data);
197*f1e9b21bSJens Wiklander 	if (res != TEE_SUCCESS)
198*f1e9b21bSJens Wiklander 		return res;
199*f1e9b21bSJens Wiklander 
200*f1e9b21bSJens Wiklander 	/* Finalize the authentication */
201*f1e9b21bSJens Wiklander 	ltc_res = ccm_done(&ccm->ctx, dst_tag, &ltc_tag_len);
202*f1e9b21bSJens Wiklander 	if (ltc_res != CRYPT_OK)
203*f1e9b21bSJens Wiklander 		return TEE_ERROR_BAD_STATE;
204*f1e9b21bSJens Wiklander 
205*f1e9b21bSJens Wiklander 	if (consttime_memcmp(dst_tag, tag, tag_len) != 0)
206*f1e9b21bSJens Wiklander 		res = TEE_ERROR_MAC_INVALID;
207*f1e9b21bSJens Wiklander 	else
208*f1e9b21bSJens Wiklander 		res = TEE_SUCCESS;
209*f1e9b21bSJens Wiklander 	return res;
210*f1e9b21bSJens Wiklander }
211*f1e9b21bSJens Wiklander 
212*f1e9b21bSJens Wiklander static void crypto_aes_ccm_final(struct crypto_authenc_ctx *aectx)
213*f1e9b21bSJens Wiklander {
214*f1e9b21bSJens Wiklander 	ccm_reset(&to_tee_ccm_state(aectx)->ctx);
215*f1e9b21bSJens Wiklander }
216*f1e9b21bSJens Wiklander 
217*f1e9b21bSJens Wiklander static const struct crypto_authenc_ops aes_ccm_ops = {
218*f1e9b21bSJens Wiklander 	.init = crypto_aes_ccm_init,
219*f1e9b21bSJens Wiklander 	.update_aad = crypto_aes_ccm_update_aad,
220*f1e9b21bSJens Wiklander 	.update_payload = crypto_aes_ccm_update_payload,
221*f1e9b21bSJens Wiklander 	.enc_final = crypto_aes_ccm_enc_final,
222*f1e9b21bSJens Wiklander 	.dec_final = crypto_aes_ccm_dec_final,
223*f1e9b21bSJens Wiklander 	.final = crypto_aes_ccm_final,
224*f1e9b21bSJens Wiklander 	.free_ctx = crypto_aes_ccm_free_ctx,
225*f1e9b21bSJens Wiklander 	.copy_state = crypto_aes_ccm_copy_state,
226*f1e9b21bSJens Wiklander };
227