xref: /optee_os/ta/pkcs11/src/processing.c (revision 4cfce748748a47029b2c30f911b4b0232b23349f)
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 
30512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function,
31512cbf1dSJens Wiklander 			       enum pkcs11_proc_state state)
32512cbf1dSJens Wiklander {
33512cbf1dSJens Wiklander 	switch (function) {
34512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
35512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_ENCRYPTING ||
36512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
37512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
38512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
39512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DECRYPTING ||
40512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
41512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
42512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DIGEST:
43512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DIGESTING ||
44512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
45512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
46512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING ||
47512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
48512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
49512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_VERIFYING ||
50512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
51512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN_RECOVER:
52512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
53512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY_RECOVER:
54512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
55512cbf1dSJens Wiklander 	default:
56512cbf1dSJens Wiklander 		TEE_Panic(function);
57512cbf1dSJens Wiklander 		return false;
58512cbf1dSJens Wiklander 	}
59512cbf1dSJens Wiklander }
60512cbf1dSJens Wiklander 
61512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
62512cbf1dSJens Wiklander 					 enum processing_func function)
63512cbf1dSJens Wiklander {
64512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
65512cbf1dSJens Wiklander 
66512cbf1dSJens Wiklander 	if (session->processing &&
67512cbf1dSJens Wiklander 	    func_matches_state(function, session->processing->state))
68512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
69512cbf1dSJens Wiklander 
70512cbf1dSJens Wiklander 	return rc;
71512cbf1dSJens Wiklander }
72512cbf1dSJens Wiklander 
73512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session)
74512cbf1dSJens Wiklander {
75512cbf1dSJens Wiklander 	if (!session->processing)
76512cbf1dSJens Wiklander 		return;
77512cbf1dSJens Wiklander 
78512cbf1dSJens Wiklander 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
79512cbf1dSJens Wiklander 		TEE_FreeOperation(session->processing->tee_op_handle);
80512cbf1dSJens Wiklander 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
81512cbf1dSJens Wiklander 	}
82512cbf1dSJens Wiklander 
832158ea6cSRuchika Gupta 	TEE_Free(session->processing->extra_ctx);
842158ea6cSRuchika Gupta 
85512cbf1dSJens Wiklander 	TEE_Free(session->processing);
86512cbf1dSJens Wiklander 	session->processing = NULL;
87512cbf1dSJens Wiklander }
88512cbf1dSJens Wiklander 
89512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
90512cbf1dSJens Wiklander {
91512cbf1dSJens Wiklander 	uint32_t a_size = 0;
92512cbf1dSJens Wiklander 	struct obj_attrs *attrs = obj->attributes;
93512cbf1dSJens Wiklander 
94512cbf1dSJens Wiklander 	switch (get_key_type(attrs)) {
95512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
96689f4e5bSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
97689f4e5bSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
98689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
99689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
100689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
101689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
102689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
103512cbf1dSJens Wiklander 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
104512cbf1dSJens Wiklander 			return 0;
105512cbf1dSJens Wiklander 
106512cbf1dSJens Wiklander 		return a_size * 8;
107512cbf1dSJens Wiklander 	default:
108512cbf1dSJens Wiklander 		TEE_Panic(0);
109512cbf1dSJens Wiklander 		return 0;
110512cbf1dSJens Wiklander 	}
111512cbf1dSJens Wiklander }
112512cbf1dSJens Wiklander 
113fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
114fa247a2aSRuchika Gupta {
115fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
116fa247a2aSRuchika Gupta 	void *data = NULL;
117fa247a2aSRuchika Gupta 	uint32_t data_size = 0;
118fa247a2aSRuchika Gupta 	uint32_t value_len = 0;
119fa247a2aSRuchika Gupta 	void *value = NULL;
120fa247a2aSRuchika Gupta 
121fa247a2aSRuchika Gupta 	if (!*head)
122fa247a2aSRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
123fa247a2aSRuchika Gupta 
124fa247a2aSRuchika Gupta 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
125fa247a2aSRuchika Gupta 	if (rc || data_size != sizeof(uint32_t)) {
126fa247a2aSRuchika Gupta 		DMSG("%s", rc ? "No attribute value_len found" :
127fa247a2aSRuchika Gupta 		     "Invalid size for attribute VALUE_LEN");
128fa247a2aSRuchika Gupta 
129fa247a2aSRuchika Gupta 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
130fa247a2aSRuchika Gupta 	}
131fa247a2aSRuchika Gupta 	TEE_MemMove(&value_len, data, data_size);
132fa247a2aSRuchika Gupta 
133fa247a2aSRuchika Gupta 	if (get_key_type(*head) == PKCS11_CKK_GENERIC_SECRET)
134fa247a2aSRuchika Gupta 		value_len = (value_len + 7) / 8;
135fa247a2aSRuchika Gupta 
136fa247a2aSRuchika Gupta 	/* Remove the default empty value attribute if found */
137fa247a2aSRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
138fa247a2aSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
139fa247a2aSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
140fa247a2aSRuchika Gupta 
141fa247a2aSRuchika Gupta 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
142fa247a2aSRuchika Gupta 	if (!value)
143fa247a2aSRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
144fa247a2aSRuchika Gupta 
145fa247a2aSRuchika Gupta 	TEE_GenerateRandom(value, value_len);
146fa247a2aSRuchika Gupta 
147fa247a2aSRuchika Gupta 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
148fa247a2aSRuchika Gupta 
149fa247a2aSRuchika Gupta 	TEE_Free(value);
150fa247a2aSRuchika Gupta 
151fa247a2aSRuchika Gupta 	return rc;
152fa247a2aSRuchika Gupta }
153fa247a2aSRuchika Gupta 
154fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
155fa247a2aSRuchika Gupta 				     uint32_t ptypes, TEE_Param *params)
156fa247a2aSRuchika Gupta {
157fa247a2aSRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
158fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE,
159fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
160fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE);
161fa247a2aSRuchika Gupta 	TEE_Param *ctrl = params;
162fa247a2aSRuchika Gupta 	TEE_Param *out = params + 2;
163fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
164fa247a2aSRuchika Gupta 	struct serialargs ctrlargs = { };
165fa247a2aSRuchika Gupta 	struct pkcs11_session *session = NULL;
166fa247a2aSRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
167fa247a2aSRuchika Gupta 	struct obj_attrs *head = NULL;
168fa247a2aSRuchika Gupta 	struct pkcs11_object_head *template = NULL;
169fa247a2aSRuchika Gupta 	size_t template_size = 0;
170fa247a2aSRuchika Gupta 	uint32_t obj_handle = 0;
171fa247a2aSRuchika Gupta 
172fa247a2aSRuchika Gupta 	if (!client || ptypes != exp_pt ||
173fa247a2aSRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
174fa247a2aSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
175fa247a2aSRuchika Gupta 
176fa247a2aSRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
177fa247a2aSRuchika Gupta 
178fa247a2aSRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
179fa247a2aSRuchika Gupta 	if (rc)
180fa247a2aSRuchika Gupta 		return rc;
181fa247a2aSRuchika Gupta 
182fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
183fa247a2aSRuchika Gupta 	if (rc)
184fa247a2aSRuchika Gupta 		goto out;
185fa247a2aSRuchika Gupta 
186fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
187fa247a2aSRuchika Gupta 	if (rc)
188fa247a2aSRuchika Gupta 		goto out;
189fa247a2aSRuchika Gupta 
190fa247a2aSRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
191fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
192fa247a2aSRuchika Gupta 		goto out;
193fa247a2aSRuchika Gupta 	}
194fa247a2aSRuchika Gupta 
195fa247a2aSRuchika Gupta 	rc = get_ready_session(session);
196fa247a2aSRuchika Gupta 	if (rc)
197fa247a2aSRuchika Gupta 		goto out;
198fa247a2aSRuchika Gupta 
199fa247a2aSRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
200fa247a2aSRuchika Gupta 
201fa247a2aSRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
202fa247a2aSRuchika Gupta 						PKCS11_FUNCTION_GENERATE,
203fa247a2aSRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
204fa247a2aSRuchika Gupta 	if (rc) {
205fa247a2aSRuchika Gupta 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
206fa247a2aSRuchika Gupta 		goto out;
207fa247a2aSRuchika Gupta 	}
208fa247a2aSRuchika Gupta 
209fa247a2aSRuchika Gupta 	/*
210fa247a2aSRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes.
211fa247a2aSRuchika Gupta 	 * Free temporary template once done.
212fa247a2aSRuchika Gupta 	 */
213fa247a2aSRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
214fa247a2aSRuchika Gupta 					     NULL, PKCS11_FUNCTION_GENERATE,
215*4cfce748SRuchika Gupta 					     proc_params->id,
216*4cfce748SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
217fa247a2aSRuchika Gupta 	if (rc)
218fa247a2aSRuchika Gupta 		goto out;
219fa247a2aSRuchika Gupta 
220fa247a2aSRuchika Gupta 	TEE_Free(template);
221fa247a2aSRuchika Gupta 	template = NULL;
222fa247a2aSRuchika Gupta 
223fa247a2aSRuchika Gupta 	rc = check_created_attrs(head, NULL);
224fa247a2aSRuchika Gupta 	if (rc)
225fa247a2aSRuchika Gupta 		goto out;
226fa247a2aSRuchika Gupta 
227fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
228fa247a2aSRuchika Gupta 	if (rc)
229fa247a2aSRuchika Gupta 		goto out;
230fa247a2aSRuchika Gupta 
231fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
232fa247a2aSRuchika Gupta 	if (rc)
233fa247a2aSRuchika Gupta 		goto out;
234fa247a2aSRuchika Gupta 
235fa247a2aSRuchika Gupta 	/*
236fa247a2aSRuchika Gupta 	 * Execute target processing and add value as attribute
237fa247a2aSRuchika Gupta 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
238fa247a2aSRuchika Gupta 	 * processing to be used.
239fa247a2aSRuchika Gupta 	 */
240fa247a2aSRuchika Gupta 	switch (proc_params->id) {
241fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
242fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
243fa247a2aSRuchika Gupta 		/* Generate random of size specified by attribute VALUE_LEN */
244fa247a2aSRuchika Gupta 		rc = generate_random_key_value(&head);
245fa247a2aSRuchika Gupta 		if (rc)
246fa247a2aSRuchika Gupta 			goto out;
247fa247a2aSRuchika Gupta 		break;
248fa247a2aSRuchika Gupta 
249fa247a2aSRuchika Gupta 	default:
250fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
251fa247a2aSRuchika Gupta 		goto out;
252fa247a2aSRuchika Gupta 	}
253fa247a2aSRuchika Gupta 
254fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
255fa247a2aSRuchika Gupta 	proc_params = NULL;
256fa247a2aSRuchika Gupta 
257fa247a2aSRuchika Gupta 	/*
258fa247a2aSRuchika Gupta 	 * Object is ready, register it and return a handle.
259fa247a2aSRuchika Gupta 	 */
260fa247a2aSRuchika Gupta 	rc = create_object(session, head, &obj_handle);
261fa247a2aSRuchika Gupta 	if (rc)
262fa247a2aSRuchika Gupta 		goto out;
263fa247a2aSRuchika Gupta 
264fa247a2aSRuchika Gupta 	/*
265fa247a2aSRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
266fa247a2aSRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
267fa247a2aSRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
268fa247a2aSRuchika Gupta 	 * be freed at function out.
269fa247a2aSRuchika Gupta 	 */
270fa247a2aSRuchika Gupta 	head = NULL;
271fa247a2aSRuchika Gupta 
272fa247a2aSRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
273fa247a2aSRuchika Gupta 	out->memref.size = sizeof(obj_handle);
274fa247a2aSRuchika Gupta 
275fa247a2aSRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
276fa247a2aSRuchika Gupta 	     session->handle, obj_handle);
277fa247a2aSRuchika Gupta 
278fa247a2aSRuchika Gupta out:
279fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
280fa247a2aSRuchika Gupta 	TEE_Free(template);
281fa247a2aSRuchika Gupta 	TEE_Free(head);
282fa247a2aSRuchika Gupta 
283fa247a2aSRuchika Gupta 	return rc;
284fa247a2aSRuchika Gupta }
285fa247a2aSRuchika Gupta 
286512cbf1dSJens Wiklander /*
287512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
288512cbf1dSJens Wiklander  *
289512cbf1dSJens Wiklander  * @client = client reference
290512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
291512cbf1dSJens Wiklander  * @params = Invocation parameters reference
292512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
293512cbf1dSJens Wiklander  */
294512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
295512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
296512cbf1dSJens Wiklander 				     enum processing_func function)
297512cbf1dSJens Wiklander {
298512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
299512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
300512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
301512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
302512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
303512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
304512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
305512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
306512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
307512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
308512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
309512cbf1dSJens Wiklander 
310512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
311512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
312512cbf1dSJens Wiklander 
313512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
314512cbf1dSJens Wiklander 
315512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
316512cbf1dSJens Wiklander 	if (rc)
317512cbf1dSJens Wiklander 		return rc;
318512cbf1dSJens Wiklander 
319512cbf1dSJens Wiklander 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
320512cbf1dSJens Wiklander 	if (rc)
321512cbf1dSJens Wiklander 		return rc;
322512cbf1dSJens Wiklander 
323512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
324512cbf1dSJens Wiklander 	if (rc)
325512cbf1dSJens Wiklander 		return rc;
326512cbf1dSJens Wiklander 
327512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
328512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
329512cbf1dSJens Wiklander 		goto out;
330512cbf1dSJens Wiklander 	}
331512cbf1dSJens Wiklander 
332512cbf1dSJens Wiklander 	rc = get_ready_session(session);
333512cbf1dSJens Wiklander 	if (rc)
334512cbf1dSJens Wiklander 		goto out;
335512cbf1dSJens Wiklander 
336512cbf1dSJens Wiklander 	obj = pkcs11_handle2object(key_handle, session);
337512cbf1dSJens Wiklander 	if (!obj) {
338512cbf1dSJens Wiklander 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
339512cbf1dSJens Wiklander 		goto out;
340512cbf1dSJens Wiklander 	}
341512cbf1dSJens Wiklander 
342512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
343512cbf1dSJens Wiklander 	if (rc)
344512cbf1dSJens Wiklander 		goto out;
345512cbf1dSJens Wiklander 
346512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
347512cbf1dSJens Wiklander 						function,
348512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
349512cbf1dSJens Wiklander 	if (rc)
350512cbf1dSJens Wiklander 		goto out;
351512cbf1dSJens Wiklander 
352512cbf1dSJens Wiklander 	rc = check_parent_attrs_against_processing(proc_params->id, function,
353512cbf1dSJens Wiklander 						   obj->attributes);
354512cbf1dSJens Wiklander 	if (rc)
355512cbf1dSJens Wiklander 		goto out;
356512cbf1dSJens Wiklander 
357512cbf1dSJens Wiklander 	rc = check_access_attrs_against_token(session, obj->attributes);
358512cbf1dSJens Wiklander 	if (rc)
359512cbf1dSJens Wiklander 		goto out;
360512cbf1dSJens Wiklander 
361512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
362512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
363512cbf1dSJens Wiklander 	else
364512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
365512cbf1dSJens Wiklander 
366512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
367512cbf1dSJens Wiklander 		session->processing->mecha_type = proc_params->id;
368512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
369512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
370512cbf1dSJens Wiklander 		     id2str_function(function));
371512cbf1dSJens Wiklander 	}
372512cbf1dSJens Wiklander 
373512cbf1dSJens Wiklander out:
374512cbf1dSJens Wiklander 	if (rc && session)
375512cbf1dSJens Wiklander 		release_active_processing(session);
376512cbf1dSJens Wiklander 
377512cbf1dSJens Wiklander 	TEE_Free(proc_params);
378512cbf1dSJens Wiklander 
379512cbf1dSJens Wiklander 	return rc;
380512cbf1dSJens Wiklander }
381512cbf1dSJens Wiklander 
382512cbf1dSJens Wiklander /*
383512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
384512cbf1dSJens Wiklander  *
385512cbf1dSJens Wiklander  * @client = client reference
386512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
387512cbf1dSJens Wiklander  * @params = Invocation parameters reference
388512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
389512cbf1dSJens Wiklander  * @step - update, oneshot, final
390512cbf1dSJens Wiklander  */
391512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
392512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
393512cbf1dSJens Wiklander 				     enum processing_func function,
394512cbf1dSJens Wiklander 				     enum processing_step step)
395512cbf1dSJens Wiklander {
396512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
397512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
398512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
399512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
400512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
401512cbf1dSJens Wiklander 
402512cbf1dSJens Wiklander 	if (!client ||
403512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
404512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
405512cbf1dSJens Wiklander 
406512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
407512cbf1dSJens Wiklander 
408512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
409512cbf1dSJens Wiklander 	if (rc)
410512cbf1dSJens Wiklander 		return rc;
411512cbf1dSJens Wiklander 
412512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
413512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
414512cbf1dSJens Wiklander 
415512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
416512cbf1dSJens Wiklander 	if (rc)
417512cbf1dSJens Wiklander 		return rc;
418512cbf1dSJens Wiklander 
419512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
420512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
421512cbf1dSJens Wiklander 						function, step);
422512cbf1dSJens Wiklander 	if (rc)
423512cbf1dSJens Wiklander 		goto out;
424512cbf1dSJens Wiklander 
425512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
426512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
427512cbf1dSJens Wiklander 					 ptypes, params);
428512cbf1dSJens Wiklander 	else
429512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
430512cbf1dSJens Wiklander 
431689f4e5bSRuchika Gupta 	if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
432512cbf1dSJens Wiklander 		session->processing->updated = true;
433512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
434512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
435512cbf1dSJens Wiklander 		     id2str_function(function));
436512cbf1dSJens Wiklander 	}
437512cbf1dSJens Wiklander 
438512cbf1dSJens Wiklander out:
439512cbf1dSJens Wiklander 	switch (step) {
440512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
441512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
442512cbf1dSJens Wiklander 			release_active_processing(session);
443512cbf1dSJens Wiklander 		break;
444512cbf1dSJens Wiklander 	default:
445512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
446512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
447512cbf1dSJens Wiklander 			release_active_processing(session);
448512cbf1dSJens Wiklander 		break;
449512cbf1dSJens Wiklander 	}
450512cbf1dSJens Wiklander 
451512cbf1dSJens Wiklander 	return rc;
452512cbf1dSJens Wiklander }
453