xref: /optee_os/ta/pkcs11/src/processing_asymm.c (revision 45d40bda652aece0c348d316b0170992f781c99a)
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>
8*45d40bdaSValerii Chubar #include <mbedtls/nist_kw.h>
9fb279d8bSVesa Jääskeläinen #include <tee_api_defines.h>
10fb279d8bSVesa Jääskeläinen #include <tee_internal_api.h>
11fb279d8bSVesa Jääskeläinen #include <tee_internal_api_extensions.h>
12fb279d8bSVesa Jääskeläinen 
13fb279d8bSVesa Jääskeläinen #include "attributes.h"
14fb279d8bSVesa Jääskeläinen #include "pkcs11_helpers.h"
15fb279d8bSVesa Jääskeläinen #include "pkcs11_token.h"
16fb279d8bSVesa Jääskeläinen #include "processing.h"
17fb279d8bSVesa Jääskeläinen #include "serializer.h"
18fb279d8bSVesa Jääskeläinen 
19fb279d8bSVesa Jääskeläinen bool processing_is_tee_asymm(uint32_t proc_id)
20fb279d8bSVesa Jääskeläinen {
21fb279d8bSVesa Jääskeläinen 	switch (proc_id) {
220442c956SVesa Jääskeläinen 	/* RSA flavors */
23*45d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
240442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
25dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
26d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
270442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
280442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
290442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
300442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
310442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
320442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
33d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
34d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
35d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
36d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
37d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
38fb279d8bSVesa Jääskeläinen 	/* EC flavors */
3903e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
40fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
41cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
42fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
43fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
44fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
45fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
46fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
47fb279d8bSVesa Jääskeläinen 		return true;
48fb279d8bSVesa Jääskeläinen 	default:
49fb279d8bSVesa Jääskeläinen 		return false;
50fb279d8bSVesa Jääskeläinen 	}
51fb279d8bSVesa Jääskeläinen }
52fb279d8bSVesa Jääskeläinen 
53fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
54fb279d8bSVesa Jääskeläinen pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id,
55fb279d8bSVesa Jääskeläinen 		   enum processing_func function __unused,
56fb279d8bSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params,
57fb279d8bSVesa Jääskeläinen 		   struct pkcs11_object *obj)
58fb279d8bSVesa Jääskeläinen {
59fb279d8bSVesa Jääskeläinen 	static const struct {
60fb279d8bSVesa Jääskeläinen 		enum pkcs11_mechanism_id mech_id;
61fb279d8bSVesa Jääskeläinen 		uint32_t tee_id;
62fb279d8bSVesa Jääskeläinen 		uint32_t tee_hash_id;
63fb279d8bSVesa Jääskeläinen 	} pkcs2tee_algo[] = {
640442c956SVesa Jääskeläinen 		/* RSA flavors */
65*45d40bdaSValerii Chubar 		{ PKCS11_CKM_RSA_AES_KEY_WRAP, 1, 0 },
660442c956SVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5, 0 },
67dc8c77fcSVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS_OAEP, 1, 0 },
68d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS_PSS, 1, 0 },
690442c956SVesa Jääskeläinen 		{ PKCS11_CKM_MD5_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_MD5,
700442c956SVesa Jääskeläinen 		  TEE_ALG_MD5 },
710442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1,
720442c956SVesa Jääskeläinen 		  TEE_ALG_SHA1 },
730442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA224_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224,
740442c956SVesa Jääskeläinen 		  TEE_ALG_SHA224 },
750442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA256_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256,
760442c956SVesa Jääskeläinen 		  TEE_ALG_SHA256 },
770442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA384_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384,
780442c956SVesa Jääskeläinen 		  TEE_ALG_SHA384 },
790442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA512_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512,
800442c956SVesa Jääskeläinen 		  TEE_ALG_SHA512 },
81d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA1_RSA_PKCS_PSS,
82d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, TEE_ALG_SHA1 },
83d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA224_RSA_PKCS_PSS,
84d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, TEE_ALG_SHA224 },
85d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA256_RSA_PKCS_PSS,
86d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, TEE_ALG_SHA256 },
87d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA384_RSA_PKCS_PSS,
88d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, TEE_ALG_SHA384 },
89d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA512_RSA_PKCS_PSS,
90d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, TEE_ALG_SHA512 },
91fb279d8bSVesa Jääskeläinen 		/* EC flavors (Must find key size from the object) */
92fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA, 1, 0 },
93fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA1, 1, TEE_ALG_SHA1 },
94fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA224, 1, TEE_ALG_SHA224 },
95fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA256, 1, TEE_ALG_SHA256 },
96fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA384, 1, TEE_ALG_SHA384 },
97fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA512, 1, TEE_ALG_SHA512 },
98cc062b46SJorge Ramirez-Ortiz 		{ PKCS11_CKM_ECDH1_DERIVE, 1, 0 },
9903e07432SValerii Chubar 		{ PKCS11_CKM_EDDSA, TEE_ALG_ED25519, 0 },
100fb279d8bSVesa Jääskeläinen 	};
101fb279d8bSVesa Jääskeläinen 	size_t n = 0;
102fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
103fb279d8bSVesa Jääskeläinen 
104fb279d8bSVesa Jääskeläinen 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
105fb279d8bSVesa Jääskeläinen 		if (pkcs2tee_algo[n].mech_id == proc_params->id) {
106fb279d8bSVesa Jääskeläinen 			*tee_id = pkcs2tee_algo[n].tee_id;
107fb279d8bSVesa Jääskeläinen 			*tee_hash_id = pkcs2tee_algo[n].tee_hash_id;
108fb279d8bSVesa Jääskeläinen 			break;
109fb279d8bSVesa Jääskeläinen 		}
110fb279d8bSVesa Jääskeläinen 	}
111fb279d8bSVesa Jääskeläinen 
112fb279d8bSVesa Jääskeläinen 	if (n == ARRAY_SIZE(pkcs2tee_algo))
113fb279d8bSVesa Jääskeläinen 		return PKCS11_RV_NOT_IMPLEMENTED;
114fb279d8bSVesa Jääskeläinen 
115fb279d8bSVesa Jääskeläinen 	switch (proc_params->id) {
116d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
117d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
118d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
119d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
120d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
121d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
122d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_algo_rsa_pss(tee_id, proc_params);
123d9af50bcSVesa Jääskeläinen 		break;
124dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
125dc8c77fcSVesa Jääskeläinen 		rc = pkcs2tee_algo_rsa_oaep(tee_id, tee_hash_id, proc_params);
126dc8c77fcSVesa Jääskeläinen 		break;
127*45d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
128*45d40bdaSValerii Chubar 		rc = pkcs2tee_algo_rsa_aes_wrap(tee_id, tee_hash_id,
129*45d40bdaSValerii Chubar 						proc_params);
130*45d40bdaSValerii Chubar 		break;
131fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
132fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
133fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
134fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
135fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
136fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
137fb279d8bSVesa Jääskeläinen 		rc = pkcs2tee_algo_ecdsa(tee_id, proc_params, obj);
138fb279d8bSVesa Jääskeläinen 		break;
139cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
140cc062b46SJorge Ramirez-Ortiz 		rc = pkcs2tee_algo_ecdh(tee_id, proc_params, obj);
141cc062b46SJorge Ramirez-Ortiz 		break;
142fb279d8bSVesa Jääskeläinen 	default:
143fb279d8bSVesa Jääskeläinen 		rc = PKCS11_CKR_OK;
144fb279d8bSVesa Jääskeläinen 		break;
145fb279d8bSVesa Jääskeläinen 	}
146fb279d8bSVesa Jääskeläinen 
1470442c956SVesa Jääskeläinen 	/*
1480442c956SVesa Jääskeläinen 	 * PKCS#11 uses single mechanism CKM_RSA_PKCS for both ciphering and
1490442c956SVesa Jääskeläinen 	 * authentication whereas GPD TEE expects TEE_ALG_RSAES_PKCS1_V1_5 for
1500442c956SVesa Jääskeläinen 	 * ciphering and TEE_ALG_RSASSA_PKCS1_V1_5 for authentication.
1510442c956SVesa Jääskeläinen 	 */
1520442c956SVesa Jääskeläinen 	if (*tee_id == TEE_ALG_RSAES_PKCS1_V1_5 &&
1530442c956SVesa Jääskeläinen 	    (function == PKCS11_FUNCTION_SIGN ||
1540442c956SVesa Jääskeläinen 	     function == PKCS11_FUNCTION_VERIFY))
1550442c956SVesa Jääskeläinen 		*tee_id = TEE_ALG_RSASSA_PKCS1_V1_5;
1560442c956SVesa Jääskeläinen 
157fb279d8bSVesa Jääskeläinen 	return rc;
158fb279d8bSVesa Jääskeläinen }
159fb279d8bSVesa Jääskeläinen 
160fb279d8bSVesa Jääskeläinen static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type,
161fb279d8bSVesa Jääskeläinen 					struct pkcs11_object *obj,
162fb279d8bSVesa Jääskeläinen 					enum processing_func function)
163fb279d8bSVesa Jääskeläinen {
164fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id class = get_class(obj->attributes);
165fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
166fb279d8bSVesa Jääskeläinen 
167fb279d8bSVesa Jääskeläinen 	switch (class) {
168fb279d8bSVesa Jääskeläinen 	case PKCS11_CKO_PUBLIC_KEY:
169fb279d8bSVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
170fb279d8bSVesa Jääskeläinen 		break;
171fb279d8bSVesa Jääskeläinen 	default:
172fb279d8bSVesa Jääskeläinen 		TEE_Panic(class);
173fb279d8bSVesa Jääskeläinen 		break;
174fb279d8bSVesa Jääskeläinen 	}
175fb279d8bSVesa Jääskeläinen 
176fb279d8bSVesa Jääskeläinen 	switch (type) {
177fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
178cc062b46SJorge Ramirez-Ortiz 		if (class == PKCS11_CKO_PRIVATE_KEY) {
179cc062b46SJorge Ramirez-Ortiz 			if (function == PKCS11_FUNCTION_DERIVE)
180cc062b46SJorge Ramirez-Ortiz 				*tee_type = TEE_TYPE_ECDH_KEYPAIR;
181cc062b46SJorge Ramirez-Ortiz 			else
182fb279d8bSVesa Jääskeläinen 				*tee_type = TEE_TYPE_ECDSA_KEYPAIR;
183cc062b46SJorge Ramirez-Ortiz 		} else {
184cc062b46SJorge Ramirez-Ortiz 			if (function == PKCS11_FUNCTION_DERIVE)
185cc062b46SJorge Ramirez-Ortiz 				*tee_type = TEE_TYPE_ECDH_PUBLIC_KEY;
186fb279d8bSVesa Jääskeläinen 			else
187fb279d8bSVesa Jääskeläinen 				*tee_type = TEE_TYPE_ECDSA_PUBLIC_KEY;
188cc062b46SJorge Ramirez-Ortiz 		}
189fb279d8bSVesa Jääskeläinen 		break;
1900442c956SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
1910442c956SVesa Jääskeläinen 		if (class == PKCS11_CKO_PRIVATE_KEY)
1920442c956SVesa Jääskeläinen 			*tee_type = TEE_TYPE_RSA_KEYPAIR;
1930442c956SVesa Jääskeläinen 		else
1940442c956SVesa Jääskeläinen 			*tee_type = TEE_TYPE_RSA_PUBLIC_KEY;
1950442c956SVesa Jääskeläinen 		break;
19603e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
19703e07432SValerii Chubar 		if (class == PKCS11_CKO_PRIVATE_KEY)
19803e07432SValerii Chubar 			*tee_type = TEE_TYPE_ED25519_KEYPAIR;
19903e07432SValerii Chubar 		else
20003e07432SValerii Chubar 			*tee_type = TEE_TYPE_ED25519_PUBLIC_KEY;
20103e07432SValerii Chubar 		break;
202fb279d8bSVesa Jääskeläinen 	default:
203fb279d8bSVesa Jääskeläinen 		TEE_Panic(type);
204fb279d8bSVesa Jääskeläinen 		break;
205fb279d8bSVesa Jääskeläinen 	}
206fb279d8bSVesa Jääskeläinen 
207fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
208fb279d8bSVesa Jääskeläinen }
209fb279d8bSVesa Jääskeläinen 
210fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
211fb279d8bSVesa Jääskeläinen allocate_tee_operation(struct pkcs11_session *session,
212fb279d8bSVesa Jääskeläinen 		       enum processing_func function,
213fb279d8bSVesa Jääskeläinen 		       struct pkcs11_attribute_head *params,
214fb279d8bSVesa Jääskeläinen 		       struct pkcs11_object *obj)
215fb279d8bSVesa Jääskeläinen {
216fb279d8bSVesa Jääskeläinen 	uint32_t size = (uint32_t)get_object_key_bit_size(obj);
217fb279d8bSVesa Jääskeläinen 	uint32_t algo = 0;
218fb279d8bSVesa Jääskeläinen 	uint32_t hash_algo = 0;
219fb279d8bSVesa Jääskeläinen 	uint32_t mode = 0;
220fb279d8bSVesa Jääskeläinen 	uint32_t hash_mode = 0;
221fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
222fb279d8bSVesa Jääskeläinen 	struct active_processing *processing = session->processing;
223fb279d8bSVesa Jääskeläinen 
224fb279d8bSVesa Jääskeläinen 	assert(processing->tee_op_handle == TEE_HANDLE_NULL);
225fb279d8bSVesa Jääskeläinen 	assert(processing->tee_hash_op_handle == TEE_HANDLE_NULL);
226fb279d8bSVesa Jääskeläinen 
227fb279d8bSVesa Jääskeläinen 	if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj))
228fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_FUNCTION_FAILED;
229fb279d8bSVesa Jääskeläinen 
230fb279d8bSVesa Jääskeläinen 	pkcs2tee_mode(&mode, function);
231fb279d8bSVesa Jääskeläinen 
232fb279d8bSVesa Jääskeläinen 	if (hash_algo) {
233fb279d8bSVesa Jääskeläinen 		pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST);
234fb279d8bSVesa Jääskeläinen 
235fb279d8bSVesa Jääskeläinen 		res = TEE_AllocateOperation(&processing->tee_hash_op_handle,
236fb279d8bSVesa Jääskeläinen 					    hash_algo, hash_mode, 0);
237fb279d8bSVesa Jääskeläinen 		if (res) {
238fb279d8bSVesa Jääskeläinen 			EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32,
239fb279d8bSVesa Jääskeläinen 			     hash_algo, hash_mode);
240fb279d8bSVesa Jääskeläinen 
241fb279d8bSVesa Jääskeläinen 			if (res == TEE_ERROR_NOT_SUPPORTED)
242fb279d8bSVesa Jääskeläinen 				return PKCS11_CKR_MECHANISM_INVALID;
243fb279d8bSVesa Jääskeläinen 			return tee2pkcs_error(res);
244fb279d8bSVesa Jääskeläinen 		}
245fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = hash_algo;
246fb279d8bSVesa Jääskeläinen 	}
247fb279d8bSVesa Jääskeläinen 
248fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateOperation(&processing->tee_op_handle,
249fb279d8bSVesa Jääskeläinen 				    algo, mode, size);
250fb279d8bSVesa Jääskeläinen 	if (res)
251fb279d8bSVesa Jääskeläinen 		EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32,
252fb279d8bSVesa Jääskeläinen 		     algo, mode, size);
253fb279d8bSVesa Jääskeläinen 
254fb279d8bSVesa Jääskeläinen 	if (res == TEE_ERROR_NOT_SUPPORTED)
255fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_MECHANISM_INVALID;
256fb279d8bSVesa Jääskeläinen 
257fb279d8bSVesa Jääskeläinen 	if (res != TEE_SUCCESS &&
258fb279d8bSVesa Jääskeläinen 	    processing->tee_hash_op_handle != TEE_HANDLE_NULL) {
259fb279d8bSVesa Jääskeläinen 		TEE_FreeOperation(session->processing->tee_hash_op_handle);
260fb279d8bSVesa Jääskeläinen 		processing->tee_hash_op_handle = TEE_HANDLE_NULL;
261fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = 0;
262fb279d8bSVesa Jääskeläinen 	}
263fb279d8bSVesa Jääskeläinen 
264fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
265fb279d8bSVesa Jääskeläinen }
266fb279d8bSVesa Jääskeläinen 
267fb279d8bSVesa Jääskeläinen static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
268fb279d8bSVesa Jääskeläinen 				   struct pkcs11_object *obj,
269fb279d8bSVesa Jääskeläinen 				   enum processing_func function)
270fb279d8bSVesa Jääskeläinen {
271fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
272fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
273fb279d8bSVesa Jääskeläinen 	size_t object_size = 0;
274fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
275fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
276fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id __maybe_unused class = get_class(obj->attributes);
277fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
278fb279d8bSVesa Jääskeläinen 
279fb279d8bSVesa Jääskeläinen 	assert(class == PKCS11_CKO_PUBLIC_KEY ||
280fb279d8bSVesa Jääskeläinen 	       class == PKCS11_CKO_PRIVATE_KEY);
281fb279d8bSVesa Jääskeläinen 
282fb279d8bSVesa Jääskeläinen 	if (obj->key_handle != TEE_HANDLE_NULL) {
283fb279d8bSVesa Jääskeläinen 		switch (type) {
2840442c956SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
2850442c956SVesa Jääskeläinen 			/* RSA loaded keys can be reused */
2860442c956SVesa Jääskeläinen 			assert((obj->key_type == TEE_TYPE_RSA_PUBLIC_KEY &&
2870442c956SVesa Jääskeläinen 				class == PKCS11_CKO_PUBLIC_KEY) ||
2880442c956SVesa Jääskeläinen 			       (obj->key_type == TEE_TYPE_RSA_KEYPAIR &&
2890442c956SVesa Jääskeläinen 				class == PKCS11_CKO_PRIVATE_KEY));
2900442c956SVesa Jääskeläinen 			goto key_ready;
291fb279d8bSVesa Jääskeläinen 		case PKCS11_CKK_EC:
292fb279d8bSVesa Jääskeläinen 			/* Reuse EC TEE key only if already DSA or DH */
293fb279d8bSVesa Jääskeläinen 			switch (obj->key_type) {
294fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_PUBLIC_KEY:
295fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_KEYPAIR:
296fb279d8bSVesa Jääskeläinen 				if (function != PKCS11_FUNCTION_DERIVE)
297fb279d8bSVesa Jääskeläinen 					goto key_ready;
298fb279d8bSVesa Jääskeläinen 				break;
299cc062b46SJorge Ramirez-Ortiz 			case TEE_TYPE_ECDH_PUBLIC_KEY:
300cc062b46SJorge Ramirez-Ortiz 			case TEE_TYPE_ECDH_KEYPAIR:
301cc062b46SJorge Ramirez-Ortiz 				if (function == PKCS11_FUNCTION_DERIVE)
302cc062b46SJorge Ramirez-Ortiz 					goto key_ready;
303cc062b46SJorge Ramirez-Ortiz 				break;
304fb279d8bSVesa Jääskeläinen 			default:
305fb279d8bSVesa Jääskeläinen 				assert(0);
306fb279d8bSVesa Jääskeläinen 				break;
307fb279d8bSVesa Jääskeläinen 			}
308fb279d8bSVesa Jääskeläinen 			break;
309fb279d8bSVesa Jääskeläinen 		default:
310fb279d8bSVesa Jääskeläinen 			assert(0);
311fb279d8bSVesa Jääskeläinen 			break;
312fb279d8bSVesa Jääskeläinen 		}
313fb279d8bSVesa Jääskeläinen 
314fb279d8bSVesa Jääskeläinen 		TEE_CloseObject(obj->key_handle);
315fb279d8bSVesa Jääskeläinen 		obj->key_handle = TEE_HANDLE_NULL;
316fb279d8bSVesa Jääskeläinen 	}
317fb279d8bSVesa Jääskeläinen 
318fb279d8bSVesa Jääskeläinen 	rc = pkcs2tee_key_type(&obj->key_type, obj, function);
319fb279d8bSVesa Jääskeläinen 	if (rc)
320fb279d8bSVesa Jääskeläinen 		return rc;
321fb279d8bSVesa Jääskeläinen 
322fb279d8bSVesa Jääskeläinen 	object_size = get_object_key_bit_size(obj);
323fb279d8bSVesa Jääskeläinen 	if (!object_size)
324fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
325fb279d8bSVesa Jääskeläinen 
326fb279d8bSVesa Jääskeläinen 	switch (type) {
3270442c956SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
3280442c956SVesa Jääskeläinen 		rc = load_tee_rsa_key_attrs(&tee_attrs, &tee_attrs_count, obj);
3290442c956SVesa Jääskeläinen 		break;
330fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
331fb279d8bSVesa Jääskeläinen 		rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj);
332fb279d8bSVesa Jääskeläinen 		break;
33303e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
33403e07432SValerii Chubar 		rc = load_tee_eddsa_key_attrs(&tee_attrs, &tee_attrs_count,
33503e07432SValerii Chubar 					      obj);
33603e07432SValerii Chubar 		break;
337fb279d8bSVesa Jääskeläinen 	default:
338fb279d8bSVesa Jääskeläinen 		break;
339fb279d8bSVesa Jääskeläinen 	}
340fb279d8bSVesa Jääskeläinen 	if (rc)
341fb279d8bSVesa Jääskeläinen 		return rc;
342fb279d8bSVesa Jääskeläinen 
343fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateTransientObject(obj->key_type, object_size,
344fb279d8bSVesa Jääskeläinen 					  &obj->key_handle);
345fb279d8bSVesa Jääskeläinen 	if (res) {
346fb279d8bSVesa Jääskeläinen 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
347fb279d8bSVesa Jääskeläinen 
348fb279d8bSVesa Jääskeläinen 		return tee2pkcs_error(res);
349fb279d8bSVesa Jääskeläinen 	}
350fb279d8bSVesa Jääskeläinen 
351fb279d8bSVesa Jääskeläinen 	res = TEE_PopulateTransientObject(obj->key_handle,
352fb279d8bSVesa Jääskeläinen 					  tee_attrs, tee_attrs_count);
353fb279d8bSVesa Jääskeläinen 
354fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
355fb279d8bSVesa Jääskeläinen 
356fb279d8bSVesa Jääskeläinen 	if (res) {
357fb279d8bSVesa Jääskeläinen 		DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res);
358fb279d8bSVesa Jääskeläinen 
359fb279d8bSVesa Jääskeläinen 		goto error;
360fb279d8bSVesa Jääskeläinen 	}
361fb279d8bSVesa Jääskeläinen 
362fb279d8bSVesa Jääskeläinen key_ready:
363fb279d8bSVesa Jääskeläinen 	res = TEE_SetOperationKey(session->processing->tee_op_handle,
364fb279d8bSVesa Jääskeläinen 				  obj->key_handle);
365fb279d8bSVesa Jääskeläinen 	if (res) {
366fb279d8bSVesa Jääskeläinen 		DMSG("TEE_SetOperationKey failed, %#"PRIx32, res);
367fb279d8bSVesa Jääskeläinen 
368fb279d8bSVesa Jääskeläinen 		goto error;
369fb279d8bSVesa Jääskeläinen 	}
370fb279d8bSVesa Jääskeläinen 
371fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
372fb279d8bSVesa Jääskeläinen 
373fb279d8bSVesa Jääskeläinen error:
374fb279d8bSVesa Jääskeläinen 	TEE_FreeTransientObject(obj->key_handle);
375fb279d8bSVesa Jääskeläinen 	obj->key_handle = TEE_HANDLE_NULL;
376fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
377fb279d8bSVesa Jääskeläinen }
378fb279d8bSVesa Jääskeläinen 
379fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
380d9af50bcSVesa Jääskeläinen init_tee_operation(struct pkcs11_session *session,
381d9af50bcSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params,
382d9af50bcSVesa Jääskeläinen 		   struct pkcs11_object *obj)
383fb279d8bSVesa Jääskeläinen {
384d9af50bcSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
385d9af50bcSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
386d9af50bcSVesa Jääskeläinen 
387d9af50bcSVesa Jääskeläinen 	switch (proc_params->id) {
388d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
389d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
390d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
391d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
392d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
393d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
394d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_proc_params_rsa_pss(proc, proc_params);
395d9af50bcSVesa Jääskeläinen 		if (rc)
396d9af50bcSVesa Jääskeläinen 			break;
397d9af50bcSVesa Jääskeläinen 
398d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_validate_rsa_pss(proc, obj);
399d9af50bcSVesa Jääskeläinen 		break;
400dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
401dc8c77fcSVesa Jääskeläinen 		rc = pkcs2tee_proc_params_rsa_oaep(proc, proc_params);
402dc8c77fcSVesa Jääskeläinen 		break;
40303e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
40403e07432SValerii Chubar 		rc = pkcs2tee_proc_params_eddsa(proc, proc_params);
40503e07432SValerii Chubar 		break;
406*45d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
407*45d40bdaSValerii Chubar 		rc = pkcs2tee_proc_params_rsa_aes_wrap(proc, proc_params);
408*45d40bdaSValerii Chubar 		break;
409d9af50bcSVesa Jääskeläinen 	default:
410d9af50bcSVesa Jääskeläinen 		break;
411d9af50bcSVesa Jääskeläinen 	}
412d9af50bcSVesa Jääskeläinen 
413d9af50bcSVesa Jääskeläinen 	return rc;
414fb279d8bSVesa Jääskeläinen }
415fb279d8bSVesa Jääskeläinen 
416fb279d8bSVesa Jääskeläinen enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session,
417fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
418fb279d8bSVesa Jääskeläinen 				    struct pkcs11_attribute_head *proc_params,
419fb279d8bSVesa Jääskeläinen 				    struct pkcs11_object *obj)
420fb279d8bSVesa Jääskeläinen {
421fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
422fb279d8bSVesa Jääskeläinen 
423fb279d8bSVesa Jääskeläinen 	assert(processing_is_tee_asymm(proc_params->id));
424fb279d8bSVesa Jääskeläinen 
425fb279d8bSVesa Jääskeläinen 	rc = allocate_tee_operation(session, function, proc_params, obj);
426fb279d8bSVesa Jääskeläinen 	if (rc)
427fb279d8bSVesa Jääskeläinen 		return rc;
428fb279d8bSVesa Jääskeläinen 
429fb279d8bSVesa Jääskeläinen 	rc = load_tee_key(session, obj, function);
430fb279d8bSVesa Jääskeläinen 	if (rc)
431fb279d8bSVesa Jääskeläinen 		return rc;
432fb279d8bSVesa Jääskeläinen 
433d9af50bcSVesa Jääskeläinen 	return init_tee_operation(session, proc_params, obj);
434fb279d8bSVesa Jääskeläinen }
435fb279d8bSVesa Jääskeläinen 
436fb279d8bSVesa Jääskeläinen /*
437fb279d8bSVesa Jääskeläinen  * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation
438fb279d8bSVesa Jääskeläinen  *
439fb279d8bSVesa Jääskeläinen  * @session - current session
440fb279d8bSVesa Jääskeläinen  * @function - processing function (encrypt, decrypt, sign, ...)
441fb279d8bSVesa Jääskeläinen  * @step - step ID in the processing (oneshot, update, final)
442fb279d8bSVesa Jääskeläinen  * @ptypes - invocation parameter types
443fb279d8bSVesa Jääskeläinen  * @params - invocation parameter references
444fb279d8bSVesa Jääskeläinen  */
445fb279d8bSVesa Jääskeläinen enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
446fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
447fb279d8bSVesa Jääskeläinen 				    enum processing_step step,
448fb279d8bSVesa Jääskeläinen 				    uint32_t ptypes, TEE_Param *params)
449fb279d8bSVesa Jääskeläinen {
450fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
451fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
452fb279d8bSVesa Jääskeläinen 	void *in_buf = NULL;
453fb279d8bSVesa Jääskeläinen 	void *in2_buf = NULL;
454fb279d8bSVesa Jääskeläinen 	void *out_buf = NULL;
455fb279d8bSVesa Jääskeläinen 	void *hash_buf = NULL;
456fb279d8bSVesa Jääskeläinen 	uint32_t in_size = 0;
457fb279d8bSVesa Jääskeläinen 	uint32_t in2_size = 0;
458fb279d8bSVesa Jääskeläinen 	uint32_t out_size = 0;
459fb279d8bSVesa Jääskeläinen 	uint32_t hash_size = 0;
460fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
461fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
462fb279d8bSVesa Jääskeläinen 	bool output_data = false;
463fb279d8bSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
464*45d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *rsa_aes_ctx = NULL;
465dc8c77fcSVesa Jääskeläinen 	struct rsa_oaep_processing_ctx *rsa_oaep_ctx = NULL;
466d9af50bcSVesa Jääskeläinen 	struct rsa_pss_processing_ctx *rsa_pss_ctx = NULL;
46703e07432SValerii Chubar 	struct eddsa_processing_ctx *eddsa_ctx = NULL;
468fb279d8bSVesa Jääskeläinen 	size_t sz = 0;
469fb279d8bSVesa Jääskeläinen 
470fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
471fb279d8bSVesa Jääskeläinen 		in_buf = params[1].memref.buffer;
472fb279d8bSVesa Jääskeläinen 		in_size = params[1].memref.size;
473fb279d8bSVesa Jääskeläinen 		if (in_size && !in_buf)
474fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
475fb279d8bSVesa Jääskeläinen 	}
476fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) {
477fb279d8bSVesa Jääskeläinen 		in2_buf = params[2].memref.buffer;
478fb279d8bSVesa Jääskeläinen 		in2_size = params[2].memref.size;
479fb279d8bSVesa Jääskeläinen 		if (in2_size && !in2_buf)
480fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
481fb279d8bSVesa Jääskeläinen 	}
482fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
483fb279d8bSVesa Jääskeläinen 		out_buf = params[2].memref.buffer;
484fb279d8bSVesa Jääskeläinen 		out_size = params[2].memref.size;
485fb279d8bSVesa Jääskeläinen 		if (out_size && !out_buf)
486fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
487fb279d8bSVesa Jääskeläinen 	}
488fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
489fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
490fb279d8bSVesa Jääskeläinen 
491fb279d8bSVesa Jääskeläinen 	switch (step) {
492fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_ONESHOT:
493fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE:
494fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_FINAL:
495fb279d8bSVesa Jääskeläinen 		break;
496fb279d8bSVesa Jääskeläinen 	default:
497fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
498fb279d8bSVesa Jääskeläinen 	}
499fb279d8bSVesa Jääskeläinen 
500d9af50bcSVesa Jääskeläinen 	/* TEE attribute(s) required by the operation */
501d9af50bcSVesa Jääskeläinen 	switch (proc->mecha_type) {
502d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
503d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
504d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
505d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
506d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
507d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
508d9af50bcSVesa Jääskeläinen 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
509d9af50bcSVesa Jääskeläinen 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
510d9af50bcSVesa Jääskeläinen 		if (!tee_attrs) {
511d9af50bcSVesa Jääskeläinen 			rc = PKCS11_CKR_DEVICE_MEMORY;
512d9af50bcSVesa Jääskeläinen 			goto out;
513d9af50bcSVesa Jääskeläinen 		}
514d9af50bcSVesa Jääskeläinen 
515d9af50bcSVesa Jääskeläinen 		rsa_pss_ctx = proc->extra_ctx;
516d9af50bcSVesa Jääskeläinen 
517d9af50bcSVesa Jääskeläinen 		TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
518d9af50bcSVesa Jääskeläinen 				       TEE_ATTR_RSA_PSS_SALT_LENGTH,
519d9af50bcSVesa Jääskeläinen 				       rsa_pss_ctx->salt_len, 0);
520d9af50bcSVesa Jääskeläinen 		tee_attrs_count++;
521d9af50bcSVesa Jääskeläinen 		break;
52203e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
52303e07432SValerii Chubar 		eddsa_ctx = proc->extra_ctx;
52403e07432SValerii Chubar 
52503e07432SValerii Chubar 		tee_attrs = TEE_Malloc(2 * sizeof(TEE_Attribute),
52603e07432SValerii Chubar 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
52703e07432SValerii Chubar 		if (!tee_attrs) {
52803e07432SValerii Chubar 			rc = PKCS11_CKR_DEVICE_MEMORY;
52903e07432SValerii Chubar 			goto out;
53003e07432SValerii Chubar 		}
53103e07432SValerii Chubar 
53203e07432SValerii Chubar 		if (eddsa_ctx->flag) {
53303e07432SValerii Chubar 			TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
53403e07432SValerii Chubar 					       TEE_ATTR_EDDSA_PREHASH, 0, 0);
53503e07432SValerii Chubar 			tee_attrs_count++;
53603e07432SValerii Chubar 		}
53703e07432SValerii Chubar 
53803e07432SValerii Chubar 		if (eddsa_ctx->ctx_len > 0) {
53903e07432SValerii Chubar 			TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
54003e07432SValerii Chubar 					     TEE_ATTR_EDDSA_CTX, eddsa_ctx->ctx,
54103e07432SValerii Chubar 					     eddsa_ctx->ctx_len);
54203e07432SValerii Chubar 			tee_attrs_count++;
54303e07432SValerii Chubar 		}
54403e07432SValerii Chubar 		break;
545dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
546dc8c77fcSVesa Jääskeläinen 		rsa_oaep_ctx = proc->extra_ctx;
547dc8c77fcSVesa Jääskeläinen 
548dc8c77fcSVesa Jääskeläinen 		if (!rsa_oaep_ctx->source_data_len)
549dc8c77fcSVesa Jääskeläinen 			break;
550dc8c77fcSVesa Jääskeläinen 
551dc8c77fcSVesa Jääskeläinen 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
552dc8c77fcSVesa Jääskeläinen 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
553dc8c77fcSVesa Jääskeläinen 		if (!tee_attrs) {
554dc8c77fcSVesa Jääskeläinen 			rc = PKCS11_CKR_DEVICE_MEMORY;
555dc8c77fcSVesa Jääskeläinen 			goto out;
556dc8c77fcSVesa Jääskeläinen 		}
557dc8c77fcSVesa Jääskeläinen 
558dc8c77fcSVesa Jääskeläinen 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
559dc8c77fcSVesa Jääskeläinen 				     TEE_ATTR_RSA_OAEP_LABEL,
560dc8c77fcSVesa Jääskeläinen 				     rsa_oaep_ctx->source_data,
561dc8c77fcSVesa Jääskeläinen 				     rsa_oaep_ctx->source_data_len);
562dc8c77fcSVesa Jääskeläinen 		tee_attrs_count++;
563dc8c77fcSVesa Jääskeläinen 		break;
564*45d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
565*45d40bdaSValerii Chubar 		rsa_aes_ctx = proc->extra_ctx;
566*45d40bdaSValerii Chubar 
567*45d40bdaSValerii Chubar 		if (!rsa_aes_ctx->source_data_len)
568*45d40bdaSValerii Chubar 			break;
569*45d40bdaSValerii Chubar 
570*45d40bdaSValerii Chubar 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
571*45d40bdaSValerii Chubar 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
572*45d40bdaSValerii Chubar 		if (!tee_attrs) {
573*45d40bdaSValerii Chubar 			rc = PKCS11_CKR_DEVICE_MEMORY;
574*45d40bdaSValerii Chubar 			goto out;
575*45d40bdaSValerii Chubar 		}
576*45d40bdaSValerii Chubar 
577*45d40bdaSValerii Chubar 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
578*45d40bdaSValerii Chubar 				     TEE_ATTR_RSA_OAEP_LABEL,
579*45d40bdaSValerii Chubar 				     rsa_aes_ctx->source_data,
580*45d40bdaSValerii Chubar 				     rsa_aes_ctx->source_data_len);
581*45d40bdaSValerii Chubar 		tee_attrs_count++;
582*45d40bdaSValerii Chubar 		break;
583d9af50bcSVesa Jääskeläinen 	default:
584d9af50bcSVesa Jääskeläinen 		break;
585d9af50bcSVesa Jääskeläinen 	}
586d9af50bcSVesa Jääskeläinen 
587fb279d8bSVesa Jääskeläinen 	/*
588fb279d8bSVesa Jääskeläinen 	 * Handle multi stage update step for mechas needing hash
589fb279d8bSVesa Jääskeläinen 	 * calculation
590fb279d8bSVesa Jääskeläinen 	 */
591fb279d8bSVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE) {
592fb279d8bSVesa Jääskeläinen 		switch (proc->mecha_type) {
593fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA1:
594fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA224:
595fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA256:
596fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA384:
597fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA512:
5980442c956SVesa Jääskeläinen 		case PKCS11_CKM_MD5_RSA_PKCS:
5990442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA1_RSA_PKCS:
6000442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA224_RSA_PKCS:
6010442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA256_RSA_PKCS:
6020442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA384_RSA_PKCS:
6030442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA512_RSA_PKCS:
604d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
605d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
606d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
607d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
608d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
609fb279d8bSVesa Jääskeläinen 			assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);
610fb279d8bSVesa Jääskeläinen 
611fb279d8bSVesa Jääskeläinen 			TEE_DigestUpdate(proc->tee_hash_op_handle, in_buf,
612fb279d8bSVesa Jääskeläinen 					 in_size);
6139df68186SEtienne Carriere 			rc = PKCS11_CKR_OK;
614fb279d8bSVesa Jääskeläinen 			break;
615fb279d8bSVesa Jääskeläinen 		default:
616fb279d8bSVesa Jääskeläinen 			/*
617fb279d8bSVesa Jääskeläinen 			 * Other mechanism do not expect multi stage
618fb279d8bSVesa Jääskeläinen 			 * operation
619fb279d8bSVesa Jääskeläinen 			 */
620fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
621fb279d8bSVesa Jääskeläinen 			break;
622fb279d8bSVesa Jääskeläinen 		}
623fb279d8bSVesa Jääskeläinen 
624fb279d8bSVesa Jääskeläinen 		goto out;
625fb279d8bSVesa Jääskeläinen 	}
626fb279d8bSVesa Jääskeläinen 
627fb279d8bSVesa Jääskeläinen 	/*
628fb279d8bSVesa Jääskeläinen 	 * Handle multi stage one shot and final steps for mechas needing hash
629fb279d8bSVesa Jääskeläinen 	 * calculation
630fb279d8bSVesa Jääskeläinen 	 */
631fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
632fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
633fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
634fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
635fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
636fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
6370442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
6380442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
6390442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
6400442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
6410442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
6420442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
643d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
644d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
645d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
646d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
647d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
648fb279d8bSVesa Jääskeläinen 		assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);
649fb279d8bSVesa Jääskeläinen 
650fb279d8bSVesa Jääskeläinen 		hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo);
651fb279d8bSVesa Jääskeläinen 		hash_buf = TEE_Malloc(hash_size, 0);
652fb279d8bSVesa Jääskeläinen 		if (!hash_buf)
653fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_DEVICE_MEMORY;
654fb279d8bSVesa Jääskeläinen 
655fb279d8bSVesa Jääskeläinen 		res = TEE_DigestDoFinal(proc->tee_hash_op_handle,
656fb279d8bSVesa Jääskeläinen 					in_buf, in_size, hash_buf,
657fb279d8bSVesa Jääskeläinen 					&hash_size);
658fb279d8bSVesa Jääskeläinen 
659fb279d8bSVesa Jääskeläinen 		rc = tee2pkcs_error(res);
660fb279d8bSVesa Jääskeläinen 		if (rc != PKCS11_CKR_OK)
661fb279d8bSVesa Jääskeläinen 			goto out;
662fb279d8bSVesa Jääskeläinen 
663fb279d8bSVesa Jääskeläinen 		break;
664fb279d8bSVesa Jääskeläinen 	default:
665fb279d8bSVesa Jääskeläinen 		break;
666fb279d8bSVesa Jääskeläinen 	}
667fb279d8bSVesa Jääskeläinen 
668fb279d8bSVesa Jääskeläinen 	/*
669fb279d8bSVesa Jääskeläinen 	 * Finalize either provided hash or calculated hash with signing
670fb279d8bSVesa Jääskeläinen 	 * operation
671fb279d8bSVesa Jääskeläinen 	 */
672fb279d8bSVesa Jääskeläinen 
673fb279d8bSVesa Jääskeläinen 	/* First determine amount of bytes for signing operation */
674fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
675fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
676fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
677fb279d8bSVesa Jääskeläinen 		if (!in_size || !sz) {
678fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
679fb279d8bSVesa Jääskeläinen 			goto out;
680fb279d8bSVesa Jääskeläinen 		}
681fb279d8bSVesa Jääskeläinen 
682fb279d8bSVesa Jääskeläinen 		/*
683fb279d8bSVesa Jääskeläinen 		 * Note 3) Input the entire raw digest. Internally, this will
684fb279d8bSVesa Jääskeläinen 		 * be truncated to the appropriate number of bits.
685fb279d8bSVesa Jääskeläinen 		 */
686fb279d8bSVesa Jääskeläinen 		if (in_size > sz)
687fb279d8bSVesa Jääskeläinen 			in_size = sz;
688fb279d8bSVesa Jääskeläinen 
689fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) {
690fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
691fb279d8bSVesa Jääskeläinen 			goto out;
692fb279d8bSVesa Jääskeläinen 		}
693fb279d8bSVesa Jääskeläinen 		break;
694fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
695fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
696fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
697fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
698fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
699fb279d8bSVesa Jääskeläinen 		/* Get key size in bytes */
700fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
701fb279d8bSVesa Jääskeläinen 		if (!sz) {
702fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
703fb279d8bSVesa Jääskeläinen 			goto out;
704fb279d8bSVesa Jääskeläinen 		}
705fb279d8bSVesa Jääskeläinen 
706fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY &&
707fb279d8bSVesa Jääskeläinen 		    in2_size != 2 * sz) {
708fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
709fb279d8bSVesa Jääskeläinen 			goto out;
710fb279d8bSVesa Jääskeläinen 		}
711fb279d8bSVesa Jääskeläinen 		break;
7120442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
7130442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
7140442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
7150442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
7160442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
7170442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
7180442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
719d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
720d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
721d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
722d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
723d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
724d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
7250442c956SVesa Jääskeläinen 		/* Get key size in bytes */
7260442c956SVesa Jääskeläinen 		sz = rsa_get_input_max_byte_size(proc->tee_op_handle);
7270442c956SVesa Jääskeläinen 		if (!sz) {
7280442c956SVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
7290442c956SVesa Jääskeläinen 			goto out;
7300442c956SVesa Jääskeläinen 		}
7310442c956SVesa Jääskeläinen 
7320442c956SVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != sz) {
7330442c956SVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
7340442c956SVesa Jääskeläinen 			goto out;
7350442c956SVesa Jääskeläinen 		}
7360442c956SVesa Jääskeläinen 		break;
737fb279d8bSVesa Jääskeläinen 	default:
738fb279d8bSVesa Jääskeläinen 		break;
739fb279d8bSVesa Jääskeläinen 	}
740fb279d8bSVesa Jääskeläinen 
741fb279d8bSVesa Jääskeläinen 	/* Next perform actual signing operation */
742fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
743fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
74403e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
7450442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
746dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
747d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
748fb279d8bSVesa Jääskeläinen 		/* For operations using provided input data */
749fb279d8bSVesa Jääskeläinen 		switch (function) {
750fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_ENCRYPT:
751fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
752fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
753fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
754fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
755fb279d8bSVesa Jääskeläinen 			output_data = true;
756fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
7576a6299fbSVesa Jääskeläinen 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
7586a6299fbSVesa Jääskeläinen 				rc = PKCS11_CKR_DATA_LEN_RANGE;
759fb279d8bSVesa Jääskeläinen 			break;
760fb279d8bSVesa Jääskeläinen 
761fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_DECRYPT:
762fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
763fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
764fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
765fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
766fb279d8bSVesa Jääskeläinen 			output_data = true;
767fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
768f27310a5SVesa Jääskeläinen 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
769f27310a5SVesa Jääskeläinen 				rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
770fb279d8bSVesa Jääskeläinen 			break;
771fb279d8bSVesa Jääskeläinen 
772fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
773fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
774fb279d8bSVesa Jääskeläinen 						       tee_attrs,
775fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
776fb279d8bSVesa Jääskeläinen 						       in_buf, in_size,
777fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
778fb279d8bSVesa Jääskeläinen 			output_data = true;
779fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
780fb279d8bSVesa Jääskeläinen 			break;
781fb279d8bSVesa Jääskeläinen 
782fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
783fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
784fb279d8bSVesa Jääskeläinen 							 tee_attrs,
785fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
786fb279d8bSVesa Jääskeläinen 							 in_buf, in_size,
787fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
788fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
789fb279d8bSVesa Jääskeläinen 			break;
790fb279d8bSVesa Jääskeläinen 
791fb279d8bSVesa Jääskeläinen 		default:
792fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
793fb279d8bSVesa Jääskeläinen 			break;
794fb279d8bSVesa Jääskeläinen 		}
795fb279d8bSVesa Jääskeläinen 		break;
796fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
797fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
798fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
799fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
800fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
8010442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
8020442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
8030442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
8040442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
8050442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
8060442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
807d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
808d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
809d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
810d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
811d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
812fb279d8bSVesa Jääskeläinen 		/* For operations having hash operation use calculated hash */
813fb279d8bSVesa Jääskeläinen 		switch (function) {
814fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
815fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
816fb279d8bSVesa Jääskeläinen 						       tee_attrs,
817fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
818fb279d8bSVesa Jääskeläinen 						       hash_buf, hash_size,
819fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
820fb279d8bSVesa Jääskeläinen 			output_data = true;
821fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
822fb279d8bSVesa Jääskeläinen 			break;
823fb279d8bSVesa Jääskeläinen 
824fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
825fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
826fb279d8bSVesa Jääskeläinen 							 tee_attrs,
827fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
828fb279d8bSVesa Jääskeläinen 							 hash_buf, hash_size,
829fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
830fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
831fb279d8bSVesa Jääskeläinen 			break;
832fb279d8bSVesa Jääskeläinen 
833fb279d8bSVesa Jääskeläinen 		default:
834fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
835fb279d8bSVesa Jääskeläinen 			break;
836fb279d8bSVesa Jääskeläinen 		}
837fb279d8bSVesa Jääskeläinen 		break;
838fb279d8bSVesa Jääskeläinen 	default:
839fb279d8bSVesa Jääskeläinen 		TEE_Panic(proc->mecha_type);
840fb279d8bSVesa Jääskeläinen 		break;
841fb279d8bSVesa Jääskeläinen 	}
842fb279d8bSVesa Jääskeläinen 
843fb279d8bSVesa Jääskeläinen out:
844fb279d8bSVesa Jääskeläinen 	if (output_data &&
845fb279d8bSVesa Jääskeläinen 	    (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) {
846fb279d8bSVesa Jääskeläinen 		switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
847fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
848fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_INOUT:
849fb279d8bSVesa Jääskeläinen 			params[2].memref.size = out_size;
850fb279d8bSVesa Jääskeläinen 			break;
851fb279d8bSVesa Jääskeläinen 		default:
852fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
853fb279d8bSVesa Jääskeläinen 			break;
854fb279d8bSVesa Jääskeläinen 		}
855fb279d8bSVesa Jääskeläinen 	}
856fb279d8bSVesa Jääskeläinen 
857fb279d8bSVesa Jääskeläinen 	TEE_Free(hash_buf);
858fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
859fb279d8bSVesa Jääskeläinen 
860fb279d8bSVesa Jääskeläinen 	return rc;
861fb279d8bSVesa Jääskeläinen }
862cc062b46SJorge Ramirez-Ortiz 
863cc062b46SJorge Ramirez-Ortiz enum pkcs11_rc do_asymm_derivation(struct pkcs11_session *session,
864cc062b46SJorge Ramirez-Ortiz 				   struct pkcs11_attribute_head *proc_params,
865cc062b46SJorge Ramirez-Ortiz 				   struct obj_attrs **head)
866cc062b46SJorge Ramirez-Ortiz {
867cc062b46SJorge Ramirez-Ortiz 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
868cc062b46SJorge Ramirez-Ortiz 	TEE_ObjectHandle out_handle = TEE_HANDLE_NULL;
869cc062b46SJorge Ramirez-Ortiz 	TEE_Result res = TEE_ERROR_GENERIC;
870cc062b46SJorge Ramirez-Ortiz 	TEE_Attribute tee_attrs[2] = { };
871cc062b46SJorge Ramirez-Ortiz 	size_t tee_attrs_count = 0;
872cc062b46SJorge Ramirez-Ortiz 	uint32_t key_byte_size = 0;
873cc062b46SJorge Ramirez-Ortiz 	uint32_t key_bit_size = 0;
874cc062b46SJorge Ramirez-Ortiz 	void *a_ptr = NULL;
875cc062b46SJorge Ramirez-Ortiz 	size_t a_size = 0;
876cc062b46SJorge Ramirez-Ortiz 
877cc062b46SJorge Ramirez-Ortiz 	/* Remove default attribute set at template sanitization */
878cc062b46SJorge Ramirez-Ortiz 	if (remove_empty_attribute(head, PKCS11_CKA_VALUE))
879cc062b46SJorge Ramirez-Ortiz 		return PKCS11_CKR_FUNCTION_FAILED;
880cc062b46SJorge Ramirez-Ortiz 
881cc062b46SJorge Ramirez-Ortiz 	rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_bit_size);
882cc062b46SJorge Ramirez-Ortiz 	if (rc)
883cc062b46SJorge Ramirez-Ortiz 		return rc;
884cc062b46SJorge Ramirez-Ortiz 
885cc062b46SJorge Ramirez-Ortiz 	key_bit_size *= 8;
886cc062b46SJorge Ramirez-Ortiz 	key_byte_size = (key_bit_size + 7) / 8;
887cc062b46SJorge Ramirez-Ortiz 
888cc062b46SJorge Ramirez-Ortiz 	res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET,
889cc062b46SJorge Ramirez-Ortiz 					  key_byte_size * 8, &out_handle);
890cc062b46SJorge Ramirez-Ortiz 	if (res) {
891cc062b46SJorge Ramirez-Ortiz 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
892cc062b46SJorge Ramirez-Ortiz 		return tee2pkcs_error(res);
893cc062b46SJorge Ramirez-Ortiz 	}
894cc062b46SJorge Ramirez-Ortiz 
895cc062b46SJorge Ramirez-Ortiz 	switch (proc_params->id) {
896cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
897cc062b46SJorge Ramirez-Ortiz 		rc = pkcs2tee_param_ecdh(proc_params, &a_ptr, &a_size);
898cc062b46SJorge Ramirez-Ortiz 		if (rc)
899cc062b46SJorge Ramirez-Ortiz 			goto out;
900cc062b46SJorge Ramirez-Ortiz 
901cc062b46SJorge Ramirez-Ortiz 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
902cc062b46SJorge Ramirez-Ortiz 				     TEE_ATTR_ECC_PUBLIC_VALUE_X,
903cc062b46SJorge Ramirez-Ortiz 				     a_ptr, a_size / 2);
904cc062b46SJorge Ramirez-Ortiz 		tee_attrs_count++;
905cc062b46SJorge Ramirez-Ortiz 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
906cc062b46SJorge Ramirez-Ortiz 				     TEE_ATTR_ECC_PUBLIC_VALUE_Y,
907cc062b46SJorge Ramirez-Ortiz 				     (char *)a_ptr + a_size / 2,
908cc062b46SJorge Ramirez-Ortiz 				     a_size / 2);
909cc062b46SJorge Ramirez-Ortiz 		tee_attrs_count++;
910cc062b46SJorge Ramirez-Ortiz 		break;
911cc062b46SJorge Ramirez-Ortiz 	default:
912cc062b46SJorge Ramirez-Ortiz 		TEE_Panic(proc_params->id);
913cc062b46SJorge Ramirez-Ortiz 		break;
914cc062b46SJorge Ramirez-Ortiz 	}
915cc062b46SJorge Ramirez-Ortiz 
916cc062b46SJorge Ramirez-Ortiz 	TEE_DeriveKey(session->processing->tee_op_handle, &tee_attrs[0],
917cc062b46SJorge Ramirez-Ortiz 		      tee_attrs_count, out_handle);
918cc062b46SJorge Ramirez-Ortiz 
919cc062b46SJorge Ramirez-Ortiz 	rc = alloc_get_tee_attribute_data(out_handle, TEE_ATTR_SECRET_VALUE,
920cc062b46SJorge Ramirez-Ortiz 					  &a_ptr, &a_size);
921cc062b46SJorge Ramirez-Ortiz 	if (rc)
922cc062b46SJorge Ramirez-Ortiz 		goto out;
923cc062b46SJorge Ramirez-Ortiz 
924cc062b46SJorge Ramirez-Ortiz 	if (a_size * 8 < key_bit_size)
925cc062b46SJorge Ramirez-Ortiz 		rc = PKCS11_CKR_KEY_SIZE_RANGE;
926cc062b46SJorge Ramirez-Ortiz 	else
927cc062b46SJorge Ramirez-Ortiz 		rc = add_attribute(head, PKCS11_CKA_VALUE, a_ptr,
928cc062b46SJorge Ramirez-Ortiz 				   key_byte_size);
929cc062b46SJorge Ramirez-Ortiz 	TEE_Free(a_ptr);
930cc062b46SJorge Ramirez-Ortiz out:
931cc062b46SJorge Ramirez-Ortiz 	release_active_processing(session);
932cc062b46SJorge Ramirez-Ortiz 	TEE_FreeTransientObject(out_handle);
933cc062b46SJorge Ramirez-Ortiz 
934cc062b46SJorge Ramirez-Ortiz 	return rc;
935cc062b46SJorge Ramirez-Ortiz }
936*45d40bdaSValerii Chubar 
937*45d40bdaSValerii Chubar static enum pkcs11_rc wrap_rsa_aes_key(struct active_processing *proc,
938*45d40bdaSValerii Chubar 				       void *data, uint32_t data_sz,
939*45d40bdaSValerii Chubar 				       void *out_buf, uint32_t *out_sz)
940*45d40bdaSValerii Chubar {
941*45d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_OK;
942*45d40bdaSValerii Chubar 	TEE_Result res = TEE_ERROR_GENERIC;
943*45d40bdaSValerii Chubar 	int mbedtls_rc = 0;
944*45d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx;
945*45d40bdaSValerii Chubar 	mbedtls_nist_kw_context kw_ctx = { };
946*45d40bdaSValerii Chubar 	uint8_t aes_key_value[32] = { };
947*45d40bdaSValerii Chubar 	uint32_t aes_key_size = ctx->aes_key_bits / 8;
948*45d40bdaSValerii Chubar 	uint32_t aes_wrapped_size = *out_sz;
949*45d40bdaSValerii Chubar 	uint32_t expected_size = 0;
950*45d40bdaSValerii Chubar 	size_t target_key_size = 0;
951*45d40bdaSValerii Chubar 	const size_t kw_semiblock_len = 8;
952*45d40bdaSValerii Chubar 
953*45d40bdaSValerii Chubar 	if (ctx->aes_key_bits != 128 &&
954*45d40bdaSValerii Chubar 	    ctx->aes_key_bits != 192 &&
955*45d40bdaSValerii Chubar 	    ctx->aes_key_bits != 256)
956*45d40bdaSValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
957*45d40bdaSValerii Chubar 
958*45d40bdaSValerii Chubar 	mbedtls_nist_kw_init(&kw_ctx);
959*45d40bdaSValerii Chubar 	TEE_GenerateRandom(aes_key_value, aes_key_size);
960*45d40bdaSValerii Chubar 	res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
961*45d40bdaSValerii Chubar 				    NULL, 0,
962*45d40bdaSValerii Chubar 				    aes_key_value, aes_key_size,
963*45d40bdaSValerii Chubar 				    out_buf, &aes_wrapped_size);
964*45d40bdaSValerii Chubar 	expected_size = aes_wrapped_size + data_sz + kw_semiblock_len;
965*45d40bdaSValerii Chubar 	if (res) {
966*45d40bdaSValerii Chubar 		if (res == TEE_ERROR_SHORT_BUFFER)
967*45d40bdaSValerii Chubar 			*out_sz = expected_size;
968*45d40bdaSValerii Chubar 
969*45d40bdaSValerii Chubar 		rc = tee2pkcs_error(res);
970*45d40bdaSValerii Chubar 		goto out;
971*45d40bdaSValerii Chubar 	}
972*45d40bdaSValerii Chubar 
973*45d40bdaSValerii Chubar 	if (*out_sz < expected_size) {
974*45d40bdaSValerii Chubar 		rc = PKCS11_CKR_BUFFER_TOO_SMALL;
975*45d40bdaSValerii Chubar 		*out_sz = expected_size;
976*45d40bdaSValerii Chubar 		goto out;
977*45d40bdaSValerii Chubar 	}
978*45d40bdaSValerii Chubar 
979*45d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES,
980*45d40bdaSValerii Chubar 					    aes_key_value, ctx->aes_key_bits,
981*45d40bdaSValerii Chubar 					    true);
982*45d40bdaSValerii Chubar 	if (mbedtls_rc) {
983*45d40bdaSValerii Chubar 		if (mbedtls_rc == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA)
984*45d40bdaSValerii Chubar 			rc = PKCS11_CKR_KEY_SIZE_RANGE;
985*45d40bdaSValerii Chubar 		else
986*45d40bdaSValerii Chubar 			rc = PKCS11_CKR_FUNCTION_FAILED;
987*45d40bdaSValerii Chubar 
988*45d40bdaSValerii Chubar 		goto out;
989*45d40bdaSValerii Chubar 	}
990*45d40bdaSValerii Chubar 
991*45d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_wrap(&kw_ctx, MBEDTLS_KW_MODE_KWP,
992*45d40bdaSValerii Chubar 					  data, data_sz,
993*45d40bdaSValerii Chubar 					  (uint8_t *)out_buf + aes_wrapped_size,
994*45d40bdaSValerii Chubar 					  &target_key_size,
995*45d40bdaSValerii Chubar 					  *out_sz - aes_wrapped_size);
996*45d40bdaSValerii Chubar 	if (mbedtls_rc) {
997*45d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
998*45d40bdaSValerii Chubar 		goto out;
999*45d40bdaSValerii Chubar 	}
1000*45d40bdaSValerii Chubar 
1001*45d40bdaSValerii Chubar 	assert(*out_sz >= target_key_size + aes_wrapped_size);
1002*45d40bdaSValerii Chubar 	*out_sz = target_key_size + aes_wrapped_size;
1003*45d40bdaSValerii Chubar 
1004*45d40bdaSValerii Chubar out:
1005*45d40bdaSValerii Chubar 	mbedtls_nist_kw_free(&kw_ctx);
1006*45d40bdaSValerii Chubar 	TEE_MemFill(aes_key_value, 0, aes_key_size);
1007*45d40bdaSValerii Chubar 	return rc;
1008*45d40bdaSValerii Chubar }
1009*45d40bdaSValerii Chubar 
1010*45d40bdaSValerii Chubar static enum pkcs11_rc unwrap_rsa_aes_key(struct active_processing *proc,
1011*45d40bdaSValerii Chubar 					 void *data, uint32_t data_sz,
1012*45d40bdaSValerii Chubar 					 void **out_buf, uint32_t *out_sz)
1013*45d40bdaSValerii Chubar {
1014*45d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1015*45d40bdaSValerii Chubar 	int mbedtls_rc = 0;
1016*45d40bdaSValerii Chubar 	TEE_Result res = TEE_ERROR_GENERIC;
1017*45d40bdaSValerii Chubar 	TEE_OperationInfo info = { };
1018*45d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx;
1019*45d40bdaSValerii Chubar 	mbedtls_nist_kw_context kw_ctx = { };
1020*45d40bdaSValerii Chubar 	uint8_t aes_key_value[32] = { };
1021*45d40bdaSValerii Chubar 	uint32_t aes_key_size = ctx->aes_key_bits / 8;
1022*45d40bdaSValerii Chubar 	uint32_t wrapped_key_size = 0;
1023*45d40bdaSValerii Chubar 	uint32_t rsa_key_size = 0;
1024*45d40bdaSValerii Chubar 	size_t target_key_size = 0;
1025*45d40bdaSValerii Chubar 
1026*45d40bdaSValerii Chubar 	if (ctx->aes_key_bits != 128 &&
1027*45d40bdaSValerii Chubar 	    ctx->aes_key_bits != 192 &&
1028*45d40bdaSValerii Chubar 	    ctx->aes_key_bits != 256)
1029*45d40bdaSValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
1030*45d40bdaSValerii Chubar 
1031*45d40bdaSValerii Chubar 	TEE_GetOperationInfo(proc->tee_op_handle, &info);
1032*45d40bdaSValerii Chubar 	rsa_key_size = info.keySize / 8;
1033*45d40bdaSValerii Chubar 	wrapped_key_size = data_sz - rsa_key_size;
1034*45d40bdaSValerii Chubar 	target_key_size = wrapped_key_size - 8;
1035*45d40bdaSValerii Chubar 
1036*45d40bdaSValerii Chubar 	*out_buf = TEE_Malloc(target_key_size, TEE_MALLOC_FILL_ZERO);
1037*45d40bdaSValerii Chubar 	if (!*out_buf)
1038*45d40bdaSValerii Chubar 		return PKCS11_CKR_DEVICE_MEMORY;
1039*45d40bdaSValerii Chubar 
1040*45d40bdaSValerii Chubar 	mbedtls_nist_kw_init(&kw_ctx);
1041*45d40bdaSValerii Chubar 	res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
1042*45d40bdaSValerii Chubar 				    NULL, 0,
1043*45d40bdaSValerii Chubar 				    data, rsa_key_size,
1044*45d40bdaSValerii Chubar 				    aes_key_value, &aes_key_size);
1045*45d40bdaSValerii Chubar 	if (res) {
1046*45d40bdaSValerii Chubar 		rc = tee2pkcs_error(res);
1047*45d40bdaSValerii Chubar 		goto out;
1048*45d40bdaSValerii Chubar 	}
1049*45d40bdaSValerii Chubar 
1050*45d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES,
1051*45d40bdaSValerii Chubar 					    aes_key_value, ctx->aes_key_bits,
1052*45d40bdaSValerii Chubar 					    false);
1053*45d40bdaSValerii Chubar 	if (mbedtls_rc) {
1054*45d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
1055*45d40bdaSValerii Chubar 		goto out;
1056*45d40bdaSValerii Chubar 	}
1057*45d40bdaSValerii Chubar 
1058*45d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_unwrap(&kw_ctx, MBEDTLS_KW_MODE_KWP,
1059*45d40bdaSValerii Chubar 					    (uint8_t *)data + rsa_key_size,
1060*45d40bdaSValerii Chubar 					    wrapped_key_size, *out_buf,
1061*45d40bdaSValerii Chubar 					    &target_key_size, target_key_size);
1062*45d40bdaSValerii Chubar 	if (mbedtls_rc) {
1063*45d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
1064*45d40bdaSValerii Chubar 		goto out;
1065*45d40bdaSValerii Chubar 	}
1066*45d40bdaSValerii Chubar 
1067*45d40bdaSValerii Chubar 	*out_sz = target_key_size;
1068*45d40bdaSValerii Chubar out:
1069*45d40bdaSValerii Chubar 	TEE_MemFill(aes_key_value, 0, aes_key_size);
1070*45d40bdaSValerii Chubar 	mbedtls_nist_kw_free(&kw_ctx);
1071*45d40bdaSValerii Chubar 	return rc;
1072*45d40bdaSValerii Chubar }
1073*45d40bdaSValerii Chubar 
1074*45d40bdaSValerii Chubar enum pkcs11_rc wrap_data_by_asymm_enc(struct pkcs11_session *session,
1075*45d40bdaSValerii Chubar 				      void *data, uint32_t data_sz,
1076*45d40bdaSValerii Chubar 				      void *out_buf, uint32_t *out_sz)
1077*45d40bdaSValerii Chubar {
1078*45d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1079*45d40bdaSValerii Chubar 	struct active_processing *proc = session->processing;
1080*45d40bdaSValerii Chubar 
1081*45d40bdaSValerii Chubar 	switch (proc->mecha_type) {
1082*45d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
1083*45d40bdaSValerii Chubar 		rc = wrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz);
1084*45d40bdaSValerii Chubar 		break;
1085*45d40bdaSValerii Chubar 	default:
1086*45d40bdaSValerii Chubar 		return PKCS11_CKR_MECHANISM_INVALID;
1087*45d40bdaSValerii Chubar 	}
1088*45d40bdaSValerii Chubar 
1089*45d40bdaSValerii Chubar 	return rc;
1090*45d40bdaSValerii Chubar }
1091*45d40bdaSValerii Chubar 
1092*45d40bdaSValerii Chubar enum pkcs11_rc unwrap_key_by_asymm(struct pkcs11_session *session,
1093*45d40bdaSValerii Chubar 				   void *data, uint32_t data_sz,
1094*45d40bdaSValerii Chubar 				   void **out_buf, uint32_t *out_sz)
1095*45d40bdaSValerii Chubar {
1096*45d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1097*45d40bdaSValerii Chubar 	struct active_processing *proc = session->processing;
1098*45d40bdaSValerii Chubar 
1099*45d40bdaSValerii Chubar 	switch (proc->mecha_type) {
1100*45d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
1101*45d40bdaSValerii Chubar 		rc = unwrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz);
1102*45d40bdaSValerii Chubar 		break;
1103*45d40bdaSValerii Chubar 	default:
1104*45d40bdaSValerii Chubar 		return PKCS11_CKR_MECHANISM_INVALID;
1105*45d40bdaSValerii Chubar 	}
1106*45d40bdaSValerii Chubar 
1107*45d40bdaSValerii Chubar 	return rc;
1108*45d40bdaSValerii Chubar }
1109