xref: /optee_os/lib/libutee/tee_api_operations.c (revision 1bc176d8ca5c3442d88241479e51c1a9a5a24735)
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  */
624ea7613SJens 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 */
2424ea7613SJens Wiklander 
2524ea7613SJens Wiklander 	/*
2624ea7613SJens Wiklander 	 * buffer to collect complete blocks or to keep a complete digest
2724ea7613SJens Wiklander 	 * for TEE_DigestExtract().
2824ea7613SJens Wiklander 	 */
2924ea7613SJens 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:
26924ea7613SJens Wiklander 	case TEE_ALG_SHA3_224:
27024ea7613SJens Wiklander 	case TEE_ALG_SHA3_256:
27124ea7613SJens Wiklander 	case TEE_ALG_SHA3_384:
27224ea7613SJens Wiklander 	case TEE_ALG_SHA3_512:
27324ea7613SJens Wiklander 	case TEE_ALG_SHAKE128:
27424ea7613SJens 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 
32924ea7613SJens Wiklander 	/*
33024ea7613SJens Wiklander 	 * Needed to buffer the digest if TEE_DigestExtract() doesn't
33124ea7613SJens Wiklander 	 * retrieve the entire digest in one go.
33224ea7613SJens Wiklander 	 */
33324ea7613SJens Wiklander 	if (op->info.operationClass == TEE_OPERATION_DIGEST)
33424ea7613SJens Wiklander 		block_size = op->info.digestLength;
33524ea7613SJens 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 
563287a6182SJens Wiklander static void reset_operation_state(TEE_OperationHandle op)
564287a6182SJens Wiklander {
565287a6182SJens Wiklander 	op->operationState = TEE_OPERATION_STATE_INITIAL;
566287a6182SJens Wiklander 
567287a6182SJens Wiklander 	if (op->info.operationClass == TEE_OPERATION_DIGEST) {
568287a6182SJens Wiklander 		TEE_Result res = _utee_hash_init(op->state, NULL, 0);
569287a6182SJens Wiklander 
570287a6182SJens Wiklander 		if (res != TEE_SUCCESS)
571287a6182SJens Wiklander 			TEE_Panic(res);
572287a6182SJens Wiklander 		op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
573287a6182SJens Wiklander 	} else {
574287a6182SJens Wiklander 		op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
575287a6182SJens Wiklander 	}
576287a6182SJens Wiklander }
577287a6182SJens Wiklander 
578b0104773SPascal Brand void TEE_ResetOperation(TEE_OperationHandle operation)
579b0104773SPascal Brand {
580b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
581b0104773SPascal Brand 		TEE_Panic(0);
582bf80076aSCedric Chaumont 
583642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET))
584bf80076aSCedric Chaumont 		TEE_Panic(0);
585bf80076aSCedric Chaumont 
586287a6182SJens Wiklander 	reset_operation_state(operation);
58705304565SCedric Chaumont }
588b0104773SPascal Brand 
589b0104773SPascal Brand TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation,
590b0104773SPascal Brand 			       TEE_ObjectHandle key)
591b0104773SPascal Brand {
5927583c59eSCedric Chaumont 	TEE_Result res;
593b0104773SPascal Brand 	uint32_t key_size = 0;
594b0104773SPascal Brand 	TEE_ObjectInfo key_info;
595b0104773SPascal Brand 
596a57c1e2eSCedric Chaumont 	if (operation == TEE_HANDLE_NULL) {
597a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
598a57c1e2eSCedric Chaumont 		goto out;
599a57c1e2eSCedric Chaumont 	}
600a57c1e2eSCedric Chaumont 
601a57c1e2eSCedric Chaumont 	if (key == TEE_HANDLE_NULL) {
602a57c1e2eSCedric Chaumont 		/* Operation key cleared */
603a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key1);
6046c4ea258SJens Wiklander 		operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
605287a6182SJens Wiklander 		if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
606287a6182SJens Wiklander 			reset_operation_state(operation);
6076c4ea258SJens Wiklander 		return TEE_SUCCESS;
608a57c1e2eSCedric Chaumont 	}
609a57c1e2eSCedric Chaumont 
610a57c1e2eSCedric Chaumont 	/* No key for digest operation */
611a57c1e2eSCedric Chaumont 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
612a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
613a57c1e2eSCedric Chaumont 		goto out;
614a57c1e2eSCedric Chaumont 	}
615a57c1e2eSCedric Chaumont 
616a57c1e2eSCedric Chaumont 	/* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */
617a57c1e2eSCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) !=
618a57c1e2eSCedric Chaumont 	    0) {
619a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
620a57c1e2eSCedric Chaumont 		goto out;
621a57c1e2eSCedric Chaumont 	}
622a57c1e2eSCedric Chaumont 
6237583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key, &key_info);
624a57c1e2eSCedric Chaumont 	/* Key is not a valid handle */
6257583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
626a57c1e2eSCedric Chaumont 		goto out;
6277583c59eSCedric Chaumont 
628b0104773SPascal Brand 	/* Supplied key has to meet required usage */
629b0104773SPascal Brand 	if ((key_info.objectUsage & operation->info.requiredKeyUsage) !=
630b0104773SPascal Brand 	    operation->info.requiredKeyUsage) {
631a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
632a57c1e2eSCedric Chaumont 		goto out;
633b0104773SPascal Brand 	}
634b0104773SPascal Brand 
635d372a47cSJens Wiklander 	if (operation->info.maxKeySize < key_info.objectSize) {
636a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
637a57c1e2eSCedric Chaumont 		goto out;
638a57c1e2eSCedric Chaumont 	}
639b0104773SPascal Brand 
640d372a47cSJens Wiklander 	key_size = key_info.objectSize;
641b0104773SPascal Brand 
642b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key1);
643b0104773SPascal Brand 	operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
644b0104773SPascal Brand 
6457583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key1, key);
6467583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
647a57c1e2eSCedric Chaumont 		goto out;
6487583c59eSCedric Chaumont 
649b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET;
650b0104773SPascal Brand 
651b0104773SPascal Brand 	operation->info.keySize = key_size;
652b0104773SPascal Brand 
653287a6182SJens Wiklander 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
654287a6182SJens Wiklander 		reset_operation_state(operation);
655287a6182SJens Wiklander 
6567583c59eSCedric Chaumont out:
657a57c1e2eSCedric Chaumont 	if (res != TEE_SUCCESS  &&
658a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT &&
659a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE)
660b36311adSJerome Forissier 		TEE_Panic(res);
661a57c1e2eSCedric Chaumont 
662a57c1e2eSCedric Chaumont 	return res;
663b0104773SPascal Brand }
664b0104773SPascal Brand 
665287a6182SJens Wiklander TEE_Result __GP11_TEE_SetOperationKey(TEE_OperationHandle operation,
666287a6182SJens Wiklander 				      TEE_ObjectHandle key)
667287a6182SJens Wiklander {
668287a6182SJens Wiklander 	if (operation == TEE_HANDLE_NULL ||
669287a6182SJens Wiklander 	    operation->operationState != TEE_OPERATION_STATE_INITIAL)
670287a6182SJens Wiklander 		TEE_Panic(0);
671287a6182SJens Wiklander 
672287a6182SJens Wiklander 	return TEE_SetOperationKey(operation, key);
673287a6182SJens Wiklander }
674287a6182SJens Wiklander 
675287a6182SJens Wiklander static TEE_Result set_operation_key2(TEE_OperationHandle operation,
676287a6182SJens Wiklander 				     TEE_ObjectHandle key1,
677287a6182SJens Wiklander 				     TEE_ObjectHandle key2)
678b0104773SPascal Brand {
6797583c59eSCedric Chaumont 	TEE_Result res;
680b0104773SPascal Brand 	uint32_t key_size = 0;
681b0104773SPascal Brand 	TEE_ObjectInfo key_info1;
682b0104773SPascal Brand 	TEE_ObjectInfo key_info2;
683b0104773SPascal Brand 
684a57c1e2eSCedric Chaumont 	if (operation == TEE_HANDLE_NULL) {
685a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
686a57c1e2eSCedric Chaumont 		goto out;
687a57c1e2eSCedric Chaumont 	}
688a57c1e2eSCedric Chaumont 
689a57c1e2eSCedric Chaumont 	/*
690a57c1e2eSCedric Chaumont 	 * Key1/Key2 and/or are not initialized and
691a57c1e2eSCedric Chaumont 	 * Either both keys are NULL or both are not NULL
692a57c1e2eSCedric Chaumont 	 */
6936c4ea258SJens Wiklander 	if (!key1 && !key2) {
6946c4ea258SJens Wiklander 		/* Clear the keys */
695a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key1);
696a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key2);
6976c4ea258SJens Wiklander 		operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
698287a6182SJens Wiklander 		if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
699287a6182SJens Wiklander 			reset_operation_state(operation);
7006c4ea258SJens Wiklander 		return TEE_SUCCESS;
7016c4ea258SJens Wiklander 	} else if (!key1 || !key2) {
7026c4ea258SJens Wiklander 		/* Both keys are obviously not valid. */
703a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
704a57c1e2eSCedric Chaumont 		goto out;
705a57c1e2eSCedric Chaumont 	}
706a57c1e2eSCedric Chaumont 
707a57c1e2eSCedric Chaumont 	/* No key for digest operation */
708a57c1e2eSCedric Chaumont 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
709a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
710a57c1e2eSCedric Chaumont 		goto out;
711a57c1e2eSCedric Chaumont 	}
712a57c1e2eSCedric Chaumont 
7135b385b3fSJerome Forissier 	/* Two keys flag expected (TEE_ALG_AES_XTS and TEE_ALG_SM2_KEP only) */
714a57c1e2eSCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) ==
715a57c1e2eSCedric Chaumont 	    0) {
716a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
717a57c1e2eSCedric Chaumont 		goto out;
718a57c1e2eSCedric Chaumont 	}
719a57c1e2eSCedric Chaumont 
7207583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key1, &key_info1);
721a57c1e2eSCedric Chaumont 	/* Key1 is not a valid handle */
7227583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
723a57c1e2eSCedric Chaumont 		goto out;
7247583c59eSCedric Chaumont 
725b0104773SPascal Brand 	/* Supplied key has to meet required usage */
726b0104773SPascal Brand 	if ((key_info1.objectUsage & operation->info.
727b0104773SPascal Brand 	     requiredKeyUsage) != operation->info.requiredKeyUsage) {
728a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
729a57c1e2eSCedric Chaumont 		goto out;
730b0104773SPascal Brand 	}
731b0104773SPascal Brand 
7327583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key2, &key_info2);
733a57c1e2eSCedric Chaumont 	/* Key2 is not a valid handle */
7347583c59eSCedric Chaumont 	if (res != TEE_SUCCESS) {
7357583c59eSCedric Chaumont 		if (res == TEE_ERROR_CORRUPT_OBJECT)
7367583c59eSCedric Chaumont 			res = TEE_ERROR_CORRUPT_OBJECT_2;
737a57c1e2eSCedric Chaumont 		goto out;
7387583c59eSCedric Chaumont 	}
7397583c59eSCedric Chaumont 
740b0104773SPascal Brand 	/* Supplied key has to meet required usage */
741b0104773SPascal Brand 	if ((key_info2.objectUsage & operation->info.
742b0104773SPascal Brand 	     requiredKeyUsage) != operation->info.requiredKeyUsage) {
743a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
744a57c1e2eSCedric Chaumont 		goto out;
745b0104773SPascal Brand 	}
746b0104773SPascal Brand 
747b0104773SPascal Brand 	/*
7485b385b3fSJerome Forissier 	 * All the multi key algorithm currently supported requires the keys to
7495b385b3fSJerome Forissier 	 * be of equal size.
750b0104773SPascal Brand 	 */
751d372a47cSJens Wiklander 	if (key_info1.objectSize != key_info2.objectSize) {
752a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
753a57c1e2eSCedric Chaumont 		goto out;
754b0104773SPascal Brand 
755a57c1e2eSCedric Chaumont 	}
756a57c1e2eSCedric Chaumont 
757d372a47cSJens Wiklander 	if (operation->info.maxKeySize < key_info1.objectSize) {
758a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
759a57c1e2eSCedric Chaumont 		goto out;
760a57c1e2eSCedric Chaumont 	}
761b0104773SPascal Brand 
762b0104773SPascal Brand 	/*
763b0104773SPascal Brand 	 * Odd that only the size of one key should be reported while
764b0104773SPascal Brand 	 * size of two key are used when allocating the operation.
765b0104773SPascal Brand 	 */
766d372a47cSJens Wiklander 	key_size = key_info1.objectSize;
767b0104773SPascal Brand 
768b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key1);
769b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key2);
770b0104773SPascal Brand 	operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
771b0104773SPascal Brand 
7727583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key1, key1);
7737583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
774a57c1e2eSCedric Chaumont 		goto out;
7757583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key2, key2);
7767583c59eSCedric Chaumont 	if (res != TEE_SUCCESS) {
7777583c59eSCedric Chaumont 		if (res == TEE_ERROR_CORRUPT_OBJECT)
7787583c59eSCedric Chaumont 			res = TEE_ERROR_CORRUPT_OBJECT_2;
779a57c1e2eSCedric Chaumont 		goto out;
7807583c59eSCedric Chaumont 	}
7817583c59eSCedric Chaumont 
782b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET;
783b0104773SPascal Brand 
784b0104773SPascal Brand 	operation->info.keySize = key_size;
785b0104773SPascal Brand 
786287a6182SJens Wiklander 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
787287a6182SJens Wiklander 		reset_operation_state(operation);
7887583c59eSCedric Chaumont out:
789a57c1e2eSCedric Chaumont 	if (res != TEE_SUCCESS  &&
790a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT &&
791a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT_2 &&
792a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE &&
793a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2)
794b36311adSJerome Forissier 		TEE_Panic(res);
795a57c1e2eSCedric Chaumont 
796a57c1e2eSCedric Chaumont 	return res;
797b0104773SPascal Brand }
798b0104773SPascal Brand 
799287a6182SJens Wiklander TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation,
800287a6182SJens Wiklander 				TEE_ObjectHandle key1, TEE_ObjectHandle key2)
801287a6182SJens Wiklander {
802287a6182SJens Wiklander 	if (operation != TEE_HANDLE_NULL && key1 && key1 == key2)
803287a6182SJens Wiklander 		return TEE_ERROR_SECURITY;
804287a6182SJens Wiklander 
805287a6182SJens Wiklander 	return set_operation_key2(operation, key1, key2);
806287a6182SJens Wiklander }
807287a6182SJens Wiklander 
808287a6182SJens Wiklander TEE_Result __GP11_TEE_SetOperationKey2(TEE_OperationHandle operation,
809287a6182SJens Wiklander 				       TEE_ObjectHandle key1,
810287a6182SJens Wiklander 				       TEE_ObjectHandle key2)
811287a6182SJens Wiklander {
812287a6182SJens Wiklander 	if (operation == TEE_HANDLE_NULL ||
813287a6182SJens Wiklander 	    operation->operationState != TEE_OPERATION_STATE_INITIAL)
814287a6182SJens Wiklander 		TEE_Panic(0);
815287a6182SJens Wiklander 
816287a6182SJens Wiklander 	return set_operation_key2(operation, key1, key2);
817287a6182SJens Wiklander }
818287a6182SJens Wiklander 
819b0104773SPascal Brand void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op)
820b0104773SPascal Brand {
821b0104773SPascal Brand 	TEE_Result res;
822b0104773SPascal Brand 
823b0104773SPascal Brand 	if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL)
824b0104773SPascal Brand 		TEE_Panic(0);
825b0104773SPascal Brand 	if (dst_op->info.algorithm != src_op->info.algorithm)
826b0104773SPascal Brand 		TEE_Panic(0);
8278734de30SJens Wiklander 	if (dst_op->info.mode != src_op->info.mode)
8288734de30SJens Wiklander 		TEE_Panic(0);
829b0104773SPascal Brand 	if (src_op->info.operationClass != TEE_OPERATION_DIGEST) {
830b0104773SPascal Brand 		TEE_ObjectHandle key1 = TEE_HANDLE_NULL;
831b0104773SPascal Brand 		TEE_ObjectHandle key2 = TEE_HANDLE_NULL;
832b0104773SPascal Brand 
833b0104773SPascal Brand 		if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) {
834b0104773SPascal Brand 			key1 = src_op->key1;
835b0104773SPascal Brand 			key2 = src_op->key2;
836b0104773SPascal Brand 		}
837b0104773SPascal Brand 
838b0104773SPascal Brand 		if ((src_op->info.handleState &
839b0104773SPascal Brand 		     TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) {
840b0104773SPascal Brand 			TEE_SetOperationKey(dst_op, key1);
841b0104773SPascal Brand 		} else {
842b0104773SPascal Brand 			TEE_SetOperationKey2(dst_op, key1, key2);
843b0104773SPascal Brand 		}
844b0104773SPascal Brand 	}
845b0104773SPascal Brand 	dst_op->info.handleState = src_op->info.handleState;
846b0104773SPascal Brand 	dst_op->info.keySize = src_op->info.keySize;
8478e07702eSJens Wiklander 	dst_op->info.digestLength = src_op->info.digestLength;
848642a1607SCedric Chaumont 	dst_op->operationState = src_op->operationState;
849b0104773SPascal Brand 
850b0104773SPascal Brand 	if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks ||
851b0104773SPascal Brand 	    dst_op->block_size != src_op->block_size)
852b0104773SPascal Brand 		TEE_Panic(0);
853b0104773SPascal Brand 
854b0104773SPascal Brand 	if (dst_op->buffer != NULL) {
85524ea7613SJens Wiklander 		size_t sz = src_op->block_size;
85624ea7613SJens Wiklander 
857b0104773SPascal Brand 		if (src_op->buffer == NULL)
858b0104773SPascal Brand 			TEE_Panic(0);
859b0104773SPascal Brand 
86024ea7613SJens Wiklander 		if (src_op->buffer_two_blocks)
86124ea7613SJens Wiklander 			sz *= 2;
86224ea7613SJens Wiklander 		memcpy(dst_op->buffer, src_op->buffer, sz);
863b0104773SPascal Brand 		dst_op->buffer_offs = src_op->buffer_offs;
864b0104773SPascal Brand 	} else if (src_op->buffer != NULL) {
865b0104773SPascal Brand 		TEE_Panic(0);
866b0104773SPascal Brand 	}
867b0104773SPascal Brand 
8682c028fdeSJerome Forissier 	res = _utee_cryp_state_copy(dst_op->state, src_op->state);
869b0104773SPascal Brand 	if (res != TEE_SUCCESS)
870b0104773SPascal Brand 		TEE_Panic(res);
871b0104773SPascal Brand }
872b0104773SPascal Brand 
873b0104773SPascal Brand /* Cryptographic Operations API - Message Digest Functions */
874b0104773SPascal Brand 
8758f07fe6fSJerome Forissier static void init_hash_operation(TEE_OperationHandle operation, const void *IV,
8766d15db08SJerome Forissier 				uint32_t IVLen)
8776d15db08SJerome Forissier {
8786d15db08SJerome Forissier 	TEE_Result res;
8796d15db08SJerome Forissier 
8806d15db08SJerome Forissier 	/*
8816d15db08SJerome Forissier 	 * Note : IV and IVLen are never used in current implementation
8826d15db08SJerome Forissier 	 * This is why coherent values of IV and IVLen are not checked
8836d15db08SJerome Forissier 	 */
8842c028fdeSJerome Forissier 	res = _utee_hash_init(operation->state, IV, IVLen);
8856d15db08SJerome Forissier 	if (res != TEE_SUCCESS)
8866d15db08SJerome Forissier 		TEE_Panic(res);
8876d15db08SJerome Forissier 	operation->buffer_offs = 0;
8886d15db08SJerome Forissier 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
8896d15db08SJerome Forissier }
8906d15db08SJerome Forissier 
891b0104773SPascal Brand void TEE_DigestUpdate(TEE_OperationHandle operation,
892185bf58cSJens Wiklander 		      const void *chunk, size_t chunkSize)
893b0104773SPascal Brand {
89473d6c3baSJoakim Bech 	TEE_Result res = TEE_ERROR_GENERIC;
895b0104773SPascal Brand 
89673d6c3baSJoakim Bech 	if (operation == TEE_HANDLE_NULL ||
89773d6c3baSJoakim Bech 	    operation->info.operationClass != TEE_OPERATION_DIGEST)
898b0104773SPascal Brand 		TEE_Panic(0);
89973d6c3baSJoakim Bech 
900642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
901642a1607SCedric Chaumont 
9022c028fdeSJerome Forissier 	res = _utee_hash_update(operation->state, chunk, chunkSize);
903b0104773SPascal Brand 	if (res != TEE_SUCCESS)
904b0104773SPascal Brand 		TEE_Panic(res);
905b0104773SPascal Brand }
906b0104773SPascal Brand 
907185bf58cSJens Wiklander void __GP11_TEE_DigestUpdate(TEE_OperationHandle operation,
908185bf58cSJens Wiklander 			     const void *chunk, uint32_t chunkSize)
909185bf58cSJens Wiklander {
910185bf58cSJens Wiklander 	return TEE_DigestUpdate(operation, chunk, chunkSize);
911185bf58cSJens Wiklander }
912185bf58cSJens Wiklander 
9138f07fe6fSJerome Forissier TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk,
914185bf58cSJens Wiklander 			     size_t chunkLen, void *hash, size_t *hashLen)
915b0104773SPascal Brand {
91624ea7613SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
91724ea7613SJens Wiklander 	uint64_t hl = 0;
91824ea7613SJens Wiklander 	size_t len = 0;
91987c2f6b6SCedric Chaumont 
92087c2f6b6SCedric Chaumont 	if ((operation == TEE_HANDLE_NULL) ||
92187c2f6b6SCedric Chaumont 	    (!chunk && chunkLen) ||
92287c2f6b6SCedric Chaumont 	    (operation->info.operationClass != TEE_OPERATION_DIGEST)) {
92387c2f6b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
92487c2f6b6SCedric Chaumont 		goto out;
92587c2f6b6SCedric Chaumont 	}
92624ea7613SJens Wiklander 	if (operation->operationState == TEE_OPERATION_STATE_EXTRACTING &&
92724ea7613SJens Wiklander 	    chunkLen) {
92824ea7613SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
92924ea7613SJens Wiklander 		goto out;
93024ea7613SJens Wiklander 	}
9316915bbbbSJens Wiklander 	__utee_check_inout_annotation(hashLen, sizeof(*hashLen));
93287c2f6b6SCedric Chaumont 
93324ea7613SJens Wiklander 	if (operation->operationState == TEE_OPERATION_STATE_EXTRACTING &&
93424ea7613SJens Wiklander 	    operation->buffer) {
93524ea7613SJens Wiklander 		/*
93624ea7613SJens Wiklander 		 * This is not an Extendable-Output Function and we have
93724ea7613SJens Wiklander 		 * already started extracting
93824ea7613SJens Wiklander 		 */
93924ea7613SJens Wiklander 		len = MIN(operation->block_size - operation->buffer_offs,
94024ea7613SJens Wiklander 			  *hashLen);
94124ea7613SJens Wiklander 		memcpy(hash, operation->buffer + operation->buffer_offs, len);
94224ea7613SJens Wiklander 		*hashLen = len;
94324ea7613SJens Wiklander 	} else {
944e86f1266SJens Wiklander 		hl = *hashLen;
94524ea7613SJens Wiklander 		res = _utee_hash_final(operation->state, chunk, chunkLen, hash,
94624ea7613SJens Wiklander 				       &hl);
947e86f1266SJens Wiklander 		*hashLen = hl;
94824ea7613SJens Wiklander 		if (res)
9496d15db08SJerome Forissier 			goto out;
95024ea7613SJens Wiklander 	}
9516d15db08SJerome Forissier 
9526d15db08SJerome Forissier 	/* Reset operation state */
9536d15db08SJerome Forissier 	init_hash_operation(operation, NULL, 0);
95487c2f6b6SCedric Chaumont 
955642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
956642a1607SCedric Chaumont 
95787c2f6b6SCedric Chaumont out:
95887c2f6b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
95987c2f6b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
960b36311adSJerome Forissier 		TEE_Panic(res);
96173d6c3baSJoakim Bech 
96287c2f6b6SCedric Chaumont 	return res;
963b0104773SPascal Brand }
964b0104773SPascal Brand 
965185bf58cSJens Wiklander TEE_Result __GP11_TEE_DigestDoFinal(TEE_OperationHandle operation,
966185bf58cSJens Wiklander 				    const void *chunk, uint32_t chunkLen,
967185bf58cSJens Wiklander 				    void *hash, uint32_t *hashLen)
968185bf58cSJens Wiklander {
969185bf58cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
970185bf58cSJens Wiklander 	size_t l = 0;
971185bf58cSJens Wiklander 
972185bf58cSJens Wiklander 	__utee_check_inout_annotation(hashLen, sizeof(*hashLen));
973185bf58cSJens Wiklander 	l = *hashLen;
974185bf58cSJens Wiklander 	res = TEE_DigestDoFinal(operation, chunk, chunkLen, hash, &l);
975185bf58cSJens Wiklander 	*hashLen = l;
976185bf58cSJens Wiklander 	return res;
977185bf58cSJens Wiklander }
978185bf58cSJens Wiklander 
97924ea7613SJens Wiklander TEE_Result TEE_DigestExtract(TEE_OperationHandle operation, void *hash,
98024ea7613SJens Wiklander 			     size_t *hashLen)
98124ea7613SJens Wiklander {
98224ea7613SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
98324ea7613SJens Wiklander 	uint64_t hl = 0;
98424ea7613SJens Wiklander 	size_t len = 0;
98524ea7613SJens Wiklander 
98624ea7613SJens Wiklander 	if (operation == TEE_HANDLE_NULL ||
98724ea7613SJens Wiklander 	    operation->info.operationClass != TEE_OPERATION_DIGEST)
98824ea7613SJens Wiklander 		TEE_Panic(0);
98924ea7613SJens Wiklander 	__utee_check_inout_annotation(hashLen, sizeof(*hashLen));
99024ea7613SJens Wiklander 
99124ea7613SJens Wiklander 	if (!operation->buffer) {
99224ea7613SJens Wiklander 		/* This is an Extendable-Output Function */
99324ea7613SJens Wiklander 		operation->info.handleState |= TEE_HANDLE_FLAG_EXTRACTING;
99424ea7613SJens Wiklander 		operation->operationState = TEE_OPERATION_STATE_EXTRACTING;
99524ea7613SJens Wiklander 		hl = *hashLen;
99624ea7613SJens Wiklander 		res = _utee_hash_final(operation->state, NULL, 0, hash, &hl);
99724ea7613SJens Wiklander 		if (res)
99824ea7613SJens Wiklander 			TEE_Panic(0);
99924ea7613SJens Wiklander 		*hashLen = hl;
100024ea7613SJens Wiklander 
100124ea7613SJens Wiklander 		return TEE_SUCCESS;
100224ea7613SJens Wiklander 	}
100324ea7613SJens Wiklander 
100424ea7613SJens Wiklander 	if (operation->operationState != TEE_OPERATION_STATE_EXTRACTING) {
100524ea7613SJens Wiklander 		hl = operation->block_size;
100624ea7613SJens Wiklander 		res = _utee_hash_final(operation->state, NULL, 0,
100724ea7613SJens Wiklander 				       operation->buffer, &hl);
100824ea7613SJens Wiklander 		if (res)
100924ea7613SJens Wiklander 			TEE_Panic(0);
101024ea7613SJens Wiklander 		if (hl != operation->block_size)
101124ea7613SJens Wiklander 			TEE_Panic(0);
101224ea7613SJens Wiklander 		assert(!operation->buffer_offs);
101324ea7613SJens Wiklander 		operation->info.handleState |= TEE_HANDLE_FLAG_EXTRACTING;
101424ea7613SJens Wiklander 		operation->operationState = TEE_OPERATION_STATE_EXTRACTING;
101524ea7613SJens Wiklander 	}
101624ea7613SJens Wiklander 
101724ea7613SJens Wiklander 	len = MIN(operation->block_size - operation->buffer_offs, *hashLen);
101824ea7613SJens Wiklander 	memcpy(hash, operation->buffer + operation->buffer_offs, len);
101924ea7613SJens Wiklander 	*hashLen = len;
102024ea7613SJens Wiklander 	operation->buffer_offs += len;
102124ea7613SJens Wiklander 
102224ea7613SJens Wiklander 	return TEE_SUCCESS;
102324ea7613SJens Wiklander }
102424ea7613SJens Wiklander 
1025b0104773SPascal Brand /* Cryptographic Operations API - Symmetric Cipher Functions */
1026b0104773SPascal Brand 
10278f07fe6fSJerome Forissier void TEE_CipherInit(TEE_OperationHandle operation, const void *IV,
1028185bf58cSJens Wiklander 		    size_t IVLen)
1029b0104773SPascal Brand {
1030b0104773SPascal Brand 	TEE_Result res;
1031b0104773SPascal Brand 
1032b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
1033b0104773SPascal Brand 		TEE_Panic(0);
1034642a1607SCedric Chaumont 
1035b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_CIPHER)
1036b0104773SPascal Brand 		TEE_Panic(0);
1037642a1607SCedric Chaumont 
1038642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||
1039642a1607SCedric Chaumont 	    !(operation->key1))
1040642a1607SCedric Chaumont 		TEE_Panic(0);
1041642a1607SCedric Chaumont 
1042642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
1043642a1607SCedric Chaumont 		TEE_ResetOperation(operation);
1044642a1607SCedric Chaumont 
1045ad7aa2a5SSadiq Hussain 	if (IV && IVLen) {
1046ad7aa2a5SSadiq Hussain 		if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD ||
1047ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD ||
1048ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD ||
1049ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD)
1050ad7aa2a5SSadiq Hussain 			TEE_Panic(0);
1051ad7aa2a5SSadiq Hussain 	}
1052ad7aa2a5SSadiq Hussain 
1053642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1054642a1607SCedric Chaumont 
10552c028fdeSJerome Forissier 	res = _utee_cipher_init(operation->state, IV, IVLen);
1056b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1057b0104773SPascal Brand 		TEE_Panic(res);
1058642a1607SCedric Chaumont 
1059b0104773SPascal Brand 	operation->buffer_offs = 0;
1060b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
1061b0104773SPascal Brand }
1062b0104773SPascal Brand 
1063185bf58cSJens Wiklander void __GP11_TEE_CipherInit(TEE_OperationHandle operation, const void *IV,
1064185bf58cSJens Wiklander 			   uint32_t IVLen)
1065185bf58cSJens Wiklander {
1066185bf58cSJens Wiklander 	return TEE_CipherInit(operation, IV, IVLen);
1067185bf58cSJens Wiklander }
1068185bf58cSJens Wiklander 
1069b0104773SPascal Brand static TEE_Result tee_buffer_update(
1070b0104773SPascal Brand 		TEE_OperationHandle op,
1071e86f1266SJens Wiklander 		TEE_Result(*update_func)(unsigned long state, const void *src,
1072e86f1266SJens Wiklander 				size_t slen, void *dst, uint64_t *dlen),
1073b0104773SPascal Brand 		const void *src_data, size_t src_len,
1074e86f1266SJens Wiklander 		void *dest_data, uint64_t *dest_len)
1075b0104773SPascal Brand {
1076b0104773SPascal Brand 	TEE_Result res;
1077b0104773SPascal Brand 	const uint8_t *src = src_data;
1078b0104773SPascal Brand 	size_t slen = src_len;
1079b0104773SPascal Brand 	uint8_t *dst = dest_data;
1080b0104773SPascal Brand 	size_t dlen = *dest_len;
1081b0104773SPascal Brand 	size_t acc_dlen = 0;
1082e86f1266SJens Wiklander 	uint64_t tmp_dlen;
1083b0104773SPascal Brand 	size_t l;
1084b0104773SPascal Brand 	size_t buffer_size;
1085d3588802SPascal Brand 	size_t buffer_left;
1086b0104773SPascal Brand 
1087090268f5SJens Wiklander 	if (!src) {
1088090268f5SJens Wiklander 		if (slen)
1089090268f5SJens Wiklander 			TEE_Panic(0);
1090090268f5SJens Wiklander 		goto out;
1091090268f5SJens Wiklander 	}
1092090268f5SJens Wiklander 
1093d3588802SPascal Brand 	if (op->buffer_two_blocks) {
1094b0104773SPascal Brand 		buffer_size = op->block_size * 2;
1095d3588802SPascal Brand 		buffer_left = 1;
1096d3588802SPascal Brand 	} else {
1097b0104773SPascal Brand 		buffer_size = op->block_size;
1098d3588802SPascal Brand 		buffer_left = 0;
1099d3588802SPascal Brand 	}
1100b0104773SPascal Brand 
1101b0104773SPascal Brand 	if (op->buffer_offs > 0) {
1102b0104773SPascal Brand 		/* Fill up complete block */
1103b0104773SPascal Brand 		if (op->buffer_offs < op->block_size)
1104b0104773SPascal Brand 			l = MIN(slen, op->block_size - op->buffer_offs);
1105b0104773SPascal Brand 		else
1106b0104773SPascal Brand 			l = MIN(slen, buffer_size - op->buffer_offs);
1107b0104773SPascal Brand 		memcpy(op->buffer + op->buffer_offs, src, l);
1108b0104773SPascal Brand 		op->buffer_offs += l;
1109b0104773SPascal Brand 		src += l;
1110b0104773SPascal Brand 		slen -= l;
1111b0104773SPascal Brand 		if ((op->buffer_offs % op->block_size) != 0)
1112b0104773SPascal Brand 			goto out;	/* Nothing left to do */
1113b0104773SPascal Brand 	}
1114b0104773SPascal Brand 
1115b0104773SPascal Brand 	/* If we can feed from buffer */
1116d3588802SPascal Brand 	if ((op->buffer_offs > 0) &&
1117d3588802SPascal Brand 	    ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) {
11182ff3fdbbSPascal Brand 		l = ROUNDUP(op->buffer_offs + slen - buffer_size,
1119b0104773SPascal Brand 				op->block_size);
1120b0104773SPascal Brand 		l = MIN(op->buffer_offs, l);
1121b0104773SPascal Brand 		tmp_dlen = dlen;
1122b0104773SPascal Brand 		res = update_func(op->state, op->buffer, l, dst, &tmp_dlen);
1123b0104773SPascal Brand 		if (res != TEE_SUCCESS)
1124b0104773SPascal Brand 			TEE_Panic(res);
1125b0104773SPascal Brand 		dst += tmp_dlen;
1126b0104773SPascal Brand 		dlen -= tmp_dlen;
1127b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1128b0104773SPascal Brand 		op->buffer_offs -= l;
1129b0104773SPascal Brand 		if (op->buffer_offs > 0) {
1130b0104773SPascal Brand 			/*
1131b0104773SPascal Brand 			 * Slen is small enough to be contained in rest buffer.
1132b0104773SPascal Brand 			 */
1133b0104773SPascal Brand 			memcpy(op->buffer, op->buffer + l, buffer_size - l);
1134b0104773SPascal Brand 			memcpy(op->buffer + op->buffer_offs, src, slen);
1135b0104773SPascal Brand 			op->buffer_offs += slen;
1136b0104773SPascal Brand 			goto out;	/* Nothing left to do */
1137b0104773SPascal Brand 		}
1138b0104773SPascal Brand 	}
1139b0104773SPascal Brand 
1140d3588802SPascal Brand 	if (slen >= (buffer_size + buffer_left)) {
1141b0104773SPascal Brand 		/* Buffer is empty, feed as much as possible from src */
1142bf7a587fSJerome Forissier 		if (op->info.algorithm == TEE_ALG_AES_CTS)
1143b1ecda78SJerome Forissier 			l = ROUNDUP(slen - buffer_size, op->block_size);
1144bf7a587fSJerome Forissier 		else
1145bf7a587fSJerome Forissier 			l = ROUNDUP(slen - buffer_size + 1, op->block_size);
1146b0104773SPascal Brand 
1147b0104773SPascal Brand 		tmp_dlen = dlen;
1148b0104773SPascal Brand 		res = update_func(op->state, src, l, dst, &tmp_dlen);
1149b0104773SPascal Brand 		if (res != TEE_SUCCESS)
1150b0104773SPascal Brand 			TEE_Panic(res);
1151b0104773SPascal Brand 		src += l;
1152b0104773SPascal Brand 		slen -= l;
1153b0104773SPascal Brand 		dst += tmp_dlen;
1154b0104773SPascal Brand 		dlen -= tmp_dlen;
1155b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1156b0104773SPascal Brand 	}
1157b0104773SPascal Brand 
1158b0104773SPascal Brand 	/* Slen is small enough to be contained in buffer. */
1159b0104773SPascal Brand 	memcpy(op->buffer + op->buffer_offs, src, slen);
1160b0104773SPascal Brand 	op->buffer_offs += slen;
1161b0104773SPascal Brand 
1162b0104773SPascal Brand out:
1163b0104773SPascal Brand 	*dest_len = acc_dlen;
1164b0104773SPascal Brand 	return TEE_SUCCESS;
1165b0104773SPascal Brand }
1166b0104773SPascal Brand 
11678f07fe6fSJerome Forissier TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData,
1168185bf58cSJens Wiklander 			    size_t srcLen, void *destData, size_t *destLen)
1169b0104773SPascal Brand {
1170dea1f2b6SCedric Chaumont 	TEE_Result res;
1171b0104773SPascal Brand 	size_t req_dlen;
1172e86f1266SJens Wiklander 	uint64_t dl;
1173b0104773SPascal Brand 
11746915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1175dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1176dea1f2b6SCedric Chaumont 		goto out;
1177dea1f2b6SCedric Chaumont 	}
11786915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1179dea1f2b6SCedric Chaumont 
1180642a1607SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_CIPHER) {
1181dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1182dea1f2b6SCedric Chaumont 		goto out;
1183dea1f2b6SCedric Chaumont 	}
1184dea1f2b6SCedric Chaumont 
1185642a1607SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1186642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1187642a1607SCedric Chaumont 		goto out;
1188642a1607SCedric Chaumont 	}
1189642a1607SCedric Chaumont 
1190642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1191dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1192dea1f2b6SCedric Chaumont 		goto out;
1193dea1f2b6SCedric Chaumont 	}
1194b0104773SPascal Brand 
1195e32c5ddfSJerome Forissier 	if (!srcData && !srcLen) {
1196090268f5SJens Wiklander 		*destLen = 0;
1197e32c5ddfSJerome Forissier 		res = TEE_SUCCESS;
1198e32c5ddfSJerome Forissier 		goto out;
1199e32c5ddfSJerome Forissier 	}
1200e32c5ddfSJerome Forissier 
1201b0104773SPascal Brand 	/* Calculate required dlen */
120257aabac5SBogdan Liulko 	if (operation->block_size > 1) {
120357aabac5SBogdan Liulko 		req_dlen = ((operation->buffer_offs + srcLen) /
120457aabac5SBogdan Liulko 			    operation->block_size) * operation->block_size;
120557aabac5SBogdan Liulko 	} else {
120657aabac5SBogdan Liulko 		req_dlen = srcLen;
120757aabac5SBogdan Liulko 	}
1208642a1607SCedric Chaumont 	if (operation->buffer_two_blocks) {
1209642a1607SCedric Chaumont 		if (req_dlen > operation->block_size * 2)
1210642a1607SCedric Chaumont 			req_dlen -= operation->block_size * 2;
1211b0104773SPascal Brand 		else
1212b0104773SPascal Brand 			req_dlen = 0;
1213b0104773SPascal Brand 	}
1214b0104773SPascal Brand 	/*
1215b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1216b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1217b0104773SPascal Brand 	 * can't restore sync with this API.
1218b0104773SPascal Brand 	 */
1219b0104773SPascal Brand 	if (*destLen < req_dlen) {
1220b0104773SPascal Brand 		*destLen = req_dlen;
1221dea1f2b6SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1222dea1f2b6SCedric Chaumont 		goto out;
1223b0104773SPascal Brand 	}
1224b0104773SPascal Brand 
1225e86f1266SJens Wiklander 	dl = *destLen;
122657aabac5SBogdan Liulko 	if (operation->block_size > 1) {
12272c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_cipher_update, srcData,
122857aabac5SBogdan Liulko 					srcLen, destData, &dl);
122957aabac5SBogdan Liulko 	} else {
123057aabac5SBogdan Liulko 		if (srcLen > 0) {
12312c028fdeSJerome Forissier 			res = _utee_cipher_update(operation->state, srcData,
123257aabac5SBogdan Liulko 						  srcLen, destData, &dl);
123357aabac5SBogdan Liulko 		} else {
123457aabac5SBogdan Liulko 			res = TEE_SUCCESS;
123557aabac5SBogdan Liulko 			dl = 0;
123657aabac5SBogdan Liulko 		}
123757aabac5SBogdan Liulko 	}
1238e86f1266SJens Wiklander 	*destLen = dl;
1239b0104773SPascal Brand 
1240dea1f2b6SCedric Chaumont out:
1241dea1f2b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
1242dea1f2b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1243b36311adSJerome Forissier 		TEE_Panic(res);
1244dea1f2b6SCedric Chaumont 
1245dea1f2b6SCedric Chaumont 	return res;
1246b0104773SPascal Brand }
1247b0104773SPascal Brand 
1248185bf58cSJens Wiklander TEE_Result __GP11_TEE_CipherUpdate(TEE_OperationHandle operation,
12498f07fe6fSJerome Forissier 				   const void *srcData, uint32_t srcLen,
12508f07fe6fSJerome Forissier 				   void *destData, uint32_t *destLen)
1251b0104773SPascal Brand {
12526915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1253185bf58cSJens Wiklander 	size_t dl = 0;
1254185bf58cSJens Wiklander 
1255185bf58cSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1256185bf58cSJens Wiklander 	dl = *destLen;
1257185bf58cSJens Wiklander 	res = TEE_CipherUpdate(operation, srcData, srcLen, destData, &dl);
1258185bf58cSJens Wiklander 	*destLen = dl;
1259185bf58cSJens Wiklander 	return res;
1260185bf58cSJens Wiklander }
1261185bf58cSJens Wiklander 
1262185bf58cSJens Wiklander TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation,
1263185bf58cSJens Wiklander 			     const void *srcData, size_t srcLen,
1264185bf58cSJens Wiklander 			     void *destData, size_t *destLen)
1265185bf58cSJens Wiklander {
1266185bf58cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1267b0104773SPascal Brand 	uint8_t *dst = destData;
1268b0104773SPascal Brand 	size_t acc_dlen = 0;
12696915bbbbSJens Wiklander 	uint64_t tmp_dlen = 0;
12706915bbbbSJens Wiklander 	size_t req_dlen = 0;
1271b0104773SPascal Brand 
12726915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1273dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1274dea1f2b6SCedric Chaumont 		goto out;
1275dea1f2b6SCedric Chaumont 	}
12766915bbbbSJens Wiklander 	if (destLen)
12776915bbbbSJens Wiklander 		__utee_check_inout_annotation(destLen, sizeof(*destLen));
1278dea1f2b6SCedric Chaumont 
1279642a1607SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_CIPHER) {
1280dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1281dea1f2b6SCedric Chaumont 		goto out;
1282dea1f2b6SCedric Chaumont 	}
1283dea1f2b6SCedric Chaumont 
1284642a1607SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1285642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1286642a1607SCedric Chaumont 		goto out;
1287642a1607SCedric Chaumont 	}
1288642a1607SCedric Chaumont 
1289642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1290dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1291dea1f2b6SCedric Chaumont 		goto out;
1292dea1f2b6SCedric Chaumont 	}
1293b0104773SPascal Brand 
1294b0104773SPascal Brand 	/*
1295b0104773SPascal Brand 	 * Check that the final block doesn't require padding for those
1296b0104773SPascal Brand 	 * algorithms that requires client to supply padding.
1297b0104773SPascal Brand 	 */
1298642a1607SCedric Chaumont 	if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD ||
1299642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD ||
1300642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD ||
1301642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD ||
1302642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD ||
1303ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD ||
1304ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD ||
1305ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_SM4_CBC_NOPAD) {
1306642a1607SCedric Chaumont 		if (((operation->buffer_offs + srcLen) % operation->block_size)
1307642a1607SCedric Chaumont 		    != 0) {
1308dea1f2b6SCedric Chaumont 			res = TEE_ERROR_BAD_PARAMETERS;
1309dea1f2b6SCedric Chaumont 			goto out;
1310dea1f2b6SCedric Chaumont 		}
1311b0104773SPascal Brand 	}
1312b0104773SPascal Brand 
1313b0104773SPascal Brand 	/*
1314b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1315b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1316b0104773SPascal Brand 	 * can't restore sync with this API.
1317b0104773SPascal Brand 	 */
131857aabac5SBogdan Liulko 	if (operation->block_size > 1) {
1319642a1607SCedric Chaumont 		req_dlen = operation->buffer_offs + srcLen;
132057aabac5SBogdan Liulko 	} else {
132157aabac5SBogdan Liulko 		req_dlen = srcLen;
132257aabac5SBogdan Liulko 	}
13236915bbbbSJens Wiklander 	if (destLen)
13246915bbbbSJens Wiklander 		tmp_dlen = *destLen;
13256915bbbbSJens Wiklander 	if (tmp_dlen < req_dlen) {
13266915bbbbSJens Wiklander 		if (destLen)
1327b0104773SPascal Brand 			*destLen = req_dlen;
1328dea1f2b6SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1329dea1f2b6SCedric Chaumont 		goto out;
1330b0104773SPascal Brand 	}
1331b0104773SPascal Brand 
133257aabac5SBogdan Liulko 	if (operation->block_size > 1) {
1333dea9063eSJens Wiklander 		if (srcLen) {
13342c028fdeSJerome Forissier 			res = tee_buffer_update(operation, _utee_cipher_update,
1335dea9063eSJens Wiklander 						srcData, srcLen, dst,
1336dea9063eSJens Wiklander 						&tmp_dlen);
1337dea1f2b6SCedric Chaumont 			if (res != TEE_SUCCESS)
1338dea1f2b6SCedric Chaumont 				goto out;
1339dea1f2b6SCedric Chaumont 
1340b0104773SPascal Brand 			dst += tmp_dlen;
1341b0104773SPascal Brand 			acc_dlen += tmp_dlen;
1342b0104773SPascal Brand 
1343b0104773SPascal Brand 			tmp_dlen = *destLen - acc_dlen;
1344dea9063eSJens Wiklander 		}
13452c028fdeSJerome Forissier 		res = _utee_cipher_final(operation->state, operation->buffer,
13462c028fdeSJerome Forissier 					 operation->buffer_offs, dst,
13472c028fdeSJerome Forissier 					 &tmp_dlen);
134857aabac5SBogdan Liulko 	} else {
13492c028fdeSJerome Forissier 		res = _utee_cipher_final(operation->state, srcData, srcLen, dst,
13502c028fdeSJerome Forissier 					 &tmp_dlen);
135157aabac5SBogdan Liulko 	}
1352b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1353dea1f2b6SCedric Chaumont 		goto out;
1354dea1f2b6SCedric Chaumont 
1355b0104773SPascal Brand 	acc_dlen += tmp_dlen;
13566915bbbbSJens Wiklander 	if (destLen)
1357b0104773SPascal Brand 		*destLen = acc_dlen;
1358dea1f2b6SCedric Chaumont 
1359642a1607SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1360642a1607SCedric Chaumont 
1361642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1362642a1607SCedric Chaumont 
1363dea1f2b6SCedric Chaumont out:
1364dea1f2b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
1365dea1f2b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1366b36311adSJerome Forissier 		TEE_Panic(res);
1367dea1f2b6SCedric Chaumont 
1368dea1f2b6SCedric Chaumont 	return res;
1369b0104773SPascal Brand }
1370b0104773SPascal Brand 
1371185bf58cSJens Wiklander TEE_Result __GP11_TEE_CipherDoFinal(TEE_OperationHandle operation,
1372185bf58cSJens Wiklander 				    const void *srcData, uint32_t srcLen,
1373185bf58cSJens Wiklander 				    void *destData, uint32_t *destLen)
1374185bf58cSJens Wiklander {
1375185bf58cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1376185bf58cSJens Wiklander 	size_t dl = 0;
1377185bf58cSJens Wiklander 
1378185bf58cSJens Wiklander 	if (destLen) {
1379185bf58cSJens Wiklander 		__utee_check_inout_annotation(destLen, sizeof(*destLen));
1380185bf58cSJens Wiklander 		dl = *destLen;
1381185bf58cSJens Wiklander 	}
1382185bf58cSJens Wiklander 	res = TEE_CipherDoFinal(operation, srcData, srcLen, destData, &dl);
1383185bf58cSJens Wiklander 	if (destLen)
1384185bf58cSJens Wiklander 		*destLen = dl;
1385185bf58cSJens Wiklander 	return res;
1386185bf58cSJens Wiklander }
1387185bf58cSJens Wiklander 
1388b0104773SPascal Brand /* Cryptographic Operations API - MAC Functions */
1389b0104773SPascal Brand 
1390185bf58cSJens Wiklander void TEE_MACInit(TEE_OperationHandle operation, const void *IV, size_t IVLen)
1391b0104773SPascal Brand {
1392b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
1393b0104773SPascal Brand 		TEE_Panic(0);
1394642a1607SCedric Chaumont 
1395b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_MAC)
1396b0104773SPascal Brand 		TEE_Panic(0);
1397642a1607SCedric Chaumont 
1398642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||
1399642a1607SCedric Chaumont 	    !(operation->key1))
1400642a1607SCedric Chaumont 		TEE_Panic(0);
1401642a1607SCedric Chaumont 
1402642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
1403642a1607SCedric Chaumont 		TEE_ResetOperation(operation);
1404642a1607SCedric Chaumont 
1405642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1406642a1607SCedric Chaumont 
14076d15db08SJerome Forissier 	init_hash_operation(operation, IV, IVLen);
1408b0104773SPascal Brand }
1409b0104773SPascal Brand 
1410185bf58cSJens Wiklander void __GP11_TEE_MACInit(TEE_OperationHandle operation, const void *IV,
1411185bf58cSJens Wiklander 			uint32_t IVLen)
1412185bf58cSJens Wiklander {
1413185bf58cSJens Wiklander 	return TEE_MACInit(operation, IV, IVLen);
1414185bf58cSJens Wiklander }
1415185bf58cSJens Wiklander 
14168f07fe6fSJerome Forissier void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk,
1417185bf58cSJens Wiklander 		   size_t chunkSize)
1418b0104773SPascal Brand {
1419b0104773SPascal Brand 	TEE_Result res;
1420b0104773SPascal Brand 
142128e0efc6SCedric Chaumont 	if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0))
1422b0104773SPascal Brand 		TEE_Panic(0);
1423642a1607SCedric Chaumont 
142428e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC)
1425b0104773SPascal Brand 		TEE_Panic(0);
1426642a1607SCedric Chaumont 
142728e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1428b0104773SPascal Brand 		TEE_Panic(0);
1429b0104773SPascal Brand 
1430642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE)
1431642a1607SCedric Chaumont 		TEE_Panic(0);
1432642a1607SCedric Chaumont 
14332c028fdeSJerome Forissier 	res = _utee_hash_update(operation->state, chunk, chunkSize);
1434b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1435b0104773SPascal Brand 		TEE_Panic(res);
1436b0104773SPascal Brand }
1437b0104773SPascal Brand 
1438185bf58cSJens Wiklander void __GP11_TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk,
1439185bf58cSJens Wiklander 			  uint32_t chunkSize)
1440185bf58cSJens Wiklander {
1441185bf58cSJens Wiklander 	return TEE_MACUpdate(operation, chunk, chunkSize);
1442185bf58cSJens Wiklander }
1443185bf58cSJens Wiklander 
144428e0efc6SCedric Chaumont TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation,
1445185bf58cSJens Wiklander 			       const void *message, size_t messageLen,
1446185bf58cSJens Wiklander 			       void *mac, size_t *macLen)
1447b0104773SPascal Brand {
1448b0104773SPascal Brand 	TEE_Result res;
1449e86f1266SJens Wiklander 	uint64_t ml;
1450b0104773SPascal Brand 
14516915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!message && messageLen)) {
145228e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
145328e0efc6SCedric Chaumont 		goto out;
145428e0efc6SCedric Chaumont 	}
14556915bbbbSJens Wiklander 	__utee_check_inout_annotation(macLen, sizeof(*macLen));
1456b0104773SPascal Brand 
145728e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC) {
145828e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
145928e0efc6SCedric Chaumont 		goto out;
146028e0efc6SCedric Chaumont 	}
146128e0efc6SCedric Chaumont 
146228e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
146328e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
146428e0efc6SCedric Chaumont 		goto out;
146528e0efc6SCedric Chaumont 	}
146628e0efc6SCedric Chaumont 
1467642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1468642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1469642a1607SCedric Chaumont 		goto out;
1470642a1607SCedric Chaumont 	}
1471642a1607SCedric Chaumont 
1472e86f1266SJens Wiklander 	ml = *macLen;
14732c028fdeSJerome Forissier 	res = _utee_hash_final(operation->state, message, messageLen, mac, &ml);
1474e86f1266SJens Wiklander 	*macLen = ml;
147528e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS)
147628e0efc6SCedric Chaumont 		goto out;
147728e0efc6SCedric Chaumont 
147828e0efc6SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
147928e0efc6SCedric Chaumont 
1480642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1481642a1607SCedric Chaumont 
148228e0efc6SCedric Chaumont out:
148328e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS &&
148428e0efc6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
148528e0efc6SCedric Chaumont 		TEE_Panic(res);
148628e0efc6SCedric Chaumont 
1487b0104773SPascal Brand 	return res;
1488b0104773SPascal Brand }
1489b0104773SPascal Brand 
1490185bf58cSJens Wiklander TEE_Result __GP11_TEE_MACComputeFinal(TEE_OperationHandle operation,
14918f07fe6fSJerome Forissier 				      const void *message, uint32_t messageLen,
1492185bf58cSJens Wiklander 				      void *mac, uint32_t *macLen)
1493185bf58cSJens Wiklander {
1494185bf58cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1495185bf58cSJens Wiklander 	size_t ml = 0;
1496185bf58cSJens Wiklander 
1497185bf58cSJens Wiklander 	__utee_check_inout_annotation(macLen, sizeof(*macLen));
1498185bf58cSJens Wiklander 	ml = *macLen;
1499185bf58cSJens Wiklander 	res = TEE_MACComputeFinal(operation, message, messageLen, mac, &ml);
1500185bf58cSJens Wiklander 	*macLen = ml;
1501185bf58cSJens Wiklander 	return res;
1502185bf58cSJens Wiklander }
1503185bf58cSJens Wiklander 
1504185bf58cSJens Wiklander TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation,
1505185bf58cSJens Wiklander 			       const void *message, size_t messageLen,
1506185bf58cSJens Wiklander 			       const void *mac, size_t macLen)
1507b0104773SPascal Brand {
1508b0104773SPascal Brand 	TEE_Result res;
1509ee4ba3d1SVictor Chong 	uint8_t computed_mac[TEE_MAX_HASH_SIZE] = { 0 };
1510185bf58cSJens Wiklander 	size_t computed_mac_size = TEE_MAX_HASH_SIZE;
1511b0104773SPascal Brand 
151228e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC) {
151328e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
151428e0efc6SCedric Chaumont 		goto out;
151528e0efc6SCedric Chaumont 	}
151628e0efc6SCedric Chaumont 
151728e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
151828e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
151928e0efc6SCedric Chaumont 		goto out;
152028e0efc6SCedric Chaumont 	}
152128e0efc6SCedric Chaumont 
1522642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1523642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1524642a1607SCedric Chaumont 		goto out;
1525642a1607SCedric Chaumont 	}
1526642a1607SCedric Chaumont 
1527b0104773SPascal Brand 	res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac,
1528b0104773SPascal Brand 				  &computed_mac_size);
1529b0104773SPascal Brand 	if (res != TEE_SUCCESS)
153028e0efc6SCedric Chaumont 		goto out;
153128e0efc6SCedric Chaumont 
153228e0efc6SCedric Chaumont 	if (computed_mac_size != macLen) {
153328e0efc6SCedric Chaumont 		res = TEE_ERROR_MAC_INVALID;
153428e0efc6SCedric Chaumont 		goto out;
153528e0efc6SCedric Chaumont 	}
153628e0efc6SCedric Chaumont 
153748e10604SJerome Forissier 	if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) {
153828e0efc6SCedric Chaumont 		res = TEE_ERROR_MAC_INVALID;
153928e0efc6SCedric Chaumont 		goto out;
154028e0efc6SCedric Chaumont 	}
154128e0efc6SCedric Chaumont 
1542642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1543642a1607SCedric Chaumont 
154428e0efc6SCedric Chaumont out:
154528e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS &&
154628e0efc6SCedric Chaumont 	    res != TEE_ERROR_MAC_INVALID)
154728e0efc6SCedric Chaumont 		TEE_Panic(res);
154828e0efc6SCedric Chaumont 
1549b0104773SPascal Brand 	return res;
1550b0104773SPascal Brand }
1551b0104773SPascal Brand 
1552185bf58cSJens Wiklander TEE_Result __GP11_TEE_MACCompareFinal(TEE_OperationHandle operation,
1553185bf58cSJens Wiklander 				      const void *message, uint32_t messageLen,
1554185bf58cSJens Wiklander 				      const void *mac, uint32_t macLen)
1555185bf58cSJens Wiklander {
1556185bf58cSJens Wiklander 	return TEE_MACCompareFinal(operation, message, messageLen, mac, macLen);
1557185bf58cSJens Wiklander }
1558185bf58cSJens Wiklander 
1559b0104773SPascal Brand /* Cryptographic Operations API - Authenticated Encryption Functions */
1560b0104773SPascal Brand 
15618f07fe6fSJerome Forissier TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce,
1562d9096215SJens Wiklander 		      size_t nonceLen, uint32_t tagLen, size_t AADLen,
1563d9096215SJens Wiklander 		      size_t payloadLen)
1564b0104773SPascal Brand {
1565b0104773SPascal Brand 	TEE_Result res;
1566b0104773SPascal Brand 
1567b5816c88SCedric Chaumont 	if (operation == TEE_HANDLE_NULL || nonce == NULL) {
1568b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1569b5816c88SCedric Chaumont 		goto out;
1570b5816c88SCedric Chaumont 	}
1571b5816c88SCedric Chaumont 
1572b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1573b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1574b5816c88SCedric Chaumont 		goto out;
1575b5816c88SCedric Chaumont 	}
1576b0104773SPascal Brand 
1577642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
1578642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1579642a1607SCedric Chaumont 		goto out;
1580642a1607SCedric Chaumont 	}
1581642a1607SCedric Chaumont 
1582b0104773SPascal Brand 	/*
1583b0104773SPascal Brand 	 * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core
1584b0104773SPascal Brand 	 * in the implementation. But AES-GCM spec doesn't specify the tag len
1585b0104773SPascal Brand 	 * according to the same principle so we have to check here instead to
1586b0104773SPascal Brand 	 * be GP compliant.
1587b0104773SPascal Brand 	 */
1588b5816c88SCedric Chaumont 	if (operation->info.algorithm == TEE_ALG_AES_GCM) {
1589b0104773SPascal Brand 		/*
1590b0104773SPascal Brand 		 * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96
1591b0104773SPascal Brand 		 */
1592b5816c88SCedric Chaumont 		if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) {
1593b5816c88SCedric Chaumont 			res = TEE_ERROR_NOT_SUPPORTED;
1594b5816c88SCedric Chaumont 			goto out;
1595b5816c88SCedric Chaumont 		}
1596b0104773SPascal Brand 	}
1597b0104773SPascal Brand 
15982c028fdeSJerome Forissier 	res = _utee_authenc_init(operation->state, nonce, nonceLen, tagLen / 8,
15992c028fdeSJerome Forissier 				 AADLen, payloadLen);
1600b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS)
1601b5816c88SCedric Chaumont 		goto out;
1602b5816c88SCedric Chaumont 
16037acaf5adSAlbert Schwarzkopf 	operation->info.digestLength = tagLen / 8;
1604f2674567SSumit Garg 	operation->buffer_offs = 0;
1605b5816c88SCedric Chaumont 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
1606b5816c88SCedric Chaumont 
1607b5816c88SCedric Chaumont out:
1608b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1609b5816c88SCedric Chaumont 	    res != TEE_ERROR_NOT_SUPPORTED)
1610b0104773SPascal Brand 			TEE_Panic(res);
1611b5816c88SCedric Chaumont 
1612b0104773SPascal Brand 	return res;
1613b0104773SPascal Brand }
1614b0104773SPascal Brand 
1615d9096215SJens Wiklander TEE_Result __GP11_TEE_AEInit(TEE_OperationHandle operation, const void *nonce,
1616d9096215SJens Wiklander 			     uint32_t nonceLen, uint32_t tagLen,
1617d9096215SJens Wiklander 			     uint32_t AADLen, uint32_t payloadLen)
1618d9096215SJens Wiklander {
1619d9096215SJens Wiklander 	return TEE_AEInit(operation, nonce, nonceLen, tagLen, AADLen,
1620d9096215SJens Wiklander 			  payloadLen);
1621d9096215SJens Wiklander }
1622d9096215SJens Wiklander 
16238f07fe6fSJerome Forissier void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata,
1624d9096215SJens Wiklander 		     size_t AADdataLen)
1625d9096215SJens Wiklander {
1626d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1627d9096215SJens Wiklander 
1628d9096215SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!AADdata && AADdataLen))
1629d9096215SJens Wiklander 		TEE_Panic(0);
1630d9096215SJens Wiklander 
1631d9096215SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_AE)
1632d9096215SJens Wiklander 		TEE_Panic(0);
1633d9096215SJens Wiklander 
1634d9096215SJens Wiklander 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
1635d9096215SJens Wiklander 		TEE_Panic(0);
1636d9096215SJens Wiklander 
1637d9096215SJens Wiklander 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1638d9096215SJens Wiklander 		TEE_Panic(0);
1639d9096215SJens Wiklander 
1640d9096215SJens Wiklander 	res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen);
1641d9096215SJens Wiklander 	if (res != TEE_SUCCESS)
1642d9096215SJens Wiklander 		TEE_Panic(res);
1643d9096215SJens Wiklander }
1644d9096215SJens Wiklander 
1645d9096215SJens Wiklander void __GP11_TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata,
164679a3c601SCedric Chaumont 			    uint32_t AADdataLen)
1647b0104773SPascal Brand {
1648d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1649b0104773SPascal Brand 
1650b5816c88SCedric Chaumont 	if (operation == TEE_HANDLE_NULL ||
1651b5816c88SCedric Chaumont 	    (AADdata == NULL && AADdataLen != 0))
1652b0104773SPascal Brand 		TEE_Panic(0);
1653642a1607SCedric Chaumont 
1654b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE)
1655b0104773SPascal Brand 		TEE_Panic(0);
1656642a1607SCedric Chaumont 
1657b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1658b0104773SPascal Brand 		TEE_Panic(0);
1659b0104773SPascal Brand 
16602c028fdeSJerome Forissier 	res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen);
1661642a1607SCedric Chaumont 
1662642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1663642a1607SCedric Chaumont 
1664b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1665b0104773SPascal Brand 		TEE_Panic(res);
1666b0104773SPascal Brand }
1667b0104773SPascal Brand 
1668d9096215SJens Wiklander static TEE_Result ae_update_helper(TEE_OperationHandle operation,
1669d9096215SJens Wiklander 				   const void *src, size_t slen, void *dst,
1670d9096215SJens Wiklander 				   size_t *dlen)
1671b0104773SPascal Brand {
16726915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
16736915bbbbSJens Wiklander 	size_t req_dlen = 0;
16746915bbbbSJens Wiklander 	uint64_t dl = 0;
1675b0104773SPascal Brand 
1676d9096215SJens Wiklander 	if (!src && !slen) {
1677d9096215SJens Wiklander 		*dlen = 0;
1678d9096215SJens Wiklander 		return TEE_SUCCESS;
1679d9096215SJens Wiklander 	}
1680d9096215SJens Wiklander 
1681d9096215SJens Wiklander 	/*
1682d9096215SJens Wiklander 	 * Check that required destLen is big enough before starting to feed
1683d9096215SJens Wiklander 	 * data to the algorithm. Errors during feeding of data are fatal as we
1684d9096215SJens Wiklander 	 * can't restore sync with this API.
1685d9096215SJens Wiklander 	 */
1686d9096215SJens Wiklander 	if (operation->block_size > 1) {
1687d9096215SJens Wiklander 		req_dlen = ROUNDDOWN(operation->buffer_offs + slen,
1688d9096215SJens Wiklander 				     operation->block_size);
1689d9096215SJens Wiklander 	} else {
1690d9096215SJens Wiklander 		req_dlen = slen;
1691d9096215SJens Wiklander 	}
1692d9096215SJens Wiklander 
1693d9096215SJens Wiklander 	dl = *dlen;
1694d9096215SJens Wiklander 	if (dl < req_dlen) {
1695d9096215SJens Wiklander 		*dlen = req_dlen;
1696d9096215SJens Wiklander 		return TEE_ERROR_SHORT_BUFFER;
1697d9096215SJens Wiklander 	}
1698d9096215SJens Wiklander 
1699d9096215SJens Wiklander 	if (operation->block_size > 1) {
1700d9096215SJens Wiklander 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1701d9096215SJens Wiklander 					src, slen, dst, &dl);
1702d9096215SJens Wiklander 	} else {
1703d9096215SJens Wiklander 		if (slen > 0) {
1704d9096215SJens Wiklander 			res = _utee_authenc_update_payload(operation->state,
1705d9096215SJens Wiklander 							   src, slen, dst, &dl);
1706d9096215SJens Wiklander 		} else {
1707d9096215SJens Wiklander 			dl = 0;
1708d9096215SJens Wiklander 			res = TEE_SUCCESS;
1709d9096215SJens Wiklander 		}
1710d9096215SJens Wiklander 	}
1711d9096215SJens Wiklander 
1712d9096215SJens Wiklander 	if (!res)
1713d9096215SJens Wiklander 		*dlen = dl;
1714d9096215SJens Wiklander 
1715d9096215SJens Wiklander 	return res;
1716d9096215SJens Wiklander }
1717d9096215SJens Wiklander 
1718d9096215SJens Wiklander TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData,
1719d9096215SJens Wiklander 			size_t srcLen, void *destData, size_t *destLen)
1720d9096215SJens Wiklander {
1721d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1722d9096215SJens Wiklander 
17236915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1724b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1725b5816c88SCedric Chaumont 		goto out;
1726b5816c88SCedric Chaumont 	}
1727d9096215SJens Wiklander 	__utee_check_outbuf_annotation(destData, destLen);
1728b5816c88SCedric Chaumont 
1729b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1730b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1731b5816c88SCedric Chaumont 		goto out;
1732b5816c88SCedric Chaumont 	}
1733b5816c88SCedric Chaumont 
1734b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1735b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1736b5816c88SCedric Chaumont 		goto out;
1737b5816c88SCedric Chaumont 	}
1738b0104773SPascal Brand 
1739d9096215SJens Wiklander 	res = ae_update_helper(operation, srcData, srcLen, destData, destLen);
1740d9096215SJens Wiklander 	if (res != TEE_ERROR_SHORT_BUFFER && srcLen)
1741d9096215SJens Wiklander 		operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1742d9096215SJens Wiklander 
1743d9096215SJens Wiklander out:
1744d9096215SJens Wiklander 	if (res != TEE_SUCCESS &&
1745d9096215SJens Wiklander 	    res != TEE_ERROR_SHORT_BUFFER)
1746d9096215SJens Wiklander 		TEE_Panic(res);
1747d9096215SJens Wiklander 
1748d9096215SJens Wiklander 	return res;
1749d9096215SJens Wiklander }
1750d9096215SJens Wiklander 
1751d9096215SJens Wiklander TEE_Result __GP11_TEE_AEUpdate(TEE_OperationHandle operation,
1752d9096215SJens Wiklander 			       const void *srcData, uint32_t srcLen,
1753d9096215SJens Wiklander 			       void *destData, uint32_t *destLen)
1754d9096215SJens Wiklander {
1755d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1756d9096215SJens Wiklander 	size_t dl = 0;
1757d9096215SJens Wiklander 
1758d9096215SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1759d9096215SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1760d9096215SJens Wiklander 		goto out;
1761d9096215SJens Wiklander 	}
1762d9096215SJens Wiklander 	__utee_check_gp11_outbuf_annotation(destData, destLen);
1763d9096215SJens Wiklander 
1764d9096215SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1765d9096215SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1766827308b8SJerome Forissier 		goto out;
1767827308b8SJerome Forissier 	}
1768827308b8SJerome Forissier 
1769d9096215SJens Wiklander 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1770d9096215SJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
1771d9096215SJens Wiklander 		goto out;
1772afc0c182SBogdan Liulko 	}
1773afc0c182SBogdan Liulko 
17746915bbbbSJens Wiklander 	dl = *destLen;
1775d9096215SJens Wiklander 	res = ae_update_helper(operation, srcData, srcLen, destData, &dl);
1776d9096215SJens Wiklander 	*destLen = dl;
1777b0104773SPascal Brand 
1778afc0c182SBogdan Liulko 	if (res != TEE_SUCCESS)
1779afc0c182SBogdan Liulko 		goto out;
1780afc0c182SBogdan Liulko 
1781642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1782642a1607SCedric Chaumont 
1783b5816c88SCedric Chaumont out:
1784b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1785b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1786b5816c88SCedric Chaumont 			TEE_Panic(res);
1787b5816c88SCedric Chaumont 
1788b5816c88SCedric Chaumont 	return res;
1789b0104773SPascal Brand }
1790b0104773SPascal Brand 
1791b5816c88SCedric Chaumont TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation,
1792d9096215SJens Wiklander 			      const void *srcData, size_t srcLen,
1793d9096215SJens Wiklander 			      void *destData, size_t *destLen, void *tag,
1794d9096215SJens Wiklander 			      size_t *tagLen)
1795b0104773SPascal Brand {
1796d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1797b0104773SPascal Brand 	uint8_t *dst = destData;
1798b0104773SPascal Brand 	size_t acc_dlen = 0;
1799d9096215SJens Wiklander 	uint64_t tmp_dlen = 0;
1800d9096215SJens Wiklander 	size_t req_dlen = 0;
1801d9096215SJens Wiklander 	uint64_t tl = 0;
1802b0104773SPascal Brand 
18036915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1804b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1805b5816c88SCedric Chaumont 		goto out;
1806b5816c88SCedric Chaumont 	}
18076915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
18086915bbbbSJens Wiklander 	__utee_check_inout_annotation(tagLen, sizeof(*tagLen));
1809b5816c88SCedric Chaumont 
1810b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1811b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1812b5816c88SCedric Chaumont 		goto out;
1813b5816c88SCedric Chaumont 	}
1814b5816c88SCedric Chaumont 
1815b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1816b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1817b5816c88SCedric Chaumont 		goto out;
1818b5816c88SCedric Chaumont 	}
1819b0104773SPascal Brand 
1820b0104773SPascal Brand 	/*
1821b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1822b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1823b0104773SPascal Brand 	 * can't restore sync with this API.
18242733280aSEtienne Carriere 	 *
18252733280aSEtienne Carriere 	 * Need to check this before update_payload since sync would be lost if
18262733280aSEtienne Carriere 	 * we return short buffer after that.
1827b0104773SPascal Brand 	 */
18282733280aSEtienne Carriere 	res = TEE_ERROR_GENERIC;
18292733280aSEtienne Carriere 
1830b5816c88SCedric Chaumont 	req_dlen = operation->buffer_offs + srcLen;
1831b0104773SPascal Brand 	if (*destLen < req_dlen) {
1832b0104773SPascal Brand 		*destLen = req_dlen;
1833b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1834b0104773SPascal Brand 	}
1835b0104773SPascal Brand 
18367acaf5adSAlbert Schwarzkopf 	if (*tagLen < operation->info.digestLength) {
18377acaf5adSAlbert Schwarzkopf 		*tagLen = operation->info.digestLength;
1838b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1839b0104773SPascal Brand 	}
1840b0104773SPascal Brand 
18412733280aSEtienne Carriere 	if (res == TEE_ERROR_SHORT_BUFFER)
18422733280aSEtienne Carriere 		goto out;
18432733280aSEtienne Carriere 
1844afc0c182SBogdan Liulko 	tl = *tagLen;
1845b0104773SPascal Brand 	tmp_dlen = *destLen - acc_dlen;
1846afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
18472c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1848afc0c182SBogdan Liulko 					srcData, srcLen, dst, &tmp_dlen);
1849b5816c88SCedric Chaumont 		if (res != TEE_SUCCESS)
1850b5816c88SCedric Chaumont 			goto out;
1851b5816c88SCedric Chaumont 
1852b0104773SPascal Brand 		dst += tmp_dlen;
1853b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1854b0104773SPascal Brand 
1855b0104773SPascal Brand 		tmp_dlen = *destLen - acc_dlen;
18562c028fdeSJerome Forissier 		res = _utee_authenc_enc_final(operation->state,
1857afc0c182SBogdan Liulko 					      operation->buffer,
1858afc0c182SBogdan Liulko 					      operation->buffer_offs, dst,
1859afc0c182SBogdan Liulko 					      &tmp_dlen, tag, &tl);
1860afc0c182SBogdan Liulko 	} else {
18612c028fdeSJerome Forissier 		res = _utee_authenc_enc_final(operation->state, srcData,
1862afc0c182SBogdan Liulko 					      srcLen, dst, &tmp_dlen,
1863e86f1266SJens Wiklander 					      tag, &tl);
1864afc0c182SBogdan Liulko 	}
1865e86f1266SJens Wiklander 	*tagLen = tl;
1866b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1867b5816c88SCedric Chaumont 		goto out;
1868b0104773SPascal Brand 
1869b5816c88SCedric Chaumont 	acc_dlen += tmp_dlen;
1870b0104773SPascal Brand 	*destLen = acc_dlen;
1871642a1607SCedric Chaumont 
1872b5816c88SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1873b5816c88SCedric Chaumont 
1874642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1875642a1607SCedric Chaumont 
1876b5816c88SCedric Chaumont out:
1877b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1878b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1879b5816c88SCedric Chaumont 			TEE_Panic(res);
1880b0104773SPascal Brand 
1881b0104773SPascal Brand 	return res;
1882b0104773SPascal Brand }
1883b0104773SPascal Brand 
1884d9096215SJens Wiklander TEE_Result __GP11_TEE_AEEncryptFinal(TEE_OperationHandle operation,
18858f07fe6fSJerome Forissier 				     const void *srcData, uint32_t srcLen,
1886d9096215SJens Wiklander 				     void *destData, uint32_t *destLen,
1887d9096215SJens Wiklander 				     void *tag, uint32_t *tagLen)
1888b0104773SPascal Brand {
1889d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1890d9096215SJens Wiklander 	size_t dl = 0;
1891d9096215SJens Wiklander 	size_t tl = 0;
1892d9096215SJens Wiklander 
1893d9096215SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1894d9096215SJens Wiklander 	__utee_check_inout_annotation(tagLen, sizeof(*tagLen));
1895d9096215SJens Wiklander 	dl = *destLen;
1896d9096215SJens Wiklander 	tl = *tagLen;
1897d9096215SJens Wiklander 	res = TEE_AEEncryptFinal(operation, srcData, srcLen, destData, &dl,
1898d9096215SJens Wiklander 				 tag, &tl);
1899d9096215SJens Wiklander 	*destLen = dl;
1900d9096215SJens Wiklander 	*tagLen = tl;
1901d9096215SJens Wiklander 	return res;
1902d9096215SJens Wiklander }
1903d9096215SJens Wiklander 
1904d9096215SJens Wiklander TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation,
1905d9096215SJens Wiklander 			      const void *srcData, size_t srcLen,
1906d9096215SJens Wiklander 			      void *destData, size_t *destLen, void *tag,
1907d9096215SJens Wiklander 			      size_t tagLen)
1908d9096215SJens Wiklander {
1909d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1910b0104773SPascal Brand 	uint8_t *dst = destData;
1911b0104773SPascal Brand 	size_t acc_dlen = 0;
1912d9096215SJens Wiklander 	uint64_t tmp_dlen = 0;
1913d9096215SJens Wiklander 	size_t req_dlen = 0;
1914b0104773SPascal Brand 
19156915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1916b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1917b5816c88SCedric Chaumont 		goto out;
1918b5816c88SCedric Chaumont 	}
19196915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1920b5816c88SCedric Chaumont 
1921b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1922b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1923b5816c88SCedric Chaumont 		goto out;
1924b5816c88SCedric Chaumont 	}
1925b5816c88SCedric Chaumont 
1926b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1927b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1928b5816c88SCedric Chaumont 		goto out;
1929b5816c88SCedric Chaumont 	}
1930b0104773SPascal Brand 
1931b0104773SPascal Brand 	/*
1932b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1933b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1934b0104773SPascal Brand 	 * can't restore sync with this API.
1935b0104773SPascal Brand 	 */
1936b5816c88SCedric Chaumont 	req_dlen = operation->buffer_offs + srcLen;
1937b0104773SPascal Brand 	if (*destLen < req_dlen) {
1938b0104773SPascal Brand 		*destLen = req_dlen;
1939b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1940b5816c88SCedric Chaumont 		goto out;
1941b0104773SPascal Brand 	}
1942b0104773SPascal Brand 
1943b0104773SPascal Brand 	tmp_dlen = *destLen - acc_dlen;
1944afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
19452c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1946afc0c182SBogdan Liulko 					srcData, srcLen, dst, &tmp_dlen);
1947b5816c88SCedric Chaumont 		if (res != TEE_SUCCESS)
1948b5816c88SCedric Chaumont 			goto out;
1949b5816c88SCedric Chaumont 
1950b0104773SPascal Brand 		dst += tmp_dlen;
1951b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1952b0104773SPascal Brand 
1953b0104773SPascal Brand 		tmp_dlen = *destLen - acc_dlen;
19542c028fdeSJerome Forissier 		res = _utee_authenc_dec_final(operation->state,
1955afc0c182SBogdan Liulko 					      operation->buffer,
1956afc0c182SBogdan Liulko 					      operation->buffer_offs, dst,
1957afc0c182SBogdan Liulko 					      &tmp_dlen, tag, tagLen);
1958afc0c182SBogdan Liulko 	} else {
19592c028fdeSJerome Forissier 		res = _utee_authenc_dec_final(operation->state, srcData,
1960afc0c182SBogdan Liulko 					      srcLen, dst, &tmp_dlen,
1961b5816c88SCedric Chaumont 					      tag, tagLen);
1962afc0c182SBogdan Liulko 	}
1963b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS)
1964b5816c88SCedric Chaumont 		goto out;
1965b5816c88SCedric Chaumont 
1966b0104773SPascal Brand 	/* Supplied tagLen should match what we initiated with */
19677acaf5adSAlbert Schwarzkopf 	if (tagLen != operation->info.digestLength)
1968b0104773SPascal Brand 		res = TEE_ERROR_MAC_INVALID;
1969b0104773SPascal Brand 
1970b0104773SPascal Brand 	acc_dlen += tmp_dlen;
1971b0104773SPascal Brand 	*destLen = acc_dlen;
1972642a1607SCedric Chaumont 
1973b5816c88SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1974b5816c88SCedric Chaumont 
1975642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1976642a1607SCedric Chaumont 
1977b5816c88SCedric Chaumont out:
1978b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1979b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER &&
1980b5816c88SCedric Chaumont 	    res != TEE_ERROR_MAC_INVALID)
1981b5816c88SCedric Chaumont 			TEE_Panic(res);
1982b0104773SPascal Brand 
1983b0104773SPascal Brand 	return res;
1984b0104773SPascal Brand }
1985b0104773SPascal Brand 
1986d9096215SJens Wiklander TEE_Result __GP11_TEE_AEDecryptFinal(TEE_OperationHandle operation,
1987d9096215SJens Wiklander 				     const void *srcData, uint32_t srcLen,
1988d9096215SJens Wiklander 				     void *destData, uint32_t *destLen,
1989d9096215SJens Wiklander 				     void *tag, uint32_t tagLen)
1990d9096215SJens Wiklander {
1991d9096215SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1992d9096215SJens Wiklander 	size_t dl = 0;
1993d9096215SJens Wiklander 
1994d9096215SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1995d9096215SJens Wiklander 	dl = *destLen;
1996d9096215SJens Wiklander 	res = TEE_AEDecryptFinal(operation, srcData, srcLen, destData, &dl,
1997d9096215SJens Wiklander 				 tag, tagLen);
1998d9096215SJens Wiklander 	*destLen = dl;
1999d9096215SJens Wiklander 	return res;
2000d9096215SJens Wiklander }
2001d9096215SJens Wiklander 
2002b0104773SPascal Brand /* Cryptographic Operations API - Asymmetric Functions */
2003b0104773SPascal Brand 
200412e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation,
20058f07fe6fSJerome Forissier 				 const TEE_Attribute *params,
20068f07fe6fSJerome Forissier 				 uint32_t paramCount, const void *srcData,
2007999b69d0SJens Wiklander 				 size_t srcLen, void *destData,
2008999b69d0SJens Wiklander 				 size_t *destLen)
2009b0104773SPascal Brand {
20106915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
2011e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
20126915bbbbSJens Wiklander 	uint64_t dl = 0;
2013b0104773SPascal Brand 
20146915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
2015b0104773SPascal Brand 		TEE_Panic(0);
20166915bbbbSJens Wiklander 
20176915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
20186915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
20196915bbbbSJens Wiklander 
202012e66b6fSCedric Chaumont 	if (!operation->key1)
2021b0104773SPascal Brand 		TEE_Panic(0);
202212e66b6fSCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
202312e66b6fSCedric Chaumont 		TEE_Panic(0);
202412e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_ENCRYPT)
2025b0104773SPascal Brand 		TEE_Panic(0);
2026b0104773SPascal Brand 
2027e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
2028e86f1266SJens Wiklander 	dl = *destLen;
20292c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
2030e86f1266SJens Wiklander 				  srcLen, destData, &dl);
2031e86f1266SJens Wiklander 	*destLen = dl;
203212e66b6fSCedric Chaumont 
20338844ebfcSPascal Brand 	if (res != TEE_SUCCESS &&
20348844ebfcSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER &&
2035*1bc176d8SJens Wiklander 	    res != TEE_ERROR_BAD_PARAMETERS &&
2036*1bc176d8SJens Wiklander 	    res != TEE_ERROR_CIPHERTEXT_INVALID &&
2037*1bc176d8SJens Wiklander 	    res != TEE_ERROR_NOT_SUPPORTED)
2038b0104773SPascal Brand 		TEE_Panic(res);
203912e66b6fSCedric Chaumont 
2040b0104773SPascal Brand 	return res;
2041b0104773SPascal Brand }
2042b0104773SPascal Brand 
20434f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricEncrypt(TEE_OperationHandle operation,
20444f4374c8SJens Wiklander 					const __GP11_TEE_Attribute *params,
20454f4374c8SJens Wiklander 					uint32_t paramCount,
20464f4374c8SJens Wiklander 					const void *srcData, uint32_t srcLen,
20474f4374c8SJens Wiklander 					void *destData, uint32_t *destLen)
20484f4374c8SJens Wiklander {
20494f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
20504f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
20514f4374c8SJens Wiklander 	uint64_t dl = 0;
20524f4374c8SJens Wiklander 
20534f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
20544f4374c8SJens Wiklander 		TEE_Panic(0);
20554f4374c8SJens Wiklander 
20564f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
20574f4374c8SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
20584f4374c8SJens Wiklander 
20594f4374c8SJens Wiklander 	if (!operation->key1)
20604f4374c8SJens Wiklander 		TEE_Panic(0);
20614f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
20624f4374c8SJens Wiklander 		TEE_Panic(0);
20634f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_ENCRYPT)
20644f4374c8SJens Wiklander 		TEE_Panic(0);
20654f4374c8SJens Wiklander 
20664f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
20674f4374c8SJens Wiklander 	dl = *destLen;
20684f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
20694f4374c8SJens Wiklander 				  srcLen, destData, &dl);
20704f4374c8SJens Wiklander 	*destLen = dl;
20714f4374c8SJens Wiklander 
20724f4374c8SJens Wiklander 	if (res != TEE_SUCCESS &&
20734f4374c8SJens Wiklander 	    res != TEE_ERROR_SHORT_BUFFER &&
20744f4374c8SJens Wiklander 	    res != TEE_ERROR_BAD_PARAMETERS)
20754f4374c8SJens Wiklander 		TEE_Panic(res);
20764f4374c8SJens Wiklander 
20774f4374c8SJens Wiklander 	return res;
20784f4374c8SJens Wiklander }
20794f4374c8SJens Wiklander 
208012e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation,
20818f07fe6fSJerome Forissier 				 const TEE_Attribute *params,
20828f07fe6fSJerome Forissier 				 uint32_t paramCount, const void *srcData,
2083999b69d0SJens Wiklander 				 size_t srcLen, void *destData,
2084999b69d0SJens Wiklander 				 size_t *destLen)
2085b0104773SPascal Brand {
20866915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
2087e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
20886915bbbbSJens Wiklander 	uint64_t dl = 0;
2089b0104773SPascal Brand 
20906915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
2091b0104773SPascal Brand 		TEE_Panic(0);
20926915bbbbSJens Wiklander 
20936915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
20946915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
20956915bbbbSJens Wiklander 
209612e66b6fSCedric Chaumont 	if (!operation->key1)
2097b0104773SPascal Brand 		TEE_Panic(0);
209812e66b6fSCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
209912e66b6fSCedric Chaumont 		TEE_Panic(0);
210012e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_DECRYPT)
2101b0104773SPascal Brand 		TEE_Panic(0);
2102b0104773SPascal Brand 
2103e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
2104e86f1266SJens Wiklander 	dl = *destLen;
21052c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
2106e86f1266SJens Wiklander 				  srcLen, destData, &dl);
2107e86f1266SJens Wiklander 	*destLen = dl;
210812e66b6fSCedric Chaumont 
21098844ebfcSPascal Brand 	if (res != TEE_SUCCESS &&
21108844ebfcSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER &&
2111*1bc176d8SJens Wiklander 	    res != TEE_ERROR_BAD_PARAMETERS &&
2112*1bc176d8SJens Wiklander 	    res != TEE_ERROR_CIPHERTEXT_INVALID &&
2113*1bc176d8SJens Wiklander 	    res != TEE_ERROR_NOT_SUPPORTED)
2114b0104773SPascal Brand 		TEE_Panic(res);
211512e66b6fSCedric Chaumont 
2116b0104773SPascal Brand 	return res;
2117b0104773SPascal Brand }
2118b0104773SPascal Brand 
21194f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricDecrypt(TEE_OperationHandle operation,
21204f4374c8SJens Wiklander 					const __GP11_TEE_Attribute *params,
21214f4374c8SJens Wiklander 					uint32_t paramCount,
21224f4374c8SJens Wiklander 					const void *srcData, uint32_t srcLen,
21234f4374c8SJens Wiklander 					void *destData, uint32_t *destLen)
21244f4374c8SJens Wiklander {
21254f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
21264f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
21274f4374c8SJens Wiklander 	uint64_t dl = 0;
21284f4374c8SJens Wiklander 
21294f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
21304f4374c8SJens Wiklander 		TEE_Panic(0);
21314f4374c8SJens Wiklander 
21324f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
21334f4374c8SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
21344f4374c8SJens Wiklander 
21354f4374c8SJens Wiklander 	if (!operation->key1)
21364f4374c8SJens Wiklander 		TEE_Panic(0);
21374f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
21384f4374c8SJens Wiklander 		TEE_Panic(0);
21394f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_DECRYPT)
21404f4374c8SJens Wiklander 		TEE_Panic(0);
21414f4374c8SJens Wiklander 
21424f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
21434f4374c8SJens Wiklander 	dl = *destLen;
21444f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
21454f4374c8SJens Wiklander 				  srcLen, destData, &dl);
21464f4374c8SJens Wiklander 	*destLen = dl;
21474f4374c8SJens Wiklander 
21484f4374c8SJens Wiklander 	if (res != TEE_SUCCESS &&
21494f4374c8SJens Wiklander 	    res != TEE_ERROR_SHORT_BUFFER &&
21504f4374c8SJens Wiklander 	    res != TEE_ERROR_BAD_PARAMETERS)
21514f4374c8SJens Wiklander 		TEE_Panic(res);
21524f4374c8SJens Wiklander 
21534f4374c8SJens Wiklander 	return res;
21544f4374c8SJens Wiklander }
21554f4374c8SJens Wiklander 
215612e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation,
21578f07fe6fSJerome Forissier 				    const TEE_Attribute *params,
21588f07fe6fSJerome Forissier 				    uint32_t paramCount, const void *digest,
21590b354ec8SJens Wiklander 				    size_t digestLen, void *signature,
21600b354ec8SJens Wiklander 				    size_t *signatureLen)
2161b0104773SPascal Brand {
21626915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
2163e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
21646915bbbbSJens Wiklander 	uint64_t sl = 0;
2165b0104773SPascal Brand 
21666915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen))
2167b0104773SPascal Brand 		TEE_Panic(0);
21686915bbbbSJens Wiklander 
21696915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
21706915bbbbSJens Wiklander 	__utee_check_inout_annotation(signatureLen, sizeof(*signatureLen));
21716915bbbbSJens Wiklander 
217212e66b6fSCedric Chaumont 	if (!operation->key1)
2173b0104773SPascal Brand 		TEE_Panic(0);
217412e66b6fSCedric Chaumont 	if (operation->info.operationClass !=
217512e66b6fSCedric Chaumont 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
217612e66b6fSCedric Chaumont 		TEE_Panic(0);
217712e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_SIGN)
2178b0104773SPascal Brand 		TEE_Panic(0);
2179b0104773SPascal Brand 
2180e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
2181e86f1266SJens Wiklander 	sl = *signatureLen;
21822c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, digest,
2183e86f1266SJens Wiklander 				  digestLen, signature, &sl);
2184e86f1266SJens Wiklander 	*signatureLen = sl;
218512e66b6fSCedric Chaumont 
2186b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)
2187b0104773SPascal Brand 		TEE_Panic(res);
218812e66b6fSCedric Chaumont 
2189b0104773SPascal Brand 	return res;
2190b0104773SPascal Brand }
2191b0104773SPascal Brand 
21924f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricSignDigest(TEE_OperationHandle operation,
21934f4374c8SJens Wiklander 					   const __GP11_TEE_Attribute *params,
21944f4374c8SJens Wiklander 					   uint32_t paramCount,
21954f4374c8SJens Wiklander 					   const void *digest,
21964f4374c8SJens Wiklander 					   uint32_t digestLen, void *signature,
21974f4374c8SJens Wiklander 					   uint32_t *signatureLen)
21984f4374c8SJens Wiklander {
21994f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
22004f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
22014f4374c8SJens Wiklander 	uint64_t sl = 0;
22024f4374c8SJens Wiklander 
22034f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen))
22044f4374c8SJens Wiklander 		TEE_Panic(0);
22054f4374c8SJens Wiklander 
22064f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
22074f4374c8SJens Wiklander 	__utee_check_inout_annotation(signatureLen, sizeof(*signatureLen));
22084f4374c8SJens Wiklander 
22094f4374c8SJens Wiklander 	if (!operation->key1)
22104f4374c8SJens Wiklander 		TEE_Panic(0);
22114f4374c8SJens Wiklander 	if (operation->info.operationClass !=
22124f4374c8SJens Wiklander 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
22134f4374c8SJens Wiklander 		TEE_Panic(0);
22144f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_SIGN)
22154f4374c8SJens Wiklander 		TEE_Panic(0);
22164f4374c8SJens Wiklander 
22174f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
22184f4374c8SJens Wiklander 	sl = *signatureLen;
22194f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, digest,
22204f4374c8SJens Wiklander 				  digestLen, signature, &sl);
22214f4374c8SJens Wiklander 	*signatureLen = sl;
22224f4374c8SJens Wiklander 
22234f4374c8SJens Wiklander 	if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)
22244f4374c8SJens Wiklander 		TEE_Panic(res);
22254f4374c8SJens Wiklander 
22264f4374c8SJens Wiklander 	return res;
22274f4374c8SJens Wiklander }
22284f4374c8SJens Wiklander 
222912e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation,
22308f07fe6fSJerome Forissier 				      const TEE_Attribute *params,
22318f07fe6fSJerome Forissier 				      uint32_t paramCount, const void *digest,
22320b354ec8SJens Wiklander 				      size_t digestLen,
22338f07fe6fSJerome Forissier 				      const void *signature,
22340b354ec8SJens Wiklander 				      size_t signatureLen)
2235b0104773SPascal Brand {
2236b0104773SPascal Brand 	TEE_Result res;
2237e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
2238b0104773SPascal Brand 
223912e66b6fSCedric Chaumont 	if (operation == TEE_HANDLE_NULL ||
224012e66b6fSCedric Chaumont 	    (digest == NULL && digestLen != 0) ||
2241b0104773SPascal Brand 	    (signature == NULL && signatureLen != 0))
2242b0104773SPascal Brand 		TEE_Panic(0);
22436915bbbbSJens Wiklander 
22446915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
22456915bbbbSJens Wiklander 
224612e66b6fSCedric Chaumont 	if (!operation->key1)
2247b0104773SPascal Brand 		TEE_Panic(0);
224812e66b6fSCedric Chaumont 	if (operation->info.operationClass !=
224912e66b6fSCedric Chaumont 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
225012e66b6fSCedric Chaumont 		TEE_Panic(0);
225112e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_VERIFY)
2252b0104773SPascal Brand 		TEE_Panic(0);
2253b0104773SPascal Brand 
2254e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
22552c028fdeSJerome Forissier 	res = _utee_asymm_verify(operation->state, ua, paramCount, digest,
225612e66b6fSCedric Chaumont 				 digestLen, signature, signatureLen);
225712e66b6fSCedric Chaumont 
2258b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID)
2259b0104773SPascal Brand 		TEE_Panic(res);
226012e66b6fSCedric Chaumont 
2261b0104773SPascal Brand 	return res;
2262b0104773SPascal Brand }
2263b0104773SPascal Brand 
22644f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation,
22654f4374c8SJens Wiklander 					     const __GP11_TEE_Attribute *params,
22664f4374c8SJens Wiklander 					     uint32_t paramCount,
22674f4374c8SJens Wiklander 					     const void *digest,
22684f4374c8SJens Wiklander 					     uint32_t digestLen,
22694f4374c8SJens Wiklander 					     const void *signature,
22704f4374c8SJens Wiklander 					     uint32_t signatureLen)
22714f4374c8SJens Wiklander {
22724f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
22734f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
22744f4374c8SJens Wiklander 
22754f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen) ||
22764f4374c8SJens Wiklander 	    (!signature && signatureLen))
22774f4374c8SJens Wiklander 		TEE_Panic(0);
22784f4374c8SJens Wiklander 
22794f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
22804f4374c8SJens Wiklander 
22814f4374c8SJens Wiklander 	if (!operation->key1)
22824f4374c8SJens Wiklander 		TEE_Panic(0);
22834f4374c8SJens Wiklander 	if (operation->info.operationClass !=
22844f4374c8SJens Wiklander 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
22854f4374c8SJens Wiklander 		TEE_Panic(0);
22864f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_VERIFY)
22874f4374c8SJens Wiklander 		TEE_Panic(0);
22884f4374c8SJens Wiklander 
22894f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
22904f4374c8SJens Wiklander 	res = _utee_asymm_verify(operation->state, ua, paramCount, digest,
22914f4374c8SJens Wiklander 				 digestLen, signature, signatureLen);
22924f4374c8SJens Wiklander 
22934f4374c8SJens Wiklander 	if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID)
22944f4374c8SJens Wiklander 		TEE_Panic(res);
22954f4374c8SJens Wiklander 
22964f4374c8SJens Wiklander 	return res;
22974f4374c8SJens Wiklander }
22984f4374c8SJens Wiklander 
2299b0104773SPascal Brand /* Cryptographic Operations API - Key Derivation Functions */
2300b0104773SPascal Brand 
2301b0104773SPascal Brand void TEE_DeriveKey(TEE_OperationHandle operation,
2302b0104773SPascal Brand 		   const TEE_Attribute *params, uint32_t paramCount,
2303b0104773SPascal Brand 		   TEE_ObjectHandle derivedKey)
2304b0104773SPascal Brand {
2305e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
230675d6a373SJens Wiklander 	struct utee_object_info key_info = { };
230775d6a373SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
2308b0104773SPascal Brand 
2309b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL || derivedKey == 0)
2310b0104773SPascal Brand 		TEE_Panic(0);
23116915bbbbSJens Wiklander 
23126915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
23136915bbbbSJens Wiklander 
23148854d3c6SJerome Forissier 	if (TEE_ALG_GET_CLASS(operation->info.algorithm) !=
23158854d3c6SJerome Forissier 	    TEE_OPERATION_KEY_DERIVATION)
2316b0104773SPascal Brand 		TEE_Panic(0);
2317b0104773SPascal Brand 
2318b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION)
2319b0104773SPascal Brand 		TEE_Panic(0);
232084fa9467SCedric Chaumont 	if (!operation->key1)
232184fa9467SCedric Chaumont 		TEE_Panic(0);
2322b0104773SPascal Brand 	if (operation->info.mode != TEE_MODE_DERIVE)
2323b0104773SPascal Brand 		TEE_Panic(0);
2324b0104773SPascal Brand 	if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0)
2325b0104773SPascal Brand 		TEE_Panic(0);
2326b0104773SPascal Brand 
23272c028fdeSJerome Forissier 	res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info);
2328b0104773SPascal Brand 	if (res != TEE_SUCCESS)
2329b36311adSJerome Forissier 		TEE_Panic(res);
2330b0104773SPascal Brand 
233175d6a373SJens Wiklander 	if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET)
2332b0104773SPascal Brand 		TEE_Panic(0);
233375d6a373SJens Wiklander 	if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
2334b0104773SPascal Brand 		TEE_Panic(0);
2335b0104773SPascal Brand 
2336e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
23372c028fdeSJerome Forissier 	res = _utee_cryp_derive_key(operation->state, ua, paramCount,
2338e86f1266SJens Wiklander 				    (unsigned long)derivedKey);
2339b0104773SPascal Brand 	if (res != TEE_SUCCESS)
2340b0104773SPascal Brand 		TEE_Panic(res);
2341b0104773SPascal Brand }
2342b0104773SPascal Brand 
23434f4374c8SJens Wiklander void __GP11_TEE_DeriveKey(TEE_OperationHandle operation,
23444f4374c8SJens Wiklander 			  const __GP11_TEE_Attribute *params,
23454f4374c8SJens Wiklander 			  uint32_t paramCount, TEE_ObjectHandle derivedKey)
23464f4374c8SJens Wiklander {
23474f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
23484f4374c8SJens Wiklander 	struct utee_object_info key_info = { };
23494f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
23504f4374c8SJens Wiklander 
23514f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || derivedKey == 0)
23524f4374c8SJens Wiklander 		TEE_Panic(0);
23534f4374c8SJens Wiklander 
23544f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
23554f4374c8SJens Wiklander 
23564f4374c8SJens Wiklander 	if (TEE_ALG_GET_CLASS(operation->info.algorithm) !=
23574f4374c8SJens Wiklander 	    TEE_OPERATION_KEY_DERIVATION)
23584f4374c8SJens Wiklander 		TEE_Panic(0);
23594f4374c8SJens Wiklander 
23604f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION)
23614f4374c8SJens Wiklander 		TEE_Panic(0);
23624f4374c8SJens Wiklander 	if (!operation->key1)
23634f4374c8SJens Wiklander 		TEE_Panic(0);
23644f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_DERIVE)
23654f4374c8SJens Wiklander 		TEE_Panic(0);
23664f4374c8SJens Wiklander 	if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0)
23674f4374c8SJens Wiklander 		TEE_Panic(0);
23684f4374c8SJens Wiklander 
23694f4374c8SJens Wiklander 	res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info);
23704f4374c8SJens Wiklander 	if (res != TEE_SUCCESS)
23714f4374c8SJens Wiklander 		TEE_Panic(res);
23724f4374c8SJens Wiklander 
23734f4374c8SJens Wiklander 	if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET)
23744f4374c8SJens Wiklander 		TEE_Panic(0);
23754f4374c8SJens Wiklander 	if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
23764f4374c8SJens Wiklander 		TEE_Panic(0);
23774f4374c8SJens Wiklander 
23784f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
23794f4374c8SJens Wiklander 	res = _utee_cryp_derive_key(operation->state, ua, paramCount,
23804f4374c8SJens Wiklander 				    (unsigned long)derivedKey);
23814f4374c8SJens Wiklander 	if (res != TEE_SUCCESS)
23824f4374c8SJens Wiklander 		TEE_Panic(res);
23834f4374c8SJens Wiklander }
23844f4374c8SJens Wiklander 
2385b0104773SPascal Brand /* Cryptographic Operations API - Random Number Generation Functions */
2386b0104773SPascal Brand 
2387411a488aSJens Wiklander void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen)
2388b0104773SPascal Brand {
2389b0104773SPascal Brand 	TEE_Result res;
2390b0104773SPascal Brand 
23912c028fdeSJerome Forissier 	res = _utee_cryp_random_number_generate(randomBuffer, randomBufferLen);
2392b0104773SPascal Brand 	if (res != TEE_SUCCESS)
2393b0104773SPascal Brand 		TEE_Panic(res);
2394b0104773SPascal Brand }
2395433c4257SJens Wiklander 
2396411a488aSJens Wiklander void __GP11_TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen)
2397411a488aSJens Wiklander {
2398411a488aSJens Wiklander 	TEE_GenerateRandom(randomBuffer, randomBufferLen);
2399411a488aSJens Wiklander }
2400411a488aSJens Wiklander 
2401433c4257SJens Wiklander int rand(void)
2402433c4257SJens Wiklander {
2403433c4257SJens Wiklander 	int rc;
2404433c4257SJens Wiklander 
2405433c4257SJens Wiklander 	TEE_GenerateRandom(&rc, sizeof(rc));
2406433c4257SJens Wiklander 
2407433c4257SJens Wiklander 	/*
2408433c4257SJens Wiklander 	 * RAND_MAX is the larges int, INT_MAX which is all bits but the
2409433c4257SJens Wiklander 	 * highest bit set.
2410433c4257SJens Wiklander 	 */
2411433c4257SJens Wiklander 	return rc & RAND_MAX;
2412433c4257SJens Wiklander }
241379170ce0SJerome Forissier 
241479170ce0SJerome Forissier TEE_Result TEE_IsAlgorithmSupported(uint32_t alg, uint32_t element)
241579170ce0SJerome Forissier {
241679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_AES)) {
241779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
241879170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_ECB_NOPAD)
241979170ce0SJerome Forissier 				goto check_element_none;
242079170ce0SJerome Forissier 		}
242179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
242279170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CBC_NOPAD)
242379170ce0SJerome Forissier 				goto check_element_none;
242479170ce0SJerome Forissier 		}
242579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTR)) {
242679170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CTR)
242779170ce0SJerome Forissier 				goto check_element_none;
242879170ce0SJerome Forissier 		}
242979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTS)) {
243079170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CTS)
243179170ce0SJerome Forissier 				goto check_element_none;
243279170ce0SJerome Forissier 		}
243379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_XTS)) {
243479170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_XTS)
243579170ce0SJerome Forissier 				goto check_element_none;
243679170ce0SJerome Forissier 		}
243779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) {
243879170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CBC_MAC_NOPAD ||
243979170ce0SJerome Forissier 			    alg == TEE_ALG_AES_CBC_MAC_PKCS5)
244079170ce0SJerome Forissier 				goto check_element_none;
244179170ce0SJerome Forissier 		}
244279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CMAC)) {
244379170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CMAC)
244479170ce0SJerome Forissier 				goto check_element_none;
244579170ce0SJerome Forissier 		}
244679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CCM)) {
244779170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CCM)
244879170ce0SJerome Forissier 				goto check_element_none;
244979170ce0SJerome Forissier 		}
245079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_GCM)) {
245179170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_GCM)
245279170ce0SJerome Forissier 				goto check_element_none;
245379170ce0SJerome Forissier 		}
245479170ce0SJerome Forissier 	}
245579170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DES)) {
245679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
245779170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_ECB_NOPAD ||
245879170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_ECB_NOPAD)
245979170ce0SJerome Forissier 				goto check_element_none;
246079170ce0SJerome Forissier 		}
246179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
246279170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_CBC_NOPAD ||
246379170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_NOPAD)
246479170ce0SJerome Forissier 				goto check_element_none;
246579170ce0SJerome Forissier 		}
246679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) {
246779170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_CBC_MAC_NOPAD ||
246879170ce0SJerome Forissier 			    alg == TEE_ALG_DES_CBC_MAC_PKCS5 ||
246979170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_MAC_NOPAD ||
247079170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_MAC_PKCS5)
247179170ce0SJerome Forissier 				goto check_element_none;
247279170ce0SJerome Forissier 		}
247379170ce0SJerome Forissier 	}
247479170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_MD5)) {
247579170ce0SJerome Forissier 		if (alg == TEE_ALG_MD5)
247679170ce0SJerome Forissier 			goto check_element_none;
247779170ce0SJerome Forissier 	}
247879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
247979170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA1)
248079170ce0SJerome Forissier 			goto check_element_none;
248179170ce0SJerome Forissier 	}
248279170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
248379170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA224)
248479170ce0SJerome Forissier 			goto check_element_none;
248579170ce0SJerome Forissier 	}
248679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
248779170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA256)
248879170ce0SJerome Forissier 			goto check_element_none;
248979170ce0SJerome Forissier 	}
249079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
249179170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA384)
249279170ce0SJerome Forissier 			goto check_element_none;
249379170ce0SJerome Forissier 	}
249479170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
249579170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA512)
249679170ce0SJerome Forissier 			goto check_element_none;
249779170ce0SJerome Forissier 	}
2498260b4028SJens Wiklander 	if (IS_ENABLED(CFG_CRYPTO_SHA3_224)) {
2499260b4028SJens Wiklander 		if (alg == TEE_ALG_SHA3_224)
2500260b4028SJens Wiklander 			goto check_element_none;
2501260b4028SJens Wiklander 	}
2502260b4028SJens Wiklander 	if (IS_ENABLED(CFG_CRYPTO_SHA3_256)) {
2503260b4028SJens Wiklander 		if (alg == TEE_ALG_SHA3_256)
2504260b4028SJens Wiklander 			goto check_element_none;
2505260b4028SJens Wiklander 	}
2506260b4028SJens Wiklander 	if (IS_ENABLED(CFG_CRYPTO_SHA3_384)) {
2507260b4028SJens Wiklander 		if (alg == TEE_ALG_SHA3_384)
2508260b4028SJens Wiklander 			goto check_element_none;
2509260b4028SJens Wiklander 	}
2510260b4028SJens Wiklander 	if (IS_ENABLED(CFG_CRYPTO_SHA3_512)) {
2511260b4028SJens Wiklander 		if (alg == TEE_ALG_SHA3_512)
2512260b4028SJens Wiklander 			goto check_element_none;
2513260b4028SJens Wiklander 	}
251479170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) {
251579170ce0SJerome Forissier 		if (alg == TEE_ALG_MD5SHA1)
251679170ce0SJerome Forissier 			goto check_element_none;
251779170ce0SJerome Forissier 	}
251879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_HMAC)) {
251979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5)) {
252079170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_MD5)
252179170ce0SJerome Forissier 				goto check_element_none;
252279170ce0SJerome Forissier 		}
252379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
252479170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA1)
252579170ce0SJerome Forissier 				goto check_element_none;
252679170ce0SJerome Forissier 		}
252779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
252879170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA224)
252979170ce0SJerome Forissier 				goto check_element_none;
253079170ce0SJerome Forissier 		}
253179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
253279170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA256)
253379170ce0SJerome Forissier 				goto check_element_none;
253479170ce0SJerome Forissier 		}
253579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
253679170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA384)
253779170ce0SJerome Forissier 				goto check_element_none;
253879170ce0SJerome Forissier 		}
253979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
254079170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA512)
254179170ce0SJerome Forissier 				goto check_element_none;
254279170ce0SJerome Forissier 		}
2543260b4028SJens Wiklander 		if (IS_ENABLED(CFG_CRYPTO_SHA3_224)) {
2544260b4028SJens Wiklander 			if (alg == TEE_ALG_HMAC_SHA3_224)
2545260b4028SJens Wiklander 				goto check_element_none;
2546260b4028SJens Wiklander 		}
2547260b4028SJens Wiklander 		if (IS_ENABLED(CFG_CRYPTO_SHA3_256)) {
2548260b4028SJens Wiklander 			if (alg == TEE_ALG_HMAC_SHA3_256)
2549260b4028SJens Wiklander 				goto check_element_none;
2550260b4028SJens Wiklander 		}
2551260b4028SJens Wiklander 		if (IS_ENABLED(CFG_CRYPTO_SHA3_384)) {
2552260b4028SJens Wiklander 			if (alg == TEE_ALG_HMAC_SHA3_384)
2553260b4028SJens Wiklander 				goto check_element_none;
2554260b4028SJens Wiklander 		}
2555260b4028SJens Wiklander 		if (IS_ENABLED(CFG_CRYPTO_SHA3_512)) {
2556260b4028SJens Wiklander 			if (alg == TEE_ALG_HMAC_SHA3_512)
2557260b4028SJens Wiklander 				goto check_element_none;
2558260b4028SJens Wiklander 		}
255979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SM3)) {
256079170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SM3)
256179170ce0SJerome Forissier 				goto check_element_none;
256279170ce0SJerome Forissier 		}
256379170ce0SJerome Forissier 	}
256479170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM3)) {
256579170ce0SJerome Forissier 		if (alg == TEE_ALG_SM3)
256679170ce0SJerome Forissier 			goto check_element_none;
256779170ce0SJerome Forissier 	}
256879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM4)) {
256979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
257079170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_ECB_NOPAD)
257179170ce0SJerome Forissier 				goto check_element_none;
257279170ce0SJerome Forissier 		}
257379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
257479170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_CBC_NOPAD)
257579170ce0SJerome Forissier 				goto check_element_none;
257679170ce0SJerome Forissier 		}
257779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTR)) {
257879170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_CTR)
257979170ce0SJerome Forissier 				goto check_element_none;
258079170ce0SJerome Forissier 		}
2581696f56acSPingan Xie 		if (IS_ENABLED(CFG_CRYPTO_XTS)) {
2582696f56acSPingan Xie 			if (alg == TEE_ALG_SM4_XTS)
2583696f56acSPingan Xie 				goto check_element_none;
2584696f56acSPingan Xie 		}
258579170ce0SJerome Forissier 	}
258679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_RSA)) {
258779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5)) {
258879170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5)
258979170ce0SJerome Forissier 				goto check_element_none;
259079170ce0SJerome Forissier 		}
259179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
259279170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 ||
259379170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 ||
259479170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1)
259579170ce0SJerome Forissier 				goto check_element_none;
259679170ce0SJerome Forissier 		}
259779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) {
259879170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1)
259979170ce0SJerome Forissier 				goto check_element_none;
260079170ce0SJerome Forissier 		}
260179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
260279170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 ||
260379170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 ||
260479170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224)
260579170ce0SJerome Forissier 				goto check_element_none;
260679170ce0SJerome Forissier 		}
260779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
260879170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 ||
260979170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 ||
261079170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256)
261179170ce0SJerome Forissier 				goto check_element_none;
261279170ce0SJerome Forissier 		}
261379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
261479170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 ||
261579170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 ||
261679170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384)
261779170ce0SJerome Forissier 				goto check_element_none;
261879170ce0SJerome Forissier 		}
261979170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
262079170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 ||
262179170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 ||
262279170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512)
262379170ce0SJerome Forissier 				goto check_element_none;
262479170ce0SJerome Forissier 		}
262579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) {
262679170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5)
262779170ce0SJerome Forissier 				goto check_element_none;
262879170ce0SJerome Forissier 		}
262979170ce0SJerome Forissier 		if (alg == TEE_ALG_RSA_NOPAD)
263079170ce0SJerome Forissier 			goto check_element_none;
263179170ce0SJerome Forissier 	}
263279170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DSA)) {
263379170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
263479170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA1)
263579170ce0SJerome Forissier 				goto check_element_none;
263679170ce0SJerome Forissier 		}
263779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
263879170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA224)
263979170ce0SJerome Forissier 				goto check_element_none;
264079170ce0SJerome Forissier 		}
264179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
264279170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA256)
264379170ce0SJerome Forissier 				goto check_element_none;
264479170ce0SJerome Forissier 		}
264579170ce0SJerome Forissier 	}
264679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DH)) {
264779170ce0SJerome Forissier 		if (alg == TEE_ALG_DH_DERIVE_SHARED_SECRET)
264879170ce0SJerome Forissier 			goto check_element_none;
264979170ce0SJerome Forissier 	}
265079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_ECC)) {
2651fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P192 ||
2652fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P192 ||
2653fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2654fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA1) &&
265579170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P192)
265679170ce0SJerome Forissier 			return TEE_SUCCESS;
2657fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P224 ||
2658fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P224 ||
2659fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2660fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA224) &&
266179170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P224)
266279170ce0SJerome Forissier 			return TEE_SUCCESS;
2663fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P256 ||
2664fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P256 ||
2665fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2666fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA256) &&
266779170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P256)
266879170ce0SJerome Forissier 			return TEE_SUCCESS;
2669fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P384 ||
2670fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P384 ||
2671fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2672fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA384) &&
267379170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P384)
267479170ce0SJerome Forissier 			return TEE_SUCCESS;
2675fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P521 ||
2676fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P521 ||
2677fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2678fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA512) &&
267979170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P521)
268079170ce0SJerome Forissier 			return TEE_SUCCESS;
268179170ce0SJerome Forissier 	}
268279170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_DSA)) {
268379170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_DSA_SM3 && element == TEE_ECC_CURVE_SM2)
268479170ce0SJerome Forissier 			return TEE_SUCCESS;
268579170ce0SJerome Forissier 	}
268679170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_KEP)) {
268779170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_KEP && element == TEE_ECC_CURVE_SM2)
268879170ce0SJerome Forissier 			return TEE_SUCCESS;
268979170ce0SJerome Forissier 	}
269079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_PKE)) {
269179170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_PKE && element == TEE_ECC_CURVE_SM2)
269279170ce0SJerome Forissier 			return TEE_SUCCESS;
269379170ce0SJerome Forissier 	}
26943f61056dSSohaib ul Hassan 	if (IS_ENABLED(CFG_CRYPTO_X25519)) {
26953f61056dSSohaib ul Hassan 		if (alg == TEE_ALG_X25519 && element == TEE_ECC_CURVE_25519)
26963f61056dSSohaib ul Hassan 			return TEE_SUCCESS;
26973f61056dSSohaib ul Hassan 	}
2698e1f9cee7SSergiy Kibrik 	if (IS_ENABLED(CFG_CRYPTO_ED25519)) {
2699e1f9cee7SSergiy Kibrik 		if (alg == TEE_ALG_ED25519 && element == TEE_ECC_CURVE_25519)
2700e1f9cee7SSergiy Kibrik 			return TEE_SUCCESS;
2701e1f9cee7SSergiy Kibrik 	}
270279170ce0SJerome Forissier 
270379170ce0SJerome Forissier 	return TEE_ERROR_NOT_SUPPORTED;
270479170ce0SJerome Forissier check_element_none:
270579170ce0SJerome Forissier 	if (element == TEE_CRYPTO_ELEMENT_NONE)
270679170ce0SJerome Forissier 		return TEE_SUCCESS;
270779170ce0SJerome Forissier 	return TEE_ERROR_NOT_SUPPORTED;
270879170ce0SJerome Forissier }
2709