xref: /optee_os/ta/pkcs11/src/processing_asymm.c (revision e02f17f374b6ce856b8569543e2066bfbaa64c59)
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>
845d40bdaSValerii Chubar #include <mbedtls/nist_kw.h>
9*e02f17f3SAlexandre Marechal #include <string_ext.h>
10fb279d8bSVesa Jääskeläinen #include <tee_api_defines.h>
11fb279d8bSVesa Jääskeläinen #include <tee_internal_api.h>
12fb279d8bSVesa Jääskeläinen #include <tee_internal_api_extensions.h>
13fb279d8bSVesa Jääskeläinen 
14fb279d8bSVesa Jääskeläinen #include "attributes.h"
15fb279d8bSVesa Jääskeläinen #include "pkcs11_helpers.h"
16fb279d8bSVesa Jääskeläinen #include "pkcs11_token.h"
17fb279d8bSVesa Jääskeläinen #include "processing.h"
18fb279d8bSVesa Jääskeläinen #include "serializer.h"
19fb279d8bSVesa Jääskeläinen 
20fb279d8bSVesa Jääskeläinen bool processing_is_tee_asymm(uint32_t proc_id)
21fb279d8bSVesa Jääskeläinen {
22fb279d8bSVesa Jääskeläinen 	switch (proc_id) {
230442c956SVesa Jääskeläinen 	/* RSA flavors */
2445d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
250442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
26*e02f17f3SAlexandre Marechal 	case PKCS11_CKM_RSA_X_509:
27dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
28d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
290442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
300442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
310442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
320442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
330442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
340442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
35d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
36d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
37d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
38d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
39d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
40fb279d8bSVesa Jääskeläinen 	/* EC flavors */
4103e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
42fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
43cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
44fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
45fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
46fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
47fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
48fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
49fb279d8bSVesa Jääskeläinen 		return true;
50fb279d8bSVesa Jääskeläinen 	default:
51fb279d8bSVesa Jääskeläinen 		return false;
52fb279d8bSVesa Jääskeläinen 	}
53fb279d8bSVesa Jääskeläinen }
54fb279d8bSVesa Jääskeläinen 
55fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
56fb279d8bSVesa Jääskeläinen pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id,
57fb279d8bSVesa Jääskeläinen 		   enum processing_func function __unused,
58fb279d8bSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params,
59fb279d8bSVesa Jääskeläinen 		   struct pkcs11_object *obj)
60fb279d8bSVesa Jääskeläinen {
61fb279d8bSVesa Jääskeläinen 	static const struct {
62fb279d8bSVesa Jääskeläinen 		enum pkcs11_mechanism_id mech_id;
63fb279d8bSVesa Jääskeläinen 		uint32_t tee_id;
64fb279d8bSVesa Jääskeläinen 		uint32_t tee_hash_id;
65fb279d8bSVesa Jääskeläinen 	} pkcs2tee_algo[] = {
660442c956SVesa Jääskeläinen 		/* RSA flavors */
6745d40bdaSValerii Chubar 		{ PKCS11_CKM_RSA_AES_KEY_WRAP, 1, 0 },
680442c956SVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5, 0 },
69dc8c77fcSVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS_OAEP, 1, 0 },
70d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_RSA_PKCS_PSS, 1, 0 },
71*e02f17f3SAlexandre Marechal 		{ PKCS11_CKM_RSA_X_509, TEE_ALG_RSA_NOPAD, 0 },
720442c956SVesa Jääskeläinen 		{ PKCS11_CKM_MD5_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_MD5,
730442c956SVesa Jääskeläinen 		  TEE_ALG_MD5 },
740442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1,
750442c956SVesa Jääskeläinen 		  TEE_ALG_SHA1 },
760442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA224_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224,
770442c956SVesa Jääskeläinen 		  TEE_ALG_SHA224 },
780442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA256_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256,
790442c956SVesa Jääskeläinen 		  TEE_ALG_SHA256 },
800442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA384_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384,
810442c956SVesa Jääskeläinen 		  TEE_ALG_SHA384 },
820442c956SVesa Jääskeläinen 		{ PKCS11_CKM_SHA512_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512,
830442c956SVesa Jääskeläinen 		  TEE_ALG_SHA512 },
84d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA1_RSA_PKCS_PSS,
85d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, TEE_ALG_SHA1 },
86d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA224_RSA_PKCS_PSS,
87d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, TEE_ALG_SHA224 },
88d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA256_RSA_PKCS_PSS,
89d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, TEE_ALG_SHA256 },
90d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA384_RSA_PKCS_PSS,
91d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, TEE_ALG_SHA384 },
92d9af50bcSVesa Jääskeläinen 		{ PKCS11_CKM_SHA512_RSA_PKCS_PSS,
93d9af50bcSVesa Jääskeläinen 		  TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, TEE_ALG_SHA512 },
94fb279d8bSVesa Jääskeläinen 		/* EC flavors (Must find key size from the object) */
95fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA, 1, 0 },
96fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA1, 1, TEE_ALG_SHA1 },
97fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA224, 1, TEE_ALG_SHA224 },
98fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA256, 1, TEE_ALG_SHA256 },
99fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA384, 1, TEE_ALG_SHA384 },
100fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA512, 1, TEE_ALG_SHA512 },
101cc062b46SJorge Ramirez-Ortiz 		{ PKCS11_CKM_ECDH1_DERIVE, 1, 0 },
10203e07432SValerii Chubar 		{ PKCS11_CKM_EDDSA, TEE_ALG_ED25519, 0 },
103fb279d8bSVesa Jääskeläinen 	};
104fb279d8bSVesa Jääskeläinen 	size_t n = 0;
105fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
106fb279d8bSVesa Jääskeläinen 
107fb279d8bSVesa Jääskeläinen 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
108fb279d8bSVesa Jääskeläinen 		if (pkcs2tee_algo[n].mech_id == proc_params->id) {
109fb279d8bSVesa Jääskeläinen 			*tee_id = pkcs2tee_algo[n].tee_id;
110fb279d8bSVesa Jääskeläinen 			*tee_hash_id = pkcs2tee_algo[n].tee_hash_id;
111fb279d8bSVesa Jääskeläinen 			break;
112fb279d8bSVesa Jääskeläinen 		}
113fb279d8bSVesa Jääskeläinen 	}
114fb279d8bSVesa Jääskeläinen 
115fb279d8bSVesa Jääskeläinen 	if (n == ARRAY_SIZE(pkcs2tee_algo))
116fb279d8bSVesa Jääskeläinen 		return PKCS11_RV_NOT_IMPLEMENTED;
117fb279d8bSVesa Jääskeläinen 
118fb279d8bSVesa Jääskeläinen 	switch (proc_params->id) {
119d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
120d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
121d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
122d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
123d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
124d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
125d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_algo_rsa_pss(tee_id, proc_params);
126d9af50bcSVesa Jääskeläinen 		break;
127dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
128dc8c77fcSVesa Jääskeläinen 		rc = pkcs2tee_algo_rsa_oaep(tee_id, tee_hash_id, proc_params);
129dc8c77fcSVesa Jääskeläinen 		break;
13045d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
13145d40bdaSValerii Chubar 		rc = pkcs2tee_algo_rsa_aes_wrap(tee_id, tee_hash_id,
13245d40bdaSValerii Chubar 						proc_params);
13345d40bdaSValerii Chubar 		break;
134fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
135fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
136fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
137fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
138fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
139fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
140fb279d8bSVesa Jääskeläinen 		rc = pkcs2tee_algo_ecdsa(tee_id, proc_params, obj);
141fb279d8bSVesa Jääskeläinen 		break;
142cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
143cc062b46SJorge Ramirez-Ortiz 		rc = pkcs2tee_algo_ecdh(tee_id, proc_params, obj);
144cc062b46SJorge Ramirez-Ortiz 		break;
145fb279d8bSVesa Jääskeläinen 	default:
146fb279d8bSVesa Jääskeläinen 		rc = PKCS11_CKR_OK;
147fb279d8bSVesa Jääskeläinen 		break;
148fb279d8bSVesa Jääskeläinen 	}
149fb279d8bSVesa Jääskeläinen 
1500442c956SVesa Jääskeläinen 	/*
1510442c956SVesa Jääskeläinen 	 * PKCS#11 uses single mechanism CKM_RSA_PKCS for both ciphering and
1520442c956SVesa Jääskeläinen 	 * authentication whereas GPD TEE expects TEE_ALG_RSAES_PKCS1_V1_5 for
1530442c956SVesa Jääskeläinen 	 * ciphering and TEE_ALG_RSASSA_PKCS1_V1_5 for authentication.
1540442c956SVesa Jääskeläinen 	 */
1550442c956SVesa Jääskeläinen 	if (*tee_id == TEE_ALG_RSAES_PKCS1_V1_5 &&
1560442c956SVesa Jääskeläinen 	    (function == PKCS11_FUNCTION_SIGN ||
1570442c956SVesa Jääskeläinen 	     function == PKCS11_FUNCTION_VERIFY))
1580442c956SVesa Jääskeläinen 		*tee_id = TEE_ALG_RSASSA_PKCS1_V1_5;
1590442c956SVesa Jääskeläinen 
160fb279d8bSVesa Jääskeläinen 	return rc;
161fb279d8bSVesa Jääskeläinen }
162fb279d8bSVesa Jääskeläinen 
163fb279d8bSVesa Jääskeläinen static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type,
164fb279d8bSVesa Jääskeläinen 					struct pkcs11_object *obj,
165fb279d8bSVesa Jääskeläinen 					enum processing_func function)
166fb279d8bSVesa Jääskeläinen {
167fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id class = get_class(obj->attributes);
168fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
169fb279d8bSVesa Jääskeläinen 
170fb279d8bSVesa Jääskeläinen 	switch (class) {
171fb279d8bSVesa Jääskeläinen 	case PKCS11_CKO_PUBLIC_KEY:
172fb279d8bSVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
173fb279d8bSVesa Jääskeläinen 		break;
174fb279d8bSVesa Jääskeläinen 	default:
175fb279d8bSVesa Jääskeläinen 		TEE_Panic(class);
176fb279d8bSVesa Jääskeläinen 		break;
177fb279d8bSVesa Jääskeläinen 	}
178fb279d8bSVesa Jääskeläinen 
179fb279d8bSVesa Jääskeläinen 	switch (type) {
180fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
181cc062b46SJorge Ramirez-Ortiz 		if (class == PKCS11_CKO_PRIVATE_KEY) {
182cc062b46SJorge Ramirez-Ortiz 			if (function == PKCS11_FUNCTION_DERIVE)
183cc062b46SJorge Ramirez-Ortiz 				*tee_type = TEE_TYPE_ECDH_KEYPAIR;
184cc062b46SJorge Ramirez-Ortiz 			else
185fb279d8bSVesa Jääskeläinen 				*tee_type = TEE_TYPE_ECDSA_KEYPAIR;
186cc062b46SJorge Ramirez-Ortiz 		} else {
187cc062b46SJorge Ramirez-Ortiz 			if (function == PKCS11_FUNCTION_DERIVE)
188cc062b46SJorge Ramirez-Ortiz 				*tee_type = TEE_TYPE_ECDH_PUBLIC_KEY;
189fb279d8bSVesa Jääskeläinen 			else
190fb279d8bSVesa Jääskeläinen 				*tee_type = TEE_TYPE_ECDSA_PUBLIC_KEY;
191cc062b46SJorge Ramirez-Ortiz 		}
192fb279d8bSVesa Jääskeläinen 		break;
1930442c956SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
1940442c956SVesa Jääskeläinen 		if (class == PKCS11_CKO_PRIVATE_KEY)
1950442c956SVesa Jääskeläinen 			*tee_type = TEE_TYPE_RSA_KEYPAIR;
1960442c956SVesa Jääskeläinen 		else
1970442c956SVesa Jääskeläinen 			*tee_type = TEE_TYPE_RSA_PUBLIC_KEY;
1980442c956SVesa Jääskeläinen 		break;
19903e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
20003e07432SValerii Chubar 		if (class == PKCS11_CKO_PRIVATE_KEY)
20103e07432SValerii Chubar 			*tee_type = TEE_TYPE_ED25519_KEYPAIR;
20203e07432SValerii Chubar 		else
20303e07432SValerii Chubar 			*tee_type = TEE_TYPE_ED25519_PUBLIC_KEY;
20403e07432SValerii Chubar 		break;
205fb279d8bSVesa Jääskeläinen 	default:
206fb279d8bSVesa Jääskeläinen 		TEE_Panic(type);
207fb279d8bSVesa Jääskeläinen 		break;
208fb279d8bSVesa Jääskeläinen 	}
209fb279d8bSVesa Jääskeläinen 
210fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
211fb279d8bSVesa Jääskeläinen }
212fb279d8bSVesa Jääskeläinen 
213fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
214fb279d8bSVesa Jääskeläinen allocate_tee_operation(struct pkcs11_session *session,
215fb279d8bSVesa Jääskeläinen 		       enum processing_func function,
216fb279d8bSVesa Jääskeläinen 		       struct pkcs11_attribute_head *params,
217fb279d8bSVesa Jääskeläinen 		       struct pkcs11_object *obj)
218fb279d8bSVesa Jääskeläinen {
219fb279d8bSVesa Jääskeläinen 	uint32_t size = (uint32_t)get_object_key_bit_size(obj);
220fb279d8bSVesa Jääskeläinen 	uint32_t algo = 0;
221fb279d8bSVesa Jääskeläinen 	uint32_t hash_algo = 0;
222fb279d8bSVesa Jääskeläinen 	uint32_t mode = 0;
223fb279d8bSVesa Jääskeläinen 	uint32_t hash_mode = 0;
224fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
225fb279d8bSVesa Jääskeläinen 	struct active_processing *processing = session->processing;
226fb279d8bSVesa Jääskeläinen 
227fb279d8bSVesa Jääskeläinen 	assert(processing->tee_op_handle == TEE_HANDLE_NULL);
228571857c0SEtienne Carriere 	assert(processing->tee_op_handle2 == TEE_HANDLE_NULL);
229fb279d8bSVesa Jääskeläinen 
230fb279d8bSVesa Jääskeläinen 	if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj))
231fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_FUNCTION_FAILED;
232fb279d8bSVesa Jääskeläinen 
233*e02f17f3SAlexandre Marechal 	/*
234*e02f17f3SAlexandre Marechal 	 * PKCS#11 allows Sign/Verify with CKM_RSA_X_509 while GP TEE API
235*e02f17f3SAlexandre Marechal 	 * only permits Encrypt/Decrypt with TEE_ALG_RSA_NOPAD.
236*e02f17f3SAlexandre Marechal 	 * For other algorithm, use simple 1-to-1 ID conversion pkcs2tee_mode().
237*e02f17f3SAlexandre Marechal 	 */
238*e02f17f3SAlexandre Marechal 	if (params->id == PKCS11_CKM_RSA_X_509) {
239*e02f17f3SAlexandre Marechal 		assert(!hash_algo);
240*e02f17f3SAlexandre Marechal 		switch (function) {
241*e02f17f3SAlexandre Marechal 		case PKCS11_FUNCTION_VERIFY:
242*e02f17f3SAlexandre Marechal 			mode = TEE_MODE_ENCRYPT;
243*e02f17f3SAlexandre Marechal 			break;
244*e02f17f3SAlexandre Marechal 		case PKCS11_FUNCTION_SIGN:
245*e02f17f3SAlexandre Marechal 			mode = TEE_MODE_DECRYPT;
246*e02f17f3SAlexandre Marechal 			break;
247*e02f17f3SAlexandre Marechal 		default:
248*e02f17f3SAlexandre Marechal 			TEE_Panic(0);
249*e02f17f3SAlexandre Marechal 		}
250*e02f17f3SAlexandre Marechal 	} else {
251fb279d8bSVesa Jääskeläinen 		pkcs2tee_mode(&mode, function);
252*e02f17f3SAlexandre Marechal 	}
253fb279d8bSVesa Jääskeläinen 
254fb279d8bSVesa Jääskeläinen 	if (hash_algo) {
255fb279d8bSVesa Jääskeläinen 		pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST);
256fb279d8bSVesa Jääskeläinen 
257571857c0SEtienne Carriere 		res = TEE_AllocateOperation(&processing->tee_op_handle2,
258fb279d8bSVesa Jääskeläinen 					    hash_algo, hash_mode, 0);
259fb279d8bSVesa Jääskeläinen 		if (res) {
260fb279d8bSVesa Jääskeläinen 			EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32,
261fb279d8bSVesa Jääskeläinen 			     hash_algo, hash_mode);
262fb279d8bSVesa Jääskeläinen 
263fb279d8bSVesa Jääskeläinen 			if (res == TEE_ERROR_NOT_SUPPORTED)
264fb279d8bSVesa Jääskeläinen 				return PKCS11_CKR_MECHANISM_INVALID;
265fb279d8bSVesa Jääskeläinen 			return tee2pkcs_error(res);
266fb279d8bSVesa Jääskeläinen 		}
267fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = hash_algo;
268fb279d8bSVesa Jääskeläinen 	}
269fb279d8bSVesa Jääskeläinen 
270fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateOperation(&processing->tee_op_handle,
271fb279d8bSVesa Jääskeläinen 				    algo, mode, size);
272fb279d8bSVesa Jääskeläinen 	if (res)
273fb279d8bSVesa Jääskeläinen 		EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32,
274fb279d8bSVesa Jääskeläinen 		     algo, mode, size);
275fb279d8bSVesa Jääskeläinen 
276fb279d8bSVesa Jääskeläinen 	if (res == TEE_ERROR_NOT_SUPPORTED)
277fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_MECHANISM_INVALID;
278fb279d8bSVesa Jääskeläinen 
279fb279d8bSVesa Jääskeläinen 	if (res != TEE_SUCCESS &&
280571857c0SEtienne Carriere 	    processing->tee_op_handle2 != TEE_HANDLE_NULL) {
281571857c0SEtienne Carriere 		TEE_FreeOperation(session->processing->tee_op_handle2);
282571857c0SEtienne Carriere 		processing->tee_op_handle2 = TEE_HANDLE_NULL;
283fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = 0;
284fb279d8bSVesa Jääskeläinen 	}
285fb279d8bSVesa Jääskeläinen 
286fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
287fb279d8bSVesa Jääskeläinen }
288fb279d8bSVesa Jääskeläinen 
289fb279d8bSVesa Jääskeläinen static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
290fb279d8bSVesa Jääskeläinen 				   struct pkcs11_object *obj,
291fb279d8bSVesa Jääskeläinen 				   enum processing_func function)
292fb279d8bSVesa Jääskeläinen {
293fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
294fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
295fb279d8bSVesa Jääskeläinen 	size_t object_size = 0;
296fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
297fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
298fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id __maybe_unused class = get_class(obj->attributes);
299fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
300fb279d8bSVesa Jääskeläinen 
301fb279d8bSVesa Jääskeläinen 	assert(class == PKCS11_CKO_PUBLIC_KEY ||
302fb279d8bSVesa Jääskeläinen 	       class == PKCS11_CKO_PRIVATE_KEY);
303fb279d8bSVesa Jääskeläinen 
304fb279d8bSVesa Jääskeläinen 	if (obj->key_handle != TEE_HANDLE_NULL) {
305fb279d8bSVesa Jääskeläinen 		switch (type) {
3060442c956SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
3070442c956SVesa Jääskeläinen 			/* RSA loaded keys can be reused */
3080442c956SVesa Jääskeläinen 			assert((obj->key_type == TEE_TYPE_RSA_PUBLIC_KEY &&
3090442c956SVesa Jääskeläinen 				class == PKCS11_CKO_PUBLIC_KEY) ||
3100442c956SVesa Jääskeläinen 			       (obj->key_type == TEE_TYPE_RSA_KEYPAIR &&
3110442c956SVesa Jääskeläinen 				class == PKCS11_CKO_PRIVATE_KEY));
3120442c956SVesa Jääskeläinen 			goto key_ready;
313fb279d8bSVesa Jääskeläinen 		case PKCS11_CKK_EC:
314fb279d8bSVesa Jääskeläinen 			/* Reuse EC TEE key only if already DSA or DH */
315fb279d8bSVesa Jääskeläinen 			switch (obj->key_type) {
316fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_PUBLIC_KEY:
317fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_KEYPAIR:
318fb279d8bSVesa Jääskeläinen 				if (function != PKCS11_FUNCTION_DERIVE)
319fb279d8bSVesa Jääskeläinen 					goto key_ready;
320fb279d8bSVesa Jääskeläinen 				break;
321cc062b46SJorge Ramirez-Ortiz 			case TEE_TYPE_ECDH_PUBLIC_KEY:
322cc062b46SJorge Ramirez-Ortiz 			case TEE_TYPE_ECDH_KEYPAIR:
323cc062b46SJorge Ramirez-Ortiz 				if (function == PKCS11_FUNCTION_DERIVE)
324cc062b46SJorge Ramirez-Ortiz 					goto key_ready;
325cc062b46SJorge Ramirez-Ortiz 				break;
326fb279d8bSVesa Jääskeläinen 			default:
327fb279d8bSVesa Jääskeläinen 				assert(0);
328fb279d8bSVesa Jääskeläinen 				break;
329fb279d8bSVesa Jääskeläinen 			}
330fb279d8bSVesa Jääskeläinen 			break;
331fb279d8bSVesa Jääskeläinen 		default:
332fb279d8bSVesa Jääskeläinen 			assert(0);
333fb279d8bSVesa Jääskeläinen 			break;
334fb279d8bSVesa Jääskeläinen 		}
335fb279d8bSVesa Jääskeläinen 
336fb279d8bSVesa Jääskeläinen 		TEE_CloseObject(obj->key_handle);
337fb279d8bSVesa Jääskeläinen 		obj->key_handle = TEE_HANDLE_NULL;
338fb279d8bSVesa Jääskeläinen 	}
339fb279d8bSVesa Jääskeläinen 
340fb279d8bSVesa Jääskeläinen 	rc = pkcs2tee_key_type(&obj->key_type, obj, function);
341fb279d8bSVesa Jääskeläinen 	if (rc)
342fb279d8bSVesa Jääskeläinen 		return rc;
343fb279d8bSVesa Jääskeläinen 
344fb279d8bSVesa Jääskeläinen 	object_size = get_object_key_bit_size(obj);
345fb279d8bSVesa Jääskeläinen 	if (!object_size)
346fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
347fb279d8bSVesa Jääskeläinen 
348fb279d8bSVesa Jääskeläinen 	switch (type) {
3490442c956SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
3500442c956SVesa Jääskeläinen 		rc = load_tee_rsa_key_attrs(&tee_attrs, &tee_attrs_count, obj);
3510442c956SVesa Jääskeläinen 		break;
352fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
353fb279d8bSVesa Jääskeläinen 		rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj);
354fb279d8bSVesa Jääskeläinen 		break;
35503e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
35603e07432SValerii Chubar 		rc = load_tee_eddsa_key_attrs(&tee_attrs, &tee_attrs_count,
35703e07432SValerii Chubar 					      obj);
35803e07432SValerii Chubar 		break;
359fb279d8bSVesa Jääskeläinen 	default:
360fb279d8bSVesa Jääskeläinen 		break;
361fb279d8bSVesa Jääskeläinen 	}
362fb279d8bSVesa Jääskeläinen 	if (rc)
363fb279d8bSVesa Jääskeläinen 		return rc;
364fb279d8bSVesa Jääskeläinen 
365fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateTransientObject(obj->key_type, object_size,
366fb279d8bSVesa Jääskeläinen 					  &obj->key_handle);
367fb279d8bSVesa Jääskeläinen 	if (res) {
368fb279d8bSVesa Jääskeläinen 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
369fb279d8bSVesa Jääskeläinen 
370fb279d8bSVesa Jääskeläinen 		return tee2pkcs_error(res);
371fb279d8bSVesa Jääskeläinen 	}
372fb279d8bSVesa Jääskeläinen 
373fb279d8bSVesa Jääskeläinen 	res = TEE_PopulateTransientObject(obj->key_handle,
374fb279d8bSVesa Jääskeläinen 					  tee_attrs, tee_attrs_count);
375fb279d8bSVesa Jääskeläinen 
376fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
377fb279d8bSVesa Jääskeläinen 
378fb279d8bSVesa Jääskeläinen 	if (res) {
379fb279d8bSVesa Jääskeläinen 		DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res);
380fb279d8bSVesa Jääskeläinen 
381fb279d8bSVesa Jääskeläinen 		goto error;
382fb279d8bSVesa Jääskeläinen 	}
383fb279d8bSVesa Jääskeläinen 
384fb279d8bSVesa Jääskeläinen key_ready:
385fb279d8bSVesa Jääskeläinen 	res = TEE_SetOperationKey(session->processing->tee_op_handle,
386fb279d8bSVesa Jääskeläinen 				  obj->key_handle);
387fb279d8bSVesa Jääskeläinen 	if (res) {
388fb279d8bSVesa Jääskeläinen 		DMSG("TEE_SetOperationKey failed, %#"PRIx32, res);
389fb279d8bSVesa Jääskeläinen 
390fb279d8bSVesa Jääskeläinen 		goto error;
391fb279d8bSVesa Jääskeläinen 	}
392fb279d8bSVesa Jääskeläinen 
393fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
394fb279d8bSVesa Jääskeläinen 
395fb279d8bSVesa Jääskeläinen error:
396fb279d8bSVesa Jääskeläinen 	TEE_FreeTransientObject(obj->key_handle);
397fb279d8bSVesa Jääskeläinen 	obj->key_handle = TEE_HANDLE_NULL;
398fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
399fb279d8bSVesa Jääskeläinen }
400fb279d8bSVesa Jääskeläinen 
401fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
402d9af50bcSVesa Jääskeläinen init_tee_operation(struct pkcs11_session *session,
403d9af50bcSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params,
404d9af50bcSVesa Jääskeläinen 		   struct pkcs11_object *obj)
405fb279d8bSVesa Jääskeläinen {
406d9af50bcSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
407d9af50bcSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
408d9af50bcSVesa Jääskeläinen 
409d9af50bcSVesa Jääskeläinen 	switch (proc_params->id) {
410*e02f17f3SAlexandre Marechal 	case PKCS11_CKM_RSA_X_509:
411*e02f17f3SAlexandre Marechal 		rc = pkcs2tee_rsa_nopad_context(proc);
412*e02f17f3SAlexandre Marechal 		break;
413d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
414d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
415d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
416d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
417d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
418d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
419d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_proc_params_rsa_pss(proc, proc_params);
420d9af50bcSVesa Jääskeläinen 		if (rc)
421d9af50bcSVesa Jääskeläinen 			break;
422d9af50bcSVesa Jääskeläinen 
423d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_validate_rsa_pss(proc, obj);
424d9af50bcSVesa Jääskeläinen 		break;
425dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
426dc8c77fcSVesa Jääskeläinen 		rc = pkcs2tee_proc_params_rsa_oaep(proc, proc_params);
427dc8c77fcSVesa Jääskeläinen 		break;
42803e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
42903e07432SValerii Chubar 		rc = pkcs2tee_proc_params_eddsa(proc, proc_params);
43003e07432SValerii Chubar 		break;
43145d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
43245d40bdaSValerii Chubar 		rc = pkcs2tee_proc_params_rsa_aes_wrap(proc, proc_params);
43345d40bdaSValerii Chubar 		break;
434d9af50bcSVesa Jääskeläinen 	default:
435d9af50bcSVesa Jääskeläinen 		break;
436d9af50bcSVesa Jääskeläinen 	}
437d9af50bcSVesa Jääskeläinen 
438d9af50bcSVesa Jääskeläinen 	return rc;
439fb279d8bSVesa Jääskeläinen }
440fb279d8bSVesa Jääskeläinen 
441fb279d8bSVesa Jääskeläinen enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session,
442fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
443fb279d8bSVesa Jääskeläinen 				    struct pkcs11_attribute_head *proc_params,
444fb279d8bSVesa Jääskeläinen 				    struct pkcs11_object *obj)
445fb279d8bSVesa Jääskeläinen {
446fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
447fb279d8bSVesa Jääskeläinen 
448fb279d8bSVesa Jääskeläinen 	assert(processing_is_tee_asymm(proc_params->id));
449fb279d8bSVesa Jääskeläinen 
450fb279d8bSVesa Jääskeläinen 	rc = allocate_tee_operation(session, function, proc_params, obj);
451fb279d8bSVesa Jääskeläinen 	if (rc)
452fb279d8bSVesa Jääskeläinen 		return rc;
453fb279d8bSVesa Jääskeläinen 
454fb279d8bSVesa Jääskeläinen 	rc = load_tee_key(session, obj, function);
455fb279d8bSVesa Jääskeläinen 	if (rc)
456fb279d8bSVesa Jääskeläinen 		return rc;
457fb279d8bSVesa Jääskeläinen 
458909efccbSEtienne Carriere 	rc = init_tee_operation(session, proc_params, obj);
459909efccbSEtienne Carriere 	if (!rc)
460909efccbSEtienne Carriere 		session->processing->mecha_type = proc_params->id;
461909efccbSEtienne Carriere 
462909efccbSEtienne Carriere 	return rc;
463fb279d8bSVesa Jääskeläinen }
464fb279d8bSVesa Jääskeläinen 
465fb279d8bSVesa Jääskeläinen /*
466fb279d8bSVesa Jääskeläinen  * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation
467fb279d8bSVesa Jääskeläinen  *
468fb279d8bSVesa Jääskeläinen  * @session - current session
469fb279d8bSVesa Jääskeläinen  * @function - processing function (encrypt, decrypt, sign, ...)
470fb279d8bSVesa Jääskeläinen  * @step - step ID in the processing (oneshot, update, final)
471fb279d8bSVesa Jääskeläinen  * @ptypes - invocation parameter types
472fb279d8bSVesa Jääskeläinen  * @params - invocation parameter references
473fb279d8bSVesa Jääskeläinen  */
474fb279d8bSVesa Jääskeläinen enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
475fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
476fb279d8bSVesa Jääskeläinen 				    enum processing_step step,
477fb279d8bSVesa Jääskeläinen 				    uint32_t ptypes, TEE_Param *params)
478fb279d8bSVesa Jääskeläinen {
479fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
480fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
481fb279d8bSVesa Jääskeläinen 	void *in_buf = NULL;
482fb279d8bSVesa Jääskeläinen 	void *in2_buf = NULL;
483fb279d8bSVesa Jääskeläinen 	void *out_buf = NULL;
484fb279d8bSVesa Jääskeläinen 	void *hash_buf = NULL;
485*e02f17f3SAlexandre Marechal 	void *temp_buf = NULL;
486fb279d8bSVesa Jääskeläinen 	uint32_t in_size = 0;
487fb279d8bSVesa Jääskeläinen 	uint32_t in2_size = 0;
488c7f1b4f7SJens Wiklander 	size_t out_size = 0;
489c7f1b4f7SJens Wiklander 	size_t hash_size = 0;
490*e02f17f3SAlexandre Marechal 	size_t temp_size = 0;
491fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
492fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
493fb279d8bSVesa Jääskeläinen 	bool output_data = false;
494fb279d8bSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
49545d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *rsa_aes_ctx = NULL;
496dc8c77fcSVesa Jääskeläinen 	struct rsa_oaep_processing_ctx *rsa_oaep_ctx = NULL;
497d9af50bcSVesa Jääskeläinen 	struct rsa_pss_processing_ctx *rsa_pss_ctx = NULL;
49803e07432SValerii Chubar 	struct eddsa_processing_ctx *eddsa_ctx = NULL;
499fb279d8bSVesa Jääskeläinen 	size_t sz = 0;
500fb279d8bSVesa Jääskeläinen 
501fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
502fb279d8bSVesa Jääskeläinen 		in_buf = params[1].memref.buffer;
503fb279d8bSVesa Jääskeläinen 		in_size = params[1].memref.size;
504fb279d8bSVesa Jääskeläinen 		if (in_size && !in_buf)
505fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
506fb279d8bSVesa Jääskeläinen 	}
507fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) {
508fb279d8bSVesa Jääskeläinen 		in2_buf = params[2].memref.buffer;
509fb279d8bSVesa Jääskeläinen 		in2_size = params[2].memref.size;
510fb279d8bSVesa Jääskeläinen 		if (in2_size && !in2_buf)
511fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
512fb279d8bSVesa Jääskeläinen 	}
513fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
514fb279d8bSVesa Jääskeläinen 		out_buf = params[2].memref.buffer;
515fb279d8bSVesa Jääskeläinen 		out_size = params[2].memref.size;
516fb279d8bSVesa Jääskeläinen 		if (out_size && !out_buf)
517fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
518fb279d8bSVesa Jääskeläinen 	}
519fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
520fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
521fb279d8bSVesa Jääskeläinen 
522fb279d8bSVesa Jääskeläinen 	switch (step) {
523fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_ONESHOT:
524fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE:
525fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_FINAL:
526fb279d8bSVesa Jääskeläinen 		break;
527fb279d8bSVesa Jääskeläinen 	default:
528fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
529fb279d8bSVesa Jääskeläinen 	}
530fb279d8bSVesa Jääskeläinen 
531d9af50bcSVesa Jääskeläinen 	/* TEE attribute(s) required by the operation */
532d9af50bcSVesa Jääskeläinen 	switch (proc->mecha_type) {
533d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
534d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
535d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
536d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
537d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
538d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
539d9af50bcSVesa Jääskeläinen 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
540d9af50bcSVesa Jääskeläinen 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
541d9af50bcSVesa Jääskeläinen 		if (!tee_attrs) {
542d9af50bcSVesa Jääskeläinen 			rc = PKCS11_CKR_DEVICE_MEMORY;
543d9af50bcSVesa Jääskeläinen 			goto out;
544d9af50bcSVesa Jääskeläinen 		}
545d9af50bcSVesa Jääskeläinen 
546d9af50bcSVesa Jääskeläinen 		rsa_pss_ctx = proc->extra_ctx;
547d9af50bcSVesa Jääskeläinen 
548d9af50bcSVesa Jääskeläinen 		TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
549d9af50bcSVesa Jääskeläinen 				       TEE_ATTR_RSA_PSS_SALT_LENGTH,
550d9af50bcSVesa Jääskeläinen 				       rsa_pss_ctx->salt_len, 0);
551d9af50bcSVesa Jääskeläinen 		tee_attrs_count++;
552d9af50bcSVesa Jääskeläinen 		break;
55303e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
55403e07432SValerii Chubar 		eddsa_ctx = proc->extra_ctx;
55503e07432SValerii Chubar 
55603e07432SValerii Chubar 		tee_attrs = TEE_Malloc(2 * sizeof(TEE_Attribute),
55703e07432SValerii Chubar 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
55803e07432SValerii Chubar 		if (!tee_attrs) {
55903e07432SValerii Chubar 			rc = PKCS11_CKR_DEVICE_MEMORY;
56003e07432SValerii Chubar 			goto out;
56103e07432SValerii Chubar 		}
56203e07432SValerii Chubar 
56303e07432SValerii Chubar 		if (eddsa_ctx->flag) {
56403e07432SValerii Chubar 			TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
56503e07432SValerii Chubar 					       TEE_ATTR_EDDSA_PREHASH, 0, 0);
56603e07432SValerii Chubar 			tee_attrs_count++;
56703e07432SValerii Chubar 		}
56803e07432SValerii Chubar 
56903e07432SValerii Chubar 		if (eddsa_ctx->ctx_len > 0) {
57003e07432SValerii Chubar 			TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
57103e07432SValerii Chubar 					     TEE_ATTR_EDDSA_CTX, eddsa_ctx->ctx,
57203e07432SValerii Chubar 					     eddsa_ctx->ctx_len);
57303e07432SValerii Chubar 			tee_attrs_count++;
57403e07432SValerii Chubar 		}
57503e07432SValerii Chubar 		break;
576dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
577dc8c77fcSVesa Jääskeläinen 		rsa_oaep_ctx = proc->extra_ctx;
578dc8c77fcSVesa Jääskeläinen 
579dc8c77fcSVesa Jääskeläinen 		if (!rsa_oaep_ctx->source_data_len)
580dc8c77fcSVesa Jääskeläinen 			break;
581dc8c77fcSVesa Jääskeläinen 
582dc8c77fcSVesa Jääskeläinen 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
583dc8c77fcSVesa Jääskeläinen 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
584dc8c77fcSVesa Jääskeläinen 		if (!tee_attrs) {
585dc8c77fcSVesa Jääskeläinen 			rc = PKCS11_CKR_DEVICE_MEMORY;
586dc8c77fcSVesa Jääskeläinen 			goto out;
587dc8c77fcSVesa Jääskeläinen 		}
588dc8c77fcSVesa Jääskeläinen 
589dc8c77fcSVesa Jääskeläinen 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
590dc8c77fcSVesa Jääskeläinen 				     TEE_ATTR_RSA_OAEP_LABEL,
591dc8c77fcSVesa Jääskeläinen 				     rsa_oaep_ctx->source_data,
592dc8c77fcSVesa Jääskeläinen 				     rsa_oaep_ctx->source_data_len);
593dc8c77fcSVesa Jääskeläinen 		tee_attrs_count++;
594dc8c77fcSVesa Jääskeläinen 		break;
59545d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
59645d40bdaSValerii Chubar 		rsa_aes_ctx = proc->extra_ctx;
59745d40bdaSValerii Chubar 
59845d40bdaSValerii Chubar 		if (!rsa_aes_ctx->source_data_len)
59945d40bdaSValerii Chubar 			break;
60045d40bdaSValerii Chubar 
60145d40bdaSValerii Chubar 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
60245d40bdaSValerii Chubar 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
60345d40bdaSValerii Chubar 		if (!tee_attrs) {
60445d40bdaSValerii Chubar 			rc = PKCS11_CKR_DEVICE_MEMORY;
60545d40bdaSValerii Chubar 			goto out;
60645d40bdaSValerii Chubar 		}
60745d40bdaSValerii Chubar 
60845d40bdaSValerii Chubar 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
60945d40bdaSValerii Chubar 				     TEE_ATTR_RSA_OAEP_LABEL,
61045d40bdaSValerii Chubar 				     rsa_aes_ctx->source_data,
61145d40bdaSValerii Chubar 				     rsa_aes_ctx->source_data_len);
61245d40bdaSValerii Chubar 		tee_attrs_count++;
61345d40bdaSValerii Chubar 		break;
614d9af50bcSVesa Jääskeläinen 	default:
615d9af50bcSVesa Jääskeläinen 		break;
616d9af50bcSVesa Jääskeläinen 	}
617d9af50bcSVesa Jääskeläinen 
618fb279d8bSVesa Jääskeläinen 	/*
619fb279d8bSVesa Jääskeläinen 	 * Handle multi stage update step for mechas needing hash
620fb279d8bSVesa Jääskeläinen 	 * calculation
621fb279d8bSVesa Jääskeläinen 	 */
622fb279d8bSVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE) {
623fb279d8bSVesa Jääskeläinen 		switch (proc->mecha_type) {
624fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA1:
625fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA224:
626fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA256:
627fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA384:
628fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA512:
6290442c956SVesa Jääskeläinen 		case PKCS11_CKM_MD5_RSA_PKCS:
6300442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA1_RSA_PKCS:
6310442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA224_RSA_PKCS:
6320442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA256_RSA_PKCS:
6330442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA384_RSA_PKCS:
6340442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA512_RSA_PKCS:
635d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
636d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
637d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
638d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
639d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
640571857c0SEtienne Carriere 			assert(proc->tee_op_handle2 != TEE_HANDLE_NULL);
641fb279d8bSVesa Jääskeläinen 
642571857c0SEtienne Carriere 			TEE_DigestUpdate(proc->tee_op_handle2, in_buf, in_size);
6439df68186SEtienne Carriere 			rc = PKCS11_CKR_OK;
644fb279d8bSVesa Jääskeläinen 			break;
645fb279d8bSVesa Jääskeläinen 		default:
646fb279d8bSVesa Jääskeläinen 			/*
647fb279d8bSVesa Jääskeläinen 			 * Other mechanism do not expect multi stage
648fb279d8bSVesa Jääskeläinen 			 * operation
649fb279d8bSVesa Jääskeläinen 			 */
650fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
651fb279d8bSVesa Jääskeläinen 			break;
652fb279d8bSVesa Jääskeläinen 		}
653fb279d8bSVesa Jääskeläinen 
654fb279d8bSVesa Jääskeläinen 		goto out;
655fb279d8bSVesa Jääskeläinen 	}
656fb279d8bSVesa Jääskeläinen 
657fb279d8bSVesa Jääskeläinen 	/*
658fb279d8bSVesa Jääskeläinen 	 * Handle multi stage one shot and final steps for mechas needing hash
659fb279d8bSVesa Jääskeläinen 	 * calculation
660fb279d8bSVesa Jääskeläinen 	 */
661fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
662fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
663fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
664fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
665fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
666fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
6670442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
6680442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
6690442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
6700442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
6710442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
6720442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
673d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
674d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
675d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
676d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
677d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
678571857c0SEtienne Carriere 		assert(proc->tee_op_handle2 != TEE_HANDLE_NULL);
679fb279d8bSVesa Jääskeläinen 
680fb279d8bSVesa Jääskeläinen 		hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo);
681fb279d8bSVesa Jääskeläinen 		hash_buf = TEE_Malloc(hash_size, 0);
682fb279d8bSVesa Jääskeläinen 		if (!hash_buf)
683fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_DEVICE_MEMORY;
684fb279d8bSVesa Jääskeläinen 
685571857c0SEtienne Carriere 		res = TEE_DigestDoFinal(proc->tee_op_handle2, in_buf, in_size,
686571857c0SEtienne Carriere 					hash_buf, &hash_size);
687fb279d8bSVesa Jääskeläinen 
688fb279d8bSVesa Jääskeläinen 		rc = tee2pkcs_error(res);
689fb279d8bSVesa Jääskeläinen 		if (rc != PKCS11_CKR_OK)
690fb279d8bSVesa Jääskeläinen 			goto out;
691fb279d8bSVesa Jääskeläinen 
692fb279d8bSVesa Jääskeläinen 		break;
693fb279d8bSVesa Jääskeläinen 	default:
694fb279d8bSVesa Jääskeläinen 		break;
695fb279d8bSVesa Jääskeläinen 	}
696fb279d8bSVesa Jääskeläinen 
697fb279d8bSVesa Jääskeläinen 	/*
698fb279d8bSVesa Jääskeläinen 	 * Finalize either provided hash or calculated hash with signing
699fb279d8bSVesa Jääskeläinen 	 * operation
700fb279d8bSVesa Jääskeläinen 	 */
701fb279d8bSVesa Jääskeläinen 
702fb279d8bSVesa Jääskeläinen 	/* First determine amount of bytes for signing operation */
703fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
704fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
705fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
706fb279d8bSVesa Jääskeläinen 		if (!in_size || !sz) {
707fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
708fb279d8bSVesa Jääskeläinen 			goto out;
709fb279d8bSVesa Jääskeläinen 		}
710fb279d8bSVesa Jääskeläinen 
711fb279d8bSVesa Jääskeläinen 		/*
712fb279d8bSVesa Jääskeläinen 		 * Note 3) Input the entire raw digest. Internally, this will
713fb279d8bSVesa Jääskeläinen 		 * be truncated to the appropriate number of bits.
714fb279d8bSVesa Jääskeläinen 		 */
715fb279d8bSVesa Jääskeläinen 		if (in_size > sz)
716fb279d8bSVesa Jääskeläinen 			in_size = sz;
717fb279d8bSVesa Jääskeläinen 
718fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) {
719fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
720fb279d8bSVesa Jääskeläinen 			goto out;
721fb279d8bSVesa Jääskeläinen 		}
722fb279d8bSVesa Jääskeläinen 		break;
723fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
724fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
725fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
726fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
727fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
728fb279d8bSVesa Jääskeläinen 		/* Get key size in bytes */
729fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
730fb279d8bSVesa Jääskeläinen 		if (!sz) {
731fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
732fb279d8bSVesa Jääskeläinen 			goto out;
733fb279d8bSVesa Jääskeläinen 		}
734fb279d8bSVesa Jääskeläinen 
735fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY &&
736fb279d8bSVesa Jääskeläinen 		    in2_size != 2 * sz) {
737fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
738fb279d8bSVesa Jääskeläinen 			goto out;
739fb279d8bSVesa Jääskeläinen 		}
740fb279d8bSVesa Jääskeläinen 		break;
7410442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
742*e02f17f3SAlexandre Marechal 	case PKCS11_CKM_RSA_X_509:
7430442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
7440442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
7450442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
7460442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
7470442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
7480442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
749d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
750d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
751d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
752d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
753d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
754d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
7550442c956SVesa Jääskeläinen 		/* Get key size in bytes */
7560442c956SVesa Jääskeläinen 		sz = rsa_get_input_max_byte_size(proc->tee_op_handle);
7570442c956SVesa Jääskeläinen 		if (!sz) {
7580442c956SVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
7590442c956SVesa Jääskeläinen 			goto out;
7600442c956SVesa Jääskeläinen 		}
7610442c956SVesa Jääskeläinen 
7620442c956SVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != sz) {
7630442c956SVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
7640442c956SVesa Jääskeläinen 			goto out;
7650442c956SVesa Jääskeläinen 		}
7660442c956SVesa Jääskeläinen 		break;
767fb279d8bSVesa Jääskeläinen 	default:
768fb279d8bSVesa Jääskeläinen 		break;
769fb279d8bSVesa Jääskeläinen 	}
770fb279d8bSVesa Jääskeläinen 
771fb279d8bSVesa Jääskeläinen 	/* Next perform actual signing operation */
772fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
773fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
77403e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
7750442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
776dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
777d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
778fb279d8bSVesa Jääskeläinen 		/* For operations using provided input data */
779fb279d8bSVesa Jääskeläinen 		switch (function) {
780fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_ENCRYPT:
781fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
782fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
783fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
784fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
785fb279d8bSVesa Jääskeläinen 			output_data = true;
786fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
7876a6299fbSVesa Jääskeläinen 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
7886a6299fbSVesa Jääskeläinen 				rc = PKCS11_CKR_DATA_LEN_RANGE;
789fb279d8bSVesa Jääskeläinen 			break;
790fb279d8bSVesa Jääskeläinen 
791fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_DECRYPT:
792fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
793fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
794fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
795fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
796fb279d8bSVesa Jääskeläinen 			output_data = true;
797fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
798f27310a5SVesa Jääskeläinen 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
799f27310a5SVesa Jääskeläinen 				rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
800fb279d8bSVesa Jääskeläinen 			break;
801fb279d8bSVesa Jääskeläinen 
802fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
803fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
804fb279d8bSVesa Jääskeläinen 						       tee_attrs,
805fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
806fb279d8bSVesa Jääskeläinen 						       in_buf, in_size,
807fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
808fb279d8bSVesa Jääskeläinen 			output_data = true;
809fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
810fb279d8bSVesa Jääskeläinen 			break;
811fb279d8bSVesa Jääskeläinen 
812fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
813fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
814fb279d8bSVesa Jääskeläinen 							 tee_attrs,
815fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
816fb279d8bSVesa Jääskeläinen 							 in_buf, in_size,
817fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
818fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
819fb279d8bSVesa Jääskeläinen 			break;
820fb279d8bSVesa Jääskeläinen 
821fb279d8bSVesa Jääskeläinen 		default:
822fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
823fb279d8bSVesa Jääskeläinen 			break;
824fb279d8bSVesa Jääskeläinen 		}
825fb279d8bSVesa Jääskeläinen 		break;
826*e02f17f3SAlexandre Marechal 
827*e02f17f3SAlexandre Marechal 	case PKCS11_CKM_RSA_X_509:
828*e02f17f3SAlexandre Marechal 		switch (function) {
829*e02f17f3SAlexandre Marechal 		case PKCS11_FUNCTION_SIGN:
830*e02f17f3SAlexandre Marechal 			/*
831*e02f17f3SAlexandre Marechal 			 * GP TEE API only allows Decrypt, not Verify operation,
832*e02f17f3SAlexandre Marechal 			 * on TEE_ALG_RSA_NOPAD. Be a bit strict on the size and
833*e02f17f3SAlexandre Marechal 			 * content of the message and ensure the generate
834*e02f17f3SAlexandre Marechal 			 * signature as the size of the modulus (@sz here).
835*e02f17f3SAlexandre Marechal 			 *
836*e02f17f3SAlexandre Marechal 			 * It remains the responsibility of the client to have
837*e02f17f3SAlexandre Marechal 			 * a safe padding scheme for the provided message data.
838*e02f17f3SAlexandre Marechal 			 */
839*e02f17f3SAlexandre Marechal 			if (in_size != sz) {
840*e02f17f3SAlexandre Marechal 				EMSG("Invalid data size %"PRIu32" != %zu",
841*e02f17f3SAlexandre Marechal 				     in_size, sz);
842*e02f17f3SAlexandre Marechal 				rc = PKCS11_CKR_DATA_LEN_RANGE;
843*e02f17f3SAlexandre Marechal 				break;
844*e02f17f3SAlexandre Marechal 			}
845*e02f17f3SAlexandre Marechal 
846*e02f17f3SAlexandre Marechal 			if (out_size < sz) {
847*e02f17f3SAlexandre Marechal 				rc = PKCS11_CKR_BUFFER_TOO_SMALL;
848*e02f17f3SAlexandre Marechal 				out_size = sz;
849*e02f17f3SAlexandre Marechal 				output_data = true;
850*e02f17f3SAlexandre Marechal 				break;
851*e02f17f3SAlexandre Marechal 			}
852*e02f17f3SAlexandre Marechal 
853*e02f17f3SAlexandre Marechal 			temp_size = sz;
854*e02f17f3SAlexandre Marechal 			temp_buf = proc->extra_ctx;
855*e02f17f3SAlexandre Marechal 			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
856*e02f17f3SAlexandre Marechal 						    tee_attrs, tee_attrs_count,
857*e02f17f3SAlexandre Marechal 						    in_buf, in_size,
858*e02f17f3SAlexandre Marechal 						    temp_buf, &temp_size);
859*e02f17f3SAlexandre Marechal 			if (!res && temp_size != sz) {
860*e02f17f3SAlexandre Marechal 				EMSG("CMK_RSA_X509: signature size %zu != %zu",
861*e02f17f3SAlexandre Marechal 				     temp_size, sz);
862*e02f17f3SAlexandre Marechal 				rc = PKCS11_CKR_DATA_INVALID;
863*e02f17f3SAlexandre Marechal 				break;
864*e02f17f3SAlexandre Marechal 			}
865*e02f17f3SAlexandre Marechal 			if (!res) {
866*e02f17f3SAlexandre Marechal 				TEE_MemMove(out_buf, temp_buf, sz);
867*e02f17f3SAlexandre Marechal 				TEE_MemFill(temp_buf, 0xa5, sz);
868*e02f17f3SAlexandre Marechal 			}
869*e02f17f3SAlexandre Marechal 			output_data = true;
870*e02f17f3SAlexandre Marechal 			rc = tee2pkcs_error(res);
871*e02f17f3SAlexandre Marechal 			out_size = sz;
872*e02f17f3SAlexandre Marechal 			break;
873*e02f17f3SAlexandre Marechal 		case PKCS11_FUNCTION_VERIFY:
874*e02f17f3SAlexandre Marechal 			/*
875*e02f17f3SAlexandre Marechal 			 * GP TEE API only allows Encrypt, not Verify operation,
876*e02f17f3SAlexandre Marechal 			 * on TEE_ALG_RSA_NOPAD. Encrypt signature in
877*e02f17f3SAlexandre Marechal 			 * temporary buffer preallocated to the size of the key.
878*e02f17f3SAlexandre Marechal 			 */
879*e02f17f3SAlexandre Marechal 			temp_size = sz;
880*e02f17f3SAlexandre Marechal 			temp_buf = proc->extra_ctx;
881*e02f17f3SAlexandre Marechal 			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
882*e02f17f3SAlexandre Marechal 						    tee_attrs, tee_attrs_count,
883*e02f17f3SAlexandre Marechal 						    in2_buf, in2_size,
884*e02f17f3SAlexandre Marechal 						    temp_buf, &temp_size);
885*e02f17f3SAlexandre Marechal 			rc = tee2pkcs_error(res);
886*e02f17f3SAlexandre Marechal 			if (rc == PKCS11_CKR_OK) {
887*e02f17f3SAlexandre Marechal 				/*
888*e02f17f3SAlexandre Marechal 				 * Skip nul bytes heading message before
889*e02f17f3SAlexandre Marechal 				 * comparing encrypted signature.
890*e02f17f3SAlexandre Marechal 				 */
891*e02f17f3SAlexandre Marechal 				char *ptr = in_buf;
892*e02f17f3SAlexandre Marechal 				size_t n = 0;
893*e02f17f3SAlexandre Marechal 
894*e02f17f3SAlexandre Marechal 				for (n = 0; n < in_size; n++)
895*e02f17f3SAlexandre Marechal 					if (ptr[n])
896*e02f17f3SAlexandre Marechal 						break;
897*e02f17f3SAlexandre Marechal 				in_size -= n;
898*e02f17f3SAlexandre Marechal 				ptr += n;
899*e02f17f3SAlexandre Marechal 				if (n > 1)
900*e02f17f3SAlexandre Marechal 					IMSG("Unsafe signature: skip %zu bytes",
901*e02f17f3SAlexandre Marechal 					     n);
902*e02f17f3SAlexandre Marechal 
903*e02f17f3SAlexandre Marechal 				if (temp_size != in_size ||
904*e02f17f3SAlexandre Marechal 				    consttime_memcmp(temp_buf, ptr, in_size))
905*e02f17f3SAlexandre Marechal 					rc = PKCS11_CKR_SIGNATURE_INVALID;
906*e02f17f3SAlexandre Marechal 			}
907*e02f17f3SAlexandre Marechal 			break;
908*e02f17f3SAlexandre Marechal 		default:
909*e02f17f3SAlexandre Marechal 			TEE_Panic(function);
910*e02f17f3SAlexandre Marechal 			break;
911*e02f17f3SAlexandre Marechal 		}
912*e02f17f3SAlexandre Marechal 		break;
913*e02f17f3SAlexandre Marechal 
914fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
915fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
916fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
917fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
918fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
9190442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
9200442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
9210442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
9220442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
9230442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
9240442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
925d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
926d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
927d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
928d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
929d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
930fb279d8bSVesa Jääskeläinen 		/* For operations having hash operation use calculated hash */
931fb279d8bSVesa Jääskeläinen 		switch (function) {
932fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
933fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
934fb279d8bSVesa Jääskeläinen 						       tee_attrs,
935fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
936fb279d8bSVesa Jääskeläinen 						       hash_buf, hash_size,
937fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
938fb279d8bSVesa Jääskeläinen 			output_data = true;
939fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
940fb279d8bSVesa Jääskeläinen 			break;
941fb279d8bSVesa Jääskeläinen 
942fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
943fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
944fb279d8bSVesa Jääskeläinen 							 tee_attrs,
945fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
946fb279d8bSVesa Jääskeläinen 							 hash_buf, hash_size,
947fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
948fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
949fb279d8bSVesa Jääskeläinen 			break;
950fb279d8bSVesa Jääskeläinen 
951fb279d8bSVesa Jääskeläinen 		default:
952fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
953fb279d8bSVesa Jääskeläinen 			break;
954fb279d8bSVesa Jääskeläinen 		}
955fb279d8bSVesa Jääskeläinen 		break;
956fb279d8bSVesa Jääskeläinen 	default:
957fb279d8bSVesa Jääskeläinen 		TEE_Panic(proc->mecha_type);
958fb279d8bSVesa Jääskeläinen 		break;
959fb279d8bSVesa Jääskeläinen 	}
960fb279d8bSVesa Jääskeläinen 
961fb279d8bSVesa Jääskeläinen out:
962fb279d8bSVesa Jääskeläinen 	if (output_data &&
963fb279d8bSVesa Jääskeläinen 	    (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) {
964fb279d8bSVesa Jääskeläinen 		switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
965fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
966fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_INOUT:
967fb279d8bSVesa Jääskeläinen 			params[2].memref.size = out_size;
968fb279d8bSVesa Jääskeläinen 			break;
969fb279d8bSVesa Jääskeläinen 		default:
970fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
971fb279d8bSVesa Jääskeläinen 			break;
972fb279d8bSVesa Jääskeläinen 		}
973fb279d8bSVesa Jääskeläinen 	}
974fb279d8bSVesa Jääskeläinen 
975fb279d8bSVesa Jääskeläinen 	TEE_Free(hash_buf);
976fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
977fb279d8bSVesa Jääskeläinen 
978fb279d8bSVesa Jääskeläinen 	return rc;
979fb279d8bSVesa Jääskeläinen }
980cc062b46SJorge Ramirez-Ortiz 
981cc062b46SJorge Ramirez-Ortiz enum pkcs11_rc do_asymm_derivation(struct pkcs11_session *session,
982cc062b46SJorge Ramirez-Ortiz 				   struct pkcs11_attribute_head *proc_params,
983cc062b46SJorge Ramirez-Ortiz 				   struct obj_attrs **head)
984cc062b46SJorge Ramirez-Ortiz {
985cc062b46SJorge Ramirez-Ortiz 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
986cc062b46SJorge Ramirez-Ortiz 	TEE_ObjectHandle out_handle = TEE_HANDLE_NULL;
987cc062b46SJorge Ramirez-Ortiz 	TEE_Result res = TEE_ERROR_GENERIC;
988cc062b46SJorge Ramirez-Ortiz 	TEE_Attribute tee_attrs[2] = { };
989cc062b46SJorge Ramirez-Ortiz 	size_t tee_attrs_count = 0;
990cc062b46SJorge Ramirez-Ortiz 	uint32_t key_byte_size = 0;
991cc062b46SJorge Ramirez-Ortiz 	uint32_t key_bit_size = 0;
992cc062b46SJorge Ramirez-Ortiz 	void *a_ptr = NULL;
993cc062b46SJorge Ramirez-Ortiz 	size_t a_size = 0;
994cc062b46SJorge Ramirez-Ortiz 
995cc062b46SJorge Ramirez-Ortiz 	/* Remove default attribute set at template sanitization */
996cc062b46SJorge Ramirez-Ortiz 	if (remove_empty_attribute(head, PKCS11_CKA_VALUE))
997cc062b46SJorge Ramirez-Ortiz 		return PKCS11_CKR_FUNCTION_FAILED;
998cc062b46SJorge Ramirez-Ortiz 
999cc062b46SJorge Ramirez-Ortiz 	rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_bit_size);
1000cc062b46SJorge Ramirez-Ortiz 	if (rc)
1001cc062b46SJorge Ramirez-Ortiz 		return rc;
1002cc062b46SJorge Ramirez-Ortiz 
1003cc062b46SJorge Ramirez-Ortiz 	key_bit_size *= 8;
1004cc062b46SJorge Ramirez-Ortiz 	key_byte_size = (key_bit_size + 7) / 8;
1005cc062b46SJorge Ramirez-Ortiz 
1006cc062b46SJorge Ramirez-Ortiz 	res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET,
1007cc062b46SJorge Ramirez-Ortiz 					  key_byte_size * 8, &out_handle);
1008cc062b46SJorge Ramirez-Ortiz 	if (res) {
1009cc062b46SJorge Ramirez-Ortiz 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
1010cc062b46SJorge Ramirez-Ortiz 		return tee2pkcs_error(res);
1011cc062b46SJorge Ramirez-Ortiz 	}
1012cc062b46SJorge Ramirez-Ortiz 
1013cc062b46SJorge Ramirez-Ortiz 	switch (proc_params->id) {
1014cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
1015cc062b46SJorge Ramirez-Ortiz 		rc = pkcs2tee_param_ecdh(proc_params, &a_ptr, &a_size);
1016cc062b46SJorge Ramirez-Ortiz 		if (rc)
1017cc062b46SJorge Ramirez-Ortiz 			goto out;
1018cc062b46SJorge Ramirez-Ortiz 
1019cc062b46SJorge Ramirez-Ortiz 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
1020cc062b46SJorge Ramirez-Ortiz 				     TEE_ATTR_ECC_PUBLIC_VALUE_X,
1021cc062b46SJorge Ramirez-Ortiz 				     a_ptr, a_size / 2);
1022cc062b46SJorge Ramirez-Ortiz 		tee_attrs_count++;
1023cc062b46SJorge Ramirez-Ortiz 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
1024cc062b46SJorge Ramirez-Ortiz 				     TEE_ATTR_ECC_PUBLIC_VALUE_Y,
1025cc062b46SJorge Ramirez-Ortiz 				     (char *)a_ptr + a_size / 2,
1026cc062b46SJorge Ramirez-Ortiz 				     a_size / 2);
1027cc062b46SJorge Ramirez-Ortiz 		tee_attrs_count++;
1028cc062b46SJorge Ramirez-Ortiz 		break;
1029cc062b46SJorge Ramirez-Ortiz 	default:
1030cc062b46SJorge Ramirez-Ortiz 		TEE_Panic(proc_params->id);
1031cc062b46SJorge Ramirez-Ortiz 		break;
1032cc062b46SJorge Ramirez-Ortiz 	}
1033cc062b46SJorge Ramirez-Ortiz 
1034cc062b46SJorge Ramirez-Ortiz 	TEE_DeriveKey(session->processing->tee_op_handle, &tee_attrs[0],
1035cc062b46SJorge Ramirez-Ortiz 		      tee_attrs_count, out_handle);
1036cc062b46SJorge Ramirez-Ortiz 
1037cc062b46SJorge Ramirez-Ortiz 	rc = alloc_get_tee_attribute_data(out_handle, TEE_ATTR_SECRET_VALUE,
1038cc062b46SJorge Ramirez-Ortiz 					  &a_ptr, &a_size);
1039cc062b46SJorge Ramirez-Ortiz 	if (rc)
1040cc062b46SJorge Ramirez-Ortiz 		goto out;
1041cc062b46SJorge Ramirez-Ortiz 
1042cc062b46SJorge Ramirez-Ortiz 	if (a_size * 8 < key_bit_size)
1043cc062b46SJorge Ramirez-Ortiz 		rc = PKCS11_CKR_KEY_SIZE_RANGE;
1044cc062b46SJorge Ramirez-Ortiz 	else
1045cc062b46SJorge Ramirez-Ortiz 		rc = add_attribute(head, PKCS11_CKA_VALUE, a_ptr,
1046cc062b46SJorge Ramirez-Ortiz 				   key_byte_size);
1047cc062b46SJorge Ramirez-Ortiz 	TEE_Free(a_ptr);
1048cc062b46SJorge Ramirez-Ortiz out:
1049cc062b46SJorge Ramirez-Ortiz 	release_active_processing(session);
1050cc062b46SJorge Ramirez-Ortiz 	TEE_FreeTransientObject(out_handle);
1051cc062b46SJorge Ramirez-Ortiz 
1052cc062b46SJorge Ramirez-Ortiz 	return rc;
1053cc062b46SJorge Ramirez-Ortiz }
105445d40bdaSValerii Chubar 
105545d40bdaSValerii Chubar static enum pkcs11_rc wrap_rsa_aes_key(struct active_processing *proc,
105645d40bdaSValerii Chubar 				       void *data, uint32_t data_sz,
105745d40bdaSValerii Chubar 				       void *out_buf, uint32_t *out_sz)
105845d40bdaSValerii Chubar {
105945d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_OK;
106045d40bdaSValerii Chubar 	TEE_Result res = TEE_ERROR_GENERIC;
106145d40bdaSValerii Chubar 	int mbedtls_rc = 0;
106245d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx;
106345d40bdaSValerii Chubar 	mbedtls_nist_kw_context kw_ctx = { };
106445d40bdaSValerii Chubar 	uint8_t aes_key_value[32] = { };
106545d40bdaSValerii Chubar 	uint32_t aes_key_size = ctx->aes_key_bits / 8;
1066c7f1b4f7SJens Wiklander 	size_t aes_wrapped_size = *out_sz;
106745d40bdaSValerii Chubar 	uint32_t expected_size = 0;
106845d40bdaSValerii Chubar 	size_t target_key_size = 0;
106945d40bdaSValerii Chubar 	const size_t kw_semiblock_len = 8;
107045d40bdaSValerii Chubar 
107145d40bdaSValerii Chubar 	if (ctx->aes_key_bits != 128 &&
107245d40bdaSValerii Chubar 	    ctx->aes_key_bits != 192 &&
107345d40bdaSValerii Chubar 	    ctx->aes_key_bits != 256)
107445d40bdaSValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
107545d40bdaSValerii Chubar 
107645d40bdaSValerii Chubar 	mbedtls_nist_kw_init(&kw_ctx);
107745d40bdaSValerii Chubar 	TEE_GenerateRandom(aes_key_value, aes_key_size);
107845d40bdaSValerii Chubar 	res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
107945d40bdaSValerii Chubar 				    NULL, 0,
108045d40bdaSValerii Chubar 				    aes_key_value, aes_key_size,
108145d40bdaSValerii Chubar 				    out_buf, &aes_wrapped_size);
108245d40bdaSValerii Chubar 	expected_size = aes_wrapped_size + data_sz + kw_semiblock_len;
108345d40bdaSValerii Chubar 	if (res) {
108445d40bdaSValerii Chubar 		if (res == TEE_ERROR_SHORT_BUFFER)
108545d40bdaSValerii Chubar 			*out_sz = expected_size;
108645d40bdaSValerii Chubar 
108745d40bdaSValerii Chubar 		rc = tee2pkcs_error(res);
108845d40bdaSValerii Chubar 		goto out;
108945d40bdaSValerii Chubar 	}
109045d40bdaSValerii Chubar 
109145d40bdaSValerii Chubar 	if (*out_sz < expected_size) {
109245d40bdaSValerii Chubar 		rc = PKCS11_CKR_BUFFER_TOO_SMALL;
109345d40bdaSValerii Chubar 		*out_sz = expected_size;
109445d40bdaSValerii Chubar 		goto out;
109545d40bdaSValerii Chubar 	}
109645d40bdaSValerii Chubar 
109745d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES,
109845d40bdaSValerii Chubar 					    aes_key_value, ctx->aes_key_bits,
109945d40bdaSValerii Chubar 					    true);
110045d40bdaSValerii Chubar 	if (mbedtls_rc) {
110145d40bdaSValerii Chubar 		if (mbedtls_rc == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA)
110245d40bdaSValerii Chubar 			rc = PKCS11_CKR_KEY_SIZE_RANGE;
110345d40bdaSValerii Chubar 		else
110445d40bdaSValerii Chubar 			rc = PKCS11_CKR_FUNCTION_FAILED;
110545d40bdaSValerii Chubar 
110645d40bdaSValerii Chubar 		goto out;
110745d40bdaSValerii Chubar 	}
110845d40bdaSValerii Chubar 
110945d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_wrap(&kw_ctx, MBEDTLS_KW_MODE_KWP,
111045d40bdaSValerii Chubar 					  data, data_sz,
111145d40bdaSValerii Chubar 					  (uint8_t *)out_buf + aes_wrapped_size,
111245d40bdaSValerii Chubar 					  &target_key_size,
111345d40bdaSValerii Chubar 					  *out_sz - aes_wrapped_size);
111445d40bdaSValerii Chubar 	if (mbedtls_rc) {
111545d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
111645d40bdaSValerii Chubar 		goto out;
111745d40bdaSValerii Chubar 	}
111845d40bdaSValerii Chubar 
111945d40bdaSValerii Chubar 	assert(*out_sz >= target_key_size + aes_wrapped_size);
112045d40bdaSValerii Chubar 	*out_sz = target_key_size + aes_wrapped_size;
112145d40bdaSValerii Chubar 
112245d40bdaSValerii Chubar out:
112345d40bdaSValerii Chubar 	mbedtls_nist_kw_free(&kw_ctx);
112445d40bdaSValerii Chubar 	TEE_MemFill(aes_key_value, 0, aes_key_size);
112545d40bdaSValerii Chubar 	return rc;
112645d40bdaSValerii Chubar }
112745d40bdaSValerii Chubar 
112845d40bdaSValerii Chubar static enum pkcs11_rc unwrap_rsa_aes_key(struct active_processing *proc,
112945d40bdaSValerii Chubar 					 void *data, uint32_t data_sz,
113045d40bdaSValerii Chubar 					 void **out_buf, uint32_t *out_sz)
113145d40bdaSValerii Chubar {
113245d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_OK;
113345d40bdaSValerii Chubar 	int mbedtls_rc = 0;
113445d40bdaSValerii Chubar 	TEE_Result res = TEE_ERROR_GENERIC;
113545d40bdaSValerii Chubar 	TEE_OperationInfo info = { };
113645d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx;
113745d40bdaSValerii Chubar 	mbedtls_nist_kw_context kw_ctx = { };
113845d40bdaSValerii Chubar 	uint8_t aes_key_value[32] = { };
1139c7f1b4f7SJens Wiklander 	size_t aes_key_size = ctx->aes_key_bits / 8;
114045d40bdaSValerii Chubar 	uint32_t wrapped_key_size = 0;
114145d40bdaSValerii Chubar 	uint32_t rsa_key_size = 0;
114245d40bdaSValerii Chubar 	size_t target_key_size = 0;
114345d40bdaSValerii Chubar 
114445d40bdaSValerii Chubar 	if (ctx->aes_key_bits != 128 &&
114545d40bdaSValerii Chubar 	    ctx->aes_key_bits != 192 &&
114645d40bdaSValerii Chubar 	    ctx->aes_key_bits != 256)
114745d40bdaSValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
114845d40bdaSValerii Chubar 
114945d40bdaSValerii Chubar 	TEE_GetOperationInfo(proc->tee_op_handle, &info);
115045d40bdaSValerii Chubar 	rsa_key_size = info.keySize / 8;
115145d40bdaSValerii Chubar 	wrapped_key_size = data_sz - rsa_key_size;
115245d40bdaSValerii Chubar 	target_key_size = wrapped_key_size - 8;
115345d40bdaSValerii Chubar 
115445d40bdaSValerii Chubar 	*out_buf = TEE_Malloc(target_key_size, TEE_MALLOC_FILL_ZERO);
115545d40bdaSValerii Chubar 	if (!*out_buf)
115645d40bdaSValerii Chubar 		return PKCS11_CKR_DEVICE_MEMORY;
115745d40bdaSValerii Chubar 
115845d40bdaSValerii Chubar 	mbedtls_nist_kw_init(&kw_ctx);
115945d40bdaSValerii Chubar 	res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
116045d40bdaSValerii Chubar 				    NULL, 0,
116145d40bdaSValerii Chubar 				    data, rsa_key_size,
116245d40bdaSValerii Chubar 				    aes_key_value, &aes_key_size);
116345d40bdaSValerii Chubar 	if (res) {
116445d40bdaSValerii Chubar 		rc = tee2pkcs_error(res);
116545d40bdaSValerii Chubar 		goto out;
116645d40bdaSValerii Chubar 	}
116745d40bdaSValerii Chubar 
116845d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES,
116945d40bdaSValerii Chubar 					    aes_key_value, ctx->aes_key_bits,
117045d40bdaSValerii Chubar 					    false);
117145d40bdaSValerii Chubar 	if (mbedtls_rc) {
117245d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
117345d40bdaSValerii Chubar 		goto out;
117445d40bdaSValerii Chubar 	}
117545d40bdaSValerii Chubar 
117645d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_unwrap(&kw_ctx, MBEDTLS_KW_MODE_KWP,
117745d40bdaSValerii Chubar 					    (uint8_t *)data + rsa_key_size,
117845d40bdaSValerii Chubar 					    wrapped_key_size, *out_buf,
117945d40bdaSValerii Chubar 					    &target_key_size, target_key_size);
118045d40bdaSValerii Chubar 	if (mbedtls_rc) {
118145d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
118245d40bdaSValerii Chubar 		goto out;
118345d40bdaSValerii Chubar 	}
118445d40bdaSValerii Chubar 
118545d40bdaSValerii Chubar 	*out_sz = target_key_size;
118645d40bdaSValerii Chubar out:
118745d40bdaSValerii Chubar 	TEE_MemFill(aes_key_value, 0, aes_key_size);
118845d40bdaSValerii Chubar 	mbedtls_nist_kw_free(&kw_ctx);
118945d40bdaSValerii Chubar 	return rc;
119045d40bdaSValerii Chubar }
119145d40bdaSValerii Chubar 
119245d40bdaSValerii Chubar enum pkcs11_rc wrap_data_by_asymm_enc(struct pkcs11_session *session,
119345d40bdaSValerii Chubar 				      void *data, uint32_t data_sz,
119445d40bdaSValerii Chubar 				      void *out_buf, uint32_t *out_sz)
119545d40bdaSValerii Chubar {
119645d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
119745d40bdaSValerii Chubar 	struct active_processing *proc = session->processing;
119845d40bdaSValerii Chubar 
119945d40bdaSValerii Chubar 	switch (proc->mecha_type) {
120045d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
120145d40bdaSValerii Chubar 		rc = wrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz);
120245d40bdaSValerii Chubar 		break;
120345d40bdaSValerii Chubar 	default:
120445d40bdaSValerii Chubar 		return PKCS11_CKR_MECHANISM_INVALID;
120545d40bdaSValerii Chubar 	}
120645d40bdaSValerii Chubar 
120745d40bdaSValerii Chubar 	return rc;
120845d40bdaSValerii Chubar }
120945d40bdaSValerii Chubar 
121045d40bdaSValerii Chubar enum pkcs11_rc unwrap_key_by_asymm(struct pkcs11_session *session,
121145d40bdaSValerii Chubar 				   void *data, uint32_t data_sz,
121245d40bdaSValerii Chubar 				   void **out_buf, uint32_t *out_sz)
121345d40bdaSValerii Chubar {
121445d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
121545d40bdaSValerii Chubar 	struct active_processing *proc = session->processing;
121645d40bdaSValerii Chubar 
121745d40bdaSValerii Chubar 	switch (proc->mecha_type) {
121845d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
121945d40bdaSValerii Chubar 		rc = unwrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz);
122045d40bdaSValerii Chubar 		break;
122145d40bdaSValerii Chubar 	default:
122245d40bdaSValerii Chubar 		return PKCS11_CKR_MECHANISM_INVALID;
122345d40bdaSValerii Chubar 	}
122445d40bdaSValerii Chubar 
122545d40bdaSValerii Chubar 	return rc;
122645d40bdaSValerii Chubar }
1227