xref: /optee_os/ta/pkcs11/src/processing_asymm.c (revision 03e07432b68f9d78dbad4b9a8af50705948e7893)
1fb279d8bSVesa Jääskeläinen // SPDX-License-Identifier: BSD-2-Clause
2fb279d8bSVesa Jääskeläinen /*
3fb279d8bSVesa Jääskeläinen  * Copyright (c) 2018-2020, Linaro Limited
4fb279d8bSVesa Jääskeläinen  */
5fb279d8bSVesa Jääskeläinen 
6fb279d8bSVesa Jääskeläinen #include <assert.h>
7fb279d8bSVesa Jääskeläinen #include <compiler.h>
8fb279d8bSVesa Jääskeläinen #include <tee_api_defines.h>
9fb279d8bSVesa Jääskeläinen #include <tee_internal_api.h>
10fb279d8bSVesa Jääskeläinen #include <tee_internal_api_extensions.h>
11fb279d8bSVesa Jääskeläinen 
12fb279d8bSVesa Jääskeläinen #include "attributes.h"
13fb279d8bSVesa Jääskeläinen #include "pkcs11_helpers.h"
14fb279d8bSVesa Jääskeläinen #include "pkcs11_token.h"
15fb279d8bSVesa Jääskeläinen #include "processing.h"
16fb279d8bSVesa Jääskeläinen #include "serializer.h"
17fb279d8bSVesa Jääskeläinen 
18fb279d8bSVesa Jääskeläinen bool processing_is_tee_asymm(uint32_t proc_id)
19fb279d8bSVesa Jääskeläinen {
20fb279d8bSVesa Jääskeläinen 	switch (proc_id) {
210442c956SVesa Jääskeläinen 	/* RSA flavors */
220442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
23dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
24d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
250442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
260442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
270442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
280442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
290442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
300442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
31d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
32d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
33d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
34d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
35d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
36fb279d8bSVesa Jääskeläinen 	/* EC flavors */
37*03e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
38fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
39cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
40fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
41fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
42fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
43fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
44fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
45fb279d8bSVesa Jääskeläinen 		return true;
46fb279d8bSVesa Jääskeläinen 	default:
47fb279d8bSVesa Jääskeläinen 		return false;
48fb279d8bSVesa Jääskeläinen 	}
49fb279d8bSVesa Jääskeläinen }
50fb279d8bSVesa Jääskeläinen 
51fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
52fb279d8bSVesa Jääskeläinen pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id,
53fb279d8bSVesa Jääskeläinen 		   enum processing_func function __unused,
54fb279d8bSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params,
55fb279d8bSVesa Jääskeläinen 		   struct pkcs11_object *obj)
56fb279d8bSVesa Jääskeläinen {
57fb279d8bSVesa Jääskeläinen 	static const struct {
58fb279d8bSVesa Jääskeläinen 		enum pkcs11_mechanism_id mech_id;
59fb279d8bSVesa Jääskeläinen 		uint32_t tee_id;
60fb279d8bSVesa Jääskeläinen 		uint32_t tee_hash_id;
61fb279d8bSVesa Jääskeläinen 	} pkcs2tee_algo[] = {
620442c956SVesa Jääskeläinen 		/* RSA flavors */
630442c956SVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5, 0 },
64dc8c77fcSVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS_OAEP, 1, 0 },
65d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS_PSS, 1, 0 },
660442c956SVesa Jääskeläinen 		{ PKCS11_CKM_MD5_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_MD5,
670442c956SVesa Jääskeläinen 		  TEE_ALG_MD5 },
680442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1,
690442c956SVesa Jääskeläinen 		  TEE_ALG_SHA1 },
700442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA224_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224,
710442c956SVesa Jääskeläinen 		  TEE_ALG_SHA224 },
720442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA256_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256,
730442c956SVesa Jääskeläinen 		  TEE_ALG_SHA256 },
740442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA384_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384,
750442c956SVesa Jääskeläinen 		  TEE_ALG_SHA384 },
760442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA512_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512,
770442c956SVesa Jääskeläinen 		  TEE_ALG_SHA512 },
78d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA1_RSA_PKCS_PSS,
79d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, TEE_ALG_SHA1 },
80d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA224_RSA_PKCS_PSS,
81d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, TEE_ALG_SHA224 },
82d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA256_RSA_PKCS_PSS,
83d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, TEE_ALG_SHA256 },
84d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA384_RSA_PKCS_PSS,
85d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, TEE_ALG_SHA384 },
86d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA512_RSA_PKCS_PSS,
87d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, TEE_ALG_SHA512 },
88fb279d8bSVesa Jääskeläinen 		/* EC flavors (Must find key size from the object) */
89fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA, 1, 0 },
90fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA1, 1, TEE_ALG_SHA1 },
91fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA224, 1, TEE_ALG_SHA224 },
92fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA256, 1, TEE_ALG_SHA256 },
93fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA384, 1, TEE_ALG_SHA384 },
94fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA512, 1, TEE_ALG_SHA512 },
95cc062b46SJorge Ramirez-Ortiz 		{ PKCS11_CKM_ECDH1_DERIVE, 1, 0 },
96*03e07432SValerii Chubar 		{ PKCS11_CKM_EDDSA, TEE_ALG_ED25519, 0 },
97fb279d8bSVesa Jääskeläinen 	};
98fb279d8bSVesa Jääskeläinen 	size_t n = 0;
99fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
100fb279d8bSVesa Jääskeläinen 
101fb279d8bSVesa Jääskeläinen 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
102fb279d8bSVesa Jääskeläinen 		if (pkcs2tee_algo[n].mech_id == proc_params->id) {
103fb279d8bSVesa Jääskeläinen 			*tee_id = pkcs2tee_algo[n].tee_id;
104fb279d8bSVesa Jääskeläinen 			*tee_hash_id = pkcs2tee_algo[n].tee_hash_id;
105fb279d8bSVesa Jääskeläinen 			break;
106fb279d8bSVesa Jääskeläinen 		}
107fb279d8bSVesa Jääskeläinen 	}
108fb279d8bSVesa Jääskeläinen 
109fb279d8bSVesa Jääskeläinen 	if (n == ARRAY_SIZE(pkcs2tee_algo))
110fb279d8bSVesa Jääskeläinen 		return PKCS11_RV_NOT_IMPLEMENTED;
111fb279d8bSVesa Jääskeläinen 
112fb279d8bSVesa Jääskeläinen 	switch (proc_params->id) {
113d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
114d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
115d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
116d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
117d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
118d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
119d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_algo_rsa_pss(tee_id, proc_params);
120d9af50bcSVesa Jääskeläinen 		break;
121dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
122dc8c77fcSVesa Jääskeläinen 		rc = pkcs2tee_algo_rsa_oaep(tee_id, tee_hash_id, proc_params);
123dc8c77fcSVesa Jääskeläinen 		break;
124fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
125fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
126fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
127fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
128fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
129fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
130fb279d8bSVesa Jääskeläinen 		rc = pkcs2tee_algo_ecdsa(tee_id, proc_params, obj);
131fb279d8bSVesa Jääskeläinen 		break;
132cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
133cc062b46SJorge Ramirez-Ortiz 		rc = pkcs2tee_algo_ecdh(tee_id, proc_params, obj);
134cc062b46SJorge Ramirez-Ortiz 		break;
135fb279d8bSVesa Jääskeläinen 	default:
136fb279d8bSVesa Jääskeläinen 		rc = PKCS11_CKR_OK;
137fb279d8bSVesa Jääskeläinen 		break;
138fb279d8bSVesa Jääskeläinen 	}
139fb279d8bSVesa Jääskeläinen 
1400442c956SVesa Jääskeläinen 	/*
1410442c956SVesa Jääskeläinen 	 * PKCS#11 uses single mechanism CKM_RSA_PKCS for both ciphering and
1420442c956SVesa Jääskeläinen 	 * authentication whereas GPD TEE expects TEE_ALG_RSAES_PKCS1_V1_5 for
1430442c956SVesa Jääskeläinen 	 * ciphering and TEE_ALG_RSASSA_PKCS1_V1_5 for authentication.
1440442c956SVesa Jääskeläinen 	 */
1450442c956SVesa Jääskeläinen 	if (*tee_id == TEE_ALG_RSAES_PKCS1_V1_5 &&
1460442c956SVesa Jääskeläinen 	    (function == PKCS11_FUNCTION_SIGN ||
1470442c956SVesa Jääskeläinen 	     function == PKCS11_FUNCTION_VERIFY))
1480442c956SVesa Jääskeläinen 		*tee_id = TEE_ALG_RSASSA_PKCS1_V1_5;
1490442c956SVesa Jääskeläinen 
150fb279d8bSVesa Jääskeläinen 	return rc;
151fb279d8bSVesa Jääskeläinen }
152fb279d8bSVesa Jääskeläinen 
153fb279d8bSVesa Jääskeläinen static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type,
154fb279d8bSVesa Jääskeläinen 					struct pkcs11_object *obj,
155fb279d8bSVesa Jääskeläinen 					enum processing_func function)
156fb279d8bSVesa Jääskeläinen {
157fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id class = get_class(obj->attributes);
158fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
159fb279d8bSVesa Jääskeläinen 
160fb279d8bSVesa Jääskeläinen 	switch (class) {
161fb279d8bSVesa Jääskeläinen 	case PKCS11_CKO_PUBLIC_KEY:
162fb279d8bSVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
163fb279d8bSVesa Jääskeläinen 		break;
164fb279d8bSVesa Jääskeläinen 	default:
165fb279d8bSVesa Jääskeläinen 		TEE_Panic(class);
166fb279d8bSVesa Jääskeläinen 		break;
167fb279d8bSVesa Jääskeläinen 	}
168fb279d8bSVesa Jääskeläinen 
169fb279d8bSVesa Jääskeläinen 	switch (type) {
170fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
171cc062b46SJorge Ramirez-Ortiz 		if (class == PKCS11_CKO_PRIVATE_KEY) {
172cc062b46SJorge Ramirez-Ortiz 			if (function == PKCS11_FUNCTION_DERIVE)
173cc062b46SJorge Ramirez-Ortiz 				*tee_type = TEE_TYPE_ECDH_KEYPAIR;
174cc062b46SJorge Ramirez-Ortiz 			else
175fb279d8bSVesa Jääskeläinen 				*tee_type = TEE_TYPE_ECDSA_KEYPAIR;
176cc062b46SJorge Ramirez-Ortiz 		} else {
177cc062b46SJorge Ramirez-Ortiz 			if (function == PKCS11_FUNCTION_DERIVE)
178cc062b46SJorge Ramirez-Ortiz 				*tee_type = TEE_TYPE_ECDH_PUBLIC_KEY;
179fb279d8bSVesa Jääskeläinen 			else
180fb279d8bSVesa Jääskeläinen 				*tee_type = TEE_TYPE_ECDSA_PUBLIC_KEY;
181cc062b46SJorge Ramirez-Ortiz 		}
182fb279d8bSVesa Jääskeläinen 		break;
1830442c956SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
1840442c956SVesa Jääskeläinen 		if (class == PKCS11_CKO_PRIVATE_KEY)
1850442c956SVesa Jääskeläinen 			*tee_type = TEE_TYPE_RSA_KEYPAIR;
1860442c956SVesa Jääskeläinen 		else
1870442c956SVesa Jääskeläinen 			*tee_type = TEE_TYPE_RSA_PUBLIC_KEY;
1880442c956SVesa Jääskeläinen 		break;
189*03e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
190*03e07432SValerii Chubar 		if (class == PKCS11_CKO_PRIVATE_KEY)
191*03e07432SValerii Chubar 			*tee_type = TEE_TYPE_ED25519_KEYPAIR;
192*03e07432SValerii Chubar 		else
193*03e07432SValerii Chubar 			*tee_type = TEE_TYPE_ED25519_PUBLIC_KEY;
194*03e07432SValerii Chubar 		break;
195fb279d8bSVesa Jääskeläinen 	default:
196fb279d8bSVesa Jääskeläinen 		TEE_Panic(type);
197fb279d8bSVesa Jääskeläinen 		break;
198fb279d8bSVesa Jääskeläinen 	}
199fb279d8bSVesa Jääskeläinen 
200fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
201fb279d8bSVesa Jääskeläinen }
202fb279d8bSVesa Jääskeläinen 
203fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
204fb279d8bSVesa Jääskeläinen allocate_tee_operation(struct pkcs11_session *session,
205fb279d8bSVesa Jääskeläinen 		       enum processing_func function,
206fb279d8bSVesa Jääskeläinen 		       struct pkcs11_attribute_head *params,
207fb279d8bSVesa Jääskeläinen 		       struct pkcs11_object *obj)
208fb279d8bSVesa Jääskeläinen {
209fb279d8bSVesa Jääskeläinen 	uint32_t size = (uint32_t)get_object_key_bit_size(obj);
210fb279d8bSVesa Jääskeläinen 	uint32_t algo = 0;
211fb279d8bSVesa Jääskeläinen 	uint32_t hash_algo = 0;
212fb279d8bSVesa Jääskeläinen 	uint32_t mode = 0;
213fb279d8bSVesa Jääskeläinen 	uint32_t hash_mode = 0;
214fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
215fb279d8bSVesa Jääskeläinen 	struct active_processing *processing = session->processing;
216fb279d8bSVesa Jääskeläinen 
217fb279d8bSVesa Jääskeläinen 	assert(processing->tee_op_handle == TEE_HANDLE_NULL);
218fb279d8bSVesa Jääskeläinen 	assert(processing->tee_hash_op_handle == TEE_HANDLE_NULL);
219fb279d8bSVesa Jääskeläinen 
220fb279d8bSVesa Jääskeläinen 	if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj))
221fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_FUNCTION_FAILED;
222fb279d8bSVesa Jääskeläinen 
223fb279d8bSVesa Jääskeläinen 	pkcs2tee_mode(&mode, function);
224fb279d8bSVesa Jääskeläinen 
225fb279d8bSVesa Jääskeläinen 	if (hash_algo) {
226fb279d8bSVesa Jääskeläinen 		pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST);
227fb279d8bSVesa Jääskeläinen 
228fb279d8bSVesa Jääskeläinen 		res = TEE_AllocateOperation(&processing->tee_hash_op_handle,
229fb279d8bSVesa Jääskeläinen 					    hash_algo, hash_mode, 0);
230fb279d8bSVesa Jääskeläinen 		if (res) {
231fb279d8bSVesa Jääskeläinen 			EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32,
232fb279d8bSVesa Jääskeläinen 			     hash_algo, hash_mode);
233fb279d8bSVesa Jääskeläinen 
234fb279d8bSVesa Jääskeläinen 			if (res == TEE_ERROR_NOT_SUPPORTED)
235fb279d8bSVesa Jääskeläinen 				return PKCS11_CKR_MECHANISM_INVALID;
236fb279d8bSVesa Jääskeläinen 			return tee2pkcs_error(res);
237fb279d8bSVesa Jääskeläinen 		}
238fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = hash_algo;
239fb279d8bSVesa Jääskeläinen 	}
240fb279d8bSVesa Jääskeläinen 
241fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateOperation(&processing->tee_op_handle,
242fb279d8bSVesa Jääskeläinen 				    algo, mode, size);
243fb279d8bSVesa Jääskeläinen 	if (res)
244fb279d8bSVesa Jääskeläinen 		EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32,
245fb279d8bSVesa Jääskeläinen 		     algo, mode, size);
246fb279d8bSVesa Jääskeläinen 
247fb279d8bSVesa Jääskeläinen 	if (res == TEE_ERROR_NOT_SUPPORTED)
248fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_MECHANISM_INVALID;
249fb279d8bSVesa Jääskeläinen 
250fb279d8bSVesa Jääskeläinen 	if (res != TEE_SUCCESS &&
251fb279d8bSVesa Jääskeläinen 	    processing->tee_hash_op_handle != TEE_HANDLE_NULL) {
252fb279d8bSVesa Jääskeläinen 		TEE_FreeOperation(session->processing->tee_hash_op_handle);
253fb279d8bSVesa Jääskeläinen 		processing->tee_hash_op_handle = TEE_HANDLE_NULL;
254fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = 0;
255fb279d8bSVesa Jääskeläinen 	}
256fb279d8bSVesa Jääskeläinen 
257fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
258fb279d8bSVesa Jääskeläinen }
259fb279d8bSVesa Jääskeläinen 
260fb279d8bSVesa Jääskeläinen static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
261fb279d8bSVesa Jääskeläinen 				   struct pkcs11_object *obj,
262fb279d8bSVesa Jääskeläinen 				   enum processing_func function)
263fb279d8bSVesa Jääskeläinen {
264fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
265fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
266fb279d8bSVesa Jääskeläinen 	size_t object_size = 0;
267fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
268fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
269fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id __maybe_unused class = get_class(obj->attributes);
270fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
271fb279d8bSVesa Jääskeläinen 
272fb279d8bSVesa Jääskeläinen 	assert(class == PKCS11_CKO_PUBLIC_KEY ||
273fb279d8bSVesa Jääskeläinen 	       class == PKCS11_CKO_PRIVATE_KEY);
274fb279d8bSVesa Jääskeläinen 
275fb279d8bSVesa Jääskeläinen 	if (obj->key_handle != TEE_HANDLE_NULL) {
276fb279d8bSVesa Jääskeläinen 		switch (type) {
2770442c956SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
2780442c956SVesa Jääskeläinen 			/* RSA loaded keys can be reused */
2790442c956SVesa Jääskeläinen 			assert((obj->key_type == TEE_TYPE_RSA_PUBLIC_KEY &&
2800442c956SVesa Jääskeläinen 				class == PKCS11_CKO_PUBLIC_KEY) ||
2810442c956SVesa Jääskeläinen 			       (obj->key_type == TEE_TYPE_RSA_KEYPAIR &&
2820442c956SVesa Jääskeläinen 				class == PKCS11_CKO_PRIVATE_KEY));
2830442c956SVesa Jääskeläinen 			goto key_ready;
284fb279d8bSVesa Jääskeläinen 		case PKCS11_CKK_EC:
285fb279d8bSVesa Jääskeläinen 			/* Reuse EC TEE key only if already DSA or DH */
286fb279d8bSVesa Jääskeläinen 			switch (obj->key_type) {
287fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_PUBLIC_KEY:
288fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_KEYPAIR:
289fb279d8bSVesa Jääskeläinen 				if (function != PKCS11_FUNCTION_DERIVE)
290fb279d8bSVesa Jääskeläinen 					goto key_ready;
291fb279d8bSVesa Jääskeläinen 				break;
292cc062b46SJorge Ramirez-Ortiz 			case TEE_TYPE_ECDH_PUBLIC_KEY:
293cc062b46SJorge Ramirez-Ortiz 			case TEE_TYPE_ECDH_KEYPAIR:
294cc062b46SJorge Ramirez-Ortiz 				if (function == PKCS11_FUNCTION_DERIVE)
295cc062b46SJorge Ramirez-Ortiz 					goto key_ready;
296cc062b46SJorge Ramirez-Ortiz 				break;
297fb279d8bSVesa Jääskeläinen 			default:
298fb279d8bSVesa Jääskeläinen 				assert(0);
299fb279d8bSVesa Jääskeläinen 				break;
300fb279d8bSVesa Jääskeläinen 			}
301fb279d8bSVesa Jääskeläinen 			break;
302fb279d8bSVesa Jääskeläinen 		default:
303fb279d8bSVesa Jääskeläinen 			assert(0);
304fb279d8bSVesa Jääskeläinen 			break;
305fb279d8bSVesa Jääskeläinen 		}
306fb279d8bSVesa Jääskeläinen 
307fb279d8bSVesa Jääskeläinen 		TEE_CloseObject(obj->key_handle);
308fb279d8bSVesa Jääskeläinen 		obj->key_handle = TEE_HANDLE_NULL;
309fb279d8bSVesa Jääskeläinen 	}
310fb279d8bSVesa Jääskeläinen 
311fb279d8bSVesa Jääskeläinen 	rc = pkcs2tee_key_type(&obj->key_type, obj, function);
312fb279d8bSVesa Jääskeläinen 	if (rc)
313fb279d8bSVesa Jääskeläinen 		return rc;
314fb279d8bSVesa Jääskeläinen 
315fb279d8bSVesa Jääskeläinen 	object_size = get_object_key_bit_size(obj);
316fb279d8bSVesa Jääskeläinen 	if (!object_size)
317fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
318fb279d8bSVesa Jääskeläinen 
319fb279d8bSVesa Jääskeläinen 	switch (type) {
3200442c956SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
3210442c956SVesa Jääskeläinen 		rc = load_tee_rsa_key_attrs(&tee_attrs, &tee_attrs_count, obj);
3220442c956SVesa Jääskeläinen 		break;
323fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
324fb279d8bSVesa Jääskeläinen 		rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj);
325fb279d8bSVesa Jääskeläinen 		break;
326*03e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
327*03e07432SValerii Chubar 		rc = load_tee_eddsa_key_attrs(&tee_attrs, &tee_attrs_count,
328*03e07432SValerii Chubar 					      obj);
329*03e07432SValerii Chubar 		break;
330fb279d8bSVesa Jääskeläinen 	default:
331fb279d8bSVesa Jääskeläinen 		break;
332fb279d8bSVesa Jääskeläinen 	}
333fb279d8bSVesa Jääskeläinen 	if (rc)
334fb279d8bSVesa Jääskeläinen 		return rc;
335fb279d8bSVesa Jääskeläinen 
336fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateTransientObject(obj->key_type, object_size,
337fb279d8bSVesa Jääskeläinen 					  &obj->key_handle);
338fb279d8bSVesa Jääskeläinen 	if (res) {
339fb279d8bSVesa Jääskeläinen 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
340fb279d8bSVesa Jääskeläinen 
341fb279d8bSVesa Jääskeläinen 		return tee2pkcs_error(res);
342fb279d8bSVesa Jääskeläinen 	}
343fb279d8bSVesa Jääskeläinen 
344fb279d8bSVesa Jääskeläinen 	res = TEE_PopulateTransientObject(obj->key_handle,
345fb279d8bSVesa Jääskeläinen 					  tee_attrs, tee_attrs_count);
346fb279d8bSVesa Jääskeläinen 
347fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
348fb279d8bSVesa Jääskeläinen 
349fb279d8bSVesa Jääskeläinen 	if (res) {
350fb279d8bSVesa Jääskeläinen 		DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res);
351fb279d8bSVesa Jääskeläinen 
352fb279d8bSVesa Jääskeläinen 		goto error;
353fb279d8bSVesa Jääskeläinen 	}
354fb279d8bSVesa Jääskeläinen 
355fb279d8bSVesa Jääskeläinen key_ready:
356fb279d8bSVesa Jääskeläinen 	res = TEE_SetOperationKey(session->processing->tee_op_handle,
357fb279d8bSVesa Jääskeläinen 				  obj->key_handle);
358fb279d8bSVesa Jääskeläinen 	if (res) {
359fb279d8bSVesa Jääskeläinen 		DMSG("TEE_SetOperationKey failed, %#"PRIx32, res);
360fb279d8bSVesa Jääskeläinen 
361fb279d8bSVesa Jääskeläinen 		goto error;
362fb279d8bSVesa Jääskeläinen 	}
363fb279d8bSVesa Jääskeläinen 
364fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
365fb279d8bSVesa Jääskeläinen 
366fb279d8bSVesa Jääskeläinen error:
367fb279d8bSVesa Jääskeläinen 	TEE_FreeTransientObject(obj->key_handle);
368fb279d8bSVesa Jääskeläinen 	obj->key_handle = TEE_HANDLE_NULL;
369fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
370fb279d8bSVesa Jääskeläinen }
371fb279d8bSVesa Jääskeläinen 
372fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
373d9af50bcSVesa Jääskeläinen init_tee_operation(struct pkcs11_session *session,
374d9af50bcSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params,
375d9af50bcSVesa Jääskeläinen 		   struct pkcs11_object *obj)
376fb279d8bSVesa Jääskeläinen {
377d9af50bcSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
378d9af50bcSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
379d9af50bcSVesa Jääskeläinen 
380d9af50bcSVesa Jääskeläinen 	switch (proc_params->id) {
381d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
382d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
383d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
384d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
385d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
386d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
387d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_proc_params_rsa_pss(proc, proc_params);
388d9af50bcSVesa Jääskeläinen 		if (rc)
389d9af50bcSVesa Jääskeläinen 			break;
390d9af50bcSVesa Jääskeläinen 
391d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_validate_rsa_pss(proc, obj);
392d9af50bcSVesa Jääskeläinen 		break;
393dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
394dc8c77fcSVesa Jääskeläinen 		rc = pkcs2tee_proc_params_rsa_oaep(proc, proc_params);
395dc8c77fcSVesa Jääskeläinen 		break;
396*03e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
397*03e07432SValerii Chubar 		rc = pkcs2tee_proc_params_eddsa(proc, proc_params);
398*03e07432SValerii Chubar 		break;
399d9af50bcSVesa Jääskeläinen 	default:
400d9af50bcSVesa Jääskeläinen 		break;
401d9af50bcSVesa Jääskeläinen 	}
402d9af50bcSVesa Jääskeläinen 
403d9af50bcSVesa Jääskeläinen 	return rc;
404fb279d8bSVesa Jääskeläinen }
405fb279d8bSVesa Jääskeläinen 
406fb279d8bSVesa Jääskeläinen enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session,
407fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
408fb279d8bSVesa Jääskeläinen 				    struct pkcs11_attribute_head *proc_params,
409fb279d8bSVesa Jääskeläinen 				    struct pkcs11_object *obj)
410fb279d8bSVesa Jääskeläinen {
411fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
412fb279d8bSVesa Jääskeläinen 
413fb279d8bSVesa Jääskeläinen 	assert(processing_is_tee_asymm(proc_params->id));
414fb279d8bSVesa Jääskeläinen 
415fb279d8bSVesa Jääskeläinen 	rc = allocate_tee_operation(session, function, proc_params, obj);
416fb279d8bSVesa Jääskeläinen 	if (rc)
417fb279d8bSVesa Jääskeläinen 		return rc;
418fb279d8bSVesa Jääskeläinen 
419fb279d8bSVesa Jääskeläinen 	rc = load_tee_key(session, obj, function);
420fb279d8bSVesa Jääskeläinen 	if (rc)
421fb279d8bSVesa Jääskeläinen 		return rc;
422fb279d8bSVesa Jääskeläinen 
423d9af50bcSVesa Jääskeläinen 	return init_tee_operation(session, proc_params, obj);
424fb279d8bSVesa Jääskeläinen }
425fb279d8bSVesa Jääskeläinen 
426fb279d8bSVesa Jääskeläinen /*
427fb279d8bSVesa Jääskeläinen  * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation
428fb279d8bSVesa Jääskeläinen  *
429fb279d8bSVesa Jääskeläinen  * @session - current session
430fb279d8bSVesa Jääskeläinen  * @function - processing function (encrypt, decrypt, sign, ...)
431fb279d8bSVesa Jääskeläinen  * @step - step ID in the processing (oneshot, update, final)
432fb279d8bSVesa Jääskeläinen  * @ptypes - invocation parameter types
433fb279d8bSVesa Jääskeläinen  * @params - invocation parameter references
434fb279d8bSVesa Jääskeläinen  */
435fb279d8bSVesa Jääskeläinen enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
436fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
437fb279d8bSVesa Jääskeläinen 				    enum processing_step step,
438fb279d8bSVesa Jääskeläinen 				    uint32_t ptypes, TEE_Param *params)
439fb279d8bSVesa Jääskeläinen {
440fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
441fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
442fb279d8bSVesa Jääskeläinen 	void *in_buf = NULL;
443fb279d8bSVesa Jääskeläinen 	void *in2_buf = NULL;
444fb279d8bSVesa Jääskeläinen 	void *out_buf = NULL;
445fb279d8bSVesa Jääskeläinen 	void *hash_buf = NULL;
446fb279d8bSVesa Jääskeläinen 	uint32_t in_size = 0;
447fb279d8bSVesa Jääskeläinen 	uint32_t in2_size = 0;
448fb279d8bSVesa Jääskeläinen 	uint32_t out_size = 0;
449fb279d8bSVesa Jääskeläinen 	uint32_t hash_size = 0;
450fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
451fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
452fb279d8bSVesa Jääskeläinen 	bool output_data = false;
453fb279d8bSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
454dc8c77fcSVesa Jääskeläinen 	struct rsa_oaep_processing_ctx *rsa_oaep_ctx = NULL;
455d9af50bcSVesa Jääskeläinen 	struct rsa_pss_processing_ctx *rsa_pss_ctx = NULL;
456*03e07432SValerii Chubar 	struct eddsa_processing_ctx *eddsa_ctx = NULL;
457fb279d8bSVesa Jääskeläinen 	size_t sz = 0;
458fb279d8bSVesa Jääskeläinen 
459fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
460fb279d8bSVesa Jääskeläinen 		in_buf = params[1].memref.buffer;
461fb279d8bSVesa Jääskeläinen 		in_size = params[1].memref.size;
462fb279d8bSVesa Jääskeläinen 		if (in_size && !in_buf)
463fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
464fb279d8bSVesa Jääskeläinen 	}
465fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) {
466fb279d8bSVesa Jääskeläinen 		in2_buf = params[2].memref.buffer;
467fb279d8bSVesa Jääskeläinen 		in2_size = params[2].memref.size;
468fb279d8bSVesa Jääskeläinen 		if (in2_size && !in2_buf)
469fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
470fb279d8bSVesa Jääskeläinen 	}
471fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
472fb279d8bSVesa Jääskeläinen 		out_buf = params[2].memref.buffer;
473fb279d8bSVesa Jääskeläinen 		out_size = params[2].memref.size;
474fb279d8bSVesa Jääskeläinen 		if (out_size && !out_buf)
475fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
476fb279d8bSVesa Jääskeläinen 	}
477fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
478fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
479fb279d8bSVesa Jääskeläinen 
480fb279d8bSVesa Jääskeläinen 	switch (step) {
481fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_ONESHOT:
482fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE:
483fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_FINAL:
484fb279d8bSVesa Jääskeläinen 		break;
485fb279d8bSVesa Jääskeläinen 	default:
486fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
487fb279d8bSVesa Jääskeläinen 	}
488fb279d8bSVesa Jääskeläinen 
489d9af50bcSVesa Jääskeläinen 	/* TEE attribute(s) required by the operation */
490d9af50bcSVesa Jääskeläinen 	switch (proc->mecha_type) {
491d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
492d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
493d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
494d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
495d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
496d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
497d9af50bcSVesa Jääskeläinen 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
498d9af50bcSVesa Jääskeläinen 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
499d9af50bcSVesa Jääskeläinen 		if (!tee_attrs) {
500d9af50bcSVesa Jääskeläinen 			rc = PKCS11_CKR_DEVICE_MEMORY;
501d9af50bcSVesa Jääskeläinen 			goto out;
502d9af50bcSVesa Jääskeläinen 		}
503d9af50bcSVesa Jääskeläinen 
504d9af50bcSVesa Jääskeläinen 		rsa_pss_ctx = proc->extra_ctx;
505d9af50bcSVesa Jääskeläinen 
506d9af50bcSVesa Jääskeläinen 		TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
507d9af50bcSVesa Jääskeläinen 				       TEE_ATTR_RSA_PSS_SALT_LENGTH,
508d9af50bcSVesa Jääskeläinen 				       rsa_pss_ctx->salt_len, 0);
509d9af50bcSVesa Jääskeläinen 		tee_attrs_count++;
510d9af50bcSVesa Jääskeläinen 		break;
511*03e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
512*03e07432SValerii Chubar 		eddsa_ctx = proc->extra_ctx;
513*03e07432SValerii Chubar 
514*03e07432SValerii Chubar 		tee_attrs = TEE_Malloc(2 * sizeof(TEE_Attribute),
515*03e07432SValerii Chubar 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
516*03e07432SValerii Chubar 		if (!tee_attrs) {
517*03e07432SValerii Chubar 			rc = PKCS11_CKR_DEVICE_MEMORY;
518*03e07432SValerii Chubar 			goto out;
519*03e07432SValerii Chubar 		}
520*03e07432SValerii Chubar 
521*03e07432SValerii Chubar 		if (eddsa_ctx->flag) {
522*03e07432SValerii Chubar 			TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
523*03e07432SValerii Chubar 					       TEE_ATTR_EDDSA_PREHASH, 0, 0);
524*03e07432SValerii Chubar 			tee_attrs_count++;
525*03e07432SValerii Chubar 		}
526*03e07432SValerii Chubar 
527*03e07432SValerii Chubar 		if (eddsa_ctx->ctx_len > 0) {
528*03e07432SValerii Chubar 			TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
529*03e07432SValerii Chubar 					     TEE_ATTR_EDDSA_CTX, eddsa_ctx->ctx,
530*03e07432SValerii Chubar 					     eddsa_ctx->ctx_len);
531*03e07432SValerii Chubar 			tee_attrs_count++;
532*03e07432SValerii Chubar 		}
533*03e07432SValerii Chubar 		break;
534dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
535dc8c77fcSVesa Jääskeläinen 		rsa_oaep_ctx = proc->extra_ctx;
536dc8c77fcSVesa Jääskeläinen 
537dc8c77fcSVesa Jääskeläinen 		if (!rsa_oaep_ctx->source_data_len)
538dc8c77fcSVesa Jääskeläinen 			break;
539dc8c77fcSVesa Jääskeläinen 
540dc8c77fcSVesa Jääskeläinen 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
541dc8c77fcSVesa Jääskeläinen 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
542dc8c77fcSVesa Jääskeläinen 		if (!tee_attrs) {
543dc8c77fcSVesa Jääskeläinen 			rc = PKCS11_CKR_DEVICE_MEMORY;
544dc8c77fcSVesa Jääskeläinen 			goto out;
545dc8c77fcSVesa Jääskeläinen 		}
546dc8c77fcSVesa Jääskeläinen 
547dc8c77fcSVesa Jääskeläinen 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
548dc8c77fcSVesa Jääskeläinen 				     TEE_ATTR_RSA_OAEP_LABEL,
549dc8c77fcSVesa Jääskeläinen 				     rsa_oaep_ctx->source_data,
550dc8c77fcSVesa Jääskeläinen 				     rsa_oaep_ctx->source_data_len);
551dc8c77fcSVesa Jääskeläinen 		tee_attrs_count++;
552dc8c77fcSVesa Jääskeläinen 		break;
553d9af50bcSVesa Jääskeläinen 	default:
554d9af50bcSVesa Jääskeläinen 		break;
555d9af50bcSVesa Jääskeläinen 	}
556d9af50bcSVesa Jääskeläinen 
557fb279d8bSVesa Jääskeläinen 	/*
558fb279d8bSVesa Jääskeläinen 	 * Handle multi stage update step for mechas needing hash
559fb279d8bSVesa Jääskeläinen 	 * calculation
560fb279d8bSVesa Jääskeläinen 	 */
561fb279d8bSVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE) {
562fb279d8bSVesa Jääskeläinen 		switch (proc->mecha_type) {
563fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA1:
564fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA224:
565fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA256:
566fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA384:
567fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA512:
5680442c956SVesa Jääskeläinen 		case PKCS11_CKM_MD5_RSA_PKCS:
5690442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA1_RSA_PKCS:
5700442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA224_RSA_PKCS:
5710442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA256_RSA_PKCS:
5720442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA384_RSA_PKCS:
5730442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA512_RSA_PKCS:
574d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
575d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
576d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
577d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
578d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
579fb279d8bSVesa Jääskeläinen 			assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);
580fb279d8bSVesa Jääskeläinen 
581fb279d8bSVesa Jääskeläinen 			TEE_DigestUpdate(proc->tee_hash_op_handle, in_buf,
582fb279d8bSVesa Jääskeläinen 					 in_size);
5839df68186SEtienne Carriere 			rc = PKCS11_CKR_OK;
584fb279d8bSVesa Jääskeläinen 			break;
585fb279d8bSVesa Jääskeläinen 		default:
586fb279d8bSVesa Jääskeläinen 			/*
587fb279d8bSVesa Jääskeläinen 			 * Other mechanism do not expect multi stage
588fb279d8bSVesa Jääskeläinen 			 * operation
589fb279d8bSVesa Jääskeläinen 			 */
590fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
591fb279d8bSVesa Jääskeläinen 			break;
592fb279d8bSVesa Jääskeläinen 		}
593fb279d8bSVesa Jääskeläinen 
594fb279d8bSVesa Jääskeläinen 		goto out;
595fb279d8bSVesa Jääskeläinen 	}
596fb279d8bSVesa Jääskeläinen 
597fb279d8bSVesa Jääskeläinen 	/*
598fb279d8bSVesa Jääskeläinen 	 * Handle multi stage one shot and final steps for mechas needing hash
599fb279d8bSVesa Jääskeläinen 	 * calculation
600fb279d8bSVesa Jääskeläinen 	 */
601fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
602fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
603fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
604fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
605fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
606fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
6070442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
6080442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
6090442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
6100442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
6110442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
6120442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
613d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
614d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
615d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
616d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
617d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
618fb279d8bSVesa Jääskeläinen 		assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);
619fb279d8bSVesa Jääskeläinen 
620fb279d8bSVesa Jääskeläinen 		hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo);
621fb279d8bSVesa Jääskeläinen 		hash_buf = TEE_Malloc(hash_size, 0);
622fb279d8bSVesa Jääskeläinen 		if (!hash_buf)
623fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_DEVICE_MEMORY;
624fb279d8bSVesa Jääskeläinen 
625fb279d8bSVesa Jääskeläinen 		res = TEE_DigestDoFinal(proc->tee_hash_op_handle,
626fb279d8bSVesa Jääskeläinen 					in_buf, in_size, hash_buf,
627fb279d8bSVesa Jääskeläinen 					&hash_size);
628fb279d8bSVesa Jääskeläinen 
629fb279d8bSVesa Jääskeläinen 		rc = tee2pkcs_error(res);
630fb279d8bSVesa Jääskeläinen 		if (rc != PKCS11_CKR_OK)
631fb279d8bSVesa Jääskeläinen 			goto out;
632fb279d8bSVesa Jääskeläinen 
633fb279d8bSVesa Jääskeläinen 		break;
634fb279d8bSVesa Jääskeläinen 	default:
635fb279d8bSVesa Jääskeläinen 		break;
636fb279d8bSVesa Jääskeläinen 	}
637fb279d8bSVesa Jääskeläinen 
638fb279d8bSVesa Jääskeläinen 	/*
639fb279d8bSVesa Jääskeläinen 	 * Finalize either provided hash or calculated hash with signing
640fb279d8bSVesa Jääskeläinen 	 * operation
641fb279d8bSVesa Jääskeläinen 	 */
642fb279d8bSVesa Jääskeläinen 
643fb279d8bSVesa Jääskeläinen 	/* First determine amount of bytes for signing operation */
644fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
645fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
646fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
647fb279d8bSVesa Jääskeläinen 		if (!in_size || !sz) {
648fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
649fb279d8bSVesa Jääskeläinen 			goto out;
650fb279d8bSVesa Jääskeläinen 		}
651fb279d8bSVesa Jääskeläinen 
652fb279d8bSVesa Jääskeläinen 		/*
653fb279d8bSVesa Jääskeläinen 		 * Note 3) Input the entire raw digest. Internally, this will
654fb279d8bSVesa Jääskeläinen 		 * be truncated to the appropriate number of bits.
655fb279d8bSVesa Jääskeläinen 		 */
656fb279d8bSVesa Jääskeläinen 		if (in_size > sz)
657fb279d8bSVesa Jääskeläinen 			in_size = sz;
658fb279d8bSVesa Jääskeläinen 
659fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) {
660fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
661fb279d8bSVesa Jääskeläinen 			goto out;
662fb279d8bSVesa Jääskeläinen 		}
663fb279d8bSVesa Jääskeläinen 		break;
664fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
665fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
666fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
667fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
668fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
669fb279d8bSVesa Jääskeläinen 		/* Get key size in bytes */
670fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
671fb279d8bSVesa Jääskeläinen 		if (!sz) {
672fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
673fb279d8bSVesa Jääskeläinen 			goto out;
674fb279d8bSVesa Jääskeläinen 		}
675fb279d8bSVesa Jääskeläinen 
676fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY &&
677fb279d8bSVesa Jääskeläinen 		    in2_size != 2 * sz) {
678fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
679fb279d8bSVesa Jääskeläinen 			goto out;
680fb279d8bSVesa Jääskeläinen 		}
681fb279d8bSVesa Jääskeläinen 		break;
6820442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
6830442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
6840442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
6850442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
6860442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
6870442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
6880442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
689d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
690d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
691d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
692d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
693d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
694d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
6950442c956SVesa Jääskeläinen 		/* Get key size in bytes */
6960442c956SVesa Jääskeläinen 		sz = rsa_get_input_max_byte_size(proc->tee_op_handle);
6970442c956SVesa Jääskeläinen 		if (!sz) {
6980442c956SVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
6990442c956SVesa Jääskeläinen 			goto out;
7000442c956SVesa Jääskeläinen 		}
7010442c956SVesa Jääskeläinen 
7020442c956SVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != sz) {
7030442c956SVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
7040442c956SVesa Jääskeläinen 			goto out;
7050442c956SVesa Jääskeläinen 		}
7060442c956SVesa Jääskeläinen 		break;
707fb279d8bSVesa Jääskeläinen 	default:
708fb279d8bSVesa Jääskeläinen 		break;
709fb279d8bSVesa Jääskeläinen 	}
710fb279d8bSVesa Jääskeläinen 
711fb279d8bSVesa Jääskeläinen 	/* Next perform actual signing operation */
712fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
713fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
714*03e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
7150442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
716dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
717d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
718fb279d8bSVesa Jääskeläinen 		/* For operations using provided input data */
719fb279d8bSVesa Jääskeläinen 		switch (function) {
720fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_ENCRYPT:
721fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
722fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
723fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
724fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
725fb279d8bSVesa Jääskeläinen 			output_data = true;
726fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
7276a6299fbSVesa Jääskeläinen 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
7286a6299fbSVesa Jääskeläinen 				rc = PKCS11_CKR_DATA_LEN_RANGE;
729fb279d8bSVesa Jääskeläinen 			break;
730fb279d8bSVesa Jääskeläinen 
731fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_DECRYPT:
732fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
733fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
734fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
735fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
736fb279d8bSVesa Jääskeläinen 			output_data = true;
737fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
738f27310a5SVesa Jääskeläinen 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
739f27310a5SVesa Jääskeläinen 				rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
740fb279d8bSVesa Jääskeläinen 			break;
741fb279d8bSVesa Jääskeläinen 
742fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
743fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
744fb279d8bSVesa Jääskeläinen 						       tee_attrs,
745fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
746fb279d8bSVesa Jääskeläinen 						       in_buf, in_size,
747fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
748fb279d8bSVesa Jääskeläinen 			output_data = true;
749fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
750fb279d8bSVesa Jääskeläinen 			break;
751fb279d8bSVesa Jääskeläinen 
752fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
753fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
754fb279d8bSVesa Jääskeläinen 							 tee_attrs,
755fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
756fb279d8bSVesa Jääskeläinen 							 in_buf, in_size,
757fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
758fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
759fb279d8bSVesa Jääskeläinen 			break;
760fb279d8bSVesa Jääskeläinen 
761fb279d8bSVesa Jääskeläinen 		default:
762fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
763fb279d8bSVesa Jääskeläinen 			break;
764fb279d8bSVesa Jääskeläinen 		}
765fb279d8bSVesa Jääskeläinen 		break;
766fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
767fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
768fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
769fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
770fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
7710442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
7720442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
7730442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
7740442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
7750442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
7760442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
777d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
778d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
779d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
780d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
781d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
782fb279d8bSVesa Jääskeläinen 		/* For operations having hash operation use calculated hash */
783fb279d8bSVesa Jääskeläinen 		switch (function) {
784fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
785fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
786fb279d8bSVesa Jääskeläinen 						       tee_attrs,
787fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
788fb279d8bSVesa Jääskeläinen 						       hash_buf, hash_size,
789fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
790fb279d8bSVesa Jääskeläinen 			output_data = true;
791fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
792fb279d8bSVesa Jääskeläinen 			break;
793fb279d8bSVesa Jääskeläinen 
794fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
795fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
796fb279d8bSVesa Jääskeläinen 							 tee_attrs,
797fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
798fb279d8bSVesa Jääskeläinen 							 hash_buf, hash_size,
799fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
800fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
801fb279d8bSVesa Jääskeläinen 			break;
802fb279d8bSVesa Jääskeläinen 
803fb279d8bSVesa Jääskeläinen 		default:
804fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
805fb279d8bSVesa Jääskeläinen 			break;
806fb279d8bSVesa Jääskeläinen 		}
807fb279d8bSVesa Jääskeläinen 		break;
808fb279d8bSVesa Jääskeläinen 	default:
809fb279d8bSVesa Jääskeläinen 		TEE_Panic(proc->mecha_type);
810fb279d8bSVesa Jääskeläinen 		break;
811fb279d8bSVesa Jääskeläinen 	}
812fb279d8bSVesa Jääskeläinen 
813fb279d8bSVesa Jääskeläinen out:
814fb279d8bSVesa Jääskeläinen 	if (output_data &&
815fb279d8bSVesa Jääskeläinen 	    (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) {
816fb279d8bSVesa Jääskeläinen 		switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
817fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
818fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_INOUT:
819fb279d8bSVesa Jääskeläinen 			params[2].memref.size = out_size;
820fb279d8bSVesa Jääskeläinen 			break;
821fb279d8bSVesa Jääskeläinen 		default:
822fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
823fb279d8bSVesa Jääskeläinen 			break;
824fb279d8bSVesa Jääskeläinen 		}
825fb279d8bSVesa Jääskeläinen 	}
826fb279d8bSVesa Jääskeläinen 
827fb279d8bSVesa Jääskeläinen 	TEE_Free(hash_buf);
828fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
829fb279d8bSVesa Jääskeläinen 
830fb279d8bSVesa Jääskeläinen 	return rc;
831fb279d8bSVesa Jääskeläinen }
832cc062b46SJorge Ramirez-Ortiz 
833cc062b46SJorge Ramirez-Ortiz enum pkcs11_rc do_asymm_derivation(struct pkcs11_session *session,
834cc062b46SJorge Ramirez-Ortiz 				   struct pkcs11_attribute_head *proc_params,
835cc062b46SJorge Ramirez-Ortiz 				   struct obj_attrs **head)
836cc062b46SJorge Ramirez-Ortiz {
837cc062b46SJorge Ramirez-Ortiz 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
838cc062b46SJorge Ramirez-Ortiz 	TEE_ObjectHandle out_handle = TEE_HANDLE_NULL;
839cc062b46SJorge Ramirez-Ortiz 	TEE_Result res = TEE_ERROR_GENERIC;
840cc062b46SJorge Ramirez-Ortiz 	TEE_Attribute tee_attrs[2] = { };
841cc062b46SJorge Ramirez-Ortiz 	size_t tee_attrs_count = 0;
842cc062b46SJorge Ramirez-Ortiz 	uint32_t key_byte_size = 0;
843cc062b46SJorge Ramirez-Ortiz 	uint32_t key_bit_size = 0;
844cc062b46SJorge Ramirez-Ortiz 	void *a_ptr = NULL;
845cc062b46SJorge Ramirez-Ortiz 	size_t a_size = 0;
846cc062b46SJorge Ramirez-Ortiz 
847cc062b46SJorge Ramirez-Ortiz 	/* Remove default attribute set at template sanitization */
848cc062b46SJorge Ramirez-Ortiz 	if (remove_empty_attribute(head, PKCS11_CKA_VALUE))
849cc062b46SJorge Ramirez-Ortiz 		return PKCS11_CKR_FUNCTION_FAILED;
850cc062b46SJorge Ramirez-Ortiz 
851cc062b46SJorge Ramirez-Ortiz 	rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_bit_size);
852cc062b46SJorge Ramirez-Ortiz 	if (rc)
853cc062b46SJorge Ramirez-Ortiz 		return rc;
854cc062b46SJorge Ramirez-Ortiz 
855cc062b46SJorge Ramirez-Ortiz 	key_bit_size *= 8;
856cc062b46SJorge Ramirez-Ortiz 	key_byte_size = (key_bit_size + 7) / 8;
857cc062b46SJorge Ramirez-Ortiz 
858cc062b46SJorge Ramirez-Ortiz 	res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET,
859cc062b46SJorge Ramirez-Ortiz 					  key_byte_size * 8, &out_handle);
860cc062b46SJorge Ramirez-Ortiz 	if (res) {
861cc062b46SJorge Ramirez-Ortiz 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
862cc062b46SJorge Ramirez-Ortiz 		return tee2pkcs_error(res);
863cc062b46SJorge Ramirez-Ortiz 	}
864cc062b46SJorge Ramirez-Ortiz 
865cc062b46SJorge Ramirez-Ortiz 	switch (proc_params->id) {
866cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
867cc062b46SJorge Ramirez-Ortiz 		rc = pkcs2tee_param_ecdh(proc_params, &a_ptr, &a_size);
868cc062b46SJorge Ramirez-Ortiz 		if (rc)
869cc062b46SJorge Ramirez-Ortiz 			goto out;
870cc062b46SJorge Ramirez-Ortiz 
871cc062b46SJorge Ramirez-Ortiz 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
872cc062b46SJorge Ramirez-Ortiz 				     TEE_ATTR_ECC_PUBLIC_VALUE_X,
873cc062b46SJorge Ramirez-Ortiz 				     a_ptr, a_size / 2);
874cc062b46SJorge Ramirez-Ortiz 		tee_attrs_count++;
875cc062b46SJorge Ramirez-Ortiz 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
876cc062b46SJorge Ramirez-Ortiz 				     TEE_ATTR_ECC_PUBLIC_VALUE_Y,
877cc062b46SJorge Ramirez-Ortiz 				     (char *)a_ptr + a_size / 2,
878cc062b46SJorge Ramirez-Ortiz 				     a_size / 2);
879cc062b46SJorge Ramirez-Ortiz 		tee_attrs_count++;
880cc062b46SJorge Ramirez-Ortiz 		break;
881cc062b46SJorge Ramirez-Ortiz 	default:
882cc062b46SJorge Ramirez-Ortiz 		TEE_Panic(proc_params->id);
883cc062b46SJorge Ramirez-Ortiz 		break;
884cc062b46SJorge Ramirez-Ortiz 	}
885cc062b46SJorge Ramirez-Ortiz 
886cc062b46SJorge Ramirez-Ortiz 	TEE_DeriveKey(session->processing->tee_op_handle, &tee_attrs[0],
887cc062b46SJorge Ramirez-Ortiz 		      tee_attrs_count, out_handle);
888cc062b46SJorge Ramirez-Ortiz 
889cc062b46SJorge Ramirez-Ortiz 	rc = alloc_get_tee_attribute_data(out_handle, TEE_ATTR_SECRET_VALUE,
890cc062b46SJorge Ramirez-Ortiz 					  &a_ptr, &a_size);
891cc062b46SJorge Ramirez-Ortiz 	if (rc)
892cc062b46SJorge Ramirez-Ortiz 		goto out;
893cc062b46SJorge Ramirez-Ortiz 
894cc062b46SJorge Ramirez-Ortiz 	if (a_size * 8 < key_bit_size)
895cc062b46SJorge Ramirez-Ortiz 		rc = PKCS11_CKR_KEY_SIZE_RANGE;
896cc062b46SJorge Ramirez-Ortiz 	else
897cc062b46SJorge Ramirez-Ortiz 		rc = add_attribute(head, PKCS11_CKA_VALUE, a_ptr,
898cc062b46SJorge Ramirez-Ortiz 				   key_byte_size);
899cc062b46SJorge Ramirez-Ortiz 	TEE_Free(a_ptr);
900cc062b46SJorge Ramirez-Ortiz out:
901cc062b46SJorge Ramirez-Ortiz 	release_active_processing(session);
902cc062b46SJorge Ramirez-Ortiz 	TEE_FreeTransientObject(out_handle);
903cc062b46SJorge Ramirez-Ortiz 
904cc062b46SJorge Ramirez-Ortiz 	return rc;
905cc062b46SJorge Ramirez-Ortiz }
906