xref: /optee_os/lib/libutee/tee_api_operations.c (revision 696f56ac2bdf1382921cc3e08a25f0e18d5f08fc)
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  */
679170ce0SJerome Forissier #include <config.h>
7b0104773SPascal Brand #include <stdlib.h>
8b0104773SPascal Brand #include <string.h>
9b796ebf3SJerome Forissier #include <string_ext.h>
10b0104773SPascal Brand #include <tee_api.h>
118854d3c6SJerome Forissier #include <tee_api_defines_extensions.h>
12b0104773SPascal Brand #include <tee_internal_api_extensions.h>
13b0104773SPascal Brand #include <utee_syscalls.h>
14b0104773SPascal Brand #include <utee_defines.h>
15fc26c92aSJens Wiklander #include <util.h>
16e86f1266SJens Wiklander #include "tee_api_private.h"
17b0104773SPascal Brand 
18b0104773SPascal Brand struct __TEE_OperationHandle {
19b0104773SPascal Brand 	TEE_OperationInfo info;
20b0104773SPascal Brand 	TEE_ObjectHandle key1;
21b0104773SPascal Brand 	TEE_ObjectHandle key2;
22642a1607SCedric Chaumont 	uint32_t operationState;/* Operation state : INITIAL or ACTIVE */
23b0104773SPascal Brand 	uint8_t *buffer;	/* buffer to collect complete blocks */
24b0104773SPascal Brand 	bool buffer_two_blocks;	/* True if two blocks need to be buffered */
25b0104773SPascal Brand 	size_t block_size;	/* Block size of cipher */
26b0104773SPascal Brand 	size_t buffer_offs;	/* Offset in buffer */
27b0104773SPascal Brand 	uint32_t state;		/* Handle to state in TEE Core */
28b0104773SPascal Brand };
29b0104773SPascal Brand 
30b0104773SPascal Brand /* Cryptographic Operations API - Generic Operation Functions */
31b0104773SPascal Brand 
32b0104773SPascal Brand TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
33b0104773SPascal Brand 				 uint32_t algorithm, uint32_t mode,
34b0104773SPascal Brand 				 uint32_t maxKeySize)
35b0104773SPascal Brand {
36b0104773SPascal Brand 	TEE_Result res;
37b0104773SPascal Brand 	TEE_OperationHandle op = TEE_HANDLE_NULL;
38b0104773SPascal Brand 	uint32_t handle_state = 0;
39b0104773SPascal Brand 	size_t block_size = 1;
40b0104773SPascal Brand 	uint32_t req_key_usage;
41b0104773SPascal Brand 	bool with_private_key = false;
42b0104773SPascal Brand 	bool buffer_two_blocks = false;
43b0104773SPascal Brand 
449b52c538SCedric Chaumont 	if (!operation)
45b0104773SPascal Brand 		TEE_Panic(0);
46b0104773SPascal Brand 
47*696f56acSPingan Xie 	if (algorithm == TEE_ALG_AES_XTS || algorithm == TEE_ALG_SM2_KEP ||
48*696f56acSPingan Xie 	    algorithm == TEE_ALG_SM4_XTS)
49b0104773SPascal Brand 		handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;
50b0104773SPascal Brand 
51218d9055SCedric Chaumont 	/* Check algorithm max key size */
52218d9055SCedric Chaumont 	switch (algorithm) {
53218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA1:
54218d9055SCedric Chaumont 		if (maxKeySize < 512)
55218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
56218d9055SCedric Chaumont 		if (maxKeySize > 1024)
57218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
58218d9055SCedric Chaumont 		if (maxKeySize % 64 != 0)
59218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
60218d9055SCedric Chaumont 		break;
61218d9055SCedric Chaumont 
62218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA224:
63218d9055SCedric Chaumont 		if (maxKeySize != 2048)
64218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
65218d9055SCedric Chaumont 		break;
66218d9055SCedric Chaumont 
67218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA256:
68218d9055SCedric Chaumont 		if (maxKeySize != 2048 && maxKeySize != 3072)
69218d9055SCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
70218d9055SCedric Chaumont 		break;
71218d9055SCedric Chaumont 
721220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P192:
731220586eSCedric Chaumont 	case TEE_ALG_ECDH_P192:
741220586eSCedric Chaumont 		if (maxKeySize != 192)
751220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
761220586eSCedric Chaumont 		break;
771220586eSCedric Chaumont 
781220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P224:
791220586eSCedric Chaumont 	case TEE_ALG_ECDH_P224:
801220586eSCedric Chaumont 		if (maxKeySize != 224)
811220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
821220586eSCedric Chaumont 		break;
831220586eSCedric Chaumont 
841220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P256:
851220586eSCedric Chaumont 	case TEE_ALG_ECDH_P256:
8691fc6bd8SJerome Forissier 	case TEE_ALG_SM2_PKE:
870f151943SJerome Forissier 	case TEE_ALG_SM2_DSA_SM3:
881220586eSCedric Chaumont 		if (maxKeySize != 256)
891220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
901220586eSCedric Chaumont 		break;
911220586eSCedric Chaumont 
925b385b3fSJerome Forissier 	case TEE_ALG_SM2_KEP:
935b385b3fSJerome Forissier 		/* Two 256-bit keys */
945b385b3fSJerome Forissier 		if (maxKeySize != 512)
955b385b3fSJerome Forissier 			return TEE_ERROR_NOT_SUPPORTED;
965b385b3fSJerome Forissier 		break;
975b385b3fSJerome Forissier 
981220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P384:
991220586eSCedric Chaumont 	case TEE_ALG_ECDH_P384:
1001220586eSCedric Chaumont 		if (maxKeySize != 384)
1011220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
1021220586eSCedric Chaumont 		break;
1031220586eSCedric Chaumont 
1041220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P521:
1051220586eSCedric Chaumont 	case TEE_ALG_ECDH_P521:
1061220586eSCedric Chaumont 		if (maxKeySize != 521)
1071220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
1081220586eSCedric Chaumont 		break;
109e1f9cee7SSergiy Kibrik 	case TEE_ALG_ED25519:
1103f61056dSSohaib ul Hassan 	case TEE_ALG_X25519:
1113f61056dSSohaib ul Hassan 		if (maxKeySize != 256)
1123f61056dSSohaib ul Hassan 			return TEE_ERROR_NOT_SUPPORTED;
1133f61056dSSohaib ul Hassan 		break;
114218d9055SCedric Chaumont 	default:
115218d9055SCedric Chaumont 		break;
116218d9055SCedric Chaumont 	}
117218d9055SCedric Chaumont 
118cf5c060cSJens Wiklander 	/* Check algorithm mode (and maxKeySize for digests) */
119b0104773SPascal Brand 	switch (algorithm) {
120b0104773SPascal Brand 	case TEE_ALG_AES_CTS:
121b0104773SPascal Brand 	case TEE_ALG_AES_XTS:
122*696f56acSPingan Xie 	case TEE_ALG_SM4_XTS:
123b0104773SPascal Brand 		buffer_two_blocks = true;
124919a5a68SJerome Forissier 		fallthrough;
1254bd53c54SJerome Forissier 	case TEE_ALG_AES_ECB_NOPAD:
126b0104773SPascal Brand 	case TEE_ALG_AES_CBC_NOPAD:
127b0104773SPascal Brand 	case TEE_ALG_AES_CCM:
128b0104773SPascal Brand 	case TEE_ALG_DES_ECB_NOPAD:
129b0104773SPascal Brand 	case TEE_ALG_DES_CBC_NOPAD:
130b0104773SPascal Brand 	case TEE_ALG_DES3_ECB_NOPAD:
131b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_NOPAD:
132ade6f848SJerome Forissier 	case TEE_ALG_SM4_ECB_NOPAD:
133ade6f848SJerome Forissier 	case TEE_ALG_SM4_CBC_NOPAD:
134ade6f848SJerome Forissier 	case TEE_ALG_SM4_CTR:
135b0104773SPascal Brand 		if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES)
136b0104773SPascal Brand 			block_size = TEE_AES_BLOCK_SIZE;
137ade6f848SJerome Forissier 		else if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_SM4)
138ade6f848SJerome Forissier 			block_size = TEE_SM4_BLOCK_SIZE;
139b0104773SPascal Brand 		else
140b0104773SPascal Brand 			block_size = TEE_DES_BLOCK_SIZE;
141919a5a68SJerome Forissier 		fallthrough;
14257aabac5SBogdan Liulko 	case TEE_ALG_AES_CTR:
143afc0c182SBogdan Liulko 	case TEE_ALG_AES_GCM:
144b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT)
145b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT;
146b0104773SPascal Brand 		else if (mode == TEE_MODE_DECRYPT)
147b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT;
148b0104773SPascal Brand 		else
149b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
150b0104773SPascal Brand 		break;
151b0104773SPascal Brand 
1526a2e0a9fSGabor Szekely #if defined(CFG_CRYPTO_RSASSA_NA1)
1536a2e0a9fSGabor Szekely 	case TEE_ALG_RSASSA_PKCS1_V1_5:
1546a2e0a9fSGabor Szekely #endif
155b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
156b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
157b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
158b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
159b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
160b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
161b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
162b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
163b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
164b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
165b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
166b0104773SPascal Brand 	case TEE_ALG_DSA_SHA1:
167218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA224:
168218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA256:
1691220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P192:
1701220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P224:
1711220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P256:
1721220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P384:
1731220586eSCedric Chaumont 	case TEE_ALG_ECDSA_P521:
1740f151943SJerome Forissier 	case TEE_ALG_SM2_DSA_SM3:
175e1f9cee7SSergiy Kibrik 	case TEE_ALG_ED25519:
176b0104773SPascal Brand 		if (mode == TEE_MODE_SIGN) {
177b0104773SPascal Brand 			with_private_key = true;
178b0104773SPascal Brand 			req_key_usage = TEE_USAGE_SIGN;
179b0104773SPascal Brand 		} else if (mode == TEE_MODE_VERIFY) {
180b0104773SPascal Brand 			req_key_usage = TEE_USAGE_VERIFY;
181b0104773SPascal Brand 		} else {
182b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
183b0104773SPascal Brand 		}
184b0104773SPascal Brand 		break;
185b0104773SPascal Brand 
186b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_V1_5:
187b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
188b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
189b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
190b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
191b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
19291fc6bd8SJerome Forissier 	case TEE_ALG_SM2_PKE:
193b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT) {
194b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT;
195b0104773SPascal Brand 		} else if (mode == TEE_MODE_DECRYPT) {
196b0104773SPascal Brand 			with_private_key = true;
197b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT;
198b0104773SPascal Brand 		} else {
199b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
200b0104773SPascal Brand 		}
201b0104773SPascal Brand 		break;
202b0104773SPascal Brand 
203b0104773SPascal Brand 	case TEE_ALG_RSA_NOPAD:
204b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT) {
205b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY;
206b0104773SPascal Brand 		} else if (mode == TEE_MODE_DECRYPT) {
207b0104773SPascal Brand 			with_private_key = true;
208b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN;
209b0104773SPascal Brand 		} else {
210b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
211b0104773SPascal Brand 		}
212b0104773SPascal Brand 		break;
213b0104773SPascal Brand 
214b0104773SPascal Brand 	case TEE_ALG_DH_DERIVE_SHARED_SECRET:
2151220586eSCedric Chaumont 	case TEE_ALG_ECDH_P192:
2161220586eSCedric Chaumont 	case TEE_ALG_ECDH_P224:
2171220586eSCedric Chaumont 	case TEE_ALG_ECDH_P256:
2181220586eSCedric Chaumont 	case TEE_ALG_ECDH_P384:
2191220586eSCedric Chaumont 	case TEE_ALG_ECDH_P521:
220cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_MD5_DERIVE_KEY:
221cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA1_DERIVE_KEY:
222cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA224_DERIVE_KEY:
223cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA256_DERIVE_KEY:
224cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA384_DERIVE_KEY:
225cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA512_DERIVE_KEY:
2268854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY:
2278854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY:
2288854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY:
2298854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY:
2308854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY:
2310f2293b7SJerome Forissier 	case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY:
2325b385b3fSJerome Forissier 	case TEE_ALG_SM2_KEP:
2333f61056dSSohaib ul Hassan 	case TEE_ALG_X25519:
234b0104773SPascal Brand 		if (mode != TEE_MODE_DERIVE)
235b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
236b0104773SPascal Brand 		with_private_key = true;
237b0104773SPascal Brand 		req_key_usage = TEE_USAGE_DERIVE;
238b0104773SPascal Brand 		break;
239b0104773SPascal Brand 
240b0104773SPascal Brand 	case TEE_ALG_MD5:
241b0104773SPascal Brand 	case TEE_ALG_SHA1:
242b0104773SPascal Brand 	case TEE_ALG_SHA224:
243b0104773SPascal Brand 	case TEE_ALG_SHA256:
244b0104773SPascal Brand 	case TEE_ALG_SHA384:
245b0104773SPascal Brand 	case TEE_ALG_SHA512:
24647645577SJerome Forissier 	case TEE_ALG_SM3:
247b0104773SPascal Brand 		if (mode != TEE_MODE_DIGEST)
248b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
249cf5c060cSJens Wiklander 		if (maxKeySize)
250cf5c060cSJens Wiklander 			return TEE_ERROR_NOT_SUPPORTED;
25105304565SCedric Chaumont 		/* v1.1: flags always set for digest operations */
252b0104773SPascal Brand 		handle_state |= TEE_HANDLE_FLAG_KEY_SET;
253b0104773SPascal Brand 		req_key_usage = 0;
254b0104773SPascal Brand 		break;
255b0104773SPascal Brand 
256b0104773SPascal Brand 	case TEE_ALG_DES_CBC_MAC_NOPAD:
257b0104773SPascal Brand 	case TEE_ALG_AES_CBC_MAC_NOPAD:
258b0104773SPascal Brand 	case TEE_ALG_AES_CBC_MAC_PKCS5:
259b0104773SPascal Brand 	case TEE_ALG_AES_CMAC:
260b0104773SPascal Brand 	case TEE_ALG_DES_CBC_MAC_PKCS5:
261b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_MAC_NOPAD:
262b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_MAC_PKCS5:
263eee637e7SAlexander Zakharov 	case TEE_ALG_DES3_CMAC:
264b0104773SPascal Brand 	case TEE_ALG_HMAC_MD5:
265b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA1:
266b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA224:
267b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA256:
268b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA384:
269b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA512:
27047645577SJerome Forissier 	case TEE_ALG_HMAC_SM3:
271b0104773SPascal Brand 		if (mode != TEE_MODE_MAC)
272b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
273b0104773SPascal Brand 		req_key_usage = TEE_USAGE_MAC;
274b0104773SPascal Brand 		break;
275b0104773SPascal Brand 
276b0104773SPascal Brand 	default:
277b0104773SPascal Brand 		return TEE_ERROR_NOT_SUPPORTED;
278b0104773SPascal Brand 	}
279b0104773SPascal Brand 
280b66f219bSJens Wiklander 	op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO);
2819b52c538SCedric Chaumont 	if (!op)
282b0104773SPascal Brand 		return TEE_ERROR_OUT_OF_MEMORY;
283b0104773SPascal Brand 
284b0104773SPascal Brand 	op->info.algorithm = algorithm;
285b0104773SPascal Brand 	op->info.operationClass = TEE_ALG_GET_CLASS(algorithm);
2866a2e0a9fSGabor Szekely #ifdef CFG_CRYPTO_RSASSA_NA1
2876a2e0a9fSGabor Szekely 	if (algorithm == TEE_ALG_RSASSA_PKCS1_V1_5)
2886a2e0a9fSGabor Szekely 		op->info.operationClass = TEE_OPERATION_ASYMMETRIC_SIGNATURE;
2896a2e0a9fSGabor Szekely #endif
290b0104773SPascal Brand 	op->info.mode = mode;
2912e5e6460SAlbert Schwarzkopf 	op->info.digestLength = TEE_ALG_GET_DIGEST_SIZE(algorithm);
292b0104773SPascal Brand 	op->info.maxKeySize = maxKeySize;
293b0104773SPascal Brand 	op->info.requiredKeyUsage = req_key_usage;
294b0104773SPascal Brand 	op->info.handleState = handle_state;
295b0104773SPascal Brand 
296b0104773SPascal Brand 	if (block_size > 1) {
297b0104773SPascal Brand 		size_t buffer_size = block_size;
298b0104773SPascal Brand 
299b0104773SPascal Brand 		if (buffer_two_blocks)
300b0104773SPascal Brand 			buffer_size *= 2;
301b0104773SPascal Brand 
3029b52c538SCedric Chaumont 		op->buffer = TEE_Malloc(buffer_size,
3039b52c538SCedric Chaumont 					TEE_USER_MEM_HINT_NO_FILL_ZERO);
304b0104773SPascal Brand 		if (op->buffer == NULL) {
305b0104773SPascal Brand 			res = TEE_ERROR_OUT_OF_MEMORY;
306b66f219bSJens Wiklander 			goto out;
307b0104773SPascal Brand 		}
308b0104773SPascal Brand 	}
309b0104773SPascal Brand 	op->block_size = block_size;
310b0104773SPascal Brand 	op->buffer_two_blocks = buffer_two_blocks;
311b0104773SPascal Brand 
312b0104773SPascal Brand 	if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) {
313b0104773SPascal Brand 		uint32_t mks = maxKeySize;
314b0104773SPascal Brand 		TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm,
315b0104773SPascal Brand 						       with_private_key);
316b0104773SPascal Brand 
317b0104773SPascal Brand 		/*
318b0104773SPascal Brand 		 * If two keys are expected the max key size is the sum of
319b0104773SPascal Brand 		 * the size of both keys.
320b0104773SPascal Brand 		 */
321b0104773SPascal Brand 		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS)
322b0104773SPascal Brand 			mks /= 2;
323b0104773SPascal Brand 
324b0104773SPascal Brand 		res = TEE_AllocateTransientObject(key_type, mks, &op->key1);
325b0104773SPascal Brand 		if (res != TEE_SUCCESS)
326b66f219bSJens Wiklander 			goto out;
327b0104773SPascal Brand 
32805304565SCedric Chaumont 		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) {
3299b52c538SCedric Chaumont 			res = TEE_AllocateTransientObject(key_type, mks,
330b0104773SPascal Brand 							  &op->key2);
331b0104773SPascal Brand 			if (res != TEE_SUCCESS)
332b66f219bSJens Wiklander 				goto out;
333b0104773SPascal Brand 		}
334b0104773SPascal Brand 	}
335b0104773SPascal Brand 
3362c028fdeSJerome Forissier 	res = _utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1,
337e86f1266SJens Wiklander 				     (unsigned long)op->key2, &op->state);
338b66f219bSJens Wiklander 	if (res != TEE_SUCCESS)
339b66f219bSJens Wiklander 		goto out;
340b0104773SPascal Brand 
34105304565SCedric Chaumont 	/*
34205304565SCedric Chaumont 	 * Initialize digest operations
34305304565SCedric Chaumont 	 * Other multi-stage operations initialized w/ TEE_xxxInit functions
34405304565SCedric Chaumont 	 * Non-applicable on asymmetric operations
34505304565SCedric Chaumont 	 */
34605304565SCedric Chaumont 	if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) {
3472c028fdeSJerome Forissier 		res = _utee_hash_init(op->state, NULL, 0);
34805304565SCedric Chaumont 		if (res != TEE_SUCCESS)
349b66f219bSJens Wiklander 			goto out;
35005304565SCedric Chaumont 		/* v1.1: flags always set for digest operations */
35105304565SCedric Chaumont 		op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
35205304565SCedric Chaumont 	}
35305304565SCedric Chaumont 
354642a1607SCedric Chaumont 	op->operationState = TEE_OPERATION_STATE_INITIAL;
355642a1607SCedric Chaumont 
356b0104773SPascal Brand 	*operation = op;
357b0104773SPascal Brand 
358b66f219bSJens Wiklander out:
359b66f219bSJens Wiklander 	if (res != TEE_SUCCESS) {
360b66f219bSJens Wiklander 		if (res != TEE_ERROR_OUT_OF_MEMORY &&
3619b52c538SCedric Chaumont 		    res != TEE_ERROR_NOT_SUPPORTED)
362b36311adSJerome Forissier 			TEE_Panic(res);
363b66f219bSJens Wiklander 		if (op) {
364b66f219bSJens Wiklander 			if (op->state) {
365b66f219bSJens Wiklander 				TEE_FreeOperation(op);
366b66f219bSJens Wiklander 			} else {
367b66f219bSJens Wiklander 				TEE_Free(op->buffer);
368b66f219bSJens Wiklander 				TEE_FreeTransientObject(op->key1);
369b66f219bSJens Wiklander 				TEE_FreeTransientObject(op->key2);
370b66f219bSJens Wiklander 				TEE_Free(op);
371b66f219bSJens Wiklander 			}
372b66f219bSJens Wiklander 		}
373b66f219bSJens Wiklander 	}
374b66f219bSJens Wiklander 
375b0104773SPascal Brand 	return res;
376b0104773SPascal Brand }
377b0104773SPascal Brand 
378b0104773SPascal Brand void TEE_FreeOperation(TEE_OperationHandle operation)
379b0104773SPascal Brand {
380e889e80bSCedric Chaumont 	TEE_Result res;
381e889e80bSCedric Chaumont 
382e889e80bSCedric Chaumont 	if (operation == TEE_HANDLE_NULL)
383e889e80bSCedric Chaumont 		TEE_Panic(0);
384e889e80bSCedric Chaumont 
385b0104773SPascal Brand 	/*
386b0104773SPascal Brand 	 * Note that keys should not be freed here, since they are
387b0104773SPascal Brand 	 * claimed by the operation they will be freed by
388b0104773SPascal Brand 	 * utee_cryp_state_free().
389b0104773SPascal Brand 	 */
3902c028fdeSJerome Forissier 	res = _utee_cryp_state_free(operation->state);
391e889e80bSCedric Chaumont 	if (res != TEE_SUCCESS)
392b36311adSJerome Forissier 		TEE_Panic(res);
393e889e80bSCedric Chaumont 
394b0104773SPascal Brand 	TEE_Free(operation->buffer);
395b0104773SPascal Brand 	TEE_Free(operation);
396b0104773SPascal Brand }
397b0104773SPascal Brand 
398b0104773SPascal Brand void TEE_GetOperationInfo(TEE_OperationHandle operation,
399b0104773SPascal Brand 			  TEE_OperationInfo *operationInfo)
400b0104773SPascal Brand {
401b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
402b0104773SPascal Brand 		TEE_Panic(0);
403b0104773SPascal Brand 
4046915bbbbSJens Wiklander 	__utee_check_out_annotation(operationInfo, sizeof(*operationInfo));
405b0104773SPascal Brand 
406b0104773SPascal Brand 	*operationInfo = operation->info;
407bac3a8a7SJens Wiklander 	if (operationInfo->handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) {
408bac3a8a7SJens Wiklander 		operationInfo->keySize = 0;
409bac3a8a7SJens Wiklander 		operationInfo->requiredKeyUsage = 0;
410bac3a8a7SJens Wiklander 	}
411b0104773SPascal Brand }
412b0104773SPascal Brand 
413ee2f75afSJens Wiklander TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle op,
414ee2f75afSJens Wiklander 					TEE_OperationInfoMultiple *op_info,
415ee2f75afSJens Wiklander 					uint32_t *size)
41605304565SCedric Chaumont {
41705304565SCedric Chaumont 	TEE_Result res = TEE_SUCCESS;
418ee2f75afSJens Wiklander 	TEE_ObjectInfo kinfo = { };
419ee2f75afSJens Wiklander 	size_t max_key_count = 0;
420ee2f75afSJens Wiklander 	bool two_keys = false;
42105304565SCedric Chaumont 
422ee2f75afSJens Wiklander 	if (op == TEE_HANDLE_NULL) {
42305304565SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
42405304565SCedric Chaumont 		goto out;
42505304565SCedric Chaumont 	}
42605304565SCedric Chaumont 
427ee2f75afSJens Wiklander 	__utee_check_outbuf_annotation(op_info, size);
42805304565SCedric Chaumont 
429ee2f75afSJens Wiklander 	if (*size < sizeof(*op_info)) {
430ee2f75afSJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
431ee2f75afSJens Wiklander 		goto out;
432ee2f75afSJens Wiklander 	}
433ee2f75afSJens Wiklander 	max_key_count = (*size - sizeof(*op_info)) /
43405304565SCedric Chaumont 			sizeof(TEE_OperationInfoKey);
43505304565SCedric Chaumont 
436ee2f75afSJens Wiklander 	TEE_MemFill(op_info, 0, *size);
43705304565SCedric Chaumont 
43805304565SCedric Chaumont 	/* Two keys flag (TEE_ALG_AES_XTS only) */
439ee2f75afSJens Wiklander 	two_keys = op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;
440ee2f75afSJens Wiklander 
441ee2f75afSJens Wiklander 	if (op->info.mode == TEE_MODE_DIGEST) {
442ee2f75afSJens Wiklander 		op_info->numberOfKeys = 0;
443ee2f75afSJens Wiklander 	} else if (!two_keys) {
444ee2f75afSJens Wiklander 		if (max_key_count < 1) {
44505304565SCedric Chaumont 			res = TEE_ERROR_SHORT_BUFFER;
44605304565SCedric Chaumont 			goto out;
44705304565SCedric Chaumont 		}
44805304565SCedric Chaumont 
449ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key1, &kinfo);
450ee2f75afSJens Wiklander 		/* Key1 is not a valid handle, "can't happen". */
451ee2f75afSJens Wiklander 		if (res)
45205304565SCedric Chaumont 			goto out;
45305304565SCedric Chaumont 
454ee2f75afSJens Wiklander 		op_info->keyInformation[0].keySize = kinfo.keySize;
455ee2f75afSJens Wiklander 		op_info->keyInformation[0].requiredKeyUsage =
456ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
457ee2f75afSJens Wiklander 		op_info->numberOfKeys = 1;
458ee2f75afSJens Wiklander 	} else {
459ee2f75afSJens Wiklander 		if (max_key_count < 2) {
460ee2f75afSJens Wiklander 			res = TEE_ERROR_SHORT_BUFFER;
46105304565SCedric Chaumont 			goto out;
46205304565SCedric Chaumont 		}
46305304565SCedric Chaumont 
464ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key1, &kinfo);
465ee2f75afSJens Wiklander 		/* Key1 is not a valid handle, "can't happen". */
466ee2f75afSJens Wiklander 		if (res)
467ee2f75afSJens Wiklander 			goto out;
468ee2f75afSJens Wiklander 
469ee2f75afSJens Wiklander 		op_info->keyInformation[0].keySize = kinfo.keySize;
470ee2f75afSJens Wiklander 		op_info->keyInformation[0].requiredKeyUsage =
471ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
472ee2f75afSJens Wiklander 
473ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key2, &kinfo);
474ee2f75afSJens Wiklander 		/* Key2 is not a valid handle, "can't happen". */
475ee2f75afSJens Wiklander 		if (res)
476ee2f75afSJens Wiklander 			goto out;
477ee2f75afSJens Wiklander 
478ee2f75afSJens Wiklander 		op_info->keyInformation[1].keySize = kinfo.keySize;
479ee2f75afSJens Wiklander 		op_info->keyInformation[1].requiredKeyUsage =
480ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
481ee2f75afSJens Wiklander 
482ee2f75afSJens Wiklander 		op_info->numberOfKeys = 2;
48305304565SCedric Chaumont 	}
48405304565SCedric Chaumont 
485ee2f75afSJens Wiklander 	op_info->algorithm = op->info.algorithm;
486ee2f75afSJens Wiklander 	op_info->operationClass = op->info.operationClass;
487ee2f75afSJens Wiklander 	op_info->mode = op->info.mode;
488ee2f75afSJens Wiklander 	op_info->digestLength = op->info.digestLength;
489ee2f75afSJens Wiklander 	op_info->maxKeySize = op->info.maxKeySize;
490ee2f75afSJens Wiklander 	op_info->handleState = op->info.handleState;
491ee2f75afSJens Wiklander 	op_info->operationState = op->operationState;
49205304565SCedric Chaumont 
49305304565SCedric Chaumont out:
49405304565SCedric Chaumont 	if (res != TEE_SUCCESS &&
49505304565SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
496b36311adSJerome Forissier 		TEE_Panic(res);
49705304565SCedric Chaumont 
49805304565SCedric Chaumont 	return res;
49905304565SCedric Chaumont }
50005304565SCedric Chaumont 
501b0104773SPascal Brand void TEE_ResetOperation(TEE_OperationHandle operation)
502b0104773SPascal Brand {
503b0104773SPascal Brand 	TEE_Result res;
504b0104773SPascal Brand 
505b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
506b0104773SPascal Brand 		TEE_Panic(0);
507bf80076aSCedric Chaumont 
508642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET))
509bf80076aSCedric Chaumont 			TEE_Panic(0);
510bf80076aSCedric Chaumont 
511642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
512642a1607SCedric Chaumont 
513b0104773SPascal Brand 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
5142c028fdeSJerome Forissier 		res = _utee_hash_init(operation->state, NULL, 0);
515b0104773SPascal Brand 		if (res != TEE_SUCCESS)
516b0104773SPascal Brand 			TEE_Panic(res);
51705304565SCedric Chaumont 		operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
51805304565SCedric Chaumont 	} else {
519b0104773SPascal Brand 		operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
520b0104773SPascal Brand 	}
52105304565SCedric Chaumont }
522b0104773SPascal Brand 
523b0104773SPascal Brand TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation,
524b0104773SPascal Brand 			       TEE_ObjectHandle key)
525b0104773SPascal Brand {
5267583c59eSCedric Chaumont 	TEE_Result res;
527b0104773SPascal Brand 	uint32_t key_size = 0;
528b0104773SPascal Brand 	TEE_ObjectInfo key_info;
529b0104773SPascal Brand 
530a57c1e2eSCedric Chaumont 	if (operation == TEE_HANDLE_NULL) {
531a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
532a57c1e2eSCedric Chaumont 		goto out;
533a57c1e2eSCedric Chaumont 	}
534a57c1e2eSCedric Chaumont 
535642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
536642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
537642a1607SCedric Chaumont 		goto out;
538642a1607SCedric Chaumont 	}
539642a1607SCedric Chaumont 
540a57c1e2eSCedric Chaumont 	if (key == TEE_HANDLE_NULL) {
541a57c1e2eSCedric Chaumont 		/* Operation key cleared */
542a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key1);
5436c4ea258SJens Wiklander 		operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
5446c4ea258SJens Wiklander 		return TEE_SUCCESS;
545a57c1e2eSCedric Chaumont 	}
546a57c1e2eSCedric Chaumont 
547a57c1e2eSCedric Chaumont 	/* No key for digest operation */
548a57c1e2eSCedric Chaumont 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
549a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
550a57c1e2eSCedric Chaumont 		goto out;
551a57c1e2eSCedric Chaumont 	}
552a57c1e2eSCedric Chaumont 
553a57c1e2eSCedric Chaumont 	/* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */
554a57c1e2eSCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) !=
555a57c1e2eSCedric Chaumont 	    0) {
556a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
557a57c1e2eSCedric Chaumont 		goto out;
558a57c1e2eSCedric Chaumont 	}
559a57c1e2eSCedric Chaumont 
5607583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key, &key_info);
561a57c1e2eSCedric Chaumont 	/* Key is not a valid handle */
5627583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
563a57c1e2eSCedric Chaumont 		goto out;
5647583c59eSCedric Chaumont 
565b0104773SPascal Brand 	/* Supplied key has to meet required usage */
566b0104773SPascal Brand 	if ((key_info.objectUsage & operation->info.requiredKeyUsage) !=
567b0104773SPascal Brand 	    operation->info.requiredKeyUsage) {
568a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
569a57c1e2eSCedric Chaumont 		goto out;
570b0104773SPascal Brand 	}
571b0104773SPascal Brand 
572a57c1e2eSCedric Chaumont 	if (operation->info.maxKeySize < key_info.keySize) {
573a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
574a57c1e2eSCedric Chaumont 		goto out;
575a57c1e2eSCedric Chaumont 	}
576b0104773SPascal Brand 
5777583c59eSCedric Chaumont 	key_size = key_info.keySize;
578b0104773SPascal Brand 
579b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key1);
580b0104773SPascal Brand 	operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
581b0104773SPascal Brand 
5827583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key1, key);
5837583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
584a57c1e2eSCedric Chaumont 		goto out;
5857583c59eSCedric Chaumont 
586b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET;
587b0104773SPascal Brand 
588b0104773SPascal Brand 	operation->info.keySize = key_size;
589b0104773SPascal Brand 
5907583c59eSCedric Chaumont out:
591a57c1e2eSCedric Chaumont 	if (res != TEE_SUCCESS  &&
592a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT &&
593a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE)
594b36311adSJerome Forissier 		TEE_Panic(res);
595a57c1e2eSCedric Chaumont 
596a57c1e2eSCedric Chaumont 	return res;
597b0104773SPascal Brand }
598b0104773SPascal Brand 
599b0104773SPascal Brand TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation,
600b0104773SPascal Brand 				TEE_ObjectHandle key1, TEE_ObjectHandle key2)
601b0104773SPascal Brand {
6027583c59eSCedric Chaumont 	TEE_Result res;
603b0104773SPascal Brand 	uint32_t key_size = 0;
604b0104773SPascal Brand 	TEE_ObjectInfo key_info1;
605b0104773SPascal Brand 	TEE_ObjectInfo key_info2;
606b0104773SPascal Brand 
607a57c1e2eSCedric Chaumont 	if (operation == TEE_HANDLE_NULL) {
608a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
609a57c1e2eSCedric Chaumont 		goto out;
610a57c1e2eSCedric Chaumont 	}
611a57c1e2eSCedric Chaumont 
612642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
613642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
614642a1607SCedric Chaumont 		goto out;
615642a1607SCedric Chaumont 	}
616642a1607SCedric Chaumont 
617a57c1e2eSCedric Chaumont 	/*
618a57c1e2eSCedric Chaumont 	 * Key1/Key2 and/or are not initialized and
619a57c1e2eSCedric Chaumont 	 * Either both keys are NULL or both are not NULL
620a57c1e2eSCedric Chaumont 	 */
6216c4ea258SJens Wiklander 	if (!key1 && !key2) {
6226c4ea258SJens Wiklander 		/* Clear the keys */
623a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key1);
624a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key2);
6256c4ea258SJens Wiklander 		operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
6266c4ea258SJens Wiklander 		return TEE_SUCCESS;
6276c4ea258SJens Wiklander 	} else if (!key1 || !key2) {
6286c4ea258SJens Wiklander 		/* Both keys are obviously not valid. */
629a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
630a57c1e2eSCedric Chaumont 		goto out;
631a57c1e2eSCedric Chaumont 	}
632a57c1e2eSCedric Chaumont 
633a57c1e2eSCedric Chaumont 	/* No key for digest operation */
634a57c1e2eSCedric Chaumont 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
635a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
636a57c1e2eSCedric Chaumont 		goto out;
637a57c1e2eSCedric Chaumont 	}
638a57c1e2eSCedric Chaumont 
6395b385b3fSJerome Forissier 	/* Two keys flag expected (TEE_ALG_AES_XTS and TEE_ALG_SM2_KEP only) */
640a57c1e2eSCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) ==
641a57c1e2eSCedric Chaumont 	    0) {
642a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
643a57c1e2eSCedric Chaumont 		goto out;
644a57c1e2eSCedric Chaumont 	}
645a57c1e2eSCedric Chaumont 
6467583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key1, &key_info1);
647a57c1e2eSCedric Chaumont 	/* Key1 is not a valid handle */
6487583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
649a57c1e2eSCedric Chaumont 		goto out;
6507583c59eSCedric Chaumont 
651b0104773SPascal Brand 	/* Supplied key has to meet required usage */
652b0104773SPascal Brand 	if ((key_info1.objectUsage & operation->info.
653b0104773SPascal Brand 	     requiredKeyUsage) != operation->info.requiredKeyUsage) {
654a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
655a57c1e2eSCedric Chaumont 		goto out;
656b0104773SPascal Brand 	}
657b0104773SPascal Brand 
6587583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key2, &key_info2);
659a57c1e2eSCedric Chaumont 	/* Key2 is not a valid handle */
6607583c59eSCedric Chaumont 	if (res != TEE_SUCCESS) {
6617583c59eSCedric Chaumont 		if (res == TEE_ERROR_CORRUPT_OBJECT)
6627583c59eSCedric Chaumont 			res = TEE_ERROR_CORRUPT_OBJECT_2;
663a57c1e2eSCedric Chaumont 		goto out;
6647583c59eSCedric Chaumont 	}
6657583c59eSCedric Chaumont 
666b0104773SPascal Brand 	/* Supplied key has to meet required usage */
667b0104773SPascal Brand 	if ((key_info2.objectUsage & operation->info.
668b0104773SPascal Brand 	     requiredKeyUsage) != operation->info.requiredKeyUsage) {
669a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
670a57c1e2eSCedric Chaumont 		goto out;
671b0104773SPascal Brand 	}
672b0104773SPascal Brand 
673b0104773SPascal Brand 	/*
6745b385b3fSJerome Forissier 	 * All the multi key algorithm currently supported requires the keys to
6755b385b3fSJerome Forissier 	 * be of equal size.
676b0104773SPascal Brand 	 */
6775b385b3fSJerome Forissier 	if (key_info1.keySize != key_info2.keySize) {
678a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
679a57c1e2eSCedric Chaumont 		goto out;
680b0104773SPascal Brand 
681a57c1e2eSCedric Chaumont 	}
682a57c1e2eSCedric Chaumont 
683a57c1e2eSCedric Chaumont 	if (operation->info.maxKeySize < key_info1.keySize) {
684a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
685a57c1e2eSCedric Chaumont 		goto out;
686a57c1e2eSCedric Chaumont 	}
687b0104773SPascal Brand 
688b0104773SPascal Brand 	/*
689b0104773SPascal Brand 	 * Odd that only the size of one key should be reported while
690b0104773SPascal Brand 	 * size of two key are used when allocating the operation.
691b0104773SPascal Brand 	 */
6927583c59eSCedric Chaumont 	key_size = key_info1.keySize;
693b0104773SPascal Brand 
694b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key1);
695b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key2);
696b0104773SPascal Brand 	operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
697b0104773SPascal Brand 
6987583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key1, key1);
6997583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
700a57c1e2eSCedric Chaumont 		goto out;
7017583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key2, key2);
7027583c59eSCedric Chaumont 	if (res != TEE_SUCCESS) {
7037583c59eSCedric Chaumont 		if (res == TEE_ERROR_CORRUPT_OBJECT)
7047583c59eSCedric Chaumont 			res = TEE_ERROR_CORRUPT_OBJECT_2;
705a57c1e2eSCedric Chaumont 		goto out;
7067583c59eSCedric Chaumont 	}
7077583c59eSCedric Chaumont 
708b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET;
709b0104773SPascal Brand 
710b0104773SPascal Brand 	operation->info.keySize = key_size;
711b0104773SPascal Brand 
7127583c59eSCedric Chaumont out:
713a57c1e2eSCedric Chaumont 	if (res != TEE_SUCCESS  &&
714a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT &&
715a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT_2 &&
716a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE &&
717a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2)
718b36311adSJerome Forissier 		TEE_Panic(res);
719a57c1e2eSCedric Chaumont 
720a57c1e2eSCedric Chaumont 	return res;
721b0104773SPascal Brand }
722b0104773SPascal Brand 
723b0104773SPascal Brand void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op)
724b0104773SPascal Brand {
725b0104773SPascal Brand 	TEE_Result res;
726b0104773SPascal Brand 
727b0104773SPascal Brand 	if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL)
728b0104773SPascal Brand 		TEE_Panic(0);
729b0104773SPascal Brand 	if (dst_op->info.algorithm != src_op->info.algorithm)
730b0104773SPascal Brand 		TEE_Panic(0);
7318734de30SJens Wiklander 	if (dst_op->info.mode != src_op->info.mode)
7328734de30SJens Wiklander 		TEE_Panic(0);
733b0104773SPascal Brand 	if (src_op->info.operationClass != TEE_OPERATION_DIGEST) {
734b0104773SPascal Brand 		TEE_ObjectHandle key1 = TEE_HANDLE_NULL;
735b0104773SPascal Brand 		TEE_ObjectHandle key2 = TEE_HANDLE_NULL;
736b0104773SPascal Brand 
737b0104773SPascal Brand 		if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) {
738b0104773SPascal Brand 			key1 = src_op->key1;
739b0104773SPascal Brand 			key2 = src_op->key2;
740b0104773SPascal Brand 		}
741b0104773SPascal Brand 
742b0104773SPascal Brand 		if ((src_op->info.handleState &
743b0104773SPascal Brand 		     TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) {
744b0104773SPascal Brand 			TEE_SetOperationKey(dst_op, key1);
745b0104773SPascal Brand 		} else {
746b0104773SPascal Brand 			TEE_SetOperationKey2(dst_op, key1, key2);
747b0104773SPascal Brand 		}
748b0104773SPascal Brand 	}
749b0104773SPascal Brand 	dst_op->info.handleState = src_op->info.handleState;
750b0104773SPascal Brand 	dst_op->info.keySize = src_op->info.keySize;
7518e07702eSJens Wiklander 	dst_op->info.digestLength = src_op->info.digestLength;
752642a1607SCedric Chaumont 	dst_op->operationState = src_op->operationState;
753b0104773SPascal Brand 
754b0104773SPascal Brand 	if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks ||
755b0104773SPascal Brand 	    dst_op->block_size != src_op->block_size)
756b0104773SPascal Brand 		TEE_Panic(0);
757b0104773SPascal Brand 
758b0104773SPascal Brand 	if (dst_op->buffer != NULL) {
759b0104773SPascal Brand 		if (src_op->buffer == NULL)
760b0104773SPascal Brand 			TEE_Panic(0);
761b0104773SPascal Brand 
762b0104773SPascal Brand 		memcpy(dst_op->buffer, src_op->buffer, src_op->buffer_offs);
763b0104773SPascal Brand 		dst_op->buffer_offs = src_op->buffer_offs;
764b0104773SPascal Brand 	} else if (src_op->buffer != NULL) {
765b0104773SPascal Brand 		TEE_Panic(0);
766b0104773SPascal Brand 	}
767b0104773SPascal Brand 
7682c028fdeSJerome Forissier 	res = _utee_cryp_state_copy(dst_op->state, src_op->state);
769b0104773SPascal Brand 	if (res != TEE_SUCCESS)
770b0104773SPascal Brand 		TEE_Panic(res);
771b0104773SPascal Brand }
772b0104773SPascal Brand 
773b0104773SPascal Brand /* Cryptographic Operations API - Message Digest Functions */
774b0104773SPascal Brand 
7758f07fe6fSJerome Forissier static void init_hash_operation(TEE_OperationHandle operation, const void *IV,
7766d15db08SJerome Forissier 				uint32_t IVLen)
7776d15db08SJerome Forissier {
7786d15db08SJerome Forissier 	TEE_Result res;
7796d15db08SJerome Forissier 
7806d15db08SJerome Forissier 	/*
7816d15db08SJerome Forissier 	 * Note : IV and IVLen are never used in current implementation
7826d15db08SJerome Forissier 	 * This is why coherent values of IV and IVLen are not checked
7836d15db08SJerome Forissier 	 */
7842c028fdeSJerome Forissier 	res = _utee_hash_init(operation->state, IV, IVLen);
7856d15db08SJerome Forissier 	if (res != TEE_SUCCESS)
7866d15db08SJerome Forissier 		TEE_Panic(res);
7876d15db08SJerome Forissier 	operation->buffer_offs = 0;
7886d15db08SJerome Forissier 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
7896d15db08SJerome Forissier }
7906d15db08SJerome Forissier 
791b0104773SPascal Brand void TEE_DigestUpdate(TEE_OperationHandle operation,
7928f07fe6fSJerome Forissier 		      const void *chunk, uint32_t chunkSize)
793b0104773SPascal Brand {
79473d6c3baSJoakim Bech 	TEE_Result res = TEE_ERROR_GENERIC;
795b0104773SPascal Brand 
79673d6c3baSJoakim Bech 	if (operation == TEE_HANDLE_NULL ||
79773d6c3baSJoakim Bech 	    operation->info.operationClass != TEE_OPERATION_DIGEST)
798b0104773SPascal Brand 		TEE_Panic(0);
79973d6c3baSJoakim Bech 
800642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
801642a1607SCedric Chaumont 
8022c028fdeSJerome Forissier 	res = _utee_hash_update(operation->state, chunk, chunkSize);
803b0104773SPascal Brand 	if (res != TEE_SUCCESS)
804b0104773SPascal Brand 		TEE_Panic(res);
805b0104773SPascal Brand }
806b0104773SPascal Brand 
8078f07fe6fSJerome Forissier TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk,
80879a3c601SCedric Chaumont 			     uint32_t chunkLen, void *hash, uint32_t *hashLen)
809b0104773SPascal Brand {
81087c2f6b6SCedric Chaumont 	TEE_Result res;
811e86f1266SJens Wiklander 	uint64_t hl;
81287c2f6b6SCedric Chaumont 
81387c2f6b6SCedric Chaumont 	if ((operation == TEE_HANDLE_NULL) ||
81487c2f6b6SCedric Chaumont 	    (!chunk && chunkLen) ||
81587c2f6b6SCedric Chaumont 	    (operation->info.operationClass != TEE_OPERATION_DIGEST)) {
81687c2f6b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
81787c2f6b6SCedric Chaumont 		goto out;
81887c2f6b6SCedric Chaumont 	}
8196915bbbbSJens Wiklander 	__utee_check_inout_annotation(hashLen, sizeof(*hashLen));
82087c2f6b6SCedric Chaumont 
821e86f1266SJens Wiklander 	hl = *hashLen;
8222c028fdeSJerome Forissier 	res = _utee_hash_final(operation->state, chunk, chunkLen, hash, &hl);
823e86f1266SJens Wiklander 	*hashLen = hl;
8246d15db08SJerome Forissier 	if (res != TEE_SUCCESS)
8256d15db08SJerome Forissier 		goto out;
8266d15db08SJerome Forissier 
8276d15db08SJerome Forissier 	/* Reset operation state */
8286d15db08SJerome Forissier 	init_hash_operation(operation, NULL, 0);
82987c2f6b6SCedric Chaumont 
830642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
831642a1607SCedric Chaumont 
83287c2f6b6SCedric Chaumont out:
83387c2f6b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
83487c2f6b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
835b36311adSJerome Forissier 		TEE_Panic(res);
83673d6c3baSJoakim Bech 
83787c2f6b6SCedric Chaumont 	return res;
838b0104773SPascal Brand }
839b0104773SPascal Brand 
840b0104773SPascal Brand /* Cryptographic Operations API - Symmetric Cipher Functions */
841b0104773SPascal Brand 
8428f07fe6fSJerome Forissier void TEE_CipherInit(TEE_OperationHandle operation, const void *IV,
8438f07fe6fSJerome Forissier 		    uint32_t IVLen)
844b0104773SPascal Brand {
845b0104773SPascal Brand 	TEE_Result res;
846b0104773SPascal Brand 
847b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
848b0104773SPascal Brand 		TEE_Panic(0);
849642a1607SCedric Chaumont 
850b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_CIPHER)
851b0104773SPascal Brand 		TEE_Panic(0);
852642a1607SCedric Chaumont 
853642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||
854642a1607SCedric Chaumont 	    !(operation->key1))
855642a1607SCedric Chaumont 		TEE_Panic(0);
856642a1607SCedric Chaumont 
857642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
858642a1607SCedric Chaumont 		TEE_ResetOperation(operation);
859642a1607SCedric Chaumont 
860ad7aa2a5SSadiq Hussain 	if (IV && IVLen) {
861ad7aa2a5SSadiq Hussain 		if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD ||
862ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD ||
863ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD ||
864ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD)
865ad7aa2a5SSadiq Hussain 			TEE_Panic(0);
866ad7aa2a5SSadiq Hussain 	}
867ad7aa2a5SSadiq Hussain 
868642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
869642a1607SCedric Chaumont 
8702c028fdeSJerome Forissier 	res = _utee_cipher_init(operation->state, IV, IVLen);
871b0104773SPascal Brand 	if (res != TEE_SUCCESS)
872b0104773SPascal Brand 		TEE_Panic(res);
873642a1607SCedric Chaumont 
874b0104773SPascal Brand 	operation->buffer_offs = 0;
875b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
876b0104773SPascal Brand }
877b0104773SPascal Brand 
878b0104773SPascal Brand static TEE_Result tee_buffer_update(
879b0104773SPascal Brand 		TEE_OperationHandle op,
880e86f1266SJens Wiklander 		TEE_Result(*update_func)(unsigned long state, const void *src,
881e86f1266SJens Wiklander 				size_t slen, void *dst, uint64_t *dlen),
882b0104773SPascal Brand 		const void *src_data, size_t src_len,
883e86f1266SJens Wiklander 		void *dest_data, uint64_t *dest_len)
884b0104773SPascal Brand {
885b0104773SPascal Brand 	TEE_Result res;
886b0104773SPascal Brand 	const uint8_t *src = src_data;
887b0104773SPascal Brand 	size_t slen = src_len;
888b0104773SPascal Brand 	uint8_t *dst = dest_data;
889b0104773SPascal Brand 	size_t dlen = *dest_len;
890b0104773SPascal Brand 	size_t acc_dlen = 0;
891e86f1266SJens Wiklander 	uint64_t tmp_dlen;
892b0104773SPascal Brand 	size_t l;
893b0104773SPascal Brand 	size_t buffer_size;
894d3588802SPascal Brand 	size_t buffer_left;
895b0104773SPascal Brand 
896090268f5SJens Wiklander 	if (!src) {
897090268f5SJens Wiklander 		if (slen)
898090268f5SJens Wiklander 			TEE_Panic(0);
899090268f5SJens Wiklander 		goto out;
900090268f5SJens Wiklander 	}
901090268f5SJens Wiklander 
902d3588802SPascal Brand 	if (op->buffer_two_blocks) {
903b0104773SPascal Brand 		buffer_size = op->block_size * 2;
904d3588802SPascal Brand 		buffer_left = 1;
905d3588802SPascal Brand 	} else {
906b0104773SPascal Brand 		buffer_size = op->block_size;
907d3588802SPascal Brand 		buffer_left = 0;
908d3588802SPascal Brand 	}
909b0104773SPascal Brand 
910b0104773SPascal Brand 	if (op->buffer_offs > 0) {
911b0104773SPascal Brand 		/* Fill up complete block */
912b0104773SPascal Brand 		if (op->buffer_offs < op->block_size)
913b0104773SPascal Brand 			l = MIN(slen, op->block_size - op->buffer_offs);
914b0104773SPascal Brand 		else
915b0104773SPascal Brand 			l = MIN(slen, buffer_size - op->buffer_offs);
916b0104773SPascal Brand 		memcpy(op->buffer + op->buffer_offs, src, l);
917b0104773SPascal Brand 		op->buffer_offs += l;
918b0104773SPascal Brand 		src += l;
919b0104773SPascal Brand 		slen -= l;
920b0104773SPascal Brand 		if ((op->buffer_offs % op->block_size) != 0)
921b0104773SPascal Brand 			goto out;	/* Nothing left to do */
922b0104773SPascal Brand 	}
923b0104773SPascal Brand 
924b0104773SPascal Brand 	/* If we can feed from buffer */
925d3588802SPascal Brand 	if ((op->buffer_offs > 0) &&
926d3588802SPascal Brand 	    ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) {
9272ff3fdbbSPascal Brand 		l = ROUNDUP(op->buffer_offs + slen - buffer_size,
928b0104773SPascal Brand 				op->block_size);
929b0104773SPascal Brand 		l = MIN(op->buffer_offs, l);
930b0104773SPascal Brand 		tmp_dlen = dlen;
931b0104773SPascal Brand 		res = update_func(op->state, op->buffer, l, dst, &tmp_dlen);
932b0104773SPascal Brand 		if (res != TEE_SUCCESS)
933b0104773SPascal Brand 			TEE_Panic(res);
934b0104773SPascal Brand 		dst += tmp_dlen;
935b0104773SPascal Brand 		dlen -= tmp_dlen;
936b0104773SPascal Brand 		acc_dlen += tmp_dlen;
937b0104773SPascal Brand 		op->buffer_offs -= l;
938b0104773SPascal Brand 		if (op->buffer_offs > 0) {
939b0104773SPascal Brand 			/*
940b0104773SPascal Brand 			 * Slen is small enough to be contained in rest buffer.
941b0104773SPascal Brand 			 */
942b0104773SPascal Brand 			memcpy(op->buffer, op->buffer + l, buffer_size - l);
943b0104773SPascal Brand 			memcpy(op->buffer + op->buffer_offs, src, slen);
944b0104773SPascal Brand 			op->buffer_offs += slen;
945b0104773SPascal Brand 			goto out;	/* Nothing left to do */
946b0104773SPascal Brand 		}
947b0104773SPascal Brand 	}
948b0104773SPascal Brand 
949d3588802SPascal Brand 	if (slen >= (buffer_size + buffer_left)) {
950b0104773SPascal Brand 		/* Buffer is empty, feed as much as possible from src */
951bf7a587fSJerome Forissier 		if (op->info.algorithm == TEE_ALG_AES_CTS)
952b1ecda78SJerome Forissier 			l = ROUNDUP(slen - buffer_size, op->block_size);
953bf7a587fSJerome Forissier 		else
954bf7a587fSJerome Forissier 			l = ROUNDUP(slen - buffer_size + 1, op->block_size);
955b0104773SPascal Brand 
956b0104773SPascal Brand 		tmp_dlen = dlen;
957b0104773SPascal Brand 		res = update_func(op->state, src, l, dst, &tmp_dlen);
958b0104773SPascal Brand 		if (res != TEE_SUCCESS)
959b0104773SPascal Brand 			TEE_Panic(res);
960b0104773SPascal Brand 		src += l;
961b0104773SPascal Brand 		slen -= l;
962b0104773SPascal Brand 		dst += tmp_dlen;
963b0104773SPascal Brand 		dlen -= tmp_dlen;
964b0104773SPascal Brand 		acc_dlen += tmp_dlen;
965b0104773SPascal Brand 	}
966b0104773SPascal Brand 
967b0104773SPascal Brand 	/* Slen is small enough to be contained in buffer. */
968b0104773SPascal Brand 	memcpy(op->buffer + op->buffer_offs, src, slen);
969b0104773SPascal Brand 	op->buffer_offs += slen;
970b0104773SPascal Brand 
971b0104773SPascal Brand out:
972b0104773SPascal Brand 	*dest_len = acc_dlen;
973b0104773SPascal Brand 	return TEE_SUCCESS;
974b0104773SPascal Brand }
975b0104773SPascal Brand 
9768f07fe6fSJerome Forissier TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData,
97779a3c601SCedric Chaumont 			    uint32_t srcLen, void *destData, uint32_t *destLen)
978b0104773SPascal Brand {
979dea1f2b6SCedric Chaumont 	TEE_Result res;
980b0104773SPascal Brand 	size_t req_dlen;
981e86f1266SJens Wiklander 	uint64_t dl;
982b0104773SPascal Brand 
9836915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
984dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
985dea1f2b6SCedric Chaumont 		goto out;
986dea1f2b6SCedric Chaumont 	}
9876915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
988dea1f2b6SCedric Chaumont 
989642a1607SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_CIPHER) {
990dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
991dea1f2b6SCedric Chaumont 		goto out;
992dea1f2b6SCedric Chaumont 	}
993dea1f2b6SCedric Chaumont 
994642a1607SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
995642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
996642a1607SCedric Chaumont 		goto out;
997642a1607SCedric Chaumont 	}
998642a1607SCedric Chaumont 
999642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1000dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1001dea1f2b6SCedric Chaumont 		goto out;
1002dea1f2b6SCedric Chaumont 	}
1003b0104773SPascal Brand 
1004e32c5ddfSJerome Forissier 	if (!srcData && !srcLen) {
1005090268f5SJens Wiklander 		*destLen = 0;
1006e32c5ddfSJerome Forissier 		res = TEE_SUCCESS;
1007e32c5ddfSJerome Forissier 		goto out;
1008e32c5ddfSJerome Forissier 	}
1009e32c5ddfSJerome Forissier 
1010b0104773SPascal Brand 	/* Calculate required dlen */
101157aabac5SBogdan Liulko 	if (operation->block_size > 1) {
101257aabac5SBogdan Liulko 		req_dlen = ((operation->buffer_offs + srcLen) /
101357aabac5SBogdan Liulko 			    operation->block_size) * operation->block_size;
101457aabac5SBogdan Liulko 	} else {
101557aabac5SBogdan Liulko 		req_dlen = srcLen;
101657aabac5SBogdan Liulko 	}
1017642a1607SCedric Chaumont 	if (operation->buffer_two_blocks) {
1018642a1607SCedric Chaumont 		if (req_dlen > operation->block_size * 2)
1019642a1607SCedric Chaumont 			req_dlen -= operation->block_size * 2;
1020b0104773SPascal Brand 		else
1021b0104773SPascal Brand 			req_dlen = 0;
1022b0104773SPascal Brand 	}
1023b0104773SPascal Brand 	/*
1024b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1025b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1026b0104773SPascal Brand 	 * can't restore sync with this API.
1027b0104773SPascal Brand 	 */
1028b0104773SPascal Brand 	if (*destLen < req_dlen) {
1029b0104773SPascal Brand 		*destLen = req_dlen;
1030dea1f2b6SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1031dea1f2b6SCedric Chaumont 		goto out;
1032b0104773SPascal Brand 	}
1033b0104773SPascal Brand 
1034e86f1266SJens Wiklander 	dl = *destLen;
103557aabac5SBogdan Liulko 	if (operation->block_size > 1) {
10362c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_cipher_update, srcData,
103757aabac5SBogdan Liulko 					srcLen, destData, &dl);
103857aabac5SBogdan Liulko 	} else {
103957aabac5SBogdan Liulko 		if (srcLen > 0) {
10402c028fdeSJerome Forissier 			res = _utee_cipher_update(operation->state, srcData,
104157aabac5SBogdan Liulko 						  srcLen, destData, &dl);
104257aabac5SBogdan Liulko 		} else {
104357aabac5SBogdan Liulko 			res = TEE_SUCCESS;
104457aabac5SBogdan Liulko 			dl = 0;
104557aabac5SBogdan Liulko 		}
104657aabac5SBogdan Liulko 	}
1047e86f1266SJens Wiklander 	*destLen = dl;
1048b0104773SPascal Brand 
1049dea1f2b6SCedric Chaumont out:
1050dea1f2b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
1051dea1f2b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1052b36311adSJerome Forissier 		TEE_Panic(res);
1053dea1f2b6SCedric Chaumont 
1054dea1f2b6SCedric Chaumont 	return res;
1055b0104773SPascal Brand }
1056b0104773SPascal Brand 
1057642a1607SCedric Chaumont TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation,
10588f07fe6fSJerome Forissier 			     const void *srcData, uint32_t srcLen,
10598f07fe6fSJerome Forissier 			     void *destData, uint32_t *destLen)
1060b0104773SPascal Brand {
10616915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1062b0104773SPascal Brand 	uint8_t *dst = destData;
1063b0104773SPascal Brand 	size_t acc_dlen = 0;
10646915bbbbSJens Wiklander 	uint64_t tmp_dlen = 0;
10656915bbbbSJens Wiklander 	size_t req_dlen = 0;
1066b0104773SPascal Brand 
10676915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1068dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1069dea1f2b6SCedric Chaumont 		goto out;
1070dea1f2b6SCedric Chaumont 	}
10716915bbbbSJens Wiklander 	if (destLen)
10726915bbbbSJens Wiklander 		__utee_check_inout_annotation(destLen, sizeof(*destLen));
1073dea1f2b6SCedric Chaumont 
1074642a1607SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_CIPHER) {
1075dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1076dea1f2b6SCedric Chaumont 		goto out;
1077dea1f2b6SCedric Chaumont 	}
1078dea1f2b6SCedric Chaumont 
1079642a1607SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1080642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1081642a1607SCedric Chaumont 		goto out;
1082642a1607SCedric Chaumont 	}
1083642a1607SCedric Chaumont 
1084642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1085dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1086dea1f2b6SCedric Chaumont 		goto out;
1087dea1f2b6SCedric Chaumont 	}
1088b0104773SPascal Brand 
1089b0104773SPascal Brand 	/*
1090b0104773SPascal Brand 	 * Check that the final block doesn't require padding for those
1091b0104773SPascal Brand 	 * algorithms that requires client to supply padding.
1092b0104773SPascal Brand 	 */
1093642a1607SCedric Chaumont 	if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD ||
1094642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD ||
1095642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD ||
1096642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD ||
1097642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD ||
1098ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD ||
1099ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD ||
1100ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_SM4_CBC_NOPAD) {
1101642a1607SCedric Chaumont 		if (((operation->buffer_offs + srcLen) % operation->block_size)
1102642a1607SCedric Chaumont 		    != 0) {
1103dea1f2b6SCedric Chaumont 			res = TEE_ERROR_BAD_PARAMETERS;
1104dea1f2b6SCedric Chaumont 			goto out;
1105dea1f2b6SCedric Chaumont 		}
1106b0104773SPascal Brand 	}
1107b0104773SPascal Brand 
1108b0104773SPascal Brand 	/*
1109b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1110b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1111b0104773SPascal Brand 	 * can't restore sync with this API.
1112b0104773SPascal Brand 	 */
111357aabac5SBogdan Liulko 	if (operation->block_size > 1) {
1114642a1607SCedric Chaumont 		req_dlen = operation->buffer_offs + srcLen;
111557aabac5SBogdan Liulko 	} else {
111657aabac5SBogdan Liulko 		req_dlen = srcLen;
111757aabac5SBogdan Liulko 	}
11186915bbbbSJens Wiklander 	if (destLen)
11196915bbbbSJens Wiklander 		tmp_dlen = *destLen;
11206915bbbbSJens Wiklander 	if (tmp_dlen < req_dlen) {
11216915bbbbSJens Wiklander 		if (destLen)
1122b0104773SPascal Brand 			*destLen = req_dlen;
1123dea1f2b6SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1124dea1f2b6SCedric Chaumont 		goto out;
1125b0104773SPascal Brand 	}
1126b0104773SPascal Brand 
112757aabac5SBogdan Liulko 	if (operation->block_size > 1) {
1128dea9063eSJens Wiklander 		if (srcLen) {
11292c028fdeSJerome Forissier 			res = tee_buffer_update(operation, _utee_cipher_update,
1130dea9063eSJens Wiklander 						srcData, srcLen, dst,
1131dea9063eSJens Wiklander 						&tmp_dlen);
1132dea1f2b6SCedric Chaumont 			if (res != TEE_SUCCESS)
1133dea1f2b6SCedric Chaumont 				goto out;
1134dea1f2b6SCedric Chaumont 
1135b0104773SPascal Brand 			dst += tmp_dlen;
1136b0104773SPascal Brand 			acc_dlen += tmp_dlen;
1137b0104773SPascal Brand 
1138b0104773SPascal Brand 			tmp_dlen = *destLen - acc_dlen;
1139dea9063eSJens Wiklander 		}
11402c028fdeSJerome Forissier 		res = _utee_cipher_final(operation->state, operation->buffer,
11412c028fdeSJerome Forissier 					 operation->buffer_offs, dst,
11422c028fdeSJerome Forissier 					 &tmp_dlen);
114357aabac5SBogdan Liulko 	} else {
11442c028fdeSJerome Forissier 		res = _utee_cipher_final(operation->state, srcData, srcLen, dst,
11452c028fdeSJerome Forissier 					 &tmp_dlen);
114657aabac5SBogdan Liulko 	}
1147b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1148dea1f2b6SCedric Chaumont 		goto out;
1149dea1f2b6SCedric Chaumont 
1150b0104773SPascal Brand 	acc_dlen += tmp_dlen;
11516915bbbbSJens Wiklander 	if (destLen)
1152b0104773SPascal Brand 		*destLen = acc_dlen;
1153dea1f2b6SCedric Chaumont 
1154642a1607SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1155642a1607SCedric Chaumont 
1156642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1157642a1607SCedric Chaumont 
1158dea1f2b6SCedric Chaumont out:
1159dea1f2b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
1160dea1f2b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1161b36311adSJerome Forissier 		TEE_Panic(res);
1162dea1f2b6SCedric Chaumont 
1163dea1f2b6SCedric Chaumont 	return res;
1164b0104773SPascal Brand }
1165b0104773SPascal Brand 
1166b0104773SPascal Brand /* Cryptographic Operations API - MAC Functions */
1167b0104773SPascal Brand 
11688f07fe6fSJerome Forissier void TEE_MACInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen)
1169b0104773SPascal Brand {
1170b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
1171b0104773SPascal Brand 		TEE_Panic(0);
1172642a1607SCedric Chaumont 
1173b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_MAC)
1174b0104773SPascal Brand 		TEE_Panic(0);
1175642a1607SCedric Chaumont 
1176642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||
1177642a1607SCedric Chaumont 	    !(operation->key1))
1178642a1607SCedric Chaumont 		TEE_Panic(0);
1179642a1607SCedric Chaumont 
1180642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
1181642a1607SCedric Chaumont 		TEE_ResetOperation(operation);
1182642a1607SCedric Chaumont 
1183642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1184642a1607SCedric Chaumont 
11856d15db08SJerome Forissier 	init_hash_operation(operation, IV, IVLen);
1186b0104773SPascal Brand }
1187b0104773SPascal Brand 
11888f07fe6fSJerome Forissier void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk,
118928e0efc6SCedric Chaumont 		   uint32_t chunkSize)
1190b0104773SPascal Brand {
1191b0104773SPascal Brand 	TEE_Result res;
1192b0104773SPascal Brand 
119328e0efc6SCedric Chaumont 	if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0))
1194b0104773SPascal Brand 		TEE_Panic(0);
1195642a1607SCedric Chaumont 
119628e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC)
1197b0104773SPascal Brand 		TEE_Panic(0);
1198642a1607SCedric Chaumont 
119928e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1200b0104773SPascal Brand 		TEE_Panic(0);
1201b0104773SPascal Brand 
1202642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE)
1203642a1607SCedric Chaumont 		TEE_Panic(0);
1204642a1607SCedric Chaumont 
12052c028fdeSJerome Forissier 	res = _utee_hash_update(operation->state, chunk, chunkSize);
1206b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1207b0104773SPascal Brand 		TEE_Panic(res);
1208b0104773SPascal Brand }
1209b0104773SPascal Brand 
121028e0efc6SCedric Chaumont TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation,
12118f07fe6fSJerome Forissier 			       const void *message, uint32_t messageLen,
121279a3c601SCedric Chaumont 			       void *mac, uint32_t *macLen)
1213b0104773SPascal Brand {
1214b0104773SPascal Brand 	TEE_Result res;
1215e86f1266SJens Wiklander 	uint64_t ml;
1216b0104773SPascal Brand 
12176915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!message && messageLen)) {
121828e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
121928e0efc6SCedric Chaumont 		goto out;
122028e0efc6SCedric Chaumont 	}
12216915bbbbSJens Wiklander 	__utee_check_inout_annotation(macLen, sizeof(*macLen));
1222b0104773SPascal Brand 
122328e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC) {
122428e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
122528e0efc6SCedric Chaumont 		goto out;
122628e0efc6SCedric Chaumont 	}
122728e0efc6SCedric Chaumont 
122828e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
122928e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
123028e0efc6SCedric Chaumont 		goto out;
123128e0efc6SCedric Chaumont 	}
123228e0efc6SCedric Chaumont 
1233642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1234642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1235642a1607SCedric Chaumont 		goto out;
1236642a1607SCedric Chaumont 	}
1237642a1607SCedric Chaumont 
1238e86f1266SJens Wiklander 	ml = *macLen;
12392c028fdeSJerome Forissier 	res = _utee_hash_final(operation->state, message, messageLen, mac, &ml);
1240e86f1266SJens Wiklander 	*macLen = ml;
124128e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS)
124228e0efc6SCedric Chaumont 		goto out;
124328e0efc6SCedric Chaumont 
124428e0efc6SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
124528e0efc6SCedric Chaumont 
1246642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1247642a1607SCedric Chaumont 
124828e0efc6SCedric Chaumont out:
124928e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS &&
125028e0efc6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
125128e0efc6SCedric Chaumont 		TEE_Panic(res);
125228e0efc6SCedric Chaumont 
1253b0104773SPascal Brand 	return res;
1254b0104773SPascal Brand }
1255b0104773SPascal Brand 
1256b0104773SPascal Brand TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation,
12578f07fe6fSJerome Forissier 			       const void *message, uint32_t messageLen,
12588f07fe6fSJerome Forissier 			       const void *mac, uint32_t macLen)
1259b0104773SPascal Brand {
1260b0104773SPascal Brand 	TEE_Result res;
1261ee4ba3d1SVictor Chong 	uint8_t computed_mac[TEE_MAX_HASH_SIZE] = { 0 };
12627f74c64aSPascal Brand 	uint32_t computed_mac_size = TEE_MAX_HASH_SIZE;
1263b0104773SPascal Brand 
126428e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC) {
126528e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
126628e0efc6SCedric Chaumont 		goto out;
126728e0efc6SCedric Chaumont 	}
126828e0efc6SCedric Chaumont 
126928e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
127028e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
127128e0efc6SCedric Chaumont 		goto out;
127228e0efc6SCedric Chaumont 	}
127328e0efc6SCedric Chaumont 
1274642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1275642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1276642a1607SCedric Chaumont 		goto out;
1277642a1607SCedric Chaumont 	}
1278642a1607SCedric Chaumont 
1279b0104773SPascal Brand 	res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac,
1280b0104773SPascal Brand 				  &computed_mac_size);
1281b0104773SPascal Brand 	if (res != TEE_SUCCESS)
128228e0efc6SCedric Chaumont 		goto out;
128328e0efc6SCedric Chaumont 
128428e0efc6SCedric Chaumont 	if (computed_mac_size != macLen) {
128528e0efc6SCedric Chaumont 		res = TEE_ERROR_MAC_INVALID;
128628e0efc6SCedric Chaumont 		goto out;
128728e0efc6SCedric Chaumont 	}
128828e0efc6SCedric Chaumont 
128948e10604SJerome Forissier 	if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) {
129028e0efc6SCedric Chaumont 		res = TEE_ERROR_MAC_INVALID;
129128e0efc6SCedric Chaumont 		goto out;
129228e0efc6SCedric Chaumont 	}
129328e0efc6SCedric Chaumont 
1294642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1295642a1607SCedric Chaumont 
129628e0efc6SCedric Chaumont out:
129728e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS &&
129828e0efc6SCedric Chaumont 	    res != TEE_ERROR_MAC_INVALID)
129928e0efc6SCedric Chaumont 		TEE_Panic(res);
130028e0efc6SCedric Chaumont 
1301b0104773SPascal Brand 	return res;
1302b0104773SPascal Brand }
1303b0104773SPascal Brand 
1304b0104773SPascal Brand /* Cryptographic Operations API - Authenticated Encryption Functions */
1305b0104773SPascal Brand 
13068f07fe6fSJerome Forissier TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce,
130779a3c601SCedric Chaumont 		      uint32_t nonceLen, uint32_t tagLen, uint32_t AADLen,
1308b0104773SPascal Brand 		      uint32_t payloadLen)
1309b0104773SPascal Brand {
1310b0104773SPascal Brand 	TEE_Result res;
1311b0104773SPascal Brand 
1312b5816c88SCedric Chaumont 	if (operation == TEE_HANDLE_NULL || nonce == NULL) {
1313b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1314b5816c88SCedric Chaumont 		goto out;
1315b5816c88SCedric Chaumont 	}
1316b5816c88SCedric Chaumont 
1317b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1318b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1319b5816c88SCedric Chaumont 		goto out;
1320b5816c88SCedric Chaumont 	}
1321b0104773SPascal Brand 
1322642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
1323642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1324642a1607SCedric Chaumont 		goto out;
1325642a1607SCedric Chaumont 	}
1326642a1607SCedric Chaumont 
1327b0104773SPascal Brand 	/*
1328b0104773SPascal Brand 	 * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core
1329b0104773SPascal Brand 	 * in the implementation. But AES-GCM spec doesn't specify the tag len
1330b0104773SPascal Brand 	 * according to the same principle so we have to check here instead to
1331b0104773SPascal Brand 	 * be GP compliant.
1332b0104773SPascal Brand 	 */
1333b5816c88SCedric Chaumont 	if (operation->info.algorithm == TEE_ALG_AES_GCM) {
1334b0104773SPascal Brand 		/*
1335b0104773SPascal Brand 		 * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96
1336b0104773SPascal Brand 		 */
1337b5816c88SCedric Chaumont 		if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) {
1338b5816c88SCedric Chaumont 			res = TEE_ERROR_NOT_SUPPORTED;
1339b5816c88SCedric Chaumont 			goto out;
1340b5816c88SCedric Chaumont 		}
1341b0104773SPascal Brand 	}
1342b0104773SPascal Brand 
13432c028fdeSJerome Forissier 	res = _utee_authenc_init(operation->state, nonce, nonceLen, tagLen / 8,
13442c028fdeSJerome Forissier 				 AADLen, payloadLen);
1345b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS)
1346b5816c88SCedric Chaumont 		goto out;
1347b5816c88SCedric Chaumont 
13487acaf5adSAlbert Schwarzkopf 	operation->info.digestLength = tagLen / 8;
1349f2674567SSumit Garg 	operation->buffer_offs = 0;
1350b5816c88SCedric Chaumont 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
1351b5816c88SCedric Chaumont 
1352b5816c88SCedric Chaumont out:
1353b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1354b5816c88SCedric Chaumont 	    res != TEE_ERROR_NOT_SUPPORTED)
1355b0104773SPascal Brand 			TEE_Panic(res);
1356b5816c88SCedric Chaumont 
1357b0104773SPascal Brand 	return res;
1358b0104773SPascal Brand }
1359b0104773SPascal Brand 
13608f07fe6fSJerome Forissier void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata,
136179a3c601SCedric Chaumont 		     uint32_t AADdataLen)
1362b0104773SPascal Brand {
1363b0104773SPascal Brand 	TEE_Result res;
1364b0104773SPascal Brand 
1365b5816c88SCedric Chaumont 	if (operation == TEE_HANDLE_NULL ||
1366b5816c88SCedric Chaumont 	    (AADdata == NULL && AADdataLen != 0))
1367b0104773SPascal Brand 		TEE_Panic(0);
1368642a1607SCedric Chaumont 
1369b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE)
1370b0104773SPascal Brand 		TEE_Panic(0);
1371642a1607SCedric Chaumont 
1372b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1373b0104773SPascal Brand 		TEE_Panic(0);
1374b0104773SPascal Brand 
13752c028fdeSJerome Forissier 	res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen);
1376642a1607SCedric Chaumont 
1377642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1378642a1607SCedric Chaumont 
1379b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1380b0104773SPascal Brand 		TEE_Panic(res);
1381b0104773SPascal Brand }
1382b0104773SPascal Brand 
13838f07fe6fSJerome Forissier TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData,
138479a3c601SCedric Chaumont 			uint32_t srcLen, void *destData, uint32_t *destLen)
1385b0104773SPascal Brand {
13866915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
13876915bbbbSJens Wiklander 	size_t req_dlen = 0;
13886915bbbbSJens Wiklander 	uint64_t dl = 0;
1389b0104773SPascal Brand 
13906915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1391b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1392b5816c88SCedric Chaumont 		goto out;
1393b5816c88SCedric Chaumont 	}
13946915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1395b5816c88SCedric Chaumont 
1396b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1397b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1398b5816c88SCedric Chaumont 		goto out;
1399b5816c88SCedric Chaumont 	}
1400b5816c88SCedric Chaumont 
1401b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1402b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1403b5816c88SCedric Chaumont 		goto out;
1404b5816c88SCedric Chaumont 	}
1405b0104773SPascal Brand 
1406827308b8SJerome Forissier 	if (!srcData && !srcLen) {
1407090268f5SJens Wiklander 		*destLen = 0;
1408827308b8SJerome Forissier 		res = TEE_SUCCESS;
1409827308b8SJerome Forissier 		goto out;
1410827308b8SJerome Forissier 	}
1411827308b8SJerome Forissier 
1412b0104773SPascal Brand 	/*
1413b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1414b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1415b0104773SPascal Brand 	 * can't restore sync with this API.
1416b0104773SPascal Brand 	 */
1417afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
1418b5816c88SCedric Chaumont 		req_dlen = ROUNDDOWN(operation->buffer_offs + srcLen,
1419b5816c88SCedric Chaumont 				     operation->block_size);
1420afc0c182SBogdan Liulko 	} else {
1421afc0c182SBogdan Liulko 		req_dlen = srcLen;
1422afc0c182SBogdan Liulko 	}
1423afc0c182SBogdan Liulko 
14246915bbbbSJens Wiklander 	dl = *destLen;
14256915bbbbSJens Wiklander 	if (dl < req_dlen) {
1426b0104773SPascal Brand 		*destLen = req_dlen;
1427b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1428b5816c88SCedric Chaumont 		goto out;
1429b0104773SPascal Brand 	}
1430b0104773SPascal Brand 
1431afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
14322c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1433afc0c182SBogdan Liulko 					srcData, srcLen, destData, &dl);
1434afc0c182SBogdan Liulko 	} else {
1435afc0c182SBogdan Liulko 		if (srcLen > 0) {
14362c028fdeSJerome Forissier 			res = _utee_authenc_update_payload(operation->state,
1437afc0c182SBogdan Liulko 							   srcData, srcLen,
1438afc0c182SBogdan Liulko 							   destData, &dl);
1439afc0c182SBogdan Liulko 		} else {
1440afc0c182SBogdan Liulko 			dl = 0;
1441afc0c182SBogdan Liulko 			res = TEE_SUCCESS;
1442afc0c182SBogdan Liulko 		}
1443afc0c182SBogdan Liulko 	}
1444afc0c182SBogdan Liulko 	if (res != TEE_SUCCESS)
1445afc0c182SBogdan Liulko 		goto out;
1446afc0c182SBogdan Liulko 
1447e86f1266SJens Wiklander 	*destLen = dl;
1448b0104773SPascal Brand 
1449642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1450642a1607SCedric Chaumont 
1451b5816c88SCedric Chaumont out:
1452b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1453b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1454b5816c88SCedric Chaumont 			TEE_Panic(res);
1455b5816c88SCedric Chaumont 
1456b5816c88SCedric Chaumont 	return res;
1457b0104773SPascal Brand }
1458b0104773SPascal Brand 
1459b5816c88SCedric Chaumont TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation,
14608f07fe6fSJerome Forissier 			      const void *srcData, uint32_t srcLen,
146179a3c601SCedric Chaumont 			      void *destData, uint32_t *destLen, void *tag,
146279a3c601SCedric Chaumont 			      uint32_t *tagLen)
1463b0104773SPascal Brand {
1464b0104773SPascal Brand 	TEE_Result res;
1465b0104773SPascal Brand 	uint8_t *dst = destData;
1466b0104773SPascal Brand 	size_t acc_dlen = 0;
1467e86f1266SJens Wiklander 	uint64_t tmp_dlen;
1468b0104773SPascal Brand 	size_t req_dlen;
1469e86f1266SJens Wiklander 	uint64_t tl;
1470b0104773SPascal Brand 
14716915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1472b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1473b5816c88SCedric Chaumont 		goto out;
1474b5816c88SCedric Chaumont 	}
14756915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
14766915bbbbSJens Wiklander 	__utee_check_inout_annotation(tagLen, sizeof(*tagLen));
1477b5816c88SCedric Chaumont 
1478b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1479b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1480b5816c88SCedric Chaumont 		goto out;
1481b5816c88SCedric Chaumont 	}
1482b5816c88SCedric Chaumont 
1483b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1484b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1485b5816c88SCedric Chaumont 		goto out;
1486b5816c88SCedric Chaumont 	}
1487b0104773SPascal Brand 
1488b0104773SPascal Brand 	/*
1489b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1490b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1491b0104773SPascal Brand 	 * can't restore sync with this API.
14922733280aSEtienne Carriere 	 *
14932733280aSEtienne Carriere 	 * Need to check this before update_payload since sync would be lost if
14942733280aSEtienne Carriere 	 * we return short buffer after that.
1495b0104773SPascal Brand 	 */
14962733280aSEtienne Carriere 	res = TEE_ERROR_GENERIC;
14972733280aSEtienne Carriere 
1498b5816c88SCedric Chaumont 	req_dlen = operation->buffer_offs + srcLen;
1499b0104773SPascal Brand 	if (*destLen < req_dlen) {
1500b0104773SPascal Brand 		*destLen = req_dlen;
1501b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1502b0104773SPascal Brand 	}
1503b0104773SPascal Brand 
15047acaf5adSAlbert Schwarzkopf 	if (*tagLen < operation->info.digestLength) {
15057acaf5adSAlbert Schwarzkopf 		*tagLen = operation->info.digestLength;
1506b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1507b0104773SPascal Brand 	}
1508b0104773SPascal Brand 
15092733280aSEtienne Carriere 	if (res == TEE_ERROR_SHORT_BUFFER)
15102733280aSEtienne Carriere 		goto out;
15112733280aSEtienne Carriere 
1512afc0c182SBogdan Liulko 	tl = *tagLen;
1513b0104773SPascal Brand 	tmp_dlen = *destLen - acc_dlen;
1514afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
15152c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1516afc0c182SBogdan Liulko 					srcData, srcLen, dst, &tmp_dlen);
1517b5816c88SCedric Chaumont 		if (res != TEE_SUCCESS)
1518b5816c88SCedric Chaumont 			goto out;
1519b5816c88SCedric Chaumont 
1520b0104773SPascal Brand 		dst += tmp_dlen;
1521b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1522b0104773SPascal Brand 
1523b0104773SPascal Brand 		tmp_dlen = *destLen - acc_dlen;
15242c028fdeSJerome Forissier 		res = _utee_authenc_enc_final(operation->state,
1525afc0c182SBogdan Liulko 					      operation->buffer,
1526afc0c182SBogdan Liulko 					      operation->buffer_offs, dst,
1527afc0c182SBogdan Liulko 					      &tmp_dlen, tag, &tl);
1528afc0c182SBogdan Liulko 	} else {
15292c028fdeSJerome Forissier 		res = _utee_authenc_enc_final(operation->state, srcData,
1530afc0c182SBogdan Liulko 					      srcLen, dst, &tmp_dlen,
1531e86f1266SJens Wiklander 					      tag, &tl);
1532afc0c182SBogdan Liulko 	}
1533e86f1266SJens Wiklander 	*tagLen = tl;
1534b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1535b5816c88SCedric Chaumont 		goto out;
1536b0104773SPascal Brand 
1537b5816c88SCedric Chaumont 	acc_dlen += tmp_dlen;
1538b0104773SPascal Brand 	*destLen = acc_dlen;
1539642a1607SCedric Chaumont 
1540b5816c88SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1541b5816c88SCedric Chaumont 
1542642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1543642a1607SCedric Chaumont 
1544b5816c88SCedric Chaumont out:
1545b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1546b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1547b5816c88SCedric Chaumont 			TEE_Panic(res);
1548b0104773SPascal Brand 
1549b0104773SPascal Brand 	return res;
1550b0104773SPascal Brand }
1551b0104773SPascal Brand 
1552b5816c88SCedric Chaumont TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation,
15538f07fe6fSJerome Forissier 			      const void *srcData, uint32_t srcLen,
1554b5816c88SCedric Chaumont 			      void *destData, uint32_t *destLen, void *tag,
155579a3c601SCedric Chaumont 			      uint32_t tagLen)
1556b0104773SPascal Brand {
1557b0104773SPascal Brand 	TEE_Result res;
1558b0104773SPascal Brand 	uint8_t *dst = destData;
1559b0104773SPascal Brand 	size_t acc_dlen = 0;
1560e86f1266SJens Wiklander 	uint64_t tmp_dlen;
1561b0104773SPascal Brand 	size_t req_dlen;
1562b0104773SPascal Brand 
15636915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1564b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1565b5816c88SCedric Chaumont 		goto out;
1566b5816c88SCedric Chaumont 	}
15676915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1568b5816c88SCedric Chaumont 
1569b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1570b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1571b5816c88SCedric Chaumont 		goto out;
1572b5816c88SCedric Chaumont 	}
1573b5816c88SCedric Chaumont 
1574b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1575b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1576b5816c88SCedric Chaumont 		goto out;
1577b5816c88SCedric Chaumont 	}
1578b0104773SPascal Brand 
1579b0104773SPascal Brand 	/*
1580b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1581b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1582b0104773SPascal Brand 	 * can't restore sync with this API.
1583b0104773SPascal Brand 	 */
1584b5816c88SCedric Chaumont 	req_dlen = operation->buffer_offs + srcLen;
1585b0104773SPascal Brand 	if (*destLen < req_dlen) {
1586b0104773SPascal Brand 		*destLen = req_dlen;
1587b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1588b5816c88SCedric Chaumont 		goto out;
1589b0104773SPascal Brand 	}
1590b0104773SPascal Brand 
1591b0104773SPascal Brand 	tmp_dlen = *destLen - acc_dlen;
1592afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
15932c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1594afc0c182SBogdan Liulko 					srcData, srcLen, dst, &tmp_dlen);
1595b5816c88SCedric Chaumont 		if (res != TEE_SUCCESS)
1596b5816c88SCedric Chaumont 			goto out;
1597b5816c88SCedric Chaumont 
1598b0104773SPascal Brand 		dst += tmp_dlen;
1599b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1600b0104773SPascal Brand 
1601b0104773SPascal Brand 		tmp_dlen = *destLen - acc_dlen;
16022c028fdeSJerome Forissier 		res = _utee_authenc_dec_final(operation->state,
1603afc0c182SBogdan Liulko 					      operation->buffer,
1604afc0c182SBogdan Liulko 					      operation->buffer_offs, dst,
1605afc0c182SBogdan Liulko 					      &tmp_dlen, tag, tagLen);
1606afc0c182SBogdan Liulko 	} else {
16072c028fdeSJerome Forissier 		res = _utee_authenc_dec_final(operation->state, srcData,
1608afc0c182SBogdan Liulko 					      srcLen, dst, &tmp_dlen,
1609b5816c88SCedric Chaumont 					      tag, tagLen);
1610afc0c182SBogdan Liulko 	}
1611b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS)
1612b5816c88SCedric Chaumont 		goto out;
1613b5816c88SCedric Chaumont 
1614b0104773SPascal Brand 	/* Supplied tagLen should match what we initiated with */
16157acaf5adSAlbert Schwarzkopf 	if (tagLen != operation->info.digestLength)
1616b0104773SPascal Brand 		res = TEE_ERROR_MAC_INVALID;
1617b0104773SPascal Brand 
1618b0104773SPascal Brand 	acc_dlen += tmp_dlen;
1619b0104773SPascal Brand 	*destLen = acc_dlen;
1620642a1607SCedric Chaumont 
1621b5816c88SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1622b5816c88SCedric Chaumont 
1623642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1624642a1607SCedric Chaumont 
1625b5816c88SCedric Chaumont out:
1626b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1627b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER &&
1628b5816c88SCedric Chaumont 	    res != TEE_ERROR_MAC_INVALID)
1629b5816c88SCedric Chaumont 			TEE_Panic(res);
1630b0104773SPascal Brand 
1631b0104773SPascal Brand 	return res;
1632b0104773SPascal Brand }
1633b0104773SPascal Brand 
1634b0104773SPascal Brand /* Cryptographic Operations API - Asymmetric Functions */
1635b0104773SPascal Brand 
163612e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation,
16378f07fe6fSJerome Forissier 				 const TEE_Attribute *params,
16388f07fe6fSJerome Forissier 				 uint32_t paramCount, const void *srcData,
163979a3c601SCedric Chaumont 				 uint32_t srcLen, void *destData,
164079a3c601SCedric Chaumont 				 uint32_t *destLen)
1641b0104773SPascal Brand {
16426915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1643e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
16446915bbbbSJens Wiklander 	uint64_t dl = 0;
1645b0104773SPascal Brand 
16466915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
1647b0104773SPascal Brand 		TEE_Panic(0);
16486915bbbbSJens Wiklander 
16496915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
16506915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
16516915bbbbSJens Wiklander 
165212e66b6fSCedric Chaumont 	if (!operation->key1)
1653b0104773SPascal Brand 		TEE_Panic(0);
165412e66b6fSCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
165512e66b6fSCedric Chaumont 		TEE_Panic(0);
165612e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_ENCRYPT)
1657b0104773SPascal Brand 		TEE_Panic(0);
1658b0104773SPascal Brand 
1659e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
1660e86f1266SJens Wiklander 	dl = *destLen;
16612c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
1662e86f1266SJens Wiklander 				  srcLen, destData, &dl);
1663e86f1266SJens Wiklander 	*destLen = dl;
166412e66b6fSCedric Chaumont 
16658844ebfcSPascal Brand 	if (res != TEE_SUCCESS &&
16668844ebfcSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER &&
16678844ebfcSPascal Brand 	    res != TEE_ERROR_BAD_PARAMETERS)
1668b0104773SPascal Brand 		TEE_Panic(res);
166912e66b6fSCedric Chaumont 
1670b0104773SPascal Brand 	return res;
1671b0104773SPascal Brand }
1672b0104773SPascal Brand 
167312e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation,
16748f07fe6fSJerome Forissier 				 const TEE_Attribute *params,
16758f07fe6fSJerome Forissier 				 uint32_t paramCount, const void *srcData,
167679a3c601SCedric Chaumont 				 uint32_t srcLen, void *destData,
167779a3c601SCedric Chaumont 				 uint32_t *destLen)
1678b0104773SPascal Brand {
16796915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1680e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
16816915bbbbSJens Wiklander 	uint64_t dl = 0;
1682b0104773SPascal Brand 
16836915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
1684b0104773SPascal Brand 		TEE_Panic(0);
16856915bbbbSJens Wiklander 
16866915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
16876915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
16886915bbbbSJens Wiklander 
168912e66b6fSCedric Chaumont 	if (!operation->key1)
1690b0104773SPascal Brand 		TEE_Panic(0);
169112e66b6fSCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
169212e66b6fSCedric Chaumont 		TEE_Panic(0);
169312e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_DECRYPT)
1694b0104773SPascal Brand 		TEE_Panic(0);
1695b0104773SPascal Brand 
1696e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
1697e86f1266SJens Wiklander 	dl = *destLen;
16982c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
1699e86f1266SJens Wiklander 				  srcLen, destData, &dl);
1700e86f1266SJens Wiklander 	*destLen = dl;
170112e66b6fSCedric Chaumont 
17028844ebfcSPascal Brand 	if (res != TEE_SUCCESS &&
17038844ebfcSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER &&
17048844ebfcSPascal Brand 	    res != TEE_ERROR_BAD_PARAMETERS)
1705b0104773SPascal Brand 		TEE_Panic(res);
170612e66b6fSCedric Chaumont 
1707b0104773SPascal Brand 	return res;
1708b0104773SPascal Brand }
1709b0104773SPascal Brand 
171012e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation,
17118f07fe6fSJerome Forissier 				    const TEE_Attribute *params,
17128f07fe6fSJerome Forissier 				    uint32_t paramCount, const void *digest,
171379a3c601SCedric Chaumont 				    uint32_t digestLen, void *signature,
171479a3c601SCedric Chaumont 				    uint32_t *signatureLen)
1715b0104773SPascal Brand {
17166915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1717e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
17186915bbbbSJens Wiklander 	uint64_t sl = 0;
1719b0104773SPascal Brand 
17206915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen))
1721b0104773SPascal Brand 		TEE_Panic(0);
17226915bbbbSJens Wiklander 
17236915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
17246915bbbbSJens Wiklander 	__utee_check_inout_annotation(signatureLen, sizeof(*signatureLen));
17256915bbbbSJens Wiklander 
172612e66b6fSCedric Chaumont 	if (!operation->key1)
1727b0104773SPascal Brand 		TEE_Panic(0);
172812e66b6fSCedric Chaumont 	if (operation->info.operationClass !=
172912e66b6fSCedric Chaumont 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
173012e66b6fSCedric Chaumont 		TEE_Panic(0);
173112e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_SIGN)
1732b0104773SPascal Brand 		TEE_Panic(0);
1733b0104773SPascal Brand 
1734e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
1735e86f1266SJens Wiklander 	sl = *signatureLen;
17362c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, digest,
1737e86f1266SJens Wiklander 				  digestLen, signature, &sl);
1738e86f1266SJens Wiklander 	*signatureLen = sl;
173912e66b6fSCedric Chaumont 
1740b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)
1741b0104773SPascal Brand 		TEE_Panic(res);
174212e66b6fSCedric Chaumont 
1743b0104773SPascal Brand 	return res;
1744b0104773SPascal Brand }
1745b0104773SPascal Brand 
174612e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation,
17478f07fe6fSJerome Forissier 				      const TEE_Attribute *params,
17488f07fe6fSJerome Forissier 				      uint32_t paramCount, const void *digest,
17498f07fe6fSJerome Forissier 				      uint32_t digestLen,
17508f07fe6fSJerome Forissier 				      const void *signature,
175179a3c601SCedric Chaumont 				      uint32_t signatureLen)
1752b0104773SPascal Brand {
1753b0104773SPascal Brand 	TEE_Result res;
1754e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
1755b0104773SPascal Brand 
175612e66b6fSCedric Chaumont 	if (operation == TEE_HANDLE_NULL ||
175712e66b6fSCedric Chaumont 	    (digest == NULL && digestLen != 0) ||
1758b0104773SPascal Brand 	    (signature == NULL && signatureLen != 0))
1759b0104773SPascal Brand 		TEE_Panic(0);
17606915bbbbSJens Wiklander 
17616915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
17626915bbbbSJens Wiklander 
176312e66b6fSCedric Chaumont 	if (!operation->key1)
1764b0104773SPascal Brand 		TEE_Panic(0);
176512e66b6fSCedric Chaumont 	if (operation->info.operationClass !=
176612e66b6fSCedric Chaumont 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
176712e66b6fSCedric Chaumont 		TEE_Panic(0);
176812e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_VERIFY)
1769b0104773SPascal Brand 		TEE_Panic(0);
1770b0104773SPascal Brand 
1771e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
17722c028fdeSJerome Forissier 	res = _utee_asymm_verify(operation->state, ua, paramCount, digest,
177312e66b6fSCedric Chaumont 				 digestLen, signature, signatureLen);
177412e66b6fSCedric Chaumont 
1775b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID)
1776b0104773SPascal Brand 		TEE_Panic(res);
177712e66b6fSCedric Chaumont 
1778b0104773SPascal Brand 	return res;
1779b0104773SPascal Brand }
1780b0104773SPascal Brand 
1781b0104773SPascal Brand /* Cryptographic Operations API - Key Derivation Functions */
1782b0104773SPascal Brand 
1783b0104773SPascal Brand void TEE_DeriveKey(TEE_OperationHandle operation,
1784b0104773SPascal Brand 		   const TEE_Attribute *params, uint32_t paramCount,
1785b0104773SPascal Brand 		   TEE_ObjectHandle derivedKey)
1786b0104773SPascal Brand {
1787e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
178875d6a373SJens Wiklander 	struct utee_object_info key_info = { };
178975d6a373SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1790b0104773SPascal Brand 
1791b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL || derivedKey == 0)
1792b0104773SPascal Brand 		TEE_Panic(0);
17936915bbbbSJens Wiklander 
17946915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
17956915bbbbSJens Wiklander 
17968854d3c6SJerome Forissier 	if (TEE_ALG_GET_CLASS(operation->info.algorithm) !=
17978854d3c6SJerome Forissier 	    TEE_OPERATION_KEY_DERIVATION)
1798b0104773SPascal Brand 		TEE_Panic(0);
1799b0104773SPascal Brand 
1800b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION)
1801b0104773SPascal Brand 		TEE_Panic(0);
180284fa9467SCedric Chaumont 	if (!operation->key1)
180384fa9467SCedric Chaumont 		TEE_Panic(0);
1804b0104773SPascal Brand 	if (operation->info.mode != TEE_MODE_DERIVE)
1805b0104773SPascal Brand 		TEE_Panic(0);
1806b0104773SPascal Brand 	if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0)
1807b0104773SPascal Brand 		TEE_Panic(0);
1808b0104773SPascal Brand 
18092c028fdeSJerome Forissier 	res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info);
1810b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1811b36311adSJerome Forissier 		TEE_Panic(res);
1812b0104773SPascal Brand 
181375d6a373SJens Wiklander 	if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET)
1814b0104773SPascal Brand 		TEE_Panic(0);
181575d6a373SJens Wiklander 	if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
1816b0104773SPascal Brand 		TEE_Panic(0);
1817b0104773SPascal Brand 
1818e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
18192c028fdeSJerome Forissier 	res = _utee_cryp_derive_key(operation->state, ua, paramCount,
1820e86f1266SJens Wiklander 				    (unsigned long)derivedKey);
1821b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1822b0104773SPascal Brand 		TEE_Panic(res);
1823b0104773SPascal Brand }
1824b0104773SPascal Brand 
1825b0104773SPascal Brand /* Cryptographic Operations API - Random Number Generation Functions */
1826b0104773SPascal Brand 
182779a3c601SCedric Chaumont void TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen)
1828b0104773SPascal Brand {
1829b0104773SPascal Brand 	TEE_Result res;
1830b0104773SPascal Brand 
18312c028fdeSJerome Forissier 	res = _utee_cryp_random_number_generate(randomBuffer, randomBufferLen);
1832b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1833b0104773SPascal Brand 		TEE_Panic(res);
1834b0104773SPascal Brand }
1835433c4257SJens Wiklander 
1836433c4257SJens Wiklander int rand(void)
1837433c4257SJens Wiklander {
1838433c4257SJens Wiklander 	int rc;
1839433c4257SJens Wiklander 
1840433c4257SJens Wiklander 	TEE_GenerateRandom(&rc, sizeof(rc));
1841433c4257SJens Wiklander 
1842433c4257SJens Wiklander 	/*
1843433c4257SJens Wiklander 	 * RAND_MAX is the larges int, INT_MAX which is all bits but the
1844433c4257SJens Wiklander 	 * highest bit set.
1845433c4257SJens Wiklander 	 */
1846433c4257SJens Wiklander 	return rc & RAND_MAX;
1847433c4257SJens Wiklander }
184879170ce0SJerome Forissier 
184979170ce0SJerome Forissier TEE_Result TEE_IsAlgorithmSupported(uint32_t alg, uint32_t element)
185079170ce0SJerome Forissier {
185179170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_AES)) {
185279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
185379170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_ECB_NOPAD)
185479170ce0SJerome Forissier 				goto check_element_none;
185579170ce0SJerome Forissier 		}
185679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
185779170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CBC_NOPAD)
185879170ce0SJerome Forissier 				goto check_element_none;
185979170ce0SJerome Forissier 		}
186079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTR)) {
186179170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CTR)
186279170ce0SJerome Forissier 				goto check_element_none;
186379170ce0SJerome Forissier 		}
186479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTS)) {
186579170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CTS)
186679170ce0SJerome Forissier 				goto check_element_none;
186779170ce0SJerome Forissier 		}
186879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_XTS)) {
186979170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_XTS)
187079170ce0SJerome Forissier 				goto check_element_none;
187179170ce0SJerome Forissier 		}
187279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) {
187379170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CBC_MAC_NOPAD ||
187479170ce0SJerome Forissier 			    alg == TEE_ALG_AES_CBC_MAC_PKCS5)
187579170ce0SJerome Forissier 				goto check_element_none;
187679170ce0SJerome Forissier 		}
187779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CMAC)) {
187879170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CMAC)
187979170ce0SJerome Forissier 				goto check_element_none;
188079170ce0SJerome Forissier 		}
188179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CCM)) {
188279170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CCM)
188379170ce0SJerome Forissier 				goto check_element_none;
188479170ce0SJerome Forissier 		}
188579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_GCM)) {
188679170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_GCM)
188779170ce0SJerome Forissier 				goto check_element_none;
188879170ce0SJerome Forissier 		}
188979170ce0SJerome Forissier 	}
189079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DES)) {
189179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
189279170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_ECB_NOPAD ||
189379170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_ECB_NOPAD)
189479170ce0SJerome Forissier 				goto check_element_none;
189579170ce0SJerome Forissier 		}
189679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
189779170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_CBC_NOPAD ||
189879170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_NOPAD)
189979170ce0SJerome Forissier 				goto check_element_none;
190079170ce0SJerome Forissier 		}
190179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) {
190279170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_CBC_MAC_NOPAD ||
190379170ce0SJerome Forissier 			    alg == TEE_ALG_DES_CBC_MAC_PKCS5 ||
190479170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_MAC_NOPAD ||
190579170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_MAC_PKCS5)
190679170ce0SJerome Forissier 				goto check_element_none;
190779170ce0SJerome Forissier 		}
190879170ce0SJerome Forissier 	}
190979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_MD5)) {
191079170ce0SJerome Forissier 		if (alg == TEE_ALG_MD5)
191179170ce0SJerome Forissier 			goto check_element_none;
191279170ce0SJerome Forissier 	}
191379170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
191479170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA1)
191579170ce0SJerome Forissier 			goto check_element_none;
191679170ce0SJerome Forissier 	}
191779170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
191879170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA224)
191979170ce0SJerome Forissier 			goto check_element_none;
192079170ce0SJerome Forissier 	}
192179170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
192279170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA256)
192379170ce0SJerome Forissier 			goto check_element_none;
192479170ce0SJerome Forissier 	}
192579170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
192679170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA384)
192779170ce0SJerome Forissier 			goto check_element_none;
192879170ce0SJerome Forissier 	}
192979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
193079170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA512)
193179170ce0SJerome Forissier 			goto check_element_none;
193279170ce0SJerome Forissier 	}
193379170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) {
193479170ce0SJerome Forissier 		if (alg == TEE_ALG_MD5SHA1)
193579170ce0SJerome Forissier 			goto check_element_none;
193679170ce0SJerome Forissier 	}
193779170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_HMAC)) {
193879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5)) {
193979170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_MD5)
194079170ce0SJerome Forissier 				goto check_element_none;
194179170ce0SJerome Forissier 		}
194279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
194379170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA1)
194479170ce0SJerome Forissier 				goto check_element_none;
194579170ce0SJerome Forissier 		}
194679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
194779170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA224)
194879170ce0SJerome Forissier 				goto check_element_none;
194979170ce0SJerome Forissier 		}
195079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
195179170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA256)
195279170ce0SJerome Forissier 				goto check_element_none;
195379170ce0SJerome Forissier 		}
195479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
195579170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA384)
195679170ce0SJerome Forissier 				goto check_element_none;
195779170ce0SJerome Forissier 		}
195879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
195979170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA512)
196079170ce0SJerome Forissier 				goto check_element_none;
196179170ce0SJerome Forissier 		}
196279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SM3)) {
196379170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SM3)
196479170ce0SJerome Forissier 				goto check_element_none;
196579170ce0SJerome Forissier 		}
196679170ce0SJerome Forissier 	}
196779170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM3)) {
196879170ce0SJerome Forissier 		if (alg == TEE_ALG_SM3)
196979170ce0SJerome Forissier 			goto check_element_none;
197079170ce0SJerome Forissier 	}
197179170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM4)) {
197279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
197379170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_ECB_NOPAD)
197479170ce0SJerome Forissier 				goto check_element_none;
197579170ce0SJerome Forissier 		}
197679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
197779170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_CBC_NOPAD)
197879170ce0SJerome Forissier 				goto check_element_none;
197979170ce0SJerome Forissier 		}
198079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTR)) {
198179170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_CTR)
198279170ce0SJerome Forissier 				goto check_element_none;
198379170ce0SJerome Forissier 		}
1984*696f56acSPingan Xie 		if (IS_ENABLED(CFG_CRYPTO_XTS)) {
1985*696f56acSPingan Xie 			if (alg == TEE_ALG_SM4_XTS)
1986*696f56acSPingan Xie 				goto check_element_none;
1987*696f56acSPingan Xie 		}
198879170ce0SJerome Forissier 	}
198979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_RSA)) {
199079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5)) {
199179170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5)
199279170ce0SJerome Forissier 				goto check_element_none;
199379170ce0SJerome Forissier 		}
199479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
199579170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 ||
199679170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 ||
199779170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1)
199879170ce0SJerome Forissier 				goto check_element_none;
199979170ce0SJerome Forissier 		}
200079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) {
200179170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1)
200279170ce0SJerome Forissier 				goto check_element_none;
200379170ce0SJerome Forissier 		}
200479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
200579170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 ||
200679170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 ||
200779170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224)
200879170ce0SJerome Forissier 				goto check_element_none;
200979170ce0SJerome Forissier 		}
201079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
201179170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 ||
201279170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 ||
201379170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256)
201479170ce0SJerome Forissier 				goto check_element_none;
201579170ce0SJerome Forissier 		}
201679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
201779170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 ||
201879170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 ||
201979170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384)
202079170ce0SJerome Forissier 				goto check_element_none;
202179170ce0SJerome Forissier 		}
202279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
202379170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 ||
202479170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 ||
202579170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512)
202679170ce0SJerome Forissier 				goto check_element_none;
202779170ce0SJerome Forissier 		}
202879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) {
202979170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5)
203079170ce0SJerome Forissier 				goto check_element_none;
203179170ce0SJerome Forissier 		}
203279170ce0SJerome Forissier 		if (alg == TEE_ALG_RSA_NOPAD)
203379170ce0SJerome Forissier 			goto check_element_none;
203479170ce0SJerome Forissier 	}
203579170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DSA)) {
203679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
203779170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA1)
203879170ce0SJerome Forissier 				goto check_element_none;
203979170ce0SJerome Forissier 		}
204079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
204179170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA224)
204279170ce0SJerome Forissier 				goto check_element_none;
204379170ce0SJerome Forissier 		}
204479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
204579170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA256)
204679170ce0SJerome Forissier 				goto check_element_none;
204779170ce0SJerome Forissier 		}
204879170ce0SJerome Forissier 	}
204979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DH)) {
205079170ce0SJerome Forissier 		if (alg == TEE_ALG_DH_DERIVE_SHARED_SECRET)
205179170ce0SJerome Forissier 			goto check_element_none;
205279170ce0SJerome Forissier 	}
205379170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_ECC)) {
205479170ce0SJerome Forissier 		if ((alg == TEE_ALG_ECDH_P192 || alg == TEE_ALG_ECDSA_P192) &&
205579170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P192)
205679170ce0SJerome Forissier 			return TEE_SUCCESS;
205779170ce0SJerome Forissier 		if ((alg == TEE_ALG_ECDH_P224 || alg == TEE_ALG_ECDSA_P224) &&
205879170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P224)
205979170ce0SJerome Forissier 			return TEE_SUCCESS;
206079170ce0SJerome Forissier 		if ((alg == TEE_ALG_ECDH_P256 || alg == TEE_ALG_ECDSA_P256) &&
206179170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P256)
206279170ce0SJerome Forissier 			return TEE_SUCCESS;
206379170ce0SJerome Forissier 		if ((alg == TEE_ALG_ECDH_P384 || alg == TEE_ALG_ECDSA_P384) &&
206479170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P384)
206579170ce0SJerome Forissier 			return TEE_SUCCESS;
206679170ce0SJerome Forissier 		if ((alg == TEE_ALG_ECDH_P521 || alg == TEE_ALG_ECDSA_P521) &&
206779170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P521)
206879170ce0SJerome Forissier 			return TEE_SUCCESS;
206979170ce0SJerome Forissier 	}
207079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_DSA)) {
207179170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_DSA_SM3 && element == TEE_ECC_CURVE_SM2)
207279170ce0SJerome Forissier 			return TEE_SUCCESS;
207379170ce0SJerome Forissier 	}
207479170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_KEP)) {
207579170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_KEP && element == TEE_ECC_CURVE_SM2)
207679170ce0SJerome Forissier 			return TEE_SUCCESS;
207779170ce0SJerome Forissier 	}
207879170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_PKE)) {
207979170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_PKE && element == TEE_ECC_CURVE_SM2)
208079170ce0SJerome Forissier 			return TEE_SUCCESS;
208179170ce0SJerome Forissier 	}
20823f61056dSSohaib ul Hassan 	if (IS_ENABLED(CFG_CRYPTO_X25519)) {
20833f61056dSSohaib ul Hassan 		if (alg == TEE_ALG_X25519 && element == TEE_ECC_CURVE_25519)
20843f61056dSSohaib ul Hassan 			return TEE_SUCCESS;
20853f61056dSSohaib ul Hassan 	}
2086e1f9cee7SSergiy Kibrik 	if (IS_ENABLED(CFG_CRYPTO_ED25519)) {
2087e1f9cee7SSergiy Kibrik 		if (alg == TEE_ALG_ED25519 && element == TEE_ECC_CURVE_25519)
2088e1f9cee7SSergiy Kibrik 			return TEE_SUCCESS;
2089e1f9cee7SSergiy Kibrik 	}
209079170ce0SJerome Forissier 
209179170ce0SJerome Forissier 	return TEE_ERROR_NOT_SUPPORTED;
209279170ce0SJerome Forissier check_element_none:
209379170ce0SJerome Forissier 	if (element == TEE_CRYPTO_ELEMENT_NONE)
209479170ce0SJerome Forissier 		return TEE_SUCCESS;
209579170ce0SJerome Forissier 	return TEE_ERROR_NOT_SUPPORTED;
209679170ce0SJerome Forissier }
2097