xref: /optee_os/core/drivers/crypto/stm32/authenc.c (revision 061e13f64e8470a8d82bd356dc3e7c81ab80116c)
1fa8cb7a8SNicolas Toromanoff // SPDX-License-Identifier: BSD-2-Clause
2fa8cb7a8SNicolas Toromanoff /*
3fa8cb7a8SNicolas Toromanoff  * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
4fa8cb7a8SNicolas Toromanoff  */
5fa8cb7a8SNicolas Toromanoff 
6fa8cb7a8SNicolas Toromanoff #include <assert.h>
7fa8cb7a8SNicolas Toromanoff #include <crypto/crypto.h>
8fa8cb7a8SNicolas Toromanoff #include <crypto/crypto_impl.h>
9fa8cb7a8SNicolas Toromanoff #include <crypto/internal_aes-gcm.h>
10fa8cb7a8SNicolas Toromanoff #include <drvcrypt.h>
11fa8cb7a8SNicolas Toromanoff #include <drvcrypt_authenc.h>
12fa8cb7a8SNicolas Toromanoff #include <initcall.h>
13fa8cb7a8SNicolas Toromanoff #include <stdlib.h>
14fa8cb7a8SNicolas Toromanoff #include <string.h>
15fa8cb7a8SNicolas Toromanoff #include <string_ext.h>
16fa8cb7a8SNicolas Toromanoff #include <tee_api_types.h>
17fa8cb7a8SNicolas Toromanoff #include <utee_defines.h>
18fa8cb7a8SNicolas Toromanoff #include <util.h>
19fa8cb7a8SNicolas Toromanoff 
20fa8cb7a8SNicolas Toromanoff #include "common.h"
21fa8cb7a8SNicolas Toromanoff #include "stm32_cryp.h"
22fa8cb7a8SNicolas Toromanoff 
23fa8cb7a8SNicolas Toromanoff #define MAX_TAG_SIZE			16U
24fa8cb7a8SNicolas Toromanoff 
25fa8cb7a8SNicolas Toromanoff struct stm32_ae_ctx {
26fa8cb7a8SNicolas Toromanoff 	struct crypto_authenc_ctx a_ctx;
27fa8cb7a8SNicolas Toromanoff 	struct stm32_cryp_context cryp;
28fa8cb7a8SNicolas Toromanoff 	enum stm32_cryp_algo_mode algo;
29fa8cb7a8SNicolas Toromanoff 	uint8_t tag_mask[MAX_TAG_SIZE];
30fa8cb7a8SNicolas Toromanoff };
31fa8cb7a8SNicolas Toromanoff 
xor_vec(uint8_t * r,uint8_t * a,uint8_t * b,size_t len)32fa8cb7a8SNicolas Toromanoff static void xor_vec(uint8_t *r, uint8_t *a, uint8_t *b, size_t len)
33fa8cb7a8SNicolas Toromanoff {
34fa8cb7a8SNicolas Toromanoff 	size_t i = 0;
35fa8cb7a8SNicolas Toromanoff 
36fa8cb7a8SNicolas Toromanoff 	for (i = 0; i < len; i++)
37fa8cb7a8SNicolas Toromanoff 		r[i] = a[i] ^ b[i];
38fa8cb7a8SNicolas Toromanoff }
39fa8cb7a8SNicolas Toromanoff 
to_stm32_ae_ctx(struct crypto_authenc_ctx * ctx)40fa8cb7a8SNicolas Toromanoff static struct stm32_ae_ctx *to_stm32_ae_ctx(struct crypto_authenc_ctx *ctx)
41fa8cb7a8SNicolas Toromanoff {
42fa8cb7a8SNicolas Toromanoff 	assert(ctx);
43fa8cb7a8SNicolas Toromanoff 
44fa8cb7a8SNicolas Toromanoff 	return container_of(ctx, struct stm32_ae_ctx, a_ctx);
45fa8cb7a8SNicolas Toromanoff }
46fa8cb7a8SNicolas Toromanoff 
stm32_ae_gcm_generate_iv(struct stm32_ae_ctx * c,uint32_t * iv,struct drvcrypt_authenc_init * dinit)47fa8cb7a8SNicolas Toromanoff static TEE_Result stm32_ae_gcm_generate_iv(struct stm32_ae_ctx *c,
48fa8cb7a8SNicolas Toromanoff 					   uint32_t *iv,
49fa8cb7a8SNicolas Toromanoff 					   struct drvcrypt_authenc_init *dinit)
50fa8cb7a8SNicolas Toromanoff {
51fa8cb7a8SNicolas Toromanoff 	TEE_Result res = TEE_SUCCESS;
52fa8cb7a8SNicolas Toromanoff 	uint8_t tag1[MAX_TAG_SIZE] = { 0 };
53fa8cb7a8SNicolas Toromanoff 	uint8_t tag2[MAX_TAG_SIZE] = { 0 };
54fa8cb7a8SNicolas Toromanoff 	uint32_t j0[MAX_TAG_SIZE / sizeof(uint32_t)] = { 0 };
55fa8cb7a8SNicolas Toromanoff 	uint8_t dummy_iv[MAX_TAG_SIZE] = { 0 };
56fa8cb7a8SNicolas Toromanoff 	struct stm32_cryp_context ctx = { };
57fa8cb7a8SNicolas Toromanoff 	uint8_t *data_out = NULL;
58fa8cb7a8SNicolas Toromanoff 
59fa8cb7a8SNicolas Toromanoff 	if (dinit->nonce.length == 12) {
60fa8cb7a8SNicolas Toromanoff 		memcpy(iv, dinit->nonce.data, dinit->nonce.length);
61e55d0bcaSThomas Bourgoin 		iv[3] = TEE_U32_TO_BIG_ENDIAN(2);
62fa8cb7a8SNicolas Toromanoff 		return TEE_SUCCESS;
63fa8cb7a8SNicolas Toromanoff 	}
64fa8cb7a8SNicolas Toromanoff 
65fa8cb7a8SNicolas Toromanoff 	/* Calculate GHASH(dinit->nonce.data) */
66fa8cb7a8SNicolas Toromanoff 	dummy_iv[15] = 2;
67fa8cb7a8SNicolas Toromanoff 
68fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_init(&ctx, true, STM32_CRYP_MODE_AES_GCM,
69fa8cb7a8SNicolas Toromanoff 			      dinit->key.data, dinit->key.length,
70fa8cb7a8SNicolas Toromanoff 			      dummy_iv, sizeof(dummy_iv));
71fa8cb7a8SNicolas Toromanoff 	if (res)
72fa8cb7a8SNicolas Toromanoff 		return res;
73fa8cb7a8SNicolas Toromanoff 
74fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_final(&ctx, tag1, sizeof(tag1));
75fa8cb7a8SNicolas Toromanoff 	if (res)
76fa8cb7a8SNicolas Toromanoff 		return res;
77fa8cb7a8SNicolas Toromanoff 
78fa8cb7a8SNicolas Toromanoff 	memset(&ctx, 0, sizeof(ctx));
79fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_init(&ctx, true, STM32_CRYP_MODE_AES_GCM,
80fa8cb7a8SNicolas Toromanoff 			      dinit->key.data, dinit->key.length,
81fa8cb7a8SNicolas Toromanoff 			      dummy_iv, sizeof(dummy_iv));
82fa8cb7a8SNicolas Toromanoff 	if (res)
83fa8cb7a8SNicolas Toromanoff 		return res;
84fa8cb7a8SNicolas Toromanoff 
85fa8cb7a8SNicolas Toromanoff 	data_out = malloc(dinit->nonce.length);
86fa8cb7a8SNicolas Toromanoff 	if (!data_out)
87fa8cb7a8SNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
88fa8cb7a8SNicolas Toromanoff 
89fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_update_load(&ctx, dinit->nonce.data, data_out,
90fa8cb7a8SNicolas Toromanoff 				     dinit->nonce.length);
91fa8cb7a8SNicolas Toromanoff 	free(data_out);
92fa8cb7a8SNicolas Toromanoff 
93fa8cb7a8SNicolas Toromanoff 	if (res)
94fa8cb7a8SNicolas Toromanoff 		return res;
95fa8cb7a8SNicolas Toromanoff 
96fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_final(&ctx, tag2, sizeof(tag2));
97fa8cb7a8SNicolas Toromanoff 	if (res)
98fa8cb7a8SNicolas Toromanoff 		return res;
99fa8cb7a8SNicolas Toromanoff 
100fa8cb7a8SNicolas Toromanoff 	xor_vec((uint8_t *)j0, tag1, tag2, sizeof(tag1));
101fa8cb7a8SNicolas Toromanoff 
102fa8cb7a8SNicolas Toromanoff 	memcpy(iv, j0, sizeof(j0));
103e55d0bcaSThomas Bourgoin 	iv[3] = TEE_U32_TO_BIG_ENDIAN(TEE_U32_FROM_BIG_ENDIAN(iv[3]) + 1);
104fa8cb7a8SNicolas Toromanoff 
105fa8cb7a8SNicolas Toromanoff 	/* Compute first mask=AES_ECB(J0_real) into tag1 */
106fa8cb7a8SNicolas Toromanoff 	memset(&ctx, 0, sizeof(ctx));
107fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_init(&ctx, false, STM32_CRYP_MODE_AES_ECB,
108fa8cb7a8SNicolas Toromanoff 			      dinit->key.data, dinit->key.length,
109fa8cb7a8SNicolas Toromanoff 			      NULL, 0);
110fa8cb7a8SNicolas Toromanoff 	if (res)
111fa8cb7a8SNicolas Toromanoff 		return res;
112fa8cb7a8SNicolas Toromanoff 
113fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_update(&ctx, true, (uint8_t *)j0, tag1,
114fa8cb7a8SNicolas Toromanoff 				sizeof(tag1));
115fa8cb7a8SNicolas Toromanoff 	if (res)
116fa8cb7a8SNicolas Toromanoff 		return res;
117fa8cb7a8SNicolas Toromanoff 
118fa8cb7a8SNicolas Toromanoff 	/* Compute second mask=AES_ECB(J0_used_by_HW) into tag2 */
119fa8cb7a8SNicolas Toromanoff 	memset(&ctx, 0, sizeof(ctx));
120e55d0bcaSThomas Bourgoin 	j0[3] = TEE_U32_TO_BIG_ENDIAN(1);
121fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_init(&ctx, false, STM32_CRYP_MODE_AES_ECB,
122fa8cb7a8SNicolas Toromanoff 			      dinit->key.data, dinit->key.length,
123fa8cb7a8SNicolas Toromanoff 			      NULL, 0);
124fa8cb7a8SNicolas Toromanoff 	if (res)
125fa8cb7a8SNicolas Toromanoff 		return res;
126fa8cb7a8SNicolas Toromanoff 
127fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_update(&ctx, true, (uint8_t *)j0, tag2,
128fa8cb7a8SNicolas Toromanoff 				sizeof(tag2));
129fa8cb7a8SNicolas Toromanoff 	if (res)
130fa8cb7a8SNicolas Toromanoff 		return res;
131fa8cb7a8SNicolas Toromanoff 
132fa8cb7a8SNicolas Toromanoff 	/*
133fa8cb7a8SNicolas Toromanoff 	 * Save the mask we will apply in {enc,dec}_final() to the
134fa8cb7a8SNicolas Toromanoff 	 * (wrongly) computed tag to get the expected one.
135fa8cb7a8SNicolas Toromanoff 	 */
136fa8cb7a8SNicolas Toromanoff 	xor_vec(c->tag_mask, tag1, tag2, sizeof(c->tag_mask));
137fa8cb7a8SNicolas Toromanoff 
138fa8cb7a8SNicolas Toromanoff 	return TEE_SUCCESS;
139fa8cb7a8SNicolas Toromanoff }
140fa8cb7a8SNicolas Toromanoff 
stm32_ae_ccm_generate_b0(uint8_t * b0,struct drvcrypt_authenc_init * dinit)141fa8cb7a8SNicolas Toromanoff static void stm32_ae_ccm_generate_b0(uint8_t *b0,
142fa8cb7a8SNicolas Toromanoff 				     struct drvcrypt_authenc_init *dinit)
143fa8cb7a8SNicolas Toromanoff {
144fa8cb7a8SNicolas Toromanoff 	size_t m = dinit->tag_len;
145fa8cb7a8SNicolas Toromanoff 	size_t l = 15 - dinit->nonce.length;
146fa8cb7a8SNicolas Toromanoff 	size_t payload_len = dinit->payload_len;
147fa8cb7a8SNicolas Toromanoff 	size_t i = 15;
148fa8cb7a8SNicolas Toromanoff 
149fa8cb7a8SNicolas Toromanoff 	/* The tag_len should be 4, 6, 8, 10, 12, 14 or 16 */
150fa8cb7a8SNicolas Toromanoff 	assert(m >= 4 && m <= 16 && (m % 2) == 0);
151fa8cb7a8SNicolas Toromanoff 
152fa8cb7a8SNicolas Toromanoff 	memset(b0, 0, TEE_AES_BLOCK_SIZE);
153fa8cb7a8SNicolas Toromanoff 	/* Flags: (Adata << 6) | (M' << 3) | L' */
154fa8cb7a8SNicolas Toromanoff 	b0[0] = ((dinit->aad_len ? 1 : 0) << 6) |
155fa8cb7a8SNicolas Toromanoff 		(((m - 2) / 2) << 3) |
156fa8cb7a8SNicolas Toromanoff 		(l - 1);
157fa8cb7a8SNicolas Toromanoff 
158fa8cb7a8SNicolas Toromanoff 	/* Nonce */
159fa8cb7a8SNicolas Toromanoff 	memcpy(b0 + 1, dinit->nonce.data, dinit->nonce.length);
160fa8cb7a8SNicolas Toromanoff 
161fa8cb7a8SNicolas Toromanoff 	/* Payload length */
162fa8cb7a8SNicolas Toromanoff 	for (i = 15; i >= 15 - l + 1; i--, payload_len >>= 8)
163fa8cb7a8SNicolas Toromanoff 		b0[i] = payload_len & 0xFF;
164fa8cb7a8SNicolas Toromanoff }
165fa8cb7a8SNicolas Toromanoff 
stm32_ae_ccm_push_b1(struct stm32_ae_ctx * c,struct drvcrypt_authenc_init * dinit)166fa8cb7a8SNicolas Toromanoff static TEE_Result stm32_ae_ccm_push_b1(struct stm32_ae_ctx *c,
167fa8cb7a8SNicolas Toromanoff 				       struct drvcrypt_authenc_init *dinit)
168fa8cb7a8SNicolas Toromanoff {
169fa8cb7a8SNicolas Toromanoff 	uint8_t b1[TEE_AES_BLOCK_SIZE] = { 0 };
170fa8cb7a8SNicolas Toromanoff 	size_t len = 0;
171fa8cb7a8SNicolas Toromanoff 
172fa8cb7a8SNicolas Toromanoff 	if (dinit->aad_len == 0)
173fa8cb7a8SNicolas Toromanoff 		return TEE_SUCCESS;
174fa8cb7a8SNicolas Toromanoff 
175fa8cb7a8SNicolas Toromanoff 	if (dinit->aad_len < 0x100) {
176fa8cb7a8SNicolas Toromanoff 		b1[1] = dinit->aad_len;
177fa8cb7a8SNicolas Toromanoff 		len = 2;
178fa8cb7a8SNicolas Toromanoff 	} else if (dinit->aad_len < 0xFF00) {
179fa8cb7a8SNicolas Toromanoff 		b1[0] = dinit->aad_len / 0x100;
180fa8cb7a8SNicolas Toromanoff 		b1[1] = dinit->aad_len % 0x100;
181fa8cb7a8SNicolas Toromanoff 		len = 2;
182fa8cb7a8SNicolas Toromanoff 	} else if  (dinit->aad_len <= UINT32_MAX) {
183fa8cb7a8SNicolas Toromanoff 		b1[0] = 0xFF;
184fa8cb7a8SNicolas Toromanoff 		b1[1] = 0xFE;
185fa8cb7a8SNicolas Toromanoff 		b1[2] = dinit->aad_len & GENMASK_32(7, 0);
186fa8cb7a8SNicolas Toromanoff 		b1[3] = (dinit->aad_len & GENMASK_32(15, 8)) >> 8;
187fa8cb7a8SNicolas Toromanoff 		b1[4] = (dinit->aad_len & GENMASK_32(23, 16)) >> 16;
188fa8cb7a8SNicolas Toromanoff 		b1[5] = (dinit->aad_len & GENMASK_32(31, 24)) >> 24;
189fa8cb7a8SNicolas Toromanoff 		len = 6;
190fa8cb7a8SNicolas Toromanoff 	} else {
191fa8cb7a8SNicolas Toromanoff 		b1[0] = 0xFF;
192fa8cb7a8SNicolas Toromanoff 		b1[1] = 0xFF;
193fa8cb7a8SNicolas Toromanoff 		b1[2] = dinit->aad_len & GENMASK_64(7, 0);
194fa8cb7a8SNicolas Toromanoff 		b1[3] = (dinit->aad_len & GENMASK_64(15, 8)) >> 8;
195fa8cb7a8SNicolas Toromanoff 		b1[4] = (dinit->aad_len & GENMASK_64(23, 16)) >> 16;
196fa8cb7a8SNicolas Toromanoff 		b1[5] = (dinit->aad_len & GENMASK_64(31, 24)) >> 24;
197fa8cb7a8SNicolas Toromanoff 		b1[6] = (dinit->aad_len & GENMASK_64(39, 32)) >> 32;
198fa8cb7a8SNicolas Toromanoff 		b1[7] = (dinit->aad_len & GENMASK_64(47, 40)) >> 40;
199fa8cb7a8SNicolas Toromanoff 		b1[8] = (dinit->aad_len & GENMASK_64(55, 48)) >> 48;
200fa8cb7a8SNicolas Toromanoff 		b1[9] = (dinit->aad_len & GENMASK_64(63, 56)) >> 56;
201fa8cb7a8SNicolas Toromanoff 		len = 10;
202fa8cb7a8SNicolas Toromanoff 	}
203fa8cb7a8SNicolas Toromanoff 
204fa8cb7a8SNicolas Toromanoff 	return stm32_cryp_update_assodata(&c->cryp, b1, len);
205fa8cb7a8SNicolas Toromanoff }
206fa8cb7a8SNicolas Toromanoff 
stm32_ae_initialize(struct drvcrypt_authenc_init * dinit)207fa8cb7a8SNicolas Toromanoff static TEE_Result stm32_ae_initialize(struct drvcrypt_authenc_init *dinit)
208fa8cb7a8SNicolas Toromanoff {
209fa8cb7a8SNicolas Toromanoff 	TEE_Result res = TEE_SUCCESS;
210fa8cb7a8SNicolas Toromanoff 	uint32_t iv[4] = { 0 };
211fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *c = to_stm32_ae_ctx(dinit->ctx);
212fa8cb7a8SNicolas Toromanoff 
213fa8cb7a8SNicolas Toromanoff 	if (c->algo == STM32_CRYP_MODE_AES_GCM) {
214fa8cb7a8SNicolas Toromanoff 		res = stm32_ae_gcm_generate_iv(c, iv, dinit);
215fa8cb7a8SNicolas Toromanoff 		if (res)
216fa8cb7a8SNicolas Toromanoff 			return res;
217fa8cb7a8SNicolas Toromanoff 	} else if (c->algo == STM32_CRYP_MODE_AES_CCM) {
218fa8cb7a8SNicolas Toromanoff 		stm32_ae_ccm_generate_b0((uint8_t *)iv, dinit);
219fa8cb7a8SNicolas Toromanoff 	}
220fa8cb7a8SNicolas Toromanoff 
221fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_init(&c->cryp, !dinit->encrypt, c->algo,
222fa8cb7a8SNicolas Toromanoff 			      dinit->key.data, dinit->key.length, iv,
223fa8cb7a8SNicolas Toromanoff 			      sizeof(iv));
224fa8cb7a8SNicolas Toromanoff 	if (res)
225fa8cb7a8SNicolas Toromanoff 		return res;
226fa8cb7a8SNicolas Toromanoff 
227fa8cb7a8SNicolas Toromanoff 	if (c->algo == STM32_CRYP_MODE_AES_CCM)
228fa8cb7a8SNicolas Toromanoff 		return stm32_ae_ccm_push_b1(c, dinit);
229fa8cb7a8SNicolas Toromanoff 
230fa8cb7a8SNicolas Toromanoff 	return TEE_SUCCESS;
231fa8cb7a8SNicolas Toromanoff }
232fa8cb7a8SNicolas Toromanoff 
233fa8cb7a8SNicolas Toromanoff static TEE_Result
stm32_ae_update_aad(struct drvcrypt_authenc_update_aad * dupdate)234fa8cb7a8SNicolas Toromanoff stm32_ae_update_aad(struct drvcrypt_authenc_update_aad *dupdate)
235fa8cb7a8SNicolas Toromanoff {
236fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *c = to_stm32_ae_ctx(dupdate->ctx);
237fa8cb7a8SNicolas Toromanoff 
238fa8cb7a8SNicolas Toromanoff 	return stm32_cryp_update_assodata(&c->cryp, dupdate->aad.data,
239fa8cb7a8SNicolas Toromanoff 					  dupdate->aad.length);
240fa8cb7a8SNicolas Toromanoff }
241fa8cb7a8SNicolas Toromanoff 
242fa8cb7a8SNicolas Toromanoff static TEE_Result
stm32_ae_update_payload(struct drvcrypt_authenc_update_payload * dupdate)243fa8cb7a8SNicolas Toromanoff stm32_ae_update_payload(struct drvcrypt_authenc_update_payload *dupdate)
244fa8cb7a8SNicolas Toromanoff {
245fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *c = to_stm32_ae_ctx(dupdate->ctx);
246fa8cb7a8SNicolas Toromanoff 	size_t len = MIN(dupdate->src.length, dupdate->dst.length);
247fa8cb7a8SNicolas Toromanoff 
248fa8cb7a8SNicolas Toromanoff 	return stm32_cryp_update_load(&c->cryp, dupdate->src.data,
249fa8cb7a8SNicolas Toromanoff 				      dupdate->dst.data, len);
250fa8cb7a8SNicolas Toromanoff }
251fa8cb7a8SNicolas Toromanoff 
stm32_ae_encdec_final(struct stm32_ae_ctx * c,uint8_t * tag,size_t tag_size)252fa8cb7a8SNicolas Toromanoff static TEE_Result stm32_ae_encdec_final(struct stm32_ae_ctx *c, uint8_t *tag,
253fa8cb7a8SNicolas Toromanoff 					size_t tag_size)
254fa8cb7a8SNicolas Toromanoff {
255fa8cb7a8SNicolas Toromanoff 	TEE_Result res = TEE_SUCCESS;
256fa8cb7a8SNicolas Toromanoff 	uint8_t t[MAX_TAG_SIZE] = { 0 };
257fa8cb7a8SNicolas Toromanoff 
258fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_final(&c->cryp, t, sizeof(t));
259fa8cb7a8SNicolas Toromanoff 	if (res)
260fa8cb7a8SNicolas Toromanoff 		return res;
261fa8cb7a8SNicolas Toromanoff 
262fa8cb7a8SNicolas Toromanoff 	xor_vec(tag, t, c->tag_mask, tag_size);
263fa8cb7a8SNicolas Toromanoff 
264fa8cb7a8SNicolas Toromanoff 	return TEE_SUCCESS;
265fa8cb7a8SNicolas Toromanoff }
266fa8cb7a8SNicolas Toromanoff 
stm32_ae_enc_final(struct drvcrypt_authenc_final * dfinal)267fa8cb7a8SNicolas Toromanoff static TEE_Result stm32_ae_enc_final(struct drvcrypt_authenc_final *dfinal)
268fa8cb7a8SNicolas Toromanoff {
269fa8cb7a8SNicolas Toromanoff 	TEE_Result res = TEE_SUCCESS;
270fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *c = to_stm32_ae_ctx(dfinal->ctx);
271fa8cb7a8SNicolas Toromanoff 	size_t len = MIN(dfinal->src.length, dfinal->dst.length);
272fa8cb7a8SNicolas Toromanoff 
273fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_update_load(&c->cryp, dfinal->src.data,
274fa8cb7a8SNicolas Toromanoff 				     dfinal->dst.data, len);
275fa8cb7a8SNicolas Toromanoff 	if (res)
276fa8cb7a8SNicolas Toromanoff 		return res;
277fa8cb7a8SNicolas Toromanoff 
278fa8cb7a8SNicolas Toromanoff 	return stm32_ae_encdec_final(c, dfinal->tag.data, dfinal->tag.length);
279fa8cb7a8SNicolas Toromanoff }
280fa8cb7a8SNicolas Toromanoff 
stm32_ae_dec_final(struct drvcrypt_authenc_final * dfinal)281fa8cb7a8SNicolas Toromanoff static TEE_Result stm32_ae_dec_final(struct drvcrypt_authenc_final *dfinal)
282fa8cb7a8SNicolas Toromanoff {
283fa8cb7a8SNicolas Toromanoff 	TEE_Result res = TEE_SUCCESS;
284fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *c = to_stm32_ae_ctx(dfinal->ctx);
285fa8cb7a8SNicolas Toromanoff 	size_t len = MIN(dfinal->src.length, dfinal->dst.length);
286fa8cb7a8SNicolas Toromanoff 	unsigned char tag_buf[MAX_TAG_SIZE] = { 0 };
287fa8cb7a8SNicolas Toromanoff 
288fa8cb7a8SNicolas Toromanoff 	res = stm32_cryp_update_load(&c->cryp, dfinal->src.data,
289fa8cb7a8SNicolas Toromanoff 				     dfinal->dst.data, len);
290fa8cb7a8SNicolas Toromanoff 	if (res)
291fa8cb7a8SNicolas Toromanoff 		return res;
292fa8cb7a8SNicolas Toromanoff 
293fa8cb7a8SNicolas Toromanoff 	res = stm32_ae_encdec_final(c, tag_buf, sizeof(tag_buf));
294fa8cb7a8SNicolas Toromanoff 	if (res)
295fa8cb7a8SNicolas Toromanoff 		return res;
296fa8cb7a8SNicolas Toromanoff 
297fa8cb7a8SNicolas Toromanoff 	if (consttime_memcmp(tag_buf, dfinal->tag.data, dfinal->tag.length))
298fa8cb7a8SNicolas Toromanoff 		return TEE_ERROR_MAC_INVALID;
299fa8cb7a8SNicolas Toromanoff 
300fa8cb7a8SNicolas Toromanoff 	return TEE_SUCCESS;
301fa8cb7a8SNicolas Toromanoff }
302fa8cb7a8SNicolas Toromanoff 
stm32_ae_final(void * ctx __unused)303fa8cb7a8SNicolas Toromanoff static void stm32_ae_final(void *ctx __unused)
304fa8cb7a8SNicolas Toromanoff {
305fa8cb7a8SNicolas Toromanoff }
306fa8cb7a8SNicolas Toromanoff 
stm32_ae_free(void * ctx)307fa8cb7a8SNicolas Toromanoff static void stm32_ae_free(void *ctx)
308fa8cb7a8SNicolas Toromanoff {
309fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *c = to_stm32_ae_ctx(ctx);
310fa8cb7a8SNicolas Toromanoff 
311fa8cb7a8SNicolas Toromanoff 	free(c);
312fa8cb7a8SNicolas Toromanoff }
313fa8cb7a8SNicolas Toromanoff 
stm32_ae_copy_state(void * dst_ctx,void * src_ctx)314fa8cb7a8SNicolas Toromanoff static void stm32_ae_copy_state(void *dst_ctx, void *src_ctx)
315fa8cb7a8SNicolas Toromanoff {
316fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *src = to_stm32_ae_ctx(src_ctx);
317fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *dst = to_stm32_ae_ctx(dst_ctx);
318fa8cb7a8SNicolas Toromanoff 
319fa8cb7a8SNicolas Toromanoff 	memcpy(dst, src, sizeof(*dst));
320fa8cb7a8SNicolas Toromanoff }
321fa8cb7a8SNicolas Toromanoff 
alloc_ctx(void ** ctx,enum stm32_cryp_algo_mode algo)322fa8cb7a8SNicolas Toromanoff static TEE_Result alloc_ctx(void **ctx, enum stm32_cryp_algo_mode algo)
323fa8cb7a8SNicolas Toromanoff {
324fa8cb7a8SNicolas Toromanoff 	struct stm32_ae_ctx *c = calloc(1, sizeof(*c));
325fa8cb7a8SNicolas Toromanoff 
326fa8cb7a8SNicolas Toromanoff 	if (!c)
327fa8cb7a8SNicolas Toromanoff 		return TEE_ERROR_OUT_OF_MEMORY;
328fa8cb7a8SNicolas Toromanoff 
329fa8cb7a8SNicolas Toromanoff 	c->algo = algo;
330fa8cb7a8SNicolas Toromanoff 	*ctx = &c->a_ctx;
331fa8cb7a8SNicolas Toromanoff 
332fa8cb7a8SNicolas Toromanoff 	return TEE_SUCCESS;
333fa8cb7a8SNicolas Toromanoff }
334fa8cb7a8SNicolas Toromanoff 
335fa8cb7a8SNicolas Toromanoff /*
336fa8cb7a8SNicolas Toromanoff  * Allocate the SW authenc data context
337fa8cb7a8SNicolas Toromanoff  *
338fa8cb7a8SNicolas Toromanoff  * @ctx   [out] Caller context variable
339fa8cb7a8SNicolas Toromanoff  * @algo  Algorithm ID of the context
340fa8cb7a8SNicolas Toromanoff  */
stm32_ae_allocate(void ** ctx,uint32_t algo)341fa8cb7a8SNicolas Toromanoff static TEE_Result stm32_ae_allocate(void **ctx, uint32_t algo)
342fa8cb7a8SNicolas Toromanoff {
343fa8cb7a8SNicolas Toromanoff 	/* Convert TEE_ALGO id to CRYP id */
344fa8cb7a8SNicolas Toromanoff 	switch (algo) {
345fa8cb7a8SNicolas Toromanoff 	case TEE_ALG_AES_CCM:
346fa8cb7a8SNicolas Toromanoff 		return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CCM);
347fa8cb7a8SNicolas Toromanoff 	case TEE_ALG_AES_GCM:
348fa8cb7a8SNicolas Toromanoff 		return alloc_ctx(ctx, STM32_CRYP_MODE_AES_GCM);
349fa8cb7a8SNicolas Toromanoff 	default:
350fa8cb7a8SNicolas Toromanoff 		return TEE_ERROR_NOT_IMPLEMENTED;
351fa8cb7a8SNicolas Toromanoff 	}
352fa8cb7a8SNicolas Toromanoff }
353fa8cb7a8SNicolas Toromanoff 
354fa8cb7a8SNicolas Toromanoff /*
355fa8cb7a8SNicolas Toromanoff  * Registration of the Authenc Driver
356fa8cb7a8SNicolas Toromanoff  */
357fa8cb7a8SNicolas Toromanoff static struct drvcrypt_authenc driver_authenc = {
358*061e13f6SEtienne Carriere 	.alloc_ctx = stm32_ae_allocate,
359*061e13f6SEtienne Carriere 	.free_ctx = stm32_ae_free,
360*061e13f6SEtienne Carriere 	.init = stm32_ae_initialize,
361*061e13f6SEtienne Carriere 	.update_aad = stm32_ae_update_aad,
362*061e13f6SEtienne Carriere 	.update_payload = stm32_ae_update_payload,
363*061e13f6SEtienne Carriere 	.enc_final = stm32_ae_enc_final,
364*061e13f6SEtienne Carriere 	.dec_final = stm32_ae_dec_final,
365*061e13f6SEtienne Carriere 	.final = stm32_ae_final,
366*061e13f6SEtienne Carriere 	.copy_state = stm32_ae_copy_state,
367fa8cb7a8SNicolas Toromanoff };
368fa8cb7a8SNicolas Toromanoff 
stm32_register_authenc(void)369fa8cb7a8SNicolas Toromanoff TEE_Result stm32_register_authenc(void)
370fa8cb7a8SNicolas Toromanoff {
371fa8cb7a8SNicolas Toromanoff 	return drvcrypt_register_authenc(&driver_authenc);
372fa8cb7a8SNicolas Toromanoff }
373