xref: /optee_os/ta/pkcs11/src/processing_asymm.c (revision b7abff7230abfd93c84625b0022e552f9a8212ca)
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>
9e02f17f3SAlexandre 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 
processing_is_tee_asymm(uint32_t proc_id)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:
26e02f17f3SAlexandre 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
pkcs2tee_algorithm(uint32_t * tee_id,uint32_t * tee_hash_id,enum processing_func function __unused,struct pkcs11_attribute_head * proc_params,struct pkcs11_object * obj)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 },
71e02f17f3SAlexandre 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 
pkcs2tee_key_type(uint32_t * tee_type,struct pkcs11_object * obj,enum processing_func function)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
allocate_tee_operation(struct pkcs11_session * session,enum processing_func function,struct pkcs11_attribute_head * params,struct pkcs11_object * obj)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 
233e02f17f3SAlexandre Marechal 	/*
234e02f17f3SAlexandre Marechal 	 * PKCS#11 allows Sign/Verify with CKM_RSA_X_509 while GP TEE API
235e02f17f3SAlexandre Marechal 	 * only permits Encrypt/Decrypt with TEE_ALG_RSA_NOPAD.
236e02f17f3SAlexandre Marechal 	 * For other algorithm, use simple 1-to-1 ID conversion pkcs2tee_mode().
237e02f17f3SAlexandre Marechal 	 */
238e02f17f3SAlexandre Marechal 	if (params->id == PKCS11_CKM_RSA_X_509) {
239e02f17f3SAlexandre Marechal 		assert(!hash_algo);
240e02f17f3SAlexandre Marechal 		switch (function) {
241*b7abff72SEtienne Carriere 		case PKCS11_FUNCTION_ENCRYPT:
242e02f17f3SAlexandre Marechal 		case PKCS11_FUNCTION_VERIFY:
243e02f17f3SAlexandre Marechal 			mode = TEE_MODE_ENCRYPT;
244e02f17f3SAlexandre Marechal 			break;
245*b7abff72SEtienne Carriere 		case PKCS11_FUNCTION_DECRYPT:
246e02f17f3SAlexandre Marechal 		case PKCS11_FUNCTION_SIGN:
247e02f17f3SAlexandre Marechal 			mode = TEE_MODE_DECRYPT;
248e02f17f3SAlexandre Marechal 			break;
249e02f17f3SAlexandre Marechal 		default:
250e02f17f3SAlexandre Marechal 			TEE_Panic(0);
251e02f17f3SAlexandre Marechal 		}
252e02f17f3SAlexandre Marechal 	} else {
253fb279d8bSVesa Jääskeläinen 		pkcs2tee_mode(&mode, function);
254e02f17f3SAlexandre Marechal 	}
255fb279d8bSVesa Jääskeläinen 
256fb279d8bSVesa Jääskeläinen 	if (hash_algo) {
257fb279d8bSVesa Jääskeläinen 		pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST);
258fb279d8bSVesa Jääskeläinen 
259571857c0SEtienne Carriere 		res = TEE_AllocateOperation(&processing->tee_op_handle2,
260fb279d8bSVesa Jääskeläinen 					    hash_algo, hash_mode, 0);
261fb279d8bSVesa Jääskeläinen 		if (res) {
262fb279d8bSVesa Jääskeläinen 			EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32,
263fb279d8bSVesa Jääskeläinen 			     hash_algo, hash_mode);
264fb279d8bSVesa Jääskeläinen 
265fb279d8bSVesa Jääskeläinen 			if (res == TEE_ERROR_NOT_SUPPORTED)
266fb279d8bSVesa Jääskeläinen 				return PKCS11_CKR_MECHANISM_INVALID;
267fb279d8bSVesa Jääskeläinen 			return tee2pkcs_error(res);
268fb279d8bSVesa Jääskeläinen 		}
269fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = hash_algo;
270fb279d8bSVesa Jääskeläinen 	}
271fb279d8bSVesa Jääskeläinen 
272fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateOperation(&processing->tee_op_handle,
273fb279d8bSVesa Jääskeläinen 				    algo, mode, size);
274fb279d8bSVesa Jääskeläinen 	if (res)
275fb279d8bSVesa Jääskeläinen 		EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32,
276fb279d8bSVesa Jääskeläinen 		     algo, mode, size);
277fb279d8bSVesa Jääskeläinen 
278fb279d8bSVesa Jääskeläinen 	if (res == TEE_ERROR_NOT_SUPPORTED)
279fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_MECHANISM_INVALID;
280fb279d8bSVesa Jääskeläinen 
281fb279d8bSVesa Jääskeläinen 	if (res != TEE_SUCCESS &&
282571857c0SEtienne Carriere 	    processing->tee_op_handle2 != TEE_HANDLE_NULL) {
283571857c0SEtienne Carriere 		TEE_FreeOperation(session->processing->tee_op_handle2);
284571857c0SEtienne Carriere 		processing->tee_op_handle2 = TEE_HANDLE_NULL;
285fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = 0;
286fb279d8bSVesa Jääskeläinen 	}
287fb279d8bSVesa Jääskeläinen 
288fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
289fb279d8bSVesa Jääskeläinen }
290fb279d8bSVesa Jääskeläinen 
load_tee_key(struct pkcs11_session * session,struct pkcs11_object * obj,enum processing_func function)291fb279d8bSVesa Jääskeläinen static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
292fb279d8bSVesa Jääskeläinen 				   struct pkcs11_object *obj,
293fb279d8bSVesa Jääskeläinen 				   enum processing_func function)
294fb279d8bSVesa Jääskeläinen {
295fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
296fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
297fb279d8bSVesa Jääskeläinen 	size_t object_size = 0;
298fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
299fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
300fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id __maybe_unused class = get_class(obj->attributes);
301fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
302fb279d8bSVesa Jääskeläinen 
303fb279d8bSVesa Jääskeläinen 	assert(class == PKCS11_CKO_PUBLIC_KEY ||
304fb279d8bSVesa Jääskeläinen 	       class == PKCS11_CKO_PRIVATE_KEY);
305fb279d8bSVesa Jääskeläinen 
306fb279d8bSVesa Jääskeläinen 	if (obj->key_handle != TEE_HANDLE_NULL) {
307fb279d8bSVesa Jääskeläinen 		switch (type) {
3080442c956SVesa Jääskeläinen 		case PKCS11_CKK_RSA:
3090442c956SVesa Jääskeläinen 			/* RSA loaded keys can be reused */
3100442c956SVesa Jääskeläinen 			assert((obj->key_type == TEE_TYPE_RSA_PUBLIC_KEY &&
3110442c956SVesa Jääskeläinen 				class == PKCS11_CKO_PUBLIC_KEY) ||
3120442c956SVesa Jääskeläinen 			       (obj->key_type == TEE_TYPE_RSA_KEYPAIR &&
3130442c956SVesa Jääskeläinen 				class == PKCS11_CKO_PRIVATE_KEY));
3140442c956SVesa Jääskeläinen 			goto key_ready;
315fb279d8bSVesa Jääskeläinen 		case PKCS11_CKK_EC:
316fb279d8bSVesa Jääskeläinen 			/* Reuse EC TEE key only if already DSA or DH */
317fb279d8bSVesa Jääskeläinen 			switch (obj->key_type) {
318fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_PUBLIC_KEY:
319fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_KEYPAIR:
320fb279d8bSVesa Jääskeläinen 				if (function != PKCS11_FUNCTION_DERIVE)
321fb279d8bSVesa Jääskeläinen 					goto key_ready;
322fb279d8bSVesa Jääskeläinen 				break;
323cc062b46SJorge Ramirez-Ortiz 			case TEE_TYPE_ECDH_PUBLIC_KEY:
324cc062b46SJorge Ramirez-Ortiz 			case TEE_TYPE_ECDH_KEYPAIR:
325cc062b46SJorge Ramirez-Ortiz 				if (function == PKCS11_FUNCTION_DERIVE)
326cc062b46SJorge Ramirez-Ortiz 					goto key_ready;
327cc062b46SJorge Ramirez-Ortiz 				break;
328fb279d8bSVesa Jääskeläinen 			default:
329fb279d8bSVesa Jääskeläinen 				assert(0);
330fb279d8bSVesa Jääskeläinen 				break;
331fb279d8bSVesa Jääskeläinen 			}
332fb279d8bSVesa Jääskeläinen 			break;
333fb279d8bSVesa Jääskeläinen 		default:
334fb279d8bSVesa Jääskeläinen 			assert(0);
335fb279d8bSVesa Jääskeläinen 			break;
336fb279d8bSVesa Jääskeläinen 		}
337fb279d8bSVesa Jääskeläinen 
338fb279d8bSVesa Jääskeläinen 		TEE_CloseObject(obj->key_handle);
339fb279d8bSVesa Jääskeläinen 		obj->key_handle = TEE_HANDLE_NULL;
340fb279d8bSVesa Jääskeläinen 	}
341fb279d8bSVesa Jääskeläinen 
342fb279d8bSVesa Jääskeläinen 	rc = pkcs2tee_key_type(&obj->key_type, obj, function);
343fb279d8bSVesa Jääskeläinen 	if (rc)
344fb279d8bSVesa Jääskeläinen 		return rc;
345fb279d8bSVesa Jääskeläinen 
346fb279d8bSVesa Jääskeläinen 	object_size = get_object_key_bit_size(obj);
347fb279d8bSVesa Jääskeläinen 	if (!object_size)
348fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
349fb279d8bSVesa Jääskeläinen 
350fb279d8bSVesa Jääskeläinen 	switch (type) {
3510442c956SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
3520442c956SVesa Jääskeläinen 		rc = load_tee_rsa_key_attrs(&tee_attrs, &tee_attrs_count, obj);
3530442c956SVesa Jääskeläinen 		break;
354fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
355fb279d8bSVesa Jääskeläinen 		rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj);
356fb279d8bSVesa Jääskeläinen 		break;
35703e07432SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
35803e07432SValerii Chubar 		rc = load_tee_eddsa_key_attrs(&tee_attrs, &tee_attrs_count,
35903e07432SValerii Chubar 					      obj);
36003e07432SValerii Chubar 		break;
361fb279d8bSVesa Jääskeläinen 	default:
362fb279d8bSVesa Jääskeläinen 		break;
363fb279d8bSVesa Jääskeläinen 	}
364fb279d8bSVesa Jääskeläinen 	if (rc)
365fb279d8bSVesa Jääskeläinen 		return rc;
366fb279d8bSVesa Jääskeläinen 
367fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateTransientObject(obj->key_type, object_size,
368fb279d8bSVesa Jääskeläinen 					  &obj->key_handle);
369fb279d8bSVesa Jääskeläinen 	if (res) {
370fb279d8bSVesa Jääskeläinen 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
371fb279d8bSVesa Jääskeläinen 
372fb279d8bSVesa Jääskeläinen 		return tee2pkcs_error(res);
373fb279d8bSVesa Jääskeläinen 	}
374fb279d8bSVesa Jääskeläinen 
375fb279d8bSVesa Jääskeläinen 	res = TEE_PopulateTransientObject(obj->key_handle,
376fb279d8bSVesa Jääskeläinen 					  tee_attrs, tee_attrs_count);
377fb279d8bSVesa Jääskeläinen 
378fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
379fb279d8bSVesa Jääskeläinen 
380fb279d8bSVesa Jääskeläinen 	if (res) {
381fb279d8bSVesa Jääskeläinen 		DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res);
382fb279d8bSVesa Jääskeläinen 
383fb279d8bSVesa Jääskeläinen 		goto error;
384fb279d8bSVesa Jääskeläinen 	}
385fb279d8bSVesa Jääskeläinen 
386fb279d8bSVesa Jääskeläinen key_ready:
387fb279d8bSVesa Jääskeläinen 	res = TEE_SetOperationKey(session->processing->tee_op_handle,
388fb279d8bSVesa Jääskeläinen 				  obj->key_handle);
389fb279d8bSVesa Jääskeläinen 	if (res) {
390fb279d8bSVesa Jääskeläinen 		DMSG("TEE_SetOperationKey failed, %#"PRIx32, res);
391fb279d8bSVesa Jääskeläinen 
392fb279d8bSVesa Jääskeläinen 		goto error;
393fb279d8bSVesa Jääskeläinen 	}
394fb279d8bSVesa Jääskeläinen 
395fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
396fb279d8bSVesa Jääskeläinen 
397fb279d8bSVesa Jääskeläinen error:
398fb279d8bSVesa Jääskeläinen 	TEE_FreeTransientObject(obj->key_handle);
399fb279d8bSVesa Jääskeläinen 	obj->key_handle = TEE_HANDLE_NULL;
400fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
401fb279d8bSVesa Jääskeläinen }
402fb279d8bSVesa Jääskeläinen 
403fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
init_tee_operation(struct pkcs11_session * session,struct pkcs11_attribute_head * proc_params,struct pkcs11_object * obj)404d9af50bcSVesa Jääskeläinen init_tee_operation(struct pkcs11_session *session,
405d9af50bcSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params,
406d9af50bcSVesa Jääskeläinen 		   struct pkcs11_object *obj)
407fb279d8bSVesa Jääskeläinen {
408d9af50bcSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
409d9af50bcSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
410d9af50bcSVesa Jääskeläinen 
411d9af50bcSVesa Jääskeläinen 	switch (proc_params->id) {
412e02f17f3SAlexandre Marechal 	case PKCS11_CKM_RSA_X_509:
413e02f17f3SAlexandre Marechal 		rc = pkcs2tee_rsa_nopad_context(proc);
414e02f17f3SAlexandre Marechal 		break;
415d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
416d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
417d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
418d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
419d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
420d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
421d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_proc_params_rsa_pss(proc, proc_params);
422d9af50bcSVesa Jääskeläinen 		if (rc)
423d9af50bcSVesa Jääskeläinen 			break;
424d9af50bcSVesa Jääskeläinen 
425d9af50bcSVesa Jääskeläinen 		rc = pkcs2tee_validate_rsa_pss(proc, obj);
426d9af50bcSVesa Jääskeläinen 		break;
427dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
428dc8c77fcSVesa Jääskeläinen 		rc = pkcs2tee_proc_params_rsa_oaep(proc, proc_params);
429dc8c77fcSVesa Jääskeläinen 		break;
43003e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
43103e07432SValerii Chubar 		rc = pkcs2tee_proc_params_eddsa(proc, proc_params);
43203e07432SValerii Chubar 		break;
43345d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
43445d40bdaSValerii Chubar 		rc = pkcs2tee_proc_params_rsa_aes_wrap(proc, proc_params);
43545d40bdaSValerii Chubar 		break;
436d9af50bcSVesa Jääskeläinen 	default:
437d9af50bcSVesa Jääskeläinen 		break;
438d9af50bcSVesa Jääskeläinen 	}
439d9af50bcSVesa Jääskeläinen 
440d9af50bcSVesa Jääskeläinen 	return rc;
441fb279d8bSVesa Jääskeläinen }
442fb279d8bSVesa Jääskeläinen 
init_asymm_operation(struct pkcs11_session * session,enum processing_func function,struct pkcs11_attribute_head * proc_params,struct pkcs11_object * obj)443fb279d8bSVesa Jääskeläinen enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session,
444fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
445fb279d8bSVesa Jääskeläinen 				    struct pkcs11_attribute_head *proc_params,
446fb279d8bSVesa Jääskeläinen 				    struct pkcs11_object *obj)
447fb279d8bSVesa Jääskeläinen {
448fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
449fb279d8bSVesa Jääskeläinen 
450fb279d8bSVesa Jääskeläinen 	assert(processing_is_tee_asymm(proc_params->id));
451fb279d8bSVesa Jääskeläinen 
452fb279d8bSVesa Jääskeläinen 	rc = allocate_tee_operation(session, function, proc_params, obj);
453fb279d8bSVesa Jääskeläinen 	if (rc)
454fb279d8bSVesa Jääskeläinen 		return rc;
455fb279d8bSVesa Jääskeläinen 
456fb279d8bSVesa Jääskeläinen 	rc = load_tee_key(session, obj, function);
457fb279d8bSVesa Jääskeläinen 	if (rc)
458fb279d8bSVesa Jääskeläinen 		return rc;
459fb279d8bSVesa Jääskeläinen 
460909efccbSEtienne Carriere 	rc = init_tee_operation(session, proc_params, obj);
461909efccbSEtienne Carriere 	if (!rc)
462909efccbSEtienne Carriere 		session->processing->mecha_type = proc_params->id;
463909efccbSEtienne Carriere 
464909efccbSEtienne Carriere 	return rc;
465fb279d8bSVesa Jääskeläinen }
466fb279d8bSVesa Jääskeläinen 
467fb279d8bSVesa Jääskeläinen /*
468fb279d8bSVesa Jääskeläinen  * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation
469fb279d8bSVesa Jääskeläinen  *
470fb279d8bSVesa Jääskeläinen  * @session - current session
471fb279d8bSVesa Jääskeläinen  * @function - processing function (encrypt, decrypt, sign, ...)
472fb279d8bSVesa Jääskeläinen  * @step - step ID in the processing (oneshot, update, final)
473fb279d8bSVesa Jääskeläinen  * @ptypes - invocation parameter types
474fb279d8bSVesa Jääskeläinen  * @params - invocation parameter references
475fb279d8bSVesa Jääskeläinen  */
step_asymm_operation(struct pkcs11_session * session,enum processing_func function,enum processing_step step,uint32_t ptypes,TEE_Param * params)476fb279d8bSVesa Jääskeläinen enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
477fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
478fb279d8bSVesa Jääskeläinen 				    enum processing_step step,
479fb279d8bSVesa Jääskeläinen 				    uint32_t ptypes, TEE_Param *params)
480fb279d8bSVesa Jääskeläinen {
481fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
482fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
483fb279d8bSVesa Jääskeläinen 	void *in_buf = NULL;
484fb279d8bSVesa Jääskeläinen 	void *in2_buf = NULL;
485fb279d8bSVesa Jääskeläinen 	void *out_buf = NULL;
486fb279d8bSVesa Jääskeläinen 	void *hash_buf = NULL;
487e02f17f3SAlexandre Marechal 	void *temp_buf = NULL;
488fb279d8bSVesa Jääskeläinen 	uint32_t in_size = 0;
489fb279d8bSVesa Jääskeläinen 	uint32_t in2_size = 0;
490c7f1b4f7SJens Wiklander 	size_t out_size = 0;
491c7f1b4f7SJens Wiklander 	size_t hash_size = 0;
492e02f17f3SAlexandre Marechal 	size_t temp_size = 0;
493fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
494fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
495fb279d8bSVesa Jääskeläinen 	bool output_data = false;
496fb279d8bSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
49745d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *rsa_aes_ctx = NULL;
498dc8c77fcSVesa Jääskeläinen 	struct rsa_oaep_processing_ctx *rsa_oaep_ctx = NULL;
499d9af50bcSVesa Jääskeläinen 	struct rsa_pss_processing_ctx *rsa_pss_ctx = NULL;
50003e07432SValerii Chubar 	struct eddsa_processing_ctx *eddsa_ctx = NULL;
501fb279d8bSVesa Jääskeläinen 	size_t sz = 0;
502fb279d8bSVesa Jääskeläinen 
503fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
504fb279d8bSVesa Jääskeläinen 		in_buf = params[1].memref.buffer;
505fb279d8bSVesa Jääskeläinen 		in_size = params[1].memref.size;
506fb279d8bSVesa Jääskeläinen 		if (in_size && !in_buf)
507fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
508fb279d8bSVesa Jääskeläinen 	}
509fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) {
510fb279d8bSVesa Jääskeläinen 		in2_buf = params[2].memref.buffer;
511fb279d8bSVesa Jääskeläinen 		in2_size = params[2].memref.size;
512fb279d8bSVesa Jääskeläinen 		if (in2_size && !in2_buf)
513fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
514fb279d8bSVesa Jääskeläinen 	}
515fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
516fb279d8bSVesa Jääskeläinen 		out_buf = params[2].memref.buffer;
517fb279d8bSVesa Jääskeläinen 		out_size = params[2].memref.size;
518fb279d8bSVesa Jääskeläinen 		if (out_size && !out_buf)
519fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
520fb279d8bSVesa Jääskeläinen 	}
521fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
522fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
523fb279d8bSVesa Jääskeläinen 
524fb279d8bSVesa Jääskeläinen 	switch (step) {
525fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_ONESHOT:
526fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE:
527fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_FINAL:
528fb279d8bSVesa Jääskeläinen 		break;
529fb279d8bSVesa Jääskeläinen 	default:
530fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
531fb279d8bSVesa Jääskeläinen 	}
532fb279d8bSVesa Jääskeläinen 
533d9af50bcSVesa Jääskeläinen 	/* TEE attribute(s) required by the operation */
534d9af50bcSVesa Jääskeläinen 	switch (proc->mecha_type) {
535d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
536d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
537d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
538d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
539d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
540d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
541d9af50bcSVesa Jääskeläinen 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
542d9af50bcSVesa Jääskeläinen 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
543d9af50bcSVesa Jääskeläinen 		if (!tee_attrs) {
544d9af50bcSVesa Jääskeläinen 			rc = PKCS11_CKR_DEVICE_MEMORY;
545d9af50bcSVesa Jääskeläinen 			goto out;
546d9af50bcSVesa Jääskeläinen 		}
547d9af50bcSVesa Jääskeläinen 
548d9af50bcSVesa Jääskeläinen 		rsa_pss_ctx = proc->extra_ctx;
549d9af50bcSVesa Jääskeläinen 
550d9af50bcSVesa Jääskeläinen 		TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
551d9af50bcSVesa Jääskeläinen 				       TEE_ATTR_RSA_PSS_SALT_LENGTH,
552d9af50bcSVesa Jääskeläinen 				       rsa_pss_ctx->salt_len, 0);
553d9af50bcSVesa Jääskeläinen 		tee_attrs_count++;
554d9af50bcSVesa Jääskeläinen 		break;
55503e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
55603e07432SValerii Chubar 		eddsa_ctx = proc->extra_ctx;
55703e07432SValerii Chubar 
55803e07432SValerii Chubar 		tee_attrs = TEE_Malloc(2 * sizeof(TEE_Attribute),
55903e07432SValerii Chubar 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
56003e07432SValerii Chubar 		if (!tee_attrs) {
56103e07432SValerii Chubar 			rc = PKCS11_CKR_DEVICE_MEMORY;
56203e07432SValerii Chubar 			goto out;
56303e07432SValerii Chubar 		}
56403e07432SValerii Chubar 
56503e07432SValerii Chubar 		if (eddsa_ctx->flag) {
56603e07432SValerii Chubar 			TEE_InitValueAttribute(&tee_attrs[tee_attrs_count],
56703e07432SValerii Chubar 					       TEE_ATTR_EDDSA_PREHASH, 0, 0);
56803e07432SValerii Chubar 			tee_attrs_count++;
56903e07432SValerii Chubar 		}
57003e07432SValerii Chubar 
57103e07432SValerii Chubar 		if (eddsa_ctx->ctx_len > 0) {
57203e07432SValerii Chubar 			TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
57303e07432SValerii Chubar 					     TEE_ATTR_EDDSA_CTX, eddsa_ctx->ctx,
57403e07432SValerii Chubar 					     eddsa_ctx->ctx_len);
57503e07432SValerii Chubar 			tee_attrs_count++;
57603e07432SValerii Chubar 		}
57703e07432SValerii Chubar 		break;
578dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
579dc8c77fcSVesa Jääskeläinen 		rsa_oaep_ctx = proc->extra_ctx;
580dc8c77fcSVesa Jääskeläinen 
581dc8c77fcSVesa Jääskeläinen 		if (!rsa_oaep_ctx->source_data_len)
582dc8c77fcSVesa Jääskeläinen 			break;
583dc8c77fcSVesa Jääskeläinen 
584dc8c77fcSVesa Jääskeläinen 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
585dc8c77fcSVesa Jääskeläinen 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
586dc8c77fcSVesa Jääskeläinen 		if (!tee_attrs) {
587dc8c77fcSVesa Jääskeläinen 			rc = PKCS11_CKR_DEVICE_MEMORY;
588dc8c77fcSVesa Jääskeläinen 			goto out;
589dc8c77fcSVesa Jääskeläinen 		}
590dc8c77fcSVesa Jääskeläinen 
591dc8c77fcSVesa Jääskeläinen 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
592dc8c77fcSVesa Jääskeläinen 				     TEE_ATTR_RSA_OAEP_LABEL,
593dc8c77fcSVesa Jääskeläinen 				     rsa_oaep_ctx->source_data,
594dc8c77fcSVesa Jääskeläinen 				     rsa_oaep_ctx->source_data_len);
595dc8c77fcSVesa Jääskeläinen 		tee_attrs_count++;
596dc8c77fcSVesa Jääskeläinen 		break;
59745d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
59845d40bdaSValerii Chubar 		rsa_aes_ctx = proc->extra_ctx;
59945d40bdaSValerii Chubar 
60045d40bdaSValerii Chubar 		if (!rsa_aes_ctx->source_data_len)
60145d40bdaSValerii Chubar 			break;
60245d40bdaSValerii Chubar 
60345d40bdaSValerii Chubar 		tee_attrs = TEE_Malloc(sizeof(TEE_Attribute),
60445d40bdaSValerii Chubar 				       TEE_USER_MEM_HINT_NO_FILL_ZERO);
60545d40bdaSValerii Chubar 		if (!tee_attrs) {
60645d40bdaSValerii Chubar 			rc = PKCS11_CKR_DEVICE_MEMORY;
60745d40bdaSValerii Chubar 			goto out;
60845d40bdaSValerii Chubar 		}
60945d40bdaSValerii Chubar 
61045d40bdaSValerii Chubar 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
61145d40bdaSValerii Chubar 				     TEE_ATTR_RSA_OAEP_LABEL,
61245d40bdaSValerii Chubar 				     rsa_aes_ctx->source_data,
61345d40bdaSValerii Chubar 				     rsa_aes_ctx->source_data_len);
61445d40bdaSValerii Chubar 		tee_attrs_count++;
61545d40bdaSValerii Chubar 		break;
616d9af50bcSVesa Jääskeläinen 	default:
617d9af50bcSVesa Jääskeläinen 		break;
618d9af50bcSVesa Jääskeläinen 	}
619d9af50bcSVesa Jääskeläinen 
620fb279d8bSVesa Jääskeläinen 	/*
621fb279d8bSVesa Jääskeläinen 	 * Handle multi stage update step for mechas needing hash
622fb279d8bSVesa Jääskeläinen 	 * calculation
623fb279d8bSVesa Jääskeläinen 	 */
624fb279d8bSVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE) {
625fb279d8bSVesa Jääskeläinen 		switch (proc->mecha_type) {
626fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA1:
627fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA224:
628fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA256:
629fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA384:
630fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA512:
6310442c956SVesa Jääskeläinen 		case PKCS11_CKM_MD5_RSA_PKCS:
6320442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA1_RSA_PKCS:
6330442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA224_RSA_PKCS:
6340442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA256_RSA_PKCS:
6350442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA384_RSA_PKCS:
6360442c956SVesa Jääskeläinen 		case PKCS11_CKM_SHA512_RSA_PKCS:
637d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
638d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
639d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
640d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
641d9af50bcSVesa Jääskeläinen 		case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
642571857c0SEtienne Carriere 			assert(proc->tee_op_handle2 != TEE_HANDLE_NULL);
643fb279d8bSVesa Jääskeläinen 
644571857c0SEtienne Carriere 			TEE_DigestUpdate(proc->tee_op_handle2, in_buf, in_size);
6459df68186SEtienne Carriere 			rc = PKCS11_CKR_OK;
646fb279d8bSVesa Jääskeläinen 			break;
647fb279d8bSVesa Jääskeläinen 		default:
648fb279d8bSVesa Jääskeläinen 			/*
649fb279d8bSVesa Jääskeläinen 			 * Other mechanism do not expect multi stage
650fb279d8bSVesa Jääskeläinen 			 * operation
651fb279d8bSVesa Jääskeläinen 			 */
652fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
653fb279d8bSVesa Jääskeläinen 			break;
654fb279d8bSVesa Jääskeläinen 		}
655fb279d8bSVesa Jääskeläinen 
656fb279d8bSVesa Jääskeläinen 		goto out;
657fb279d8bSVesa Jääskeläinen 	}
658fb279d8bSVesa Jääskeläinen 
659fb279d8bSVesa Jääskeläinen 	/*
660fb279d8bSVesa Jääskeläinen 	 * Handle multi stage one shot and final steps for mechas needing hash
661fb279d8bSVesa Jääskeläinen 	 * calculation
662fb279d8bSVesa Jääskeläinen 	 */
663fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
664fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
665fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
666fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
667fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
668fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
6690442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
6700442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
6710442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
6720442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
6730442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
6740442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
675d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
676d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
677d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
678d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
679d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
680571857c0SEtienne Carriere 		assert(proc->tee_op_handle2 != TEE_HANDLE_NULL);
681fb279d8bSVesa Jääskeläinen 
682fb279d8bSVesa Jääskeläinen 		hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo);
683fb279d8bSVesa Jääskeläinen 		hash_buf = TEE_Malloc(hash_size, 0);
684fb279d8bSVesa Jääskeläinen 		if (!hash_buf)
685fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_DEVICE_MEMORY;
686fb279d8bSVesa Jääskeläinen 
687571857c0SEtienne Carriere 		res = TEE_DigestDoFinal(proc->tee_op_handle2, in_buf, in_size,
688571857c0SEtienne Carriere 					hash_buf, &hash_size);
689fb279d8bSVesa Jääskeläinen 
690fb279d8bSVesa Jääskeläinen 		rc = tee2pkcs_error(res);
691fb279d8bSVesa Jääskeläinen 		if (rc != PKCS11_CKR_OK)
692fb279d8bSVesa Jääskeläinen 			goto out;
693fb279d8bSVesa Jääskeläinen 
694fb279d8bSVesa Jääskeläinen 		break;
695fb279d8bSVesa Jääskeläinen 	default:
696fb279d8bSVesa Jääskeläinen 		break;
697fb279d8bSVesa Jääskeläinen 	}
698fb279d8bSVesa Jääskeläinen 
699fb279d8bSVesa Jääskeläinen 	/*
700fb279d8bSVesa Jääskeläinen 	 * Finalize either provided hash or calculated hash with signing
701fb279d8bSVesa Jääskeläinen 	 * operation
702fb279d8bSVesa Jääskeläinen 	 */
703fb279d8bSVesa Jääskeläinen 
704fb279d8bSVesa Jääskeläinen 	/* First determine amount of bytes for signing operation */
705fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
706fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
707fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
708fb279d8bSVesa Jääskeläinen 		if (!in_size || !sz) {
709fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
710fb279d8bSVesa Jääskeläinen 			goto out;
711fb279d8bSVesa Jääskeläinen 		}
712fb279d8bSVesa Jääskeläinen 
713fb279d8bSVesa Jääskeläinen 		/*
714fb279d8bSVesa Jääskeläinen 		 * Note 3) Input the entire raw digest. Internally, this will
715fb279d8bSVesa Jääskeläinen 		 * be truncated to the appropriate number of bits.
716fb279d8bSVesa Jääskeläinen 		 */
717fb279d8bSVesa Jääskeläinen 		if (in_size > sz)
718fb279d8bSVesa Jääskeläinen 			in_size = sz;
719fb279d8bSVesa Jääskeläinen 
720fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) {
721fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
722fb279d8bSVesa Jääskeläinen 			goto out;
723fb279d8bSVesa Jääskeläinen 		}
724fb279d8bSVesa Jääskeläinen 		break;
725fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
726fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
727fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
728fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
729fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
730fb279d8bSVesa Jääskeläinen 		/* Get key size in bytes */
731fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
732fb279d8bSVesa Jääskeläinen 		if (!sz) {
733fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
734fb279d8bSVesa Jääskeläinen 			goto out;
735fb279d8bSVesa Jääskeläinen 		}
736fb279d8bSVesa Jääskeläinen 
737fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY &&
738fb279d8bSVesa Jääskeläinen 		    in2_size != 2 * sz) {
739fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
740fb279d8bSVesa Jääskeläinen 			goto out;
741fb279d8bSVesa Jääskeläinen 		}
742fb279d8bSVesa Jääskeläinen 		break;
7430442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
744e02f17f3SAlexandre Marechal 	case PKCS11_CKM_RSA_X_509:
7450442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
7460442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
7470442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
7480442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
7490442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
7500442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
751d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
752d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
753d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
754d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
755d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
756d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
7570442c956SVesa Jääskeläinen 		/* Get key size in bytes */
7580442c956SVesa Jääskeläinen 		sz = rsa_get_input_max_byte_size(proc->tee_op_handle);
7590442c956SVesa Jääskeläinen 		if (!sz) {
7600442c956SVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
7610442c956SVesa Jääskeläinen 			goto out;
7620442c956SVesa Jääskeläinen 		}
7630442c956SVesa Jääskeläinen 
7640442c956SVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != sz) {
7650442c956SVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
7660442c956SVesa Jääskeläinen 			goto out;
7670442c956SVesa Jääskeläinen 		}
7680442c956SVesa Jääskeläinen 		break;
769fb279d8bSVesa Jääskeläinen 	default:
770fb279d8bSVesa Jääskeläinen 		break;
771fb279d8bSVesa Jääskeläinen 	}
772fb279d8bSVesa Jääskeläinen 
773fb279d8bSVesa Jääskeläinen 	/* Next perform actual signing operation */
774fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
775fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
77603e07432SValerii Chubar 	case PKCS11_CKM_EDDSA:
7770442c956SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS:
778dc8c77fcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_OAEP:
779d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_PSS:
780fb279d8bSVesa Jääskeläinen 		/* For operations using provided input data */
781fb279d8bSVesa Jääskeläinen 		switch (function) {
782fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_ENCRYPT:
783fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
784fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
785fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
786fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
787fb279d8bSVesa Jääskeläinen 			output_data = true;
788fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
7896a6299fbSVesa Jääskeläinen 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
7906a6299fbSVesa Jääskeläinen 				rc = PKCS11_CKR_DATA_LEN_RANGE;
791fb279d8bSVesa Jääskeläinen 			break;
792fb279d8bSVesa Jääskeläinen 
793fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_DECRYPT:
794fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
795fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
796fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
797fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
798fb279d8bSVesa Jääskeläinen 			output_data = true;
799fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
800f27310a5SVesa Jääskeläinen 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
801f27310a5SVesa Jääskeläinen 				rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
802fb279d8bSVesa Jääskeläinen 			break;
803fb279d8bSVesa Jääskeläinen 
804fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
805fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
806fb279d8bSVesa Jääskeläinen 						       tee_attrs,
807fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
808fb279d8bSVesa Jääskeläinen 						       in_buf, in_size,
809fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
810fb279d8bSVesa Jääskeläinen 			output_data = true;
811fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
812fb279d8bSVesa Jääskeläinen 			break;
813fb279d8bSVesa Jääskeläinen 
814fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
815fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
816fb279d8bSVesa Jääskeläinen 							 tee_attrs,
817fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
818fb279d8bSVesa Jääskeläinen 							 in_buf, in_size,
819fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
820fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
821fb279d8bSVesa Jääskeläinen 			break;
822fb279d8bSVesa Jääskeläinen 
823fb279d8bSVesa Jääskeläinen 		default:
824fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
825fb279d8bSVesa Jääskeläinen 			break;
826fb279d8bSVesa Jääskeläinen 		}
827fb279d8bSVesa Jääskeläinen 		break;
828e02f17f3SAlexandre Marechal 
829e02f17f3SAlexandre Marechal 	case PKCS11_CKM_RSA_X_509:
830e02f17f3SAlexandre Marechal 		switch (function) {
831*b7abff72SEtienne Carriere 		case PKCS11_FUNCTION_ENCRYPT:
832*b7abff72SEtienne Carriere 			/*
833*b7abff72SEtienne Carriere 			 * Input message size shall be at most the key size
834*b7abff72SEtienne Carriere 			 * As encrypting with raw RSA can be unsafe, it
835*b7abff72SEtienne Carriere 			 * remains the responsibility of the client to
836*b7abff72SEtienne Carriere 			 * prolerly pad the message for safe usage.
837*b7abff72SEtienne Carriere 			 */
838*b7abff72SEtienne Carriere 			if (in_size > sz) {
839*b7abff72SEtienne Carriere 				rc = PKCS11_CKR_DATA_LEN_RANGE;
840*b7abff72SEtienne Carriere 				break;
841*b7abff72SEtienne Carriere 			}
842*b7abff72SEtienne Carriere 			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
843*b7abff72SEtienne Carriere 						    tee_attrs, tee_attrs_count,
844*b7abff72SEtienne Carriere 						    in_buf, in_size,
845*b7abff72SEtienne Carriere 						    out_buf, &out_size);
846*b7abff72SEtienne Carriere 			output_data = true;
847*b7abff72SEtienne Carriere 			rc = tee2pkcs_error(res);
848*b7abff72SEtienne Carriere 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
849*b7abff72SEtienne Carriere 				rc = PKCS11_CKR_DATA_LEN_RANGE;
850*b7abff72SEtienne Carriere 			break;
851*b7abff72SEtienne Carriere 		case PKCS11_FUNCTION_DECRYPT:
852*b7abff72SEtienne Carriere 			/*
853*b7abff72SEtienne Carriere 			 * Input message size shall be at most the key size
854*b7abff72SEtienne Carriere 			 * As decrypting with raw RSA can be unsafe, it
855*b7abff72SEtienne Carriere 			 * remains the responsibility of the encryption
856*b7abff72SEtienne Carriere 			 * instance to have prolerly padded its message.
857*b7abff72SEtienne Carriere 			 */
858*b7abff72SEtienne Carriere 			if (in_size > sz) {
859*b7abff72SEtienne Carriere 				rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
860*b7abff72SEtienne Carriere 				break;
861*b7abff72SEtienne Carriere 			}
862*b7abff72SEtienne Carriere 
863*b7abff72SEtienne Carriere 			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
864*b7abff72SEtienne Carriere 						    tee_attrs, tee_attrs_count,
865*b7abff72SEtienne Carriere 						    in_buf, in_size,
866*b7abff72SEtienne Carriere 						    out_buf, &out_size);
867*b7abff72SEtienne Carriere 			output_data = true;
868*b7abff72SEtienne Carriere 			rc = tee2pkcs_error(res);
869*b7abff72SEtienne Carriere 			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
870*b7abff72SEtienne Carriere 				rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
871*b7abff72SEtienne Carriere 			break;
872e02f17f3SAlexandre Marechal 		case PKCS11_FUNCTION_SIGN:
873e02f17f3SAlexandre Marechal 			/*
874e02f17f3SAlexandre Marechal 			 * GP TEE API only allows Decrypt, not Verify operation,
875e02f17f3SAlexandre Marechal 			 * on TEE_ALG_RSA_NOPAD. Be a bit strict on the size and
876e02f17f3SAlexandre Marechal 			 * content of the message and ensure the generate
877e02f17f3SAlexandre Marechal 			 * signature as the size of the modulus (@sz here).
878e02f17f3SAlexandre Marechal 			 *
879e02f17f3SAlexandre Marechal 			 * It remains the responsibility of the client to have
880e02f17f3SAlexandre Marechal 			 * a safe padding scheme for the provided message data.
881e02f17f3SAlexandre Marechal 			 */
882e02f17f3SAlexandre Marechal 			if (in_size != sz) {
883e02f17f3SAlexandre Marechal 				EMSG("Invalid data size %"PRIu32" != %zu",
884e02f17f3SAlexandre Marechal 				     in_size, sz);
885e02f17f3SAlexandre Marechal 				rc = PKCS11_CKR_DATA_LEN_RANGE;
886e02f17f3SAlexandre Marechal 				break;
887e02f17f3SAlexandre Marechal 			}
888e02f17f3SAlexandre Marechal 
889e02f17f3SAlexandre Marechal 			if (out_size < sz) {
890e02f17f3SAlexandre Marechal 				rc = PKCS11_CKR_BUFFER_TOO_SMALL;
891e02f17f3SAlexandre Marechal 				out_size = sz;
892e02f17f3SAlexandre Marechal 				output_data = true;
893e02f17f3SAlexandre Marechal 				break;
894e02f17f3SAlexandre Marechal 			}
895e02f17f3SAlexandre Marechal 
896e02f17f3SAlexandre Marechal 			temp_size = sz;
897e02f17f3SAlexandre Marechal 			temp_buf = proc->extra_ctx;
898e02f17f3SAlexandre Marechal 			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
899e02f17f3SAlexandre Marechal 						    tee_attrs, tee_attrs_count,
900e02f17f3SAlexandre Marechal 						    in_buf, in_size,
901e02f17f3SAlexandre Marechal 						    temp_buf, &temp_size);
902e02f17f3SAlexandre Marechal 			if (!res && temp_size != sz) {
903e02f17f3SAlexandre Marechal 				EMSG("CMK_RSA_X509: signature size %zu != %zu",
904e02f17f3SAlexandre Marechal 				     temp_size, sz);
905e02f17f3SAlexandre Marechal 				rc = PKCS11_CKR_DATA_INVALID;
906e02f17f3SAlexandre Marechal 				break;
907e02f17f3SAlexandre Marechal 			}
908e02f17f3SAlexandre Marechal 			if (!res) {
909e02f17f3SAlexandre Marechal 				TEE_MemMove(out_buf, temp_buf, sz);
910e02f17f3SAlexandre Marechal 				TEE_MemFill(temp_buf, 0xa5, sz);
911e02f17f3SAlexandre Marechal 			}
912e02f17f3SAlexandre Marechal 			output_data = true;
913e02f17f3SAlexandre Marechal 			rc = tee2pkcs_error(res);
914e02f17f3SAlexandre Marechal 			out_size = sz;
915e02f17f3SAlexandre Marechal 			break;
916e02f17f3SAlexandre Marechal 		case PKCS11_FUNCTION_VERIFY:
917e02f17f3SAlexandre Marechal 			/*
918e02f17f3SAlexandre Marechal 			 * GP TEE API only allows Encrypt, not Verify operation,
919e02f17f3SAlexandre Marechal 			 * on TEE_ALG_RSA_NOPAD. Encrypt signature in
920e02f17f3SAlexandre Marechal 			 * temporary buffer preallocated to the size of the key.
921e02f17f3SAlexandre Marechal 			 */
922e02f17f3SAlexandre Marechal 			temp_size = sz;
923e02f17f3SAlexandre Marechal 			temp_buf = proc->extra_ctx;
924e02f17f3SAlexandre Marechal 			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
925e02f17f3SAlexandre Marechal 						    tee_attrs, tee_attrs_count,
926e02f17f3SAlexandre Marechal 						    in2_buf, in2_size,
927e02f17f3SAlexandre Marechal 						    temp_buf, &temp_size);
928e02f17f3SAlexandre Marechal 			rc = tee2pkcs_error(res);
929e02f17f3SAlexandre Marechal 			if (rc == PKCS11_CKR_OK) {
930e02f17f3SAlexandre Marechal 				/*
931e02f17f3SAlexandre Marechal 				 * Skip nul bytes heading message before
932e02f17f3SAlexandre Marechal 				 * comparing encrypted signature.
933e02f17f3SAlexandre Marechal 				 */
934e02f17f3SAlexandre Marechal 				char *ptr = in_buf;
935e02f17f3SAlexandre Marechal 				size_t n = 0;
936e02f17f3SAlexandre Marechal 
937e02f17f3SAlexandre Marechal 				for (n = 0; n < in_size; n++)
938e02f17f3SAlexandre Marechal 					if (ptr[n])
939e02f17f3SAlexandre Marechal 						break;
940e02f17f3SAlexandre Marechal 				in_size -= n;
941e02f17f3SAlexandre Marechal 				ptr += n;
942e02f17f3SAlexandre Marechal 				if (n > 1)
943e02f17f3SAlexandre Marechal 					IMSG("Unsafe signature: skip %zu bytes",
944e02f17f3SAlexandre Marechal 					     n);
945e02f17f3SAlexandre Marechal 
946e02f17f3SAlexandre Marechal 				if (temp_size != in_size ||
947e02f17f3SAlexandre Marechal 				    consttime_memcmp(temp_buf, ptr, in_size))
948e02f17f3SAlexandre Marechal 					rc = PKCS11_CKR_SIGNATURE_INVALID;
949e02f17f3SAlexandre Marechal 			}
950e02f17f3SAlexandre Marechal 			break;
951e02f17f3SAlexandre Marechal 		default:
952e02f17f3SAlexandre Marechal 			TEE_Panic(function);
953e02f17f3SAlexandre Marechal 			break;
954e02f17f3SAlexandre Marechal 		}
955e02f17f3SAlexandre Marechal 		break;
956e02f17f3SAlexandre Marechal 
957fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
958fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
959fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
960fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
961fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
9620442c956SVesa Jääskeläinen 	case PKCS11_CKM_MD5_RSA_PKCS:
9630442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS:
9640442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS:
9650442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS:
9660442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS:
9670442c956SVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS:
968d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
969d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
970d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
971d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
972d9af50bcSVesa Jääskeläinen 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
973fb279d8bSVesa Jääskeläinen 		/* For operations having hash operation use calculated hash */
974fb279d8bSVesa Jääskeläinen 		switch (function) {
975fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
976fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
977fb279d8bSVesa Jääskeläinen 						       tee_attrs,
978fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
979fb279d8bSVesa Jääskeläinen 						       hash_buf, hash_size,
980fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
981fb279d8bSVesa Jääskeläinen 			output_data = true;
982fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
983fb279d8bSVesa Jääskeläinen 			break;
984fb279d8bSVesa Jääskeläinen 
985fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
986fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
987fb279d8bSVesa Jääskeläinen 							 tee_attrs,
988fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
989fb279d8bSVesa Jääskeläinen 							 hash_buf, hash_size,
990fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
991fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
992fb279d8bSVesa Jääskeläinen 			break;
993fb279d8bSVesa Jääskeläinen 
994fb279d8bSVesa Jääskeläinen 		default:
995fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
996fb279d8bSVesa Jääskeläinen 			break;
997fb279d8bSVesa Jääskeläinen 		}
998fb279d8bSVesa Jääskeläinen 		break;
999fb279d8bSVesa Jääskeläinen 	default:
1000fb279d8bSVesa Jääskeläinen 		TEE_Panic(proc->mecha_type);
1001fb279d8bSVesa Jääskeläinen 		break;
1002fb279d8bSVesa Jääskeläinen 	}
1003fb279d8bSVesa Jääskeläinen 
1004fb279d8bSVesa Jääskeläinen out:
1005fb279d8bSVesa Jääskeläinen 	if (output_data &&
1006fb279d8bSVesa Jääskeläinen 	    (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) {
1007fb279d8bSVesa Jääskeläinen 		switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
1008fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
1009fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_INOUT:
1010fb279d8bSVesa Jääskeläinen 			params[2].memref.size = out_size;
1011fb279d8bSVesa Jääskeläinen 			break;
1012fb279d8bSVesa Jääskeläinen 		default:
1013fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
1014fb279d8bSVesa Jääskeläinen 			break;
1015fb279d8bSVesa Jääskeläinen 		}
1016fb279d8bSVesa Jääskeläinen 	}
1017fb279d8bSVesa Jääskeläinen 
1018fb279d8bSVesa Jääskeläinen 	TEE_Free(hash_buf);
1019fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
1020fb279d8bSVesa Jääskeläinen 
1021fb279d8bSVesa Jääskeläinen 	return rc;
1022fb279d8bSVesa Jääskeläinen }
1023cc062b46SJorge Ramirez-Ortiz 
do_asymm_derivation(struct pkcs11_session * session,struct pkcs11_attribute_head * proc_params,struct obj_attrs ** head)1024cc062b46SJorge Ramirez-Ortiz enum pkcs11_rc do_asymm_derivation(struct pkcs11_session *session,
1025cc062b46SJorge Ramirez-Ortiz 				   struct pkcs11_attribute_head *proc_params,
1026cc062b46SJorge Ramirez-Ortiz 				   struct obj_attrs **head)
1027cc062b46SJorge Ramirez-Ortiz {
1028cc062b46SJorge Ramirez-Ortiz 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1029cc062b46SJorge Ramirez-Ortiz 	TEE_ObjectHandle out_handle = TEE_HANDLE_NULL;
1030cc062b46SJorge Ramirez-Ortiz 	TEE_Result res = TEE_ERROR_GENERIC;
1031cc062b46SJorge Ramirez-Ortiz 	TEE_Attribute tee_attrs[2] = { };
1032cc062b46SJorge Ramirez-Ortiz 	size_t tee_attrs_count = 0;
1033cc062b46SJorge Ramirez-Ortiz 	uint32_t key_byte_size = 0;
1034cc062b46SJorge Ramirez-Ortiz 	uint32_t key_bit_size = 0;
1035cc062b46SJorge Ramirez-Ortiz 	void *a_ptr = NULL;
1036cc062b46SJorge Ramirez-Ortiz 	size_t a_size = 0;
1037cc062b46SJorge Ramirez-Ortiz 
1038cc062b46SJorge Ramirez-Ortiz 	/* Remove default attribute set at template sanitization */
1039cc062b46SJorge Ramirez-Ortiz 	if (remove_empty_attribute(head, PKCS11_CKA_VALUE))
1040cc062b46SJorge Ramirez-Ortiz 		return PKCS11_CKR_FUNCTION_FAILED;
1041cc062b46SJorge Ramirez-Ortiz 
1042cc062b46SJorge Ramirez-Ortiz 	rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_bit_size);
1043cc062b46SJorge Ramirez-Ortiz 	if (rc)
1044cc062b46SJorge Ramirez-Ortiz 		return rc;
1045cc062b46SJorge Ramirez-Ortiz 
1046cc062b46SJorge Ramirez-Ortiz 	key_bit_size *= 8;
1047cc062b46SJorge Ramirez-Ortiz 	key_byte_size = (key_bit_size + 7) / 8;
1048cc062b46SJorge Ramirez-Ortiz 
1049cc062b46SJorge Ramirez-Ortiz 	res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET,
1050cc062b46SJorge Ramirez-Ortiz 					  key_byte_size * 8, &out_handle);
1051cc062b46SJorge Ramirez-Ortiz 	if (res) {
1052cc062b46SJorge Ramirez-Ortiz 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
1053cc062b46SJorge Ramirez-Ortiz 		return tee2pkcs_error(res);
1054cc062b46SJorge Ramirez-Ortiz 	}
1055cc062b46SJorge Ramirez-Ortiz 
1056cc062b46SJorge Ramirez-Ortiz 	switch (proc_params->id) {
1057cc062b46SJorge Ramirez-Ortiz 	case PKCS11_CKM_ECDH1_DERIVE:
1058cc062b46SJorge Ramirez-Ortiz 		rc = pkcs2tee_param_ecdh(proc_params, &a_ptr, &a_size);
1059cc062b46SJorge Ramirez-Ortiz 		if (rc)
1060cc062b46SJorge Ramirez-Ortiz 			goto out;
1061cc062b46SJorge Ramirez-Ortiz 
1062cc062b46SJorge Ramirez-Ortiz 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
1063cc062b46SJorge Ramirez-Ortiz 				     TEE_ATTR_ECC_PUBLIC_VALUE_X,
1064cc062b46SJorge Ramirez-Ortiz 				     a_ptr, a_size / 2);
1065cc062b46SJorge Ramirez-Ortiz 		tee_attrs_count++;
1066cc062b46SJorge Ramirez-Ortiz 		TEE_InitRefAttribute(&tee_attrs[tee_attrs_count],
1067cc062b46SJorge Ramirez-Ortiz 				     TEE_ATTR_ECC_PUBLIC_VALUE_Y,
1068cc062b46SJorge Ramirez-Ortiz 				     (char *)a_ptr + a_size / 2,
1069cc062b46SJorge Ramirez-Ortiz 				     a_size / 2);
1070cc062b46SJorge Ramirez-Ortiz 		tee_attrs_count++;
1071cc062b46SJorge Ramirez-Ortiz 		break;
1072cc062b46SJorge Ramirez-Ortiz 	default:
1073cc062b46SJorge Ramirez-Ortiz 		TEE_Panic(proc_params->id);
1074cc062b46SJorge Ramirez-Ortiz 		break;
1075cc062b46SJorge Ramirez-Ortiz 	}
1076cc062b46SJorge Ramirez-Ortiz 
1077cc062b46SJorge Ramirez-Ortiz 	TEE_DeriveKey(session->processing->tee_op_handle, &tee_attrs[0],
1078cc062b46SJorge Ramirez-Ortiz 		      tee_attrs_count, out_handle);
1079cc062b46SJorge Ramirez-Ortiz 
1080cc062b46SJorge Ramirez-Ortiz 	rc = alloc_get_tee_attribute_data(out_handle, TEE_ATTR_SECRET_VALUE,
1081cc062b46SJorge Ramirez-Ortiz 					  &a_ptr, &a_size);
1082cc062b46SJorge Ramirez-Ortiz 	if (rc)
1083cc062b46SJorge Ramirez-Ortiz 		goto out;
1084cc062b46SJorge Ramirez-Ortiz 
1085cc062b46SJorge Ramirez-Ortiz 	if (a_size * 8 < key_bit_size)
1086cc062b46SJorge Ramirez-Ortiz 		rc = PKCS11_CKR_KEY_SIZE_RANGE;
1087cc062b46SJorge Ramirez-Ortiz 	else
1088cc062b46SJorge Ramirez-Ortiz 		rc = add_attribute(head, PKCS11_CKA_VALUE, a_ptr,
1089cc062b46SJorge Ramirez-Ortiz 				   key_byte_size);
1090cc062b46SJorge Ramirez-Ortiz 	TEE_Free(a_ptr);
1091cc062b46SJorge Ramirez-Ortiz out:
1092cc062b46SJorge Ramirez-Ortiz 	release_active_processing(session);
1093cc062b46SJorge Ramirez-Ortiz 	TEE_FreeTransientObject(out_handle);
1094cc062b46SJorge Ramirez-Ortiz 
1095cc062b46SJorge Ramirez-Ortiz 	return rc;
1096cc062b46SJorge Ramirez-Ortiz }
109745d40bdaSValerii Chubar 
wrap_rsa_aes_key(struct active_processing * proc,void * data,uint32_t data_sz,void * out_buf,uint32_t * out_sz)109845d40bdaSValerii Chubar static enum pkcs11_rc wrap_rsa_aes_key(struct active_processing *proc,
109945d40bdaSValerii Chubar 				       void *data, uint32_t data_sz,
110045d40bdaSValerii Chubar 				       void *out_buf, uint32_t *out_sz)
110145d40bdaSValerii Chubar {
110245d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_OK;
110345d40bdaSValerii Chubar 	TEE_Result res = TEE_ERROR_GENERIC;
110445d40bdaSValerii Chubar 	int mbedtls_rc = 0;
110545d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx;
110645d40bdaSValerii Chubar 	mbedtls_nist_kw_context kw_ctx = { };
110745d40bdaSValerii Chubar 	uint8_t aes_key_value[32] = { };
110845d40bdaSValerii Chubar 	uint32_t aes_key_size = ctx->aes_key_bits / 8;
1109c7f1b4f7SJens Wiklander 	size_t aes_wrapped_size = *out_sz;
111045d40bdaSValerii Chubar 	uint32_t expected_size = 0;
111145d40bdaSValerii Chubar 	size_t target_key_size = 0;
111245d40bdaSValerii Chubar 	const size_t kw_semiblock_len = 8;
111345d40bdaSValerii Chubar 
111445d40bdaSValerii Chubar 	if (ctx->aes_key_bits != 128 &&
111545d40bdaSValerii Chubar 	    ctx->aes_key_bits != 192 &&
111645d40bdaSValerii Chubar 	    ctx->aes_key_bits != 256)
111745d40bdaSValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
111845d40bdaSValerii Chubar 
111945d40bdaSValerii Chubar 	mbedtls_nist_kw_init(&kw_ctx);
112045d40bdaSValerii Chubar 	TEE_GenerateRandom(aes_key_value, aes_key_size);
112145d40bdaSValerii Chubar 	res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
112245d40bdaSValerii Chubar 				    NULL, 0,
112345d40bdaSValerii Chubar 				    aes_key_value, aes_key_size,
112445d40bdaSValerii Chubar 				    out_buf, &aes_wrapped_size);
112545d40bdaSValerii Chubar 	expected_size = aes_wrapped_size + data_sz + kw_semiblock_len;
112645d40bdaSValerii Chubar 	if (res) {
112745d40bdaSValerii Chubar 		if (res == TEE_ERROR_SHORT_BUFFER)
112845d40bdaSValerii Chubar 			*out_sz = expected_size;
112945d40bdaSValerii Chubar 
113045d40bdaSValerii Chubar 		rc = tee2pkcs_error(res);
113145d40bdaSValerii Chubar 		goto out;
113245d40bdaSValerii Chubar 	}
113345d40bdaSValerii Chubar 
113445d40bdaSValerii Chubar 	if (*out_sz < expected_size) {
113545d40bdaSValerii Chubar 		rc = PKCS11_CKR_BUFFER_TOO_SMALL;
113645d40bdaSValerii Chubar 		*out_sz = expected_size;
113745d40bdaSValerii Chubar 		goto out;
113845d40bdaSValerii Chubar 	}
113945d40bdaSValerii Chubar 
114045d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES,
114145d40bdaSValerii Chubar 					    aes_key_value, ctx->aes_key_bits,
114245d40bdaSValerii Chubar 					    true);
114345d40bdaSValerii Chubar 	if (mbedtls_rc) {
114445d40bdaSValerii Chubar 		if (mbedtls_rc == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA)
114545d40bdaSValerii Chubar 			rc = PKCS11_CKR_KEY_SIZE_RANGE;
114645d40bdaSValerii Chubar 		else
114745d40bdaSValerii Chubar 			rc = PKCS11_CKR_FUNCTION_FAILED;
114845d40bdaSValerii Chubar 
114945d40bdaSValerii Chubar 		goto out;
115045d40bdaSValerii Chubar 	}
115145d40bdaSValerii Chubar 
115245d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_wrap(&kw_ctx, MBEDTLS_KW_MODE_KWP,
115345d40bdaSValerii Chubar 					  data, data_sz,
115445d40bdaSValerii Chubar 					  (uint8_t *)out_buf + aes_wrapped_size,
115545d40bdaSValerii Chubar 					  &target_key_size,
115645d40bdaSValerii Chubar 					  *out_sz - aes_wrapped_size);
115745d40bdaSValerii Chubar 	if (mbedtls_rc) {
115845d40bdaSValerii Chubar 		rc = PKCS11_CKR_ARGUMENTS_BAD;
115945d40bdaSValerii Chubar 		goto out;
116045d40bdaSValerii Chubar 	}
116145d40bdaSValerii Chubar 
116245d40bdaSValerii Chubar 	assert(*out_sz >= target_key_size + aes_wrapped_size);
116345d40bdaSValerii Chubar 	*out_sz = target_key_size + aes_wrapped_size;
116445d40bdaSValerii Chubar 
116545d40bdaSValerii Chubar out:
116645d40bdaSValerii Chubar 	mbedtls_nist_kw_free(&kw_ctx);
116745d40bdaSValerii Chubar 	TEE_MemFill(aes_key_value, 0, aes_key_size);
116845d40bdaSValerii Chubar 	return rc;
116945d40bdaSValerii Chubar }
117045d40bdaSValerii Chubar 
unwrap_rsa_aes_key(struct active_processing * proc,void * data,uint32_t data_sz,void ** out_buf,uint32_t * out_sz)117145d40bdaSValerii Chubar static enum pkcs11_rc unwrap_rsa_aes_key(struct active_processing *proc,
117245d40bdaSValerii Chubar 					 void *data, uint32_t data_sz,
117345d40bdaSValerii Chubar 					 void **out_buf, uint32_t *out_sz)
117445d40bdaSValerii Chubar {
117545d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_OK;
117645d40bdaSValerii Chubar 	int mbedtls_rc = 0;
117745d40bdaSValerii Chubar 	TEE_Result res = TEE_ERROR_GENERIC;
117845d40bdaSValerii Chubar 	TEE_OperationInfo info = { };
117945d40bdaSValerii Chubar 	struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx;
118045d40bdaSValerii Chubar 	mbedtls_nist_kw_context kw_ctx = { };
118145d40bdaSValerii Chubar 	uint8_t aes_key_value[32] = { };
1182c7f1b4f7SJens Wiklander 	size_t aes_key_size = ctx->aes_key_bits / 8;
118345d40bdaSValerii Chubar 	uint32_t wrapped_key_size = 0;
118445d40bdaSValerii Chubar 	uint32_t rsa_key_size = 0;
118545d40bdaSValerii Chubar 	size_t target_key_size = 0;
118645d40bdaSValerii Chubar 
118745d40bdaSValerii Chubar 	if (ctx->aes_key_bits != 128 &&
118845d40bdaSValerii Chubar 	    ctx->aes_key_bits != 192 &&
118945d40bdaSValerii Chubar 	    ctx->aes_key_bits != 256)
119045d40bdaSValerii Chubar 		return PKCS11_CKR_ARGUMENTS_BAD;
119145d40bdaSValerii Chubar 
119245d40bdaSValerii Chubar 	TEE_GetOperationInfo(proc->tee_op_handle, &info);
119345d40bdaSValerii Chubar 	rsa_key_size = info.keySize / 8;
119445d40bdaSValerii Chubar 	wrapped_key_size = data_sz - rsa_key_size;
119545d40bdaSValerii Chubar 	target_key_size = wrapped_key_size - 8;
119645d40bdaSValerii Chubar 
119745d40bdaSValerii Chubar 	*out_buf = TEE_Malloc(target_key_size, TEE_MALLOC_FILL_ZERO);
119845d40bdaSValerii Chubar 	if (!*out_buf)
119945d40bdaSValerii Chubar 		return PKCS11_CKR_DEVICE_MEMORY;
120045d40bdaSValerii Chubar 
120145d40bdaSValerii Chubar 	mbedtls_nist_kw_init(&kw_ctx);
120245d40bdaSValerii Chubar 	res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
120345d40bdaSValerii Chubar 				    NULL, 0,
120445d40bdaSValerii Chubar 				    data, rsa_key_size,
120545d40bdaSValerii Chubar 				    aes_key_value, &aes_key_size);
120645d40bdaSValerii Chubar 	if (res) {
120745d40bdaSValerii Chubar 		rc = tee2pkcs_error(res);
120845d40bdaSValerii Chubar 		goto out;
120945d40bdaSValerii Chubar 	}
121045d40bdaSValerii Chubar 
121145d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES,
121245d40bdaSValerii Chubar 					    aes_key_value, ctx->aes_key_bits,
121345d40bdaSValerii Chubar 					    false);
121445d40bdaSValerii Chubar 	if (mbedtls_rc) {
121545d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
121645d40bdaSValerii Chubar 		goto out;
121745d40bdaSValerii Chubar 	}
121845d40bdaSValerii Chubar 
121945d40bdaSValerii Chubar 	mbedtls_rc = mbedtls_nist_kw_unwrap(&kw_ctx, MBEDTLS_KW_MODE_KWP,
122045d40bdaSValerii Chubar 					    (uint8_t *)data + rsa_key_size,
122145d40bdaSValerii Chubar 					    wrapped_key_size, *out_buf,
122245d40bdaSValerii Chubar 					    &target_key_size, target_key_size);
122345d40bdaSValerii Chubar 	if (mbedtls_rc) {
122445d40bdaSValerii Chubar 		rc = PKCS11_CKR_WRAPPED_KEY_INVALID;
122545d40bdaSValerii Chubar 		goto out;
122645d40bdaSValerii Chubar 	}
122745d40bdaSValerii Chubar 
122845d40bdaSValerii Chubar 	*out_sz = target_key_size;
122945d40bdaSValerii Chubar out:
123045d40bdaSValerii Chubar 	TEE_MemFill(aes_key_value, 0, aes_key_size);
123145d40bdaSValerii Chubar 	mbedtls_nist_kw_free(&kw_ctx);
123245d40bdaSValerii Chubar 	return rc;
123345d40bdaSValerii Chubar }
123445d40bdaSValerii Chubar 
wrap_data_by_asymm_enc(struct pkcs11_session * session,void * data,uint32_t data_sz,void * out_buf,uint32_t * out_sz)123545d40bdaSValerii Chubar enum pkcs11_rc wrap_data_by_asymm_enc(struct pkcs11_session *session,
123645d40bdaSValerii Chubar 				      void *data, uint32_t data_sz,
123745d40bdaSValerii Chubar 				      void *out_buf, uint32_t *out_sz)
123845d40bdaSValerii Chubar {
123945d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
124045d40bdaSValerii Chubar 	struct active_processing *proc = session->processing;
124145d40bdaSValerii Chubar 
124245d40bdaSValerii Chubar 	switch (proc->mecha_type) {
124345d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
124445d40bdaSValerii Chubar 		rc = wrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz);
124545d40bdaSValerii Chubar 		break;
124645d40bdaSValerii Chubar 	default:
124745d40bdaSValerii Chubar 		return PKCS11_CKR_MECHANISM_INVALID;
124845d40bdaSValerii Chubar 	}
124945d40bdaSValerii Chubar 
125045d40bdaSValerii Chubar 	return rc;
125145d40bdaSValerii Chubar }
125245d40bdaSValerii Chubar 
unwrap_key_by_asymm(struct pkcs11_session * session,void * data,uint32_t data_sz,void ** out_buf,uint32_t * out_sz)125345d40bdaSValerii Chubar enum pkcs11_rc unwrap_key_by_asymm(struct pkcs11_session *session,
125445d40bdaSValerii Chubar 				   void *data, uint32_t data_sz,
125545d40bdaSValerii Chubar 				   void **out_buf, uint32_t *out_sz)
125645d40bdaSValerii Chubar {
125745d40bdaSValerii Chubar 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
125845d40bdaSValerii Chubar 	struct active_processing *proc = session->processing;
125945d40bdaSValerii Chubar 
126045d40bdaSValerii Chubar 	switch (proc->mecha_type) {
126145d40bdaSValerii Chubar 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
126245d40bdaSValerii Chubar 		rc = unwrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz);
126345d40bdaSValerii Chubar 		break;
126445d40bdaSValerii Chubar 	default:
126545d40bdaSValerii Chubar 		return PKCS11_CKR_MECHANISM_INVALID;
126645d40bdaSValerii Chubar 	}
126745d40bdaSValerii Chubar 
126845d40bdaSValerii Chubar 	return rc;
126945d40bdaSValerii Chubar }
1270