xref: /optee_os/ta/pkcs11/src/processing.c (revision 63778faac4b7d8917d6170104c2c20a3a78dad9f)
1512cbf1dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2512cbf1dSJens Wiklander /*
3512cbf1dSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
4512cbf1dSJens Wiklander  */
5512cbf1dSJens Wiklander 
6512cbf1dSJens Wiklander #include <assert.h>
7512cbf1dSJens Wiklander #include <pkcs11_ta.h>
8512cbf1dSJens Wiklander #include <string.h>
9512cbf1dSJens Wiklander #include <tee_api_defines.h>
10512cbf1dSJens Wiklander #include <tee_internal_api.h>
11512cbf1dSJens Wiklander #include <tee_internal_api_extensions.h>
12512cbf1dSJens Wiklander #include <util.h>
13512cbf1dSJens Wiklander 
14512cbf1dSJens Wiklander #include "attributes.h"
15512cbf1dSJens Wiklander #include "object.h"
16512cbf1dSJens Wiklander #include "pkcs11_attributes.h"
17512cbf1dSJens Wiklander #include "pkcs11_helpers.h"
18512cbf1dSJens Wiklander #include "pkcs11_token.h"
19512cbf1dSJens Wiklander #include "processing.h"
20512cbf1dSJens Wiklander #include "serializer.h"
21512cbf1dSJens Wiklander 
22512cbf1dSJens Wiklander static enum pkcs11_rc get_ready_session(struct pkcs11_session *session)
23512cbf1dSJens Wiklander {
24512cbf1dSJens Wiklander 	if (session_is_active(session))
25512cbf1dSJens Wiklander 		return PKCS11_CKR_OPERATION_ACTIVE;
26512cbf1dSJens Wiklander 
27512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
28512cbf1dSJens Wiklander }
29512cbf1dSJens Wiklander 
30eb6141b6SVesa Jääskeläinen static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd)
31eb6141b6SVesa Jääskeläinen {
32eb6141b6SVesa Jääskeläinen 	switch (cmd) {
33eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_ENCRYPT_UPDATE:
34eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_ENCRYPT_ONESHOT:
35eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_ENCRYPT_FINAL:
36eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_ENCRYPT;
37eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_DECRYPT_UPDATE:
38eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_DECRYPT_ONESHOT:
39eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_DECRYPT_FINAL:
40eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_DECRYPT;
41eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_SIGN_ONESHOT:
42eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_SIGN_UPDATE:
43eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_SIGN_FINAL:
44eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_SIGN;
45eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_VERIFY_ONESHOT:
46eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_VERIFY_UPDATE:
47eb6141b6SVesa Jääskeläinen 	case PKCS11_CMD_VERIFY_FINAL:
48eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_VERIFY;
499e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_UPDATE:
509e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_KEY:
519e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_ONESHOT:
529e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_FINAL:
539e91a619SVesa Jääskeläinen 		return PKCS11_FUNCTION_DIGEST;
54eb6141b6SVesa Jääskeläinen 	default:
55eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_UNKNOWN;
56eb6141b6SVesa Jääskeläinen 	}
57eb6141b6SVesa Jääskeläinen }
58eb6141b6SVesa Jääskeläinen 
59512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function,
60512cbf1dSJens Wiklander 			       enum pkcs11_proc_state state)
61512cbf1dSJens Wiklander {
62512cbf1dSJens Wiklander 	switch (function) {
63512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
64512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_ENCRYPTING ||
65512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
66512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
67512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
68512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DECRYPTING ||
69512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
70512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
71512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DIGEST:
72512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DIGESTING ||
73512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
74512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
75512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING ||
76512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
77512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
78512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_VERIFYING ||
79512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
80512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN_RECOVER:
81512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
82512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY_RECOVER:
83512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
84512cbf1dSJens Wiklander 	default:
85512cbf1dSJens Wiklander 		TEE_Panic(function);
86512cbf1dSJens Wiklander 		return false;
87512cbf1dSJens Wiklander 	}
88512cbf1dSJens Wiklander }
89512cbf1dSJens Wiklander 
90512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
91512cbf1dSJens Wiklander 					 enum processing_func function)
92512cbf1dSJens Wiklander {
93512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
94512cbf1dSJens Wiklander 
95512cbf1dSJens Wiklander 	if (session->processing &&
96512cbf1dSJens Wiklander 	    func_matches_state(function, session->processing->state))
97512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
98512cbf1dSJens Wiklander 
99512cbf1dSJens Wiklander 	return rc;
100512cbf1dSJens Wiklander }
101512cbf1dSJens Wiklander 
102512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session)
103512cbf1dSJens Wiklander {
104512cbf1dSJens Wiklander 	if (!session->processing)
105512cbf1dSJens Wiklander 		return;
106512cbf1dSJens Wiklander 
107*63778faaSEtienne Carriere 	switch (session->processing->mecha_type) {
108*63778faaSEtienne Carriere 	case PKCS11_CKM_AES_GCM:
109*63778faaSEtienne Carriere 		tee_release_gcm_operation(session);
110*63778faaSEtienne Carriere 		break;
111*63778faaSEtienne Carriere 	default:
112*63778faaSEtienne Carriere 		break;
113*63778faaSEtienne Carriere 	}
114*63778faaSEtienne Carriere 
115fb279d8bSVesa Jääskeläinen 	if (session->processing->tee_hash_op_handle != TEE_HANDLE_NULL) {
116fb279d8bSVesa Jääskeläinen 		TEE_FreeOperation(session->processing->tee_hash_op_handle);
117fb279d8bSVesa Jääskeläinen 		session->processing->tee_hash_op_handle = TEE_HANDLE_NULL;
118fb279d8bSVesa Jääskeläinen 		session->processing->tee_hash_algo = 0;
119fb279d8bSVesa Jääskeläinen 	}
120fb279d8bSVesa Jääskeläinen 
121512cbf1dSJens Wiklander 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
122512cbf1dSJens Wiklander 		TEE_FreeOperation(session->processing->tee_op_handle);
123512cbf1dSJens Wiklander 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
124512cbf1dSJens Wiklander 	}
125512cbf1dSJens Wiklander 
126*63778faaSEtienne Carriere 	if (session->processing->tee_op_handle2 != TEE_HANDLE_NULL) {
127*63778faaSEtienne Carriere 		TEE_FreeOperation(session->processing->tee_op_handle2);
128*63778faaSEtienne Carriere 		session->processing->tee_op_handle2 = TEE_HANDLE_NULL;
129*63778faaSEtienne Carriere 	}
130*63778faaSEtienne Carriere 
1312158ea6cSRuchika Gupta 	TEE_Free(session->processing->extra_ctx);
1322158ea6cSRuchika Gupta 
133512cbf1dSJens Wiklander 	TEE_Free(session->processing);
134512cbf1dSJens Wiklander 	session->processing = NULL;
135512cbf1dSJens Wiklander }
136512cbf1dSJens Wiklander 
137512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
138512cbf1dSJens Wiklander {
139fb279d8bSVesa Jääskeläinen 	void *a_ptr = NULL;
140512cbf1dSJens Wiklander 	uint32_t a_size = 0;
141512cbf1dSJens Wiklander 	struct obj_attrs *attrs = obj->attributes;
142512cbf1dSJens Wiklander 
143512cbf1dSJens Wiklander 	switch (get_key_type(attrs)) {
144512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
145689f4e5bSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
146689f4e5bSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
147689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
148689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
149689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
150689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
151689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
152512cbf1dSJens Wiklander 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
153512cbf1dSJens Wiklander 			return 0;
154512cbf1dSJens Wiklander 
155512cbf1dSJens Wiklander 		return a_size * 8;
1560442c956SVesa Jääskeläinen 	case PKCS11_CKK_RSA:
1570442c956SVesa Jääskeläinen 		if (get_attribute_ptr(attrs, PKCS11_CKA_MODULUS, NULL, &a_size))
1580442c956SVesa Jääskeläinen 			return 0;
1590442c956SVesa Jääskeläinen 
1600442c956SVesa Jääskeläinen 		return a_size * 8;
161fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
162fb279d8bSVesa Jääskeläinen 		if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS,
163fb279d8bSVesa Jääskeläinen 				      &a_ptr, &a_size) || !a_ptr)
164fb279d8bSVesa Jääskeläinen 			return 0;
165fb279d8bSVesa Jääskeläinen 
166fb279d8bSVesa Jääskeläinen 		return ec_params2tee_keysize(a_ptr, a_size);
167ecd7f426SValerii Chubar 	case PKCS11_CKK_EC_EDWARDS:
168ecd7f426SValerii Chubar 		if (get_attribute_ptr(attrs, PKCS11_CKA_EC_POINT, NULL,
169ecd7f426SValerii Chubar 				      &a_size))
170ecd7f426SValerii Chubar 			return 0;
171ecd7f426SValerii Chubar 
172ecd7f426SValerii Chubar 		return a_size * 8;
173512cbf1dSJens Wiklander 	default:
174512cbf1dSJens Wiklander 		TEE_Panic(0);
175512cbf1dSJens Wiklander 		return 0;
176512cbf1dSJens Wiklander 	}
177512cbf1dSJens Wiklander }
178512cbf1dSJens Wiklander 
179fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
180fa247a2aSRuchika Gupta {
181fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
182fa247a2aSRuchika Gupta 	uint32_t data_size = 0;
183fa247a2aSRuchika Gupta 	uint32_t value_len = 0;
184fa247a2aSRuchika Gupta 	void *value = NULL;
185bcac2127SMarouene Boubakri 	void *data = NULL;
186fa247a2aSRuchika Gupta 
187fa247a2aSRuchika Gupta 	if (!*head)
188fa247a2aSRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
189fa247a2aSRuchika Gupta 
190fa247a2aSRuchika Gupta 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
191fa247a2aSRuchika Gupta 	if (rc || data_size != sizeof(uint32_t)) {
192fa247a2aSRuchika Gupta 		DMSG("%s", rc ? "No attribute value_len found" :
193fa247a2aSRuchika Gupta 		     "Invalid size for attribute VALUE_LEN");
194fa247a2aSRuchika Gupta 
195fa247a2aSRuchika Gupta 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
196fa247a2aSRuchika Gupta 	}
197fa247a2aSRuchika Gupta 	TEE_MemMove(&value_len, data, data_size);
198fa247a2aSRuchika Gupta 
199fa247a2aSRuchika Gupta 	/* Remove the default empty value attribute if found */
200fa247a2aSRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
201fa247a2aSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
202fa247a2aSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
203fa247a2aSRuchika Gupta 
204fa247a2aSRuchika Gupta 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
205fa247a2aSRuchika Gupta 	if (!value)
206fa247a2aSRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
207fa247a2aSRuchika Gupta 
208fa247a2aSRuchika Gupta 	TEE_GenerateRandom(value, value_len);
209fa247a2aSRuchika Gupta 
210fa247a2aSRuchika Gupta 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
211fa247a2aSRuchika Gupta 
212bcac2127SMarouene Boubakri 	if (rc == PKCS11_CKR_OK)
213bcac2127SMarouene Boubakri 		rc = set_check_value_attr(head);
214bcac2127SMarouene Boubakri 
215fa247a2aSRuchika Gupta 	TEE_Free(value);
216fa247a2aSRuchika Gupta 
217fa247a2aSRuchika Gupta 	return rc;
218fa247a2aSRuchika Gupta }
219fa247a2aSRuchika Gupta 
220fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
221fa247a2aSRuchika Gupta 				     uint32_t ptypes, TEE_Param *params)
222fa247a2aSRuchika Gupta {
223fa247a2aSRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
224fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE,
225fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
226fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE);
227fa247a2aSRuchika Gupta 	TEE_Param *ctrl = params;
228fa247a2aSRuchika Gupta 	TEE_Param *out = params + 2;
229fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
230fa247a2aSRuchika Gupta 	struct serialargs ctrlargs = { };
231fa247a2aSRuchika Gupta 	struct pkcs11_session *session = NULL;
232fa247a2aSRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
233fa247a2aSRuchika Gupta 	struct obj_attrs *head = NULL;
234fa247a2aSRuchika Gupta 	struct pkcs11_object_head *template = NULL;
235fa247a2aSRuchika Gupta 	size_t template_size = 0;
236fa247a2aSRuchika Gupta 	uint32_t obj_handle = 0;
237fa247a2aSRuchika Gupta 
238fa247a2aSRuchika Gupta 	if (!client || ptypes != exp_pt ||
239fa247a2aSRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
240fa247a2aSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
241fa247a2aSRuchika Gupta 
242fa247a2aSRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
243fa247a2aSRuchika Gupta 
244fa247a2aSRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
245fa247a2aSRuchika Gupta 	if (rc)
246fa247a2aSRuchika Gupta 		return rc;
247fa247a2aSRuchika Gupta 
248fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
249fa247a2aSRuchika Gupta 	if (rc)
250fa247a2aSRuchika Gupta 		goto out;
251fa247a2aSRuchika Gupta 
252fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
253fa247a2aSRuchika Gupta 	if (rc)
254fa247a2aSRuchika Gupta 		goto out;
255fa247a2aSRuchika Gupta 
256fa247a2aSRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
257fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
258fa247a2aSRuchika Gupta 		goto out;
259fa247a2aSRuchika Gupta 	}
260fa247a2aSRuchika Gupta 
261fa247a2aSRuchika Gupta 	rc = get_ready_session(session);
262fa247a2aSRuchika Gupta 	if (rc)
263fa247a2aSRuchika Gupta 		goto out;
264fa247a2aSRuchika Gupta 
265fa247a2aSRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
266fa247a2aSRuchika Gupta 
267fa247a2aSRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
268fa247a2aSRuchika Gupta 						PKCS11_FUNCTION_GENERATE,
269fa247a2aSRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
270fa247a2aSRuchika Gupta 	if (rc) {
271fa247a2aSRuchika Gupta 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
272fa247a2aSRuchika Gupta 		goto out;
273fa247a2aSRuchika Gupta 	}
274fa247a2aSRuchika Gupta 
275fa247a2aSRuchika Gupta 	/*
276fa247a2aSRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes.
277fa247a2aSRuchika Gupta 	 * Free temporary template once done.
278fa247a2aSRuchika Gupta 	 */
279fa247a2aSRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
280fa247a2aSRuchika Gupta 					     NULL, PKCS11_FUNCTION_GENERATE,
2814cfce748SRuchika Gupta 					     proc_params->id,
2824cfce748SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
283fa247a2aSRuchika Gupta 	if (rc)
284fa247a2aSRuchika Gupta 		goto out;
285fa247a2aSRuchika Gupta 
286fa247a2aSRuchika Gupta 	TEE_Free(template);
287fa247a2aSRuchika Gupta 	template = NULL;
288fa247a2aSRuchika Gupta 
289fa247a2aSRuchika Gupta 	rc = check_created_attrs(head, NULL);
290fa247a2aSRuchika Gupta 	if (rc)
291fa247a2aSRuchika Gupta 		goto out;
292fa247a2aSRuchika Gupta 
293fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
294fa247a2aSRuchika Gupta 	if (rc)
295fa247a2aSRuchika Gupta 		goto out;
296fa247a2aSRuchika Gupta 
297fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
298fa247a2aSRuchika Gupta 	if (rc)
299fa247a2aSRuchika Gupta 		goto out;
300fa247a2aSRuchika Gupta 
301fa247a2aSRuchika Gupta 	/*
302fa247a2aSRuchika Gupta 	 * Execute target processing and add value as attribute
303fa247a2aSRuchika Gupta 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
304fa247a2aSRuchika Gupta 	 * processing to be used.
305fa247a2aSRuchika Gupta 	 */
306fa247a2aSRuchika Gupta 	switch (proc_params->id) {
307fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
308fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
309fa247a2aSRuchika Gupta 		/* Generate random of size specified by attribute VALUE_LEN */
310fa247a2aSRuchika Gupta 		rc = generate_random_key_value(&head);
311fa247a2aSRuchika Gupta 		if (rc)
312fa247a2aSRuchika Gupta 			goto out;
313fa247a2aSRuchika Gupta 		break;
314fa247a2aSRuchika Gupta 
315fa247a2aSRuchika Gupta 	default:
316fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
317fa247a2aSRuchika Gupta 		goto out;
318fa247a2aSRuchika Gupta 	}
319fa247a2aSRuchika Gupta 
320fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
321fa247a2aSRuchika Gupta 	proc_params = NULL;
322fa247a2aSRuchika Gupta 
323fa247a2aSRuchika Gupta 	/*
324fa247a2aSRuchika Gupta 	 * Object is ready, register it and return a handle.
325fa247a2aSRuchika Gupta 	 */
326fa247a2aSRuchika Gupta 	rc = create_object(session, head, &obj_handle);
327fa247a2aSRuchika Gupta 	if (rc)
328fa247a2aSRuchika Gupta 		goto out;
329fa247a2aSRuchika Gupta 
330fa247a2aSRuchika Gupta 	/*
331fa247a2aSRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
332fa247a2aSRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
333fa247a2aSRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
334fa247a2aSRuchika Gupta 	 * be freed at function out.
335fa247a2aSRuchika Gupta 	 */
336fa247a2aSRuchika Gupta 	head = NULL;
337fa247a2aSRuchika Gupta 
338fa247a2aSRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
339fa247a2aSRuchika Gupta 	out->memref.size = sizeof(obj_handle);
340fa247a2aSRuchika Gupta 
341fa247a2aSRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
342fa247a2aSRuchika Gupta 	     session->handle, obj_handle);
343fa247a2aSRuchika Gupta 
344fa247a2aSRuchika Gupta out:
345fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
346fa247a2aSRuchika Gupta 	TEE_Free(template);
347fa247a2aSRuchika Gupta 	TEE_Free(head);
348fa247a2aSRuchika Gupta 
349fa247a2aSRuchika Gupta 	return rc;
350fa247a2aSRuchika Gupta }
351fa247a2aSRuchika Gupta 
352013934d8SVesa Jääskeläinen enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
353013934d8SVesa Jääskeläinen 					    uint32_t attribute,
354013934d8SVesa Jääskeläinen 					    void **data, size_t *size)
355013934d8SVesa Jääskeläinen {
356013934d8SVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
357013934d8SVesa Jääskeläinen 	void *ptr = NULL;
358c7f1b4f7SJens Wiklander 	size_t sz = 0;
359013934d8SVesa Jääskeläinen 
360013934d8SVesa Jääskeläinen 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
361013934d8SVesa Jääskeläinen 	if (res != TEE_ERROR_SHORT_BUFFER)
362013934d8SVesa Jääskeläinen 		return PKCS11_CKR_FUNCTION_FAILED;
363013934d8SVesa Jääskeläinen 
364013934d8SVesa Jääskeläinen 	ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
365013934d8SVesa Jääskeläinen 	if (!ptr)
366013934d8SVesa Jääskeläinen 		return PKCS11_CKR_DEVICE_MEMORY;
367013934d8SVesa Jääskeläinen 
368013934d8SVesa Jääskeläinen 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
369013934d8SVesa Jääskeläinen 	if (res) {
370013934d8SVesa Jääskeläinen 		TEE_Free(ptr);
371013934d8SVesa Jääskeläinen 	} else {
372013934d8SVesa Jääskeläinen 		*data = ptr;
373013934d8SVesa Jääskeläinen 		*size = sz;
374013934d8SVesa Jääskeläinen 	}
375013934d8SVesa Jääskeläinen 
376013934d8SVesa Jääskeläinen 	return tee2pkcs_error(res);
377013934d8SVesa Jääskeläinen }
378013934d8SVesa Jääskeläinen 
379013934d8SVesa Jääskeläinen enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head,
380013934d8SVesa Jääskeläinen 				      uint32_t pkcs11_id,
381013934d8SVesa Jääskeläinen 				      TEE_ObjectHandle tee_obj,
382013934d8SVesa Jääskeläinen 				      uint32_t tee_id)
383013934d8SVesa Jääskeläinen {
384013934d8SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
385013934d8SVesa Jääskeläinen 	void *a_ptr = NULL;
386013934d8SVesa Jääskeläinen 	size_t a_size = 0;
387013934d8SVesa Jääskeläinen 
388013934d8SVesa Jääskeläinen 	rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size);
389013934d8SVesa Jääskeläinen 	if (rc)
390013934d8SVesa Jääskeläinen 		goto out;
391013934d8SVesa Jääskeläinen 
392013934d8SVesa Jääskeläinen 	rc = add_attribute(head, pkcs11_id, a_ptr, a_size);
393013934d8SVesa Jääskeläinen 
394013934d8SVesa Jääskeläinen 	TEE_Free(a_ptr);
395013934d8SVesa Jääskeläinen 
396013934d8SVesa Jääskeläinen out:
397013934d8SVesa Jääskeläinen 	if (rc)
398013934d8SVesa Jääskeläinen 		EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s",
399013934d8SVesa Jääskeläinen 		     tee_id, pkcs11_id, id2str_attr(pkcs11_id));
400013934d8SVesa Jääskeläinen 	return rc;
401013934d8SVesa Jääskeläinen }
402013934d8SVesa Jääskeläinen 
403013934d8SVesa Jääskeläinen enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client,
404013934d8SVesa Jääskeläinen 				       uint32_t ptypes, TEE_Param *params)
405013934d8SVesa Jääskeläinen {
406013934d8SVesa Jääskeläinen 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
407013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
408013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
409013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE);
410013934d8SVesa Jääskeläinen 	TEE_Param *ctrl = params;
411013934d8SVesa Jääskeläinen 	TEE_Param *out = params + 2;
412013934d8SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
413013934d8SVesa Jääskeläinen 	struct serialargs ctrlargs = { };
414013934d8SVesa Jääskeläinen 	struct pkcs11_session *session = NULL;
415013934d8SVesa Jääskeläinen 	struct pkcs11_attribute_head *proc_params = NULL;
416013934d8SVesa Jääskeläinen 	struct obj_attrs *pub_head = NULL;
417013934d8SVesa Jääskeläinen 	struct obj_attrs *priv_head = NULL;
418013934d8SVesa Jääskeläinen 	struct pkcs11_object_head *pub_template = NULL;
419013934d8SVesa Jääskeläinen 	struct pkcs11_object_head *priv_template = NULL;
420013934d8SVesa Jääskeläinen 	struct pkcs11_object *object = NULL;
421013934d8SVesa Jääskeläinen 	size_t pub_template_size = 0;
422013934d8SVesa Jääskeläinen 	size_t priv_template_size = 0;
423013934d8SVesa Jääskeläinen 	uint32_t pubkey_handle = 0;
424013934d8SVesa Jääskeläinen 	uint32_t privkey_handle = 0;
425013934d8SVesa Jääskeläinen 	uint32_t *hdl_ptr = NULL;
426013934d8SVesa Jääskeläinen 	size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle);
427013934d8SVesa Jääskeläinen 
428013934d8SVesa Jääskeläinen 	if (!client || ptypes != exp_pt || out->memref.size != out_ref_size)
429013934d8SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
430013934d8SVesa Jääskeläinen 
431013934d8SVesa Jääskeläinen 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
432013934d8SVesa Jääskeläinen 
433013934d8SVesa Jääskeläinen 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
434013934d8SVesa Jääskeläinen 	if (rc)
435013934d8SVesa Jääskeläinen 		return rc;
436013934d8SVesa Jääskeläinen 
437013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
438013934d8SVesa Jääskeläinen 	if (rc)
439013934d8SVesa Jääskeläinen 		goto out;
440013934d8SVesa Jääskeläinen 
441013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template);
442013934d8SVesa Jääskeläinen 	if (rc)
443013934d8SVesa Jääskeläinen 		goto out;
444013934d8SVesa Jääskeläinen 
445013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template);
446013934d8SVesa Jääskeläinen 	if (rc)
447013934d8SVesa Jääskeläinen 		goto out;
448013934d8SVesa Jääskeläinen 
449013934d8SVesa Jääskeläinen 	if (serialargs_remaining_bytes(&ctrlargs)) {
450013934d8SVesa Jääskeläinen 		rc = PKCS11_CKR_ARGUMENTS_BAD;
451013934d8SVesa Jääskeläinen 		goto out;
452013934d8SVesa Jääskeläinen 	}
453013934d8SVesa Jääskeläinen 
454013934d8SVesa Jääskeläinen 	rc = get_ready_session(session);
455013934d8SVesa Jääskeläinen 	if (rc)
456013934d8SVesa Jääskeläinen 		goto out;
457013934d8SVesa Jääskeläinen 
458013934d8SVesa Jääskeläinen 	rc = check_mechanism_against_processing(session, proc_params->id,
459013934d8SVesa Jääskeläinen 						PKCS11_FUNCTION_GENERATE_PAIR,
460013934d8SVesa Jääskeläinen 						PKCS11_FUNC_STEP_INIT);
461013934d8SVesa Jääskeläinen 	if (rc)
462013934d8SVesa Jääskeläinen 		goto out;
463013934d8SVesa Jääskeläinen 
464013934d8SVesa Jääskeläinen 	pub_template_size = sizeof(*pub_template) + pub_template->attrs_size;
465013934d8SVesa Jääskeläinen 
466013934d8SVesa Jääskeläinen 	rc = create_attributes_from_template(&pub_head, pub_template,
467013934d8SVesa Jääskeläinen 					     pub_template_size, NULL,
468013934d8SVesa Jääskeläinen 					     PKCS11_FUNCTION_GENERATE_PAIR,
469013934d8SVesa Jääskeläinen 					     proc_params->id,
470013934d8SVesa Jääskeläinen 					     PKCS11_CKO_PUBLIC_KEY);
471013934d8SVesa Jääskeläinen 	if (rc)
472013934d8SVesa Jääskeläinen 		goto out;
473013934d8SVesa Jääskeläinen 
474013934d8SVesa Jääskeläinen 	TEE_Free(pub_template);
475013934d8SVesa Jääskeläinen 	pub_template = NULL;
476013934d8SVesa Jääskeläinen 
477013934d8SVesa Jääskeläinen 	priv_template_size = sizeof(*priv_template) +
478013934d8SVesa Jääskeläinen 			     priv_template->attrs_size;
479013934d8SVesa Jääskeläinen 
480013934d8SVesa Jääskeläinen 	rc = create_attributes_from_template(&priv_head, priv_template,
481013934d8SVesa Jääskeläinen 					     priv_template_size, NULL,
482013934d8SVesa Jääskeläinen 					     PKCS11_FUNCTION_GENERATE_PAIR,
483013934d8SVesa Jääskeläinen 					     proc_params->id,
484013934d8SVesa Jääskeläinen 					     PKCS11_CKO_PRIVATE_KEY);
485013934d8SVesa Jääskeläinen 	if (rc)
486013934d8SVesa Jääskeläinen 		goto out;
487013934d8SVesa Jääskeläinen 
488013934d8SVesa Jääskeläinen 	TEE_Free(priv_template);
489013934d8SVesa Jääskeläinen 	priv_template = NULL;
490013934d8SVesa Jääskeläinen 
491013934d8SVesa Jääskeläinen 	/* Generate CKA_ID for keys if not specified by the templates */
492013934d8SVesa Jääskeläinen 	rc = add_missing_attribute_id(&pub_head, &priv_head);
493013934d8SVesa Jääskeläinen 	if (rc)
494013934d8SVesa Jääskeläinen 		goto out;
495013934d8SVesa Jääskeläinen 
496013934d8SVesa Jääskeläinen 	/* Check created object against processing and token state */
497013934d8SVesa Jääskeläinen 	rc = check_created_attrs(pub_head, priv_head);
498013934d8SVesa Jääskeläinen 	if (rc)
499013934d8SVesa Jääskeläinen 		goto out;
500013934d8SVesa Jääskeläinen 
501013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_processing(proc_params->id, pub_head);
502013934d8SVesa Jääskeläinen 	if (rc)
503013934d8SVesa Jääskeläinen 		goto out;
504013934d8SVesa Jääskeläinen 
505013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_processing(proc_params->id,
506013934d8SVesa Jääskeläinen 						    priv_head);
507013934d8SVesa Jääskeläinen 	if (rc)
508013934d8SVesa Jääskeläinen 		goto out;
509013934d8SVesa Jääskeläinen 
510013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_token(session, pub_head);
511013934d8SVesa Jääskeläinen 	if (rc)
512013934d8SVesa Jääskeläinen 		goto out;
513013934d8SVesa Jääskeläinen 
514013934d8SVesa Jääskeläinen 	rc = check_access_attrs_against_token(session, pub_head);
515013934d8SVesa Jääskeläinen 	if (rc)
516013934d8SVesa Jääskeläinen 		goto out;
517013934d8SVesa Jääskeläinen 
518013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_token(session, priv_head);
519013934d8SVesa Jääskeläinen 	if (rc)
520013934d8SVesa Jääskeläinen 		goto out;
521013934d8SVesa Jääskeläinen 
522013934d8SVesa Jääskeläinen 	rc = check_access_attrs_against_token(session, priv_head);
523013934d8SVesa Jääskeläinen 	if (rc)
524013934d8SVesa Jääskeläinen 		goto out;
525013934d8SVesa Jääskeläinen 
526013934d8SVesa Jääskeläinen 	/* Generate key pair */
527013934d8SVesa Jääskeläinen 	switch (proc_params->id) {
52803e07432SValerii Chubar 	case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
52903e07432SValerii Chubar 		rc = generate_eddsa_keys(proc_params, &pub_head, &priv_head);
53003e07432SValerii Chubar 		break;
53102b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
53202b16804SVesa Jääskeläinen 		rc = generate_ec_keys(proc_params, &pub_head, &priv_head);
53302b16804SVesa Jääskeläinen 		break;
53486922832SVesa Jääskeläinen 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
53586922832SVesa Jääskeläinen 		rc = generate_rsa_keys(proc_params, &pub_head, &priv_head);
53686922832SVesa Jääskeläinen 		break;
537013934d8SVesa Jääskeläinen 	default:
538013934d8SVesa Jääskeläinen 		rc = PKCS11_CKR_MECHANISM_INVALID;
539013934d8SVesa Jääskeläinen 		break;
540013934d8SVesa Jääskeläinen 	}
541013934d8SVesa Jääskeläinen 	if (rc)
542013934d8SVesa Jääskeläinen 		goto out;
543013934d8SVesa Jääskeläinen 
544013934d8SVesa Jääskeläinen 	TEE_Free(proc_params);
545013934d8SVesa Jääskeläinen 	proc_params = NULL;
546013934d8SVesa Jääskeläinen 
547013934d8SVesa Jääskeläinen 	/*
548013934d8SVesa Jääskeläinen 	 * Object is ready, register it and return a handle.
549013934d8SVesa Jääskeläinen 	 */
550013934d8SVesa Jääskeläinen 	rc = create_object(session, pub_head, &pubkey_handle);
551013934d8SVesa Jääskeläinen 	if (rc)
552013934d8SVesa Jääskeläinen 		goto out;
553013934d8SVesa Jääskeläinen 
554013934d8SVesa Jääskeläinen 	/*
555013934d8SVesa Jääskeläinen 	 * Now obj_handle (through the related struct pkcs11_object instance)
556013934d8SVesa Jääskeläinen 	 * owns the serialized buffer that holds the object attributes.
557013934d8SVesa Jääskeläinen 	 * We reset local pub_head to NULL to mark that ownership has been
558013934d8SVesa Jääskeläinen 	 * transferred.
559013934d8SVesa Jääskeläinen 	 */
560013934d8SVesa Jääskeläinen 	pub_head = NULL;
561013934d8SVesa Jääskeläinen 
562013934d8SVesa Jääskeläinen 	rc = create_object(session, priv_head, &privkey_handle);
563013934d8SVesa Jääskeläinen 	if (rc)
564013934d8SVesa Jääskeläinen 		goto out;
565013934d8SVesa Jääskeläinen 
566013934d8SVesa Jääskeläinen 	/* Ownership has been transferred so mark it with NULL */
567013934d8SVesa Jääskeläinen 	priv_head = NULL;
568013934d8SVesa Jääskeläinen 
569013934d8SVesa Jääskeläinen 	hdl_ptr = (uint32_t *)out->memref.buffer;
570013934d8SVesa Jääskeläinen 
571013934d8SVesa Jääskeläinen 	TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle));
572013934d8SVesa Jääskeläinen 	TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle));
573013934d8SVesa Jääskeläinen 
574013934d8SVesa Jääskeläinen 	DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32,
575013934d8SVesa Jääskeläinen 	     session->handle, privkey_handle, pubkey_handle);
576013934d8SVesa Jääskeläinen 
5772f7f001aSSergiy Kibrik 	pubkey_handle = 0;
5782f7f001aSSergiy Kibrik 	privkey_handle = 0;
579013934d8SVesa Jääskeläinen out:
580013934d8SVesa Jääskeläinen 	if (pubkey_handle) {
581013934d8SVesa Jääskeläinen 		object = pkcs11_handle2object(pubkey_handle, session);
582013934d8SVesa Jääskeläinen 		if (!object)
583013934d8SVesa Jääskeläinen 			TEE_Panic(0);
584013934d8SVesa Jääskeläinen 		destroy_object(session, object, false);
585013934d8SVesa Jääskeläinen 	}
586013934d8SVesa Jääskeläinen 	TEE_Free(priv_head);
587013934d8SVesa Jääskeläinen 	TEE_Free(pub_head);
588013934d8SVesa Jääskeläinen 	TEE_Free(priv_template);
589013934d8SVesa Jääskeläinen 	TEE_Free(pub_template);
590013934d8SVesa Jääskeläinen 	TEE_Free(proc_params);
591013934d8SVesa Jääskeläinen 
592013934d8SVesa Jääskeläinen 	return rc;
593013934d8SVesa Jääskeläinen }
594013934d8SVesa Jääskeläinen 
595512cbf1dSJens Wiklander /*
596512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
597512cbf1dSJens Wiklander  *
598512cbf1dSJens Wiklander  * @client = client reference
599512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
600512cbf1dSJens Wiklander  * @params = Invocation parameters reference
601512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
602512cbf1dSJens Wiklander  */
603512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
604512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
605512cbf1dSJens Wiklander 				     enum processing_func function)
606512cbf1dSJens Wiklander {
607512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
608512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
609512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
610512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
611512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
612512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
613512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
614512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
615512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
616512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
617512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
618512cbf1dSJens Wiklander 
619512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
620512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
621512cbf1dSJens Wiklander 
622512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
623512cbf1dSJens Wiklander 
624512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
625512cbf1dSJens Wiklander 	if (rc)
626512cbf1dSJens Wiklander 		return rc;
627512cbf1dSJens Wiklander 
6289e91a619SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_DIGEST) {
629512cbf1dSJens Wiklander 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
630512cbf1dSJens Wiklander 		if (rc)
631512cbf1dSJens Wiklander 			return rc;
6329e91a619SVesa Jääskeläinen 	}
633512cbf1dSJens Wiklander 
634512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
635512cbf1dSJens Wiklander 	if (rc)
636512cbf1dSJens Wiklander 		return rc;
637512cbf1dSJens Wiklander 
638512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
639512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
6408abbc8f7SVesa Jääskeläinen 		goto out_free;
641512cbf1dSJens Wiklander 	}
642512cbf1dSJens Wiklander 
643512cbf1dSJens Wiklander 	rc = get_ready_session(session);
644512cbf1dSJens Wiklander 	if (rc)
6458abbc8f7SVesa Jääskeläinen 		goto out_free;
646512cbf1dSJens Wiklander 
6479e91a619SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_DIGEST) {
648512cbf1dSJens Wiklander 		obj = pkcs11_handle2object(key_handle, session);
649512cbf1dSJens Wiklander 		if (!obj) {
650512cbf1dSJens Wiklander 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
6518abbc8f7SVesa Jääskeläinen 			goto out_free;
652512cbf1dSJens Wiklander 		}
6539e91a619SVesa Jääskeläinen 	}
654512cbf1dSJens Wiklander 
655512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
656512cbf1dSJens Wiklander 	if (rc)
657512cbf1dSJens Wiklander 		goto out;
658512cbf1dSJens Wiklander 
659512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
660512cbf1dSJens Wiklander 						function,
661512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
662512cbf1dSJens Wiklander 	if (rc)
663512cbf1dSJens Wiklander 		goto out;
664512cbf1dSJens Wiklander 
6659e91a619SVesa Jääskeläinen 	if (obj) {
6669e91a619SVesa Jääskeläinen 		rc = check_parent_attrs_against_processing(proc_params->id,
6679e91a619SVesa Jääskeläinen 							   function,
668512cbf1dSJens Wiklander 							   obj->attributes);
669512cbf1dSJens Wiklander 		if (rc)
670512cbf1dSJens Wiklander 			goto out;
671512cbf1dSJens Wiklander 
6729e91a619SVesa Jääskeläinen 		rc = check_access_attrs_against_token(session,
6739e91a619SVesa Jääskeläinen 						      obj->attributes);
674512cbf1dSJens Wiklander 		if (rc)
675512cbf1dSJens Wiklander 			goto out;
6769e91a619SVesa Jääskeläinen 	}
677512cbf1dSJens Wiklander 
678512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
679512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
680fb279d8bSVesa Jääskeläinen 	else if (processing_is_tee_asymm(proc_params->id))
681fb279d8bSVesa Jääskeläinen 		rc = init_asymm_operation(session, function, proc_params, obj);
6829e91a619SVesa Jääskeläinen 	else if (processing_is_tee_digest(proc_params->id))
6839e91a619SVesa Jääskeläinen 		rc = init_digest_operation(session, proc_params);
684512cbf1dSJens Wiklander 	else
685512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
686512cbf1dSJens Wiklander 
687512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
688512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
689512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
690512cbf1dSJens Wiklander 		     id2str_function(function));
691512cbf1dSJens Wiklander 	}
692512cbf1dSJens Wiklander 
693512cbf1dSJens Wiklander out:
6948abbc8f7SVesa Jääskeläinen 	if (rc)
695512cbf1dSJens Wiklander 		release_active_processing(session);
6968abbc8f7SVesa Jääskeläinen out_free:
697512cbf1dSJens Wiklander 	TEE_Free(proc_params);
698512cbf1dSJens Wiklander 
699512cbf1dSJens Wiklander 	return rc;
700512cbf1dSJens Wiklander }
701512cbf1dSJens Wiklander 
702512cbf1dSJens Wiklander /*
703512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
704512cbf1dSJens Wiklander  *
705512cbf1dSJens Wiklander  * @client = client reference
706512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
707512cbf1dSJens Wiklander  * @params = Invocation parameters reference
708512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
709512cbf1dSJens Wiklander  * @step - update, oneshot, final
710512cbf1dSJens Wiklander  */
711512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
712512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
713512cbf1dSJens Wiklander 				     enum processing_func function,
714512cbf1dSJens Wiklander 				     enum processing_step step)
715512cbf1dSJens Wiklander {
716512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
717512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
718512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
719512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
720512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
7219e91a619SVesa Jääskeläinen 	uint32_t key_handle = 0;
7229e91a619SVesa Jääskeläinen 	struct pkcs11_object *obj = NULL;
723512cbf1dSJens Wiklander 
724512cbf1dSJens Wiklander 	if (!client ||
725512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
726512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
727512cbf1dSJens Wiklander 
728512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
729512cbf1dSJens Wiklander 
730512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
731512cbf1dSJens Wiklander 	if (rc)
732512cbf1dSJens Wiklander 		return rc;
733512cbf1dSJens Wiklander 
7349e91a619SVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
7359e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
7369e91a619SVesa Jääskeläinen 
7379e91a619SVesa Jääskeläinen 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
7389e91a619SVesa Jääskeläinen 		if (rc)
7399e91a619SVesa Jääskeläinen 			return rc;
7409e91a619SVesa Jääskeläinen 	}
7419e91a619SVesa Jääskeläinen 
742512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
743512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
744512cbf1dSJens Wiklander 
745512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
746512cbf1dSJens Wiklander 	if (rc)
747512cbf1dSJens Wiklander 		return rc;
748512cbf1dSJens Wiklander 
7499e91a619SVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
7509e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
7519e91a619SVesa Jääskeläinen 
7529e91a619SVesa Jääskeläinen 		obj = pkcs11_handle2object(key_handle, session);
7539e91a619SVesa Jääskeläinen 		if (!obj) {
7549e91a619SVesa Jääskeläinen 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
7559e91a619SVesa Jääskeläinen 			goto out;
7569e91a619SVesa Jääskeläinen 		}
7579e91a619SVesa Jääskeläinen 
7589e91a619SVesa Jääskeläinen 		rc = check_access_attrs_against_token(session,
7599e91a619SVesa Jääskeläinen 						      obj->attributes);
7609e91a619SVesa Jääskeläinen 		if (rc) {
7619e91a619SVesa Jääskeläinen 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
7629e91a619SVesa Jääskeläinen 			goto out;
7639e91a619SVesa Jääskeläinen 		}
7649e91a619SVesa Jääskeläinen 	}
7659e91a619SVesa Jääskeläinen 
766512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
767512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
768512cbf1dSJens Wiklander 						function, step);
769512cbf1dSJens Wiklander 	if (rc)
770512cbf1dSJens Wiklander 		goto out;
771512cbf1dSJens Wiklander 
772512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
773512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
774512cbf1dSJens Wiklander 					 ptypes, params);
775fb279d8bSVesa Jääskeläinen 	else if (processing_is_tee_asymm(mecha_type))
776fb279d8bSVesa Jääskeläinen 		rc = step_asymm_operation(session, function, step,
777fb279d8bSVesa Jääskeläinen 					  ptypes, params);
7789e91a619SVesa Jääskeläinen 	else if (processing_is_tee_digest(mecha_type))
7799e91a619SVesa Jääskeläinen 		rc = step_digest_operation(session, step, obj, ptypes, params);
780512cbf1dSJens Wiklander 	else
781512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
782512cbf1dSJens Wiklander 
7839e91a619SVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE ||
7849e91a619SVesa Jääskeläinen 				    step == PKCS11_FUNC_STEP_UPDATE_KEY)) {
7852364aa69SRuchika Gupta 		session->processing->step = PKCS11_FUNC_STEP_UPDATE;
786512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
787512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
788512cbf1dSJens Wiklander 		     id2str_function(function));
789512cbf1dSJens Wiklander 	}
790512cbf1dSJens Wiklander 
7912364aa69SRuchika Gupta 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL &&
7922364aa69SRuchika Gupta 	    step == PKCS11_FUNC_STEP_ONESHOT)
7932364aa69SRuchika Gupta 		session->processing->step = PKCS11_FUNC_STEP_ONESHOT;
7942364aa69SRuchika Gupta 
7952364aa69SRuchika Gupta 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && step == PKCS11_FUNC_STEP_FINAL)
7962364aa69SRuchika Gupta 		session->processing->step = PKCS11_FUNC_STEP_FINAL;
7972364aa69SRuchika Gupta 
798512cbf1dSJens Wiklander out:
799512cbf1dSJens Wiklander 	switch (step) {
800512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
8019e91a619SVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE_KEY:
802512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
803512cbf1dSJens Wiklander 			release_active_processing(session);
804512cbf1dSJens Wiklander 		break;
805512cbf1dSJens Wiklander 	default:
806512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
807512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
808512cbf1dSJens Wiklander 			release_active_processing(session);
809512cbf1dSJens Wiklander 		break;
810512cbf1dSJens Wiklander 	}
811512cbf1dSJens Wiklander 
812512cbf1dSJens Wiklander 	return rc;
813512cbf1dSJens Wiklander }
81448799892SRuchika Gupta 
8154dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
8164dad6642SRuchika Gupta 				    uint32_t ptypes, TEE_Param *params,
8174dad6642SRuchika Gupta 				    enum processing_func function)
81848799892SRuchika Gupta {
81948799892SRuchika Gupta 	TEE_Param *ctrl = params;
82048799892SRuchika Gupta 	TEE_Param *out = params + 2;
82148799892SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
82248799892SRuchika Gupta 	struct serialargs ctrlargs = { };
82348799892SRuchika Gupta 	struct pkcs11_session *session = NULL;
82448799892SRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
82548799892SRuchika Gupta 	struct pkcs11_object_head *template = NULL;
82648799892SRuchika Gupta 	uint32_t parent_handle = 0;
82748799892SRuchika Gupta 	uint32_t obj_handle = 0;
82848799892SRuchika Gupta 	struct pkcs11_object *parent = NULL;
82948799892SRuchika Gupta 	struct obj_attrs *head = NULL;
83048799892SRuchika Gupta 	size_t template_size = 0;
8313668310bSRuchika Gupta 	void *in_buf = NULL;
8323668310bSRuchika Gupta 	uint32_t in_size = 0;
8338c499324SRuchika Gupta 	void *out_buf = NULL;
8348c499324SRuchika Gupta 	uint32_t out_size = 0;
8353668310bSRuchika Gupta 	enum processing_func operation = PKCS11_FUNCTION_UNKNOWN;
83648799892SRuchika Gupta 
8373668310bSRuchika Gupta 	if (!client ||
8383668310bSRuchika Gupta 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT ||
8393668310bSRuchika Gupta 	    TEE_PARAM_TYPE_GET(ptypes, 2) != TEE_PARAM_TYPE_MEMREF_OUTPUT ||
8403668310bSRuchika Gupta 	    out->memref.size != sizeof(obj_handle) ||
8413668310bSRuchika Gupta 	    TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
84248799892SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
84348799892SRuchika Gupta 
8443668310bSRuchika Gupta 	switch (function) {
8453668310bSRuchika Gupta 	case PKCS11_FUNCTION_UNWRAP:
8463668310bSRuchika Gupta 		if (TEE_PARAM_TYPE_GET(ptypes, 1) !=
8473668310bSRuchika Gupta 				TEE_PARAM_TYPE_MEMREF_INPUT)
8483668310bSRuchika Gupta 			return PKCS11_CKR_ARGUMENTS_BAD;
8493668310bSRuchika Gupta 
8503668310bSRuchika Gupta 		in_buf = params[1].memref.buffer;
8513668310bSRuchika Gupta 		in_size = params[1].memref.size;
8523668310bSRuchika Gupta 		if (in_size && !in_buf)
8533668310bSRuchika Gupta 			return PKCS11_CKR_ARGUMENTS_BAD;
8543668310bSRuchika Gupta 
8553668310bSRuchika Gupta 		/*
8563668310bSRuchika Gupta 		 * Some unwrap mechanisms require encryption to be
8573668310bSRuchika Gupta 		 * performed on the data passed in proc_params by parent
8583668310bSRuchika Gupta 		 * key. Hence set operation as PKCS11_FUNCTION_DECRYPT
8593668310bSRuchika Gupta 		 * to be used with init_symm_operation()
8603668310bSRuchika Gupta 		 */
8613668310bSRuchika Gupta 		operation = PKCS11_FUNCTION_DECRYPT;
8623668310bSRuchika Gupta 		break;
8633668310bSRuchika Gupta 	case PKCS11_FUNCTION_DERIVE:
8643668310bSRuchika Gupta 		if (TEE_PARAM_TYPE_GET(ptypes, 1) != TEE_PARAM_TYPE_NONE)
8653668310bSRuchika Gupta 			return PKCS11_CKR_ARGUMENTS_BAD;
8663668310bSRuchika Gupta 
8673668310bSRuchika Gupta 		/*
8683668310bSRuchika Gupta 		 * Some derivation mechanism require encryption to be
8693668310bSRuchika Gupta 		 * performed on the data passed in proc_params by parent
8703668310bSRuchika Gupta 		 * key. Hence set operation as PKCS11_FUNCTION_ENCRYPT
8713668310bSRuchika Gupta 		 * to be used with init_symm_operation()
8723668310bSRuchika Gupta 		 */
8733668310bSRuchika Gupta 		operation = PKCS11_FUNCTION_ENCRYPT;
8743668310bSRuchika Gupta 		break;
8753668310bSRuchika Gupta 	default:
8763668310bSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
8773668310bSRuchika Gupta 	}
8783668310bSRuchika Gupta 
87948799892SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
88048799892SRuchika Gupta 
88148799892SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
88248799892SRuchika Gupta 	if (rc)
88348799892SRuchika Gupta 		return rc;
88448799892SRuchika Gupta 
88548799892SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
88648799892SRuchika Gupta 	if (rc)
88748799892SRuchika Gupta 		return rc;
88848799892SRuchika Gupta 
88948799892SRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
89048799892SRuchika Gupta 	if (rc)
8915f80f270SRuchika Gupta 		return rc;
89248799892SRuchika Gupta 
89348799892SRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
89448799892SRuchika Gupta 	if (rc)
89548799892SRuchika Gupta 		goto out_free;
89648799892SRuchika Gupta 
89748799892SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
89848799892SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
89948799892SRuchika Gupta 		goto out_free;
90048799892SRuchika Gupta 	}
90148799892SRuchika Gupta 
90248799892SRuchika Gupta 	/* Return error if processing already active */
90348799892SRuchika Gupta 	rc = get_ready_session(session);
90448799892SRuchika Gupta 	if (rc)
90548799892SRuchika Gupta 		goto out_free;
90648799892SRuchika Gupta 
90748799892SRuchika Gupta 	/* Check parent handle */
90848799892SRuchika Gupta 	parent = pkcs11_handle2object(parent_handle, session);
90948799892SRuchika Gupta 	if (!parent) {
91048799892SRuchika Gupta 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
91148799892SRuchika Gupta 		goto out_free;
91248799892SRuchika Gupta 	}
91348799892SRuchika Gupta 
91448799892SRuchika Gupta 	/* Check if mechanism can be used for derivation function */
91548799892SRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
91648799892SRuchika Gupta 						function,
91748799892SRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
91848799892SRuchika Gupta 	if (rc)
91948799892SRuchika Gupta 		goto out_free;
92048799892SRuchika Gupta 
92148799892SRuchika Gupta 	/* Set the processing state to active */
92248799892SRuchika Gupta 	rc = set_processing_state(session, function, parent, NULL);
92348799892SRuchika Gupta 	if (rc)
92448799892SRuchika Gupta 		goto out_free;
92548799892SRuchika Gupta 
92648799892SRuchika Gupta 	/*
92748799892SRuchika Gupta 	 * Check if base/parent key has CKA_DERIVE set and its key type is
92848799892SRuchika Gupta 	 * compatible with the mechanism passed
92948799892SRuchika Gupta 	 */
93048799892SRuchika Gupta 	rc = check_parent_attrs_against_processing(proc_params->id, function,
93148799892SRuchika Gupta 						   parent->attributes);
932d05ab5feSRuchika Gupta 	if (rc) {
933d05ab5feSRuchika Gupta 		/*
934d05ab5feSRuchika Gupta 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
935d05ab5feSRuchika Gupta 		 * specified with C_Derive/Unwrap() in the specification. So
936d05ab5feSRuchika Gupta 		 * return the next most appropriate error.
937d05ab5feSRuchika Gupta 		 */
9383668310bSRuchika Gupta 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) {
9393668310bSRuchika Gupta 			if (function == PKCS11_FUNCTION_UNWRAP)
9403668310bSRuchika Gupta 				rc =
9413668310bSRuchika Gupta 				  PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
9423668310bSRuchika Gupta 			else
943d05ab5feSRuchika Gupta 				rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
9443668310bSRuchika Gupta 		}
94548799892SRuchika Gupta 		goto out;
946d05ab5feSRuchika Gupta 	}
94748799892SRuchika Gupta 
94848799892SRuchika Gupta 	/* Check access of base/parent key */
94948799892SRuchika Gupta 	rc = check_access_attrs_against_token(session, parent->attributes);
95048799892SRuchika Gupta 	if (rc)
95148799892SRuchika Gupta 		goto out;
95248799892SRuchika Gupta 
95348799892SRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
95448799892SRuchika Gupta 	/*
95548799892SRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes
95648799892SRuchika Gupta 	 * using base/parent key attributes. Free temporary template once done.
95748799892SRuchika Gupta 	 */
95848799892SRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
95948799892SRuchika Gupta 					     parent->attributes,
96048799892SRuchika Gupta 					     function,
96148799892SRuchika Gupta 					     proc_params->id,
96248799892SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
96348799892SRuchika Gupta 	if (rc)
96448799892SRuchika Gupta 		goto out;
96548799892SRuchika Gupta 
96648799892SRuchika Gupta 	TEE_Free(template);
96748799892SRuchika Gupta 	template = NULL;
96848799892SRuchika Gupta 
96948799892SRuchika Gupta 	/* check_created_attrs() is called later once key size is known */
97048799892SRuchika Gupta 
97148799892SRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
97248799892SRuchika Gupta 	if (rc)
97348799892SRuchika Gupta 		goto out;
97448799892SRuchika Gupta 
97548799892SRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
97648799892SRuchika Gupta 	if (rc)
97748799892SRuchika Gupta 		goto out;
97848799892SRuchika Gupta 
979f5c0739cSRuchika Gupta 	rc = check_access_attrs_against_token(session, head);
980f5c0739cSRuchika Gupta 	if (rc)
981f5c0739cSRuchika Gupta 		goto out;
982f5c0739cSRuchika Gupta 
9838c499324SRuchika Gupta 	if (processing_is_tee_symm(proc_params->id)) {
9843668310bSRuchika Gupta 		rc = init_symm_operation(session, operation, proc_params,
9853668310bSRuchika Gupta 					 parent);
98648799892SRuchika Gupta 		if (rc)
98748799892SRuchika Gupta 			goto out;
98848799892SRuchika Gupta 
9893668310bSRuchika Gupta 		switch (function) {
9903668310bSRuchika Gupta 		case PKCS11_FUNCTION_DERIVE:
9913668310bSRuchika Gupta 			rc = derive_key_by_symm_enc(session, &out_buf,
9923668310bSRuchika Gupta 						    &out_size);
9933668310bSRuchika Gupta 			break;
9943668310bSRuchika Gupta 		case PKCS11_FUNCTION_UNWRAP:
9953668310bSRuchika Gupta 			rc = unwrap_key_by_symm(session, in_buf, in_size,
9963668310bSRuchika Gupta 						&out_buf, &out_size);
9973668310bSRuchika Gupta 			break;
9983668310bSRuchika Gupta 		default:
9993668310bSRuchika Gupta 			TEE_Panic(function);
10003668310bSRuchika Gupta 		}
100148799892SRuchika Gupta 		if (rc)
100248799892SRuchika Gupta 			goto out;
1003cc062b46SJorge Ramirez-Ortiz 
1004cc062b46SJorge Ramirez-Ortiz 	} else if (processing_is_tee_asymm(proc_params->id)) {
100545d40bdaSValerii Chubar 		switch (function) {
100645d40bdaSValerii Chubar 		case PKCS11_FUNCTION_DERIVE:
100745d40bdaSValerii Chubar 			rc = init_asymm_operation(session, function,
100845d40bdaSValerii Chubar 						  proc_params, parent);
1009cc062b46SJorge Ramirez-Ortiz 			if (rc)
1010cc062b46SJorge Ramirez-Ortiz 				goto out;
1011cc062b46SJorge Ramirez-Ortiz 
1012cc062b46SJorge Ramirez-Ortiz 			rc = do_asymm_derivation(session, proc_params, &head);
101345d40bdaSValerii Chubar 			if (!rc)
101445d40bdaSValerii Chubar 				goto done;
101545d40bdaSValerii Chubar 			break;
101645d40bdaSValerii Chubar 		case PKCS11_FUNCTION_UNWRAP:
101745d40bdaSValerii Chubar 			rc = init_asymm_operation(session, operation,
101845d40bdaSValerii Chubar 						  proc_params, parent);
1019cc062b46SJorge Ramirez-Ortiz 			if (rc)
1020cc062b46SJorge Ramirez-Ortiz 				goto out;
1021cc062b46SJorge Ramirez-Ortiz 
102245d40bdaSValerii Chubar 			rc = unwrap_key_by_asymm(session, in_buf, in_size,
102345d40bdaSValerii Chubar 						 &out_buf, &out_size);
102445d40bdaSValerii Chubar 			break;
102545d40bdaSValerii Chubar 		default:
102645d40bdaSValerii Chubar 			TEE_Panic(function);
102745d40bdaSValerii Chubar 		}
102845d40bdaSValerii Chubar 
102945d40bdaSValerii Chubar 		if (rc)
103045d40bdaSValerii Chubar 			goto out;
10318c499324SRuchika Gupta 	} else {
103248799892SRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
103348799892SRuchika Gupta 		goto out;
103448799892SRuchika Gupta 	}
103548799892SRuchika Gupta 
10368c499324SRuchika Gupta 	rc = set_key_data(&head, out_buf, out_size);
10378c499324SRuchika Gupta 	if (rc)
10388c499324SRuchika Gupta 		goto out;
10398c499324SRuchika Gupta 
1040cc062b46SJorge Ramirez-Ortiz done:
10418c499324SRuchika Gupta 	TEE_Free(out_buf);
10428c499324SRuchika Gupta 	out_buf = NULL;
10438c499324SRuchika Gupta 
104448799892SRuchika Gupta 	TEE_Free(proc_params);
104548799892SRuchika Gupta 	proc_params = NULL;
104648799892SRuchika Gupta 
104748799892SRuchika Gupta 	/*
104848799892SRuchika Gupta 	 * Object is ready, register it and return a handle.
104948799892SRuchika Gupta 	 */
105048799892SRuchika Gupta 	rc = create_object(session, head, &obj_handle);
105148799892SRuchika Gupta 	if (rc)
105248799892SRuchika Gupta 		goto out;
105348799892SRuchika Gupta 
105448799892SRuchika Gupta 	/*
105548799892SRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
105648799892SRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
105748799892SRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
105848799892SRuchika Gupta 	 * be freed at function out.
105948799892SRuchika Gupta 	 */
106048799892SRuchika Gupta 	head = NULL;
106148799892SRuchika Gupta 
106248799892SRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
106348799892SRuchika Gupta 	out->memref.size = sizeof(obj_handle);
106448799892SRuchika Gupta 
106548799892SRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
106648799892SRuchika Gupta 	     session->handle, obj_handle);
106748799892SRuchika Gupta 
106848799892SRuchika Gupta out:
106948799892SRuchika Gupta 	release_active_processing(session);
107048799892SRuchika Gupta out_free:
107148799892SRuchika Gupta 	TEE_Free(proc_params);
107248799892SRuchika Gupta 	TEE_Free(template);
107348799892SRuchika Gupta 	TEE_Free(head);
10748c499324SRuchika Gupta 	TEE_Free(out_buf);
107548799892SRuchika Gupta 
107648799892SRuchika Gupta 	return rc;
107748799892SRuchika Gupta }
1078eb6141b6SVesa Jääskeläinen 
1079eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
1080eb6141b6SVesa Jääskeläinen 					       uint32_t ptypes,
1081eb6141b6SVesa Jääskeläinen 					       TEE_Param *params)
1082eb6141b6SVesa Jääskeläinen {
1083eb6141b6SVesa Jääskeläinen 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1084eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
1085eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
1086eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE);
1087eb6141b6SVesa Jääskeläinen 	TEE_Param *ctrl = params;
1088eb6141b6SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
1089eb6141b6SVesa Jääskeläinen 	struct serialargs ctrlargs = { };
1090eb6141b6SVesa Jääskeläinen 	struct pkcs11_session *session = NULL;
1091eb6141b6SVesa Jääskeläinen 	enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
1092eb6141b6SVesa Jääskeläinen 	uint32_t cmd = 0;
1093eb6141b6SVesa Jääskeläinen 
1094eb6141b6SVesa Jääskeläinen 	if (!client || ptypes != exp_pt)
1095eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
1096eb6141b6SVesa Jääskeläinen 
1097eb6141b6SVesa Jääskeläinen 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1098eb6141b6SVesa Jääskeläinen 
1099eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1100eb6141b6SVesa Jääskeläinen 	if (rc)
1101eb6141b6SVesa Jääskeläinen 		return rc;
1102eb6141b6SVesa Jääskeläinen 
1103eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_u32(&ctrlargs, &cmd);
1104eb6141b6SVesa Jääskeläinen 
1105eb6141b6SVesa Jääskeläinen 	if (serialargs_remaining_bytes(&ctrlargs))
1106eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
1107eb6141b6SVesa Jääskeläinen 
1108eb6141b6SVesa Jääskeläinen 	function = func_for_cmd(cmd);
1109eb6141b6SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_UNKNOWN)
1110eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
1111eb6141b6SVesa Jääskeläinen 
1112eb6141b6SVesa Jääskeläinen 	rc = get_active_session(session, function);
1113eb6141b6SVesa Jääskeläinen 	if (rc)
1114eb6141b6SVesa Jääskeläinen 		return rc;
1115eb6141b6SVesa Jääskeläinen 
1116eb6141b6SVesa Jääskeläinen 	release_active_processing(session);
1117eb6141b6SVesa Jääskeläinen 
1118eb6141b6SVesa Jääskeläinen 	DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
1119eb6141b6SVesa Jääskeläinen 
1120eb6141b6SVesa Jääskeläinen 	return PKCS11_CKR_OK;
1121eb6141b6SVesa Jääskeläinen }
11225f80f270SRuchika Gupta 
11235f80f270SRuchika Gupta enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client,
11245f80f270SRuchika Gupta 			      uint32_t ptypes, TEE_Param *params)
11255f80f270SRuchika Gupta {
11265f80f270SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
11275f80f270SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
11285f80f270SRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
11295f80f270SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
11305f80f270SRuchika Gupta 	TEE_Param *ctrl = params;
11315f80f270SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
11325f80f270SRuchika Gupta 	struct serialargs ctrlargs = { };
11335f80f270SRuchika Gupta 	struct pkcs11_session *session = NULL;
11345f80f270SRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
11355f80f270SRuchika Gupta 	struct pkcs11_object *wrapping_key = NULL;
11365f80f270SRuchika Gupta 	struct pkcs11_object *key = NULL;
11375f80f270SRuchika Gupta 	void *req_attrs = NULL;
11385f80f270SRuchika Gupta 	uint32_t wrapping_key_handle = 0;
11395f80f270SRuchika Gupta 	uint32_t key_handle = 0;
11405f80f270SRuchika Gupta 	uint32_t size = 0;
11415f80f270SRuchika Gupta 	void *key_data = NULL;
11425f80f270SRuchika Gupta 	uint32_t key_sz = 0;
11435f80f270SRuchika Gupta 	void *out_buf = params[2].memref.buffer;
11445f80f270SRuchika Gupta 	uint32_t out_size = params[2].memref.size;
11455f80f270SRuchika Gupta 	const enum processing_func function = PKCS11_FUNCTION_WRAP;
11465f80f270SRuchika Gupta 
11475f80f270SRuchika Gupta 	if (!client || ptypes != exp_pt ||
11485f80f270SRuchika Gupta 	    (out_size && !out_buf))
11495f80f270SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
11505f80f270SRuchika Gupta 
11515f80f270SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
11525f80f270SRuchika Gupta 
11535f80f270SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
11545f80f270SRuchika Gupta 	if (rc)
11555f80f270SRuchika Gupta 		return rc;
11565f80f270SRuchika Gupta 
11575f80f270SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &wrapping_key_handle, sizeof(uint32_t));
11585f80f270SRuchika Gupta 	if (rc)
11595f80f270SRuchika Gupta 		return rc;
11605f80f270SRuchika Gupta 
11615f80f270SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
11625f80f270SRuchika Gupta 	if (rc)
11635f80f270SRuchika Gupta 		return rc;
11645f80f270SRuchika Gupta 
11655f80f270SRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
11665f80f270SRuchika Gupta 	if (rc)
11675f80f270SRuchika Gupta 		return rc;
11685f80f270SRuchika Gupta 
11695f80f270SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
11705f80f270SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
11715f80f270SRuchika Gupta 		goto out_free;
11725f80f270SRuchika Gupta 	}
11735f80f270SRuchika Gupta 
11745f80f270SRuchika Gupta 	rc = get_ready_session(session);
11755f80f270SRuchika Gupta 	if (rc)
11765f80f270SRuchika Gupta 		goto out_free;
11775f80f270SRuchika Gupta 
11785f80f270SRuchika Gupta 	wrapping_key = pkcs11_handle2object(wrapping_key_handle, session);
11795f80f270SRuchika Gupta 	if (!wrapping_key) {
11805f80f270SRuchika Gupta 		rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
11815f80f270SRuchika Gupta 		goto out_free;
11825f80f270SRuchika Gupta 	}
11835f80f270SRuchika Gupta 
11845f80f270SRuchika Gupta 	key = pkcs11_handle2object(key_handle, session);
11855f80f270SRuchika Gupta 	if (!key) {
11865f80f270SRuchika Gupta 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
11875f80f270SRuchika Gupta 		goto out_free;
11885f80f270SRuchika Gupta 	}
11895f80f270SRuchika Gupta 
11905f80f270SRuchika Gupta 	/*
11915f80f270SRuchika Gupta 	 * The wrapping key and key to be wrapped shouldn't be same.
11925f80f270SRuchika Gupta 	 * PKCS#11 spec doesn't explicitly state that but logically this isn't
11935f80f270SRuchika Gupta 	 * a use case and also acts as an attack vector, so explicitly
11945f80f270SRuchika Gupta 	 * disallow this.
11955f80f270SRuchika Gupta 	 */
11965f80f270SRuchika Gupta 	if (key == wrapping_key) {
11975f80f270SRuchika Gupta 		rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
11985f80f270SRuchika Gupta 		goto out_free;
11995f80f270SRuchika Gupta 	}
12005f80f270SRuchika Gupta 
12015f80f270SRuchika Gupta 	rc = set_processing_state(session, function, wrapping_key, NULL);
12025f80f270SRuchika Gupta 	if (rc)
12035f80f270SRuchika Gupta 		goto out_free;
12045f80f270SRuchika Gupta 
12055f80f270SRuchika Gupta 	/* Check if mechanism can be used for wrapping function */
12065f80f270SRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
12075f80f270SRuchika Gupta 						function,
12085f80f270SRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
12095f80f270SRuchika Gupta 	if (rc)
12105f80f270SRuchika Gupta 		goto out;
12115f80f270SRuchika Gupta 
12125f80f270SRuchika Gupta 	/*
12135f80f270SRuchika Gupta 	 * Check if wrapping key has CKA_WRAP set and its key type is
12145f80f270SRuchika Gupta 	 * compatible with the mechanism passed
12155f80f270SRuchika Gupta 	 */
12165f80f270SRuchika Gupta 	rc = check_parent_attrs_against_processing(proc_params->id, function,
12175f80f270SRuchika Gupta 						   wrapping_key->attributes);
12185f80f270SRuchika Gupta 	if (rc) {
12195f80f270SRuchika Gupta 		/*
12205f80f270SRuchika Gupta 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
12215f80f270SRuchika Gupta 		 * specified with C_Wrap() in the specification. So
12225f80f270SRuchika Gupta 		 * return the next most appropriate error.
12235f80f270SRuchika Gupta 		 */
12245f80f270SRuchika Gupta 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
12255f80f270SRuchika Gupta 			rc = PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
12265f80f270SRuchika Gupta 
12275f80f270SRuchika Gupta 		goto out;
12285f80f270SRuchika Gupta 	}
12295f80f270SRuchika Gupta 
12305f80f270SRuchika Gupta 	/* Check access of wrapping key */
12315f80f270SRuchika Gupta 	rc = check_access_attrs_against_token(session,
12325f80f270SRuchika Gupta 					      wrapping_key->attributes);
12335f80f270SRuchika Gupta 	if (rc)
12345f80f270SRuchika Gupta 		goto out;
12355f80f270SRuchika Gupta 
12365f80f270SRuchika Gupta 	switch (get_class(key->attributes)) {
12375f80f270SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
12385f80f270SRuchika Gupta 	case PKCS11_CKO_PRIVATE_KEY:
123945d40bdaSValerii Chubar 		break;
12405f80f270SRuchika Gupta 	default:
12415f80f270SRuchika Gupta 		rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
12425f80f270SRuchika Gupta 		goto out;
12435f80f270SRuchika Gupta 	}
12445f80f270SRuchika Gupta 
12455f80f270SRuchika Gupta 	/* Check if key to be wrapped is extractable */
12465f80f270SRuchika Gupta 	if (!get_bool(key->attributes, PKCS11_CKA_EXTRACTABLE)) {
12475f80f270SRuchika Gupta 		DMSG("Extractable property is false");
12485f80f270SRuchika Gupta 		rc = PKCS11_CKR_KEY_UNEXTRACTABLE;
12495f80f270SRuchika Gupta 		goto out;
12505f80f270SRuchika Gupta 	}
12515f80f270SRuchika Gupta 
12525f80f270SRuchika Gupta 	if (get_bool(key->attributes, PKCS11_CKA_WRAP_WITH_TRUSTED) &&
12535f80f270SRuchika Gupta 	    !get_bool(wrapping_key->attributes, PKCS11_CKA_TRUSTED)) {
12545f80f270SRuchika Gupta 		DMSG("Wrap with trusted not satisfied");
12555f80f270SRuchika Gupta 		rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
12565f80f270SRuchika Gupta 		goto out;
12575f80f270SRuchika Gupta 	}
12585f80f270SRuchika Gupta 
12595f80f270SRuchika Gupta 	rc = check_access_attrs_against_token(session, key->attributes);
12605f80f270SRuchika Gupta 	if (rc)
12615f80f270SRuchika Gupta 		goto out;
12625f80f270SRuchika Gupta 
12635f80f270SRuchika Gupta 	rc = get_attribute_ptr(wrapping_key->attributes,
12645f80f270SRuchika Gupta 			       PKCS11_CKA_WRAP_TEMPLATE, &req_attrs, &size);
12655f80f270SRuchika Gupta 	if (rc == PKCS11_CKR_OK && size != 0) {
12665f80f270SRuchika Gupta 		if (!attributes_match_reference(key->attributes, req_attrs)) {
12675f80f270SRuchika Gupta 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
12685f80f270SRuchika Gupta 			goto out;
12695f80f270SRuchika Gupta 		}
12705f80f270SRuchika Gupta 	}
12715f80f270SRuchika Gupta 
1272a9aa45d8SValerii Chubar 	rc = alloc_key_data_to_wrap(key->attributes, &key_data, &key_sz);
12735f80f270SRuchika Gupta 	if (rc)
12745f80f270SRuchika Gupta 		goto out;
12755f80f270SRuchika Gupta 
12765f80f270SRuchika Gupta 	if (processing_is_tee_symm(proc_params->id)) {
12775f80f270SRuchika Gupta 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
12785f80f270SRuchika Gupta 					 proc_params, wrapping_key);
12795f80f270SRuchika Gupta 		if (rc)
12805f80f270SRuchika Gupta 			goto out;
12815f80f270SRuchika Gupta 
12825f80f270SRuchika Gupta 		rc = wrap_data_by_symm_enc(session, key_data, key_sz, out_buf,
12835f80f270SRuchika Gupta 					   &out_size);
12845f80f270SRuchika Gupta 	} else {
128545d40bdaSValerii Chubar 		rc = init_asymm_operation(session, PKCS11_FUNCTION_ENCRYPT,
128645d40bdaSValerii Chubar 					  proc_params, wrapping_key);
128745d40bdaSValerii Chubar 		if (rc)
128845d40bdaSValerii Chubar 			goto out;
128945d40bdaSValerii Chubar 
129045d40bdaSValerii Chubar 		rc = wrap_data_by_asymm_enc(session, key_data, key_sz, out_buf,
129145d40bdaSValerii Chubar 					    &out_size);
12925f80f270SRuchika Gupta 	}
12935f80f270SRuchika Gupta 
12945f80f270SRuchika Gupta 	if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)
12955f80f270SRuchika Gupta 		params[2].memref.size = out_size;
12965f80f270SRuchika Gupta 
12975f80f270SRuchika Gupta out:
12985f80f270SRuchika Gupta 	release_active_processing(session);
12995f80f270SRuchika Gupta out_free:
1300a9aa45d8SValerii Chubar 	TEE_Free(key_data);
13015f80f270SRuchika Gupta 	TEE_Free(proc_params);
13025f80f270SRuchika Gupta 	return rc;
13035f80f270SRuchika Gupta }
1304