xref: /optee_os/lib/libutee/tee_api_operations.c (revision 24ea76132a1203c2c46113512f7e5afa4c689f7d)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
4eee637e7SAlexander Zakharov  * Copyright (c) 2021, SumUp Services GmbH
5b0104773SPascal Brand  */
6*24ea7613SJens Wiklander #include <assert.h>
779170ce0SJerome Forissier #include <config.h>
8b0104773SPascal Brand #include <stdlib.h>
9b0104773SPascal Brand #include <string.h>
10b796ebf3SJerome Forissier #include <string_ext.h>
11b0104773SPascal Brand #include <tee_api.h>
128854d3c6SJerome Forissier #include <tee_api_defines_extensions.h>
13b0104773SPascal Brand #include <tee_internal_api_extensions.h>
14b0104773SPascal Brand #include <utee_syscalls.h>
15b0104773SPascal Brand #include <utee_defines.h>
16fc26c92aSJens Wiklander #include <util.h>
17e86f1266SJens Wiklander #include "tee_api_private.h"
18b0104773SPascal Brand 
19b0104773SPascal Brand struct __TEE_OperationHandle {
20b0104773SPascal Brand 	TEE_OperationInfo info;
21b0104773SPascal Brand 	TEE_ObjectHandle key1;
22b0104773SPascal Brand 	TEE_ObjectHandle key2;
23642a1607SCedric Chaumont 	uint32_t operationState;/* Operation state : INITIAL or ACTIVE */
24*24ea7613SJens Wiklander 
25*24ea7613SJens Wiklander 	/*
26*24ea7613SJens Wiklander 	 * buffer to collect complete blocks or to keep a complete digest
27*24ea7613SJens Wiklander 	 * for TEE_DigestExtract().
28*24ea7613SJens Wiklander 	 */
29*24ea7613SJens Wiklander 	uint8_t *buffer;
30b0104773SPascal Brand 	bool buffer_two_blocks;	/* True if two blocks need to be buffered */
31b0104773SPascal Brand 	size_t block_size;	/* Block size of cipher */
32b0104773SPascal Brand 	size_t buffer_offs;	/* Offset in buffer */
33b0104773SPascal Brand 	uint32_t state;		/* Handle to state in TEE Core */
34b0104773SPascal Brand };
35b0104773SPascal Brand 
36b0104773SPascal Brand /* Cryptographic Operations API - Generic Operation Functions */
37b0104773SPascal Brand 
38b0104773SPascal Brand TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
39b0104773SPascal Brand 				 uint32_t algorithm, uint32_t mode,
40b0104773SPascal Brand 				 uint32_t maxKeySize)
41b0104773SPascal Brand {
42b0104773SPascal Brand 	TEE_Result res;
43b0104773SPascal Brand 	TEE_OperationHandle op = TEE_HANDLE_NULL;
44b0104773SPascal Brand 	uint32_t handle_state = 0;
45b0104773SPascal Brand 	size_t block_size = 1;
46b0104773SPascal Brand 	uint32_t req_key_usage;
47b0104773SPascal Brand 	bool with_private_key = false;
48b0104773SPascal Brand 	bool buffer_two_blocks = false;
49b0104773SPascal Brand 
509b52c538SCedric Chaumont 	if (!operation)
51b0104773SPascal Brand 		TEE_Panic(0);
52b0104773SPascal Brand 
53696f56acSPingan Xie 	if (algorithm == TEE_ALG_AES_XTS || algorithm == TEE_ALG_SM2_KEP ||
54696f56acSPingan Xie 	    algorithm == TEE_ALG_SM4_XTS)
55b0104773SPascal Brand 		handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;
56b0104773SPascal Brand 
57218d9055SCedric Chaumont 	/* Check algorithm max key size */
58218d9055SCedric Chaumont 	switch (algorithm) {
59218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA1:
60218d9055SCedric Chaumont 		if (maxKeySize < 512)
61218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
62218d9055SCedric Chaumont 		if (maxKeySize > 1024)
63218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
64218d9055SCedric Chaumont 		if (maxKeySize % 64 != 0)
65218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
66218d9055SCedric Chaumont 		break;
67218d9055SCedric Chaumont 
68218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA224:
69218d9055SCedric Chaumont 		if (maxKeySize != 2048)
70218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
71218d9055SCedric Chaumont 		break;
72218d9055SCedric Chaumont 
73218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA256:
74218d9055SCedric Chaumont 		if (maxKeySize != 2048 && maxKeySize != 3072)
75218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
76218d9055SCedric Chaumont 		break;
77218d9055SCedric Chaumont 
78fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA1:
79fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P192:
80fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P192:
811220586eSCedric Chaumont 		if (maxKeySize != 192)
821220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
831220586eSCedric Chaumont 		break;
841220586eSCedric Chaumont 
85fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA224:
86fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P224:
87fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P224:
881220586eSCedric Chaumont 		if (maxKeySize != 224)
891220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
901220586eSCedric Chaumont 		break;
911220586eSCedric Chaumont 
92fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA256:
93fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P256:
94fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P256:
9591fc6bd8SJerome Forissier 	case TEE_ALG_SM2_PKE:
960f151943SJerome Forissier 	case TEE_ALG_SM2_DSA_SM3:
971220586eSCedric Chaumont 		if (maxKeySize != 256)
981220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
991220586eSCedric Chaumont 		break;
1001220586eSCedric Chaumont 
1015b385b3fSJerome Forissier 	case TEE_ALG_SM2_KEP:
1025b385b3fSJerome Forissier 		/* Two 256-bit keys */
1035b385b3fSJerome Forissier 		if (maxKeySize != 512)
1045b385b3fSJerome Forissier 			return TEE_ERROR_NOT_SUPPORTED;
1055b385b3fSJerome Forissier 		break;
1065b385b3fSJerome Forissier 
107fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA384:
108fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P384:
109fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P384:
1101220586eSCedric Chaumont 		if (maxKeySize != 384)
1111220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
1121220586eSCedric Chaumont 		break;
1131220586eSCedric Chaumont 
114fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA512:
115fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P521:
116fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P521:
1171220586eSCedric Chaumont 		if (maxKeySize != 521)
1181220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
1191220586eSCedric Chaumont 		break;
120fe2fd3ffSJens Wiklander 
121fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDH_DERIVE_SHARED_SECRET:
122fe2fd3ffSJens Wiklander 		if (maxKeySize > 521)
123fe2fd3ffSJens Wiklander 			return TEE_ERROR_NOT_SUPPORTED;
124fe2fd3ffSJens Wiklander 		break;
125fe2fd3ffSJens Wiklander 
126e1f9cee7SSergiy Kibrik 	case TEE_ALG_ED25519:
1273f61056dSSohaib ul Hassan 	case TEE_ALG_X25519:
1283f61056dSSohaib ul Hassan 		if (maxKeySize != 256)
1293f61056dSSohaib ul Hassan 			return TEE_ERROR_NOT_SUPPORTED;
1303f61056dSSohaib ul Hassan 		break;
131218d9055SCedric Chaumont 	default:
132218d9055SCedric Chaumont 		break;
133218d9055SCedric Chaumont 	}
134218d9055SCedric Chaumont 
135cf5c060cSJens Wiklander 	/* Check algorithm mode (and maxKeySize for digests) */
136b0104773SPascal Brand 	switch (algorithm) {
137b0104773SPascal Brand 	case TEE_ALG_AES_CTS:
138b0104773SPascal Brand 	case TEE_ALG_AES_XTS:
139696f56acSPingan Xie 	case TEE_ALG_SM4_XTS:
140b0104773SPascal Brand 		buffer_two_blocks = true;
141919a5a68SJerome Forissier 		fallthrough;
1424bd53c54SJerome Forissier 	case TEE_ALG_AES_ECB_NOPAD:
143b0104773SPascal Brand 	case TEE_ALG_AES_CBC_NOPAD:
144b0104773SPascal Brand 	case TEE_ALG_AES_CCM:
145b0104773SPascal Brand 	case TEE_ALG_DES_ECB_NOPAD:
146b0104773SPascal Brand 	case TEE_ALG_DES_CBC_NOPAD:
147b0104773SPascal Brand 	case TEE_ALG_DES3_ECB_NOPAD:
148b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_NOPAD:
149ade6f848SJerome Forissier 	case TEE_ALG_SM4_ECB_NOPAD:
150ade6f848SJerome Forissier 	case TEE_ALG_SM4_CBC_NOPAD:
151ade6f848SJerome Forissier 	case TEE_ALG_SM4_CTR:
152b0104773SPascal Brand 		if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES)
153b0104773SPascal Brand 			block_size = TEE_AES_BLOCK_SIZE;
154ade6f848SJerome Forissier 		else if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_SM4)
155ade6f848SJerome Forissier 			block_size = TEE_SM4_BLOCK_SIZE;
156b0104773SPascal Brand 		else
157b0104773SPascal Brand 			block_size = TEE_DES_BLOCK_SIZE;
158919a5a68SJerome Forissier 		fallthrough;
15957aabac5SBogdan Liulko 	case TEE_ALG_AES_CTR:
160afc0c182SBogdan Liulko 	case TEE_ALG_AES_GCM:
161b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT)
162b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT;
163b0104773SPascal Brand 		else if (mode == TEE_MODE_DECRYPT)
164b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT;
165b0104773SPascal Brand 		else
166b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
167b0104773SPascal Brand 		break;
168b0104773SPascal Brand 
1696a2e0a9fSGabor Szekely #if defined(CFG_CRYPTO_RSASSA_NA1)
1706a2e0a9fSGabor Szekely 	case TEE_ALG_RSASSA_PKCS1_V1_5:
1716a2e0a9fSGabor Szekely #endif
172b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
173b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
174b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
175b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
176b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
177b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
178b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
179b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
180b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
181b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
182b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
183b0104773SPascal Brand 	case TEE_ALG_DSA_SHA1:
184218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA224:
185218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA256:
186fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA1:
187fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA224:
188fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA256:
189fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA384:
190fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA512:
191fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P192:
192fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P224:
193fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P256:
194fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P384:
195fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P521:
1960f151943SJerome Forissier 	case TEE_ALG_SM2_DSA_SM3:
197e1f9cee7SSergiy Kibrik 	case TEE_ALG_ED25519:
198b0104773SPascal Brand 		if (mode == TEE_MODE_SIGN) {
199b0104773SPascal Brand 			with_private_key = true;
200b0104773SPascal Brand 			req_key_usage = TEE_USAGE_SIGN;
201b0104773SPascal Brand 		} else if (mode == TEE_MODE_VERIFY) {
202b0104773SPascal Brand 			req_key_usage = TEE_USAGE_VERIFY;
203b0104773SPascal Brand 		} else {
204b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
205b0104773SPascal Brand 		}
206b0104773SPascal Brand 		break;
207b0104773SPascal Brand 
208b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_V1_5:
209b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
210b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
211b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
212b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
213b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
21491fc6bd8SJerome Forissier 	case TEE_ALG_SM2_PKE:
215b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT) {
216b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT;
217b0104773SPascal Brand 		} else if (mode == TEE_MODE_DECRYPT) {
218b0104773SPascal Brand 			with_private_key = true;
219b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT;
220b0104773SPascal Brand 		} else {
221b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
222b0104773SPascal Brand 		}
223b0104773SPascal Brand 		break;
224b0104773SPascal Brand 
225b0104773SPascal Brand 	case TEE_ALG_RSA_NOPAD:
226b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT) {
227b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY;
228b0104773SPascal Brand 		} else if (mode == TEE_MODE_DECRYPT) {
229b0104773SPascal Brand 			with_private_key = true;
230b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN;
231b0104773SPascal Brand 		} else {
232b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
233b0104773SPascal Brand 		}
234b0104773SPascal Brand 		break;
235b0104773SPascal Brand 
236b0104773SPascal Brand 	case TEE_ALG_DH_DERIVE_SHARED_SECRET:
237fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDH_DERIVE_SHARED_SECRET:
238fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P192:
239fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P224:
240fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P256:
241fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P384:
242fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P521:
243cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_MD5_DERIVE_KEY:
244cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA1_DERIVE_KEY:
245cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA224_DERIVE_KEY:
246cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA256_DERIVE_KEY:
247cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA384_DERIVE_KEY:
248cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA512_DERIVE_KEY:
2498854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY:
2508854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY:
2518854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY:
2528854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY:
2538854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY:
2540f2293b7SJerome Forissier 	case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY:
2555b385b3fSJerome Forissier 	case TEE_ALG_SM2_KEP:
2563f61056dSSohaib ul Hassan 	case TEE_ALG_X25519:
257b0104773SPascal Brand 		if (mode != TEE_MODE_DERIVE)
258b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
259b0104773SPascal Brand 		with_private_key = true;
260b0104773SPascal Brand 		req_key_usage = TEE_USAGE_DERIVE;
261b0104773SPascal Brand 		break;
262b0104773SPascal Brand 
263b0104773SPascal Brand 	case TEE_ALG_MD5:
264b0104773SPascal Brand 	case TEE_ALG_SHA1:
265b0104773SPascal Brand 	case TEE_ALG_SHA224:
266b0104773SPascal Brand 	case TEE_ALG_SHA256:
267b0104773SPascal Brand 	case TEE_ALG_SHA384:
268b0104773SPascal Brand 	case TEE_ALG_SHA512:
269*24ea7613SJens Wiklander 	case TEE_ALG_SHA3_224:
270*24ea7613SJens Wiklander 	case TEE_ALG_SHA3_256:
271*24ea7613SJens Wiklander 	case TEE_ALG_SHA3_384:
272*24ea7613SJens Wiklander 	case TEE_ALG_SHA3_512:
273*24ea7613SJens Wiklander 	case TEE_ALG_SHAKE128:
274*24ea7613SJens Wiklander 	case TEE_ALG_SHAKE256:
27547645577SJerome Forissier 	case TEE_ALG_SM3:
276b0104773SPascal Brand 		if (mode != TEE_MODE_DIGEST)
277b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
278cf5c060cSJens Wiklander 		if (maxKeySize)
279cf5c060cSJens Wiklander 			return TEE_ERROR_NOT_SUPPORTED;
28005304565SCedric Chaumont 		/* v1.1: flags always set for digest operations */
281b0104773SPascal Brand 		handle_state |= TEE_HANDLE_FLAG_KEY_SET;
282b0104773SPascal Brand 		req_key_usage = 0;
283b0104773SPascal Brand 		break;
284b0104773SPascal Brand 
285b0104773SPascal Brand 	case TEE_ALG_DES_CBC_MAC_NOPAD:
286b0104773SPascal Brand 	case TEE_ALG_AES_CBC_MAC_NOPAD:
287b0104773SPascal Brand 	case TEE_ALG_AES_CBC_MAC_PKCS5:
288b0104773SPascal Brand 	case TEE_ALG_AES_CMAC:
289b0104773SPascal Brand 	case TEE_ALG_DES_CBC_MAC_PKCS5:
290b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_MAC_NOPAD:
291b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_MAC_PKCS5:
292eee637e7SAlexander Zakharov 	case TEE_ALG_DES3_CMAC:
293b0104773SPascal Brand 	case TEE_ALG_HMAC_MD5:
294b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA1:
295b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA224:
296b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA256:
297b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA384:
298b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA512:
299260b4028SJens Wiklander 	case TEE_ALG_HMAC_SHA3_224:
300260b4028SJens Wiklander 	case TEE_ALG_HMAC_SHA3_256:
301260b4028SJens Wiklander 	case TEE_ALG_HMAC_SHA3_384:
302260b4028SJens Wiklander 	case TEE_ALG_HMAC_SHA3_512:
30347645577SJerome Forissier 	case TEE_ALG_HMAC_SM3:
304b0104773SPascal Brand 		if (mode != TEE_MODE_MAC)
305b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
306b0104773SPascal Brand 		req_key_usage = TEE_USAGE_MAC;
307b0104773SPascal Brand 		break;
308b0104773SPascal Brand 
309b0104773SPascal Brand 	default:
310b0104773SPascal Brand 		return TEE_ERROR_NOT_SUPPORTED;
311b0104773SPascal Brand 	}
312b0104773SPascal Brand 
313b66f219bSJens Wiklander 	op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO);
3149b52c538SCedric Chaumont 	if (!op)
315b0104773SPascal Brand 		return TEE_ERROR_OUT_OF_MEMORY;
316b0104773SPascal Brand 
317b0104773SPascal Brand 	op->info.algorithm = algorithm;
318b0104773SPascal Brand 	op->info.operationClass = TEE_ALG_GET_CLASS(algorithm);
3196a2e0a9fSGabor Szekely #ifdef CFG_CRYPTO_RSASSA_NA1
3206a2e0a9fSGabor Szekely 	if (algorithm == TEE_ALG_RSASSA_PKCS1_V1_5)
3216a2e0a9fSGabor Szekely 		op->info.operationClass = TEE_OPERATION_ASYMMETRIC_SIGNATURE;
3226a2e0a9fSGabor Szekely #endif
323b0104773SPascal Brand 	op->info.mode = mode;
3242e5e6460SAlbert Schwarzkopf 	op->info.digestLength = TEE_ALG_GET_DIGEST_SIZE(algorithm);
325b0104773SPascal Brand 	op->info.maxKeySize = maxKeySize;
326b0104773SPascal Brand 	op->info.requiredKeyUsage = req_key_usage;
327b0104773SPascal Brand 	op->info.handleState = handle_state;
328b0104773SPascal Brand 
329*24ea7613SJens Wiklander 	/*
330*24ea7613SJens Wiklander 	 * Needed to buffer the digest if TEE_DigestExtract() doesn't
331*24ea7613SJens Wiklander 	 * retrieve the entire digest in one go.
332*24ea7613SJens Wiklander 	 */
333*24ea7613SJens Wiklander 	if (op->info.operationClass == TEE_OPERATION_DIGEST)
334*24ea7613SJens Wiklander 		block_size = op->info.digestLength;
335*24ea7613SJens Wiklander 
336b0104773SPascal Brand 	if (block_size > 1) {
337b0104773SPascal Brand 		size_t buffer_size = block_size;
338b0104773SPascal Brand 
339b0104773SPascal Brand 		if (buffer_two_blocks)
340b0104773SPascal Brand 			buffer_size *= 2;
341b0104773SPascal Brand 
3429b52c538SCedric Chaumont 		op->buffer = TEE_Malloc(buffer_size,
3439b52c538SCedric Chaumont 					TEE_USER_MEM_HINT_NO_FILL_ZERO);
344b0104773SPascal Brand 		if (op->buffer == NULL) {
345b0104773SPascal Brand 			res = TEE_ERROR_OUT_OF_MEMORY;
346b66f219bSJens Wiklander 			goto out;
347b0104773SPascal Brand 		}
348b0104773SPascal Brand 	}
349b0104773SPascal Brand 	op->block_size = block_size;
350b0104773SPascal Brand 	op->buffer_two_blocks = buffer_two_blocks;
351b0104773SPascal Brand 
352b0104773SPascal Brand 	if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) {
353b0104773SPascal Brand 		uint32_t mks = maxKeySize;
354b0104773SPascal Brand 		TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm,
355b0104773SPascal Brand 						       with_private_key);
356b0104773SPascal Brand 
357b0104773SPascal Brand 		/*
358b0104773SPascal Brand 		 * If two keys are expected the max key size is the sum of
359b0104773SPascal Brand 		 * the size of both keys.
360b0104773SPascal Brand 		 */
361b0104773SPascal Brand 		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS)
362b0104773SPascal Brand 			mks /= 2;
363b0104773SPascal Brand 
364b0104773SPascal Brand 		res = TEE_AllocateTransientObject(key_type, mks, &op->key1);
365b0104773SPascal Brand 		if (res != TEE_SUCCESS)
366b66f219bSJens Wiklander 			goto out;
367b0104773SPascal Brand 
36805304565SCedric Chaumont 		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) {
3699b52c538SCedric Chaumont 			res = TEE_AllocateTransientObject(key_type, mks,
370b0104773SPascal Brand 							  &op->key2);
371b0104773SPascal Brand 			if (res != TEE_SUCCESS)
372b66f219bSJens Wiklander 				goto out;
373b0104773SPascal Brand 		}
374b0104773SPascal Brand 	}
375b0104773SPascal Brand 
3762c028fdeSJerome Forissier 	res = _utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1,
377e86f1266SJens Wiklander 				     (unsigned long)op->key2, &op->state);
378b66f219bSJens Wiklander 	if (res != TEE_SUCCESS)
379b66f219bSJens Wiklander 		goto out;
380b0104773SPascal Brand 
38105304565SCedric Chaumont 	/*
38205304565SCedric Chaumont 	 * Initialize digest operations
38305304565SCedric Chaumont 	 * Other multi-stage operations initialized w/ TEE_xxxInit functions
38405304565SCedric Chaumont 	 * Non-applicable on asymmetric operations
38505304565SCedric Chaumont 	 */
38605304565SCedric Chaumont 	if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) {
3872c028fdeSJerome Forissier 		res = _utee_hash_init(op->state, NULL, 0);
38805304565SCedric Chaumont 		if (res != TEE_SUCCESS)
389b66f219bSJens Wiklander 			goto out;
39005304565SCedric Chaumont 		/* v1.1: flags always set for digest operations */
39105304565SCedric Chaumont 		op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
39205304565SCedric Chaumont 	}
39305304565SCedric Chaumont 
394642a1607SCedric Chaumont 	op->operationState = TEE_OPERATION_STATE_INITIAL;
395642a1607SCedric Chaumont 
396b0104773SPascal Brand 	*operation = op;
397b0104773SPascal Brand 
398b66f219bSJens Wiklander out:
399b66f219bSJens Wiklander 	if (res != TEE_SUCCESS) {
400b66f219bSJens Wiklander 		if (res != TEE_ERROR_OUT_OF_MEMORY &&
4019b52c538SCedric Chaumont 		    res != TEE_ERROR_NOT_SUPPORTED)
402b36311adSJerome Forissier 			TEE_Panic(res);
403b66f219bSJens Wiklander 		if (op) {
404b66f219bSJens Wiklander 			if (op->state) {
405b66f219bSJens Wiklander 				TEE_FreeOperation(op);
406b66f219bSJens Wiklander 			} else {
407b66f219bSJens Wiklander 				TEE_Free(op->buffer);
408b66f219bSJens Wiklander 				TEE_FreeTransientObject(op->key1);
409b66f219bSJens Wiklander 				TEE_FreeTransientObject(op->key2);
410b66f219bSJens Wiklander 				TEE_Free(op);
411b66f219bSJens Wiklander 			}
412b66f219bSJens Wiklander 		}
413b66f219bSJens Wiklander 	}
414b66f219bSJens Wiklander 
415b0104773SPascal Brand 	return res;
416b0104773SPascal Brand }
417b0104773SPascal Brand 
418b0104773SPascal Brand void TEE_FreeOperation(TEE_OperationHandle operation)
419b0104773SPascal Brand {
420e889e80bSCedric Chaumont 	TEE_Result res;
421e889e80bSCedric Chaumont 
422e889e80bSCedric Chaumont 	if (operation == TEE_HANDLE_NULL)
423c036e912SJens Wiklander 		return;
424e889e80bSCedric Chaumont 
425b0104773SPascal Brand 	/*
426b0104773SPascal Brand 	 * Note that keys should not be freed here, since they are
427b0104773SPascal Brand 	 * claimed by the operation they will be freed by
428b0104773SPascal Brand 	 * utee_cryp_state_free().
429b0104773SPascal Brand 	 */
4302c028fdeSJerome Forissier 	res = _utee_cryp_state_free(operation->state);
431e889e80bSCedric Chaumont 	if (res != TEE_SUCCESS)
432b36311adSJerome Forissier 		TEE_Panic(res);
433e889e80bSCedric Chaumont 
434b0104773SPascal Brand 	TEE_Free(operation->buffer);
435b0104773SPascal Brand 	TEE_Free(operation);
436b0104773SPascal Brand }
437b0104773SPascal Brand 
438c036e912SJens Wiklander void __GP11_TEE_FreeOperation(TEE_OperationHandle operation)
439c036e912SJens Wiklander {
440c036e912SJens Wiklander 	if (operation == TEE_HANDLE_NULL)
441c036e912SJens Wiklander 		TEE_Panic(0);
442c036e912SJens Wiklander 	TEE_FreeOperation(operation);
443c036e912SJens Wiklander }
444c036e912SJens Wiklander 
445b0104773SPascal Brand void TEE_GetOperationInfo(TEE_OperationHandle operation,
446b0104773SPascal Brand 			  TEE_OperationInfo *operationInfo)
447b0104773SPascal Brand {
448b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
449b0104773SPascal Brand 		TEE_Panic(0);
450b0104773SPascal Brand 
4516915bbbbSJens Wiklander 	__utee_check_out_annotation(operationInfo, sizeof(*operationInfo));
452b0104773SPascal Brand 
453b0104773SPascal Brand 	*operationInfo = operation->info;
454bac3a8a7SJens Wiklander 	if (operationInfo->handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) {
455bac3a8a7SJens Wiklander 		operationInfo->keySize = 0;
456bac3a8a7SJens Wiklander 		operationInfo->requiredKeyUsage = 0;
457bac3a8a7SJens Wiklander 	}
458b0104773SPascal Brand }
459b0104773SPascal Brand 
460ee2f75afSJens Wiklander TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle op,
461ee2f75afSJens Wiklander 					TEE_OperationInfoMultiple *op_info,
462cb98b7b2SJens Wiklander 					size_t *size)
46305304565SCedric Chaumont {
46405304565SCedric Chaumont 	TEE_Result res = TEE_SUCCESS;
465ee2f75afSJens Wiklander 	TEE_ObjectInfo kinfo = { };
466ee2f75afSJens Wiklander 	size_t max_key_count = 0;
467ee2f75afSJens Wiklander 	bool two_keys = false;
46805304565SCedric Chaumont 
469ee2f75afSJens Wiklander 	if (op == TEE_HANDLE_NULL) {
47005304565SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
47105304565SCedric Chaumont 		goto out;
47205304565SCedric Chaumont 	}
47305304565SCedric Chaumont 
474cb98b7b2SJens Wiklander 	__utee_check_outbuf_annotation(op_info, size);
47505304565SCedric Chaumont 
476ee2f75afSJens Wiklander 	if (*size < sizeof(*op_info)) {
477ee2f75afSJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
478ee2f75afSJens Wiklander 		goto out;
479ee2f75afSJens Wiklander 	}
480ee2f75afSJens Wiklander 	max_key_count = (*size - sizeof(*op_info)) /
48105304565SCedric Chaumont 			sizeof(TEE_OperationInfoKey);
48205304565SCedric Chaumont 
483ee2f75afSJens Wiklander 	TEE_MemFill(op_info, 0, *size);
48405304565SCedric Chaumont 
48505304565SCedric Chaumont 	/* Two keys flag (TEE_ALG_AES_XTS only) */
486ee2f75afSJens Wiklander 	two_keys = op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;
487ee2f75afSJens Wiklander 
488ee2f75afSJens Wiklander 	if (op->info.mode == TEE_MODE_DIGEST) {
489ee2f75afSJens Wiklander 		op_info->numberOfKeys = 0;
490ee2f75afSJens Wiklander 	} else if (!two_keys) {
491ee2f75afSJens Wiklander 		if (max_key_count < 1) {
49205304565SCedric Chaumont 			res = TEE_ERROR_SHORT_BUFFER;
49305304565SCedric Chaumont 			goto out;
49405304565SCedric Chaumont 		}
49505304565SCedric Chaumont 
496ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key1, &kinfo);
497ee2f75afSJens Wiklander 		/* Key1 is not a valid handle, "can't happen". */
498ee2f75afSJens Wiklander 		if (res)
49905304565SCedric Chaumont 			goto out;
50005304565SCedric Chaumont 
501d372a47cSJens Wiklander 		op_info->keyInformation[0].keySize = kinfo.objectSize;
502ee2f75afSJens Wiklander 		op_info->keyInformation[0].requiredKeyUsage =
503ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
504ee2f75afSJens Wiklander 		op_info->numberOfKeys = 1;
505ee2f75afSJens Wiklander 	} else {
506ee2f75afSJens Wiklander 		if (max_key_count < 2) {
507ee2f75afSJens Wiklander 			res = TEE_ERROR_SHORT_BUFFER;
50805304565SCedric Chaumont 			goto out;
50905304565SCedric Chaumont 		}
51005304565SCedric Chaumont 
511ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key1, &kinfo);
512ee2f75afSJens Wiklander 		/* Key1 is not a valid handle, "can't happen". */
513ee2f75afSJens Wiklander 		if (res)
514ee2f75afSJens Wiklander 			goto out;
515ee2f75afSJens Wiklander 
516d372a47cSJens Wiklander 		op_info->keyInformation[0].keySize = kinfo.objectSize;
517ee2f75afSJens Wiklander 		op_info->keyInformation[0].requiredKeyUsage =
518ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
519ee2f75afSJens Wiklander 
520ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key2, &kinfo);
521ee2f75afSJens Wiklander 		/* Key2 is not a valid handle, "can't happen". */
522ee2f75afSJens Wiklander 		if (res)
523ee2f75afSJens Wiklander 			goto out;
524ee2f75afSJens Wiklander 
525d372a47cSJens Wiklander 		op_info->keyInformation[1].keySize = kinfo.objectSize;
526ee2f75afSJens Wiklander 		op_info->keyInformation[1].requiredKeyUsage =
527ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
528ee2f75afSJens Wiklander 
529ee2f75afSJens Wiklander 		op_info->numberOfKeys = 2;
53005304565SCedric Chaumont 	}
53105304565SCedric Chaumont 
532ee2f75afSJens Wiklander 	op_info->algorithm = op->info.algorithm;
533ee2f75afSJens Wiklander 	op_info->operationClass = op->info.operationClass;
534ee2f75afSJens Wiklander 	op_info->mode = op->info.mode;
535ee2f75afSJens Wiklander 	op_info->digestLength = op->info.digestLength;
536ee2f75afSJens Wiklander 	op_info->maxKeySize = op->info.maxKeySize;
537ee2f75afSJens Wiklander 	op_info->handleState = op->info.handleState;
538ee2f75afSJens Wiklander 	op_info->operationState = op->operationState;
53905304565SCedric Chaumont 
54005304565SCedric Chaumont out:
54105304565SCedric Chaumont 	if (res != TEE_SUCCESS &&
54205304565SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
543b36311adSJerome Forissier 		TEE_Panic(res);
54405304565SCedric Chaumont 
54505304565SCedric Chaumont 	return res;
54605304565SCedric Chaumont }
54705304565SCedric Chaumont 
548cb98b7b2SJens Wiklander TEE_Result
549cb98b7b2SJens Wiklander __GP11_TEE_GetOperationInfoMultiple(TEE_OperationHandle operation,
550cb98b7b2SJens Wiklander 				    TEE_OperationInfoMultiple *info,
551cb98b7b2SJens Wiklander 				    uint32_t *operationSize)
552cb98b7b2SJens Wiklander {
553cb98b7b2SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
554cb98b7b2SJens Wiklander 	size_t s = 0;
555cb98b7b2SJens Wiklander 
556cb98b7b2SJens Wiklander 	__utee_check_gp11_outbuf_annotation(info, operationSize);
557cb98b7b2SJens Wiklander 	s = *operationSize;
558cb98b7b2SJens Wiklander 	res = TEE_GetOperationInfoMultiple(operation, info, &s);
559cb98b7b2SJens Wiklander 	*operationSize = s;
560cb98b7b2SJens Wiklander 	return res;
561cb98b7b2SJens Wiklander }
562cb98b7b2SJens Wiklander 
563b0104773SPascal Brand void TEE_ResetOperation(TEE_OperationHandle operation)
564b0104773SPascal Brand {
565b0104773SPascal Brand 	TEE_Result res;
566b0104773SPascal Brand 
567b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
568b0104773SPascal Brand 		TEE_Panic(0);
569bf80076aSCedric Chaumont 
570642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET))
571bf80076aSCedric Chaumont 			TEE_Panic(0);
572bf80076aSCedric Chaumont 
573642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
574642a1607SCedric Chaumont 
575b0104773SPascal Brand 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
5762c028fdeSJerome Forissier 		res = _utee_hash_init(operation->state, NULL, 0);
577b0104773SPascal Brand 		if (res != TEE_SUCCESS)
578b0104773SPascal Brand 			TEE_Panic(res);
57905304565SCedric Chaumont 		operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
58005304565SCedric Chaumont 	} else {
581b0104773SPascal Brand 		operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
582b0104773SPascal Brand 	}
58305304565SCedric Chaumont }
584b0104773SPascal Brand 
585b0104773SPascal Brand TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation,
586b0104773SPascal Brand 			       TEE_ObjectHandle key)
587b0104773SPascal Brand {
5887583c59eSCedric Chaumont 	TEE_Result res;
589b0104773SPascal Brand 	uint32_t key_size = 0;
590b0104773SPascal Brand 	TEE_ObjectInfo key_info;
591b0104773SPascal Brand 
592a57c1e2eSCedric Chaumont 	if (operation == TEE_HANDLE_NULL) {
593a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
594a57c1e2eSCedric Chaumont 		goto out;
595a57c1e2eSCedric Chaumont 	}
596a57c1e2eSCedric Chaumont 
597642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
598642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
599642a1607SCedric Chaumont 		goto out;
600642a1607SCedric Chaumont 	}
601642a1607SCedric Chaumont 
602a57c1e2eSCedric Chaumont 	if (key == TEE_HANDLE_NULL) {
603a57c1e2eSCedric Chaumont 		/* Operation key cleared */
604a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key1);
6056c4ea258SJens Wiklander 		operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
6066c4ea258SJens Wiklander 		return TEE_SUCCESS;
607a57c1e2eSCedric Chaumont 	}
608a57c1e2eSCedric Chaumont 
609a57c1e2eSCedric Chaumont 	/* No key for digest operation */
610a57c1e2eSCedric Chaumont 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
611a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
612a57c1e2eSCedric Chaumont 		goto out;
613a57c1e2eSCedric Chaumont 	}
614a57c1e2eSCedric Chaumont 
615a57c1e2eSCedric Chaumont 	/* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */
616a57c1e2eSCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) !=
617a57c1e2eSCedric Chaumont 	    0) {
618a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
619a57c1e2eSCedric Chaumont 		goto out;
620a57c1e2eSCedric Chaumont 	}
621a57c1e2eSCedric Chaumont 
6227583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key, &key_info);
623a57c1e2eSCedric Chaumont 	/* Key is not a valid handle */
6247583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
625a57c1e2eSCedric Chaumont 		goto out;
6267583c59eSCedric Chaumont 
627b0104773SPascal Brand 	/* Supplied key has to meet required usage */
628b0104773SPascal Brand 	if ((key_info.objectUsage & operation->info.requiredKeyUsage) !=
629b0104773SPascal Brand 	    operation->info.requiredKeyUsage) {
630a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
631a57c1e2eSCedric Chaumont 		goto out;
632b0104773SPascal Brand 	}
633b0104773SPascal Brand 
634d372a47cSJens Wiklander 	if (operation->info.maxKeySize < key_info.objectSize) {
635a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
636a57c1e2eSCedric Chaumont 		goto out;
637a57c1e2eSCedric Chaumont 	}
638b0104773SPascal Brand 
639d372a47cSJens Wiklander 	key_size = key_info.objectSize;
640b0104773SPascal Brand 
641b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key1);
642b0104773SPascal Brand 	operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
643b0104773SPascal Brand 
6447583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key1, key);
6457583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
646a57c1e2eSCedric Chaumont 		goto out;
6477583c59eSCedric Chaumont 
648b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET;
649b0104773SPascal Brand 
650b0104773SPascal Brand 	operation->info.keySize = key_size;
651b0104773SPascal Brand 
6527583c59eSCedric Chaumont out:
653a57c1e2eSCedric Chaumont 	if (res != TEE_SUCCESS  &&
654a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT &&
655a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE)
656b36311adSJerome Forissier 		TEE_Panic(res);
657a57c1e2eSCedric Chaumont 
658a57c1e2eSCedric Chaumont 	return res;
659b0104773SPascal Brand }
660b0104773SPascal Brand 
661b0104773SPascal Brand TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation,
662b0104773SPascal Brand 				TEE_ObjectHandle key1, TEE_ObjectHandle key2)
663b0104773SPascal Brand {
6647583c59eSCedric Chaumont 	TEE_Result res;
665b0104773SPascal Brand 	uint32_t key_size = 0;
666b0104773SPascal Brand 	TEE_ObjectInfo key_info1;
667b0104773SPascal Brand 	TEE_ObjectInfo key_info2;
668b0104773SPascal Brand 
669a57c1e2eSCedric Chaumont 	if (operation == TEE_HANDLE_NULL) {
670a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
671a57c1e2eSCedric Chaumont 		goto out;
672a57c1e2eSCedric Chaumont 	}
673a57c1e2eSCedric Chaumont 
674642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
675642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
676642a1607SCedric Chaumont 		goto out;
677642a1607SCedric Chaumont 	}
678642a1607SCedric Chaumont 
679a57c1e2eSCedric Chaumont 	/*
680a57c1e2eSCedric Chaumont 	 * Key1/Key2 and/or are not initialized and
681a57c1e2eSCedric Chaumont 	 * Either both keys are NULL or both are not NULL
682a57c1e2eSCedric Chaumont 	 */
6836c4ea258SJens Wiklander 	if (!key1 && !key2) {
6846c4ea258SJens Wiklander 		/* Clear the keys */
685a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key1);
686a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key2);
6876c4ea258SJens Wiklander 		operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
6886c4ea258SJens Wiklander 		return TEE_SUCCESS;
6896c4ea258SJens Wiklander 	} else if (!key1 || !key2) {
6906c4ea258SJens Wiklander 		/* Both keys are obviously not valid. */
691a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
692a57c1e2eSCedric Chaumont 		goto out;
693a57c1e2eSCedric Chaumont 	}
694a57c1e2eSCedric Chaumont 
695a57c1e2eSCedric Chaumont 	/* No key for digest operation */
696a57c1e2eSCedric Chaumont 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
697a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
698a57c1e2eSCedric Chaumont 		goto out;
699a57c1e2eSCedric Chaumont 	}
700a57c1e2eSCedric Chaumont 
7015b385b3fSJerome Forissier 	/* Two keys flag expected (TEE_ALG_AES_XTS and TEE_ALG_SM2_KEP only) */
702a57c1e2eSCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) ==
703a57c1e2eSCedric Chaumont 	    0) {
704a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
705a57c1e2eSCedric Chaumont 		goto out;
706a57c1e2eSCedric Chaumont 	}
707a57c1e2eSCedric Chaumont 
7087583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key1, &key_info1);
709a57c1e2eSCedric Chaumont 	/* Key1 is not a valid handle */
7107583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
711a57c1e2eSCedric Chaumont 		goto out;
7127583c59eSCedric Chaumont 
713b0104773SPascal Brand 	/* Supplied key has to meet required usage */
714b0104773SPascal Brand 	if ((key_info1.objectUsage & operation->info.
715b0104773SPascal Brand 	     requiredKeyUsage) != operation->info.requiredKeyUsage) {
716a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
717a57c1e2eSCedric Chaumont 		goto out;
718b0104773SPascal Brand 	}
719b0104773SPascal Brand 
7207583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key2, &key_info2);
721a57c1e2eSCedric Chaumont 	/* Key2 is not a valid handle */
7227583c59eSCedric Chaumont 	if (res != TEE_SUCCESS) {
7237583c59eSCedric Chaumont 		if (res == TEE_ERROR_CORRUPT_OBJECT)
7247583c59eSCedric Chaumont 			res = TEE_ERROR_CORRUPT_OBJECT_2;
725a57c1e2eSCedric Chaumont 		goto out;
7267583c59eSCedric Chaumont 	}
7277583c59eSCedric Chaumont 
728b0104773SPascal Brand 	/* Supplied key has to meet required usage */
729b0104773SPascal Brand 	if ((key_info2.objectUsage & operation->info.
730b0104773SPascal Brand 	     requiredKeyUsage) != operation->info.requiredKeyUsage) {
731a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
732a57c1e2eSCedric Chaumont 		goto out;
733b0104773SPascal Brand 	}
734b0104773SPascal Brand 
735b0104773SPascal Brand 	/*
7365b385b3fSJerome Forissier 	 * All the multi key algorithm currently supported requires the keys to
7375b385b3fSJerome Forissier 	 * be of equal size.
738b0104773SPascal Brand 	 */
739d372a47cSJens Wiklander 	if (key_info1.objectSize != key_info2.objectSize) {
740a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
741a57c1e2eSCedric Chaumont 		goto out;
742b0104773SPascal Brand 
743a57c1e2eSCedric Chaumont 	}
744a57c1e2eSCedric Chaumont 
745d372a47cSJens Wiklander 	if (operation->info.maxKeySize < key_info1.objectSize) {
746a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
747a57c1e2eSCedric Chaumont 		goto out;
748a57c1e2eSCedric Chaumont 	}
749b0104773SPascal Brand 
750b0104773SPascal Brand 	/*
751b0104773SPascal Brand 	 * Odd that only the size of one key should be reported while
752b0104773SPascal Brand 	 * size of two key are used when allocating the operation.
753b0104773SPascal Brand 	 */
754d372a47cSJens Wiklander 	key_size = key_info1.objectSize;
755b0104773SPascal Brand 
756b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key1);
757b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key2);
758b0104773SPascal Brand 	operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
759b0104773SPascal Brand 
7607583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key1, key1);
7617583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
762a57c1e2eSCedric Chaumont 		goto out;
7637583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key2, key2);
7647583c59eSCedric Chaumont 	if (res != TEE_SUCCESS) {
7657583c59eSCedric Chaumont 		if (res == TEE_ERROR_CORRUPT_OBJECT)
7667583c59eSCedric Chaumont 			res = TEE_ERROR_CORRUPT_OBJECT_2;
767a57c1e2eSCedric Chaumont 		goto out;
7687583c59eSCedric Chaumont 	}
7697583c59eSCedric Chaumont 
770b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET;
771b0104773SPascal Brand 
772b0104773SPascal Brand 	operation->info.keySize = key_size;
773b0104773SPascal Brand 
7747583c59eSCedric Chaumont out:
775a57c1e2eSCedric Chaumont 	if (res != TEE_SUCCESS  &&
776a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT &&
777a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT_2 &&
778a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE &&
779a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2)
780b36311adSJerome Forissier 		TEE_Panic(res);
781a57c1e2eSCedric Chaumont 
782a57c1e2eSCedric Chaumont 	return res;
783b0104773SPascal Brand }
784b0104773SPascal Brand 
785b0104773SPascal Brand void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op)
786b0104773SPascal Brand {
787b0104773SPascal Brand 	TEE_Result res;
788b0104773SPascal Brand 
789b0104773SPascal Brand 	if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL)
790b0104773SPascal Brand 		TEE_Panic(0);
791b0104773SPascal Brand 	if (dst_op->info.algorithm != src_op->info.algorithm)
792b0104773SPascal Brand 		TEE_Panic(0);
7938734de30SJens Wiklander 	if (dst_op->info.mode != src_op->info.mode)
7948734de30SJens Wiklander 		TEE_Panic(0);
795b0104773SPascal Brand 	if (src_op->info.operationClass != TEE_OPERATION_DIGEST) {
796b0104773SPascal Brand 		TEE_ObjectHandle key1 = TEE_HANDLE_NULL;
797b0104773SPascal Brand 		TEE_ObjectHandle key2 = TEE_HANDLE_NULL;
798b0104773SPascal Brand 
799b0104773SPascal Brand 		if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) {
800b0104773SPascal Brand 			key1 = src_op->key1;
801b0104773SPascal Brand 			key2 = src_op->key2;
802b0104773SPascal Brand 		}
803b0104773SPascal Brand 
804b0104773SPascal Brand 		if ((src_op->info.handleState &
805b0104773SPascal Brand 		     TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) {
806b0104773SPascal Brand 			TEE_SetOperationKey(dst_op, key1);
807b0104773SPascal Brand 		} else {
808b0104773SPascal Brand 			TEE_SetOperationKey2(dst_op, key1, key2);
809b0104773SPascal Brand 		}
810b0104773SPascal Brand 	}
811b0104773SPascal Brand 	dst_op->info.handleState = src_op->info.handleState;
812b0104773SPascal Brand 	dst_op->info.keySize = src_op->info.keySize;
8138e07702eSJens Wiklander 	dst_op->info.digestLength = src_op->info.digestLength;
814642a1607SCedric Chaumont 	dst_op->operationState = src_op->operationState;
815b0104773SPascal Brand 
816b0104773SPascal Brand 	if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks ||
817b0104773SPascal Brand 	    dst_op->block_size != src_op->block_size)
818b0104773SPascal Brand 		TEE_Panic(0);
819b0104773SPascal Brand 
820b0104773SPascal Brand 	if (dst_op->buffer != NULL) {
821*24ea7613SJens Wiklander 		size_t sz = src_op->block_size;
822*24ea7613SJens Wiklander 
823b0104773SPascal Brand 		if (src_op->buffer == NULL)
824b0104773SPascal Brand 			TEE_Panic(0);
825b0104773SPascal Brand 
826*24ea7613SJens Wiklander 		if (src_op->buffer_two_blocks)
827*24ea7613SJens Wiklander 			sz *= 2;
828*24ea7613SJens Wiklander 		memcpy(dst_op->buffer, src_op->buffer, sz);
829b0104773SPascal Brand 		dst_op->buffer_offs = src_op->buffer_offs;
830b0104773SPascal Brand 	} else if (src_op->buffer != NULL) {
831b0104773SPascal Brand 		TEE_Panic(0);
832b0104773SPascal Brand 	}
833b0104773SPascal Brand 
8342c028fdeSJerome Forissier 	res = _utee_cryp_state_copy(dst_op->state, src_op->state);
835b0104773SPascal Brand 	if (res != TEE_SUCCESS)
836b0104773SPascal Brand 		TEE_Panic(res);
837b0104773SPascal Brand }
838b0104773SPascal Brand 
839b0104773SPascal Brand /* Cryptographic Operations API - Message Digest Functions */
840b0104773SPascal Brand 
8418f07fe6fSJerome Forissier static void init_hash_operation(TEE_OperationHandle operation, const void *IV,
8426d15db08SJerome Forissier 				uint32_t IVLen)
8436d15db08SJerome Forissier {
8446d15db08SJerome Forissier 	TEE_Result res;
8456d15db08SJerome Forissier 
8466d15db08SJerome Forissier 	/*
8476d15db08SJerome Forissier 	 * Note : IV and IVLen are never used in current implementation
8486d15db08SJerome Forissier 	 * This is why coherent values of IV and IVLen are not checked
8496d15db08SJerome Forissier 	 */
8502c028fdeSJerome Forissier 	res = _utee_hash_init(operation->state, IV, IVLen);
8516d15db08SJerome Forissier 	if (res != TEE_SUCCESS)
8526d15db08SJerome Forissier 		TEE_Panic(res);
8536d15db08SJerome Forissier 	operation->buffer_offs = 0;
8546d15db08SJerome Forissier 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
8556d15db08SJerome Forissier }
8566d15db08SJerome Forissier 
857b0104773SPascal Brand void TEE_DigestUpdate(TEE_OperationHandle operation,
858185bf58cSJens Wiklander 		      const void *chunk, size_t chunkSize)
859b0104773SPascal Brand {
86073d6c3baSJoakim Bech 	TEE_Result res = TEE_ERROR_GENERIC;
861b0104773SPascal Brand 
86273d6c3baSJoakim Bech 	if (operation == TEE_HANDLE_NULL ||
86373d6c3baSJoakim Bech 	    operation->info.operationClass != TEE_OPERATION_DIGEST)
864b0104773SPascal Brand 		TEE_Panic(0);
86573d6c3baSJoakim Bech 
866642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
867642a1607SCedric Chaumont 
8682c028fdeSJerome Forissier 	res = _utee_hash_update(operation->state, chunk, chunkSize);
869b0104773SPascal Brand 	if (res != TEE_SUCCESS)
870b0104773SPascal Brand 		TEE_Panic(res);
871b0104773SPascal Brand }
872b0104773SPascal Brand 
873185bf58cSJens Wiklander void __GP11_TEE_DigestUpdate(TEE_OperationHandle operation,
874185bf58cSJens Wiklander 			     const void *chunk, uint32_t chunkSize)
875185bf58cSJens Wiklander {
876185bf58cSJens Wiklander 	return TEE_DigestUpdate(operation, chunk, chunkSize);
877185bf58cSJens Wiklander }
878185bf58cSJens Wiklander 
8798f07fe6fSJerome Forissier TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk,
880185bf58cSJens Wiklander 			     size_t chunkLen, void *hash, size_t *hashLen)
881b0104773SPascal Brand {
882*24ea7613SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
883*24ea7613SJens Wiklander 	uint64_t hl = 0;
884*24ea7613SJens Wiklander 	size_t len = 0;
88587c2f6b6SCedric Chaumont 
88687c2f6b6SCedric Chaumont 	if ((operation == TEE_HANDLE_NULL) ||
88787c2f6b6SCedric Chaumont 	    (!chunk && chunkLen) ||
88887c2f6b6SCedric Chaumont 	    (operation->info.operationClass != TEE_OPERATION_DIGEST)) {
88987c2f6b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
89087c2f6b6SCedric Chaumont 		goto out;
89187c2f6b6SCedric Chaumont 	}
892*24ea7613SJens Wiklander 	if (operation->operationState == TEE_OPERATION_STATE_EXTRACTING &&
893*24ea7613SJens Wiklander 	    chunkLen) {
894*24ea7613SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
895*24ea7613SJens Wiklander 		goto out;
896*24ea7613SJens Wiklander 	}
8976915bbbbSJens Wiklander 	__utee_check_inout_annotation(hashLen, sizeof(*hashLen));
89887c2f6b6SCedric Chaumont 
899*24ea7613SJens Wiklander 	if (operation->operationState == TEE_OPERATION_STATE_EXTRACTING &&
900*24ea7613SJens Wiklander 	    operation->buffer) {
901*24ea7613SJens Wiklander 		/*
902*24ea7613SJens Wiklander 		 * This is not an Extendable-Output Function and we have
903*24ea7613SJens Wiklander 		 * already started extracting
904*24ea7613SJens Wiklander 		 */
905*24ea7613SJens Wiklander 		len = MIN(operation->block_size - operation->buffer_offs,
906*24ea7613SJens Wiklander 			  *hashLen);
907*24ea7613SJens Wiklander 		memcpy(hash, operation->buffer + operation->buffer_offs, len);
908*24ea7613SJens Wiklander 		*hashLen = len;
909*24ea7613SJens Wiklander 	} else {
910e86f1266SJens Wiklander 		hl = *hashLen;
911*24ea7613SJens Wiklander 		res = _utee_hash_final(operation->state, chunk, chunkLen, hash,
912*24ea7613SJens Wiklander 				       &hl);
913e86f1266SJens Wiklander 		*hashLen = hl;
914*24ea7613SJens Wiklander 		if (res)
9156d15db08SJerome Forissier 			goto out;
916*24ea7613SJens Wiklander 	}
9176d15db08SJerome Forissier 
9186d15db08SJerome Forissier 	/* Reset operation state */
9196d15db08SJerome Forissier 	init_hash_operation(operation, NULL, 0);
92087c2f6b6SCedric Chaumont 
921642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
922642a1607SCedric Chaumont 
92387c2f6b6SCedric Chaumont out:
92487c2f6b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
92587c2f6b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
926b36311adSJerome Forissier 		TEE_Panic(res);
92773d6c3baSJoakim Bech 
92887c2f6b6SCedric Chaumont 	return res;
929b0104773SPascal Brand }
930b0104773SPascal Brand 
931185bf58cSJens Wiklander TEE_Result __GP11_TEE_DigestDoFinal(TEE_OperationHandle operation,
932185bf58cSJens Wiklander 				    const void *chunk, uint32_t chunkLen,
933185bf58cSJens Wiklander 				    void *hash, uint32_t *hashLen)
934185bf58cSJens Wiklander {
935185bf58cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
936185bf58cSJens Wiklander 	size_t l = 0;
937185bf58cSJens Wiklander 
938185bf58cSJens Wiklander 	__utee_check_inout_annotation(hashLen, sizeof(*hashLen));
939185bf58cSJens Wiklander 	l = *hashLen;
940185bf58cSJens Wiklander 	res = TEE_DigestDoFinal(operation, chunk, chunkLen, hash, &l);
941185bf58cSJens Wiklander 	*hashLen = l;
942185bf58cSJens Wiklander 	return res;
943185bf58cSJens Wiklander }
944185bf58cSJens Wiklander 
945*24ea7613SJens Wiklander TEE_Result TEE_DigestExtract(TEE_OperationHandle operation, void *hash,
946*24ea7613SJens Wiklander 			     size_t *hashLen)
947*24ea7613SJens Wiklander {
948*24ea7613SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
949*24ea7613SJens Wiklander 	uint64_t hl = 0;
950*24ea7613SJens Wiklander 	size_t len = 0;
951*24ea7613SJens Wiklander 
952*24ea7613SJens Wiklander 	if (operation == TEE_HANDLE_NULL ||
953*24ea7613SJens Wiklander 	    operation->info.operationClass != TEE_OPERATION_DIGEST)
954*24ea7613SJens Wiklander 		TEE_Panic(0);
955*24ea7613SJens Wiklander 	__utee_check_inout_annotation(hashLen, sizeof(*hashLen));
956*24ea7613SJens Wiklander 
957*24ea7613SJens Wiklander 	if (!operation->buffer) {
958*24ea7613SJens Wiklander 		/* This is an Extendable-Output Function */
959*24ea7613SJens Wiklander 		operation->info.handleState |= TEE_HANDLE_FLAG_EXTRACTING;
960*24ea7613SJens Wiklander 		operation->operationState = TEE_OPERATION_STATE_EXTRACTING;
961*24ea7613SJens Wiklander 		hl = *hashLen;
962*24ea7613SJens Wiklander 		res = _utee_hash_final(operation->state, NULL, 0, hash, &hl);
963*24ea7613SJens Wiklander 		if (res)
964*24ea7613SJens Wiklander 			TEE_Panic(0);
965*24ea7613SJens Wiklander 		*hashLen = hl;
966*24ea7613SJens Wiklander 
967*24ea7613SJens Wiklander 		return TEE_SUCCESS;
968*24ea7613SJens Wiklander 	}
969*24ea7613SJens Wiklander 
970*24ea7613SJens Wiklander 	if (operation->operationState != TEE_OPERATION_STATE_EXTRACTING) {
971*24ea7613SJens Wiklander 		hl = operation->block_size;
972*24ea7613SJens Wiklander 		res = _utee_hash_final(operation->state, NULL, 0,
973*24ea7613SJens Wiklander 				       operation->buffer, &hl);
974*24ea7613SJens Wiklander 		if (res)
975*24ea7613SJens Wiklander 			TEE_Panic(0);
976*24ea7613SJens Wiklander 		if (hl != operation->block_size)
977*24ea7613SJens Wiklander 			TEE_Panic(0);
978*24ea7613SJens Wiklander 		assert(!operation->buffer_offs);
979*24ea7613SJens Wiklander 		operation->info.handleState |= TEE_HANDLE_FLAG_EXTRACTING;
980*24ea7613SJens Wiklander 		operation->operationState = TEE_OPERATION_STATE_EXTRACTING;
981*24ea7613SJens Wiklander 	}
982*24ea7613SJens Wiklander 
983*24ea7613SJens Wiklander 	len = MIN(operation->block_size - operation->buffer_offs, *hashLen);
984*24ea7613SJens Wiklander 	memcpy(hash, operation->buffer + operation->buffer_offs, len);
985*24ea7613SJens Wiklander 	*hashLen = len;
986*24ea7613SJens Wiklander 	operation->buffer_offs += len;
987*24ea7613SJens Wiklander 
988*24ea7613SJens Wiklander 	return TEE_SUCCESS;
989*24ea7613SJens Wiklander }
990*24ea7613SJens Wiklander 
991b0104773SPascal Brand /* Cryptographic Operations API - Symmetric Cipher Functions */
992b0104773SPascal Brand 
9938f07fe6fSJerome Forissier void TEE_CipherInit(TEE_OperationHandle operation, const void *IV,
994185bf58cSJens Wiklander 		    size_t IVLen)
995b0104773SPascal Brand {
996b0104773SPascal Brand 	TEE_Result res;
997b0104773SPascal Brand 
998b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
999b0104773SPascal Brand 		TEE_Panic(0);
1000642a1607SCedric Chaumont 
1001b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_CIPHER)
1002b0104773SPascal Brand 		TEE_Panic(0);
1003642a1607SCedric Chaumont 
1004642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||
1005642a1607SCedric Chaumont 	    !(operation->key1))
1006642a1607SCedric Chaumont 		TEE_Panic(0);
1007642a1607SCedric Chaumont 
1008642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
1009642a1607SCedric Chaumont 		TEE_ResetOperation(operation);
1010642a1607SCedric Chaumont 
1011ad7aa2a5SSadiq Hussain 	if (IV && IVLen) {
1012ad7aa2a5SSadiq Hussain 		if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD ||
1013ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD ||
1014ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD ||
1015ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD)
1016ad7aa2a5SSadiq Hussain 			TEE_Panic(0);
1017ad7aa2a5SSadiq Hussain 	}
1018ad7aa2a5SSadiq Hussain 
1019642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1020642a1607SCedric Chaumont 
10212c028fdeSJerome Forissier 	res = _utee_cipher_init(operation->state, IV, IVLen);
1022b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1023b0104773SPascal Brand 		TEE_Panic(res);
1024642a1607SCedric Chaumont 
1025b0104773SPascal Brand 	operation->buffer_offs = 0;
1026b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
1027b0104773SPascal Brand }
1028b0104773SPascal Brand 
1029185bf58cSJens Wiklander void __GP11_TEE_CipherInit(TEE_OperationHandle operation, const void *IV,
1030185bf58cSJens Wiklander 			   uint32_t IVLen)
1031185bf58cSJens Wiklander {
1032185bf58cSJens Wiklander 	return TEE_CipherInit(operation, IV, IVLen);
1033185bf58cSJens Wiklander }
1034185bf58cSJens Wiklander 
1035b0104773SPascal Brand static TEE_Result tee_buffer_update(
1036b0104773SPascal Brand 		TEE_OperationHandle op,
1037e86f1266SJens Wiklander 		TEE_Result(*update_func)(unsigned long state, const void *src,
1038e86f1266SJens Wiklander 				size_t slen, void *dst, uint64_t *dlen),
1039b0104773SPascal Brand 		const void *src_data, size_t src_len,
1040e86f1266SJens Wiklander 		void *dest_data, uint64_t *dest_len)
1041b0104773SPascal Brand {
1042b0104773SPascal Brand 	TEE_Result res;
1043b0104773SPascal Brand 	const uint8_t *src = src_data;
1044b0104773SPascal Brand 	size_t slen = src_len;
1045b0104773SPascal Brand 	uint8_t *dst = dest_data;
1046b0104773SPascal Brand 	size_t dlen = *dest_len;
1047b0104773SPascal Brand 	size_t acc_dlen = 0;
1048e86f1266SJens Wiklander 	uint64_t tmp_dlen;
1049b0104773SPascal Brand 	size_t l;
1050b0104773SPascal Brand 	size_t buffer_size;
1051d3588802SPascal Brand 	size_t buffer_left;
1052b0104773SPascal Brand 
1053090268f5SJens Wiklander 	if (!src) {
1054090268f5SJens Wiklander 		if (slen)
1055090268f5SJens Wiklander 			TEE_Panic(0);
1056090268f5SJens Wiklander 		goto out;
1057090268f5SJens Wiklander 	}
1058090268f5SJens Wiklander 
1059d3588802SPascal Brand 	if (op->buffer_two_blocks) {
1060b0104773SPascal Brand 		buffer_size = op->block_size * 2;
1061d3588802SPascal Brand 		buffer_left = 1;
1062d3588802SPascal Brand 	} else {
1063b0104773SPascal Brand 		buffer_size = op->block_size;
1064d3588802SPascal Brand 		buffer_left = 0;
1065d3588802SPascal Brand 	}
1066b0104773SPascal Brand 
1067b0104773SPascal Brand 	if (op->buffer_offs > 0) {
1068b0104773SPascal Brand 		/* Fill up complete block */
1069b0104773SPascal Brand 		if (op->buffer_offs < op->block_size)
1070b0104773SPascal Brand 			l = MIN(slen, op->block_size - op->buffer_offs);
1071b0104773SPascal Brand 		else
1072b0104773SPascal Brand 			l = MIN(slen, buffer_size - op->buffer_offs);
1073b0104773SPascal Brand 		memcpy(op->buffer + op->buffer_offs, src, l);
1074b0104773SPascal Brand 		op->buffer_offs += l;
1075b0104773SPascal Brand 		src += l;
1076b0104773SPascal Brand 		slen -= l;
1077b0104773SPascal Brand 		if ((op->buffer_offs % op->block_size) != 0)
1078b0104773SPascal Brand 			goto out;	/* Nothing left to do */
1079b0104773SPascal Brand 	}
1080b0104773SPascal Brand 
1081b0104773SPascal Brand 	/* If we can feed from buffer */
1082d3588802SPascal Brand 	if ((op->buffer_offs > 0) &&
1083d3588802SPascal Brand 	    ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) {
10842ff3fdbbSPascal Brand 		l = ROUNDUP(op->buffer_offs + slen - buffer_size,
1085b0104773SPascal Brand 				op->block_size);
1086b0104773SPascal Brand 		l = MIN(op->buffer_offs, l);
1087b0104773SPascal Brand 		tmp_dlen = dlen;
1088b0104773SPascal Brand 		res = update_func(op->state, op->buffer, l, dst, &tmp_dlen);
1089b0104773SPascal Brand 		if (res != TEE_SUCCESS)
1090b0104773SPascal Brand 			TEE_Panic(res);
1091b0104773SPascal Brand 		dst += tmp_dlen;
1092b0104773SPascal Brand 		dlen -= tmp_dlen;
1093b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1094b0104773SPascal Brand 		op->buffer_offs -= l;
1095b0104773SPascal Brand 		if (op->buffer_offs > 0) {
1096b0104773SPascal Brand 			/*
1097b0104773SPascal Brand 			 * Slen is small enough to be contained in rest buffer.
1098b0104773SPascal Brand 			 */
1099b0104773SPascal Brand 			memcpy(op->buffer, op->buffer + l, buffer_size - l);
1100b0104773SPascal Brand 			memcpy(op->buffer + op->buffer_offs, src, slen);
1101b0104773SPascal Brand 			op->buffer_offs += slen;
1102b0104773SPascal Brand 			goto out;	/* Nothing left to do */
1103b0104773SPascal Brand 		}
1104b0104773SPascal Brand 	}
1105b0104773SPascal Brand 
1106d3588802SPascal Brand 	if (slen >= (buffer_size + buffer_left)) {
1107b0104773SPascal Brand 		/* Buffer is empty, feed as much as possible from src */
1108bf7a587fSJerome Forissier 		if (op->info.algorithm == TEE_ALG_AES_CTS)
1109b1ecda78SJerome Forissier 			l = ROUNDUP(slen - buffer_size, op->block_size);
1110bf7a587fSJerome Forissier 		else
1111bf7a587fSJerome Forissier 			l = ROUNDUP(slen - buffer_size + 1, op->block_size);
1112b0104773SPascal Brand 
1113b0104773SPascal Brand 		tmp_dlen = dlen;
1114b0104773SPascal Brand 		res = update_func(op->state, src, l, dst, &tmp_dlen);
1115b0104773SPascal Brand 		if (res != TEE_SUCCESS)
1116b0104773SPascal Brand 			TEE_Panic(res);
1117b0104773SPascal Brand 		src += l;
1118b0104773SPascal Brand 		slen -= l;
1119b0104773SPascal Brand 		dst += tmp_dlen;
1120b0104773SPascal Brand 		dlen -= tmp_dlen;
1121b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1122b0104773SPascal Brand 	}
1123b0104773SPascal Brand 
1124b0104773SPascal Brand 	/* Slen is small enough to be contained in buffer. */
1125b0104773SPascal Brand 	memcpy(op->buffer + op->buffer_offs, src, slen);
1126b0104773SPascal Brand 	op->buffer_offs += slen;
1127b0104773SPascal Brand 
1128b0104773SPascal Brand out:
1129b0104773SPascal Brand 	*dest_len = acc_dlen;
1130b0104773SPascal Brand 	return TEE_SUCCESS;
1131b0104773SPascal Brand }
1132b0104773SPascal Brand 
11338f07fe6fSJerome Forissier TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData,
1134185bf58cSJens Wiklander 			    size_t srcLen, void *destData, size_t *destLen)
1135b0104773SPascal Brand {
1136dea1f2b6SCedric Chaumont 	TEE_Result res;
1137b0104773SPascal Brand 	size_t req_dlen;
1138e86f1266SJens Wiklander 	uint64_t dl;
1139b0104773SPascal Brand 
11406915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1141dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1142dea1f2b6SCedric Chaumont 		goto out;
1143dea1f2b6SCedric Chaumont 	}
11446915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1145dea1f2b6SCedric Chaumont 
1146642a1607SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_CIPHER) {
1147dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1148dea1f2b6SCedric Chaumont 		goto out;
1149dea1f2b6SCedric Chaumont 	}
1150dea1f2b6SCedric Chaumont 
1151642a1607SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1152642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1153642a1607SCedric Chaumont 		goto out;
1154642a1607SCedric Chaumont 	}
1155642a1607SCedric Chaumont 
1156642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1157dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1158dea1f2b6SCedric Chaumont 		goto out;
1159dea1f2b6SCedric Chaumont 	}
1160b0104773SPascal Brand 
1161e32c5ddfSJerome Forissier 	if (!srcData && !srcLen) {
1162090268f5SJens Wiklander 		*destLen = 0;
1163e32c5ddfSJerome Forissier 		res = TEE_SUCCESS;
1164e32c5ddfSJerome Forissier 		goto out;
1165e32c5ddfSJerome Forissier 	}
1166e32c5ddfSJerome Forissier 
1167b0104773SPascal Brand 	/* Calculate required dlen */
116857aabac5SBogdan Liulko 	if (operation->block_size > 1) {
116957aabac5SBogdan Liulko 		req_dlen = ((operation->buffer_offs + srcLen) /
117057aabac5SBogdan Liulko 			    operation->block_size) * operation->block_size;
117157aabac5SBogdan Liulko 	} else {
117257aabac5SBogdan Liulko 		req_dlen = srcLen;
117357aabac5SBogdan Liulko 	}
1174642a1607SCedric Chaumont 	if (operation->buffer_two_blocks) {
1175642a1607SCedric Chaumont 		if (req_dlen > operation->block_size * 2)
1176642a1607SCedric Chaumont 			req_dlen -= operation->block_size * 2;
1177b0104773SPascal Brand 		else
1178b0104773SPascal Brand 			req_dlen = 0;
1179b0104773SPascal Brand 	}
1180b0104773SPascal Brand 	/*
1181b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1182b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1183b0104773SPascal Brand 	 * can't restore sync with this API.
1184b0104773SPascal Brand 	 */
1185b0104773SPascal Brand 	if (*destLen < req_dlen) {
1186b0104773SPascal Brand 		*destLen = req_dlen;
1187dea1f2b6SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1188dea1f2b6SCedric Chaumont 		goto out;
1189b0104773SPascal Brand 	}
1190b0104773SPascal Brand 
1191e86f1266SJens Wiklander 	dl = *destLen;
119257aabac5SBogdan Liulko 	if (operation->block_size > 1) {
11932c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_cipher_update, srcData,
119457aabac5SBogdan Liulko 					srcLen, destData, &dl);
119557aabac5SBogdan Liulko 	} else {
119657aabac5SBogdan Liulko 		if (srcLen > 0) {
11972c028fdeSJerome Forissier 			res = _utee_cipher_update(operation->state, srcData,
119857aabac5SBogdan Liulko 						  srcLen, destData, &dl);
119957aabac5SBogdan Liulko 		} else {
120057aabac5SBogdan Liulko 			res = TEE_SUCCESS;
120157aabac5SBogdan Liulko 			dl = 0;
120257aabac5SBogdan Liulko 		}
120357aabac5SBogdan Liulko 	}
1204e86f1266SJens Wiklander 	*destLen = dl;
1205b0104773SPascal Brand 
1206dea1f2b6SCedric Chaumont out:
1207dea1f2b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
1208dea1f2b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1209b36311adSJerome Forissier 		TEE_Panic(res);
1210dea1f2b6SCedric Chaumont 
1211dea1f2b6SCedric Chaumont 	return res;
1212b0104773SPascal Brand }
1213b0104773SPascal Brand 
1214185bf58cSJens Wiklander TEE_Result __GP11_TEE_CipherUpdate(TEE_OperationHandle operation,
12158f07fe6fSJerome Forissier 				   const void *srcData, uint32_t srcLen,
12168f07fe6fSJerome Forissier 				   void *destData, uint32_t *destLen)
1217b0104773SPascal Brand {
12186915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1219185bf58cSJens Wiklander 	size_t dl = 0;
1220185bf58cSJens Wiklander 
1221185bf58cSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1222185bf58cSJens Wiklander 	dl = *destLen;
1223185bf58cSJens Wiklander 	res = TEE_CipherUpdate(operation, srcData, srcLen, destData, &dl);
1224185bf58cSJens Wiklander 	*destLen = dl;
1225185bf58cSJens Wiklander 	return res;
1226185bf58cSJens Wiklander }
1227185bf58cSJens Wiklander 
1228185bf58cSJens Wiklander TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation,
1229185bf58cSJens Wiklander 			     const void *srcData, size_t srcLen,
1230185bf58cSJens Wiklander 			     void *destData, size_t *destLen)
1231185bf58cSJens Wiklander {
1232185bf58cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1233b0104773SPascal Brand 	uint8_t *dst = destData;
1234b0104773SPascal Brand 	size_t acc_dlen = 0;
12356915bbbbSJens Wiklander 	uint64_t tmp_dlen = 0;
12366915bbbbSJens Wiklander 	size_t req_dlen = 0;
1237b0104773SPascal Brand 
12386915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1239dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1240dea1f2b6SCedric Chaumont 		goto out;
1241dea1f2b6SCedric Chaumont 	}
12426915bbbbSJens Wiklander 	if (destLen)
12436915bbbbSJens Wiklander 		__utee_check_inout_annotation(destLen, sizeof(*destLen));
1244dea1f2b6SCedric Chaumont 
1245642a1607SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_CIPHER) {
1246dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1247dea1f2b6SCedric Chaumont 		goto out;
1248dea1f2b6SCedric Chaumont 	}
1249dea1f2b6SCedric Chaumont 
1250642a1607SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1251642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1252642a1607SCedric Chaumont 		goto out;
1253642a1607SCedric Chaumont 	}
1254642a1607SCedric Chaumont 
1255642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1256dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1257dea1f2b6SCedric Chaumont 		goto out;
1258dea1f2b6SCedric Chaumont 	}
1259b0104773SPascal Brand 
1260b0104773SPascal Brand 	/*
1261b0104773SPascal Brand 	 * Check that the final block doesn't require padding for those
1262b0104773SPascal Brand 	 * algorithms that requires client to supply padding.
1263b0104773SPascal Brand 	 */
1264642a1607SCedric Chaumont 	if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD ||
1265642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD ||
1266642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD ||
1267642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD ||
1268642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD ||
1269ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD ||
1270ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD ||
1271ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_SM4_CBC_NOPAD) {
1272642a1607SCedric Chaumont 		if (((operation->buffer_offs + srcLen) % operation->block_size)
1273642a1607SCedric Chaumont 		    != 0) {
1274dea1f2b6SCedric Chaumont 			res = TEE_ERROR_BAD_PARAMETERS;
1275dea1f2b6SCedric Chaumont 			goto out;
1276dea1f2b6SCedric Chaumont 		}
1277b0104773SPascal Brand 	}
1278b0104773SPascal Brand 
1279b0104773SPascal Brand 	/*
1280b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1281b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1282b0104773SPascal Brand 	 * can't restore sync with this API.
1283b0104773SPascal Brand 	 */
128457aabac5SBogdan Liulko 	if (operation->block_size > 1) {
1285642a1607SCedric Chaumont 		req_dlen = operation->buffer_offs + srcLen;
128657aabac5SBogdan Liulko 	} else {
128757aabac5SBogdan Liulko 		req_dlen = srcLen;
128857aabac5SBogdan Liulko 	}
12896915bbbbSJens Wiklander 	if (destLen)
12906915bbbbSJens Wiklander 		tmp_dlen = *destLen;
12916915bbbbSJens Wiklander 	if (tmp_dlen < req_dlen) {
12926915bbbbSJens Wiklander 		if (destLen)
1293b0104773SPascal Brand 			*destLen = req_dlen;
1294dea1f2b6SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1295dea1f2b6SCedric Chaumont 		goto out;
1296b0104773SPascal Brand 	}
1297b0104773SPascal Brand 
129857aabac5SBogdan Liulko 	if (operation->block_size > 1) {
1299dea9063eSJens Wiklander 		if (srcLen) {
13002c028fdeSJerome Forissier 			res = tee_buffer_update(operation, _utee_cipher_update,
1301dea9063eSJens Wiklander 						srcData, srcLen, dst,
1302dea9063eSJens Wiklander 						&tmp_dlen);
1303dea1f2b6SCedric Chaumont 			if (res != TEE_SUCCESS)
1304dea1f2b6SCedric Chaumont 				goto out;
1305dea1f2b6SCedric Chaumont 
1306b0104773SPascal Brand 			dst += tmp_dlen;
1307b0104773SPascal Brand 			acc_dlen += tmp_dlen;
1308b0104773SPascal Brand 
1309b0104773SPascal Brand 			tmp_dlen = *destLen - acc_dlen;
1310dea9063eSJens Wiklander 		}
13112c028fdeSJerome Forissier 		res = _utee_cipher_final(operation->state, operation->buffer,
13122c028fdeSJerome Forissier 					 operation->buffer_offs, dst,
13132c028fdeSJerome Forissier 					 &tmp_dlen);
131457aabac5SBogdan Liulko 	} else {
13152c028fdeSJerome Forissier 		res = _utee_cipher_final(operation->state, srcData, srcLen, dst,
13162c028fdeSJerome Forissier 					 &tmp_dlen);
131757aabac5SBogdan Liulko 	}
1318b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1319dea1f2b6SCedric Chaumont 		goto out;
1320dea1f2b6SCedric Chaumont 
1321b0104773SPascal Brand 	acc_dlen += tmp_dlen;
13226915bbbbSJens Wiklander 	if (destLen)
1323b0104773SPascal Brand 		*destLen = acc_dlen;
1324dea1f2b6SCedric Chaumont 
1325642a1607SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1326642a1607SCedric Chaumont 
1327642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1328642a1607SCedric Chaumont 
1329dea1f2b6SCedric Chaumont out:
1330dea1f2b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
1331dea1f2b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1332b36311adSJerome Forissier 		TEE_Panic(res);
1333dea1f2b6SCedric Chaumont 
1334dea1f2b6SCedric Chaumont 	return res;
1335b0104773SPascal Brand }
1336b0104773SPascal Brand 
1337185bf58cSJens Wiklander TEE_Result __GP11_TEE_CipherDoFinal(TEE_OperationHandle operation,
1338185bf58cSJens Wiklander 				    const void *srcData, uint32_t srcLen,
1339185bf58cSJens Wiklander 				    void *destData, uint32_t *destLen)
1340185bf58cSJens Wiklander {
1341185bf58cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1342185bf58cSJens Wiklander 	size_t dl = 0;
1343185bf58cSJens Wiklander 
1344185bf58cSJens Wiklander 	if (destLen) {
1345185bf58cSJens Wiklander 		__utee_check_inout_annotation(destLen, sizeof(*destLen));
1346185bf58cSJens Wiklander 		dl = *destLen;
1347185bf58cSJens Wiklander 	}
1348185bf58cSJens Wiklander 	res = TEE_CipherDoFinal(operation, srcData, srcLen, destData, &dl);
1349185bf58cSJens Wiklander 	if (destLen)
1350185bf58cSJens Wiklander 		*destLen = dl;
1351185bf58cSJens Wiklander 	return res;
1352185bf58cSJens Wiklander }
1353185bf58cSJens Wiklander 
1354b0104773SPascal Brand /* Cryptographic Operations API - MAC Functions */
1355b0104773SPascal Brand 
1356185bf58cSJens Wiklander void TEE_MACInit(TEE_OperationHandle operation, const void *IV, size_t IVLen)
1357b0104773SPascal Brand {
1358b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
1359b0104773SPascal Brand 		TEE_Panic(0);
1360642a1607SCedric Chaumont 
1361b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_MAC)
1362b0104773SPascal Brand 		TEE_Panic(0);
1363642a1607SCedric Chaumont 
1364642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||
1365642a1607SCedric Chaumont 	    !(operation->key1))
1366642a1607SCedric Chaumont 		TEE_Panic(0);
1367642a1607SCedric Chaumont 
1368642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
1369642a1607SCedric Chaumont 		TEE_ResetOperation(operation);
1370642a1607SCedric Chaumont 
1371642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1372642a1607SCedric Chaumont 
13736d15db08SJerome Forissier 	init_hash_operation(operation, IV, IVLen);
1374b0104773SPascal Brand }
1375b0104773SPascal Brand 
1376185bf58cSJens Wiklander void __GP11_TEE_MACInit(TEE_OperationHandle operation, const void *IV,
1377185bf58cSJens Wiklander 			uint32_t IVLen)
1378185bf58cSJens Wiklander {
1379185bf58cSJens Wiklander 	return TEE_MACInit(operation, IV, IVLen);
1380185bf58cSJens Wiklander }
1381185bf58cSJens Wiklander 
13828f07fe6fSJerome Forissier void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk,
1383185bf58cSJens Wiklander 		   size_t chunkSize)
1384b0104773SPascal Brand {
1385b0104773SPascal Brand 	TEE_Result res;
1386b0104773SPascal Brand 
138728e0efc6SCedric Chaumont 	if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0))
1388b0104773SPascal Brand 		TEE_Panic(0);
1389642a1607SCedric Chaumont 
139028e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC)
1391b0104773SPascal Brand 		TEE_Panic(0);
1392642a1607SCedric Chaumont 
139328e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1394b0104773SPascal Brand 		TEE_Panic(0);
1395b0104773SPascal Brand 
1396642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE)
1397642a1607SCedric Chaumont 		TEE_Panic(0);
1398642a1607SCedric Chaumont 
13992c028fdeSJerome Forissier 	res = _utee_hash_update(operation->state, chunk, chunkSize);
1400b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1401b0104773SPascal Brand 		TEE_Panic(res);
1402b0104773SPascal Brand }
1403b0104773SPascal Brand 
1404185bf58cSJens Wiklander void __GP11_TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk,
1405185bf58cSJens Wiklander 			  uint32_t chunkSize)
1406185bf58cSJens Wiklander {
1407185bf58cSJens Wiklander 	return TEE_MACUpdate(operation, chunk, chunkSize);
1408185bf58cSJens Wiklander }
1409185bf58cSJens Wiklander 
141028e0efc6SCedric Chaumont TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation,
1411185bf58cSJens Wiklander 			       const void *message, size_t messageLen,
1412185bf58cSJens Wiklander 			       void *mac, size_t *macLen)
1413b0104773SPascal Brand {
1414b0104773SPascal Brand 	TEE_Result res;
1415e86f1266SJens Wiklander 	uint64_t ml;
1416b0104773SPascal Brand 
14176915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!message && messageLen)) {
141828e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
141928e0efc6SCedric Chaumont 		goto out;
142028e0efc6SCedric Chaumont 	}
14216915bbbbSJens Wiklander 	__utee_check_inout_annotation(macLen, sizeof(*macLen));
1422b0104773SPascal Brand 
142328e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC) {
142428e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
142528e0efc6SCedric Chaumont 		goto out;
142628e0efc6SCedric Chaumont 	}
142728e0efc6SCedric Chaumont 
142828e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
142928e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
143028e0efc6SCedric Chaumont 		goto out;
143128e0efc6SCedric Chaumont 	}
143228e0efc6SCedric Chaumont 
1433642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1434642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1435642a1607SCedric Chaumont 		goto out;
1436642a1607SCedric Chaumont 	}
1437642a1607SCedric Chaumont 
1438e86f1266SJens Wiklander 	ml = *macLen;
14392c028fdeSJerome Forissier 	res = _utee_hash_final(operation->state, message, messageLen, mac, &ml);
1440e86f1266SJens Wiklander 	*macLen = ml;
144128e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS)
144228e0efc6SCedric Chaumont 		goto out;
144328e0efc6SCedric Chaumont 
144428e0efc6SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
144528e0efc6SCedric Chaumont 
1446642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1447642a1607SCedric Chaumont 
144828e0efc6SCedric Chaumont out:
144928e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS &&
145028e0efc6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
145128e0efc6SCedric Chaumont 		TEE_Panic(res);
145228e0efc6SCedric Chaumont 
1453b0104773SPascal Brand 	return res;
1454b0104773SPascal Brand }
1455b0104773SPascal Brand 
1456185bf58cSJens Wiklander TEE_Result __GP11_TEE_MACComputeFinal(TEE_OperationHandle operation,
14578f07fe6fSJerome Forissier 				      const void *message, uint32_t messageLen,
1458185bf58cSJens Wiklander 				      void *mac, uint32_t *macLen)
1459185bf58cSJens Wiklander {
1460185bf58cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1461185bf58cSJens Wiklander 	size_t ml = 0;
1462185bf58cSJens Wiklander 
1463185bf58cSJens Wiklander 	__utee_check_inout_annotation(macLen, sizeof(*macLen));
1464185bf58cSJens Wiklander 	ml = *macLen;
1465185bf58cSJens Wiklander 	res = TEE_MACComputeFinal(operation, message, messageLen, mac, &ml);
1466185bf58cSJens Wiklander 	*macLen = ml;
1467185bf58cSJens Wiklander 	return res;
1468185bf58cSJens Wiklander }
1469185bf58cSJens Wiklander 
1470185bf58cSJens Wiklander TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation,
1471185bf58cSJens Wiklander 			       const void *message, size_t messageLen,
1472185bf58cSJens Wiklander 			       const void *mac, size_t macLen)
1473b0104773SPascal Brand {
1474b0104773SPascal Brand 	TEE_Result res;
1475ee4ba3d1SVictor Chong 	uint8_t computed_mac[TEE_MAX_HASH_SIZE] = { 0 };
1476185bf58cSJens Wiklander 	size_t computed_mac_size = TEE_MAX_HASH_SIZE;
1477b0104773SPascal Brand 
147828e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC) {
147928e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
148028e0efc6SCedric Chaumont 		goto out;
148128e0efc6SCedric Chaumont 	}
148228e0efc6SCedric Chaumont 
148328e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
148428e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
148528e0efc6SCedric Chaumont 		goto out;
148628e0efc6SCedric Chaumont 	}
148728e0efc6SCedric Chaumont 
1488642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1489642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1490642a1607SCedric Chaumont 		goto out;
1491642a1607SCedric Chaumont 	}
1492642a1607SCedric Chaumont 
1493b0104773SPascal Brand 	res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac,
1494b0104773SPascal Brand 				  &computed_mac_size);
1495b0104773SPascal Brand 	if (res != TEE_SUCCESS)
149628e0efc6SCedric Chaumont 		goto out;
149728e0efc6SCedric Chaumont 
149828e0efc6SCedric Chaumont 	if (computed_mac_size != macLen) {
149928e0efc6SCedric Chaumont 		res = TEE_ERROR_MAC_INVALID;
150028e0efc6SCedric Chaumont 		goto out;
150128e0efc6SCedric Chaumont 	}
150228e0efc6SCedric Chaumont 
150348e10604SJerome Forissier 	if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) {
150428e0efc6SCedric Chaumont 		res = TEE_ERROR_MAC_INVALID;
150528e0efc6SCedric Chaumont 		goto out;
150628e0efc6SCedric Chaumont 	}
150728e0efc6SCedric Chaumont 
1508642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1509642a1607SCedric Chaumont 
151028e0efc6SCedric Chaumont out:
151128e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS &&
151228e0efc6SCedric Chaumont 	    res != TEE_ERROR_MAC_INVALID)
151328e0efc6SCedric Chaumont 		TEE_Panic(res);
151428e0efc6SCedric Chaumont 
1515b0104773SPascal Brand 	return res;
1516b0104773SPascal Brand }
1517b0104773SPascal Brand 
1518185bf58cSJens Wiklander TEE_Result __GP11_TEE_MACCompareFinal(TEE_OperationHandle operation,
1519185bf58cSJens Wiklander 				      const void *message, uint32_t messageLen,
1520185bf58cSJens Wiklander 				      const void *mac, uint32_t macLen)
1521185bf58cSJens Wiklander {
1522185bf58cSJens Wiklander 	return TEE_MACCompareFinal(operation, message, messageLen, mac, macLen);
1523185bf58cSJens Wiklander }
1524185bf58cSJens Wiklander 
1525b0104773SPascal Brand /* Cryptographic Operations API - Authenticated Encryption Functions */
1526b0104773SPascal Brand 
15278f07fe6fSJerome Forissier TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce,
1528d9096215SJens Wiklander 		      size_t nonceLen, uint32_t tagLen, size_t AADLen,
1529d9096215SJens Wiklander 		      size_t payloadLen)
1530b0104773SPascal Brand {
1531b0104773SPascal Brand 	TEE_Result res;
1532b0104773SPascal Brand 
1533b5816c88SCedric Chaumont 	if (operation == TEE_HANDLE_NULL || nonce == NULL) {
1534b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1535b5816c88SCedric Chaumont 		goto out;
1536b5816c88SCedric Chaumont 	}
1537b5816c88SCedric Chaumont 
1538b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1539b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1540b5816c88SCedric Chaumont 		goto out;
1541b5816c88SCedric Chaumont 	}
1542b0104773SPascal Brand 
1543642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
1544642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1545642a1607SCedric Chaumont 		goto out;
1546642a1607SCedric Chaumont 	}
1547642a1607SCedric Chaumont 
1548b0104773SPascal Brand 	/*
1549b0104773SPascal Brand 	 * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core
1550b0104773SPascal Brand 	 * in the implementation. But AES-GCM spec doesn't specify the tag len
1551b0104773SPascal Brand 	 * according to the same principle so we have to check here instead to
1552b0104773SPascal Brand 	 * be GP compliant.
1553b0104773SPascal Brand 	 */
1554b5816c88SCedric Chaumont 	if (operation->info.algorithm == TEE_ALG_AES_GCM) {
1555b0104773SPascal Brand 		/*
1556b0104773SPascal Brand 		 * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96
1557b0104773SPascal Brand 		 */
1558b5816c88SCedric Chaumont 		if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) {
1559b5816c88SCedric Chaumont 			res = TEE_ERROR_NOT_SUPPORTED;
1560b5816c88SCedric Chaumont 			goto out;
1561b5816c88SCedric Chaumont 		}
1562b0104773SPascal Brand 	}
1563b0104773SPascal Brand 
15642c028fdeSJerome Forissier 	res = _utee_authenc_init(operation->state, nonce, nonceLen, tagLen / 8,
15652c028fdeSJerome Forissier 				 AADLen, payloadLen);
1566b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS)
1567b5816c88SCedric Chaumont 		goto out;
1568b5816c88SCedric Chaumont 
15697acaf5adSAlbert Schwarzkopf 	operation->info.digestLength = tagLen / 8;
1570f2674567SSumit Garg 	operation->buffer_offs = 0;
1571b5816c88SCedric Chaumont 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
1572b5816c88SCedric Chaumont 
1573b5816c88SCedric Chaumont out:
1574b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1575b5816c88SCedric Chaumont 	    res != TEE_ERROR_NOT_SUPPORTED)
1576b0104773SPascal Brand 			TEE_Panic(res);
1577b5816c88SCedric Chaumont 
1578b0104773SPascal Brand 	return res;
1579b0104773SPascal Brand }
1580b0104773SPascal Brand 
1581d9096215SJens Wiklander TEE_Result __GP11_TEE_AEInit(TEE_OperationHandle operation, const void *nonce,
1582d9096215SJens Wiklander 			     uint32_t nonceLen, uint32_t tagLen,
1583d9096215SJens Wiklander 			     uint32_t AADLen, uint32_t payloadLen)
1584d9096215SJens Wiklander {
1585d9096215SJens Wiklander 	return TEE_AEInit(operation, nonce, nonceLen, tagLen, AADLen,
1586d9096215SJens Wiklander 			  payloadLen);
1587d9096215SJens Wiklander }
1588d9096215SJens Wiklander 
15898f07fe6fSJerome Forissier void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata,
1590d9096215SJens Wiklander 		     size_t AADdataLen)
1591d9096215SJens Wiklander {
1592d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1593d9096215SJens Wiklander 
1594d9096215SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!AADdata && AADdataLen))
1595d9096215SJens Wiklander 		TEE_Panic(0);
1596d9096215SJens Wiklander 
1597d9096215SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_AE)
1598d9096215SJens Wiklander 		TEE_Panic(0);
1599d9096215SJens Wiklander 
1600d9096215SJens Wiklander 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
1601d9096215SJens Wiklander 		TEE_Panic(0);
1602d9096215SJens Wiklander 
1603d9096215SJens Wiklander 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1604d9096215SJens Wiklander 		TEE_Panic(0);
1605d9096215SJens Wiklander 
1606d9096215SJens Wiklander 	res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen);
1607d9096215SJens Wiklander 	if (res != TEE_SUCCESS)
1608d9096215SJens Wiklander 		TEE_Panic(res);
1609d9096215SJens Wiklander }
1610d9096215SJens Wiklander 
1611d9096215SJens Wiklander void __GP11_TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata,
161279a3c601SCedric Chaumont 			    uint32_t AADdataLen)
1613b0104773SPascal Brand {
1614d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1615b0104773SPascal Brand 
1616b5816c88SCedric Chaumont 	if (operation == TEE_HANDLE_NULL ||
1617b5816c88SCedric Chaumont 	    (AADdata == NULL && AADdataLen != 0))
1618b0104773SPascal Brand 		TEE_Panic(0);
1619642a1607SCedric Chaumont 
1620b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE)
1621b0104773SPascal Brand 		TEE_Panic(0);
1622642a1607SCedric Chaumont 
1623b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1624b0104773SPascal Brand 		TEE_Panic(0);
1625b0104773SPascal Brand 
16262c028fdeSJerome Forissier 	res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen);
1627642a1607SCedric Chaumont 
1628642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1629642a1607SCedric Chaumont 
1630b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1631b0104773SPascal Brand 		TEE_Panic(res);
1632b0104773SPascal Brand }
1633b0104773SPascal Brand 
1634d9096215SJens Wiklander static TEE_Result ae_update_helper(TEE_OperationHandle operation,
1635d9096215SJens Wiklander 				   const void *src, size_t slen, void *dst,
1636d9096215SJens Wiklander 				   size_t *dlen)
1637b0104773SPascal Brand {
16386915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
16396915bbbbSJens Wiklander 	size_t req_dlen = 0;
16406915bbbbSJens Wiklander 	uint64_t dl = 0;
1641b0104773SPascal Brand 
1642d9096215SJens Wiklander 	if (!src && !slen) {
1643d9096215SJens Wiklander 		*dlen = 0;
1644d9096215SJens Wiklander 		return TEE_SUCCESS;
1645d9096215SJens Wiklander 	}
1646d9096215SJens Wiklander 
1647d9096215SJens Wiklander 	/*
1648d9096215SJens Wiklander 	 * Check that required destLen is big enough before starting to feed
1649d9096215SJens Wiklander 	 * data to the algorithm. Errors during feeding of data are fatal as we
1650d9096215SJens Wiklander 	 * can't restore sync with this API.
1651d9096215SJens Wiklander 	 */
1652d9096215SJens Wiklander 	if (operation->block_size > 1) {
1653d9096215SJens Wiklander 		req_dlen = ROUNDDOWN(operation->buffer_offs + slen,
1654d9096215SJens Wiklander 				     operation->block_size);
1655d9096215SJens Wiklander 	} else {
1656d9096215SJens Wiklander 		req_dlen = slen;
1657d9096215SJens Wiklander 	}
1658d9096215SJens Wiklander 
1659d9096215SJens Wiklander 	dl = *dlen;
1660d9096215SJens Wiklander 	if (dl < req_dlen) {
1661d9096215SJens Wiklander 		*dlen = req_dlen;
1662d9096215SJens Wiklander 		return TEE_ERROR_SHORT_BUFFER;
1663d9096215SJens Wiklander 	}
1664d9096215SJens Wiklander 
1665d9096215SJens Wiklander 	if (operation->block_size > 1) {
1666d9096215SJens Wiklander 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1667d9096215SJens Wiklander 					src, slen, dst, &dl);
1668d9096215SJens Wiklander 	} else {
1669d9096215SJens Wiklander 		if (slen > 0) {
1670d9096215SJens Wiklander 			res = _utee_authenc_update_payload(operation->state,
1671d9096215SJens Wiklander 							   src, slen, dst, &dl);
1672d9096215SJens Wiklander 		} else {
1673d9096215SJens Wiklander 			dl = 0;
1674d9096215SJens Wiklander 			res = TEE_SUCCESS;
1675d9096215SJens Wiklander 		}
1676d9096215SJens Wiklander 	}
1677d9096215SJens Wiklander 
1678d9096215SJens Wiklander 	if (!res)
1679d9096215SJens Wiklander 		*dlen = dl;
1680d9096215SJens Wiklander 
1681d9096215SJens Wiklander 	return res;
1682d9096215SJens Wiklander }
1683d9096215SJens Wiklander 
1684d9096215SJens Wiklander TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData,
1685d9096215SJens Wiklander 			size_t srcLen, void *destData, size_t *destLen)
1686d9096215SJens Wiklander {
1687d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1688d9096215SJens Wiklander 
16896915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1690b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1691b5816c88SCedric Chaumont 		goto out;
1692b5816c88SCedric Chaumont 	}
1693d9096215SJens Wiklander 	__utee_check_outbuf_annotation(destData, destLen);
1694b5816c88SCedric Chaumont 
1695b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1696b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1697b5816c88SCedric Chaumont 		goto out;
1698b5816c88SCedric Chaumont 	}
1699b5816c88SCedric Chaumont 
1700b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1701b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1702b5816c88SCedric Chaumont 		goto out;
1703b5816c88SCedric Chaumont 	}
1704b0104773SPascal Brand 
1705d9096215SJens Wiklander 	res = ae_update_helper(operation, srcData, srcLen, destData, destLen);
1706d9096215SJens Wiklander 	if (res != TEE_ERROR_SHORT_BUFFER && srcLen)
1707d9096215SJens Wiklander 		operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1708d9096215SJens Wiklander 
1709d9096215SJens Wiklander out:
1710d9096215SJens Wiklander 	if (res != TEE_SUCCESS &&
1711d9096215SJens Wiklander 	    res != TEE_ERROR_SHORT_BUFFER)
1712d9096215SJens Wiklander 		TEE_Panic(res);
1713d9096215SJens Wiklander 
1714d9096215SJens Wiklander 	return res;
1715d9096215SJens Wiklander }
1716d9096215SJens Wiklander 
1717d9096215SJens Wiklander TEE_Result __GP11_TEE_AEUpdate(TEE_OperationHandle operation,
1718d9096215SJens Wiklander 			       const void *srcData, uint32_t srcLen,
1719d9096215SJens Wiklander 			       void *destData, uint32_t *destLen)
1720d9096215SJens Wiklander {
1721d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1722d9096215SJens Wiklander 	size_t dl = 0;
1723d9096215SJens Wiklander 
1724d9096215SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1725d9096215SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1726d9096215SJens Wiklander 		goto out;
1727d9096215SJens Wiklander 	}
1728d9096215SJens Wiklander 	__utee_check_gp11_outbuf_annotation(destData, destLen);
1729d9096215SJens Wiklander 
1730d9096215SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1731d9096215SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1732827308b8SJerome Forissier 		goto out;
1733827308b8SJerome Forissier 	}
1734827308b8SJerome Forissier 
1735d9096215SJens Wiklander 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1736d9096215SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1737d9096215SJens Wiklander 		goto out;
1738afc0c182SBogdan Liulko 	}
1739afc0c182SBogdan Liulko 
17406915bbbbSJens Wiklander 	dl = *destLen;
1741d9096215SJens Wiklander 	res = ae_update_helper(operation, srcData, srcLen, destData, &dl);
1742d9096215SJens Wiklander 	*destLen = dl;
1743b0104773SPascal Brand 
1744afc0c182SBogdan Liulko 	if (res != TEE_SUCCESS)
1745afc0c182SBogdan Liulko 		goto out;
1746afc0c182SBogdan Liulko 
1747642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1748642a1607SCedric Chaumont 
1749b5816c88SCedric Chaumont out:
1750b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1751b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1752b5816c88SCedric Chaumont 			TEE_Panic(res);
1753b5816c88SCedric Chaumont 
1754b5816c88SCedric Chaumont 	return res;
1755b0104773SPascal Brand }
1756b0104773SPascal Brand 
1757b5816c88SCedric Chaumont TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation,
1758d9096215SJens Wiklander 			      const void *srcData, size_t srcLen,
1759d9096215SJens Wiklander 			      void *destData, size_t *destLen, void *tag,
1760d9096215SJens Wiklander 			      size_t *tagLen)
1761b0104773SPascal Brand {
1762d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1763b0104773SPascal Brand 	uint8_t *dst = destData;
1764b0104773SPascal Brand 	size_t acc_dlen = 0;
1765d9096215SJens Wiklander 	uint64_t tmp_dlen = 0;
1766d9096215SJens Wiklander 	size_t req_dlen = 0;
1767d9096215SJens Wiklander 	uint64_t tl = 0;
1768b0104773SPascal Brand 
17696915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1770b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1771b5816c88SCedric Chaumont 		goto out;
1772b5816c88SCedric Chaumont 	}
17736915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
17746915bbbbSJens Wiklander 	__utee_check_inout_annotation(tagLen, sizeof(*tagLen));
1775b5816c88SCedric Chaumont 
1776b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1777b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1778b5816c88SCedric Chaumont 		goto out;
1779b5816c88SCedric Chaumont 	}
1780b5816c88SCedric Chaumont 
1781b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1782b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1783b5816c88SCedric Chaumont 		goto out;
1784b5816c88SCedric Chaumont 	}
1785b0104773SPascal Brand 
1786b0104773SPascal Brand 	/*
1787b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1788b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1789b0104773SPascal Brand 	 * can't restore sync with this API.
17902733280aSEtienne Carriere 	 *
17912733280aSEtienne Carriere 	 * Need to check this before update_payload since sync would be lost if
17922733280aSEtienne Carriere 	 * we return short buffer after that.
1793b0104773SPascal Brand 	 */
17942733280aSEtienne Carriere 	res = TEE_ERROR_GENERIC;
17952733280aSEtienne Carriere 
1796b5816c88SCedric Chaumont 	req_dlen = operation->buffer_offs + srcLen;
1797b0104773SPascal Brand 	if (*destLen < req_dlen) {
1798b0104773SPascal Brand 		*destLen = req_dlen;
1799b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1800b0104773SPascal Brand 	}
1801b0104773SPascal Brand 
18027acaf5adSAlbert Schwarzkopf 	if (*tagLen < operation->info.digestLength) {
18037acaf5adSAlbert Schwarzkopf 		*tagLen = operation->info.digestLength;
1804b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1805b0104773SPascal Brand 	}
1806b0104773SPascal Brand 
18072733280aSEtienne Carriere 	if (res == TEE_ERROR_SHORT_BUFFER)
18082733280aSEtienne Carriere 		goto out;
18092733280aSEtienne Carriere 
1810afc0c182SBogdan Liulko 	tl = *tagLen;
1811b0104773SPascal Brand 	tmp_dlen = *destLen - acc_dlen;
1812afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
18132c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1814afc0c182SBogdan Liulko 					srcData, srcLen, dst, &tmp_dlen);
1815b5816c88SCedric Chaumont 		if (res != TEE_SUCCESS)
1816b5816c88SCedric Chaumont 			goto out;
1817b5816c88SCedric Chaumont 
1818b0104773SPascal Brand 		dst += tmp_dlen;
1819b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1820b0104773SPascal Brand 
1821b0104773SPascal Brand 		tmp_dlen = *destLen - acc_dlen;
18222c028fdeSJerome Forissier 		res = _utee_authenc_enc_final(operation->state,
1823afc0c182SBogdan Liulko 					      operation->buffer,
1824afc0c182SBogdan Liulko 					      operation->buffer_offs, dst,
1825afc0c182SBogdan Liulko 					      &tmp_dlen, tag, &tl);
1826afc0c182SBogdan Liulko 	} else {
18272c028fdeSJerome Forissier 		res = _utee_authenc_enc_final(operation->state, srcData,
1828afc0c182SBogdan Liulko 					      srcLen, dst, &tmp_dlen,
1829e86f1266SJens Wiklander 					      tag, &tl);
1830afc0c182SBogdan Liulko 	}
1831e86f1266SJens Wiklander 	*tagLen = tl;
1832b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1833b5816c88SCedric Chaumont 		goto out;
1834b0104773SPascal Brand 
1835b5816c88SCedric Chaumont 	acc_dlen += tmp_dlen;
1836b0104773SPascal Brand 	*destLen = acc_dlen;
1837642a1607SCedric Chaumont 
1838b5816c88SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1839b5816c88SCedric Chaumont 
1840642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1841642a1607SCedric Chaumont 
1842b5816c88SCedric Chaumont out:
1843b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1844b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1845b5816c88SCedric Chaumont 			TEE_Panic(res);
1846b0104773SPascal Brand 
1847b0104773SPascal Brand 	return res;
1848b0104773SPascal Brand }
1849b0104773SPascal Brand 
1850d9096215SJens Wiklander TEE_Result __GP11_TEE_AEEncryptFinal(TEE_OperationHandle operation,
18518f07fe6fSJerome Forissier 				     const void *srcData, uint32_t srcLen,
1852d9096215SJens Wiklander 				     void *destData, uint32_t *destLen,
1853d9096215SJens Wiklander 				     void *tag, uint32_t *tagLen)
1854b0104773SPascal Brand {
1855d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1856d9096215SJens Wiklander 	size_t dl = 0;
1857d9096215SJens Wiklander 	size_t tl = 0;
1858d9096215SJens Wiklander 
1859d9096215SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1860d9096215SJens Wiklander 	__utee_check_inout_annotation(tagLen, sizeof(*tagLen));
1861d9096215SJens Wiklander 	dl = *destLen;
1862d9096215SJens Wiklander 	tl = *tagLen;
1863d9096215SJens Wiklander 	res = TEE_AEEncryptFinal(operation, srcData, srcLen, destData, &dl,
1864d9096215SJens Wiklander 				 tag, &tl);
1865d9096215SJens Wiklander 	*destLen = dl;
1866d9096215SJens Wiklander 	*tagLen = tl;
1867d9096215SJens Wiklander 	return res;
1868d9096215SJens Wiklander }
1869d9096215SJens Wiklander 
1870d9096215SJens Wiklander TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation,
1871d9096215SJens Wiklander 			      const void *srcData, size_t srcLen,
1872d9096215SJens Wiklander 			      void *destData, size_t *destLen, void *tag,
1873d9096215SJens Wiklander 			      size_t tagLen)
1874d9096215SJens Wiklander {
1875d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1876b0104773SPascal Brand 	uint8_t *dst = destData;
1877b0104773SPascal Brand 	size_t acc_dlen = 0;
1878d9096215SJens Wiklander 	uint64_t tmp_dlen = 0;
1879d9096215SJens Wiklander 	size_t req_dlen = 0;
1880b0104773SPascal Brand 
18816915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1882b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1883b5816c88SCedric Chaumont 		goto out;
1884b5816c88SCedric Chaumont 	}
18856915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1886b5816c88SCedric Chaumont 
1887b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1888b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1889b5816c88SCedric Chaumont 		goto out;
1890b5816c88SCedric Chaumont 	}
1891b5816c88SCedric Chaumont 
1892b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1893b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1894b5816c88SCedric Chaumont 		goto out;
1895b5816c88SCedric Chaumont 	}
1896b0104773SPascal Brand 
1897b0104773SPascal Brand 	/*
1898b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1899b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1900b0104773SPascal Brand 	 * can't restore sync with this API.
1901b0104773SPascal Brand 	 */
1902b5816c88SCedric Chaumont 	req_dlen = operation->buffer_offs + srcLen;
1903b0104773SPascal Brand 	if (*destLen < req_dlen) {
1904b0104773SPascal Brand 		*destLen = req_dlen;
1905b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1906b5816c88SCedric Chaumont 		goto out;
1907b0104773SPascal Brand 	}
1908b0104773SPascal Brand 
1909b0104773SPascal Brand 	tmp_dlen = *destLen - acc_dlen;
1910afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
19112c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1912afc0c182SBogdan Liulko 					srcData, srcLen, dst, &tmp_dlen);
1913b5816c88SCedric Chaumont 		if (res != TEE_SUCCESS)
1914b5816c88SCedric Chaumont 			goto out;
1915b5816c88SCedric Chaumont 
1916b0104773SPascal Brand 		dst += tmp_dlen;
1917b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1918b0104773SPascal Brand 
1919b0104773SPascal Brand 		tmp_dlen = *destLen - acc_dlen;
19202c028fdeSJerome Forissier 		res = _utee_authenc_dec_final(operation->state,
1921afc0c182SBogdan Liulko 					      operation->buffer,
1922afc0c182SBogdan Liulko 					      operation->buffer_offs, dst,
1923afc0c182SBogdan Liulko 					      &tmp_dlen, tag, tagLen);
1924afc0c182SBogdan Liulko 	} else {
19252c028fdeSJerome Forissier 		res = _utee_authenc_dec_final(operation->state, srcData,
1926afc0c182SBogdan Liulko 					      srcLen, dst, &tmp_dlen,
1927b5816c88SCedric Chaumont 					      tag, tagLen);
1928afc0c182SBogdan Liulko 	}
1929b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS)
1930b5816c88SCedric Chaumont 		goto out;
1931b5816c88SCedric Chaumont 
1932b0104773SPascal Brand 	/* Supplied tagLen should match what we initiated with */
19337acaf5adSAlbert Schwarzkopf 	if (tagLen != operation->info.digestLength)
1934b0104773SPascal Brand 		res = TEE_ERROR_MAC_INVALID;
1935b0104773SPascal Brand 
1936b0104773SPascal Brand 	acc_dlen += tmp_dlen;
1937b0104773SPascal Brand 	*destLen = acc_dlen;
1938642a1607SCedric Chaumont 
1939b5816c88SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1940b5816c88SCedric Chaumont 
1941642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1942642a1607SCedric Chaumont 
1943b5816c88SCedric Chaumont out:
1944b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1945b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER &&
1946b5816c88SCedric Chaumont 	    res != TEE_ERROR_MAC_INVALID)
1947b5816c88SCedric Chaumont 			TEE_Panic(res);
1948b0104773SPascal Brand 
1949b0104773SPascal Brand 	return res;
1950b0104773SPascal Brand }
1951b0104773SPascal Brand 
1952d9096215SJens Wiklander TEE_Result __GP11_TEE_AEDecryptFinal(TEE_OperationHandle operation,
1953d9096215SJens Wiklander 				     const void *srcData, uint32_t srcLen,
1954d9096215SJens Wiklander 				     void *destData, uint32_t *destLen,
1955d9096215SJens Wiklander 				     void *tag, uint32_t tagLen)
1956d9096215SJens Wiklander {
1957d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1958d9096215SJens Wiklander 	size_t dl = 0;
1959d9096215SJens Wiklander 
1960d9096215SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1961d9096215SJens Wiklander 	dl = *destLen;
1962d9096215SJens Wiklander 	res = TEE_AEDecryptFinal(operation, srcData, srcLen, destData, &dl,
1963d9096215SJens Wiklander 				 tag, tagLen);
1964d9096215SJens Wiklander 	*destLen = dl;
1965d9096215SJens Wiklander 	return res;
1966d9096215SJens Wiklander }
1967d9096215SJens Wiklander 
1968b0104773SPascal Brand /* Cryptographic Operations API - Asymmetric Functions */
1969b0104773SPascal Brand 
197012e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation,
19718f07fe6fSJerome Forissier 				 const TEE_Attribute *params,
19728f07fe6fSJerome Forissier 				 uint32_t paramCount, const void *srcData,
1973999b69d0SJens Wiklander 				 size_t srcLen, void *destData,
1974999b69d0SJens Wiklander 				 size_t *destLen)
1975b0104773SPascal Brand {
19766915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1977e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
19786915bbbbSJens Wiklander 	uint64_t dl = 0;
1979b0104773SPascal Brand 
19806915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
1981b0104773SPascal Brand 		TEE_Panic(0);
19826915bbbbSJens Wiklander 
19836915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
19846915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
19856915bbbbSJens Wiklander 
198612e66b6fSCedric Chaumont 	if (!operation->key1)
1987b0104773SPascal Brand 		TEE_Panic(0);
198812e66b6fSCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
198912e66b6fSCedric Chaumont 		TEE_Panic(0);
199012e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_ENCRYPT)
1991b0104773SPascal Brand 		TEE_Panic(0);
1992b0104773SPascal Brand 
1993e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
1994e86f1266SJens Wiklander 	dl = *destLen;
19952c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
1996e86f1266SJens Wiklander 				  srcLen, destData, &dl);
1997e86f1266SJens Wiklander 	*destLen = dl;
199812e66b6fSCedric Chaumont 
19998844ebfcSPascal Brand 	if (res != TEE_SUCCESS &&
20008844ebfcSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER &&
20018844ebfcSPascal Brand 	    res != TEE_ERROR_BAD_PARAMETERS)
2002b0104773SPascal Brand 		TEE_Panic(res);
200312e66b6fSCedric Chaumont 
2004b0104773SPascal Brand 	return res;
2005b0104773SPascal Brand }
2006b0104773SPascal Brand 
20074f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricEncrypt(TEE_OperationHandle operation,
20084f4374c8SJens Wiklander 					const __GP11_TEE_Attribute *params,
20094f4374c8SJens Wiklander 					uint32_t paramCount,
20104f4374c8SJens Wiklander 					const void *srcData, uint32_t srcLen,
20114f4374c8SJens Wiklander 					void *destData, uint32_t *destLen)
20124f4374c8SJens Wiklander {
20134f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
20144f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
20154f4374c8SJens Wiklander 	uint64_t dl = 0;
20164f4374c8SJens Wiklander 
20174f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
20184f4374c8SJens Wiklander 		TEE_Panic(0);
20194f4374c8SJens Wiklander 
20204f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
20214f4374c8SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
20224f4374c8SJens Wiklander 
20234f4374c8SJens Wiklander 	if (!operation->key1)
20244f4374c8SJens Wiklander 		TEE_Panic(0);
20254f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
20264f4374c8SJens Wiklander 		TEE_Panic(0);
20274f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_ENCRYPT)
20284f4374c8SJens Wiklander 		TEE_Panic(0);
20294f4374c8SJens Wiklander 
20304f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
20314f4374c8SJens Wiklander 	dl = *destLen;
20324f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
20334f4374c8SJens Wiklander 				  srcLen, destData, &dl);
20344f4374c8SJens Wiklander 	*destLen = dl;
20354f4374c8SJens Wiklander 
20364f4374c8SJens Wiklander 	if (res != TEE_SUCCESS &&
20374f4374c8SJens Wiklander 	    res != TEE_ERROR_SHORT_BUFFER &&
20384f4374c8SJens Wiklander 	    res != TEE_ERROR_BAD_PARAMETERS)
20394f4374c8SJens Wiklander 		TEE_Panic(res);
20404f4374c8SJens Wiklander 
20414f4374c8SJens Wiklander 	return res;
20424f4374c8SJens Wiklander }
20434f4374c8SJens Wiklander 
204412e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation,
20458f07fe6fSJerome Forissier 				 const TEE_Attribute *params,
20468f07fe6fSJerome Forissier 				 uint32_t paramCount, const void *srcData,
2047999b69d0SJens Wiklander 				 size_t srcLen, void *destData,
2048999b69d0SJens Wiklander 				 size_t *destLen)
2049b0104773SPascal Brand {
20506915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
2051e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
20526915bbbbSJens Wiklander 	uint64_t dl = 0;
2053b0104773SPascal Brand 
20546915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
2055b0104773SPascal Brand 		TEE_Panic(0);
20566915bbbbSJens Wiklander 
20576915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
20586915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
20596915bbbbSJens Wiklander 
206012e66b6fSCedric Chaumont 	if (!operation->key1)
2061b0104773SPascal Brand 		TEE_Panic(0);
206212e66b6fSCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
206312e66b6fSCedric Chaumont 		TEE_Panic(0);
206412e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_DECRYPT)
2065b0104773SPascal Brand 		TEE_Panic(0);
2066b0104773SPascal Brand 
2067e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
2068e86f1266SJens Wiklander 	dl = *destLen;
20692c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
2070e86f1266SJens Wiklander 				  srcLen, destData, &dl);
2071e86f1266SJens Wiklander 	*destLen = dl;
207212e66b6fSCedric Chaumont 
20738844ebfcSPascal Brand 	if (res != TEE_SUCCESS &&
20748844ebfcSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER &&
20758844ebfcSPascal Brand 	    res != TEE_ERROR_BAD_PARAMETERS)
2076b0104773SPascal Brand 		TEE_Panic(res);
207712e66b6fSCedric Chaumont 
2078b0104773SPascal Brand 	return res;
2079b0104773SPascal Brand }
2080b0104773SPascal Brand 
20814f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricDecrypt(TEE_OperationHandle operation,
20824f4374c8SJens Wiklander 					const __GP11_TEE_Attribute *params,
20834f4374c8SJens Wiklander 					uint32_t paramCount,
20844f4374c8SJens Wiklander 					const void *srcData, uint32_t srcLen,
20854f4374c8SJens Wiklander 					void *destData, uint32_t *destLen)
20864f4374c8SJens Wiklander {
20874f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
20884f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
20894f4374c8SJens Wiklander 	uint64_t dl = 0;
20904f4374c8SJens Wiklander 
20914f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
20924f4374c8SJens Wiklander 		TEE_Panic(0);
20934f4374c8SJens Wiklander 
20944f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
20954f4374c8SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
20964f4374c8SJens Wiklander 
20974f4374c8SJens Wiklander 	if (!operation->key1)
20984f4374c8SJens Wiklander 		TEE_Panic(0);
20994f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
21004f4374c8SJens Wiklander 		TEE_Panic(0);
21014f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_DECRYPT)
21024f4374c8SJens Wiklander 		TEE_Panic(0);
21034f4374c8SJens Wiklander 
21044f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
21054f4374c8SJens Wiklander 	dl = *destLen;
21064f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
21074f4374c8SJens Wiklander 				  srcLen, destData, &dl);
21084f4374c8SJens Wiklander 	*destLen = dl;
21094f4374c8SJens Wiklander 
21104f4374c8SJens Wiklander 	if (res != TEE_SUCCESS &&
21114f4374c8SJens Wiklander 	    res != TEE_ERROR_SHORT_BUFFER &&
21124f4374c8SJens Wiklander 	    res != TEE_ERROR_BAD_PARAMETERS)
21134f4374c8SJens Wiklander 		TEE_Panic(res);
21144f4374c8SJens Wiklander 
21154f4374c8SJens Wiklander 	return res;
21164f4374c8SJens Wiklander }
21174f4374c8SJens Wiklander 
211812e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation,
21198f07fe6fSJerome Forissier 				    const TEE_Attribute *params,
21208f07fe6fSJerome Forissier 				    uint32_t paramCount, const void *digest,
21210b354ec8SJens Wiklander 				    size_t digestLen, void *signature,
21220b354ec8SJens Wiklander 				    size_t *signatureLen)
2123b0104773SPascal Brand {
21246915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
2125e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
21266915bbbbSJens Wiklander 	uint64_t sl = 0;
2127b0104773SPascal Brand 
21286915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen))
2129b0104773SPascal Brand 		TEE_Panic(0);
21306915bbbbSJens Wiklander 
21316915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
21326915bbbbSJens Wiklander 	__utee_check_inout_annotation(signatureLen, sizeof(*signatureLen));
21336915bbbbSJens Wiklander 
213412e66b6fSCedric Chaumont 	if (!operation->key1)
2135b0104773SPascal Brand 		TEE_Panic(0);
213612e66b6fSCedric Chaumont 	if (operation->info.operationClass !=
213712e66b6fSCedric Chaumont 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
213812e66b6fSCedric Chaumont 		TEE_Panic(0);
213912e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_SIGN)
2140b0104773SPascal Brand 		TEE_Panic(0);
2141b0104773SPascal Brand 
2142e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
2143e86f1266SJens Wiklander 	sl = *signatureLen;
21442c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, digest,
2145e86f1266SJens Wiklander 				  digestLen, signature, &sl);
2146e86f1266SJens Wiklander 	*signatureLen = sl;
214712e66b6fSCedric Chaumont 
2148b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)
2149b0104773SPascal Brand 		TEE_Panic(res);
215012e66b6fSCedric Chaumont 
2151b0104773SPascal Brand 	return res;
2152b0104773SPascal Brand }
2153b0104773SPascal Brand 
21544f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricSignDigest(TEE_OperationHandle operation,
21554f4374c8SJens Wiklander 					   const __GP11_TEE_Attribute *params,
21564f4374c8SJens Wiklander 					   uint32_t paramCount,
21574f4374c8SJens Wiklander 					   const void *digest,
21584f4374c8SJens Wiklander 					   uint32_t digestLen, void *signature,
21594f4374c8SJens Wiklander 					   uint32_t *signatureLen)
21604f4374c8SJens Wiklander {
21614f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
21624f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
21634f4374c8SJens Wiklander 	uint64_t sl = 0;
21644f4374c8SJens Wiklander 
21654f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen))
21664f4374c8SJens Wiklander 		TEE_Panic(0);
21674f4374c8SJens Wiklander 
21684f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
21694f4374c8SJens Wiklander 	__utee_check_inout_annotation(signatureLen, sizeof(*signatureLen));
21704f4374c8SJens Wiklander 
21714f4374c8SJens Wiklander 	if (!operation->key1)
21724f4374c8SJens Wiklander 		TEE_Panic(0);
21734f4374c8SJens Wiklander 	if (operation->info.operationClass !=
21744f4374c8SJens Wiklander 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
21754f4374c8SJens Wiklander 		TEE_Panic(0);
21764f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_SIGN)
21774f4374c8SJens Wiklander 		TEE_Panic(0);
21784f4374c8SJens Wiklander 
21794f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
21804f4374c8SJens Wiklander 	sl = *signatureLen;
21814f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, digest,
21824f4374c8SJens Wiklander 				  digestLen, signature, &sl);
21834f4374c8SJens Wiklander 	*signatureLen = sl;
21844f4374c8SJens Wiklander 
21854f4374c8SJens Wiklander 	if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)
21864f4374c8SJens Wiklander 		TEE_Panic(res);
21874f4374c8SJens Wiklander 
21884f4374c8SJens Wiklander 	return res;
21894f4374c8SJens Wiklander }
21904f4374c8SJens Wiklander 
219112e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation,
21928f07fe6fSJerome Forissier 				      const TEE_Attribute *params,
21938f07fe6fSJerome Forissier 				      uint32_t paramCount, const void *digest,
21940b354ec8SJens Wiklander 				      size_t digestLen,
21958f07fe6fSJerome Forissier 				      const void *signature,
21960b354ec8SJens Wiklander 				      size_t signatureLen)
2197b0104773SPascal Brand {
2198b0104773SPascal Brand 	TEE_Result res;
2199e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
2200b0104773SPascal Brand 
220112e66b6fSCedric Chaumont 	if (operation == TEE_HANDLE_NULL ||
220212e66b6fSCedric Chaumont 	    (digest == NULL && digestLen != 0) ||
2203b0104773SPascal Brand 	    (signature == NULL && signatureLen != 0))
2204b0104773SPascal Brand 		TEE_Panic(0);
22056915bbbbSJens Wiklander 
22066915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
22076915bbbbSJens Wiklander 
220812e66b6fSCedric Chaumont 	if (!operation->key1)
2209b0104773SPascal Brand 		TEE_Panic(0);
221012e66b6fSCedric Chaumont 	if (operation->info.operationClass !=
221112e66b6fSCedric Chaumont 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
221212e66b6fSCedric Chaumont 		TEE_Panic(0);
221312e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_VERIFY)
2214b0104773SPascal Brand 		TEE_Panic(0);
2215b0104773SPascal Brand 
2216e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
22172c028fdeSJerome Forissier 	res = _utee_asymm_verify(operation->state, ua, paramCount, digest,
221812e66b6fSCedric Chaumont 				 digestLen, signature, signatureLen);
221912e66b6fSCedric Chaumont 
2220b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID)
2221b0104773SPascal Brand 		TEE_Panic(res);
222212e66b6fSCedric Chaumont 
2223b0104773SPascal Brand 	return res;
2224b0104773SPascal Brand }
2225b0104773SPascal Brand 
22264f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation,
22274f4374c8SJens Wiklander 					     const __GP11_TEE_Attribute *params,
22284f4374c8SJens Wiklander 					     uint32_t paramCount,
22294f4374c8SJens Wiklander 					     const void *digest,
22304f4374c8SJens Wiklander 					     uint32_t digestLen,
22314f4374c8SJens Wiklander 					     const void *signature,
22324f4374c8SJens Wiklander 					     uint32_t signatureLen)
22334f4374c8SJens Wiklander {
22344f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
22354f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
22364f4374c8SJens Wiklander 
22374f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen) ||
22384f4374c8SJens Wiklander 	    (!signature && signatureLen))
22394f4374c8SJens Wiklander 		TEE_Panic(0);
22404f4374c8SJens Wiklander 
22414f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
22424f4374c8SJens Wiklander 
22434f4374c8SJens Wiklander 	if (!operation->key1)
22444f4374c8SJens Wiklander 		TEE_Panic(0);
22454f4374c8SJens Wiklander 	if (operation->info.operationClass !=
22464f4374c8SJens Wiklander 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
22474f4374c8SJens Wiklander 		TEE_Panic(0);
22484f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_VERIFY)
22494f4374c8SJens Wiklander 		TEE_Panic(0);
22504f4374c8SJens Wiklander 
22514f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
22524f4374c8SJens Wiklander 	res = _utee_asymm_verify(operation->state, ua, paramCount, digest,
22534f4374c8SJens Wiklander 				 digestLen, signature, signatureLen);
22544f4374c8SJens Wiklander 
22554f4374c8SJens Wiklander 	if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID)
22564f4374c8SJens Wiklander 		TEE_Panic(res);
22574f4374c8SJens Wiklander 
22584f4374c8SJens Wiklander 	return res;
22594f4374c8SJens Wiklander }
22604f4374c8SJens Wiklander 
2261b0104773SPascal Brand /* Cryptographic Operations API - Key Derivation Functions */
2262b0104773SPascal Brand 
2263b0104773SPascal Brand void TEE_DeriveKey(TEE_OperationHandle operation,
2264b0104773SPascal Brand 		   const TEE_Attribute *params, uint32_t paramCount,
2265b0104773SPascal Brand 		   TEE_ObjectHandle derivedKey)
2266b0104773SPascal Brand {
2267e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
226875d6a373SJens Wiklander 	struct utee_object_info key_info = { };
226975d6a373SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
2270b0104773SPascal Brand 
2271b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL || derivedKey == 0)
2272b0104773SPascal Brand 		TEE_Panic(0);
22736915bbbbSJens Wiklander 
22746915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
22756915bbbbSJens Wiklander 
22768854d3c6SJerome Forissier 	if (TEE_ALG_GET_CLASS(operation->info.algorithm) !=
22778854d3c6SJerome Forissier 	    TEE_OPERATION_KEY_DERIVATION)
2278b0104773SPascal Brand 		TEE_Panic(0);
2279b0104773SPascal Brand 
2280b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION)
2281b0104773SPascal Brand 		TEE_Panic(0);
228284fa9467SCedric Chaumont 	if (!operation->key1)
228384fa9467SCedric Chaumont 		TEE_Panic(0);
2284b0104773SPascal Brand 	if (operation->info.mode != TEE_MODE_DERIVE)
2285b0104773SPascal Brand 		TEE_Panic(0);
2286b0104773SPascal Brand 	if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0)
2287b0104773SPascal Brand 		TEE_Panic(0);
2288b0104773SPascal Brand 
22892c028fdeSJerome Forissier 	res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info);
2290b0104773SPascal Brand 	if (res != TEE_SUCCESS)
2291b36311adSJerome Forissier 		TEE_Panic(res);
2292b0104773SPascal Brand 
229375d6a373SJens Wiklander 	if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET)
2294b0104773SPascal Brand 		TEE_Panic(0);
229575d6a373SJens Wiklander 	if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
2296b0104773SPascal Brand 		TEE_Panic(0);
2297b0104773SPascal Brand 
2298e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
22992c028fdeSJerome Forissier 	res = _utee_cryp_derive_key(operation->state, ua, paramCount,
2300e86f1266SJens Wiklander 				    (unsigned long)derivedKey);
2301b0104773SPascal Brand 	if (res != TEE_SUCCESS)
2302b0104773SPascal Brand 		TEE_Panic(res);
2303b0104773SPascal Brand }
2304b0104773SPascal Brand 
23054f4374c8SJens Wiklander void __GP11_TEE_DeriveKey(TEE_OperationHandle operation,
23064f4374c8SJens Wiklander 			  const __GP11_TEE_Attribute *params,
23074f4374c8SJens Wiklander 			  uint32_t paramCount, TEE_ObjectHandle derivedKey)
23084f4374c8SJens Wiklander {
23094f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
23104f4374c8SJens Wiklander 	struct utee_object_info key_info = { };
23114f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
23124f4374c8SJens Wiklander 
23134f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || derivedKey == 0)
23144f4374c8SJens Wiklander 		TEE_Panic(0);
23154f4374c8SJens Wiklander 
23164f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
23174f4374c8SJens Wiklander 
23184f4374c8SJens Wiklander 	if (TEE_ALG_GET_CLASS(operation->info.algorithm) !=
23194f4374c8SJens Wiklander 	    TEE_OPERATION_KEY_DERIVATION)
23204f4374c8SJens Wiklander 		TEE_Panic(0);
23214f4374c8SJens Wiklander 
23224f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION)
23234f4374c8SJens Wiklander 		TEE_Panic(0);
23244f4374c8SJens Wiklander 	if (!operation->key1)
23254f4374c8SJens Wiklander 		TEE_Panic(0);
23264f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_DERIVE)
23274f4374c8SJens Wiklander 		TEE_Panic(0);
23284f4374c8SJens Wiklander 	if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0)
23294f4374c8SJens Wiklander 		TEE_Panic(0);
23304f4374c8SJens Wiklander 
23314f4374c8SJens Wiklander 	res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info);
23324f4374c8SJens Wiklander 	if (res != TEE_SUCCESS)
23334f4374c8SJens Wiklander 		TEE_Panic(res);
23344f4374c8SJens Wiklander 
23354f4374c8SJens Wiklander 	if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET)
23364f4374c8SJens Wiklander 		TEE_Panic(0);
23374f4374c8SJens Wiklander 	if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
23384f4374c8SJens Wiklander 		TEE_Panic(0);
23394f4374c8SJens Wiklander 
23404f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
23414f4374c8SJens Wiklander 	res = _utee_cryp_derive_key(operation->state, ua, paramCount,
23424f4374c8SJens Wiklander 				    (unsigned long)derivedKey);
23434f4374c8SJens Wiklander 	if (res != TEE_SUCCESS)
23444f4374c8SJens Wiklander 		TEE_Panic(res);
23454f4374c8SJens Wiklander }
23464f4374c8SJens Wiklander 
2347b0104773SPascal Brand /* Cryptographic Operations API - Random Number Generation Functions */
2348b0104773SPascal Brand 
2349411a488aSJens Wiklander void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen)
2350b0104773SPascal Brand {
2351b0104773SPascal Brand 	TEE_Result res;
2352b0104773SPascal Brand 
23532c028fdeSJerome Forissier 	res = _utee_cryp_random_number_generate(randomBuffer, randomBufferLen);
2354b0104773SPascal Brand 	if (res != TEE_SUCCESS)
2355b0104773SPascal Brand 		TEE_Panic(res);
2356b0104773SPascal Brand }
2357433c4257SJens Wiklander 
2358411a488aSJens Wiklander void __GP11_TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen)
2359411a488aSJens Wiklander {
2360411a488aSJens Wiklander 	TEE_GenerateRandom(randomBuffer, randomBufferLen);
2361411a488aSJens Wiklander }
2362411a488aSJens Wiklander 
2363433c4257SJens Wiklander int rand(void)
2364433c4257SJens Wiklander {
2365433c4257SJens Wiklander 	int rc;
2366433c4257SJens Wiklander 
2367433c4257SJens Wiklander 	TEE_GenerateRandom(&rc, sizeof(rc));
2368433c4257SJens Wiklander 
2369433c4257SJens Wiklander 	/*
2370433c4257SJens Wiklander 	 * RAND_MAX is the larges int, INT_MAX which is all bits but the
2371433c4257SJens Wiklander 	 * highest bit set.
2372433c4257SJens Wiklander 	 */
2373433c4257SJens Wiklander 	return rc & RAND_MAX;
2374433c4257SJens Wiklander }
237579170ce0SJerome Forissier 
237679170ce0SJerome Forissier TEE_Result TEE_IsAlgorithmSupported(uint32_t alg, uint32_t element)
237779170ce0SJerome Forissier {
237879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_AES)) {
237979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
238079170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_ECB_NOPAD)
238179170ce0SJerome Forissier 				goto check_element_none;
238279170ce0SJerome Forissier 		}
238379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
238479170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CBC_NOPAD)
238579170ce0SJerome Forissier 				goto check_element_none;
238679170ce0SJerome Forissier 		}
238779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTR)) {
238879170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CTR)
238979170ce0SJerome Forissier 				goto check_element_none;
239079170ce0SJerome Forissier 		}
239179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTS)) {
239279170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CTS)
239379170ce0SJerome Forissier 				goto check_element_none;
239479170ce0SJerome Forissier 		}
239579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_XTS)) {
239679170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_XTS)
239779170ce0SJerome Forissier 				goto check_element_none;
239879170ce0SJerome Forissier 		}
239979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) {
240079170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CBC_MAC_NOPAD ||
240179170ce0SJerome Forissier 			    alg == TEE_ALG_AES_CBC_MAC_PKCS5)
240279170ce0SJerome Forissier 				goto check_element_none;
240379170ce0SJerome Forissier 		}
240479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CMAC)) {
240579170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CMAC)
240679170ce0SJerome Forissier 				goto check_element_none;
240779170ce0SJerome Forissier 		}
240879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CCM)) {
240979170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CCM)
241079170ce0SJerome Forissier 				goto check_element_none;
241179170ce0SJerome Forissier 		}
241279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_GCM)) {
241379170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_GCM)
241479170ce0SJerome Forissier 				goto check_element_none;
241579170ce0SJerome Forissier 		}
241679170ce0SJerome Forissier 	}
241779170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DES)) {
241879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
241979170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_ECB_NOPAD ||
242079170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_ECB_NOPAD)
242179170ce0SJerome Forissier 				goto check_element_none;
242279170ce0SJerome Forissier 		}
242379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
242479170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_CBC_NOPAD ||
242579170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_NOPAD)
242679170ce0SJerome Forissier 				goto check_element_none;
242779170ce0SJerome Forissier 		}
242879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) {
242979170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_CBC_MAC_NOPAD ||
243079170ce0SJerome Forissier 			    alg == TEE_ALG_DES_CBC_MAC_PKCS5 ||
243179170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_MAC_NOPAD ||
243279170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_MAC_PKCS5)
243379170ce0SJerome Forissier 				goto check_element_none;
243479170ce0SJerome Forissier 		}
243579170ce0SJerome Forissier 	}
243679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_MD5)) {
243779170ce0SJerome Forissier 		if (alg == TEE_ALG_MD5)
243879170ce0SJerome Forissier 			goto check_element_none;
243979170ce0SJerome Forissier 	}
244079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
244179170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA1)
244279170ce0SJerome Forissier 			goto check_element_none;
244379170ce0SJerome Forissier 	}
244479170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
244579170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA224)
244679170ce0SJerome Forissier 			goto check_element_none;
244779170ce0SJerome Forissier 	}
244879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
244979170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA256)
245079170ce0SJerome Forissier 			goto check_element_none;
245179170ce0SJerome Forissier 	}
245279170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
245379170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA384)
245479170ce0SJerome Forissier 			goto check_element_none;
245579170ce0SJerome Forissier 	}
245679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
245779170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA512)
245879170ce0SJerome Forissier 			goto check_element_none;
245979170ce0SJerome Forissier 	}
2460260b4028SJens Wiklander 	if (IS_ENABLED(CFG_CRYPTO_SHA3_224)) {
2461260b4028SJens Wiklander 		if (alg == TEE_ALG_SHA3_224)
2462260b4028SJens Wiklander 			goto check_element_none;
2463260b4028SJens Wiklander 	}
2464260b4028SJens Wiklander 	if (IS_ENABLED(CFG_CRYPTO_SHA3_256)) {
2465260b4028SJens Wiklander 		if (alg == TEE_ALG_SHA3_256)
2466260b4028SJens Wiklander 			goto check_element_none;
2467260b4028SJens Wiklander 	}
2468260b4028SJens Wiklander 	if (IS_ENABLED(CFG_CRYPTO_SHA3_384)) {
2469260b4028SJens Wiklander 		if (alg == TEE_ALG_SHA3_384)
2470260b4028SJens Wiklander 			goto check_element_none;
2471260b4028SJens Wiklander 	}
2472260b4028SJens Wiklander 	if (IS_ENABLED(CFG_CRYPTO_SHA3_512)) {
2473260b4028SJens Wiklander 		if (alg == TEE_ALG_SHA3_512)
2474260b4028SJens Wiklander 			goto check_element_none;
2475260b4028SJens Wiklander 	}
247679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) {
247779170ce0SJerome Forissier 		if (alg == TEE_ALG_MD5SHA1)
247879170ce0SJerome Forissier 			goto check_element_none;
247979170ce0SJerome Forissier 	}
248079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_HMAC)) {
248179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5)) {
248279170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_MD5)
248379170ce0SJerome Forissier 				goto check_element_none;
248479170ce0SJerome Forissier 		}
248579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
248679170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA1)
248779170ce0SJerome Forissier 				goto check_element_none;
248879170ce0SJerome Forissier 		}
248979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
249079170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA224)
249179170ce0SJerome Forissier 				goto check_element_none;
249279170ce0SJerome Forissier 		}
249379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
249479170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA256)
249579170ce0SJerome Forissier 				goto check_element_none;
249679170ce0SJerome Forissier 		}
249779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
249879170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA384)
249979170ce0SJerome Forissier 				goto check_element_none;
250079170ce0SJerome Forissier 		}
250179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
250279170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA512)
250379170ce0SJerome Forissier 				goto check_element_none;
250479170ce0SJerome Forissier 		}
2505260b4028SJens Wiklander 		if (IS_ENABLED(CFG_CRYPTO_SHA3_224)) {
2506260b4028SJens Wiklander 			if (alg == TEE_ALG_HMAC_SHA3_224)
2507260b4028SJens Wiklander 				goto check_element_none;
2508260b4028SJens Wiklander 		}
2509260b4028SJens Wiklander 		if (IS_ENABLED(CFG_CRYPTO_SHA3_256)) {
2510260b4028SJens Wiklander 			if (alg == TEE_ALG_HMAC_SHA3_256)
2511260b4028SJens Wiklander 				goto check_element_none;
2512260b4028SJens Wiklander 		}
2513260b4028SJens Wiklander 		if (IS_ENABLED(CFG_CRYPTO_SHA3_384)) {
2514260b4028SJens Wiklander 			if (alg == TEE_ALG_HMAC_SHA3_384)
2515260b4028SJens Wiklander 				goto check_element_none;
2516260b4028SJens Wiklander 		}
2517260b4028SJens Wiklander 		if (IS_ENABLED(CFG_CRYPTO_SHA3_512)) {
2518260b4028SJens Wiklander 			if (alg == TEE_ALG_HMAC_SHA3_512)
2519260b4028SJens Wiklander 				goto check_element_none;
2520260b4028SJens Wiklander 		}
252179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SM3)) {
252279170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SM3)
252379170ce0SJerome Forissier 				goto check_element_none;
252479170ce0SJerome Forissier 		}
252579170ce0SJerome Forissier 	}
252679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM3)) {
252779170ce0SJerome Forissier 		if (alg == TEE_ALG_SM3)
252879170ce0SJerome Forissier 			goto check_element_none;
252979170ce0SJerome Forissier 	}
253079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM4)) {
253179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
253279170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_ECB_NOPAD)
253379170ce0SJerome Forissier 				goto check_element_none;
253479170ce0SJerome Forissier 		}
253579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
253679170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_CBC_NOPAD)
253779170ce0SJerome Forissier 				goto check_element_none;
253879170ce0SJerome Forissier 		}
253979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTR)) {
254079170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_CTR)
254179170ce0SJerome Forissier 				goto check_element_none;
254279170ce0SJerome Forissier 		}
2543696f56acSPingan Xie 		if (IS_ENABLED(CFG_CRYPTO_XTS)) {
2544696f56acSPingan Xie 			if (alg == TEE_ALG_SM4_XTS)
2545696f56acSPingan Xie 				goto check_element_none;
2546696f56acSPingan Xie 		}
254779170ce0SJerome Forissier 	}
254879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_RSA)) {
254979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5)) {
255079170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5)
255179170ce0SJerome Forissier 				goto check_element_none;
255279170ce0SJerome Forissier 		}
255379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
255479170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 ||
255579170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 ||
255679170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1)
255779170ce0SJerome Forissier 				goto check_element_none;
255879170ce0SJerome Forissier 		}
255979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) {
256079170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1)
256179170ce0SJerome Forissier 				goto check_element_none;
256279170ce0SJerome Forissier 		}
256379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
256479170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 ||
256579170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 ||
256679170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224)
256779170ce0SJerome Forissier 				goto check_element_none;
256879170ce0SJerome Forissier 		}
256979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
257079170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 ||
257179170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 ||
257279170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256)
257379170ce0SJerome Forissier 				goto check_element_none;
257479170ce0SJerome Forissier 		}
257579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
257679170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 ||
257779170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 ||
257879170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384)
257979170ce0SJerome Forissier 				goto check_element_none;
258079170ce0SJerome Forissier 		}
258179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
258279170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 ||
258379170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 ||
258479170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512)
258579170ce0SJerome Forissier 				goto check_element_none;
258679170ce0SJerome Forissier 		}
258779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) {
258879170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5)
258979170ce0SJerome Forissier 				goto check_element_none;
259079170ce0SJerome Forissier 		}
259179170ce0SJerome Forissier 		if (alg == TEE_ALG_RSA_NOPAD)
259279170ce0SJerome Forissier 			goto check_element_none;
259379170ce0SJerome Forissier 	}
259479170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DSA)) {
259579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
259679170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA1)
259779170ce0SJerome Forissier 				goto check_element_none;
259879170ce0SJerome Forissier 		}
259979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
260079170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA224)
260179170ce0SJerome Forissier 				goto check_element_none;
260279170ce0SJerome Forissier 		}
260379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
260479170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA256)
260579170ce0SJerome Forissier 				goto check_element_none;
260679170ce0SJerome Forissier 		}
260779170ce0SJerome Forissier 	}
260879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DH)) {
260979170ce0SJerome Forissier 		if (alg == TEE_ALG_DH_DERIVE_SHARED_SECRET)
261079170ce0SJerome Forissier 			goto check_element_none;
261179170ce0SJerome Forissier 	}
261279170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_ECC)) {
2613fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P192 ||
2614fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P192 ||
2615fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2616fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA1) &&
261779170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P192)
261879170ce0SJerome Forissier 			return TEE_SUCCESS;
2619fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P224 ||
2620fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P224 ||
2621fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2622fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA224) &&
262379170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P224)
262479170ce0SJerome Forissier 			return TEE_SUCCESS;
2625fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P256 ||
2626fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P256 ||
2627fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2628fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA256) &&
262979170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P256)
263079170ce0SJerome Forissier 			return TEE_SUCCESS;
2631fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P384 ||
2632fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P384 ||
2633fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2634fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA384) &&
263579170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P384)
263679170ce0SJerome Forissier 			return TEE_SUCCESS;
2637fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P521 ||
2638fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P521 ||
2639fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2640fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA512) &&
264179170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P521)
264279170ce0SJerome Forissier 			return TEE_SUCCESS;
264379170ce0SJerome Forissier 	}
264479170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_DSA)) {
264579170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_DSA_SM3 && element == TEE_ECC_CURVE_SM2)
264679170ce0SJerome Forissier 			return TEE_SUCCESS;
264779170ce0SJerome Forissier 	}
264879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_KEP)) {
264979170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_KEP && element == TEE_ECC_CURVE_SM2)
265079170ce0SJerome Forissier 			return TEE_SUCCESS;
265179170ce0SJerome Forissier 	}
265279170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_PKE)) {
265379170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_PKE && element == TEE_ECC_CURVE_SM2)
265479170ce0SJerome Forissier 			return TEE_SUCCESS;
265579170ce0SJerome Forissier 	}
26563f61056dSSohaib ul Hassan 	if (IS_ENABLED(CFG_CRYPTO_X25519)) {
26573f61056dSSohaib ul Hassan 		if (alg == TEE_ALG_X25519 && element == TEE_ECC_CURVE_25519)
26583f61056dSSohaib ul Hassan 			return TEE_SUCCESS;
26593f61056dSSohaib ul Hassan 	}
2660e1f9cee7SSergiy Kibrik 	if (IS_ENABLED(CFG_CRYPTO_ED25519)) {
2661e1f9cee7SSergiy Kibrik 		if (alg == TEE_ALG_ED25519 && element == TEE_ECC_CURVE_25519)
2662e1f9cee7SSergiy Kibrik 			return TEE_SUCCESS;
2663e1f9cee7SSergiy Kibrik 	}
266479170ce0SJerome Forissier 
266579170ce0SJerome Forissier 	return TEE_ERROR_NOT_SUPPORTED;
266679170ce0SJerome Forissier check_element_none:
266779170ce0SJerome Forissier 	if (element == TEE_CRYPTO_ELEMENT_NONE)
266879170ce0SJerome Forissier 		return TEE_SUCCESS;
266979170ce0SJerome Forissier 	return TEE_ERROR_NOT_SUPPORTED;
267079170ce0SJerome Forissier }
2671