xref: /optee_os/lib/libutee/tee_api_operations.c (revision cb98b7b2e5978c0280d4920bc74c9b691049a4be)
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 
47696f56acSPingan Xie 	if (algorithm == TEE_ALG_AES_XTS || algorithm == TEE_ALG_SM2_KEP ||
48696f56acSPingan 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 
72fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA1:
73fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P192:
74fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P192:
751220586eSCedric Chaumont 		if (maxKeySize != 192)
761220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
771220586eSCedric Chaumont 		break;
781220586eSCedric Chaumont 
79fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA224:
80fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P224:
81fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P224:
821220586eSCedric Chaumont 		if (maxKeySize != 224)
831220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
841220586eSCedric Chaumont 		break;
851220586eSCedric Chaumont 
86fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA256:
87fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P256:
88fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P256:
8991fc6bd8SJerome Forissier 	case TEE_ALG_SM2_PKE:
900f151943SJerome Forissier 	case TEE_ALG_SM2_DSA_SM3:
911220586eSCedric Chaumont 		if (maxKeySize != 256)
921220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
931220586eSCedric Chaumont 		break;
941220586eSCedric Chaumont 
955b385b3fSJerome Forissier 	case TEE_ALG_SM2_KEP:
965b385b3fSJerome Forissier 		/* Two 256-bit keys */
975b385b3fSJerome Forissier 		if (maxKeySize != 512)
985b385b3fSJerome Forissier 			return TEE_ERROR_NOT_SUPPORTED;
995b385b3fSJerome Forissier 		break;
1005b385b3fSJerome Forissier 
101fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA384:
102fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P384:
103fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P384:
1041220586eSCedric Chaumont 		if (maxKeySize != 384)
1051220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
1061220586eSCedric Chaumont 		break;
1071220586eSCedric Chaumont 
108fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA512:
109fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P521:
110fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P521:
1111220586eSCedric Chaumont 		if (maxKeySize != 521)
1121220586eSCedric Chaumont 			return TEE_ERROR_NOT_SUPPORTED;
1131220586eSCedric Chaumont 		break;
114fe2fd3ffSJens Wiklander 
115fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDH_DERIVE_SHARED_SECRET:
116fe2fd3ffSJens Wiklander 		if (maxKeySize > 521)
117fe2fd3ffSJens Wiklander 			return TEE_ERROR_NOT_SUPPORTED;
118fe2fd3ffSJens Wiklander 		break;
119fe2fd3ffSJens Wiklander 
120e1f9cee7SSergiy Kibrik 	case TEE_ALG_ED25519:
1213f61056dSSohaib ul Hassan 	case TEE_ALG_X25519:
1223f61056dSSohaib ul Hassan 		if (maxKeySize != 256)
1233f61056dSSohaib ul Hassan 			return TEE_ERROR_NOT_SUPPORTED;
1243f61056dSSohaib ul Hassan 		break;
125218d9055SCedric Chaumont 	default:
126218d9055SCedric Chaumont 		break;
127218d9055SCedric Chaumont 	}
128218d9055SCedric Chaumont 
129cf5c060cSJens Wiklander 	/* Check algorithm mode (and maxKeySize for digests) */
130b0104773SPascal Brand 	switch (algorithm) {
131b0104773SPascal Brand 	case TEE_ALG_AES_CTS:
132b0104773SPascal Brand 	case TEE_ALG_AES_XTS:
133696f56acSPingan Xie 	case TEE_ALG_SM4_XTS:
134b0104773SPascal Brand 		buffer_two_blocks = true;
135919a5a68SJerome Forissier 		fallthrough;
1364bd53c54SJerome Forissier 	case TEE_ALG_AES_ECB_NOPAD:
137b0104773SPascal Brand 	case TEE_ALG_AES_CBC_NOPAD:
138b0104773SPascal Brand 	case TEE_ALG_AES_CCM:
139b0104773SPascal Brand 	case TEE_ALG_DES_ECB_NOPAD:
140b0104773SPascal Brand 	case TEE_ALG_DES_CBC_NOPAD:
141b0104773SPascal Brand 	case TEE_ALG_DES3_ECB_NOPAD:
142b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_NOPAD:
143ade6f848SJerome Forissier 	case TEE_ALG_SM4_ECB_NOPAD:
144ade6f848SJerome Forissier 	case TEE_ALG_SM4_CBC_NOPAD:
145ade6f848SJerome Forissier 	case TEE_ALG_SM4_CTR:
146b0104773SPascal Brand 		if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES)
147b0104773SPascal Brand 			block_size = TEE_AES_BLOCK_SIZE;
148ade6f848SJerome Forissier 		else if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_SM4)
149ade6f848SJerome Forissier 			block_size = TEE_SM4_BLOCK_SIZE;
150b0104773SPascal Brand 		else
151b0104773SPascal Brand 			block_size = TEE_DES_BLOCK_SIZE;
152919a5a68SJerome Forissier 		fallthrough;
15357aabac5SBogdan Liulko 	case TEE_ALG_AES_CTR:
154afc0c182SBogdan Liulko 	case TEE_ALG_AES_GCM:
155b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT)
156b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT;
157b0104773SPascal Brand 		else if (mode == TEE_MODE_DECRYPT)
158b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT;
159b0104773SPascal Brand 		else
160b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
161b0104773SPascal Brand 		break;
162b0104773SPascal Brand 
1636a2e0a9fSGabor Szekely #if defined(CFG_CRYPTO_RSASSA_NA1)
1646a2e0a9fSGabor Szekely 	case TEE_ALG_RSASSA_PKCS1_V1_5:
1656a2e0a9fSGabor Szekely #endif
166b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
167b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
168b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
169b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
170b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
171b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
172b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
173b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
174b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
175b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
176b0104773SPascal Brand 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
177b0104773SPascal Brand 	case TEE_ALG_DSA_SHA1:
178218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA224:
179218d9055SCedric Chaumont 	case TEE_ALG_DSA_SHA256:
180fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA1:
181fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA224:
182fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA256:
183fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA384:
184fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDSA_SHA512:
185fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P192:
186fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P224:
187fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P256:
188fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P384:
189fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDSA_P521:
1900f151943SJerome Forissier 	case TEE_ALG_SM2_DSA_SM3:
191e1f9cee7SSergiy Kibrik 	case TEE_ALG_ED25519:
192b0104773SPascal Brand 		if (mode == TEE_MODE_SIGN) {
193b0104773SPascal Brand 			with_private_key = true;
194b0104773SPascal Brand 			req_key_usage = TEE_USAGE_SIGN;
195b0104773SPascal Brand 		} else if (mode == TEE_MODE_VERIFY) {
196b0104773SPascal Brand 			req_key_usage = TEE_USAGE_VERIFY;
197b0104773SPascal Brand 		} else {
198b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
199b0104773SPascal Brand 		}
200b0104773SPascal Brand 		break;
201b0104773SPascal Brand 
202b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_V1_5:
203b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
204b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
205b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
206b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
207b0104773SPascal Brand 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
20891fc6bd8SJerome Forissier 	case TEE_ALG_SM2_PKE:
209b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT) {
210b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT;
211b0104773SPascal Brand 		} else if (mode == TEE_MODE_DECRYPT) {
212b0104773SPascal Brand 			with_private_key = true;
213b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT;
214b0104773SPascal Brand 		} else {
215b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
216b0104773SPascal Brand 		}
217b0104773SPascal Brand 		break;
218b0104773SPascal Brand 
219b0104773SPascal Brand 	case TEE_ALG_RSA_NOPAD:
220b0104773SPascal Brand 		if (mode == TEE_MODE_ENCRYPT) {
221b0104773SPascal Brand 			req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY;
222b0104773SPascal Brand 		} else if (mode == TEE_MODE_DECRYPT) {
223b0104773SPascal Brand 			with_private_key = true;
224b0104773SPascal Brand 			req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN;
225b0104773SPascal Brand 		} else {
226b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
227b0104773SPascal Brand 		}
228b0104773SPascal Brand 		break;
229b0104773SPascal Brand 
230b0104773SPascal Brand 	case TEE_ALG_DH_DERIVE_SHARED_SECRET:
231fe2fd3ffSJens Wiklander 	case TEE_ALG_ECDH_DERIVE_SHARED_SECRET:
232fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P192:
233fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P224:
234fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P256:
235fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P384:
236fe2fd3ffSJens Wiklander 	case __OPTEE_ALG_ECDH_P521:
237cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_MD5_DERIVE_KEY:
238cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA1_DERIVE_KEY:
239cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA224_DERIVE_KEY:
240cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA256_DERIVE_KEY:
241cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA384_DERIVE_KEY:
242cdb198a7SJerome Forissier 	case TEE_ALG_HKDF_SHA512_DERIVE_KEY:
2438854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY:
2448854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY:
2458854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY:
2468854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY:
2478854d3c6SJerome Forissier 	case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY:
2480f2293b7SJerome Forissier 	case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY:
2495b385b3fSJerome Forissier 	case TEE_ALG_SM2_KEP:
2503f61056dSSohaib ul Hassan 	case TEE_ALG_X25519:
251b0104773SPascal Brand 		if (mode != TEE_MODE_DERIVE)
252b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
253b0104773SPascal Brand 		with_private_key = true;
254b0104773SPascal Brand 		req_key_usage = TEE_USAGE_DERIVE;
255b0104773SPascal Brand 		break;
256b0104773SPascal Brand 
257b0104773SPascal Brand 	case TEE_ALG_MD5:
258b0104773SPascal Brand 	case TEE_ALG_SHA1:
259b0104773SPascal Brand 	case TEE_ALG_SHA224:
260b0104773SPascal Brand 	case TEE_ALG_SHA256:
261b0104773SPascal Brand 	case TEE_ALG_SHA384:
262b0104773SPascal Brand 	case TEE_ALG_SHA512:
26347645577SJerome Forissier 	case TEE_ALG_SM3:
264b0104773SPascal Brand 		if (mode != TEE_MODE_DIGEST)
265b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
266cf5c060cSJens Wiklander 		if (maxKeySize)
267cf5c060cSJens Wiklander 			return TEE_ERROR_NOT_SUPPORTED;
26805304565SCedric Chaumont 		/* v1.1: flags always set for digest operations */
269b0104773SPascal Brand 		handle_state |= TEE_HANDLE_FLAG_KEY_SET;
270b0104773SPascal Brand 		req_key_usage = 0;
271b0104773SPascal Brand 		break;
272b0104773SPascal Brand 
273b0104773SPascal Brand 	case TEE_ALG_DES_CBC_MAC_NOPAD:
274b0104773SPascal Brand 	case TEE_ALG_AES_CBC_MAC_NOPAD:
275b0104773SPascal Brand 	case TEE_ALG_AES_CBC_MAC_PKCS5:
276b0104773SPascal Brand 	case TEE_ALG_AES_CMAC:
277b0104773SPascal Brand 	case TEE_ALG_DES_CBC_MAC_PKCS5:
278b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_MAC_NOPAD:
279b0104773SPascal Brand 	case TEE_ALG_DES3_CBC_MAC_PKCS5:
280eee637e7SAlexander Zakharov 	case TEE_ALG_DES3_CMAC:
281b0104773SPascal Brand 	case TEE_ALG_HMAC_MD5:
282b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA1:
283b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA224:
284b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA256:
285b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA384:
286b0104773SPascal Brand 	case TEE_ALG_HMAC_SHA512:
28747645577SJerome Forissier 	case TEE_ALG_HMAC_SM3:
288b0104773SPascal Brand 		if (mode != TEE_MODE_MAC)
289b0104773SPascal Brand 			return TEE_ERROR_NOT_SUPPORTED;
290b0104773SPascal Brand 		req_key_usage = TEE_USAGE_MAC;
291b0104773SPascal Brand 		break;
292b0104773SPascal Brand 
293b0104773SPascal Brand 	default:
294b0104773SPascal Brand 		return TEE_ERROR_NOT_SUPPORTED;
295b0104773SPascal Brand 	}
296b0104773SPascal Brand 
297b66f219bSJens Wiklander 	op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO);
2989b52c538SCedric Chaumont 	if (!op)
299b0104773SPascal Brand 		return TEE_ERROR_OUT_OF_MEMORY;
300b0104773SPascal Brand 
301b0104773SPascal Brand 	op->info.algorithm = algorithm;
302b0104773SPascal Brand 	op->info.operationClass = TEE_ALG_GET_CLASS(algorithm);
3036a2e0a9fSGabor Szekely #ifdef CFG_CRYPTO_RSASSA_NA1
3046a2e0a9fSGabor Szekely 	if (algorithm == TEE_ALG_RSASSA_PKCS1_V1_5)
3056a2e0a9fSGabor Szekely 		op->info.operationClass = TEE_OPERATION_ASYMMETRIC_SIGNATURE;
3066a2e0a9fSGabor Szekely #endif
307b0104773SPascal Brand 	op->info.mode = mode;
3082e5e6460SAlbert Schwarzkopf 	op->info.digestLength = TEE_ALG_GET_DIGEST_SIZE(algorithm);
309b0104773SPascal Brand 	op->info.maxKeySize = maxKeySize;
310b0104773SPascal Brand 	op->info.requiredKeyUsage = req_key_usage;
311b0104773SPascal Brand 	op->info.handleState = handle_state;
312b0104773SPascal Brand 
313b0104773SPascal Brand 	if (block_size > 1) {
314b0104773SPascal Brand 		size_t buffer_size = block_size;
315b0104773SPascal Brand 
316b0104773SPascal Brand 		if (buffer_two_blocks)
317b0104773SPascal Brand 			buffer_size *= 2;
318b0104773SPascal Brand 
3199b52c538SCedric Chaumont 		op->buffer = TEE_Malloc(buffer_size,
3209b52c538SCedric Chaumont 					TEE_USER_MEM_HINT_NO_FILL_ZERO);
321b0104773SPascal Brand 		if (op->buffer == NULL) {
322b0104773SPascal Brand 			res = TEE_ERROR_OUT_OF_MEMORY;
323b66f219bSJens Wiklander 			goto out;
324b0104773SPascal Brand 		}
325b0104773SPascal Brand 	}
326b0104773SPascal Brand 	op->block_size = block_size;
327b0104773SPascal Brand 	op->buffer_two_blocks = buffer_two_blocks;
328b0104773SPascal Brand 
329b0104773SPascal Brand 	if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) {
330b0104773SPascal Brand 		uint32_t mks = maxKeySize;
331b0104773SPascal Brand 		TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm,
332b0104773SPascal Brand 						       with_private_key);
333b0104773SPascal Brand 
334b0104773SPascal Brand 		/*
335b0104773SPascal Brand 		 * If two keys are expected the max key size is the sum of
336b0104773SPascal Brand 		 * the size of both keys.
337b0104773SPascal Brand 		 */
338b0104773SPascal Brand 		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS)
339b0104773SPascal Brand 			mks /= 2;
340b0104773SPascal Brand 
341b0104773SPascal Brand 		res = TEE_AllocateTransientObject(key_type, mks, &op->key1);
342b0104773SPascal Brand 		if (res != TEE_SUCCESS)
343b66f219bSJens Wiklander 			goto out;
344b0104773SPascal Brand 
34505304565SCedric Chaumont 		if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) {
3469b52c538SCedric Chaumont 			res = TEE_AllocateTransientObject(key_type, mks,
347b0104773SPascal Brand 							  &op->key2);
348b0104773SPascal Brand 			if (res != TEE_SUCCESS)
349b66f219bSJens Wiklander 				goto out;
350b0104773SPascal Brand 		}
351b0104773SPascal Brand 	}
352b0104773SPascal Brand 
3532c028fdeSJerome Forissier 	res = _utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1,
354e86f1266SJens Wiklander 				     (unsigned long)op->key2, &op->state);
355b66f219bSJens Wiklander 	if (res != TEE_SUCCESS)
356b66f219bSJens Wiklander 		goto out;
357b0104773SPascal Brand 
35805304565SCedric Chaumont 	/*
35905304565SCedric Chaumont 	 * Initialize digest operations
36005304565SCedric Chaumont 	 * Other multi-stage operations initialized w/ TEE_xxxInit functions
36105304565SCedric Chaumont 	 * Non-applicable on asymmetric operations
36205304565SCedric Chaumont 	 */
36305304565SCedric Chaumont 	if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) {
3642c028fdeSJerome Forissier 		res = _utee_hash_init(op->state, NULL, 0);
36505304565SCedric Chaumont 		if (res != TEE_SUCCESS)
366b66f219bSJens Wiklander 			goto out;
36705304565SCedric Chaumont 		/* v1.1: flags always set for digest operations */
36805304565SCedric Chaumont 		op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
36905304565SCedric Chaumont 	}
37005304565SCedric Chaumont 
371642a1607SCedric Chaumont 	op->operationState = TEE_OPERATION_STATE_INITIAL;
372642a1607SCedric Chaumont 
373b0104773SPascal Brand 	*operation = op;
374b0104773SPascal Brand 
375b66f219bSJens Wiklander out:
376b66f219bSJens Wiklander 	if (res != TEE_SUCCESS) {
377b66f219bSJens Wiklander 		if (res != TEE_ERROR_OUT_OF_MEMORY &&
3789b52c538SCedric Chaumont 		    res != TEE_ERROR_NOT_SUPPORTED)
379b36311adSJerome Forissier 			TEE_Panic(res);
380b66f219bSJens Wiklander 		if (op) {
381b66f219bSJens Wiklander 			if (op->state) {
382b66f219bSJens Wiklander 				TEE_FreeOperation(op);
383b66f219bSJens Wiklander 			} else {
384b66f219bSJens Wiklander 				TEE_Free(op->buffer);
385b66f219bSJens Wiklander 				TEE_FreeTransientObject(op->key1);
386b66f219bSJens Wiklander 				TEE_FreeTransientObject(op->key2);
387b66f219bSJens Wiklander 				TEE_Free(op);
388b66f219bSJens Wiklander 			}
389b66f219bSJens Wiklander 		}
390b66f219bSJens Wiklander 	}
391b66f219bSJens Wiklander 
392b0104773SPascal Brand 	return res;
393b0104773SPascal Brand }
394b0104773SPascal Brand 
395b0104773SPascal Brand void TEE_FreeOperation(TEE_OperationHandle operation)
396b0104773SPascal Brand {
397e889e80bSCedric Chaumont 	TEE_Result res;
398e889e80bSCedric Chaumont 
399e889e80bSCedric Chaumont 	if (operation == TEE_HANDLE_NULL)
400e889e80bSCedric Chaumont 		TEE_Panic(0);
401e889e80bSCedric Chaumont 
402b0104773SPascal Brand 	/*
403b0104773SPascal Brand 	 * Note that keys should not be freed here, since they are
404b0104773SPascal Brand 	 * claimed by the operation they will be freed by
405b0104773SPascal Brand 	 * utee_cryp_state_free().
406b0104773SPascal Brand 	 */
4072c028fdeSJerome Forissier 	res = _utee_cryp_state_free(operation->state);
408e889e80bSCedric Chaumont 	if (res != TEE_SUCCESS)
409b36311adSJerome Forissier 		TEE_Panic(res);
410e889e80bSCedric Chaumont 
411b0104773SPascal Brand 	TEE_Free(operation->buffer);
412b0104773SPascal Brand 	TEE_Free(operation);
413b0104773SPascal Brand }
414b0104773SPascal Brand 
415b0104773SPascal Brand void TEE_GetOperationInfo(TEE_OperationHandle operation,
416b0104773SPascal Brand 			  TEE_OperationInfo *operationInfo)
417b0104773SPascal Brand {
418b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
419b0104773SPascal Brand 		TEE_Panic(0);
420b0104773SPascal Brand 
4216915bbbbSJens Wiklander 	__utee_check_out_annotation(operationInfo, sizeof(*operationInfo));
422b0104773SPascal Brand 
423b0104773SPascal Brand 	*operationInfo = operation->info;
424bac3a8a7SJens Wiklander 	if (operationInfo->handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) {
425bac3a8a7SJens Wiklander 		operationInfo->keySize = 0;
426bac3a8a7SJens Wiklander 		operationInfo->requiredKeyUsage = 0;
427bac3a8a7SJens Wiklander 	}
428b0104773SPascal Brand }
429b0104773SPascal Brand 
430ee2f75afSJens Wiklander TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle op,
431ee2f75afSJens Wiklander 					TEE_OperationInfoMultiple *op_info,
432*cb98b7b2SJens Wiklander 					size_t *size)
43305304565SCedric Chaumont {
43405304565SCedric Chaumont 	TEE_Result res = TEE_SUCCESS;
435ee2f75afSJens Wiklander 	TEE_ObjectInfo kinfo = { };
436ee2f75afSJens Wiklander 	size_t max_key_count = 0;
437ee2f75afSJens Wiklander 	bool two_keys = false;
43805304565SCedric Chaumont 
439ee2f75afSJens Wiklander 	if (op == TEE_HANDLE_NULL) {
44005304565SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
44105304565SCedric Chaumont 		goto out;
44205304565SCedric Chaumont 	}
44305304565SCedric Chaumont 
444*cb98b7b2SJens Wiklander 	__utee_check_outbuf_annotation(op_info, size);
44505304565SCedric Chaumont 
446ee2f75afSJens Wiklander 	if (*size < sizeof(*op_info)) {
447ee2f75afSJens Wiklander 		res = TEE_ERROR_BAD_PARAMETERS;
448ee2f75afSJens Wiklander 		goto out;
449ee2f75afSJens Wiklander 	}
450ee2f75afSJens Wiklander 	max_key_count = (*size - sizeof(*op_info)) /
45105304565SCedric Chaumont 			sizeof(TEE_OperationInfoKey);
45205304565SCedric Chaumont 
453ee2f75afSJens Wiklander 	TEE_MemFill(op_info, 0, *size);
45405304565SCedric Chaumont 
45505304565SCedric Chaumont 	/* Two keys flag (TEE_ALG_AES_XTS only) */
456ee2f75afSJens Wiklander 	two_keys = op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS;
457ee2f75afSJens Wiklander 
458ee2f75afSJens Wiklander 	if (op->info.mode == TEE_MODE_DIGEST) {
459ee2f75afSJens Wiklander 		op_info->numberOfKeys = 0;
460ee2f75afSJens Wiklander 	} else if (!two_keys) {
461ee2f75afSJens Wiklander 		if (max_key_count < 1) {
46205304565SCedric Chaumont 			res = TEE_ERROR_SHORT_BUFFER;
46305304565SCedric Chaumont 			goto out;
46405304565SCedric Chaumont 		}
46505304565SCedric Chaumont 
466ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key1, &kinfo);
467ee2f75afSJens Wiklander 		/* Key1 is not a valid handle, "can't happen". */
468ee2f75afSJens Wiklander 		if (res)
46905304565SCedric Chaumont 			goto out;
47005304565SCedric Chaumont 
471d372a47cSJens Wiklander 		op_info->keyInformation[0].keySize = kinfo.objectSize;
472ee2f75afSJens Wiklander 		op_info->keyInformation[0].requiredKeyUsage =
473ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
474ee2f75afSJens Wiklander 		op_info->numberOfKeys = 1;
475ee2f75afSJens Wiklander 	} else {
476ee2f75afSJens Wiklander 		if (max_key_count < 2) {
477ee2f75afSJens Wiklander 			res = TEE_ERROR_SHORT_BUFFER;
47805304565SCedric Chaumont 			goto out;
47905304565SCedric Chaumont 		}
48005304565SCedric Chaumont 
481ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key1, &kinfo);
482ee2f75afSJens Wiklander 		/* Key1 is not a valid handle, "can't happen". */
483ee2f75afSJens Wiklander 		if (res)
484ee2f75afSJens Wiklander 			goto out;
485ee2f75afSJens Wiklander 
486d372a47cSJens Wiklander 		op_info->keyInformation[0].keySize = kinfo.objectSize;
487ee2f75afSJens Wiklander 		op_info->keyInformation[0].requiredKeyUsage =
488ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
489ee2f75afSJens Wiklander 
490ee2f75afSJens Wiklander 		res = TEE_GetObjectInfo1(op->key2, &kinfo);
491ee2f75afSJens Wiklander 		/* Key2 is not a valid handle, "can't happen". */
492ee2f75afSJens Wiklander 		if (res)
493ee2f75afSJens Wiklander 			goto out;
494ee2f75afSJens Wiklander 
495d372a47cSJens Wiklander 		op_info->keyInformation[1].keySize = kinfo.objectSize;
496ee2f75afSJens Wiklander 		op_info->keyInformation[1].requiredKeyUsage =
497ee2f75afSJens Wiklander 			op->info.requiredKeyUsage;
498ee2f75afSJens Wiklander 
499ee2f75afSJens Wiklander 		op_info->numberOfKeys = 2;
50005304565SCedric Chaumont 	}
50105304565SCedric Chaumont 
502ee2f75afSJens Wiklander 	op_info->algorithm = op->info.algorithm;
503ee2f75afSJens Wiklander 	op_info->operationClass = op->info.operationClass;
504ee2f75afSJens Wiklander 	op_info->mode = op->info.mode;
505ee2f75afSJens Wiklander 	op_info->digestLength = op->info.digestLength;
506ee2f75afSJens Wiklander 	op_info->maxKeySize = op->info.maxKeySize;
507ee2f75afSJens Wiklander 	op_info->handleState = op->info.handleState;
508ee2f75afSJens Wiklander 	op_info->operationState = op->operationState;
50905304565SCedric Chaumont 
51005304565SCedric Chaumont out:
51105304565SCedric Chaumont 	if (res != TEE_SUCCESS &&
51205304565SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
513b36311adSJerome Forissier 		TEE_Panic(res);
51405304565SCedric Chaumont 
51505304565SCedric Chaumont 	return res;
51605304565SCedric Chaumont }
51705304565SCedric Chaumont 
518*cb98b7b2SJens Wiklander TEE_Result
519*cb98b7b2SJens Wiklander __GP11_TEE_GetOperationInfoMultiple(TEE_OperationHandle operation,
520*cb98b7b2SJens Wiklander 				    TEE_OperationInfoMultiple *info,
521*cb98b7b2SJens Wiklander 				    uint32_t *operationSize)
522*cb98b7b2SJens Wiklander {
523*cb98b7b2SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
524*cb98b7b2SJens Wiklander 	size_t s = 0;
525*cb98b7b2SJens Wiklander 
526*cb98b7b2SJens Wiklander 	__utee_check_gp11_outbuf_annotation(info, operationSize);
527*cb98b7b2SJens Wiklander 	s = *operationSize;
528*cb98b7b2SJens Wiklander 	res = TEE_GetOperationInfoMultiple(operation, info, &s);
529*cb98b7b2SJens Wiklander 	*operationSize = s;
530*cb98b7b2SJens Wiklander 	return res;
531*cb98b7b2SJens Wiklander }
532*cb98b7b2SJens Wiklander 
533b0104773SPascal Brand void TEE_ResetOperation(TEE_OperationHandle operation)
534b0104773SPascal Brand {
535b0104773SPascal Brand 	TEE_Result res;
536b0104773SPascal Brand 
537b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
538b0104773SPascal Brand 		TEE_Panic(0);
539bf80076aSCedric Chaumont 
540642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET))
541bf80076aSCedric Chaumont 			TEE_Panic(0);
542bf80076aSCedric Chaumont 
543642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
544642a1607SCedric Chaumont 
545b0104773SPascal Brand 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
5462c028fdeSJerome Forissier 		res = _utee_hash_init(operation->state, NULL, 0);
547b0104773SPascal Brand 		if (res != TEE_SUCCESS)
548b0104773SPascal Brand 			TEE_Panic(res);
54905304565SCedric Chaumont 		operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
55005304565SCedric Chaumont 	} else {
551b0104773SPascal Brand 		operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
552b0104773SPascal Brand 	}
55305304565SCedric Chaumont }
554b0104773SPascal Brand 
555b0104773SPascal Brand TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation,
556b0104773SPascal Brand 			       TEE_ObjectHandle key)
557b0104773SPascal Brand {
5587583c59eSCedric Chaumont 	TEE_Result res;
559b0104773SPascal Brand 	uint32_t key_size = 0;
560b0104773SPascal Brand 	TEE_ObjectInfo key_info;
561b0104773SPascal Brand 
562a57c1e2eSCedric Chaumont 	if (operation == TEE_HANDLE_NULL) {
563a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
564a57c1e2eSCedric Chaumont 		goto out;
565a57c1e2eSCedric Chaumont 	}
566a57c1e2eSCedric Chaumont 
567642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
568642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
569642a1607SCedric Chaumont 		goto out;
570642a1607SCedric Chaumont 	}
571642a1607SCedric Chaumont 
572a57c1e2eSCedric Chaumont 	if (key == TEE_HANDLE_NULL) {
573a57c1e2eSCedric Chaumont 		/* Operation key cleared */
574a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key1);
5756c4ea258SJens Wiklander 		operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
5766c4ea258SJens Wiklander 		return TEE_SUCCESS;
577a57c1e2eSCedric Chaumont 	}
578a57c1e2eSCedric Chaumont 
579a57c1e2eSCedric Chaumont 	/* No key for digest operation */
580a57c1e2eSCedric Chaumont 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
581a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
582a57c1e2eSCedric Chaumont 		goto out;
583a57c1e2eSCedric Chaumont 	}
584a57c1e2eSCedric Chaumont 
585a57c1e2eSCedric Chaumont 	/* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */
586a57c1e2eSCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) !=
587a57c1e2eSCedric Chaumont 	    0) {
588a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
589a57c1e2eSCedric Chaumont 		goto out;
590a57c1e2eSCedric Chaumont 	}
591a57c1e2eSCedric Chaumont 
5927583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key, &key_info);
593a57c1e2eSCedric Chaumont 	/* Key is not a valid handle */
5947583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
595a57c1e2eSCedric Chaumont 		goto out;
5967583c59eSCedric Chaumont 
597b0104773SPascal Brand 	/* Supplied key has to meet required usage */
598b0104773SPascal Brand 	if ((key_info.objectUsage & operation->info.requiredKeyUsage) !=
599b0104773SPascal Brand 	    operation->info.requiredKeyUsage) {
600a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
601a57c1e2eSCedric Chaumont 		goto out;
602b0104773SPascal Brand 	}
603b0104773SPascal Brand 
604d372a47cSJens Wiklander 	if (operation->info.maxKeySize < key_info.objectSize) {
605a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
606a57c1e2eSCedric Chaumont 		goto out;
607a57c1e2eSCedric Chaumont 	}
608b0104773SPascal Brand 
609d372a47cSJens Wiklander 	key_size = key_info.objectSize;
610b0104773SPascal Brand 
611b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key1);
612b0104773SPascal Brand 	operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
613b0104773SPascal Brand 
6147583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key1, key);
6157583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
616a57c1e2eSCedric Chaumont 		goto out;
6177583c59eSCedric Chaumont 
618b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET;
619b0104773SPascal Brand 
620b0104773SPascal Brand 	operation->info.keySize = key_size;
621b0104773SPascal Brand 
6227583c59eSCedric Chaumont out:
623a57c1e2eSCedric Chaumont 	if (res != TEE_SUCCESS  &&
624a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT &&
625a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE)
626b36311adSJerome Forissier 		TEE_Panic(res);
627a57c1e2eSCedric Chaumont 
628a57c1e2eSCedric Chaumont 	return res;
629b0104773SPascal Brand }
630b0104773SPascal Brand 
631b0104773SPascal Brand TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation,
632b0104773SPascal Brand 				TEE_ObjectHandle key1, TEE_ObjectHandle key2)
633b0104773SPascal Brand {
6347583c59eSCedric Chaumont 	TEE_Result res;
635b0104773SPascal Brand 	uint32_t key_size = 0;
636b0104773SPascal Brand 	TEE_ObjectInfo key_info1;
637b0104773SPascal Brand 	TEE_ObjectInfo key_info2;
638b0104773SPascal Brand 
639a57c1e2eSCedric Chaumont 	if (operation == TEE_HANDLE_NULL) {
640a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
641a57c1e2eSCedric Chaumont 		goto out;
642a57c1e2eSCedric Chaumont 	}
643a57c1e2eSCedric Chaumont 
644642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
645642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
646642a1607SCedric Chaumont 		goto out;
647642a1607SCedric Chaumont 	}
648642a1607SCedric Chaumont 
649a57c1e2eSCedric Chaumont 	/*
650a57c1e2eSCedric Chaumont 	 * Key1/Key2 and/or are not initialized and
651a57c1e2eSCedric Chaumont 	 * Either both keys are NULL or both are not NULL
652a57c1e2eSCedric Chaumont 	 */
6536c4ea258SJens Wiklander 	if (!key1 && !key2) {
6546c4ea258SJens Wiklander 		/* Clear the keys */
655a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key1);
656a57c1e2eSCedric Chaumont 		TEE_ResetTransientObject(operation->key2);
6576c4ea258SJens Wiklander 		operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
6586c4ea258SJens Wiklander 		return TEE_SUCCESS;
6596c4ea258SJens Wiklander 	} else if (!key1 || !key2) {
6606c4ea258SJens Wiklander 		/* Both keys are obviously not valid. */
661a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
662a57c1e2eSCedric Chaumont 		goto out;
663a57c1e2eSCedric Chaumont 	}
664a57c1e2eSCedric Chaumont 
665a57c1e2eSCedric Chaumont 	/* No key for digest operation */
666a57c1e2eSCedric Chaumont 	if (operation->info.operationClass == TEE_OPERATION_DIGEST) {
667a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
668a57c1e2eSCedric Chaumont 		goto out;
669a57c1e2eSCedric Chaumont 	}
670a57c1e2eSCedric Chaumont 
6715b385b3fSJerome Forissier 	/* Two keys flag expected (TEE_ALG_AES_XTS and TEE_ALG_SM2_KEP only) */
672a57c1e2eSCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) ==
673a57c1e2eSCedric Chaumont 	    0) {
674a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
675a57c1e2eSCedric Chaumont 		goto out;
676a57c1e2eSCedric Chaumont 	}
677a57c1e2eSCedric Chaumont 
6787583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key1, &key_info1);
679a57c1e2eSCedric Chaumont 	/* Key1 is not a valid handle */
6807583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
681a57c1e2eSCedric Chaumont 		goto out;
6827583c59eSCedric Chaumont 
683b0104773SPascal Brand 	/* Supplied key has to meet required usage */
684b0104773SPascal Brand 	if ((key_info1.objectUsage & operation->info.
685b0104773SPascal Brand 	     requiredKeyUsage) != operation->info.requiredKeyUsage) {
686a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
687a57c1e2eSCedric Chaumont 		goto out;
688b0104773SPascal Brand 	}
689b0104773SPascal Brand 
6907583c59eSCedric Chaumont 	res = TEE_GetObjectInfo1(key2, &key_info2);
691a57c1e2eSCedric Chaumont 	/* Key2 is not a valid handle */
6927583c59eSCedric Chaumont 	if (res != TEE_SUCCESS) {
6937583c59eSCedric Chaumont 		if (res == TEE_ERROR_CORRUPT_OBJECT)
6947583c59eSCedric Chaumont 			res = TEE_ERROR_CORRUPT_OBJECT_2;
695a57c1e2eSCedric Chaumont 		goto out;
6967583c59eSCedric Chaumont 	}
6977583c59eSCedric Chaumont 
698b0104773SPascal Brand 	/* Supplied key has to meet required usage */
699b0104773SPascal Brand 	if ((key_info2.objectUsage & operation->info.
700b0104773SPascal Brand 	     requiredKeyUsage) != operation->info.requiredKeyUsage) {
701a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
702a57c1e2eSCedric Chaumont 		goto out;
703b0104773SPascal Brand 	}
704b0104773SPascal Brand 
705b0104773SPascal Brand 	/*
7065b385b3fSJerome Forissier 	 * All the multi key algorithm currently supported requires the keys to
7075b385b3fSJerome Forissier 	 * be of equal size.
708b0104773SPascal Brand 	 */
709d372a47cSJens Wiklander 	if (key_info1.objectSize != key_info2.objectSize) {
710a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
711a57c1e2eSCedric Chaumont 		goto out;
712b0104773SPascal Brand 
713a57c1e2eSCedric Chaumont 	}
714a57c1e2eSCedric Chaumont 
715d372a47cSJens Wiklander 	if (operation->info.maxKeySize < key_info1.objectSize) {
716a57c1e2eSCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
717a57c1e2eSCedric Chaumont 		goto out;
718a57c1e2eSCedric Chaumont 	}
719b0104773SPascal Brand 
720b0104773SPascal Brand 	/*
721b0104773SPascal Brand 	 * Odd that only the size of one key should be reported while
722b0104773SPascal Brand 	 * size of two key are used when allocating the operation.
723b0104773SPascal Brand 	 */
724d372a47cSJens Wiklander 	key_size = key_info1.objectSize;
725b0104773SPascal Brand 
726b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key1);
727b0104773SPascal Brand 	TEE_ResetTransientObject(operation->key2);
728b0104773SPascal Brand 	operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET;
729b0104773SPascal Brand 
7307583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key1, key1);
7317583c59eSCedric Chaumont 	if (res != TEE_SUCCESS)
732a57c1e2eSCedric Chaumont 		goto out;
7337583c59eSCedric Chaumont 	res = TEE_CopyObjectAttributes1(operation->key2, key2);
7347583c59eSCedric Chaumont 	if (res != TEE_SUCCESS) {
7357583c59eSCedric Chaumont 		if (res == TEE_ERROR_CORRUPT_OBJECT)
7367583c59eSCedric Chaumont 			res = TEE_ERROR_CORRUPT_OBJECT_2;
737a57c1e2eSCedric Chaumont 		goto out;
7387583c59eSCedric Chaumont 	}
7397583c59eSCedric Chaumont 
740b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET;
741b0104773SPascal Brand 
742b0104773SPascal Brand 	operation->info.keySize = key_size;
743b0104773SPascal Brand 
7447583c59eSCedric Chaumont out:
745a57c1e2eSCedric Chaumont 	if (res != TEE_SUCCESS  &&
746a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT &&
747a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_CORRUPT_OBJECT_2 &&
748a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE &&
749a57c1e2eSCedric Chaumont 	    res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2)
750b36311adSJerome Forissier 		TEE_Panic(res);
751a57c1e2eSCedric Chaumont 
752a57c1e2eSCedric Chaumont 	return res;
753b0104773SPascal Brand }
754b0104773SPascal Brand 
755b0104773SPascal Brand void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op)
756b0104773SPascal Brand {
757b0104773SPascal Brand 	TEE_Result res;
758b0104773SPascal Brand 
759b0104773SPascal Brand 	if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL)
760b0104773SPascal Brand 		TEE_Panic(0);
761b0104773SPascal Brand 	if (dst_op->info.algorithm != src_op->info.algorithm)
762b0104773SPascal Brand 		TEE_Panic(0);
7638734de30SJens Wiklander 	if (dst_op->info.mode != src_op->info.mode)
7648734de30SJens Wiklander 		TEE_Panic(0);
765b0104773SPascal Brand 	if (src_op->info.operationClass != TEE_OPERATION_DIGEST) {
766b0104773SPascal Brand 		TEE_ObjectHandle key1 = TEE_HANDLE_NULL;
767b0104773SPascal Brand 		TEE_ObjectHandle key2 = TEE_HANDLE_NULL;
768b0104773SPascal Brand 
769b0104773SPascal Brand 		if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) {
770b0104773SPascal Brand 			key1 = src_op->key1;
771b0104773SPascal Brand 			key2 = src_op->key2;
772b0104773SPascal Brand 		}
773b0104773SPascal Brand 
774b0104773SPascal Brand 		if ((src_op->info.handleState &
775b0104773SPascal Brand 		     TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) {
776b0104773SPascal Brand 			TEE_SetOperationKey(dst_op, key1);
777b0104773SPascal Brand 		} else {
778b0104773SPascal Brand 			TEE_SetOperationKey2(dst_op, key1, key2);
779b0104773SPascal Brand 		}
780b0104773SPascal Brand 	}
781b0104773SPascal Brand 	dst_op->info.handleState = src_op->info.handleState;
782b0104773SPascal Brand 	dst_op->info.keySize = src_op->info.keySize;
7838e07702eSJens Wiklander 	dst_op->info.digestLength = src_op->info.digestLength;
784642a1607SCedric Chaumont 	dst_op->operationState = src_op->operationState;
785b0104773SPascal Brand 
786b0104773SPascal Brand 	if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks ||
787b0104773SPascal Brand 	    dst_op->block_size != src_op->block_size)
788b0104773SPascal Brand 		TEE_Panic(0);
789b0104773SPascal Brand 
790b0104773SPascal Brand 	if (dst_op->buffer != NULL) {
791b0104773SPascal Brand 		if (src_op->buffer == NULL)
792b0104773SPascal Brand 			TEE_Panic(0);
793b0104773SPascal Brand 
794b0104773SPascal Brand 		memcpy(dst_op->buffer, src_op->buffer, src_op->buffer_offs);
795b0104773SPascal Brand 		dst_op->buffer_offs = src_op->buffer_offs;
796b0104773SPascal Brand 	} else if (src_op->buffer != NULL) {
797b0104773SPascal Brand 		TEE_Panic(0);
798b0104773SPascal Brand 	}
799b0104773SPascal Brand 
8002c028fdeSJerome Forissier 	res = _utee_cryp_state_copy(dst_op->state, src_op->state);
801b0104773SPascal Brand 	if (res != TEE_SUCCESS)
802b0104773SPascal Brand 		TEE_Panic(res);
803b0104773SPascal Brand }
804b0104773SPascal Brand 
805b0104773SPascal Brand /* Cryptographic Operations API - Message Digest Functions */
806b0104773SPascal Brand 
8078f07fe6fSJerome Forissier static void init_hash_operation(TEE_OperationHandle operation, const void *IV,
8086d15db08SJerome Forissier 				uint32_t IVLen)
8096d15db08SJerome Forissier {
8106d15db08SJerome Forissier 	TEE_Result res;
8116d15db08SJerome Forissier 
8126d15db08SJerome Forissier 	/*
8136d15db08SJerome Forissier 	 * Note : IV and IVLen are never used in current implementation
8146d15db08SJerome Forissier 	 * This is why coherent values of IV and IVLen are not checked
8156d15db08SJerome Forissier 	 */
8162c028fdeSJerome Forissier 	res = _utee_hash_init(operation->state, IV, IVLen);
8176d15db08SJerome Forissier 	if (res != TEE_SUCCESS)
8186d15db08SJerome Forissier 		TEE_Panic(res);
8196d15db08SJerome Forissier 	operation->buffer_offs = 0;
8206d15db08SJerome Forissier 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
8216d15db08SJerome Forissier }
8226d15db08SJerome Forissier 
823b0104773SPascal Brand void TEE_DigestUpdate(TEE_OperationHandle operation,
8248f07fe6fSJerome Forissier 		      const void *chunk, uint32_t chunkSize)
825b0104773SPascal Brand {
82673d6c3baSJoakim Bech 	TEE_Result res = TEE_ERROR_GENERIC;
827b0104773SPascal Brand 
82873d6c3baSJoakim Bech 	if (operation == TEE_HANDLE_NULL ||
82973d6c3baSJoakim Bech 	    operation->info.operationClass != TEE_OPERATION_DIGEST)
830b0104773SPascal Brand 		TEE_Panic(0);
83173d6c3baSJoakim Bech 
832642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
833642a1607SCedric Chaumont 
8342c028fdeSJerome Forissier 	res = _utee_hash_update(operation->state, chunk, chunkSize);
835b0104773SPascal Brand 	if (res != TEE_SUCCESS)
836b0104773SPascal Brand 		TEE_Panic(res);
837b0104773SPascal Brand }
838b0104773SPascal Brand 
8398f07fe6fSJerome Forissier TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk,
84079a3c601SCedric Chaumont 			     uint32_t chunkLen, void *hash, uint32_t *hashLen)
841b0104773SPascal Brand {
84287c2f6b6SCedric Chaumont 	TEE_Result res;
843e86f1266SJens Wiklander 	uint64_t hl;
84487c2f6b6SCedric Chaumont 
84587c2f6b6SCedric Chaumont 	if ((operation == TEE_HANDLE_NULL) ||
84687c2f6b6SCedric Chaumont 	    (!chunk && chunkLen) ||
84787c2f6b6SCedric Chaumont 	    (operation->info.operationClass != TEE_OPERATION_DIGEST)) {
84887c2f6b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
84987c2f6b6SCedric Chaumont 		goto out;
85087c2f6b6SCedric Chaumont 	}
8516915bbbbSJens Wiklander 	__utee_check_inout_annotation(hashLen, sizeof(*hashLen));
85287c2f6b6SCedric Chaumont 
853e86f1266SJens Wiklander 	hl = *hashLen;
8542c028fdeSJerome Forissier 	res = _utee_hash_final(operation->state, chunk, chunkLen, hash, &hl);
855e86f1266SJens Wiklander 	*hashLen = hl;
8566d15db08SJerome Forissier 	if (res != TEE_SUCCESS)
8576d15db08SJerome Forissier 		goto out;
8586d15db08SJerome Forissier 
8596d15db08SJerome Forissier 	/* Reset operation state */
8606d15db08SJerome Forissier 	init_hash_operation(operation, NULL, 0);
86187c2f6b6SCedric Chaumont 
862642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
863642a1607SCedric Chaumont 
86487c2f6b6SCedric Chaumont out:
86587c2f6b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
86687c2f6b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
867b36311adSJerome Forissier 		TEE_Panic(res);
86873d6c3baSJoakim Bech 
86987c2f6b6SCedric Chaumont 	return res;
870b0104773SPascal Brand }
871b0104773SPascal Brand 
872b0104773SPascal Brand /* Cryptographic Operations API - Symmetric Cipher Functions */
873b0104773SPascal Brand 
8748f07fe6fSJerome Forissier void TEE_CipherInit(TEE_OperationHandle operation, const void *IV,
8758f07fe6fSJerome Forissier 		    uint32_t IVLen)
876b0104773SPascal Brand {
877b0104773SPascal Brand 	TEE_Result res;
878b0104773SPascal Brand 
879b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
880b0104773SPascal Brand 		TEE_Panic(0);
881642a1607SCedric Chaumont 
882b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_CIPHER)
883b0104773SPascal Brand 		TEE_Panic(0);
884642a1607SCedric Chaumont 
885642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||
886642a1607SCedric Chaumont 	    !(operation->key1))
887642a1607SCedric Chaumont 		TEE_Panic(0);
888642a1607SCedric Chaumont 
889642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
890642a1607SCedric Chaumont 		TEE_ResetOperation(operation);
891642a1607SCedric Chaumont 
892ad7aa2a5SSadiq Hussain 	if (IV && IVLen) {
893ad7aa2a5SSadiq Hussain 		if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD ||
894ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD ||
895ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD ||
896ad7aa2a5SSadiq Hussain 		    operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD)
897ad7aa2a5SSadiq Hussain 			TEE_Panic(0);
898ad7aa2a5SSadiq Hussain 	}
899ad7aa2a5SSadiq Hussain 
900642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
901642a1607SCedric Chaumont 
9022c028fdeSJerome Forissier 	res = _utee_cipher_init(operation->state, IV, IVLen);
903b0104773SPascal Brand 	if (res != TEE_SUCCESS)
904b0104773SPascal Brand 		TEE_Panic(res);
905642a1607SCedric Chaumont 
906b0104773SPascal Brand 	operation->buffer_offs = 0;
907b0104773SPascal Brand 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
908b0104773SPascal Brand }
909b0104773SPascal Brand 
910b0104773SPascal Brand static TEE_Result tee_buffer_update(
911b0104773SPascal Brand 		TEE_OperationHandle op,
912e86f1266SJens Wiklander 		TEE_Result(*update_func)(unsigned long state, const void *src,
913e86f1266SJens Wiklander 				size_t slen, void *dst, uint64_t *dlen),
914b0104773SPascal Brand 		const void *src_data, size_t src_len,
915e86f1266SJens Wiklander 		void *dest_data, uint64_t *dest_len)
916b0104773SPascal Brand {
917b0104773SPascal Brand 	TEE_Result res;
918b0104773SPascal Brand 	const uint8_t *src = src_data;
919b0104773SPascal Brand 	size_t slen = src_len;
920b0104773SPascal Brand 	uint8_t *dst = dest_data;
921b0104773SPascal Brand 	size_t dlen = *dest_len;
922b0104773SPascal Brand 	size_t acc_dlen = 0;
923e86f1266SJens Wiklander 	uint64_t tmp_dlen;
924b0104773SPascal Brand 	size_t l;
925b0104773SPascal Brand 	size_t buffer_size;
926d3588802SPascal Brand 	size_t buffer_left;
927b0104773SPascal Brand 
928090268f5SJens Wiklander 	if (!src) {
929090268f5SJens Wiklander 		if (slen)
930090268f5SJens Wiklander 			TEE_Panic(0);
931090268f5SJens Wiklander 		goto out;
932090268f5SJens Wiklander 	}
933090268f5SJens Wiklander 
934d3588802SPascal Brand 	if (op->buffer_two_blocks) {
935b0104773SPascal Brand 		buffer_size = op->block_size * 2;
936d3588802SPascal Brand 		buffer_left = 1;
937d3588802SPascal Brand 	} else {
938b0104773SPascal Brand 		buffer_size = op->block_size;
939d3588802SPascal Brand 		buffer_left = 0;
940d3588802SPascal Brand 	}
941b0104773SPascal Brand 
942b0104773SPascal Brand 	if (op->buffer_offs > 0) {
943b0104773SPascal Brand 		/* Fill up complete block */
944b0104773SPascal Brand 		if (op->buffer_offs < op->block_size)
945b0104773SPascal Brand 			l = MIN(slen, op->block_size - op->buffer_offs);
946b0104773SPascal Brand 		else
947b0104773SPascal Brand 			l = MIN(slen, buffer_size - op->buffer_offs);
948b0104773SPascal Brand 		memcpy(op->buffer + op->buffer_offs, src, l);
949b0104773SPascal Brand 		op->buffer_offs += l;
950b0104773SPascal Brand 		src += l;
951b0104773SPascal Brand 		slen -= l;
952b0104773SPascal Brand 		if ((op->buffer_offs % op->block_size) != 0)
953b0104773SPascal Brand 			goto out;	/* Nothing left to do */
954b0104773SPascal Brand 	}
955b0104773SPascal Brand 
956b0104773SPascal Brand 	/* If we can feed from buffer */
957d3588802SPascal Brand 	if ((op->buffer_offs > 0) &&
958d3588802SPascal Brand 	    ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) {
9592ff3fdbbSPascal Brand 		l = ROUNDUP(op->buffer_offs + slen - buffer_size,
960b0104773SPascal Brand 				op->block_size);
961b0104773SPascal Brand 		l = MIN(op->buffer_offs, l);
962b0104773SPascal Brand 		tmp_dlen = dlen;
963b0104773SPascal Brand 		res = update_func(op->state, op->buffer, l, dst, &tmp_dlen);
964b0104773SPascal Brand 		if (res != TEE_SUCCESS)
965b0104773SPascal Brand 			TEE_Panic(res);
966b0104773SPascal Brand 		dst += tmp_dlen;
967b0104773SPascal Brand 		dlen -= tmp_dlen;
968b0104773SPascal Brand 		acc_dlen += tmp_dlen;
969b0104773SPascal Brand 		op->buffer_offs -= l;
970b0104773SPascal Brand 		if (op->buffer_offs > 0) {
971b0104773SPascal Brand 			/*
972b0104773SPascal Brand 			 * Slen is small enough to be contained in rest buffer.
973b0104773SPascal Brand 			 */
974b0104773SPascal Brand 			memcpy(op->buffer, op->buffer + l, buffer_size - l);
975b0104773SPascal Brand 			memcpy(op->buffer + op->buffer_offs, src, slen);
976b0104773SPascal Brand 			op->buffer_offs += slen;
977b0104773SPascal Brand 			goto out;	/* Nothing left to do */
978b0104773SPascal Brand 		}
979b0104773SPascal Brand 	}
980b0104773SPascal Brand 
981d3588802SPascal Brand 	if (slen >= (buffer_size + buffer_left)) {
982b0104773SPascal Brand 		/* Buffer is empty, feed as much as possible from src */
983bf7a587fSJerome Forissier 		if (op->info.algorithm == TEE_ALG_AES_CTS)
984b1ecda78SJerome Forissier 			l = ROUNDUP(slen - buffer_size, op->block_size);
985bf7a587fSJerome Forissier 		else
986bf7a587fSJerome Forissier 			l = ROUNDUP(slen - buffer_size + 1, op->block_size);
987b0104773SPascal Brand 
988b0104773SPascal Brand 		tmp_dlen = dlen;
989b0104773SPascal Brand 		res = update_func(op->state, src, l, dst, &tmp_dlen);
990b0104773SPascal Brand 		if (res != TEE_SUCCESS)
991b0104773SPascal Brand 			TEE_Panic(res);
992b0104773SPascal Brand 		src += l;
993b0104773SPascal Brand 		slen -= l;
994b0104773SPascal Brand 		dst += tmp_dlen;
995b0104773SPascal Brand 		dlen -= tmp_dlen;
996b0104773SPascal Brand 		acc_dlen += tmp_dlen;
997b0104773SPascal Brand 	}
998b0104773SPascal Brand 
999b0104773SPascal Brand 	/* Slen is small enough to be contained in buffer. */
1000b0104773SPascal Brand 	memcpy(op->buffer + op->buffer_offs, src, slen);
1001b0104773SPascal Brand 	op->buffer_offs += slen;
1002b0104773SPascal Brand 
1003b0104773SPascal Brand out:
1004b0104773SPascal Brand 	*dest_len = acc_dlen;
1005b0104773SPascal Brand 	return TEE_SUCCESS;
1006b0104773SPascal Brand }
1007b0104773SPascal Brand 
10088f07fe6fSJerome Forissier TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData,
100979a3c601SCedric Chaumont 			    uint32_t srcLen, void *destData, uint32_t *destLen)
1010b0104773SPascal Brand {
1011dea1f2b6SCedric Chaumont 	TEE_Result res;
1012b0104773SPascal Brand 	size_t req_dlen;
1013e86f1266SJens Wiklander 	uint64_t dl;
1014b0104773SPascal Brand 
10156915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1016dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1017dea1f2b6SCedric Chaumont 		goto out;
1018dea1f2b6SCedric Chaumont 	}
10196915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1020dea1f2b6SCedric Chaumont 
1021642a1607SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_CIPHER) {
1022dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1023dea1f2b6SCedric Chaumont 		goto out;
1024dea1f2b6SCedric Chaumont 	}
1025dea1f2b6SCedric Chaumont 
1026642a1607SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1027642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1028642a1607SCedric Chaumont 		goto out;
1029642a1607SCedric Chaumont 	}
1030642a1607SCedric Chaumont 
1031642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1032dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1033dea1f2b6SCedric Chaumont 		goto out;
1034dea1f2b6SCedric Chaumont 	}
1035b0104773SPascal Brand 
1036e32c5ddfSJerome Forissier 	if (!srcData && !srcLen) {
1037090268f5SJens Wiklander 		*destLen = 0;
1038e32c5ddfSJerome Forissier 		res = TEE_SUCCESS;
1039e32c5ddfSJerome Forissier 		goto out;
1040e32c5ddfSJerome Forissier 	}
1041e32c5ddfSJerome Forissier 
1042b0104773SPascal Brand 	/* Calculate required dlen */
104357aabac5SBogdan Liulko 	if (operation->block_size > 1) {
104457aabac5SBogdan Liulko 		req_dlen = ((operation->buffer_offs + srcLen) /
104557aabac5SBogdan Liulko 			    operation->block_size) * operation->block_size;
104657aabac5SBogdan Liulko 	} else {
104757aabac5SBogdan Liulko 		req_dlen = srcLen;
104857aabac5SBogdan Liulko 	}
1049642a1607SCedric Chaumont 	if (operation->buffer_two_blocks) {
1050642a1607SCedric Chaumont 		if (req_dlen > operation->block_size * 2)
1051642a1607SCedric Chaumont 			req_dlen -= operation->block_size * 2;
1052b0104773SPascal Brand 		else
1053b0104773SPascal Brand 			req_dlen = 0;
1054b0104773SPascal Brand 	}
1055b0104773SPascal Brand 	/*
1056b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1057b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1058b0104773SPascal Brand 	 * can't restore sync with this API.
1059b0104773SPascal Brand 	 */
1060b0104773SPascal Brand 	if (*destLen < req_dlen) {
1061b0104773SPascal Brand 		*destLen = req_dlen;
1062dea1f2b6SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1063dea1f2b6SCedric Chaumont 		goto out;
1064b0104773SPascal Brand 	}
1065b0104773SPascal Brand 
1066e86f1266SJens Wiklander 	dl = *destLen;
106757aabac5SBogdan Liulko 	if (operation->block_size > 1) {
10682c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_cipher_update, srcData,
106957aabac5SBogdan Liulko 					srcLen, destData, &dl);
107057aabac5SBogdan Liulko 	} else {
107157aabac5SBogdan Liulko 		if (srcLen > 0) {
10722c028fdeSJerome Forissier 			res = _utee_cipher_update(operation->state, srcData,
107357aabac5SBogdan Liulko 						  srcLen, destData, &dl);
107457aabac5SBogdan Liulko 		} else {
107557aabac5SBogdan Liulko 			res = TEE_SUCCESS;
107657aabac5SBogdan Liulko 			dl = 0;
107757aabac5SBogdan Liulko 		}
107857aabac5SBogdan Liulko 	}
1079e86f1266SJens Wiklander 	*destLen = dl;
1080b0104773SPascal Brand 
1081dea1f2b6SCedric Chaumont out:
1082dea1f2b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
1083dea1f2b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1084b36311adSJerome Forissier 		TEE_Panic(res);
1085dea1f2b6SCedric Chaumont 
1086dea1f2b6SCedric Chaumont 	return res;
1087b0104773SPascal Brand }
1088b0104773SPascal Brand 
1089642a1607SCedric Chaumont TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation,
10908f07fe6fSJerome Forissier 			     const void *srcData, uint32_t srcLen,
10918f07fe6fSJerome Forissier 			     void *destData, uint32_t *destLen)
1092b0104773SPascal Brand {
10936915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1094b0104773SPascal Brand 	uint8_t *dst = destData;
1095b0104773SPascal Brand 	size_t acc_dlen = 0;
10966915bbbbSJens Wiklander 	uint64_t tmp_dlen = 0;
10976915bbbbSJens Wiklander 	size_t req_dlen = 0;
1098b0104773SPascal Brand 
10996915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1100dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1101dea1f2b6SCedric Chaumont 		goto out;
1102dea1f2b6SCedric Chaumont 	}
11036915bbbbSJens Wiklander 	if (destLen)
11046915bbbbSJens Wiklander 		__utee_check_inout_annotation(destLen, sizeof(*destLen));
1105dea1f2b6SCedric Chaumont 
1106642a1607SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_CIPHER) {
1107dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1108dea1f2b6SCedric Chaumont 		goto out;
1109dea1f2b6SCedric Chaumont 	}
1110dea1f2b6SCedric Chaumont 
1111642a1607SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1112642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1113642a1607SCedric Chaumont 		goto out;
1114642a1607SCedric Chaumont 	}
1115642a1607SCedric Chaumont 
1116642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1117dea1f2b6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1118dea1f2b6SCedric Chaumont 		goto out;
1119dea1f2b6SCedric Chaumont 	}
1120b0104773SPascal Brand 
1121b0104773SPascal Brand 	/*
1122b0104773SPascal Brand 	 * Check that the final block doesn't require padding for those
1123b0104773SPascal Brand 	 * algorithms that requires client to supply padding.
1124b0104773SPascal Brand 	 */
1125642a1607SCedric Chaumont 	if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD ||
1126642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD ||
1127642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD ||
1128642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD ||
1129642a1607SCedric Chaumont 	    operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD ||
1130ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD ||
1131ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD ||
1132ade6f848SJerome Forissier 	    operation->info.algorithm == TEE_ALG_SM4_CBC_NOPAD) {
1133642a1607SCedric Chaumont 		if (((operation->buffer_offs + srcLen) % operation->block_size)
1134642a1607SCedric Chaumont 		    != 0) {
1135dea1f2b6SCedric Chaumont 			res = TEE_ERROR_BAD_PARAMETERS;
1136dea1f2b6SCedric Chaumont 			goto out;
1137dea1f2b6SCedric Chaumont 		}
1138b0104773SPascal Brand 	}
1139b0104773SPascal Brand 
1140b0104773SPascal Brand 	/*
1141b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1142b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1143b0104773SPascal Brand 	 * can't restore sync with this API.
1144b0104773SPascal Brand 	 */
114557aabac5SBogdan Liulko 	if (operation->block_size > 1) {
1146642a1607SCedric Chaumont 		req_dlen = operation->buffer_offs + srcLen;
114757aabac5SBogdan Liulko 	} else {
114857aabac5SBogdan Liulko 		req_dlen = srcLen;
114957aabac5SBogdan Liulko 	}
11506915bbbbSJens Wiklander 	if (destLen)
11516915bbbbSJens Wiklander 		tmp_dlen = *destLen;
11526915bbbbSJens Wiklander 	if (tmp_dlen < req_dlen) {
11536915bbbbSJens Wiklander 		if (destLen)
1154b0104773SPascal Brand 			*destLen = req_dlen;
1155dea1f2b6SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1156dea1f2b6SCedric Chaumont 		goto out;
1157b0104773SPascal Brand 	}
1158b0104773SPascal Brand 
115957aabac5SBogdan Liulko 	if (operation->block_size > 1) {
1160dea9063eSJens Wiklander 		if (srcLen) {
11612c028fdeSJerome Forissier 			res = tee_buffer_update(operation, _utee_cipher_update,
1162dea9063eSJens Wiklander 						srcData, srcLen, dst,
1163dea9063eSJens Wiklander 						&tmp_dlen);
1164dea1f2b6SCedric Chaumont 			if (res != TEE_SUCCESS)
1165dea1f2b6SCedric Chaumont 				goto out;
1166dea1f2b6SCedric Chaumont 
1167b0104773SPascal Brand 			dst += tmp_dlen;
1168b0104773SPascal Brand 			acc_dlen += tmp_dlen;
1169b0104773SPascal Brand 
1170b0104773SPascal Brand 			tmp_dlen = *destLen - acc_dlen;
1171dea9063eSJens Wiklander 		}
11722c028fdeSJerome Forissier 		res = _utee_cipher_final(operation->state, operation->buffer,
11732c028fdeSJerome Forissier 					 operation->buffer_offs, dst,
11742c028fdeSJerome Forissier 					 &tmp_dlen);
117557aabac5SBogdan Liulko 	} else {
11762c028fdeSJerome Forissier 		res = _utee_cipher_final(operation->state, srcData, srcLen, dst,
11772c028fdeSJerome Forissier 					 &tmp_dlen);
117857aabac5SBogdan Liulko 	}
1179b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1180dea1f2b6SCedric Chaumont 		goto out;
1181dea1f2b6SCedric Chaumont 
1182b0104773SPascal Brand 	acc_dlen += tmp_dlen;
11836915bbbbSJens Wiklander 	if (destLen)
1184b0104773SPascal Brand 		*destLen = acc_dlen;
1185dea1f2b6SCedric Chaumont 
1186642a1607SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1187642a1607SCedric Chaumont 
1188642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1189642a1607SCedric Chaumont 
1190dea1f2b6SCedric Chaumont out:
1191dea1f2b6SCedric Chaumont 	if (res != TEE_SUCCESS &&
1192dea1f2b6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1193b36311adSJerome Forissier 		TEE_Panic(res);
1194dea1f2b6SCedric Chaumont 
1195dea1f2b6SCedric Chaumont 	return res;
1196b0104773SPascal Brand }
1197b0104773SPascal Brand 
1198b0104773SPascal Brand /* Cryptographic Operations API - MAC Functions */
1199b0104773SPascal Brand 
12008f07fe6fSJerome Forissier void TEE_MACInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen)
1201b0104773SPascal Brand {
1202b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL)
1203b0104773SPascal Brand 		TEE_Panic(0);
1204642a1607SCedric Chaumont 
1205b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_MAC)
1206b0104773SPascal Brand 		TEE_Panic(0);
1207642a1607SCedric Chaumont 
1208642a1607SCedric Chaumont 	if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) ||
1209642a1607SCedric Chaumont 	    !(operation->key1))
1210642a1607SCedric Chaumont 		TEE_Panic(0);
1211642a1607SCedric Chaumont 
1212642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL)
1213642a1607SCedric Chaumont 		TEE_ResetOperation(operation);
1214642a1607SCedric Chaumont 
1215642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1216642a1607SCedric Chaumont 
12176d15db08SJerome Forissier 	init_hash_operation(operation, IV, IVLen);
1218b0104773SPascal Brand }
1219b0104773SPascal Brand 
12208f07fe6fSJerome Forissier void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk,
122128e0efc6SCedric Chaumont 		   uint32_t chunkSize)
1222b0104773SPascal Brand {
1223b0104773SPascal Brand 	TEE_Result res;
1224b0104773SPascal Brand 
122528e0efc6SCedric Chaumont 	if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0))
1226b0104773SPascal Brand 		TEE_Panic(0);
1227642a1607SCedric Chaumont 
122828e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC)
1229b0104773SPascal Brand 		TEE_Panic(0);
1230642a1607SCedric Chaumont 
123128e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1232b0104773SPascal Brand 		TEE_Panic(0);
1233b0104773SPascal Brand 
1234642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE)
1235642a1607SCedric Chaumont 		TEE_Panic(0);
1236642a1607SCedric Chaumont 
12372c028fdeSJerome Forissier 	res = _utee_hash_update(operation->state, chunk, chunkSize);
1238b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1239b0104773SPascal Brand 		TEE_Panic(res);
1240b0104773SPascal Brand }
1241b0104773SPascal Brand 
124228e0efc6SCedric Chaumont TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation,
12438f07fe6fSJerome Forissier 			       const void *message, uint32_t messageLen,
124479a3c601SCedric Chaumont 			       void *mac, uint32_t *macLen)
1245b0104773SPascal Brand {
1246b0104773SPascal Brand 	TEE_Result res;
1247e86f1266SJens Wiklander 	uint64_t ml;
1248b0104773SPascal Brand 
12496915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!message && messageLen)) {
125028e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
125128e0efc6SCedric Chaumont 		goto out;
125228e0efc6SCedric Chaumont 	}
12536915bbbbSJens Wiklander 	__utee_check_inout_annotation(macLen, sizeof(*macLen));
1254b0104773SPascal Brand 
125528e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC) {
125628e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
125728e0efc6SCedric Chaumont 		goto out;
125828e0efc6SCedric Chaumont 	}
125928e0efc6SCedric Chaumont 
126028e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
126128e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
126228e0efc6SCedric Chaumont 		goto out;
126328e0efc6SCedric Chaumont 	}
126428e0efc6SCedric Chaumont 
1265642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1266642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1267642a1607SCedric Chaumont 		goto out;
1268642a1607SCedric Chaumont 	}
1269642a1607SCedric Chaumont 
1270e86f1266SJens Wiklander 	ml = *macLen;
12712c028fdeSJerome Forissier 	res = _utee_hash_final(operation->state, message, messageLen, mac, &ml);
1272e86f1266SJens Wiklander 	*macLen = ml;
127328e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS)
127428e0efc6SCedric Chaumont 		goto out;
127528e0efc6SCedric Chaumont 
127628e0efc6SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
127728e0efc6SCedric Chaumont 
1278642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1279642a1607SCedric Chaumont 
128028e0efc6SCedric Chaumont out:
128128e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS &&
128228e0efc6SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
128328e0efc6SCedric Chaumont 		TEE_Panic(res);
128428e0efc6SCedric Chaumont 
1285b0104773SPascal Brand 	return res;
1286b0104773SPascal Brand }
1287b0104773SPascal Brand 
1288b0104773SPascal Brand TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation,
12898f07fe6fSJerome Forissier 			       const void *message, uint32_t messageLen,
12908f07fe6fSJerome Forissier 			       const void *mac, uint32_t macLen)
1291b0104773SPascal Brand {
1292b0104773SPascal Brand 	TEE_Result res;
1293ee4ba3d1SVictor Chong 	uint8_t computed_mac[TEE_MAX_HASH_SIZE] = { 0 };
12947f74c64aSPascal Brand 	uint32_t computed_mac_size = TEE_MAX_HASH_SIZE;
1295b0104773SPascal Brand 
129628e0efc6SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_MAC) {
129728e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
129828e0efc6SCedric Chaumont 		goto out;
129928e0efc6SCedric Chaumont 	}
130028e0efc6SCedric Chaumont 
130128e0efc6SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
130228e0efc6SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
130328e0efc6SCedric Chaumont 		goto out;
130428e0efc6SCedric Chaumont 	}
130528e0efc6SCedric Chaumont 
1306642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) {
1307642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1308642a1607SCedric Chaumont 		goto out;
1309642a1607SCedric Chaumont 	}
1310642a1607SCedric Chaumont 
1311b0104773SPascal Brand 	res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac,
1312b0104773SPascal Brand 				  &computed_mac_size);
1313b0104773SPascal Brand 	if (res != TEE_SUCCESS)
131428e0efc6SCedric Chaumont 		goto out;
131528e0efc6SCedric Chaumont 
131628e0efc6SCedric Chaumont 	if (computed_mac_size != macLen) {
131728e0efc6SCedric Chaumont 		res = TEE_ERROR_MAC_INVALID;
131828e0efc6SCedric Chaumont 		goto out;
131928e0efc6SCedric Chaumont 	}
132028e0efc6SCedric Chaumont 
132148e10604SJerome Forissier 	if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) {
132228e0efc6SCedric Chaumont 		res = TEE_ERROR_MAC_INVALID;
132328e0efc6SCedric Chaumont 		goto out;
132428e0efc6SCedric Chaumont 	}
132528e0efc6SCedric Chaumont 
1326642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1327642a1607SCedric Chaumont 
132828e0efc6SCedric Chaumont out:
132928e0efc6SCedric Chaumont 	if (res != TEE_SUCCESS &&
133028e0efc6SCedric Chaumont 	    res != TEE_ERROR_MAC_INVALID)
133128e0efc6SCedric Chaumont 		TEE_Panic(res);
133228e0efc6SCedric Chaumont 
1333b0104773SPascal Brand 	return res;
1334b0104773SPascal Brand }
1335b0104773SPascal Brand 
1336b0104773SPascal Brand /* Cryptographic Operations API - Authenticated Encryption Functions */
1337b0104773SPascal Brand 
13388f07fe6fSJerome Forissier TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce,
133979a3c601SCedric Chaumont 		      uint32_t nonceLen, uint32_t tagLen, uint32_t AADLen,
1340b0104773SPascal Brand 		      uint32_t payloadLen)
1341b0104773SPascal Brand {
1342b0104773SPascal Brand 	TEE_Result res;
1343b0104773SPascal Brand 
1344b5816c88SCedric Chaumont 	if (operation == TEE_HANDLE_NULL || nonce == NULL) {
1345b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1346b5816c88SCedric Chaumont 		goto out;
1347b5816c88SCedric Chaumont 	}
1348b5816c88SCedric Chaumont 
1349b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1350b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1351b5816c88SCedric Chaumont 		goto out;
1352b5816c88SCedric Chaumont 	}
1353b0104773SPascal Brand 
1354642a1607SCedric Chaumont 	if (operation->operationState != TEE_OPERATION_STATE_INITIAL) {
1355642a1607SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1356642a1607SCedric Chaumont 		goto out;
1357642a1607SCedric Chaumont 	}
1358642a1607SCedric Chaumont 
1359b0104773SPascal Brand 	/*
1360b0104773SPascal Brand 	 * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core
1361b0104773SPascal Brand 	 * in the implementation. But AES-GCM spec doesn't specify the tag len
1362b0104773SPascal Brand 	 * according to the same principle so we have to check here instead to
1363b0104773SPascal Brand 	 * be GP compliant.
1364b0104773SPascal Brand 	 */
1365b5816c88SCedric Chaumont 	if (operation->info.algorithm == TEE_ALG_AES_GCM) {
1366b0104773SPascal Brand 		/*
1367b0104773SPascal Brand 		 * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96
1368b0104773SPascal Brand 		 */
1369b5816c88SCedric Chaumont 		if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) {
1370b5816c88SCedric Chaumont 			res = TEE_ERROR_NOT_SUPPORTED;
1371b5816c88SCedric Chaumont 			goto out;
1372b5816c88SCedric Chaumont 		}
1373b0104773SPascal Brand 	}
1374b0104773SPascal Brand 
13752c028fdeSJerome Forissier 	res = _utee_authenc_init(operation->state, nonce, nonceLen, tagLen / 8,
13762c028fdeSJerome Forissier 				 AADLen, payloadLen);
1377b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS)
1378b5816c88SCedric Chaumont 		goto out;
1379b5816c88SCedric Chaumont 
13807acaf5adSAlbert Schwarzkopf 	operation->info.digestLength = tagLen / 8;
1381f2674567SSumit Garg 	operation->buffer_offs = 0;
1382b5816c88SCedric Chaumont 	operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED;
1383b5816c88SCedric Chaumont 
1384b5816c88SCedric Chaumont out:
1385b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1386b5816c88SCedric Chaumont 	    res != TEE_ERROR_NOT_SUPPORTED)
1387b0104773SPascal Brand 			TEE_Panic(res);
1388b5816c88SCedric Chaumont 
1389b0104773SPascal Brand 	return res;
1390b0104773SPascal Brand }
1391b0104773SPascal Brand 
13928f07fe6fSJerome Forissier void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata,
139379a3c601SCedric Chaumont 		     uint32_t AADdataLen)
1394b0104773SPascal Brand {
1395b0104773SPascal Brand 	TEE_Result res;
1396b0104773SPascal Brand 
1397b5816c88SCedric Chaumont 	if (operation == TEE_HANDLE_NULL ||
1398b5816c88SCedric Chaumont 	    (AADdata == NULL && AADdataLen != 0))
1399b0104773SPascal Brand 		TEE_Panic(0);
1400642a1607SCedric Chaumont 
1401b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE)
1402b0104773SPascal Brand 		TEE_Panic(0);
1403642a1607SCedric Chaumont 
1404b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0)
1405b0104773SPascal Brand 		TEE_Panic(0);
1406b0104773SPascal Brand 
14072c028fdeSJerome Forissier 	res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen);
1408642a1607SCedric Chaumont 
1409642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1410642a1607SCedric Chaumont 
1411b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1412b0104773SPascal Brand 		TEE_Panic(res);
1413b0104773SPascal Brand }
1414b0104773SPascal Brand 
14158f07fe6fSJerome Forissier TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData,
141679a3c601SCedric Chaumont 			uint32_t srcLen, void *destData, uint32_t *destLen)
1417b0104773SPascal Brand {
14186915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
14196915bbbbSJens Wiklander 	size_t req_dlen = 0;
14206915bbbbSJens Wiklander 	uint64_t dl = 0;
1421b0104773SPascal Brand 
14226915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1423b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1424b5816c88SCedric Chaumont 		goto out;
1425b5816c88SCedric Chaumont 	}
14266915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1427b5816c88SCedric Chaumont 
1428b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1429b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1430b5816c88SCedric Chaumont 		goto out;
1431b5816c88SCedric Chaumont 	}
1432b5816c88SCedric Chaumont 
1433b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1434b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1435b5816c88SCedric Chaumont 		goto out;
1436b5816c88SCedric Chaumont 	}
1437b0104773SPascal Brand 
1438827308b8SJerome Forissier 	if (!srcData && !srcLen) {
1439090268f5SJens Wiklander 		*destLen = 0;
1440827308b8SJerome Forissier 		res = TEE_SUCCESS;
1441827308b8SJerome Forissier 		goto out;
1442827308b8SJerome Forissier 	}
1443827308b8SJerome Forissier 
1444b0104773SPascal Brand 	/*
1445b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1446b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1447b0104773SPascal Brand 	 * can't restore sync with this API.
1448b0104773SPascal Brand 	 */
1449afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
1450b5816c88SCedric Chaumont 		req_dlen = ROUNDDOWN(operation->buffer_offs + srcLen,
1451b5816c88SCedric Chaumont 				     operation->block_size);
1452afc0c182SBogdan Liulko 	} else {
1453afc0c182SBogdan Liulko 		req_dlen = srcLen;
1454afc0c182SBogdan Liulko 	}
1455afc0c182SBogdan Liulko 
14566915bbbbSJens Wiklander 	dl = *destLen;
14576915bbbbSJens Wiklander 	if (dl < req_dlen) {
1458b0104773SPascal Brand 		*destLen = req_dlen;
1459b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1460b5816c88SCedric Chaumont 		goto out;
1461b0104773SPascal Brand 	}
1462b0104773SPascal Brand 
1463afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
14642c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1465afc0c182SBogdan Liulko 					srcData, srcLen, destData, &dl);
1466afc0c182SBogdan Liulko 	} else {
1467afc0c182SBogdan Liulko 		if (srcLen > 0) {
14682c028fdeSJerome Forissier 			res = _utee_authenc_update_payload(operation->state,
1469afc0c182SBogdan Liulko 							   srcData, srcLen,
1470afc0c182SBogdan Liulko 							   destData, &dl);
1471afc0c182SBogdan Liulko 		} else {
1472afc0c182SBogdan Liulko 			dl = 0;
1473afc0c182SBogdan Liulko 			res = TEE_SUCCESS;
1474afc0c182SBogdan Liulko 		}
1475afc0c182SBogdan Liulko 	}
1476afc0c182SBogdan Liulko 	if (res != TEE_SUCCESS)
1477afc0c182SBogdan Liulko 		goto out;
1478afc0c182SBogdan Liulko 
1479e86f1266SJens Wiklander 	*destLen = dl;
1480b0104773SPascal Brand 
1481642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_ACTIVE;
1482642a1607SCedric Chaumont 
1483b5816c88SCedric Chaumont out:
1484b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1485b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1486b5816c88SCedric Chaumont 			TEE_Panic(res);
1487b5816c88SCedric Chaumont 
1488b5816c88SCedric Chaumont 	return res;
1489b0104773SPascal Brand }
1490b0104773SPascal Brand 
1491b5816c88SCedric Chaumont TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation,
14928f07fe6fSJerome Forissier 			      const void *srcData, uint32_t srcLen,
149379a3c601SCedric Chaumont 			      void *destData, uint32_t *destLen, void *tag,
149479a3c601SCedric Chaumont 			      uint32_t *tagLen)
1495b0104773SPascal Brand {
1496b0104773SPascal Brand 	TEE_Result res;
1497b0104773SPascal Brand 	uint8_t *dst = destData;
1498b0104773SPascal Brand 	size_t acc_dlen = 0;
1499e86f1266SJens Wiklander 	uint64_t tmp_dlen;
1500b0104773SPascal Brand 	size_t req_dlen;
1501e86f1266SJens Wiklander 	uint64_t tl;
1502b0104773SPascal Brand 
15036915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1504b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1505b5816c88SCedric Chaumont 		goto out;
1506b5816c88SCedric Chaumont 	}
15076915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
15086915bbbbSJens Wiklander 	__utee_check_inout_annotation(tagLen, sizeof(*tagLen));
1509b5816c88SCedric Chaumont 
1510b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1511b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1512b5816c88SCedric Chaumont 		goto out;
1513b5816c88SCedric Chaumont 	}
1514b5816c88SCedric Chaumont 
1515b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1516b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1517b5816c88SCedric Chaumont 		goto out;
1518b5816c88SCedric Chaumont 	}
1519b0104773SPascal Brand 
1520b0104773SPascal Brand 	/*
1521b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1522b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1523b0104773SPascal Brand 	 * can't restore sync with this API.
15242733280aSEtienne Carriere 	 *
15252733280aSEtienne Carriere 	 * Need to check this before update_payload since sync would be lost if
15262733280aSEtienne Carriere 	 * we return short buffer after that.
1527b0104773SPascal Brand 	 */
15282733280aSEtienne Carriere 	res = TEE_ERROR_GENERIC;
15292733280aSEtienne Carriere 
1530b5816c88SCedric Chaumont 	req_dlen = operation->buffer_offs + srcLen;
1531b0104773SPascal Brand 	if (*destLen < req_dlen) {
1532b0104773SPascal Brand 		*destLen = req_dlen;
1533b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1534b0104773SPascal Brand 	}
1535b0104773SPascal Brand 
15367acaf5adSAlbert Schwarzkopf 	if (*tagLen < operation->info.digestLength) {
15377acaf5adSAlbert Schwarzkopf 		*tagLen = operation->info.digestLength;
1538b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1539b0104773SPascal Brand 	}
1540b0104773SPascal Brand 
15412733280aSEtienne Carriere 	if (res == TEE_ERROR_SHORT_BUFFER)
15422733280aSEtienne Carriere 		goto out;
15432733280aSEtienne Carriere 
1544afc0c182SBogdan Liulko 	tl = *tagLen;
1545b0104773SPascal Brand 	tmp_dlen = *destLen - acc_dlen;
1546afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
15472c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1548afc0c182SBogdan Liulko 					srcData, srcLen, dst, &tmp_dlen);
1549b5816c88SCedric Chaumont 		if (res != TEE_SUCCESS)
1550b5816c88SCedric Chaumont 			goto out;
1551b5816c88SCedric Chaumont 
1552b0104773SPascal Brand 		dst += tmp_dlen;
1553b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1554b0104773SPascal Brand 
1555b0104773SPascal Brand 		tmp_dlen = *destLen - acc_dlen;
15562c028fdeSJerome Forissier 		res = _utee_authenc_enc_final(operation->state,
1557afc0c182SBogdan Liulko 					      operation->buffer,
1558afc0c182SBogdan Liulko 					      operation->buffer_offs, dst,
1559afc0c182SBogdan Liulko 					      &tmp_dlen, tag, &tl);
1560afc0c182SBogdan Liulko 	} else {
15612c028fdeSJerome Forissier 		res = _utee_authenc_enc_final(operation->state, srcData,
1562afc0c182SBogdan Liulko 					      srcLen, dst, &tmp_dlen,
1563e86f1266SJens Wiklander 					      tag, &tl);
1564afc0c182SBogdan Liulko 	}
1565e86f1266SJens Wiklander 	*tagLen = tl;
1566b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1567b5816c88SCedric Chaumont 		goto out;
1568b0104773SPascal Brand 
1569b5816c88SCedric Chaumont 	acc_dlen += tmp_dlen;
1570b0104773SPascal Brand 	*destLen = acc_dlen;
1571642a1607SCedric Chaumont 
1572b5816c88SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1573b5816c88SCedric Chaumont 
1574642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1575642a1607SCedric Chaumont 
1576b5816c88SCedric Chaumont out:
1577b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1578b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER)
1579b5816c88SCedric Chaumont 			TEE_Panic(res);
1580b0104773SPascal Brand 
1581b0104773SPascal Brand 	return res;
1582b0104773SPascal Brand }
1583b0104773SPascal Brand 
1584b5816c88SCedric Chaumont TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation,
15858f07fe6fSJerome Forissier 			      const void *srcData, uint32_t srcLen,
1586b5816c88SCedric Chaumont 			      void *destData, uint32_t *destLen, void *tag,
158779a3c601SCedric Chaumont 			      uint32_t tagLen)
1588b0104773SPascal Brand {
1589b0104773SPascal Brand 	TEE_Result res;
1590b0104773SPascal Brand 	uint8_t *dst = destData;
1591b0104773SPascal Brand 	size_t acc_dlen = 0;
1592e86f1266SJens Wiklander 	uint64_t tmp_dlen;
1593b0104773SPascal Brand 	size_t req_dlen;
1594b0104773SPascal Brand 
15956915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) {
1596b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1597b5816c88SCedric Chaumont 		goto out;
1598b5816c88SCedric Chaumont 	}
15996915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
1600b5816c88SCedric Chaumont 
1601b5816c88SCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_AE) {
1602b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1603b5816c88SCedric Chaumont 		goto out;
1604b5816c88SCedric Chaumont 	}
1605b5816c88SCedric Chaumont 
1606b5816c88SCedric Chaumont 	if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) {
1607b5816c88SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
1608b5816c88SCedric Chaumont 		goto out;
1609b5816c88SCedric Chaumont 	}
1610b0104773SPascal Brand 
1611b0104773SPascal Brand 	/*
1612b0104773SPascal Brand 	 * Check that required destLen is big enough before starting to feed
1613b0104773SPascal Brand 	 * data to the algorithm. Errors during feeding of data are fatal as we
1614b0104773SPascal Brand 	 * can't restore sync with this API.
1615b0104773SPascal Brand 	 */
1616b5816c88SCedric Chaumont 	req_dlen = operation->buffer_offs + srcLen;
1617b0104773SPascal Brand 	if (*destLen < req_dlen) {
1618b0104773SPascal Brand 		*destLen = req_dlen;
1619b5816c88SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
1620b5816c88SCedric Chaumont 		goto out;
1621b0104773SPascal Brand 	}
1622b0104773SPascal Brand 
1623b0104773SPascal Brand 	tmp_dlen = *destLen - acc_dlen;
1624afc0c182SBogdan Liulko 	if (operation->block_size > 1) {
16252c028fdeSJerome Forissier 		res = tee_buffer_update(operation, _utee_authenc_update_payload,
1626afc0c182SBogdan Liulko 					srcData, srcLen, dst, &tmp_dlen);
1627b5816c88SCedric Chaumont 		if (res != TEE_SUCCESS)
1628b5816c88SCedric Chaumont 			goto out;
1629b5816c88SCedric Chaumont 
1630b0104773SPascal Brand 		dst += tmp_dlen;
1631b0104773SPascal Brand 		acc_dlen += tmp_dlen;
1632b0104773SPascal Brand 
1633b0104773SPascal Brand 		tmp_dlen = *destLen - acc_dlen;
16342c028fdeSJerome Forissier 		res = _utee_authenc_dec_final(operation->state,
1635afc0c182SBogdan Liulko 					      operation->buffer,
1636afc0c182SBogdan Liulko 					      operation->buffer_offs, dst,
1637afc0c182SBogdan Liulko 					      &tmp_dlen, tag, tagLen);
1638afc0c182SBogdan Liulko 	} else {
16392c028fdeSJerome Forissier 		res = _utee_authenc_dec_final(operation->state, srcData,
1640afc0c182SBogdan Liulko 					      srcLen, dst, &tmp_dlen,
1641b5816c88SCedric Chaumont 					      tag, tagLen);
1642afc0c182SBogdan Liulko 	}
1643b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS)
1644b5816c88SCedric Chaumont 		goto out;
1645b5816c88SCedric Chaumont 
1646b0104773SPascal Brand 	/* Supplied tagLen should match what we initiated with */
16477acaf5adSAlbert Schwarzkopf 	if (tagLen != operation->info.digestLength)
1648b0104773SPascal Brand 		res = TEE_ERROR_MAC_INVALID;
1649b0104773SPascal Brand 
1650b0104773SPascal Brand 	acc_dlen += tmp_dlen;
1651b0104773SPascal Brand 	*destLen = acc_dlen;
1652642a1607SCedric Chaumont 
1653b5816c88SCedric Chaumont 	operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED;
1654b5816c88SCedric Chaumont 
1655642a1607SCedric Chaumont 	operation->operationState = TEE_OPERATION_STATE_INITIAL;
1656642a1607SCedric Chaumont 
1657b5816c88SCedric Chaumont out:
1658b5816c88SCedric Chaumont 	if (res != TEE_SUCCESS &&
1659b5816c88SCedric Chaumont 	    res != TEE_ERROR_SHORT_BUFFER &&
1660b5816c88SCedric Chaumont 	    res != TEE_ERROR_MAC_INVALID)
1661b5816c88SCedric Chaumont 			TEE_Panic(res);
1662b0104773SPascal Brand 
1663b0104773SPascal Brand 	return res;
1664b0104773SPascal Brand }
1665b0104773SPascal Brand 
1666b0104773SPascal Brand /* Cryptographic Operations API - Asymmetric Functions */
1667b0104773SPascal Brand 
166812e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation,
16698f07fe6fSJerome Forissier 				 const TEE_Attribute *params,
16708f07fe6fSJerome Forissier 				 uint32_t paramCount, const void *srcData,
167179a3c601SCedric Chaumont 				 uint32_t srcLen, void *destData,
167279a3c601SCedric Chaumont 				 uint32_t *destLen)
1673b0104773SPascal Brand {
16746915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1675e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
16766915bbbbSJens Wiklander 	uint64_t dl = 0;
1677b0104773SPascal Brand 
16786915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
1679b0104773SPascal Brand 		TEE_Panic(0);
16806915bbbbSJens Wiklander 
16816915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
16826915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
16836915bbbbSJens Wiklander 
168412e66b6fSCedric Chaumont 	if (!operation->key1)
1685b0104773SPascal Brand 		TEE_Panic(0);
168612e66b6fSCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
168712e66b6fSCedric Chaumont 		TEE_Panic(0);
168812e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_ENCRYPT)
1689b0104773SPascal Brand 		TEE_Panic(0);
1690b0104773SPascal Brand 
1691e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
1692e86f1266SJens Wiklander 	dl = *destLen;
16932c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
1694e86f1266SJens Wiklander 				  srcLen, destData, &dl);
1695e86f1266SJens Wiklander 	*destLen = dl;
169612e66b6fSCedric Chaumont 
16978844ebfcSPascal Brand 	if (res != TEE_SUCCESS &&
16988844ebfcSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER &&
16998844ebfcSPascal Brand 	    res != TEE_ERROR_BAD_PARAMETERS)
1700b0104773SPascal Brand 		TEE_Panic(res);
170112e66b6fSCedric Chaumont 
1702b0104773SPascal Brand 	return res;
1703b0104773SPascal Brand }
1704b0104773SPascal Brand 
17054f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricEncrypt(TEE_OperationHandle operation,
17064f4374c8SJens Wiklander 					const __GP11_TEE_Attribute *params,
17074f4374c8SJens Wiklander 					uint32_t paramCount,
17084f4374c8SJens Wiklander 					const void *srcData, uint32_t srcLen,
17094f4374c8SJens Wiklander 					void *destData, uint32_t *destLen)
17104f4374c8SJens Wiklander {
17114f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
17124f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
17134f4374c8SJens Wiklander 	uint64_t dl = 0;
17144f4374c8SJens Wiklander 
17154f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
17164f4374c8SJens Wiklander 		TEE_Panic(0);
17174f4374c8SJens Wiklander 
17184f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
17194f4374c8SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
17204f4374c8SJens Wiklander 
17214f4374c8SJens Wiklander 	if (!operation->key1)
17224f4374c8SJens Wiklander 		TEE_Panic(0);
17234f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
17244f4374c8SJens Wiklander 		TEE_Panic(0);
17254f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_ENCRYPT)
17264f4374c8SJens Wiklander 		TEE_Panic(0);
17274f4374c8SJens Wiklander 
17284f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
17294f4374c8SJens Wiklander 	dl = *destLen;
17304f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
17314f4374c8SJens Wiklander 				  srcLen, destData, &dl);
17324f4374c8SJens Wiklander 	*destLen = dl;
17334f4374c8SJens Wiklander 
17344f4374c8SJens Wiklander 	if (res != TEE_SUCCESS &&
17354f4374c8SJens Wiklander 	    res != TEE_ERROR_SHORT_BUFFER &&
17364f4374c8SJens Wiklander 	    res != TEE_ERROR_BAD_PARAMETERS)
17374f4374c8SJens Wiklander 		TEE_Panic(res);
17384f4374c8SJens Wiklander 
17394f4374c8SJens Wiklander 	return res;
17404f4374c8SJens Wiklander }
17414f4374c8SJens Wiklander 
174212e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation,
17438f07fe6fSJerome Forissier 				 const TEE_Attribute *params,
17448f07fe6fSJerome Forissier 				 uint32_t paramCount, const void *srcData,
174579a3c601SCedric Chaumont 				 uint32_t srcLen, void *destData,
174679a3c601SCedric Chaumont 				 uint32_t *destLen)
1747b0104773SPascal Brand {
17486915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1749e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
17506915bbbbSJens Wiklander 	uint64_t dl = 0;
1751b0104773SPascal Brand 
17526915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
1753b0104773SPascal Brand 		TEE_Panic(0);
17546915bbbbSJens Wiklander 
17556915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
17566915bbbbSJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
17576915bbbbSJens Wiklander 
175812e66b6fSCedric Chaumont 	if (!operation->key1)
1759b0104773SPascal Brand 		TEE_Panic(0);
176012e66b6fSCedric Chaumont 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
176112e66b6fSCedric Chaumont 		TEE_Panic(0);
176212e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_DECRYPT)
1763b0104773SPascal Brand 		TEE_Panic(0);
1764b0104773SPascal Brand 
1765e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
1766e86f1266SJens Wiklander 	dl = *destLen;
17672c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
1768e86f1266SJens Wiklander 				  srcLen, destData, &dl);
1769e86f1266SJens Wiklander 	*destLen = dl;
177012e66b6fSCedric Chaumont 
17718844ebfcSPascal Brand 	if (res != TEE_SUCCESS &&
17728844ebfcSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER &&
17738844ebfcSPascal Brand 	    res != TEE_ERROR_BAD_PARAMETERS)
1774b0104773SPascal Brand 		TEE_Panic(res);
177512e66b6fSCedric Chaumont 
1776b0104773SPascal Brand 	return res;
1777b0104773SPascal Brand }
1778b0104773SPascal Brand 
17794f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricDecrypt(TEE_OperationHandle operation,
17804f4374c8SJens Wiklander 					const __GP11_TEE_Attribute *params,
17814f4374c8SJens Wiklander 					uint32_t paramCount,
17824f4374c8SJens Wiklander 					const void *srcData, uint32_t srcLen,
17834f4374c8SJens Wiklander 					void *destData, uint32_t *destLen)
17844f4374c8SJens Wiklander {
17854f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
17864f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
17874f4374c8SJens Wiklander 	uint64_t dl = 0;
17884f4374c8SJens Wiklander 
17894f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!srcData && srcLen))
17904f4374c8SJens Wiklander 		TEE_Panic(0);
17914f4374c8SJens Wiklander 
17924f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
17934f4374c8SJens Wiklander 	__utee_check_inout_annotation(destLen, sizeof(*destLen));
17944f4374c8SJens Wiklander 
17954f4374c8SJens Wiklander 	if (!operation->key1)
17964f4374c8SJens Wiklander 		TEE_Panic(0);
17974f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER)
17984f4374c8SJens Wiklander 		TEE_Panic(0);
17994f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_DECRYPT)
18004f4374c8SJens Wiklander 		TEE_Panic(0);
18014f4374c8SJens Wiklander 
18024f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
18034f4374c8SJens Wiklander 	dl = *destLen;
18044f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, srcData,
18054f4374c8SJens Wiklander 				  srcLen, destData, &dl);
18064f4374c8SJens Wiklander 	*destLen = dl;
18074f4374c8SJens Wiklander 
18084f4374c8SJens Wiklander 	if (res != TEE_SUCCESS &&
18094f4374c8SJens Wiklander 	    res != TEE_ERROR_SHORT_BUFFER &&
18104f4374c8SJens Wiklander 	    res != TEE_ERROR_BAD_PARAMETERS)
18114f4374c8SJens Wiklander 		TEE_Panic(res);
18124f4374c8SJens Wiklander 
18134f4374c8SJens Wiklander 	return res;
18144f4374c8SJens Wiklander }
18154f4374c8SJens Wiklander 
181612e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation,
18178f07fe6fSJerome Forissier 				    const TEE_Attribute *params,
18188f07fe6fSJerome Forissier 				    uint32_t paramCount, const void *digest,
181979a3c601SCedric Chaumont 				    uint32_t digestLen, void *signature,
182079a3c601SCedric Chaumont 				    uint32_t *signatureLen)
1821b0104773SPascal Brand {
18226915bbbbSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1823e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
18246915bbbbSJens Wiklander 	uint64_t sl = 0;
1825b0104773SPascal Brand 
18266915bbbbSJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen))
1827b0104773SPascal Brand 		TEE_Panic(0);
18286915bbbbSJens Wiklander 
18296915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
18306915bbbbSJens Wiklander 	__utee_check_inout_annotation(signatureLen, sizeof(*signatureLen));
18316915bbbbSJens Wiklander 
183212e66b6fSCedric Chaumont 	if (!operation->key1)
1833b0104773SPascal Brand 		TEE_Panic(0);
183412e66b6fSCedric Chaumont 	if (operation->info.operationClass !=
183512e66b6fSCedric Chaumont 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
183612e66b6fSCedric Chaumont 		TEE_Panic(0);
183712e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_SIGN)
1838b0104773SPascal Brand 		TEE_Panic(0);
1839b0104773SPascal Brand 
1840e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
1841e86f1266SJens Wiklander 	sl = *signatureLen;
18422c028fdeSJerome Forissier 	res = _utee_asymm_operate(operation->state, ua, paramCount, digest,
1843e86f1266SJens Wiklander 				  digestLen, signature, &sl);
1844e86f1266SJens Wiklander 	*signatureLen = sl;
184512e66b6fSCedric Chaumont 
1846b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)
1847b0104773SPascal Brand 		TEE_Panic(res);
184812e66b6fSCedric Chaumont 
1849b0104773SPascal Brand 	return res;
1850b0104773SPascal Brand }
1851b0104773SPascal Brand 
18524f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricSignDigest(TEE_OperationHandle operation,
18534f4374c8SJens Wiklander 					   const __GP11_TEE_Attribute *params,
18544f4374c8SJens Wiklander 					   uint32_t paramCount,
18554f4374c8SJens Wiklander 					   const void *digest,
18564f4374c8SJens Wiklander 					   uint32_t digestLen, void *signature,
18574f4374c8SJens Wiklander 					   uint32_t *signatureLen)
18584f4374c8SJens Wiklander {
18594f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
18604f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
18614f4374c8SJens Wiklander 	uint64_t sl = 0;
18624f4374c8SJens Wiklander 
18634f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen))
18644f4374c8SJens Wiklander 		TEE_Panic(0);
18654f4374c8SJens Wiklander 
18664f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
18674f4374c8SJens Wiklander 	__utee_check_inout_annotation(signatureLen, sizeof(*signatureLen));
18684f4374c8SJens Wiklander 
18694f4374c8SJens Wiklander 	if (!operation->key1)
18704f4374c8SJens Wiklander 		TEE_Panic(0);
18714f4374c8SJens Wiklander 	if (operation->info.operationClass !=
18724f4374c8SJens Wiklander 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
18734f4374c8SJens Wiklander 		TEE_Panic(0);
18744f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_SIGN)
18754f4374c8SJens Wiklander 		TEE_Panic(0);
18764f4374c8SJens Wiklander 
18774f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
18784f4374c8SJens Wiklander 	sl = *signatureLen;
18794f4374c8SJens Wiklander 	res = _utee_asymm_operate(operation->state, ua, paramCount, digest,
18804f4374c8SJens Wiklander 				  digestLen, signature, &sl);
18814f4374c8SJens Wiklander 	*signatureLen = sl;
18824f4374c8SJens Wiklander 
18834f4374c8SJens Wiklander 	if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)
18844f4374c8SJens Wiklander 		TEE_Panic(res);
18854f4374c8SJens Wiklander 
18864f4374c8SJens Wiklander 	return res;
18874f4374c8SJens Wiklander }
18884f4374c8SJens Wiklander 
188912e66b6fSCedric Chaumont TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation,
18908f07fe6fSJerome Forissier 				      const TEE_Attribute *params,
18918f07fe6fSJerome Forissier 				      uint32_t paramCount, const void *digest,
18928f07fe6fSJerome Forissier 				      uint32_t digestLen,
18938f07fe6fSJerome Forissier 				      const void *signature,
189479a3c601SCedric Chaumont 				      uint32_t signatureLen)
1895b0104773SPascal Brand {
1896b0104773SPascal Brand 	TEE_Result res;
1897e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
1898b0104773SPascal Brand 
189912e66b6fSCedric Chaumont 	if (operation == TEE_HANDLE_NULL ||
190012e66b6fSCedric Chaumont 	    (digest == NULL && digestLen != 0) ||
1901b0104773SPascal Brand 	    (signature == NULL && signatureLen != 0))
1902b0104773SPascal Brand 		TEE_Panic(0);
19036915bbbbSJens Wiklander 
19046915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
19056915bbbbSJens Wiklander 
190612e66b6fSCedric Chaumont 	if (!operation->key1)
1907b0104773SPascal Brand 		TEE_Panic(0);
190812e66b6fSCedric Chaumont 	if (operation->info.operationClass !=
190912e66b6fSCedric Chaumont 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
191012e66b6fSCedric Chaumont 		TEE_Panic(0);
191112e66b6fSCedric Chaumont 	if (operation->info.mode != TEE_MODE_VERIFY)
1912b0104773SPascal Brand 		TEE_Panic(0);
1913b0104773SPascal Brand 
1914e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
19152c028fdeSJerome Forissier 	res = _utee_asymm_verify(operation->state, ua, paramCount, digest,
191612e66b6fSCedric Chaumont 				 digestLen, signature, signatureLen);
191712e66b6fSCedric Chaumont 
1918b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID)
1919b0104773SPascal Brand 		TEE_Panic(res);
192012e66b6fSCedric Chaumont 
1921b0104773SPascal Brand 	return res;
1922b0104773SPascal Brand }
1923b0104773SPascal Brand 
19244f4374c8SJens Wiklander TEE_Result __GP11_TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation,
19254f4374c8SJens Wiklander 					     const __GP11_TEE_Attribute *params,
19264f4374c8SJens Wiklander 					     uint32_t paramCount,
19274f4374c8SJens Wiklander 					     const void *digest,
19284f4374c8SJens Wiklander 					     uint32_t digestLen,
19294f4374c8SJens Wiklander 					     const void *signature,
19304f4374c8SJens Wiklander 					     uint32_t signatureLen)
19314f4374c8SJens Wiklander {
19324f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
19334f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
19344f4374c8SJens Wiklander 
19354f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || (!digest && digestLen) ||
19364f4374c8SJens Wiklander 	    (!signature && signatureLen))
19374f4374c8SJens Wiklander 		TEE_Panic(0);
19384f4374c8SJens Wiklander 
19394f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
19404f4374c8SJens Wiklander 
19414f4374c8SJens Wiklander 	if (!operation->key1)
19424f4374c8SJens Wiklander 		TEE_Panic(0);
19434f4374c8SJens Wiklander 	if (operation->info.operationClass !=
19444f4374c8SJens Wiklander 	    TEE_OPERATION_ASYMMETRIC_SIGNATURE)
19454f4374c8SJens Wiklander 		TEE_Panic(0);
19464f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_VERIFY)
19474f4374c8SJens Wiklander 		TEE_Panic(0);
19484f4374c8SJens Wiklander 
19494f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
19504f4374c8SJens Wiklander 	res = _utee_asymm_verify(operation->state, ua, paramCount, digest,
19514f4374c8SJens Wiklander 				 digestLen, signature, signatureLen);
19524f4374c8SJens Wiklander 
19534f4374c8SJens Wiklander 	if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID)
19544f4374c8SJens Wiklander 		TEE_Panic(res);
19554f4374c8SJens Wiklander 
19564f4374c8SJens Wiklander 	return res;
19574f4374c8SJens Wiklander }
19584f4374c8SJens Wiklander 
1959b0104773SPascal Brand /* Cryptographic Operations API - Key Derivation Functions */
1960b0104773SPascal Brand 
1961b0104773SPascal Brand void TEE_DeriveKey(TEE_OperationHandle operation,
1962b0104773SPascal Brand 		   const TEE_Attribute *params, uint32_t paramCount,
1963b0104773SPascal Brand 		   TEE_ObjectHandle derivedKey)
1964b0104773SPascal Brand {
1965e86f1266SJens Wiklander 	struct utee_attribute ua[paramCount];
196675d6a373SJens Wiklander 	struct utee_object_info key_info = { };
196775d6a373SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1968b0104773SPascal Brand 
1969b0104773SPascal Brand 	if (operation == TEE_HANDLE_NULL || derivedKey == 0)
1970b0104773SPascal Brand 		TEE_Panic(0);
19716915bbbbSJens Wiklander 
19726915bbbbSJens Wiklander 	__utee_check_attr_in_annotation(params, paramCount);
19736915bbbbSJens Wiklander 
19748854d3c6SJerome Forissier 	if (TEE_ALG_GET_CLASS(operation->info.algorithm) !=
19758854d3c6SJerome Forissier 	    TEE_OPERATION_KEY_DERIVATION)
1976b0104773SPascal Brand 		TEE_Panic(0);
1977b0104773SPascal Brand 
1978b0104773SPascal Brand 	if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION)
1979b0104773SPascal Brand 		TEE_Panic(0);
198084fa9467SCedric Chaumont 	if (!operation->key1)
198184fa9467SCedric Chaumont 		TEE_Panic(0);
1982b0104773SPascal Brand 	if (operation->info.mode != TEE_MODE_DERIVE)
1983b0104773SPascal Brand 		TEE_Panic(0);
1984b0104773SPascal Brand 	if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0)
1985b0104773SPascal Brand 		TEE_Panic(0);
1986b0104773SPascal Brand 
19872c028fdeSJerome Forissier 	res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info);
1988b0104773SPascal Brand 	if (res != TEE_SUCCESS)
1989b36311adSJerome Forissier 		TEE_Panic(res);
1990b0104773SPascal Brand 
199175d6a373SJens Wiklander 	if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET)
1992b0104773SPascal Brand 		TEE_Panic(0);
199375d6a373SJens Wiklander 	if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
1994b0104773SPascal Brand 		TEE_Panic(0);
1995b0104773SPascal Brand 
1996e86f1266SJens Wiklander 	__utee_from_attr(ua, params, paramCount);
19972c028fdeSJerome Forissier 	res = _utee_cryp_derive_key(operation->state, ua, paramCount,
1998e86f1266SJens Wiklander 				    (unsigned long)derivedKey);
1999b0104773SPascal Brand 	if (res != TEE_SUCCESS)
2000b0104773SPascal Brand 		TEE_Panic(res);
2001b0104773SPascal Brand }
2002b0104773SPascal Brand 
20034f4374c8SJens Wiklander void __GP11_TEE_DeriveKey(TEE_OperationHandle operation,
20044f4374c8SJens Wiklander 			  const __GP11_TEE_Attribute *params,
20054f4374c8SJens Wiklander 			  uint32_t paramCount, TEE_ObjectHandle derivedKey)
20064f4374c8SJens Wiklander {
20074f4374c8SJens Wiklander 	struct utee_attribute ua[paramCount];
20084f4374c8SJens Wiklander 	struct utee_object_info key_info = { };
20094f4374c8SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
20104f4374c8SJens Wiklander 
20114f4374c8SJens Wiklander 	if (operation == TEE_HANDLE_NULL || derivedKey == 0)
20124f4374c8SJens Wiklander 		TEE_Panic(0);
20134f4374c8SJens Wiklander 
20144f4374c8SJens Wiklander 	__utee_check_gp11_attr_in_annotation(params, paramCount);
20154f4374c8SJens Wiklander 
20164f4374c8SJens Wiklander 	if (TEE_ALG_GET_CLASS(operation->info.algorithm) !=
20174f4374c8SJens Wiklander 	    TEE_OPERATION_KEY_DERIVATION)
20184f4374c8SJens Wiklander 		TEE_Panic(0);
20194f4374c8SJens Wiklander 
20204f4374c8SJens Wiklander 	if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION)
20214f4374c8SJens Wiklander 		TEE_Panic(0);
20224f4374c8SJens Wiklander 	if (!operation->key1)
20234f4374c8SJens Wiklander 		TEE_Panic(0);
20244f4374c8SJens Wiklander 	if (operation->info.mode != TEE_MODE_DERIVE)
20254f4374c8SJens Wiklander 		TEE_Panic(0);
20264f4374c8SJens Wiklander 	if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0)
20274f4374c8SJens Wiklander 		TEE_Panic(0);
20284f4374c8SJens Wiklander 
20294f4374c8SJens Wiklander 	res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info);
20304f4374c8SJens Wiklander 	if (res != TEE_SUCCESS)
20314f4374c8SJens Wiklander 		TEE_Panic(res);
20324f4374c8SJens Wiklander 
20334f4374c8SJens Wiklander 	if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET)
20344f4374c8SJens Wiklander 		TEE_Panic(0);
20354f4374c8SJens Wiklander 	if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
20364f4374c8SJens Wiklander 		TEE_Panic(0);
20374f4374c8SJens Wiklander 
20384f4374c8SJens Wiklander 	__utee_from_gp11_attr(ua, params, paramCount);
20394f4374c8SJens Wiklander 	res = _utee_cryp_derive_key(operation->state, ua, paramCount,
20404f4374c8SJens Wiklander 				    (unsigned long)derivedKey);
20414f4374c8SJens Wiklander 	if (res != TEE_SUCCESS)
20424f4374c8SJens Wiklander 		TEE_Panic(res);
20434f4374c8SJens Wiklander }
20444f4374c8SJens Wiklander 
2045b0104773SPascal Brand /* Cryptographic Operations API - Random Number Generation Functions */
2046b0104773SPascal Brand 
204779a3c601SCedric Chaumont void TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen)
2048b0104773SPascal Brand {
2049b0104773SPascal Brand 	TEE_Result res;
2050b0104773SPascal Brand 
20512c028fdeSJerome Forissier 	res = _utee_cryp_random_number_generate(randomBuffer, randomBufferLen);
2052b0104773SPascal Brand 	if (res != TEE_SUCCESS)
2053b0104773SPascal Brand 		TEE_Panic(res);
2054b0104773SPascal Brand }
2055433c4257SJens Wiklander 
2056433c4257SJens Wiklander int rand(void)
2057433c4257SJens Wiklander {
2058433c4257SJens Wiklander 	int rc;
2059433c4257SJens Wiklander 
2060433c4257SJens Wiklander 	TEE_GenerateRandom(&rc, sizeof(rc));
2061433c4257SJens Wiklander 
2062433c4257SJens Wiklander 	/*
2063433c4257SJens Wiklander 	 * RAND_MAX is the larges int, INT_MAX which is all bits but the
2064433c4257SJens Wiklander 	 * highest bit set.
2065433c4257SJens Wiklander 	 */
2066433c4257SJens Wiklander 	return rc & RAND_MAX;
2067433c4257SJens Wiklander }
206879170ce0SJerome Forissier 
206979170ce0SJerome Forissier TEE_Result TEE_IsAlgorithmSupported(uint32_t alg, uint32_t element)
207079170ce0SJerome Forissier {
207179170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_AES)) {
207279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
207379170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_ECB_NOPAD)
207479170ce0SJerome Forissier 				goto check_element_none;
207579170ce0SJerome Forissier 		}
207679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
207779170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CBC_NOPAD)
207879170ce0SJerome Forissier 				goto check_element_none;
207979170ce0SJerome Forissier 		}
208079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTR)) {
208179170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CTR)
208279170ce0SJerome Forissier 				goto check_element_none;
208379170ce0SJerome Forissier 		}
208479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTS)) {
208579170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CTS)
208679170ce0SJerome Forissier 				goto check_element_none;
208779170ce0SJerome Forissier 		}
208879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_XTS)) {
208979170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_XTS)
209079170ce0SJerome Forissier 				goto check_element_none;
209179170ce0SJerome Forissier 		}
209279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) {
209379170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CBC_MAC_NOPAD ||
209479170ce0SJerome Forissier 			    alg == TEE_ALG_AES_CBC_MAC_PKCS5)
209579170ce0SJerome Forissier 				goto check_element_none;
209679170ce0SJerome Forissier 		}
209779170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CMAC)) {
209879170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CMAC)
209979170ce0SJerome Forissier 				goto check_element_none;
210079170ce0SJerome Forissier 		}
210179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CCM)) {
210279170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_CCM)
210379170ce0SJerome Forissier 				goto check_element_none;
210479170ce0SJerome Forissier 		}
210579170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_GCM)) {
210679170ce0SJerome Forissier 			if (alg == TEE_ALG_AES_GCM)
210779170ce0SJerome Forissier 				goto check_element_none;
210879170ce0SJerome Forissier 		}
210979170ce0SJerome Forissier 	}
211079170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DES)) {
211179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
211279170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_ECB_NOPAD ||
211379170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_ECB_NOPAD)
211479170ce0SJerome Forissier 				goto check_element_none;
211579170ce0SJerome Forissier 		}
211679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
211779170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_CBC_NOPAD ||
211879170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_NOPAD)
211979170ce0SJerome Forissier 				goto check_element_none;
212079170ce0SJerome Forissier 		}
212179170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) {
212279170ce0SJerome Forissier 			if (alg == TEE_ALG_DES_CBC_MAC_NOPAD ||
212379170ce0SJerome Forissier 			    alg == TEE_ALG_DES_CBC_MAC_PKCS5 ||
212479170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_MAC_NOPAD ||
212579170ce0SJerome Forissier 			    alg == TEE_ALG_DES3_CBC_MAC_PKCS5)
212679170ce0SJerome Forissier 				goto check_element_none;
212779170ce0SJerome Forissier 		}
212879170ce0SJerome Forissier 	}
212979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_MD5)) {
213079170ce0SJerome Forissier 		if (alg == TEE_ALG_MD5)
213179170ce0SJerome Forissier 			goto check_element_none;
213279170ce0SJerome Forissier 	}
213379170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
213479170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA1)
213579170ce0SJerome Forissier 			goto check_element_none;
213679170ce0SJerome Forissier 	}
213779170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
213879170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA224)
213979170ce0SJerome Forissier 			goto check_element_none;
214079170ce0SJerome Forissier 	}
214179170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
214279170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA256)
214379170ce0SJerome Forissier 			goto check_element_none;
214479170ce0SJerome Forissier 	}
214579170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
214679170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA384)
214779170ce0SJerome Forissier 			goto check_element_none;
214879170ce0SJerome Forissier 	}
214979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
215079170ce0SJerome Forissier 		if (alg == TEE_ALG_SHA512)
215179170ce0SJerome Forissier 			goto check_element_none;
215279170ce0SJerome Forissier 	}
215379170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) {
215479170ce0SJerome Forissier 		if (alg == TEE_ALG_MD5SHA1)
215579170ce0SJerome Forissier 			goto check_element_none;
215679170ce0SJerome Forissier 	}
215779170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_HMAC)) {
215879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5)) {
215979170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_MD5)
216079170ce0SJerome Forissier 				goto check_element_none;
216179170ce0SJerome Forissier 		}
216279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
216379170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA1)
216479170ce0SJerome Forissier 				goto check_element_none;
216579170ce0SJerome Forissier 		}
216679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
216779170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA224)
216879170ce0SJerome Forissier 				goto check_element_none;
216979170ce0SJerome Forissier 		}
217079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
217179170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA256)
217279170ce0SJerome Forissier 				goto check_element_none;
217379170ce0SJerome Forissier 		}
217479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
217579170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA384)
217679170ce0SJerome Forissier 				goto check_element_none;
217779170ce0SJerome Forissier 		}
217879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
217979170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SHA512)
218079170ce0SJerome Forissier 				goto check_element_none;
218179170ce0SJerome Forissier 		}
218279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SM3)) {
218379170ce0SJerome Forissier 			if (alg == TEE_ALG_HMAC_SM3)
218479170ce0SJerome Forissier 				goto check_element_none;
218579170ce0SJerome Forissier 		}
218679170ce0SJerome Forissier 	}
218779170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM3)) {
218879170ce0SJerome Forissier 		if (alg == TEE_ALG_SM3)
218979170ce0SJerome Forissier 			goto check_element_none;
219079170ce0SJerome Forissier 	}
219179170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM4)) {
219279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_ECB)) {
219379170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_ECB_NOPAD)
219479170ce0SJerome Forissier 				goto check_element_none;
219579170ce0SJerome Forissier 		}
219679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CBC)) {
219779170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_CBC_NOPAD)
219879170ce0SJerome Forissier 				goto check_element_none;
219979170ce0SJerome Forissier 		}
220079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_CTR)) {
220179170ce0SJerome Forissier 			if (alg == TEE_ALG_SM4_CTR)
220279170ce0SJerome Forissier 				goto check_element_none;
220379170ce0SJerome Forissier 		}
2204696f56acSPingan Xie 		if (IS_ENABLED(CFG_CRYPTO_XTS)) {
2205696f56acSPingan Xie 			if (alg == TEE_ALG_SM4_XTS)
2206696f56acSPingan Xie 				goto check_element_none;
2207696f56acSPingan Xie 		}
220879170ce0SJerome Forissier 	}
220979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_RSA)) {
221079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5)) {
221179170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5)
221279170ce0SJerome Forissier 				goto check_element_none;
221379170ce0SJerome Forissier 		}
221479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
221579170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 ||
221679170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 ||
221779170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1)
221879170ce0SJerome Forissier 				goto check_element_none;
221979170ce0SJerome Forissier 		}
222079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) {
222179170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1)
222279170ce0SJerome Forissier 				goto check_element_none;
222379170ce0SJerome Forissier 		}
222479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
222579170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 ||
222679170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 ||
222779170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224)
222879170ce0SJerome Forissier 				goto check_element_none;
222979170ce0SJerome Forissier 		}
223079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
223179170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 ||
223279170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 ||
223379170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256)
223479170ce0SJerome Forissier 				goto check_element_none;
223579170ce0SJerome Forissier 		}
223679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA384)) {
223779170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 ||
223879170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 ||
223979170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384)
224079170ce0SJerome Forissier 				goto check_element_none;
224179170ce0SJerome Forissier 		}
224279170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA512)) {
224379170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 ||
224479170ce0SJerome Forissier 			    alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 ||
224579170ce0SJerome Forissier 			    alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512)
224679170ce0SJerome Forissier 				goto check_element_none;
224779170ce0SJerome Forissier 		}
224879170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) {
224979170ce0SJerome Forissier 			if (alg == TEE_ALG_RSASSA_PKCS1_V1_5)
225079170ce0SJerome Forissier 				goto check_element_none;
225179170ce0SJerome Forissier 		}
225279170ce0SJerome Forissier 		if (alg == TEE_ALG_RSA_NOPAD)
225379170ce0SJerome Forissier 			goto check_element_none;
225479170ce0SJerome Forissier 	}
225579170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DSA)) {
225679170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA1)) {
225779170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA1)
225879170ce0SJerome Forissier 				goto check_element_none;
225979170ce0SJerome Forissier 		}
226079170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA224)) {
226179170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA224)
226279170ce0SJerome Forissier 				goto check_element_none;
226379170ce0SJerome Forissier 		}
226479170ce0SJerome Forissier 		if (IS_ENABLED(CFG_CRYPTO_SHA256)) {
226579170ce0SJerome Forissier 			if (alg == TEE_ALG_DSA_SHA256)
226679170ce0SJerome Forissier 				goto check_element_none;
226779170ce0SJerome Forissier 		}
226879170ce0SJerome Forissier 	}
226979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_DH)) {
227079170ce0SJerome Forissier 		if (alg == TEE_ALG_DH_DERIVE_SHARED_SECRET)
227179170ce0SJerome Forissier 			goto check_element_none;
227279170ce0SJerome Forissier 	}
227379170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_ECC)) {
2274fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P192 ||
2275fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P192 ||
2276fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2277fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA1) &&
227879170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P192)
227979170ce0SJerome Forissier 			return TEE_SUCCESS;
2280fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P224 ||
2281fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P224 ||
2282fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2283fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA224) &&
228479170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P224)
228579170ce0SJerome Forissier 			return TEE_SUCCESS;
2286fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P256 ||
2287fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P256 ||
2288fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2289fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA256) &&
229079170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P256)
229179170ce0SJerome Forissier 			return TEE_SUCCESS;
2292fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P384 ||
2293fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P384 ||
2294fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2295fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA384) &&
229679170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P384)
229779170ce0SJerome Forissier 			return TEE_SUCCESS;
2298fe2fd3ffSJens Wiklander 		if ((alg == __OPTEE_ALG_ECDH_P521 ||
2299fe2fd3ffSJens Wiklander 		     alg == __OPTEE_ALG_ECDSA_P521 ||
2300fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET ||
2301fe2fd3ffSJens Wiklander 		     alg == TEE_ALG_ECDSA_SHA512) &&
230279170ce0SJerome Forissier 		    element == TEE_ECC_CURVE_NIST_P521)
230379170ce0SJerome Forissier 			return TEE_SUCCESS;
230479170ce0SJerome Forissier 	}
230579170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_DSA)) {
230679170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_DSA_SM3 && element == TEE_ECC_CURVE_SM2)
230779170ce0SJerome Forissier 			return TEE_SUCCESS;
230879170ce0SJerome Forissier 	}
230979170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_KEP)) {
231079170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_KEP && element == TEE_ECC_CURVE_SM2)
231179170ce0SJerome Forissier 			return TEE_SUCCESS;
231279170ce0SJerome Forissier 	}
231379170ce0SJerome Forissier 	if (IS_ENABLED(CFG_CRYPTO_SM2_PKE)) {
231479170ce0SJerome Forissier 		if (alg == TEE_ALG_SM2_PKE && element == TEE_ECC_CURVE_SM2)
231579170ce0SJerome Forissier 			return TEE_SUCCESS;
231679170ce0SJerome Forissier 	}
23173f61056dSSohaib ul Hassan 	if (IS_ENABLED(CFG_CRYPTO_X25519)) {
23183f61056dSSohaib ul Hassan 		if (alg == TEE_ALG_X25519 && element == TEE_ECC_CURVE_25519)
23193f61056dSSohaib ul Hassan 			return TEE_SUCCESS;
23203f61056dSSohaib ul Hassan 	}
2321e1f9cee7SSergiy Kibrik 	if (IS_ENABLED(CFG_CRYPTO_ED25519)) {
2322e1f9cee7SSergiy Kibrik 		if (alg == TEE_ALG_ED25519 && element == TEE_ECC_CURVE_25519)
2323e1f9cee7SSergiy Kibrik 			return TEE_SUCCESS;
2324e1f9cee7SSergiy Kibrik 	}
232579170ce0SJerome Forissier 
232679170ce0SJerome Forissier 	return TEE_ERROR_NOT_SUPPORTED;
232779170ce0SJerome Forissier check_element_none:
232879170ce0SJerome Forissier 	if (element == TEE_CRYPTO_ELEMENT_NONE)
232979170ce0SJerome Forissier 		return TEE_SUCCESS;
233079170ce0SJerome Forissier 	return TEE_ERROR_NOT_SUPPORTED;
233179170ce0SJerome Forissier }
2332